使用 matplotlib 和 twinx 进行光标跟踪

unu*_*tbu 5 python matplotlib

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)
Run Code Online (Sandbox Code Playgroud)

If I use:

    inv = ax.transData.inverted()
    x, y = inv.transform((event.x, event.y))
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

tac*_*ell 5

由于回调的工作方式,事件始终在顶部轴中返回。您只需要一些逻辑来检查事件是否发生在我们想要的轴中:

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))
Run Code Online (Sandbox Code Playgroud)

这可能是转换堆栈中的一个微妙的错误(或者这是正确的用法,并且幸运的是它之前与元组一起工作过),但无论如何,这将使它工作。问题在于,第 1996 行的代码transform.py期望返回 2D ndarray,但恒等变换仅返回传递给它的元组,这就是生成错误的原因。