简体   繁体   中英

Matplotlib figure is not updating with ipywidgets slider

I have the following code to generate a simple graph.

%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, np.sin(x))

def update(w = 1.0):
    line.set_ydata(np.sin(w * x))
    plt.show()

interact(update)

The code generates the plot just fine - output

But when I drag the slider, the figure will not update. Any ideas on why this is?

Note: Your code actually works for me out of the box, so it may be worth updating your dependencies and see if that fixes it.

However, the main thing you want to change is to call fig.canvas.draw() instead of plt.show()

%matplotlib notebook
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, np.sin(x))

def update(w = 1.0):
    line.set_ydata(np.sin(w * x))
    fig.canvas.draw()

interact(update)

Using Ipympl

There is also a widget based notebook backend (that will also work in jupyterlab): ipympl which you can install with pip install ipympl and use with %matplotlib ipympl

In general the ipympl backend will work better with other widgets than the notebook backend.

using interactive with matplotlib

One unfortunate consequence of interactive is that it assumes the output will be fully regenerated every time the slider value changes. This doesn't always play super nicely with the set_data methods you are using. So you are likely better off manually generating and connecting the sliders. I'll also note that I've written a package that automates using the set_data command to connect widgets to updating matplotlib plots: https://mpl-interactions.readthedocs.io/en/stable/ . With that package your code would be

%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as iplt

x = np.linspace(0, 2 * np.pi, 1000)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

def f(x, w):
    return np.sin(w * x)

controls = iplt.plot(x, f, w=(1, 10))

This would do a job.

# load the interactive tool
from ipywidgets import interact, interactive, widgets, fixed
try:
    from ipywidgets import Layout
except:
    pass 

import numpy as np
import matplotlib.pyplot as plt
%matplotlib notebook

def fta(freq = 50.0):
    "showing sine frequency"
    y = np.sin(freq*x)
    f, ax1 = plt.subplots(nrows=1,figsize=(8,6))
    ax1.plot(x[0:100], y[0:100],'b')
    ax1.set_ylim(ymin=-1.1, ymax=1.1)
    ax1.grid();
    # then use it interactively,
interactive( fta, freq=(0.0,100.0))

互动情节

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM