当使用 sahex 属性 对另一个轴进行缩放时更新多个 matplotlib 轴?

update several matplotlib axes when a zoom is done on another one with sahex property?

我想绘制四条曲线,左边是两条时间曲线,右边是两条基于时间曲线的 FFT。 例如:

import matplotlib.pyplot as plt
import numpy as np
from scipy import signal


Fs=1024
t=np.arange(0,10,1/Fs)
F=np.arange(0,10,1/Fs)
x = np.sin(2 * 3.1416 * F *t )

plt.figure()
ax1 = plt.subplot(221)
plt.plot(t,x)
ax2 = plt.subplot(222)
f, Pxx_den = signal.periodogram(x, Fs)
line1, = plt.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

ax3 = plt.subplot(223, sharex=ax1)
plt.plot(t,x)
ax4 = plt.subplot(224)
f, Pxx_den = signal.periodogram(x, Fs)
line1, = plt.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )


def on_xlims_change1(axes):
    lim = axes.get_xlim()
    f, Pxx_den = signal.periodogram(x[np.bitwise_and(t >lim[0] , t <lim[1])], Fs)
    ax2.clear()
    ax2.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

def on_xlims_change2(axes):
    lim = axes.get_xlim()
    f, Pxx_den = signal.periodogram(x[np.bitwise_and(t >lim[0] , t <lim[1])], Fs)
    ax4.clear()
    ax4.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

ax1.callbacks.connect('xlim_changed', on_xlims_change1)
ax3.callbacks.connect('xlim_changed', on_xlims_change2)


plt.show()

我正在寻找的是一种在 ax1ax3x axis 被修改时更新 ax2ax4 的方法.每次修改 ax1ax3x axis 时,我只想在显示的曲线范围内计算 FFT。 所以我几乎完成了这一部分。但是因为 ax1ax3 共享 x 轴。我期待这两个 FFT 图应该更新,但他们没有。

因此,当我放大一个时间轴时,只有最右边的 FFT 会更新,而不是所有时间轴都会更新。 不知道哪里少了什么?

回调仅针对限制实际在外部发生变化的轴触发。您可以只使用一个函数同时更新两个图。

def onlimschange(ax):
    on_xlims_change1(ax)
    on_xlims_change2(ax)

def on_xlims_change1(axes):
    lim = axes.get_xlim()
    f, Pxx_den = signal.periodogram(x[np.bitwise_and(t >lim[0] , t <lim[1])], Fs)
    ax2.clear()
    ax2.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

def on_xlims_change2(axes):
    lim = axes.get_xlim()
    f, Pxx_den = signal.periodogram(x[np.bitwise_and(t >lim[0] , t <lim[1])], Fs)
    ax4.clear()
    ax4.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

ax1.callbacks.connect('xlim_changed', onlimschange)
ax3.callbacks.connect('xlim_changed', onlimschange)

可以共享任意轴的更通用的解决方案可以是引入从 source_axestarget_axes 的映射,并循环遍历所有共享轴以根据映射。

import matplotlib.pyplot as plt
import numpy as np
from scipy import signal

Fs=1024.
t=np.arange(0,10,1/Fs)
F=np.arange(0,10,1/Fs)
x = np.sin(2 * 3.1416 * F *t )

plt.figure()
ax1 = plt.subplot(221)
plt.plot(t,x)
ax2 = plt.subplot(222)
f, Pxx_den = signal.periodogram(x, Fs)
line1, = plt.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

ax3 = plt.subplot(223, sharex=ax1)
plt.plot(t,x)
ax4 = plt.subplot(224)
f, Pxx_den = signal.periodogram(x, Fs)
line1, = plt.plot(f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]] )

def func1(source_axes):
    lim = source_axes.get_xlim()
    f, Pxx_den = signal.periodogram(x[np.bitwise_and(t >lim[0] , t <lim[1])], Fs)
    X,Y = f[:np.where(f>50)[0][0]],Pxx_den[:np.where(f>50)[0][0]]
    return X,Y

mapping = {ax1 : [ax2, func1], ax3 : [ax4, func1]}

def onlimschange(source_axes):
    for source_ax in source_axes.get_shared_x_axes().get_siblings(source_axes):
        target_ax = mapping[source_ax][0]
        X,Y = mapping[source_ax][1](source_axes)
        target_ax.clear()
        target_ax.plot(X,Y)

ax1.callbacks.connect('xlim_changed', onlimschange)
ax3.callbacks.connect('xlim_changed', onlimschange)


plt.show()