I have two matplotlib subplots in a Tkinter canvas plotting the same data, with Matplotlib NavigationToolbar2TkAgg buttons for the user to navigate the subplots, etc. I would like to have the top panel display one region of the data (with xlimits x1 to x2), while the bottom panel automatically shows what the data looks like offset from that region (xlimits: x1+offset to x2+offset) based on how the user zooms/pans in either panel. I'm essentially looking for sharex/sharey behaviour in Tkinter, but with the limit values manipulated by some simple function. Is there a way to catch a NavigationToolbar event happening to trigger a simple function; or am I going about this the wrong way?
You can set new axis limits for one plot depending on the axis limits of another plot. Use xlim_changed
events on both axes to call a function that adjusts the limits of the other plot depending on the current limits.
One needs to make sure to disconnect the event prior to changing the limits, in order not to end up in an infinite loop.
The following would be an implementation where the bottom plot is shifted by 100 units compared to the top one.
import numpy as np; np.random.seed(1)
import matplotlib.pyplot as plt
x = np.linspace(0,500,1001)
y = np.convolve(np.ones(20), np.cumsum(np.random.randn(len(x))), mode="same")
fig, (ax, ax2) = plt.subplots(nrows=2)
ax.set_title("original axes")
ax.plot(x,y)
ax2.set_title("offset axes")
ax2.plot(x,y)
offset = lambda x: x + 100
inverse_offset = lambda x: x - 100
class OffsetAxes():
def __init__(self, ax, ax2, func, invfunc):
self.ax = ax
self.ax2 = ax2
self.func = func
self.invfunc = invfunc
self.cid = ax.callbacks.connect('xlim_changed', self.on_lims)
self.cid2 = ax2.callbacks.connect('xlim_changed', self.on_lims)
self.offsetaxes(ax, ax2, func)
def offsetaxes(self,axes_to_keep, axes_to_change, func):
self.ax.callbacks.disconnect(self.cid)
self.ax2.callbacks.disconnect(self.cid2)
xlim = np.array(axes_to_keep.get_xlim())
axes_to_change.set_xlim(func(xlim))
self.cid = ax.callbacks.connect('xlim_changed', self.on_lims)
self.cid2 = ax2.callbacks.connect('xlim_changed', self.on_lims)
def on_lims(self,axes):
print "xlim"
if axes == self.ax:
self.offsetaxes(self.ax, self.ax2, self.func)
if axes == self.ax2:
self.offsetaxes(self.ax2, self.ax, self.invfunc)
o = OffsetAxes(ax, ax2, offset, inverse_offset)
plt.show()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.