Thanks to visit codestin.com
Credit goes to github.com

Skip to content

'Figure' object has no attribute '_original_dpi' #9040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fariza opened this issue Aug 15, 2017 · 23 comments
Closed

'Figure' object has no attribute '_original_dpi' #9040

fariza opened this issue Aug 15, 2017 · 23 comments

Comments

@fariza
Copy link
Member

fariza commented Aug 15, 2017

With current master, running any example

python3 histogram_cumulative.py

I get

Traceback (most recent call last):
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 80, in paintEvent
    self._update_figure_dpi()
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5.py", line 186, in _update_figure_dpi
    dpi = self._dpi_ratio * self.figure._original_dpi
AttributeError: 'Figure' object has no attribute '_original_dpi'
Traceback (most recent call last):
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 80, in paintEvent
    self._update_figure_dpi()
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5.py", line 186, in _update_figure_dpi
    dpi = self._dpi_ratio * self.figure._original_dpi
AttributeError: 'Figure' object has no attribute '_original_dpi'

It opens the window but the image is black

If I force to use a GTK3 backend I dont get the error and the figure is fine

@fariza fariza added the GUI: Qt label Aug 15, 2017
@fariza
Copy link
Member Author

fariza commented Aug 15, 2017

maybe related to #8052

@tacaswell
Copy link
Member

What sha are you at?

#9002 went in yesterday and may have fixed this.

@fariza
Copy link
Member Author

fariza commented Aug 15, 2017

I just pulled from master (20 min ago)

@fariza
Copy link
Member Author

fariza commented Aug 15, 2017

From git rev-parse HEAD
3769792

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Aug 15, 2017
@tacaswell
Copy link
Member

I can not reproduce this, I assume it has something to do some subtle ordering in when things are created and when things are attempted to be drawn.

Does applying

20:00 $ git diff
diff --git a/lib/matplotlib/backends/backend_qt5agg.py b/lib/matplotlib/backends/backend_qt5agg.py
index 78d9fdada..85954c003 100644
--- a/lib/matplotlib/backends/backend_qt5agg.py
+++ b/lib/matplotlib/backends/backend_qt5agg.py
@@ -176,7 +176,7 @@ class FigureCanvasQTAggBase(FigureCanvasAgg):
         self.draw()
 
 
-class FigureCanvasQTAgg(FigureCanvasQTAggBase, FigureCanvasQT):
+class FigureCanvasQTAgg(FigureCanvasQT, FigureCanvasQTAggBase):
     """
     The canvas the figure renders into.  Calls the draw and print fig
     methods, creates the renderers, etc.

help?

@fariza
Copy link
Member Author

fariza commented Aug 16, 2017

@tacaswell no, I change the order and it doesn't help.

The FigureCanvasQT.__init__ its not being called.

I think FigureCanvasQTAggBase it's being called directly

@fariza
Copy link
Member Author

fariza commented Aug 16, 2017

@tacaswell if I make the change in backend_qt4agg.py.FigureCanvasQTAgg the error changes to

Traceback (most recent call last):
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5.py", line 309, in resizeEvent
    self.draw_idle()
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 143, in draw_idle
    if not self._agg_draw_pending:
AttributeError: 'FigureCanvasQTAgg' object has no attribute '_agg_draw_pending'

Why it shows me the error in qt5? if it is qt4 in reality?

@tacaswell
Copy link
Member

Ah! Because the qt4 backend is a sub-class of the qt5 backend. The main differences between them are that qt5 is co-opperative and qt4 is not which mostly shows up in the __init__ method.

@tacaswell tacaswell added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Aug 17, 2017
@tacaswell
Copy link
Member

import networkx
import matplotlib.backends.backend_qt4agg

def build_inheritance_graph(cls):
    g = networkx.DiGraph()
    todo = set([cls])
    done = set()

    while todo:
        cls = todo.pop()
        for b in cls.__bases__:
            if b not in done:
                todo.add(b)
            g.add_edge(cls.__name__, b.__name__)
    return g

g = build_inheritance_graph(matplotlib.backends.backend_qt5agg.FigureCanvas)
networkx.draw_networkx(g)

will give you a visualization of the MI diagram from these classes (there are 3 diamonds, 1 from us, 1 from Qt and 1 from us + Qt back to object). At least on __init__ is not being properly called on the Qt4 side.

@tacaswell
Copy link
Member

def decorate_init(cls):

    for b in cls.mro():
        decorate(b)

            
def decorate(cls):
    print(cls.__name__)
    if cls is object:
        return

    if 'matplotlib' not in cls.__module__:
        return
    if '__init__' not in cls.__dict__:
        return
    
    orig_init = cls.__dict__['__init__']
    
    def new_init(self, *args, **kwargs):
        print(cls.__module__, cls.__name__)
        return orig_init(self, *args, **kwargs)
    
    cls.__init__ = new_init
 


decorate_init(matplotlib.backends.backend_qt4agg.FigureCanvas)

Will trace through what get called.

@tacaswell
Copy link
Member

I have a patch that works but calls base class inits too many times....

tacaswell added a commit to tacaswell/matplotlib that referenced this issue Aug 17, 2017
in two places `super` needs to be used in the Qt5 case and
frustrated in the Qt4 case.  These are handled by the two
`_fake_super_*` methods.  The must be just private as we need to
override in sub-classes.

Closes matplotlib#9040
@fariza
Copy link
Member Author

fariza commented Aug 17, 2017

@tacaswell with the decorator

FigureCanvasQTAgg
FigureCanvasQTAggBase
FigureCanvasAgg
FigureCanvasQT
FigureCanvasQT
QWidget
QObject
QPaintDevice
Object
FigureCanvasBase
object
matplotlib.backends.backend_qt5agg FigureCanvasQTAggBase
matplotlib.backends.backend_qt4 FigureCanvasQT
matplotlib.backend_bases FigureCanvasBase
Traceback (most recent call last):
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 80, in paintEvent
    self._update_figure_dpi()
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5.py", line 186, in _update_figure_dpi
    dpi = self._dpi_ratio * self.figure._original_dpi
AttributeError: 'Figure' object has no attribute '_original_dpi'
Traceback (most recent call last):
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 80, in paintEvent
    self._update_figure_dpi()
  File "/home/fariza/workspace/matplotlib/lib/matplotlib/backends/backend_qt5.py", line 186, in _update_figure_dpi
    dpi = self._dpi_ratio * self.figure._original_dpi
AttributeError: 'Figure' object has no attribute '_original_dpi'

@fariza
Copy link
Member Author

fariza commented Aug 22, 2017

#9052 solves this problem

@fariza
Copy link
Member Author

fariza commented Aug 22, 2017

closed by #9052

@zerothi
Copy link
Contributor

zerothi commented Oct 11, 2017

In 2.1.0 I still see this problem,

python3 ...

and with the decorator shown above I get

FigureCanvasQTAgg
FigureCanvasQTAggBase
FigureCanvasAgg
FigureCanvasQT
FigureCanvasQT
QWidget
QObject
wrapper
QPaintDevice
simplewrapper
FigureCanvasBase
object
matplotlib.backends.backend_qt5agg FigureCanvasQTAggBase
matplotlib.backends.backend_qt5 FigureCanvasQT
matplotlib.backend_bases FigureCanvasBase
Traceback (most recent call last):
  File "/opt/python/3.6.3/packages/matplotlib/2.1.0/gnu-7.2.0/lib/python3.6/site-packages/matplotlib-2.1.0-py3.6-linux-x86_64.egg/matplotlib/backends/backend_qt5agg.py", line 68, in paintEvent
    self._update_figure_dpi()
  File "/opt/python/3.6.3/packages/matplotlib/2.1.0/gnu-7.2.0/lib/python3.6/site-packages/matplotlib-2.1.0-py3.6-linux-x86_64.egg/matplotlib/backends/backend_qt5.py", line 230, in _update_figure_dpi
    dpi = self._dpi_ratio * self.figure._original_dpi
AttributeError: 'Figure' object has no attribute '_original_dpi'

From the path above, you may also see versions used, pyqt is 5.9 (the latest).

@tacaswell tacaswell reopened this Oct 12, 2017
@tacaswell
Copy link
Member

How did you install matplotlib? Are you using pyqt4 or pyqt5?

@zerothi
Copy link
Contributor

zerothi commented Oct 12, 2017

Sorry about the 5.9, specification.

This is the print-out at installation:

 $> python3 setup.py build
Edit setup.cfg to change the build options

BUILDING MATPLOTLIB
            matplotlib: yes [2.1.0]
                python: yes [3.6.3 (default, Oct  9 2017, 08:51:47)  [GCC
                        7.2.0]]
              platform: yes [linux]

REQUIRED DEPENDENCIES AND EXTENSIONS
                 numpy: yes [version 1.13.3]
                   six: yes [using six version 1.11.0]
              dateutil: yes [using dateutil version 2.6.1]
backports.functools_lru_cache: yes [Not required]
          subprocess32: yes [Not required]
                  pytz: yes [using pytz version 2017.2]
                cycler: yes [using cycler version 0.10.0]
               tornado: yes [using tornado version 4.5.2]
             pyparsing: yes [using pyparsing version 2.2.0]
                libagg: yes [pkg-config information for 'libagg' could not
                        be found. Using local copy.]
              freetype: yes [version 2.8.1]
                   png: yes [version 1.6.32]
                 qhull: yes [pkg-config information for 'libqhull' could not
                        be found. Using local copy.]

OPTIONAL SUBPACKAGES
           sample_data: yes [installing]
              toolkits: yes [installing]
                 tests: no  [skipping due to configuration]
        toolkits_tests: no  [skipping due to configuration]

OPTIONAL BACKEND EXTENSIONS
                macosx: no  [Mac OS-X only]
                qt5agg: yes [installing, Qt: 5.7.1, PyQt: 5.7.1; PySide2 not
                        found]
                qt4agg: no  [PySide not found; PyQt4 not found]
               gtk3agg: no  [Requires pygobject to be installed.]
             gtk3cairo: no  [Requires cairocffi or pycairo to be installed.]
                gtkagg: no  [Requires pygtk]
                 tkagg: yes [installing; run-time loading from Python Tcl /
                        Tk]
                 wxagg: no  [requires wxPython]
                   gtk: no  [Requires pygtk]
                   agg: yes [installing]
                 cairo: no  [cairocffi or pycairo not found]
             windowing: no  [Microsoft Windows only]

OPTIONAL LATEX DEPENDENCIES
                dvipng: no
           ghostscript: yes [version 9.20]
                 latex: yes [version 3.14159265]
               pdftops: yes [version 0.48.0]

OPTIONAL PACKAGE DATA
                  dlls: no  [skipping due to configuration]

@zerothi
Copy link
Contributor

zerothi commented Oct 12, 2017

I just noticed that in fact it is using PyQt 5.9, as I initially wrote. If I do:

>>> import PyQt5.QtCore as q
>>> print(q.PYQT_VERSION_STR)
5.9
>>> print(q.QT_VERSION_STR)
5.7.1

So I guess there is a bug in the QT_VERSION_STR, I will try and report this to their mailing list.

@zerothi
Copy link
Contributor

zerothi commented Oct 12, 2017

Ahh, no, of course. QT is the parent library, while PYQT is the python wrapper qt.

@zerothi
Copy link
Contributor

zerothi commented Oct 12, 2017

In fact, I believe this to be a bug in setupext.py, it reads (@line 2077 and 2127)

qt_version = QtCore.QT_VERSION
pyqt_version_str = QtCore.QT_VERSION_STR

while I guess it should read:

qt_version = QtCore.QT_VERSION
pyqt_version_str = QtCore.PYQT_VERSION_STR

What do you think?

@dopplershift
Copy link
Contributor

I think you're right, would you submit a PR for that fix? Not sure what's going wrong with your original problem, unfortunately.

@QuLogic QuLogic modified the milestones: v2.1, v2.1.2 Dec 15, 2017
@tacaswell
Copy link
Member

@zerothi Do you still have this problem with 2.1.1?

@tacaswell
Copy link
Member

Closing as we can not reproduce this with 2.1.1. Please ping to be re-opened if you can still reproduce this issue with the current stable release.

@tacaswell tacaswell removed this from the v2.1.2 milestone Jan 8, 2018
@tacaswell tacaswell removed the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Jan 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants