Open henrypinkard opened 2 years ago
Hi @henrypinkard this is unfortunately a known issue. There is some discussion of it and potential solutions here https://github.com/matplotlib/ipympl/issues/290
ahh and it turns out that there is a pretty simple workaround for the meantime
%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)
Got it, thanks. I'll give that a shot.
Awesome library overall!!
as an aside I would recommend instead of clearing and redrawing every time you should use the set_data methods. e.g
line = ax.plot(some_data)[0]
# for updating
line.set_data(new_data)
fig.canvas.draw()
Yeah I think I saw that way in the example, but I opted for clear()
because I'm not always calling plot
. Sometimes imshow
, scatter
, bar
, etc. As far as I can tell, the objects returned don't always have a set_data
method. Thoughts?
Yeah I think I saw that way in the example, but I opted for clear() because I'm not always calling plot. Sometimes imshow, scatter, bar, etc. As far as I can tell, the objects returned don't always have a set_data method. Thoughts?
Many (but not all artists) do have set_data
or equivalent, though they are not always documented and there is no central example (https://github.com/matplotlib/matplotlib/issues/19520).
In my mpl-interactions pcakage I've done a lot of the work of figuring that out and if you look through this file https://github.com/ianhi/mpl-interactions/blob/master/mpl_interactions/pyplot.py then you can find the techniques for updating various functions. There's a bit of extra stuff around the framework for buliding sliders (and also because I make every argument adjustable) but for scatter for example looking at https://github.com/ianhi/mpl-interactions/blob/0517177b687722f8d4ecf9fd89910986be3377b3/mpl_interactions/pyplot.py#L530 you can see that the steps are:
scatter = ax.scatter(x, y)
scatter.set_offsets(np.column_stack([new_x, new_y]))
and then some trickiness with a helper function for updating the axis limits automatically (though there are simpler ways)
Actually I'll bet that it wouldn't be too difficult to use mpl-interactions as an engine for updating plots in cases like this. Just would need to make a widget that doesn't get rendered anywhere and update it's value. But that's probably best discussed not on this issue
Complete example of using mpl-interactions to auto update plots in a loop all in one cell can be found here: https://github.com/ianhi/mpl-interactions/issues/234
Something I've seen in previous versions as well as the current version: In order to have a figure that dynamically updates while some code is executing (e.g. tracking the loss function of an optimization), I have to create the figure in a separate jupyter notebook cell and run it before a I run the code that updates. If I don't do this, then a blank figure shows and never updates. I'm using Jupyter lab. Wondering if I'm doing something wrong here? It would make the code cleaner and easier to run if it could all be put in a single cell.
Example:
Using the following function:
This works:
But this does not: