Home > Enterprise >  Getting the points of a matplotlib Rectangle in axes coordinate system?
Getting the points of a matplotlib Rectangle in axes coordinate system?

Time:09-22

I would like to obtain the coordinates of the points of a matplotlib.patches.Rectangle in the "axes" coordinate system, which in matplotlib plot

Roughly, I'd expect lower left point of rect2 in axes coordinates to be at xy (0.1, 0.2), and the upper right point of rect2 to be at (0.5, 0.6).

However, I don't understand how I can obtain those coordinates; I have tried several things in the code above, and the printout is:

rect2.get_extents()=Bbox([[5040.0, 3748.7999999999997], [24880.0, 11140.8]])
rect2.get_path().vertices=array([[0., 0.],
       [1., 0.],
       [1., 1.],
       [0., 1.],
       [0., 0.]])
rdatapoints=array([[10., 10.],
       [50., 10.],
       [50., 30.],
       [10., 30.],
       [10., 10.]])
ax.transLimits.transform(rdatapoints)=array([[10., 10.],
       [50., 10.],
       [50., 30.],
       [10., 30.],
       [10., 10.]])

So,

  • rect2.get_extents() produces numbers that are waaaaaaay out of either the data or axes coordinates for that item on the plot;
  • rect2.get_path() apparently keeps it vertices as just straight 0 and 1
  • I can get the coordinates in "data" coordinate system in rdatapoints - but trying to transform them with transLimits results in ... exactly the same numbers?!

I really don't understand what is going on here ...

So, how can I get the points of the rect2 Rectangle on the plot in the "axes" coordinate system of the plot?

CodePudding user response:

I would recommend reading chapter 2 from the Nicolas Rougier's book on this, if you're interested in understanding the coordinate systems, it already provides example of exactly what you want. You can get the pdf at:
https://github.com/rougier/scientific-visualization-book#read-the-book

In this case you can use ax.transData to transform your data coordinates (from rect2.get_bbox()) to Figure coordinates. And subsequently transform those with the inverted ax.transAxes to convert from Figure to Axes coordinates. That last step corrects for the position of the axes in the figure (there's usually some buffer/padding).

So given your example, starting with the bounding box of rect2, which is in data coordinates:

bbox = rect2.get_bbox()
# Bbox([[10.0, 10.0], [50.0, 30.0]])

You can define the transformation with:

data_to_figure = ax.transData.transform
data_to_axes = lambda x: ax.transAxes.inverted().transform(data_to_figure(x))

Then transforming the bbox from data coordinates to axes coordinates:

data_to_axes(bbox)

Results in:

array([[0.13636364, 0.22727273],
       [0.5       , 0.59090909]])

Note that Matplotlib automatically adds some padding to the x- and y limits of the axes, based on the data plotted. So when explicitly setting the axes limits equal to your data, the rectangle coordinates (in axes coordinates) match your intuition:

# add
ax.set_xlim(0, 100)
ax.set_ylim(0, 50)

data_to_axes(bbox)

Results in:

array([[0.1, 0.2],
       [0.5, 0.6]])

This is more or less identical to what's explained on page 21 & 22 in the above mentioned book.

  • Related