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

Skip to content

Mnt direct call draw idle [WIP] #4849

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

Conversation

tacaswell
Copy link
Member

Built on top of #4738

@mdehoon

When I went to implement this I grew confused as to where the canvas knowing it was stale would fit in. Isn't the call to draw_idle the message to the canvas that it is stale?

There were also some issues with the first draw_idle going out before all of the objects had finished building them selves adding stale to the canvas in the naive way because callbacks in python get executed synchronously.

I did re-work how the stale state gets propagated and (I think) greatly simplified it by adding a dedicated callback.

As-is this has an issue with __init__ order of operations with the nbagg backend which I don't have time to debug tonight.

I am worried about how this method will interact with nbagg which has a js side event loop running in the browser and then call backs listening to comms on the python side. By hooking into the IPython callbacks we get to leverage their understanding of how to manage things.

@mdboom
Copy link
Member

mdboom commented Aug 1, 2015

At first blush, this looks like a nice simplification. Ping me to come back and look again as it progresses.

One possible further simplification:

Maybe include a default stale_callback method that is a no-op, rather than requiring if self.stale_callback is not None everywhere it is called? That seems like the kind of thing that could be forgotten down the road.

@mdehoon
Copy link
Contributor

mdehoon commented Aug 2, 2015

@tacaswell

Isn't the call to draw_idle the message to the canvas that it is stale?

Yes it is. "draw_idle" is a bit of a misnomer; "invalidate" may be better. The purpose of draw_idle is to let the canvas know that it is stale. How the canvas responds to that is up to the backend. Typically, a GUI backend will indeed schedule a redraw when the event loop is idle, but I could imagine that in specific backends draw_idle does something else (e.g. set a flag or something). Not sure if this is what you were asking, but anyway I hope it helps.

@tacaswell
Copy link
Member Author

@mdehoon I disagree about the purpose of draw_idle, it is to instruct the canvas that it should redraw at the next opportunity (vs draw which is telling the canvas to re-render right now). The details of how this is implemented is up to the backends (and in the case of macosx you deal with this by having an 'invalid' flag which the draw loop knows to mean it should re-draw on this cycle through), but other wise the canvas objects are (publicly) stateless and the implementation in backend bases to pass draw_idle through to draw (which really only matters for agg in terms of the backends we ship) is perfectly correct.

Trying to implement this highlighted a design choice that did not get articulated in my conversation with @mdehoon is mpl's idea of where the stale/invalid state should live is in scene graph tree or in the canvas. As I have implemented it, it lives in the scene graph, as @mdehoon wants it (and as it is explicitly implemented in macosx, explicitly as part of draw_idle in some backends, and deep in the guts of Qt currently) the state lives on the canvas side.

I think the arguments for doing this on the scene graph side are:

  • will work with backends we do not ship (I know of at least 2 in the wild)
  • will work with use-cases where the scene graph does not have a canvas associated with it (not relevant now, but pure export based work flows are coming).
  • requires changing less code

Although I admittedly have trouble coming up with a good use case, but forcing users into our idea of what the draw cadence should be seems wrong (but on the other hand, just turning interactive mode off seems to be the cut-out).

@mdehoon
Copy link
Contributor

mdehoon commented Aug 3, 2015

@tacaswell Just for clarification,

in the case of macosx you deal with this by having an 'invalid' flag which the draw loop knows to mean it should re-draw on this cycle through

as it is explicitly implemented in macosx

There is no explicit 'invalid' flag in the macosx backend; currently draw_idle in the macosx backend simply calls canvas.invalidate(), which (in the C code) calls Apple's API function to schedule a redraw. There may be some 'invalid' flag hidden deep in Apple's libraries, but there is no explicit 'invalid' flag within matplotlib. In this sense it is similar to Qt.

Tkagg is different as it draws to _tkphoto, which then needs to be blitted explicitly.

This is the result of a phone discussion with @medhoon

The idea is to not rely on pyplot knowing to check if the figure
needs to be re-drawn, but just have the Figure object directly
kick the canvas to draw_idle.

This does not currently work with nbagg due to the first draw_idle
being fired before it is finished building it's self.  There maybe
similar race conditions in the other backends.
@tacaswell tacaswell force-pushed the mnt_direct_call_draw_idle branch from 2dcda03 to e048b12 Compare August 15, 2015 02:55
@tacaswell tacaswell added this to the unassigned milestone Aug 15, 2015
@tacaswell tacaswell closed this Aug 21, 2017
@tacaswell tacaswell deleted the mnt_direct_call_draw_idle branch August 21, 2017 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants