Skip to content
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

Quiver does not _init with animated=True and quiverkey attached #2616

Closed
OceanWolf opened this issue Nov 26, 2013 · 9 comments · Fixed by #2835
Closed

Quiver does not _init with animated=True and quiverkey attached #2616

OceanWolf opened this issue Nov 26, 2013 · 9 comments · Fixed by #2835

Comments

@OceanWolf
Copy link
Contributor

Creating a quiver object with animated=True and adding this to a quiver key, this fails

self.plot = self.ax.quiver(x, y, U, V, scale=10, animated=True)
self.ax.quiverkey(self.plot, 0.9, 0.95, 1, '1 m/s')

with

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 236, in resize
    self.show()
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 239, in draw
    FigureCanvasAgg.draw(self)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_agg.py", line 421, in draw
    self.figure.draw(self.renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/figure.py", line 898, in draw
    func(*args)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 1997, in draw
    a.draw(renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/quiver.py", line 304, in draw
    self._init()
  File "/usr/lib/pymodules/python2.7/matplotlib/quiver.py", line 272, in _init
    np.zeros((1,)))
  File "/usr/lib/pymodules/python2.7/matplotlib/quiver.py", line 571, in _make_verts
    length = a * (widthu_per_lenu / (self.scale * self.width))
TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'

Obviously adding the optional width attribute to the quiver call, works as a dodgy workaround, but not the best as it neglects other code in the _init method. Note, using matplotlib version 1.1.1rc2

As a side issue, why can one not call quiverkey from the figure object? One can add both a colorbar and a legend from the figure object, so quiverkey seems the odd one out.

@tacaswell
Copy link
Member

Thanks for the bug report. It is easier to deal with bug reports that include complete examples to generate the issue http://sscce.org/ .

from matplotlib.pylab import *
x,  y = np.meshgrid(range(17), range(17))
u, v = rand(17), rand(17)
res = plt.gca().quiver(x, y, U, V, scale=10, animated=True)
plt.gca().quiverkey(res, 0.9, 0.95, 1, '1 m/s')

Confirmed on current master.

@efiring
Copy link
Member

efiring commented Feb 3, 2014

Although it looks like there should be a very simple fix for this, I don't have it working yet. There is something going on with the transforms that I haven't figured out.

@OceanWolf, regarding your question: the reason quiverkey is only an Axes method and pyplot function is that its functionality is inherently tied to a Quiver instance, which in turn is inherently tied to an Axes instance.

@ghost
Copy link

ghost commented Feb 21, 2014

Beside the code given above, when executing the following code:

import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.ylabel('some numbers')
plt.show()

But with the second line changed to:

plt.plot([1,2,3,4], animated = True)

Will cause the line to disappear, as shown below.
out1

In matplotlib / lib / matplotlib / axes / _base.py, line 2005 - 2009 looks suspicious:

    if self.figure.canvas.is_saving():
        dsu = [(a.zorder, a) for a in artists]
    else:
        dsu = [(a.zorder, a) for a in artists
               if not a.get_animated()]

By changing the else clause to:

        dsu = [(a.zorder, a) for a in artists ]

will fix the bug.

But I'm not familiar with matplotlib, so can somebody confirm this? And why is dsu defined to be that in the first place?

@tacaswell
Copy link
Member

@zhenghu2 Did you mean to post this to a different thread? I do not immediately see the relation to quiverkey.

@efiring
Copy link
Member

efiring commented Feb 21, 2014

@tacaswell, it is related, but the @zhenghu2 fix simply defeats the purpose of the get_animated() method for everything. I think that purpose is to make it possible to draw everything but the animated artists, take a snapshot of it, and then animate by repeatedly drawing the artists on that snapshot. The problem is that part of the quiver initialization doesn't occur until drawing time (for good reason) but quiverkey needs the result of that initialization. I tried a simple fix but ran into a problem, and haven't been able to get back to it.

@ghost
Copy link

ghost commented Feb 21, 2014

Is it possible to give a more detailed description on what animated keyword is about? The example I posted is taken from here:

http://matplotlib.org/users/pyplot_tutorial.html

With animated set to True, the blue line did not show, which makes me think that its draw method is not called. Also in Quiver, _init is only called if the draw method is called. That's why I proposed that change.

Or is animated keyword not intended to be used this way?

@ghost
Copy link

ghost commented Feb 21, 2014

@efiring Since there is a boolean variable Quiver._initialized(https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/quiver.py#L441) . Could it be used in QuiverKey._init to check if Quiver is been initialized? So QuiverKey._init will be changed to:

    def _init(self):
        if True: # not self._initialized:
            self._set_transform()
            _pivot = self.Q.pivot
            self.Q.pivot = self.pivot[self.labelpos]
            # Hack: save and restore the Umask
            _mask = self.Q.Umask
            self.Q.Umask = ma.nomask
#changes----------------------------------------------
            if not self.Q._initialized:
                self.Q._init()
                self.Q._initialized = True
#---------------------------------------------------------------------------
            self.verts = self.Q._make_verts(np.array([self.U]),
                                            np.zeros((1,)))
            self.Q.Umask = _mask
            self.Q.pivot = _pivot
            kw = self.Q.polykw
            kw.update(self.kw)
            self.vector = mcollections.PolyCollection(
                                        self.verts,
                                        offsets=[(self.X, self.Y)],
                                        transOffset=self.get_transform(),
                                        **kw)
            if self.color is not None:
                self.vector.set_color(self.color)
            self.vector.set_transform(self.Q.get_transform())
            self.vector.set_figure(self.get_figure())
            self._initialized = True

@efiring
Copy link
Member

efiring commented Feb 22, 2014

@zhenghu2 I think that is what I tried, and as I said, there was a problem. If I remember correctly, it messed up either the vector scaling, or the quiverkey scaling.

@efiring
Copy link
Member

efiring commented Feb 22, 2014

I have the solution and will provide a PR, but not right this minute.

efiring added a commit to efiring/matplotlib that referenced this issue Feb 24, 2014
efiring added a commit to efiring/matplotlib that referenced this issue Feb 24, 2014
efiring added a commit to efiring/matplotlib that referenced this issue Feb 25, 2014
efiring added a commit to efiring/matplotlib that referenced this issue Feb 25, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants