问题
I'm trying to scroll through some magnetic resonance slices using plt.show()
and ipywidgets interact()
function. I've found no problem by slowly moving the slider, but an important delay is found when sliding through the slices a little bit faster.
Here below is the code I'm using.
def dicom_animation(x, volume):
fig = plt.figure(figsize=(8,8))
plt.imshow(volume['slices'][x]['pixel_array'], cmap=plt.cm.gray)
interact(dicom_animation, volume = fixed(a), x=IntSlider(round(len(a['slices'])/2,0), 0, (len(a['slices'])-1), layout=Layout(width='500px')))
And this is the result.
Is there anything I can do to make the sliding a little bit faster without this important delay?
回答1:
Remaking the figure and calling plt.imshow
are both pretty expensive operations which is what is slowing this down. Instead you need to use an interactive matplotlib backend and then use methods like set_data
.
Install ipympl
ipympl is an interactive backend for matplotlbi that works in both jupyter nobteook and jupyterlab. It has a nice example notebook that explains things like how to interact with other widgets here: https://github.com/matplotlib/ipympl/blob/0.6.1/examples/ipympl.ipynb
Installing this is significantly easier for JupyterLab 3+ So:
pip install --upgrade jupyterlab ipympl
manually create a slider
While interact
is convenient it doesn't tend to play well with ipympl as it expects to completely regenerate the output everytime the slider changes.
%matplotlib ipympl
# the rest of your setup code
fig, ax = plt.figure()
img = ax.imshow(volume['slices'][x]['pixel_array'], cmap=plt.cm.gray)
def update_plot(change):
img.set_data(volume['slices'][change['new']['pixel_array']
fig.canvas.draw_idle()
x_slider = IntSlider(round(len(a['slices'])/2,0), 0, (len(a['slices'])-1)
x_slider.observe(update_plot, names='value')
Use mpl-interactions
Manually setting up the slider can be a real hassle. So I wrote a library that to make it easy to control interactive plots using widgets. It handles creating the sliders and does all the correct things such as using set_data
for you. It also will use matplotlib sliders if you aren't in a jupyter notebook so it is more portable.
In your case you would be interested in the imshow example or depending on how your data is structured you may also be able to use the hyperslicer.
Your example would then be:
%matplotlib ipympl
import mpl_interactions.ipyplot as iplt
# other setup stuff
volume = a
def f(x):
return volume['slices'][x]['pixel_array']
fig, ax = plt.subplots()
controls = iplt.imshow(f, cmap=plt.cm.gray, x = np.arange(0, len(a)-1))
来源:https://stackoverflow.com/questions/65264185/slow-matplotlib-and-ipywidgets-image-refresh