使用matplotlib和twinx进行光标跟踪

2024-09-27 21:30:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我想同时跟踪鼠标在两个轴上相对于数据坐标的坐标。我可以跟踪鼠标相对于一个轴的位置。问题是:当我使用twinx()添加第二个轴时,Cursors都只与第二个轴有关的报告数据坐标。在

例如,我的光标(fernmuffy)报告y-值为7.93

Fern: (1597.63, 7.93)
Muffy: (1597.63, 7.93)

如果我使用:

^{pr2}$

我有一个索引器。在

所以问题是:如何修改代码来跟踪关于两个轴的数据坐标?在


enter image description here

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()

Tags: 数据nameimportselfeventlogging报告np
2条回答

由于回调的工作方式,事件总是在顶部轴返回。您只需要一点逻辑来检查如果事件发生在我们想要的轴上:

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))

这可能是转换堆栈中的一个细微的错误(或者这是正确的用法,幸运的是它以前曾使用过元组),但无论如何,这将使它正常工作。问题是transform.py中第1996行的代码期望返回一个2Dndarray,但是身份转换只返回交给它的元组,这就是产生错误的原因。在

可以使用一个光标(或事件处理程序)跟踪两个轴的坐标,方法如下:

import numpy as np
import matplotlib.pyplot as plt
import logging
logger = logging.getLogger(__name__)

class Cursor(object):
    def __init__(self):
        plt.connect('motion_notify_event', self)

    def __call__(self, event):
        if event.inaxes is None:
            return
        x, y1 = ax1.transData.inverted().transform((event.x,event.y))
        x, y2 = ax2.transData.inverted().transform((event.x,event.y))
        logger.debug('(x,y1,y2)=({x:0.2f}, {y1:0.2f}, {y2:0.2f})'.format(x=x,y1=y1,y2=y2))

logging.basicConfig(level=logging.DEBUG,
                    format='%(message)s',)
fig, ax1 = plt.subplots()

x = np.linspace(1000, 2000, 500)
y = 100*np.sin(20*np.pi*(x-1500)/2000.0)
fern = Cursor()
ax1.plot(x,y)
ax2 = ax1.twinx()
z = x/200.0
ax2.plot(x,z)
plt.show()

(当我使用ax2.semilogy(x,z)时,我得到了“太多索引”,但是没有解决这个问题。)

ax1.transData.inverted().transform((event.x,event.y))代码在指定的轴上执行从显示坐标到数据坐标的转换,并且可以任意与任一轴一起使用。在

相关问题 更多 >

    热门问题