This is one of the most confusing parts for getting exact pixel values ​​from matplotlib. Matplotlib separates the renderer, which processes the exact pixel values ​​from the canvas onto which the shape and axes are drawn.
In principle, the visualization tool that exists when the drawing is initially created (but not yet displayed) does not necessarily coincide with the visualizer that is used to display the shape or save it to a file.
What you do is correct, but it uses the original renderer, not the one used to save the shape.
To illustrate this, here is a slightly simplified version of your code:
import numpy as np import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) im = ax.imshow(np.random.random((27,27)), interpolation='nearest') for i in range(28): x, y = ax.transData.transform_point([i,i]) print '%i, %i' % (x, fig.bbox.height - y) fig.savefig('foo.png', dpi=fig.dpi)
This gives similar results to what you have above: (the differences are related to the different rendering mechanisms between your machine and mine)
89, 55 107, 69 125, 83 ... 548, 410 566, 424 585, 439
However, if we do the same, but instead draw a shape before displaying the coordinates, we get the right answer!
import numpy as np import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) im = ax.imshow(np.random.random((27,27)), interpolation='nearest') fig.canvas.draw() for i in range(28): x, y = ax.transData.transform_point([i,i]) print '%i, %i' % (x, fig.bbox.height - y) fig.savefig('foo.png', dpi=fig.dpi)
This yields: (Keep in mind that the edge of the figure is located at <-0.5, -0.5> in the data coordinates, and not <0, 0> . (I.e. the coordinates for the graphic image are in pixel orientation). That is why <0, 0> gives 143, 55 , not 135, 48 )
143, 55 157, 69 171, 83 ... 498, 410 512, 424 527, 439
Of course, drawing a figure just to repeat it while saving it is redundant and computationally expensive.
To avoid drawing twice, you can connect the callback function to the draw event and display your HTML image map inside this function. As a short example:
import numpy as np import matplotlib.pyplot as plt def print_pixel_coords(event): fig = event.canvas.figure ax = fig.axes[0]
This gives the correct result, but only draws the picture once when it is saved:
143, 55 157, 69 171, 83 ... 498, 410 512, 424 527, 439
Another advantage is that you can use any tag in the fig.savefig call without having to manually set the fig tag manually. Therefore, when using the callback function, you can simply execute fig.savefig('foo.png') , (or fig.savefig('foo.png', dpi=whatever) ), and you will get the result corresponding to the saved .png file. (The default value when saving a digit is 100, while the default value for an object with numbers is 80, so you had to specify that the dpi would be the same as fig.dpi )
Hope to be at least somewhat clear!