0

With Jupyter Notebook 6.5.4, Python 3.8.13, IPython 8.12.0, I can make an interactive plot with:

from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook 
#inline doesn't work in jupyter notebook 
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
fig, ax = plt.subplots(figsize=(6,4))
x = np.linspace(-10, 10, num=1000)
l, = ax.plot(x, r_widget.value * x + c_widget.value)
ax.set_ylim(-5, 5)
def f(m, b):
    l.set_ydata(m*x+b) 
    fig.canvas.draw()
interactive_plot = interactive(f, m = m_widget, b=b_widget )
interactive_plot 

and the interactive plot works with pan/zoom and updates as I slide the widgets. I thought this technique would be better/faster/more efficient since I am not creating the figure with each slider adjustment, but instead only updating the line data. Also, I found if I didn't update the line data directly, I would end up with new lines on each update, instead of just changing the line. I switched to jupyterlab 3.6.3, and a few others have asked about the differences with interactive plotting between jupyterlab and jupyter notebook, however those solutions are 3-4 years old and are not solving my issue. In jupyterlab, I can only get interactive to work with %matplotlib inline and in the following style:

%matplotlib inline  
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

Using %matplotib notebook and %matplotlib widget both result in Javascript Error: IPython is not defined. If I move the fig, ax = plt.subplots(figsize=(6,4)) above the function f, the plot does nothing. This answer has not changed the behavior I'm describing. I have ipympl 0.9.3. Should I not expect my older style of making interactive plots to work? Is there even an advantage to that (besides being able to pan/zoom)?

Erik Iverson
  • 309
  • 1
  • 11

2 Answers2

0

In JupyterLab 3.4.8, the following variations of your second code block works to have both the pan/zoom, etc. 'interactivity' options and the ipywidgets interactivity of the plot.

%matplotlib ipympl
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

This is where ipympl is installed.

This also works:

%matplotlib widget
from ipywidgets import interactive, FloatSlider
import matplotlib.pyplot as plt
import numpy as np
m_widget = FloatSlider(min=-2, max=2, step=.5, readout_format='.3f', continuous_update=False)
b_widget = FloatSlider(min=-5, max=5, step=.5, readout_format='.1e', continuous_update=False)
def f(m, b):
    fig, ax = plt.subplots(figsize=(6,4))
    x = np.linspace(-10, 10, num=1000)
    ax.plot(x, m * x + b)
    ax.set_ylim(-5, 5)
    plt.show()

interactive_plot = interactive(f, m=m_widget, b=b_widget)
interactive_plot 

This is because as explained 'Basic Example' section in the documentation for ipympl here:

"To activate the ipympl backend all you need to do is include the %matplotlib ipympl magic in the notebook. Alternatively you can use %matplotlib widget which will have the same effect."

I can direct you to a place to compare what you see with what you should see. Click here and after session starts up, open a new notebook and run your second code block. That is JupyterLab 3.4.8 (presently -- it will change over time because it isn't locked) with ipympl installed.

I have verified that the same two code blocks will also work in JupyterLab 4.0.3, too. You can demonstrate that for yourself by clicking here to get a session with JupyterLab 4.0.3 with ipympl installed.
I'll note that to make a version of a MyBinder session that has ipympl installed properly, I had to add before build & launch as it is tricky install and doesn't work if installed later in a running session. In fact, a situation similar to this is probably what you may be seeing because the result, giving javascript error, is similar to what you report.


By the way, this 'interactive plot' is showing two types of interactivity. It exhibits both the interactive features of matplotlib ('ipympl-style interactivity') and ipywidget interactivity in controlling updating of the plot via floating slider widget controller. See an example of 'ipympl-style interactivity', in other words the interactive features of matplotlib, here and see here for a discussion with further examples of using ipywidget's interact and interactive to automatically creates user interface (UI) controls for exploring code and data interactively.

Wayne
  • 6,607
  • 8
  • 36
  • 93
0

I found this discussion and so I did conda install nodejs and now the first code block in my question works with %matplotlib widget and also %matplotlib ipympl, with both types of interaction (the widgets and the pan/zoom).

Erik Iverson
  • 309
  • 1
  • 11