简体   繁体   中英

How do you automatically update matplotlib subplot limits based on another's limits within Tkinter?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM