7

Consider the following python code for plotting a matplotlib figure:

import matplotlib.pylab as pp
import numpy as np

alpha = np.linspace(0, 2 * np.pi, 400)
sig1 = np.sin(alpha)
sig2 = np.sin(2 * alpha) + 2 * (alpha > np.pi)

ax1 = pp.subplot(111)
ax2 = ax1.twinx()

ax1.plot(alpha, sig1, color='b')
ax2.plot(alpha, sig2, color='r')
ax1.set_ylabel('sig1 value', color='b')
ax2.set_ylabel('sig2 value', color='r')
pp.grid()
pp.show()

Giving me a nice plot

enter image description here

I would like to find out how to disable one of the axes for panning / zooming, so when I use the pan / zoom tool, only ax2 will rescale for example. Is there a way to do this? I want to do it programmatically.

danodonovan
  • 19,636
  • 10
  • 70
  • 78
Tompa
  • 5,131
  • 2
  • 13
  • 13
  • I suspect you will have to write a callback to update the second axis when the first one changes. pan/zoom are axis level activities and it is not clear how you want the two y-axis generate by twinx to be linked generically. It works for the x-axis because they use the same underlying objects for the x-axis. – tacaswell Mar 09 '13 at 04:03

2 Answers2

7

You can do this using ax2.set_navigate(False):

from matplotlib.pyplot import *
import numpy as np

fig,ax1 = subplots(1,1)
ax2 = ax1.twinx()
ax2.set_navigate(False)
x = np.linspace(0,2*np.pi,100)
ax1.plot(x,np.sin(x),'b')
ax1.set_xlabel('Scaleable axis')
ax1.set_ylabel('Scaleable axis')
ax2.plot(x,np.sin(x+1),'r')
ax2.set_ylabel('Static axis',weight='bold')
ali_m
  • 71,714
  • 23
  • 223
  • 298
  • I had a feel there would be a built-in way to do this. Thank you for finding out. The "need" for this has occured for me once or twice but it seems im not in a big crowd. – Tompa Apr 30 '13 at 10:09
  • Yeah, it seems like a pretty niche feature - I was quite surprised it even existed! Out of curiosity what do you use it for? – ali_m Apr 30 '13 at 17:47
  • I have data from measurements. One being a pulsating voltage signal and for example flow readings whitch vary over time. Analyzing the flow relating to voltage then, is more convinient with the voltage scale being fixed. Fabulus. – Tompa Apr 30 '13 at 21:38
  • It's not a niche feature if the combination of having two vertical axes and using panning mode isn't also a niche feature. Usually the two axes are for quantities of different dimension, not only different units (e.g., mmHg and mbar), which is one of the rare cases of naturally linked axes I can think of. So a default behaviour could be to only affect the axis defined first. Or to determine the axis addressed by the user based on the initial mouse position. – Rainald62 Oct 24 '18 at 11:46
0

A slightly more complex example with two plot areas and three vertical axes. Only the common horizontal axis and the left vertical axis of the lower subplot are interactive.

fig, ax_left = plt.subplots()
ax_right = ax_left.twinx()
ax_status = make_axes_locatable(ax_left).append_axes('top', size=1.2, pad=0., sharex=ax_left)
ax_status.xaxis.set_tick_params(labelbottom=False)
ax_right.set_navigate(False)
ax_status.set_navigate(False)

Before I added set_navigate(False) according to ali_m's answer, the two vertical axes of the lower plot were both affected by dragging the mouse vertically in the lower plot, while the status axis was unaffected as it should but only after the first mouse gesture. Dragging the mouse for the first time, all axes are affected. This seems to be a bug in matplotlib, just reported as #12613.

Rainald62
  • 706
  • 12
  • 19