cursor tracking using matplotlib and twinx
matplotlib, python
Solution
Due to the way that the call backs work, the event always returns in the top axes. You just need a bit of logic to check which if the event happens in the axes we want:
class Cursor(object):
def __init__(self, ax, x, y, name):
self.ax = ax
self.name = name
plt.connect('motion_notify_event', self)
def __call__(self, event):
if event.inaxes is None:
return
ax = self.ax
if ax != event.inaxes:
inv = ax.transData.inverted()
x, y = inv.transform(np.array((event.x, event.y)).reshape(1, 2)).ravel()
elif ax == event.inaxes:
x, y = event.xdata, event.ydata
else:
return
logger.debug('{n}: ({x:0.2f}, {y:0.2f})'.format(n=self.name,x=x,y=y))
This might be a subtle bug down in the transform stack (or this is the correct usage and it was by luck it worked with tuples before), but at any rate, this will make it work. The issue is that the code at line 1996 in `transform.py` expects to get a 2D `ndarray` back, but the identity transform just returns the tuple that get handed into it, which is what generates the errors.
Problem
I would like to track the coordinates of the mouse with respect to data coordinates on two axes simultaneously. I can track the mouse position with respect to one axis just fine. The problem is: when I add a second axis with `twinx()`, both `Cursors` report data coordinates with respect to the second axis only. For example, my Cursors (`fern` and `muffy`) report the `y`-value is 7.93 ``` Fern: (1597.63, 7.93) Muffy: (1597.63, 7.93) ``` If I use: ``` inv = ax.transData.inverted() x, y = inv.transform((event.x, event.y)) ``` I get an IndexError. So the question is: How can I modify the code to track the data coordinates with respect to both axes? ``` import numpy as np import matplotlib.pyplot as plt import logging logger = logging.getLogger(__name__) class Cursor(object): def __init__(self, ax, name): self.ax = ax self.name = name plt.connect('motion_notify_event', self) def __call__(self, event): x, y = event.xdata, event.ydata ax = self.ax # inv = ax.transData.inverted() # x, y = inv.transform((event.x, event.y)) logger.debug('{n}: ({x:0.2f}, {y:0.2f})'.format(n=self.name,x=x,y=y)) logging.basicConfig(level=logging.DEBUG, format='%(message)s',) fig, ax = plt.subplots() x = np.linspace(1000, 2000, 500) y = 100*np.sin(20*np.pi*(x-1500)/2000.0) fern = Cursor(ax, 'Fern') ax.plot(x,y) ax2 = ax.twinx() z = x/200.0 muffy = Cursor(ax2, 'Muffy') ax2.semilogy(x,z) plt.show() ```