In all the examples I can find using interact to produce matplotlib plots in the notebook, the function that is passed to interact generates a new matplotlib Figure. For instance,
If one modifies that example to create a single Figure and Axes beforehand and then just modify what is on the axes for each widget value, it doesn't work; only the widget appears, with no plot. Here is the modification I'm referring to:
I think this is because the inline backend defaults to closing the figure at the end of the cell.
I think there is a configure option to change this somewhere in IPython
You can also try using the nnagg backend which is fully interactive and more suitable for interactive work.
I was experimenting with this recently and it does work. But I found that I had to create the figure in a cell before using interact in the next. I have not had the time to debug that.
I think this is because the inline backend defaults to closing the figure at the end of the cell.
No, if you create a figure in one cell and reference it later, it appears again just fine. I often use this.
You can also try using the nnagg backend which is fully interactive and more suitable for interactive work. I was experimenting with this recently and it does work. But I found that I had to create the figure in a cell before using interact in the next. I have not had the time to debug that.
I tried running your notebook and I get no plot from the last cell:
I'm running IPython 2.3.1.
Thanks again for your help; I would really like to make this work.
In that notebook the plot should be attached to the cell above the interact. The idea is first to create a figure and then attach a interact to it in the next cell. If that doesn't work I guess that the nbagg backend is not working for you.
Thanks to @jenshnielsen for the workaround, which works for me now. It would be nice if one did not need to put the figure creation and interact in separate cells, but does what I wanted. To summarize, what does NOT work is:
in-place updates of interact plots using the inline backend
in-place updates of interact plots using the nbagg backend, unless the figure creation and interact are in two separate cells.
@blink1073 Hello! Im sorry, but how exactly can we get it working now?
If I define the following function:
def my_func(x,y,a=1,b=1):
val = np.sin(a*x**2 + b*y**2)
return val
I then to try to only plot the particular slices interactively as:
# Make 3D Plot:
# setup the 3D Grid of points
x = np.arange(-3, 3, 0.025) # points in the x axis
y = np.arange(-3, 3, 0.025) # points in the y axis
XGrid, YGrid = np.meshgrid(x, y) # create the "base grid"
# calculate your function on this grid
Z = my_func(XGrid,YGrid)
# setup 3D figure
fig = plt.figure(figsize=(20,5));
# Create 3D Subplot
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
# plot it on the sublot
ax2 = fig.add_subplot(2,2,2)
# plot it on the sublot
ax3 = fig.add_subplot(2,2,4)
# 3D Plot
ax1.plot_surface(XGrid, YGrid, Z, # data values (2D Arryas)
rstride=2, # row step size
cstride=2, # column step size
cmap=cm.RdPu, # colour map
linewidth=0, # wireframe line width
antialiased=True,
alpha=0.3);
# interactive plotting
def plot_slices(x_val, y_val,ax2,ax3):
## plot x slice
# setup y value
y = np.arange(-3,3,0.025)
# calculate function for that x_value
z = my_func(x_val,y)
ax2.plot(y,z, 'r--');
# setup figure asthetics
ax2.set_xlabel('y axis');
ax2.set_ylabel('z axis');
ax2.set_title('A slice in x: f(' + str(np.round(x_val,2)) + ', y)');
## plot y slice
# setup x values
x = np.arange(-3,3,0.025)
# calculate function for that y_value
z = my_func(x,y_val)
# plot it on the sublot
ax3.plot(x,z, 'b--');
# setup figure asthetics
ax3.set_xlabel('y axis');
ax3.set_ylabel('z axis');
ax3.set_title('A slice in y: f(x,' + str(np.round(y_val,2)) + ')');
interact(plot_slices, x_val=(-3,3,0.1), y_val=(-3,3,0.1),ax2=fixed(ax2),ax3=fixed(ax3));
But that doesn't work. I get an initial plot and then upon moving the sliders the entire figure disappears. The only way to make it work is to have it declare the figure and axes inside the function everytime!
Activity
ketch commented on Jan 21, 2015
Note that matplotlib's funcanimation does work with in-place figure updates.
jenshnielsen commented on Jan 21, 2015
I think this is because the inline backend defaults to closing the figure at the end of the cell.
I think there is a configure option to change this somewhere in IPython
You can also try using the nnagg backend which is fully interactive and more suitable for interactive work.
I was experimenting with this recently and it does work. But I found that I had to create the figure in a cell before using interact in the next. I have not had the time to debug that.
An example is available here http://nbviewer.ipython.org/github/jenshnielsen/netcdf-lesson/blob/master/Interactive%20plotting%20with%20nbagg.ipynb
Edit For this to work directly I think you need dev versions of both matplotlib and IPython
ketch commented on Jan 21, 2015
Thanks for the suggestions.
No, if you create a figure in one cell and reference it later, it appears again just fine. I often use this.
I tried running your notebook and I get no plot from the last cell:
I'm running IPython 2.3.1.
Thanks again for your help; I would really like to make this work.
jenshnielsen commented on Jan 21, 2015
In that notebook the plot should be attached to the cell above the interact. The idea is first to create a figure and then attach a interact to it in the next cell. If that doesn't work I guess that the nbagg backend is not working for you.
ketch commented on Jan 21, 2015
Ah, it does work! I did not expect the widget to control a plot in another output cell, so I didn't notice. Thanks; I will try this.
ketch commented on Jan 21, 2015
Thanks to @jenshnielsen for the workaround, which works for me now. It would be nice if one did not need to put the figure creation and interact in separate cells, but does what I wanted. To summarize, what does NOT work is:
davidcortesortuno commented on Dec 23, 2015
Has this been solved to allow the widget to be in the same place than the plot?
blink1073 commented on Dec 27, 2015
@davidcortesortuno, the new matplotlib IPython widget will allow that to take place: matplotlib/matplotlib#5754 (comment).
diego898 commented on Aug 9, 2016
@blink1073 Hello! Im sorry, but how exactly can we get it working now?
If I define the following function:
def my_func(x,y,a=1,b=1): val = np.sin(a*x**2 + b*y**2) return valI then to try to only plot the particular slices interactively as:
# Make 3D Plot: # setup the 3D Grid of points x = np.arange(-3, 3, 0.025) # points in the x axis y = np.arange(-3, 3, 0.025) # points in the y axis XGrid, YGrid = np.meshgrid(x, y) # create the "base grid" # calculate your function on this grid Z = my_func(XGrid,YGrid) # setup 3D figure fig = plt.figure(figsize=(20,5)); # Create 3D Subplot ax1 = fig.add_subplot(1, 2, 1, projection='3d') # plot it on the sublot ax2 = fig.add_subplot(2,2,2) # plot it on the sublot ax3 = fig.add_subplot(2,2,4) # 3D Plot ax1.plot_surface(XGrid, YGrid, Z, # data values (2D Arryas) rstride=2, # row step size cstride=2, # column step size cmap=cm.RdPu, # colour map linewidth=0, # wireframe line width antialiased=True, alpha=0.3); # interactive plotting def plot_slices(x_val, y_val,ax2,ax3): ## plot x slice # setup y value y = np.arange(-3,3,0.025) # calculate function for that x_value z = my_func(x_val,y) ax2.plot(y,z, 'r--'); # setup figure asthetics ax2.set_xlabel('y axis'); ax2.set_ylabel('z axis'); ax2.set_title('A slice in x: f(' + str(np.round(x_val,2)) + ', y)'); ## plot y slice # setup x values x = np.arange(-3,3,0.025) # calculate function for that y_value z = my_func(x,y_val) # plot it on the sublot ax3.plot(x,z, 'b--'); # setup figure asthetics ax3.set_xlabel('y axis'); ax3.set_ylabel('z axis'); ax3.set_title('A slice in y: f(x,' + str(np.round(y_val,2)) + ')'); interact(plot_slices, x_val=(-3,3,0.1), y_val=(-3,3,0.1),ax2=fixed(ax2),ax3=fixed(ax3));But that doesn't work. I get an initial plot and then upon moving the sliders the entire figure disappears. The only way to make it work is to have it declare the figure and axes inside the function everytime!
blink1073 commented on Aug 9, 2016
The widget will be in matplotlib 2.1, which has not yet been released.
diego898 commented on Aug 9, 2016
ah. Ok thanks @blink1073 !
satra commented on Sep 8, 2017
i'm testing with matplotlib 2.1.0rc1 and this bug appears to be still there.
satra commented on Sep 8, 2017
actually it seems that it is working.
jenshnielsen commented on Sep 9, 2017
The widget vas removed from matplotlib 2.1 after @blink1073 comment. It's now what will become https://github.com/matplotlib/jupyter-matplotlib