Bobesh
Bobesh

Reputation: 1207

Use slider for two different lines in one subplot matplotlib

I am plotting six subplots in one figure in matplotlib. I am plotting one function with different parameter values using matplotlib sliders. There are two lines in one subplot, each representing function. I want to see where they cross and how they behave if I am changing function parameters. But I havent figured out how to plot two lines and change ydata for two lines in one subplot with sliders.

Here is part of code:

#imports
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.widgets as mw
import math
import numpy as np

#set variables
E0 = 0.5
E1 = .0003
V = .3

#x axis
N = [i for i in range(10000)]

#functions
V_fc_list = [V for n in N]
E_list = [E0*math.exp(-E1*n) for n in N]

#subplots
fig = plt.figure()
ax1 = fig.add_subplot(321)
ax2 = fig.add_subplot(322)
ax3 = fig.add_subplot(323)
ax4 = fig.add_subplot(324)
ax5 = fig.add_subplot(325)
ax6 = fig.add_subplot(326)
#sliders place
ax6.axis('off')

#Sliders
axis_color = 'lightgoldenrodyellow'
E0_slider_ax = fig.add_axes([0.57, 0.3, 0.3, 0.02], axisbg=axis_color)
E1_slider_ax = fig.add_axes([0.57, 0.25, 0.3, .02], axisbg = axis_color)
V_slider_ax = fig.add_axes([0.57, 0.2, 0.3, .02], axisbg = axis_color)
E0_slider = mw.Slider(E0_slider_ax, r'$\epsilon_0$', valmin = 0, valmax = 1, valinit = E0)
E0_slider.label.set_size(15)
E1_slider = mw.Slider(E1_slider_ax, r'$\epsilon_1$', 0.0001, 0.003, valinit = E1)
E1_slider.label.set_size(15)
V_slider = mw.Slider(V_slider_ax, r'$V_c$', 0.001, 0.99, valinit = V)
V_slider.label.set_size(15)

#slider function HERE IS THE MISTAKE
def sliders_on_change(val):
    p2.set_ydata([V_slider.val for n in N])
    p2.set_ydata([E0_slider.val*math.exp(-E1_slider.val*n) for n in N])
    fig.canvas.draw_idle()

V_slider.on_changed(sliders_on_change)
E0_slider.on_changed(sliders_on_change)
E1_slider.on_changed(sliders_on_change)

Here is the last part of error from python

  File "C:/Users/Robert/Desktop/python/multidif_S.py", line 109, in <module>
    p2,= ax2.plot(N, V_fc_list, 'r-', N, E_list, 'b-', lw = 3)

ValueError: too many values to unpack (expected 1)

Thx for any help!

Upvotes: 0

Views: 982

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339795

If you have two lines in a plot, you need to unpack them to two different variables,

p2,p3 = ax2.plot(N, V_fc_list, 'r-', N, E_list, 'b-', lw = 3)

You can then set the data on the two lines as follows:

def sliders_on_change(val):
    p3.set_ydata([V_slider.val for n in N])
    p2.set_ydata([E0_slider.val*math.exp(-E1_slider.val*n) for n in N])
    fig.canvas.draw_idle()

Upvotes: 1

Michael H.
Michael H.

Reputation: 3493

I changed only a few things in your code to get this:

#imports
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.widgets as mw
import math
import numpy as np

#set variables
E0 = 0.5
E1 = .0003
V = .3

#x axis
N = [i for i in range(10000)]

#functions
V_fc_list = [V for n in N]
E_list = [E0*math.exp(-E1*n) for n in N]

#subplots
fig = plt.figure()
ax1 = fig.add_subplot(321)
ax2 = fig.add_subplot(322)
ax3 = fig.add_subplot(323)
ax4 = fig.add_subplot(324)
ax5 = fig.add_subplot(325)
ax6 = fig.add_subplot(326)
#sliders place
ax6.axis('off')

#Sliders
axis_color = 'lightgoldenrodyellow'
E0_slider_ax = fig.add_axes([0.57, 0.3, 0.3, 0.02], axisbg=axis_color)
E1_slider_ax = fig.add_axes([0.57, 0.25, 0.3, .02], axisbg = axis_color)
V_slider_ax = fig.add_axes([0.57, 0.2, 0.3, .02], axisbg = axis_color)
E0_slider = mw.Slider(E0_slider_ax, r'$\epsilon_0$', valmin = 0, valmax = 1, valinit = E0)
E0_slider.label.set_size(15)
E1_slider = mw.Slider(E1_slider_ax, r'$\epsilon_1$', 0.0001, 0.003, valinit = E1)
E1_slider.label.set_size(15)
V_slider = mw.Slider(V_slider_ax, r'$V_c$', 0.001, 0.99, valinit = V)
V_slider.label.set_size(15)

# Here I introduce the plots p1 and p2. Your code didn't have any plots.
p1 = ax1.plot(np.zeros_like(N))  # plot1 
p2 = ax1.plot(np.zeros_like(N))  # plot2, both in ax1

#slider function HERE IS THE MISTAKE
def sliders_on_change(val):
    p1[0].set_ydata([V_slider.val for n in N])  # update p1
    p2[0].set_ydata([E0_slider.val*math.exp(-E1_slider.val*n) for n in N]) # update p2
    ax1.relim()  # rescale the shown area (like an automatic call of ax1.set_xlim and ax1.set_ylim with proper inputs)
    ax1.autoscale_view()  # taken from this question: http://stackoverflow.com/questions/10984085/automatically-rescale-ylim-and-xlim-in-matplotlib
    fig.canvas.draw()

V_slider.on_changed(sliders_on_change)
E0_slider.on_changed(sliders_on_change)
E1_slider.on_changed(sliders_on_change)

You see I commented where I changed something. Mostly this was adding the plots p1 and p2 and rescaling on update.

I hope this works for you. I can't help you with that error code because the code you provided does not even have 109 lines...

Upvotes: 1

Related Questions