python - Dynamically change y limit -


here code:

#!/usr/bin/python import numpy np import matplotlib.pyplot  plt   matplotlib.widgets import slider ######################################## t = np.arange(0.0, 1.0, 0.001) a0 = 5 f0 = 3 s = a0*np.sin(2*np.pi*f0*t) ######################################## plt.close('all') fig, ax = plt.subplots(nrows=2, ncols=1) plt.subplots_adjust(bottom=0.30) ######################################## line0, = ax[0].plot(t,s, lw=2, color='red',   label="red") # line necessary line1, = ax[1].plot(t,s, lw=2, color='green', label="green") ######################################## ax[0].set_xlim([0, 1]) ax[0].set_ylim([-10, 10]) ######################################## axcolor = 'lightgoldenrodyellow' left   = 0.25 bottom = 0.20 width  = 0.65 # different scale # height = fig.get_size_inches()[1] * 0.1 height = 0.03 vgap   = 0.02 print "fig height %s" % fig.get_size_inches()[1]  f1  = plt.axes([left, bottom-0*(height+vgap), width, height], axisbg=axcolor) a1  = plt.axes([left, bottom-1*(height+vgap), width, height], axisbg=axcolor)  sf1 = slider(f1, 'freq1', 0.1, 30.0, valinit=f0) sa1 = slider(a1, 'amp1',  0.1, 10.0, valinit=a0) ######################################## def update1(val):     amp  = sa1.val     freq = sf1.val      line0.set_ydata(amp*np.sin(2*np.pi*freq*t))     line1.set_ydata(2*amp*np.sin(2*np.pi*freq*t))  sf1.on_changed(update1) sa1.on_changed(update1)  plt.show() 

when amplitude/frequency of wave on 1st plot changed using slider changes amplitude/frequency of wave on 2nd plot (it doubles amplitude on 2nd plot). problem when amplitude of 1st plot exceeds 3. in case not fits in 2nd plot. because has y range -6 6. y limit not enough

three questions:

  1. where -6 , 6 number comes from? did not set them.
  2. how can y limit changed dynamically on 2nd plot? can set using e.g. ax[1].set_ylim([-20, 20]) want more general. let's pretend 2nd plot can have y value more 20 (it might result of complicated computation not known during plotting). when amplitude of 1st plot small value y of 2nd plot should shrink , when amplitude large y should expand.
  3. can leave 2nd plot empty until change amplitude/frequency of 1st plot. in other words can (please show both cases, 1 when 2nd plot existing , when not) achieved without creating 2nd plot first using following line: line1, = ax[1].plot(t,s, lw=2, color='green', label="green")

edit: user hitzg provided helpful improvements original answer in comments - i've taken these , made answer deeper , more generic.


i'll take questions 1 one

  1. where did 6 , -6 come from?

that's matplotlib's best guess, based on data plotted on axis originally. if don't specify values, fit axes limits best can.

for deeper interest - these lines of code matplotlib defaults auto-scaling axes if no scales specified, this line applying auto scaling.

  1. how can y limit changed dynamically on 2nd plot? i

you're there. in update1(), add ax[1].autoscale_view() which, you've added new data, must preceded by ax[1].relim(). let matplotlib autoscale axes suit values of whatever data have plotted on them , generic solution. if need 'manual' dynamic control of axes yourself, see original suggestion below.

n.b. in original version, suggested writing ax[1].set_ylim(-2.2*amp,2.2*amp) or similar 2.2 arbitrary factor: limits of sine wave amplitude set slider plus little bit (the 0.2)

  1. can leave 2nd plot empty until change amplitude/frequency of 1st plot?

yes. 1 way replace

line1, = ax[1].plot(t,s, lw=2, color='green', label="green") 

with

line1, = ax[1].plot([],[], lw=2, color='green', label="green") 

this creates line object on axes can update, has no data. n.b. suggested using 0,0 instead of [],[], plot point @ 0,0 might not suit purposes.

and in update1() put

line1.set_xdata(t) 

final code update1() function

def update1(val):     amp  = sa1.val     freq = sf1.val      line0.set_ydata(amp*np.sin(2*np.pi*freq*t))     line1.set_xdata(t)     line1.set_ydata(2*amp*np.sin(2*np.pi*freq*t))     ax[1].relim()     ax[1].autoscale_view() 

Comments