Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: personalize imshow axis

I have the results of a (H,ranges) = numpy.histogram2d() computation and I'm trying to plot it.

Given H I can easily put it into plt.imshow(H) to get the corresponding image. (see http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.imshow )

My problem is that the axis of the produced image are the "cell counting" of H and are completely unrelated to the values of ranges.

I know I can use the keyword extent (as pointed in: Change values on matplotlib imshow() graph axis ). But this solution does not work for me: my values on range are not growing linearly (actually they are going exponentially)

My question is: How can I put the value of range in plt.imshow()? Or at least, or can I manually set the label values of the plt.imshow resulting object?

Editing the extent is not a good solution.

like image 234
Antonio Ragagnin Avatar asked Nov 30 '15 16:11

Antonio Ragagnin


2 Answers

You can just change the tick labels to something more appropriate for your data.

For example, here we'll set every 5th pixel to an exponential function:

import numpy as np
import matplotlib.pyplot as plt

im = np.random.rand(21,21)

fig,(ax1,ax2) = plt.subplots(1,2)

ax1.imshow(im)
ax2.imshow(im)

# Where we want the ticks, in pixel locations
ticks = np.linspace(0,20,5)
# What those pixel locations correspond to in data coordinates.
# Also set the float format here
ticklabels = ["{:6.2f}".format(i) for i in np.exp(ticks/5)]

ax2.set_xticks(ticks)
ax2.set_xticklabels(ticklabels)
ax2.set_yticks(ticks)
ax2.set_yticklabels(ticklabels)

plt.show()

enter image description here

like image 107
tmdavison Avatar answered Oct 21 '22 17:10

tmdavison


Expanding a bit on @thomas answer

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mi

im = np.random.rand(20, 20)

ticks = np.exp(np.linspace(0, 10, 20))

fig, ax = plt.subplots()

ax.pcolor(ticks, ticks, im, cmap='viridis')
ax.set_yscale('log')
ax.set_xscale('log')

ax.set_xlim([1, np.exp(10)])
ax.set_ylim([1, np.exp(10)])

example result

By letting mpl take care of the non-linear mapping you can now accurately over-plot other artists. There is a performance hit for this (as pcolor is more expensive to draw than AxesImage), but getting accurate ticks is worth it.

like image 41
tacaswell Avatar answered Oct 21 '22 15:10

tacaswell