3

I have a plot that is a representation of a sine wave.

In the code, I have the frequency of the sine wave represented as a variable b. I need to be able to change b in real time (i.e. without having to re-run the code after manually changing the value). Ideally, this could be done by using a slider. I tried to use Tkinter's Slider feature, but was unable to embed the plot in the Tkinter window.

The code that generates the stimulus is as follows:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm      

vals = np.linspace(-np.pi,np.pi,100)
xgrid, ygrid = np.meshgrid(vals,vals)       

b = 5
the_sine = np.sin(xgrid * b)    

plt.imshow(the_sine)        
fig = plt.imshow(the_sine, cm.gray)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)

plt.show()      

I can't include an image of the plot, but if you run the code, you'll see how this is a little different than adjusting the parameters of something like a simple line.

Any suggestions?

Mickey
  • 131
  • 3
  • 12
  • possible duplicate of [matplotlib slider for parameters](http://stackoverflow.com/questions/12006883/matplotlib-slider-for-parameters) – drglove Jun 23 '15 at 22:16
  • The difference is the variable I need to manipulate is within an equation - after sliding the bar, the equation will need to be immediately re-evaluated to display the consequent image. I don't know how to incorporate the slider into the code I have. – Mickey Jun 23 '15 at 22:32
  • There is no fundamental difference between the an equation like sin(bx), and an arbitrary function as listed in the duplicate. I'll post an answer soon that follows that solution for your problem. – drglove Jun 23 '15 at 23:16

1 Answers1

3

Following matplotlib slider for parameters, it's possible to use the matplotlib.widgets.Slider module to update the data contained in the figure.

Simply define your function that you're plotting with some arbitrary parameter, make a slider and stuff it into your plot, and call fig.set_data with your function evaluated at the new slider value everytime the slider changes. This is done by defining an update function (see below) and calling Slider.on_changed(my_update_function).

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm      
from matplotlib.widgets import Slider

vals = np.linspace(-np.pi,np.pi,100)
xgrid, ygrid = np.meshgrid(vals,vals)       

def f(x, y, b):
    return np.sin(x * b)
b = 5

ax = plt.subplot(111)
plt.subplots_adjust(left=0.15, bottom=0.25)
fig = plt.imshow(f(xgrid, ygrid, b), cm.gray)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)

axb = plt.axes([0.15, 0.1, 0.65, 0.03])
sb = Slider(axb, 'b', 0.1, 10.0, valinit=b)
def update(val):
    fig.set_data(f(xgrid, ygrid, val))
sb.on_changed(update)

plt.show()

This should produce the plot you're looking for, where you scan over b.

Community
  • 1
  • 1
drglove
  • 638
  • 1
  • 6
  • 21
  • Thank you! Is there a way to add something like a +/- button to the slider? Is that a feature of this widget? – Mickey Jun 24 '15 at 02:33
  • I'm not sure, you'll have to explore the `matplotlib.widgets` package for that. – drglove Jun 24 '15 at 20:06