60

I am trying to generate an interactive plot that depends on widgets. The problem I have is that when I change parameters using the slider, a new plot is done after the previous one, instead I would expect only one plot changing according to the parameters.

Example:

from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets

import matplotlib.pyplot as plt
%matplotlib inline

import numpy as np

def plot_func(freq):
    x = np.linspace(0, 2*np.pi)
    y = np.sin(x * freq)
    plt.plot(x, y)

interact(plot_func, freq = widgets.FloatSlider(value=7.5,
                                               min=1,
                                               max=5.0,
                                               step=0.5))

After moving the slider to 4.0, I have:

enter image description here

while I just want one figure to change as I move the slider. How can I achieve this?

(I am using Python 2.7, matplotlib 2.0 and I have just updated notebook and jupyter to the latest version. let me know if further info is needed.)

FLab
  • 7,136
  • 5
  • 36
  • 69

3 Answers3

72

As you want to change the figure, instead of creating a new one, may I suggest the following way:

  1. Use an interactive backend; %matplotlib notebook
  2. Update the line in the plot, instead of drawing new ones.

So the code could look something like this:

%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_idle()

interact(update);

enter image description here

Alternatively you may use plt.show() as in this answer.

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • 1
    Why is there a comma after `line` ? in line `line, = ax.plot(x, np.sin(x))` – Boris Yakubchik Aug 26 '18 at 16:59
  • 1
    @BorisYakubchik See [is this trailing comma the comma operator?](https://stackoverflow.com/questions/16037494/x-is-this-trailing-comma-the-comma-operator) – ImportanceOfBeingErnest Aug 26 '18 at 17:28
  • @ImportanceOfBeingErnest As soon as I click the widget and try to slide it, it disappears. Any idea why? Jupyter version info: The version of the notebook server is 4.3.1 and is running on Python 3.6.6, IPython 5.1.0 – vestland Dec 03 '18 at 21:01
  • 2
    @vestland I just tested with Python 3.6.6, jupyter core 4.4.0, notebook server 5.6.0, jupyter_client 5.2.3, jupyter_console 5.2.0, Ipython 6.5.0, ipywidgets 7.4.2 (not sure which is relevant here), and it works as expected. – ImportanceOfBeingErnest Dec 03 '18 at 21:40
  • 1
    For me, `fig.canvas.draw_idle()` works better as rapid parameter changes do not leave *ghost* plots. – norok2 May 29 '19 at 10:59
  • This is a great simple example. Thank you! – twinturbotom Mar 02 '20 at 03:48
3

For completion, here is an answer that makes use of more than one slider bar and sets the default parameters as well as the interval lengths.

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

x = np.linspace(-10, 10,100)

def f(x, A, B, C):
    return A*x**2 + B*x + C

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
line, = ax.plot(x, f(x, A=1, B=1, C=1))

def update(A = 1, B = 0, C = 0):
    line.set_ydata(f(x,A,B,C))
    fig.canvas.draw_idle()
    
interact(update, A = (-4,4,0.1), B = (-4,4,0.1), C = (-4,4,0.1));

enter image description here

Luis Jose
  • 664
  • 6
  • 8
2

This is an issue (?) introduced in the last version of jupyter and/or ipywidgets. One workaround I found was to add the line plt.show() at the end of plot_func.

Stelios
  • 5,271
  • 1
  • 18
  • 32
  • 1
    This will create a new figure for every silder update, right? So, it seems to be the most inefficient of all solutions? – ImportanceOfBeingErnest Jun 02 '17 at 15:13
  • @ImportanceOfBeingErnest Creating a new figure for every slider update is clearly not efficient. Your approach is (+1). I only added this answer as it resolves the issue to the (inefficient) approach of the OP. TBH, I do find this inefficient approach more convenient for a quick and dirty view of a function's properties. – Stelios Jun 02 '17 at 15:21
  • I see, maybe you add that argument to the answer? – ImportanceOfBeingErnest Jun 02 '17 at 15:22