1

Based on this and that examples, I am trying to add sliders to a figure dynamically (in function of the object that is plotted).

The sliders are created and added inside a for-loop, and a new update() function is created every time.

Problems: The sliders do not respond to any mouse inputs!

Any idea how to solve this?

graph

import numpy as np from matplotlib import pyplot as plt from matplotlib.widgets import Slider class Plotter: def __init__(self): self.fig, self.ax = plt.subplots() def plot(self, obj): self.obj = obj self.l = plt.plot(obj.t,obj.series()) vars = obj.get_variables() plt.subplots_adjust(bottom=0.03*(len(vars)+2)) for i,var in enumerate(vars): self.add_slider(i*0.03, var[0], var[1], var[2]) plt.show() def add_slider(self, pos, name, min, max): ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow') slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name)) def update(val): setattr(self.obj, name, val) self.l.set_ydata(self.obj.series()) self.fig.canvas.draw_idle() slider.on_changed(update) class SinFunction: def __init__(self): self.freq = 1.0 self.amp = 0.5 self.t = np.arange(0.0, 1.0, 0.001) def series(self): return self.amp*np.sin(2*np.pi*self.freq*self.t) def get_variables(self): return [ ('freq', 0.1, 10), ('amp', 0.1, 1) ] Plotter().plot(SinFunction()) 

1 Answer 1

1

In the plot method of the Plotter class you are obtaining all the series of the plot in this way self.l = plt.plot(obj.t,obj.series()) so in self.l you have a list of objects and not the object itself. You could have more than one line.

In the add_slider method you should change the line self.l.set_ydata(self.obj.series()) with self.l[0].set_ydata(self.obj.series()) to use the method of the object. In this case there is only one object in self.l but you could have more. Please, take this into account.

Also, to make sliders work accordingly (see comments below) it seems they need to be in the same scope. To have sliders in the same scope you could create a sliders attribute

The final code should be:

import numpy as np from matplotlib import pyplot as plt from matplotlib.widgets import Slider class Plotter: def __init__(self): self.fig, self.ax = plt.subplots() def plot(self, obj): self.obj = obj self.l = plt.plot(obj.t,obj.series()) _vars = obj.get_variables() plt.subplots_adjust(bottom=0.03*(len(_vars)+2)) self.sliders = [] for i,var in enumerate(_vars): self.add_slider(i*0.03, var[0], var[1], var[2]) plt.show() def add_slider(self, pos, name, min, max): ax = plt.axes([0.1, 0.02+pos, 0.8, 0.02], axisbg='lightgoldenrodyellow') slider = Slider(ax, name, min, max, valinit=getattr(self.obj, name)) self.sliders.append(slider) def update(val): setattr(self.obj, name, val) self.l[0].set_ydata(self.obj.series()) self.fig.canvas.draw_idle() slider.on_changed(update) class SinFunction: def __init__(self): self.freq = 1.0 self.amp = 0.5 self.t = np.arange(0.0, 1.0, 0.001) def series(self): return self.amp*np.sin(2*np.pi*self.freq*self.t) def get_variables(self): return [ ('freq', 0.1, 10), ('amp', 0.1, 1) ] k = Plotter() k.plot(SinFunction()) 

This version is working for me on Python 2 and Python 3.

P.D.: I saw different behaviour on Python 2 when compared with Python 3. I don't know if it is something related with Python or with Matplotlib... ¿?

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you! However, this does not resolve the original problem (the non-responsive sliders). Any clue on that?
It is working for me. Please, could you tell me how are you running the code, what errors are you obtaining, library versions,...?
I'm using Python 2.7, matplotlib 1.4.3, and I am running the script from a IPython notebook.
Do you want the plots to be embedded inside the notebook or as an independent window?
I'm fine with a window
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.