I am trying to retrieve the bbox of an AnchoredOffsetBox in Matplotlib before the canvas itself is rendered. The reason is mostly unimportant, but essentially I want to do this so that I can understand the coordinates the OffsetBox would (hypothetically) exist in, so that I can then change it if it were to meet certain conditions.
For a generic artist, I know I can do the following:
# Create the plot
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=300)
# Create a generic triangle artist at the midpoint of the axis
triangle = ax.add_artist(matplotlib.patches.RegularPolygon((0.5,0.5), 3, radius=0.2))
# Retrieve the bbox of the triangle in data coordinates
ax.transData.inverted().transform(triangle.get_window_extent())
And this same code works if I place the artist in an AnchoredOffsetBox as well, which is useful for more generic positioning code:
# Create the plot
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=300)
# Create a generic triangle artist
triangle = matplotlib.patches.RegularPolygon((0.5,0.5), 3, radius=0.2)
# Create an offsetbox in data coordinates
offsetbox = matplotlib.offsetbox.AuxTransformBox(ax.transData)
# Place the triangle in the offsetbox
offsetbox.add_artist(triangle)
# Place the offsetbox in the AnchoredOffsetBox
container = matplotlib.offsetbox.AnchoredOffsetbox(loc="center", pad=0, child=offsetbox)
# Add the AnchoredOffsetBox to the figure
ax.add_artist(container)
# Retrieve the bbox of the AnchoredOffsetBox in data coordinates
ax.transData.inverted().transform(container.get_window_extent())
(Note: I’m not sure why the triangle rendered with the above code is slightly “lower” than in the first code block, but I’m ignoring this for now)
However, I need to get the position of the AnchoredOffsetBox before it is rendered, so that I can modify its position if necessary. I’ve tried to accomplish it like so:
### SAME AS ABOVE ###
# Create the plot
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(5,5), dpi=300)
# Create a generic triangle artist
triangle = matplotlib.patches.RegularPolygon((0.5,0.5), 3, radius=0.2)
# Create an offsetbox in data coordinates
offsetbox = matplotlib.offsetbox.AuxTransformBox(ax.transData)
# Place the triangle in the offsetbox
offsetbox.add_artist(triangle)
# Place the offsetbox in the AnchoredOffsetBox
container = matplotlib.offsetbox.AnchoredOffsetbox(loc="center", pad=0, child=offsetbox)
### NEW CODE ###
# Set the figure for the container
container.set_figure(fig)
# Retrieve the renderer for the figure
renderer = fig._get_renderer()
# Retrieve the bbox of the AnchoredOffsetBox in data coordinates
ax.transData.inverted().transform(container.get_bbox(renderer))
Unfortunately, doing this gets me nonsensical results: the data coordinates returned are negative, and I can’t make heads nor tails as to why. My hunch is that get_bbox()
does not return the same information as get_window_extent()
, but calling get_window_extent()
returns AttributeError: 'NoneType' object has no attribute 'bbox'
.
If this is an exercise in futility it would be great to know. I am open to any other suggestions as to how I can accomplish a similar feat as well: for some reason I’ve decided it is too difficult to e.g. update the rotation of the artist after it has been added to the axis, but I’ve been working on this problem so long I can’t remember why.