-
Notifications
You must be signed in to change notification settings - Fork 226
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
What prevents a figure showing before notebook cell completion? #290
Comments
For anyone who is looking for a temporary solution, I'll add that for my project, where I am generating figures to be able to keep track of whether an image correction algorithm is proceeding in the right direction, I'm currently creating a figure in the notebook, and then getting hold of that in my code library with # Cell 1
plt.figure(figsize=some_size_for_a_nice_aspect_ratio)
# Cell 2
while not_converged:
# (...)
fig = plt.gcf()
fig.clear()
ax = fig.add_subplot()
ax.plot(...) |
My understanding of this is that:
In particular the issue is due to the dpi handling that's done in the initialization method on js side: Lines 72 to 81 in ac0a7c3
A "fix" for this is to just pretend that the frontend sent the messages early by adding these lines
to ipympl/ipympl/backend_nbagg.py Lines 281 to 288 in ac0a7c3
just after the That set that set of handle_message that I force is pretty much when the frontend asks for at the beginning of it's init. So the thought is that even though the figure isn't ready to be initialized yet you can just plop the messages on to the queue of outgoing comms bc they're garunteed (i think) to arrive after the messages that create the frontend object. (serious tbd on this, would need to ask someone more knowledgeable about the jupyter comms). |
More information on the order of comms processing on gitter here: |
I wonder if we could us https://github.com/Kirill888/jupyter-ui-poll#jupyter-ui-poll and maybe eventually use https://github.com/davidbrochart/akernel Also this is the same as matplotlib/matplotlib#18596 and #258 |
I tried the approach you suggested with canvas._handle_message(canvas, {'type': 'send_image_mode'}, [])
canvas._handle_message(canvas, {'type':'refresh'}, [])
canvas._handle_message(canvas,{'type': 'initialized'},[])
canvas._handle_message(canvas,{'type': 'draw'},[]) And it seems to work fine. The first animation won't have the correct DPI, but the next ones will have the right one (because we now save the DPI as a static Canvas property) |
I think guessing a DPI of 1 is a reasonable strategy? and then once the communication of the true DPI happens we can immediately redraw in the case that the DPI is different. Although faking the messages like this may not be strictly optimal instead of just calling the underlying methods. |
A workaround that works with the current version is: %matplotlib widget
from matplotlib import pyplot as plt
from time import sleep
import numpy as np
def display_immediately(fig):
canvas = fig.canvas
display(canvas)
canvas._handle_message(canvas, {'type': 'send_image_mode'}, [])
canvas._handle_message(canvas, {'type':'refresh'}, [])
canvas._handle_message(canvas,{'type': 'initialized'},[])
canvas._handle_message(canvas,{'type': 'draw'},[])
with plt.ioff():
fig = plt.figure()
display_immediately(fig)
for i in range(10):
x, y = np.random.random(2)
plt.scatter(x, y)
fig.canvas.draw()
sleep(0.1) |
Is there a possibility to make that the default behavior? and is there a reason not to? |
@shaielc I think the plan is to make it the default. The reason it hasn't been done yet is that no one has had the time to implement. Though I'd happily review a PR implementing it. |
First, thx for this thread, solved a longstanding problem of mine! One thing I noticed: in VSCode jupyter, the size of the plot inside the figure seems to be by a factor of 0.85 wrong, until the cell execution completes. This is insfofar annoying, as the axes are larger than the displayed figure window. This seems not to be the case in the browser. Has this something to do with the wrong dpi setting? Workaround is to scale the axis a bit smaller before the first display, and only do so if the environment is VSCode. |
My issue boils down to:
"Why does the figure not show immediately, but instead waits until the cell has completed running?"
This behaviour is preventing fun uses, like dynamic plotting in a single cell:
The previous code works if one splits it into two cells, placing the
figure()
call in the first one:Edit: I also note that in the qt backend, there figure and plot are shown immediately, in contrast to the ipympl behaviour.
The text was updated successfully, but these errors were encountered: