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

macosx backend does not work with blitting #531

Closed
WeatherGod opened this issue Oct 16, 2011 · 25 comments
Closed

macosx backend does not work with blitting #531

WeatherGod opened this issue Oct 16, 2011 · 25 comments

Comments

@WeatherGod
Copy link
Member

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.

@iveney
Copy link

iveney commented Nov 8, 2011

+1 for this issue. Happened to encounter this issue and cannot find any workaround.

@mdehoon
Copy link
Contributor

mdehoon commented 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
Copy link
Contributor

mdehoon commented 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
Copy link
Member

mdboom commented 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
Copy link
Contributor

mdehoon commented 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
Copy link
Member

mdboom commented 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
Copy link
Contributor

mdehoon commented 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
Copy link
Member

mdboom commented 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
Copy link
Contributor

mdehoon commented 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
Copy link
Member

mdboom commented 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
Copy link
Member Author

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
Copy link
Contributor

mdehoon commented 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
Copy link

MattDMo commented Dec 22, 2013

Has there been any progress on this issue?

@mdehoon
Copy link
Contributor

mdehoon commented 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
Copy link

MattDMo commented 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 :)

@asselinpaul
Copy link

@MattDMo Did you get it to work in the end?

@raw915
Copy link

raw915 commented 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
Copy link
Contributor

mdehoon commented 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
Copy link

raw915 commented 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
Copy link

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
Copy link

mpacer commented 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
Copy link
Contributor

Just a fyi, I've refined my function definition a bit more:

export GLOBALPYTHON=$(which python)

function python {
    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.

@efiring efiring modified the milestones: unassigned, 2.1 (next point release) Feb 19, 2016
@efiring
Copy link
Member

efiring commented 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
Copy link
Member

mdboom commented Mar 21, 2016

Fixed by #6178

@QuLogic QuLogic modified the milestones: 2.0 (style change major release), unassigned Mar 28, 2016
@ReaddyEddy
Copy link

ReaddyEddy commented Oct 12, 2016

As noted at https://mail.python.org/pipermail/pythonmac-sig/2012-September/023664.html use:

import matplotlib
matplotlib.use('TkAgg')

just before

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

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:

line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l),
    interval=50, blit=False)

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