2

I'm using .imshow() to show a 2D array from Z(X, Y), and I would like the axes to reflect the original x and y values used for the function, instead of the array indices.

But I would like Matplotlib to use it's tick marking algorithm to places ticks at "nice" numbers. Below I show what those might look like.

One way to do this would be to "extract" the tick mars from the two 1D plots and "implant" them on the imshow, but I don't know how to do that.

I've tried some searching but I can't even think of good matplotlib search terms to describe what I need.

enter image description here

def Z(X, Y):
    Rsq  = X**2 + Y**2 - 0.025*X**4
    return np.exp(-0.2*Rsq)*np.cos(2.*Rsq)

import numpy as np
import matplotlib.pyplot as plt

halfpi, pi, threehalfpi, twopi = [f*np.pi for f in (0.5, 1, 1.5, 2)]

x = np.linspace(-twopi,       pi, 450)
y = np.linspace(-threehalfpi, pi, 350)

X, Y = np.meshgrid(x, y, indexing='xy')
z1   = Z(X, Y)
z2   = Z(x, 0)
z3   = Z(0, y)

fig  = plt.figure()

ax1   = fig.add_subplot(2, 2, 2)
ax1.imshow(z1, origin='lower')
ax1.xaxis.tick_top()
ax1.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)

ax2   = fig.add_subplot(2, 2, 4)
ax2.plot(x, z2)
ax2.set_xlim(x.min(), x.max())
ax2.xaxis.tick_top()
ax2.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)


ax3   = fig.add_subplot(2, 2, 1)
ax3.plot(z3, y)
ax3.set_ylim(y.min(), y.max())
ax3.yaxis.tick_right()
plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()

print 'x: ', x.min(), x.max()
print 'y: ', y.min(), y.max()
uhoh
  • 3,713
  • 6
  • 42
  • 95
  • The key is to use the `extent` of the image. I marked as duplicate of a general solution. If you have problems applying this, you could redact your question. (Mind that you need to decide whether pixel coordinates are at the edge or the center.) – ImportanceOfBeingErnest Dec 06 '18 at 11:59
  • Here is a solution written out: https://stackoverflow.com/a/44260928/3904031 – uhoh Dec 06 '18 at 13:11
  • 1
    FYI, with the `extent` you can set both transformation for both axes. If you just want to transform one axis, you can also use a custom tick-formatting via `plt.FuncFormatter` to handle the transformation as described here: https://jakevdp.github.io/PythonDataScienceHandbook/04.10-customizing-ticks.html#Fancy-Tick-Formats (Most people would probably consider this a hack, though) – STiFU Sep 27 '22 at 09:09

1 Answers1

1

You can set the ticklabels:

delta_x = x[1] - x[0] # get the spacing of your data points
xticks = ax.get_xticks()
ax.set_xticklabels(xticks * delta_x)

and the same for y.

F. Win
  • 390
  • 5
  • 17
  • Unfortunately that doesn't let Matpoltolib use it's "skills" to choose reasonable locations like for example y: [-5, -3, -1, 1, 3], x: [4, 2, 0, 2] . Instead, I get this: https://i.stack.imgur.com/b1t71.png I need something that goes a little deeper. – uhoh Dec 06 '18 at 08:31
  • Thanks for your help, just fyi a solution has been found. yay! – uhoh Dec 06 '18 at 13:12