I can't find the solution to update the graph when the slider is moved (in Jupyter notebook). The graph shows the sine and cosine functions, and their sum. The sine and cosine are weighed by the value of the slider (k) between 0 and 1:
- sine = k * sin(x)
- cosine = (1-k) * cos(x)
The arrays to plot are updated correctly, e.g. for k = 0.2:
np.max(graph.ysin), np.max(graph.ycos)
0.19997482553477502, 0.7995972339065481)
The plots don't update, they continue to show curves for k = .5 (initial value).
Note I don't want (as far as possible) to recreate the whole figure each time the slider changes, only to update the plots by passing the updated arrays with Line2D.set_data.
What I tried:
- Adding
plt.show ()
call (suggested here) - Adding
fig.canvas.draw()
(suggested here) - Adding
%matplotlib notebook
(suggested here) - Adding
ax.relim() and ax.autoscale_view()
(suggested here)
and some combinations of them...
class DynamicGraph ():
def __init__ (self, ratio):
# Define x range
self.x = np.linspace (-np.pi, np.pi, 100)
# Compute and display values
self.init_figure (ratio)
# Set figure, axe and plots
def init_figure (self, ratio):
self.fig, self.ax = plt.subplots (figsize=(8,3))
self.ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(np.pi/2))
self.ax.xaxis.set_major_formatter(mpl.ticker.FuncFormatter(lambda x,pos:f'{x/np.pi} $\pi$'))
self.ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(.25))
self.ax.axhline(-.5, color='grey', lw=.5)
self.ax.axhline(0, color='grey', lw=.5)
self.ax.axhline(.5, color='grey', lw=.5)
self.ax.axvline(0, color='grey', lw=.5)
self.show_plots (ratio, init=True)
plt.legend ()
return
# Create/update plots
def show_plots (self, ratio, init=False):
self._compute_values_ (ratio)
if init:
self.sin_plot, = self.ax.plot(self.x, self.ysin, color='grey', ls=':', label='sin');
self.cos_plot, = self.ax.plot(self.x, self.ycos, color='grey', ls='--', label='cos');
self.sum_plot, = self.ax.plot(self.x, self.ysum, color='green', label='sin+cos');
else:
self.sin_plot.set_data (self.x, self.ysin)
self.cos_plot.set_data (self.x, self.ycos)
self.sum_plot.set_data (self.x, self.ysum)
return
# Compute values which change with the slider value
def _compute_values_ (self, ratio):
self.ysin = ratio*np.sin(self.x)
self.ycos = (1-ratio)*np.cos(self.x)
self.ysum = self.ysin + self.ycos
return
# Create slider, listen to changes
slider = widgets.FloatSlider (min=0, max=1, value=.5)
slider. observe(lambda change: graph.show_plots (slider.value), names='value')
# Show slider and graph
display(slider)
graph = DynamicGraph (slider.value)
I'd appreciate some explanation with the solution, e.g. if this has something to do with a particular context, or version, etc to understand why the above suggestions where not applicable.