I'm using matplotlib.imshow
to get an interactive display of a 2D array. The x/y coordinate under the cursor is displayed at the bottom left of the window. Is it possible to also get the value of the array under the cursor as well?
You simply need to re-assign ax.format_coord
. See this example from the documentation.
(code lifted directly from example)
"""
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()
I needed something I could re-use, so I encapsulated the solution through a class:
#!/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
Example usage:
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()
Features:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With