matplotlibのMultiCursor()の使い方は、
公式のページにありますが、matplotlib 1.3.0あたりからクロスラインカーソルも利用できます。
multi = MultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1, horizOn=True)
のように、horizOnキーワード引数にTrueを渡すと水平線を描画します。
ここで、クロスラインカーソルを表示したいaxes、(ax1, ax2)を渡しているのですが、
最後のax2でないaxes、ここではax1の軸がオートスケールになっていると、あれっ?
と思う挙動をします。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import MultiCursor
t = np.arange(0.0, 2.0, 0.01)
s1 = np.sin(2*np.pi*t)+400
s2 = np.sin(4*np.pi*t)
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(t, s1)
ax2 = fig.add_subplot(212, sharex=ax1)
ax2.plot(t, s2)
multi = MultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1, horizOn=True)
plt.show()
ax1に描画する波形を400だけオフセットしただけですが、実行すると、以下のようになります。
y軸のレンジが0からになってしまいます。
オートスケールで期待する結果とは異なります。
matplotlibパッケージのwidgets.pyにある、MultiCursorのクラスを見てみると、
どうやら、カーソル線の初期位置の計算に、渡したaxesの最後のものだけを使っているために
生じるようです。
これをwidgets.pyをいじらずに回避するには、MultiCursorの__init__()で行なわれる
カーソル線の生成を、別に行えばよさそうです。
そこで、MultiCursorの__init__()には、vertOn、 horizOnともにFalseを渡します。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import MultiCursor
class MyMultiCursor(MultiCursor):
def __init__(self, canvas, axes,
useblit=True, horizOn=True, vertOn=True, **lineprops):
MultiCursor.__init__(self, canvas, axes,
useblit=useblit, horizOn=False, vertOn=False, **lineprops)
xmids = [0.5 * (xmin + xmax) for xmin, xmax in [ax.get_xlim() for ax in axes]]
ymids = [0.5 * (ymin + ymax) for ymin, ymax in [ax.get_ylim() for ax in axes]]
if self.useblit:
lineprops['animated'] = True
if vertOn:
self.vlines = [ax.axvline(xmids[i], visible=False, **lineprops)
for i, ax in enumerate(axes)]
else:
self.vlines = []
if horizOn:
self.hlines = [ax.axhline(ymids[i], visible=False, **lineprops)
for i, ax in enumerate(axes)]
else:
self.hlines = []
self.vertOn, self.horizOn = vertOn, horizOn
t = np.arange(0.0, 2.0, 0.01)
s1 = np.sin(2*np.pi*t)+400
s2 = np.sin(4*np.pi*t)
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(t, s1)
ax2 = fig.add_subplot(212, sharex=ax1)
ax2.plot(t, s2)
multi = MyMultiCursor(fig.canvas, (ax1, ax2), color='r', lw=1, horizOn=True)
plt.show()
MultiCursorを継承したMyMultiCursorを利用します。
実行すると、以下のように期待されたグラフが得られました。