Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to speed up interactive IPython Notebook plots by not generating new figures every time?

Every example I've seen of using widgets for interactive matplotlib plots in the notebook do something like this (adapted from here):

%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt
from IPython.html.widgets import interact
from IPython.display import display

def sigmoid_demo(a=5,b=1):
    x = np.linspace(0,10,256)
    s = 1/(1+np.exp(-(x-a)/(b+0.1))) # +0.1 to avoid dividing by 0
    sn = 100.0*(s-min(s))/(max(s)-min(s)) # normalize sigmoid to 0-100

    # Does this have to be in this function?
    fig, ax = plt.subplots(figsize=(24,6))

    ax.set_xticks([])
    ax.set_yticks([])
    plt.plot(x,sn,lw=2,color='black')
    plt.xlim(x.min(), x.max())

w=interact(sigmoid_demo,a=5,b=1)

I suspect that the responsiveness of the plot could be sped up hugely if you didn't have to create a brand new figure with plt.subplots() or plt.figure() each time a widget was adjusted.

I've tried a few things to move figure creation outside of the function being called by interact() but nothing has worked.

like image 878
Mr. W. Avatar asked May 13 '15 20:05

Mr. W.


People also ask

What happens if I dont use %Matplotlib inline?

In the current versions of the IPython notebook and jupyter notebook, it is not necessary to use the %matplotlib inline function. As, whether you call matplotlib. pyplot. show() function or not, the graph output will be displayed in any case.

What is the currently correct way to dynamically update plots in Jupyter IPython?

What is the currently correct way to dynamically update plots in Jupyter/iPython? We can first activate the figure using plt. ion() method. Then, we can update the plot with different sets of values.


1 Answers

Some setup:

%matplotlib notebook
import matplotlib.pyplot as plt
from IPython.html.widgets import interactive
from IPython.display import display
import numpy as np

Create your objects:

fig, ax = plt.subplots()
ax.set_xlim(0, .25)
ax.set_ylim(-2.5, 2.5)
ax.set_title('beat frequencies')
lnA, = ax.plot([], [], color='r', label='A')
lnB, = ax.plot([], [], color='purple', label='B')
lnsum, = ax.plot([], [], color='k', label='signal')
ax.legend()
max_time = 3
rate = 8000
times = np.linspace(0,max_time,rate*max_time)

def beat_freq(f1=220.0, f2=224.0):

    A = np.sin(2*np.pi*f1*times)
    B = np.sin(2*np.pi*f2*times)
    sig = A + B

    lnA.set_data(times, A)
    lnB.set_data(times, B)
    lnsum.set_data(times, sig)

    plt.draw()

beat_freq(0, 0)

and the interactive (which I think needs to go in it's own cell)

interactive(beat_freq, f1=(200.0,300.0), f2=(200.0,300.0))

You can also poke at the objects from a different cell:

ax.set_xlim(0, .05)
ax.set_ylim(-2, 2)
plt.draw()

or

lnB.set_color('g')
ax.legend()
plt.draw()
like image 194
tacaswell Avatar answered Oct 06 '22 00:10

tacaswell