I'm trying to create a Jupyter notebook that plots some data using matplotlib. I've been told that when using pcolormesh, as I am, instead of creating a plot from scratch, one can instead use the set_array function on the plot object and this greatly speeds up the plotting. The person who doing this was using matplotlib for batch processing images, so was using set_ray then calling save_fig, and that worked OK. I would like to use matplotlib to plot data in a jupyter notebook.
Here is an example Jupyter Notebook which contains an example of plotting 2 blobs using pcolormesh, and a Jupyter Widget slider to change the position of one of the blobs:
Link to notebook:
mpl_interactive_plot.ipynb
In the example, I set up a class for plotting. In the next cell I call create_plot(), which creates and shows the plot. In the last cell, I create a Jupiter Widgets slider, which has a callback that should update the plot created in the previous cell when the slider changes position.
I create the plot using a call to pcolormesh:
self.plot_arr[0] = self.axarr[0].pcolormesh(self.xarr,self.yarr,self.blob1_arr,cmap='viridis')
I recalculate the value of the data array in the callback function passed to the slider, and call the following code to update the plot:
self.plot_arr[0].set_array(self.blob1_arr)
to update the array. This seems to have no effect on the plot. It seems likely I need to call some sort of update/refresh function to trigger a redraw of the plot using the new array, but all the obvious candidate just seem to cause the plot to disappear. Is what I'm trying to do sensible, and what is the right way to do it?
Here is the code extracted from the notebook:
import matplotlib
import matplotlib.pyplot
import numpy
import ipywidgets
get_ipython().magic('matplotlib notebook')
def gaussian_blob(xarr, yarr, blob_params):
blob_dist = (xarr - blob_params[0]) **2 + (yarr - blob_params[1])**2
gaussian_func = numpy.exp(-blob_dist / blob_params[2])
return gaussian_func
class MyPlot(object):
def __init__(self):
self.blob1_params = [2.0,5.0,5.0]
self.blob2_params = [8.0,12.0,5.0]
self.plot_arr = None
self.fig_name = 'blob_plots'
self.f1 = None
self.axarr = None
def calc_data(self):
self.xarr, self.yarr = numpy.meshgrid(range(10),range(15))
self.blob1_arr = gaussian_blob(self.xarr, self.yarr, self.blob1_params)
self.blob2_arr = gaussian_blob(self.xarr, self.yarr, self.blob2_params)
def create_plot(self):
self.calc_data()
#print(self.blob1_arr[2,:])
#matplotlib.pyplot.figure(self.fig_name).clear()
self.f1, self.axarr = matplotlib.pyplot.subplots(num=self.fig_name,
ncols=2,
nrows=1,
figsize=matplotlib.pyplot.figaspect(0.5))
self.plot_arr = [None] * 2
self.plot_arr[0] = self.axarr[0].pcolormesh(self.xarr,self.yarr,self.blob1_arr,cmap='viridis')
self.plot_arr[1] = self.axarr[1].pcolormesh(self.xarr,self.yarr,self.blob2_arr,cmap='viridis')
matplotlib.pyplot.show()
def update_plot(self):
self.calc_data()
self.plot_arr[0].set_array(self.blob1_arr)
self.plot_arr[1].set_array(self.blob2_arr)
# probably need some sort of update/refresh call, but what?
def on_x_centre_change(self, xc_event):
self.blob1_params[0] = xc_event['new']
self.update_plot()
plot_obj1 = MyPlot()
plot_obj1.create_plot()
pslider = ipywidgets.IntSlider(value=2,
min=0,
max=10,
description='left x centre',
continuous_update=False)
pslider.observe(plot_obj1.on_x_centre_change, names='value')
pslider