matplotlibのグラフ上にマウスカーソルに合わせて動く十字のカーソルを表示するMultiCursorというものがありますが、 twinx()してY2軸を利用すると奇妙なことがおこりました。
カーソルは、Y軸に描画されながらも、その表示位置はY2軸上の値になるという状態です。
もちろん、カーソルを描画する対象をY2軸のほうにすると矛盾のない状態にはなります。
そもそもMultiCursorを利用する対象にY2軸を追加するような利用の仕方は、あまりなさそうです。そうはいっても、そのような要求があったため、Y2軸を追加しても、カーソル位置は、Y軸のほうで決まるようにしてみました。
マウス移動のイベントを処理するonmove()に渡されるeventからキャンバス上のx,y座標が得られるので、それを利用してグラフ軸上のデータに焼きなおすようにしました。
使い方はオリジナルのMultiCursorとほぼ同じですが、parentウィンドウを渡すようにして、そちらへ座標を通知するイベントをポストしています。parentウィンドウでそのイベントを拾えば、カーソル移動にあわせて座標位置を表示できます。
from matplotlib.widgets import MultiCursor import wx import wx.lib.newevent class MyMultiCursor(MultiCursor): def __init__(self, parent, canvas, axes, color='r', lw=1, useblit = True, horizOn=True, vertOn=True): if matplotlib.__version__ >= '1.3.0': MultiCursor.__init__(self, canvas, axes, color=color, lw=lw, useblit=useblit, horizOn=horizOn, vertOn=vertOn) else: MultiCursor.__init__(self, canvas, axes, color=color, lw=lw, useblit=useblit) # Produce New Event for Cursor Move Notification to parent window. self.parent = parent self.CursorMoveEvent, self.EVT_CURSOR_MOVE = wx.lib.newevent.NewEvent() self.visible = False def xydata(self, x, y): #make new xdata, ydata cwidth, cheight = self.canvas.GetSize() target = None for ax in self.axes: #find the axes in which the mouse cursor is. bbox = ax.get_position() [[left,bottom], [right, top]] = bbox.get_points() xc = (x+1)/float(cwidth) yc = y/float(cheight) if ((left < xc) and (xc < right) and (bottom < yc) and (yc < top)): target = ax break if not target: # if there is no target return (None, None) width = right-left height =top-bottom xmin, xmax = ax.get_xlim() ymin, ymax = ax.get_ylim() xdata = xmin + (xc - left) * (xmax - xmin)/width ydata = ymin + (yc - bottom) * (ymax - ymin)/height return (xdata, ydata) def onmove(self, event): event.xdata, event.ydata = self.xydata(event.x, event.y) MultiCursor.onmove(self, event) #make event data evt = self.CursorMoveEvent(pos = (event.xdata, event.ydata)) #post event to parent window wx.PostEvent(self.parent, evt) self.visible = True
0 件のコメント:
コメントを投稿