Looks like the FigureCanvasMac object for the macosx backend have a few missing functions that are critical for animations. First, it doesn't have copy_from_bbox(). Besides animations, this also impacts some widgets, particularly the lasso widget. The FigureCanvasMac object also doesn't have restore_region(), so any animations that have blit=True will fail.
Unfortunately it is not just an issue of adding the missing functions to the macosx backend. Currently the animations code in matplotlib sends drawing commands to the figures outside of the event loop. This will not work on Mac OS X because of how the operating system works. To fix this issue, the animations code in matplotlib will have to be redesigned.
Anything we can do to move this issue forward? I'd be happy to add the required blitting functionality to the MacOSX backend, but we'd still need to rethink the animations code.
Can you elaborate on what the barrier for the Mac OSX backend is? The animation code is not making drawing commands outside of the event loop -- it's generally in a callback from a timer event that is triggered by the event loop. Are you saying that we can't draw outside of the draw callback? Does the Mac API have a way to render to an off-screen buffer, perhaps, and then blit that to the window on the next refresh event? Is it fundamentally a problem with the Quartz API or the way the backend is structured? Other backends that are built on top of this are able to do this, so there must be a way with a little creativity.
@mdboom Sorry I wasn't being clear. I meant to say that we cannot draw outside of the draw callback.
This is a fundamental feature of the Quartz API.
If the timer were to just invalidate the canvas, while letting the actual drawing be done by the draw callback, we should be able to get blitting to work.
I see. It's not even possible to draw to an off-screen buffer outside of the draw callback? I'll look around and see what we might be able to refactor at our end, and also see what can be done with the various layered toolkits (Qt, Wx) as they might offer some clues for workarounds.
It may be possible to draw to an off-screen buffer outside of the draw callback, but it seems like a hack. Is it necessary for the Timer to issue the drawing commands, rather than relying on the draw callback?
It seems like the easiest thing might be to have the macosx backend timer callback set a flag and invalidate the window. That should trigger a draw callback "as soon as possible", and if the flag is set, it can call all of the timer callbacks from there, which may, of course, issue drawing commands.
That would work if there is only one window, but if there are more then the timer would have to know which windows to invalidate. But anyway I will give it a try to see how it works out.
matplotlib timer events are created through the canvas object (in new_timer) so the macosx implementation of new_timer can associate the canvas with the timer callback, and from there get back to the window.
There is a bit of a wrinkle... @dopplershift specifically designed the
animation class to allow for an animation to span multiple figures, I
believe. Plus, the timer is used for TimedAnimation. There are other
subclasses of animations that don't use a timer, IIRC.
I agree that an animation should be able to span multiple figures. But then it seems odd that new_timer is a method of the canvas object; I would expect new_timer to be a function by itself.
Looking at the different backends that implement new_timer, it turns out that the gtk, gtk3, macosx, and qt4 backends don't actually use the canvas (self) object passed in in the call to new_timer, but the tkagg and wx backends do. But even for tkagg and wx there seems to be a simple workaround to let the Timer be independent of a particular canvas. So I would suggest to change the definition of new_timer in matplotlib from a method associated with a canvas to a regular function.
Perhaps this is something for the mailing list?
There has been some progress, but nothing that is quite ready yet. This is a complicated issue that goes beyond the MacOSX backend and involves the design of the event loop in Python and the choice of the backend. So there is no simple bug fix involving the MacOSX backend only. This will take some time.
@mdehoon thanks for the update. I've worked around this by specifying the Qt bindings in my ipython_config.py and matplotlibrc files, and that seems to be working for now.
Best of luck on solving this issue! I'd love to volunteer, but I know next to nothing about graphics internals - I'm definitely a Python guy :)
@raw915 To solve this bug, the animations code will have to be redesigned. I did not write the animations code and I don't have time to fix it myself. If you can volunteer to work on this, or find somebody willing to take on this task, I'd be happy to explain what is wrong with the current code.
same issue +1
matplotlib 1.4.3
10.10.3 Yosemite
Darwin LQMacPro.local 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64
Just a fyi, I've refined my function definition a bit more:
export GLOBALPYTHON=$(which python)functionpython {
if [[ !-z"$VIRTUAL_ENV" ]];then#test if we are running python 2 or 3
pyversion=`command python -V 2>&1| cut -d '' -f2 | cut -d. -f1,2`
PYTHONHOME=$VIRTUAL_ENV$GLOBALPYTHON$pyversion"$@"else$GLOBALPYTHON"$@"fi
}
put that in your .bashrc and using matplotlib in virtualenvs should "just work". In case that function breaks anything you can always force execution of the "plain virtualenv interpreter" by using command python.
I changed this to "unassigned" because the solution to problems such as this will likely involve major changes such as an agg-based version of macosx. The immediate workaround is to use one of the existing backends other than macosx.
This has worked for me with Tkinter installed using the ActiveState Tkinter installation on OSX 10.11.6, Python 2.71
The basic animation example is still a little noisy until blt=False in the line_ani code here:
Activity
iveney commented on Nov 8, 2011
+1 for this issue. Happened to encounter this issue and cannot find any workaround.
mdehoon commented on Mar 4, 2012
Unfortunately it is not just an issue of adding the missing functions to the macosx backend. Currently the animations code in matplotlib sends drawing commands to the figures outside of the event loop. This will not work on Mac OS X because of how the operating system works. To fix this issue, the animations code in matplotlib will have to be redesigned.
mdehoon commented on Mar 26, 2013
Anything we can do to move this issue forward? I'd be happy to add the required blitting functionality to the MacOSX backend, but we'd still need to rethink the animations code.
mdboom commented on Mar 26, 2013
Can you elaborate on what the barrier for the Mac OSX backend is? The animation code is not making drawing commands outside of the event loop -- it's generally in a callback from a timer event that is triggered by the event loop. Are you saying that we can't draw outside of the draw callback? Does the Mac API have a way to render to an off-screen buffer, perhaps, and then blit that to the window on the next refresh event? Is it fundamentally a problem with the Quartz API or the way the backend is structured? Other backends that are built on top of this are able to do this, so there must be a way with a little creativity.
mdehoon commented on Mar 26, 2013
@mdboom Sorry I wasn't being clear. I meant to say that we cannot draw outside of the draw callback.
This is a fundamental feature of the Quartz API.
If the timer were to just invalidate the canvas, while letting the actual drawing be done by the draw callback, we should be able to get blitting to work.
mdboom commented on Mar 26, 2013
I see. It's not even possible to draw to an off-screen buffer outside of the draw callback? I'll look around and see what we might be able to refactor at our end, and also see what can be done with the various layered toolkits (Qt, Wx) as they might offer some clues for workarounds.
mdehoon commented on Mar 26, 2013
It may be possible to draw to an off-screen buffer outside of the draw callback, but it seems like a hack. Is it necessary for the Timer to issue the drawing commands, rather than relying on the draw callback?
mdboom commented on Mar 26, 2013
It seems like the easiest thing might be to have the macosx backend timer callback set a flag and invalidate the window. That should trigger a draw callback "as soon as possible", and if the flag is set, it can call all of the timer callbacks from there, which may, of course, issue drawing commands.
mdehoon commented on Mar 27, 2013
That would work if there is only one window, but if there are more then the timer would have to know which windows to invalidate. But anyway I will give it a try to see how it works out.
mdboom commented on Mar 27, 2013
matplotlib timer events are created through the canvas object (in new_timer) so the macosx implementation of new_timer can associate the canvas with the timer callback, and from there get back to the window.
WeatherGod commented on Mar 27, 2013
There is a bit of a wrinkle... @dopplershift specifically designed the
animation class to allow for an animation to span multiple figures, I
believe. Plus, the timer is used for TimedAnimation. There are other
subclasses of animations that don't use a timer, IIRC.
mdehoon commented on Mar 29, 2013
I agree that an animation should be able to span multiple figures. But then it seems odd that new_timer is a method of the canvas object; I would expect new_timer to be a function by itself.
Looking at the different backends that implement new_timer, it turns out that the gtk, gtk3, macosx, and qt4 backends don't actually use the canvas (self) object passed in in the call to new_timer, but the tkagg and wx backends do. But even for tkagg and wx there seems to be a simple workaround to let the Timer be independent of a particular canvas. So I would suggest to change the definition of new_timer in matplotlib from a method associated with a canvas to a regular function.
Perhaps this is something for the mailing list?
MattDMo commented on Dec 22, 2013
Has there been any progress on this issue?
mdehoon commented on Dec 25, 2013
There has been some progress, but nothing that is quite ready yet. This is a complicated issue that goes beyond the MacOSX backend and involves the design of the event loop in Python and the choice of the backend. So there is no simple bug fix involving the MacOSX backend only. This will take some time.
MattDMo commented on Dec 26, 2013
@mdehoon thanks for the update. I've worked around this by specifying the Qt bindings in my ipython_config.py and matplotlibrc files, and that seems to be working for now.
Best of luck on solving this issue! I'd love to volunteer, but I know next to nothing about graphics internals - I'm definitely a Python guy :)
2 remaining items
raw915 commented on Apr 3, 2015
Here it is April 2015 and animation capability on mac OSX 10.10.2 is still not working. Any hope? Will this be fixed in v1.5.x?
mdehoon commented on Apr 3, 2015
@raw915 To solve this bug, the animations code will have to be redesigned. I did not write the animations code and I don't have time to fix it myself. If you can volunteer to work on this, or find somebody willing to take on this task, I'd be happy to explain what is wrong with the current code.
raw915 commented on Apr 5, 2015
I used the suggestion from http://stackoverflow.com/users/2388218/matt at http://stackoverflow.com/questions/9401658/matplotlib-animating-a-scatter-plot to get the first example working on OSX 10.10.2. He inserted import matplotlib and matplotlib.use('TkAgg') at the top of the file. This may not work if Tk/Tcl is not installed. I have it through Anaconda https://store.continuum.io/cshop/anaconda/
zhanglongqi commented on Jun 1, 2015
same issue +1
matplotlib 1.4.3
10.10.3 Yosemite
Darwin LQMacPro.local 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64
mpacer commented on Oct 19, 2015
Just wanted to chime in that I ran into this as well. It's kinda intimidating that the default simple example (http://matplotlib.org/1.4.1/examples/animation/simple_anim.html) doesn't work out of the box.
If I have time I'll try to look at the underlying animations code, but I'm no expert so I don't know if I'll actually be able to help.
nils-werner commented on Feb 19, 2016
Just a fyi, I've refined my function definition a bit more:
put that in your .bashrc and using matplotlib in virtualenvs should "just work". In case that function breaks anything you can always force execution of the "plain virtualenv interpreter" by using command python.
efiring commented on Feb 19, 2016
I changed this to "unassigned" because the solution to problems such as this will likely involve major changes such as an agg-based version of macosx. The immediate workaround is to use one of the existing backends other than macosx.
mdboom commented on Mar 21, 2016
Fixed by #6178
ReaddyEddy commented on Oct 12, 2016
As noted at https://mail.python.org/pipermail/pythonmac-sig/2012-September/023664.html use:
just before
This has worked for me with Tkinter installed using the ActiveState Tkinter installation on OSX 10.11.6, Python 2.71
The basic animation example is still a little noisy until blt=False in the line_ani code here: