matplotlib光标下的值

34

我正在使用 matplotlib.imshow 来获取一个二维数组的交互式显示。鼠标下的x/y坐标会显示在窗口左下角。是否有可能同时获取鼠标下的数组值呢?


在一个使用imshow的matplotlib图形窗口中,如何删除、隐藏或重新定义?可能是重复问题。 - tacaswell
与Matplotlib坐标格式相关内容,请参考此链接:https://dev59.com/Om3Xa4cB1Zd3GeqPk_-o#14666889 - tacaswell
我担心这可能是一个重复的(三倍,四倍...)但搜索了一下,没有找到... - ajwood
不用担心,这只是为将来增加更多的 Google 标记。 - tacaswell
2个回答

25
你只需要重新分配ax.format_coord。请参阅文档中的此示例
(代码直接从示例中提取)
"""
Show how to modify the coordinate formatter to report the image "z"
value of the nearest pixel given x and y
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

X = 10*np.random.rand(5,3)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.imshow(X, cmap=cm.jet, interpolation='nearest')

numrows, numcols = X.shape
def format_coord(x, y):
    col = int(x+0.5)
    row = int(y+0.5)
    if col>=0 and col<numcols and row>=0 and row<numrows:
        z = X[row,col]
        return 'x=%1.4f, y=%1.4f, z=%1.4f'%(x, y, z)
    else:
        return 'x=%1.4f, y=%1.4f'%(x, y)

ax.format_coord = format_coord
plt.show()

7
我需要一个可以重复使用的东西,所以我通过一个类把解决方案封装起来:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import numpy as np
class imshow_show_z:

    def __init__(self, ax, z, x, y):
        self.ax = ax
        self.x  = x
        self.y  = y
        self.z  = z
        self.dx = self.x[1] - self.x[0]
        self.dy = self.y[1] - self.y[0]
        self.numrows, self.numcols = self.z.shape
        self.ax.format_coord = self.format_coord
    def format_coord(self, x, y):
        col = int(x/self.dx+0.5)
        row = int(y/self.dy+0.5)
        #print "Nx, Nf = ", len(self.x), len(self.y), "    x, y =", x, y, "    dx, dy =", self.dx, self.dy, "    col, row =", col, row
        xyz_str = ''
        if ((col>=0) and (col<self.numcols) and (row>=0) and (row<self.numrows)):
            zij = self.z[row,col]
            #print "zij =", zij, '  |zij| =', abs(zij)
            if (np.iscomplex(zij)):
                amp = abs(zij)
                phs = np.angle(zij) / np.pi
                if (zij.imag >= 0.0):
                    signz = '+'
                else:
                    signz = '-'
                xyz_str = 'x=' + str('%.4g' % x) + ', y=' + str('%.4g' % y) + ',' \
                            + ' z=(' + str('%.4g' % zij.real) + signz + str('%.4g' % abs(zij.imag)) + 'j)' \
                            + '=' + str('%.4g' % amp) + r'*exp{' + str('%.4g' % phs) + u' π j})'
            else:
                xyz_str = 'x=' + str('%.4g' % x) + ', y=' + str('%.4g' % y) + ', z=' + str('%.4g' % zij)
        else:
            xyz_str = 'x=%1.4f, y=%1.4f'%(x, y)
        return xyz_str

def new_imshow(ax, x, y, z, *args, **kwargs):
    assert(len(x) == z.shape[1])
    assert(len(y) == z.shape[0])
    dx = x[1] - x[0]
    dy = y[1] - y[0]
    if (np.iscomplex(z).any()):
        zabs = abs(z)
    else:
        zabs = z
    # Use this to center pixel around (x,y) values
    extent = (x[0]-dx/2.0, x[-1]+dx/2.0, y[0]-dy/2.0, y[-1]+dy/2.0)
    # Use this to let (x,y) be the lower-left pixel location (upper-left when origin = 'lower' is not used)
    #extent = (x[0]-dx/2.0, x[-1]+dx/2.0, y[0]-dy/2.0, y[-1]+dy/2.0)
    im = ax.imshow(zabs, extent = extent, *args, **kwargs)
    imshow_show_z(ax, z, x, y)
    ax.set_xlim((x[0], x[-1]))
    ax.set_ylim((y[0], y[-1]))
    return im

示例用法:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-5, 10, 100)
y = np.linspace(-2.0, 5, 51)
xx, yy = np.meshgrid(x, y)
Z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
im = new_imshow(ax, x, y, Z, aspect = 'auto', origin = 'lower', interpolation = 'nearest')
ax.set_xlabel('x')
ax.set_ylabel('y')

plt.show()

功能:

  • 可以显示浮点数和复数值。对于复数,显示实部+虚部和极坐标形式。
  • 会根据 xy 数组设置范围。请注意,如果使用 extent 关键字,则 matplotlib 示例将不起作用。
  • 像素以它们的 (x,y) 位置为中心而不是 (x,y) 作为下(或上)左位置。

再次阅读此内容,发现使用该类有点滑稽,因为您没有保留对它的引用,而是依赖于 format_coord 引用来保持对象的活动状态。您可以通过直接执行闭包来完全实现相同的功能。 - tacaswell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接