Skip to content

ENH: Allow tuple for borderpad in AnchoredOffsetbox #30359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Aaratrika-Shelly
Copy link

This PR closes #30331 .

PR summary

This PR enhances AnchoredOffsetbox to allow the borderpad parameter to accept a tuple of (x_pad, y_pad) in addition to a single float value.

  • Why is this change necessary? Currently, borderpad applies the same padding in both x and y directions. This can be inflexible, especially when placing inset axes in a corner. For example, a user may want horizontal padding to avoid overlapping the main plot's y-axis labels, but no vertical padding in order to keep the inset flush with the top of the plot area.

  • What problem does it solve? It gives users finer control over the positioning of anchored elements, allowing for separate horizontal and vertical padding.

  • What is the reasoning for this implementation?

    • The implementation modifies AnchoredOffsetbox.get_offset.
    • It checks if self.borderpad is a tuple and calculates separate pad_x_pixels and pad_y_pixels.
    • These values are then used to create a manually padded anchor box, which is a robust approach that does not require changing downstream helper functions.
    • The implementation is fully backward-compatible, treating single float values as before.

A new unit test has been added to verify this functionality, and the docstring for AnchoredOffsetbox has been updated to reflect the new API.

PR checklist

@Aaratrika-Shelly Aaratrika-Shelly force-pushed the feature/tuple-borderpad branch 3 times, most recently from 98cfadf to 8df4614 Compare July 26, 2025 07:24
Copy link
Member

@rcomer rcomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Aaratrika-Shelly, nice work! I have confirmed this solves the inset_axes issue:

import matplotlib.pyplot as plt

from mpl_toolkits.axes_grid1.inset_locator import inset_axes

fig, ax = plt.subplots()

axins = inset_axes(ax, width="30%", height=1., loc="upper left", borderpad=(3, 0))

plt.show()
Image

Please could you update the inset_axes docstring to match what you have done here? This should also get a what's new entry and "added" directive.

@rcomer rcomer changed the title ENH: Allow tupple for borderpad in AnchoredOffsetbox ENH: Allow tuple for borderpad in AnchoredOffsetbox Jul 26, 2025
@melissawm melissawm moved this to Waiting for author in First Time Contributors Jul 26, 2025
@Aaratrika-Shelly Aaratrika-Shelly force-pushed the feature/tuple-borderpad branch from 8df4614 to c84ef64 Compare July 26, 2025 21:46
@Aaratrika-Shelly
Copy link
Author

All the suggested changes have been made. Thanks for the suggestions.

Copy link
Member

@rcomer rcomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Aaratrika-Shelly, this will still need a new entry in https://github.com/matplotlib/matplotlib/tree/main/doc/users/next_whats_new

Also I just remembered that the type annotation will need updating in offsetbox.pyi. We do not yet have typing stubs for anything under toolkits so there is nothing to do for type annotations for inset_axes.

ax.add_artist(text_tuple_equal)

# Case 3: Test that an asymmetric tuple with larger values works as expected.
text_tuple_asym = AnchoredText("tuple_asym", loc='lower left', borderpad=(10, 15))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest making one of these less than 5. At the moment the below assertions would pass even if only one element of the tuple mistakenly got used for both x and y.

@@ -1053,13 +1055,22 @@ def set_bbox_to_anchor(self, bbox, transform=None):

@_compat_get_offset
def get_offset(self, bbox, renderer):
# docstring inherited
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring for this method is still inherited from the parent class, so this comment should not be removed.

fontsize_in_pixels = renderer.points_to_pixels(self.prop.get_size_in_points())
try:
borderpad_x, borderpad_y = self.borderpad
except (TypeError):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
except (TypeError):
except TypeError:

Brackets are not needed if we only catch one exception.

Comment on lines 1098 to 1108
def _get_anchored_bbox(loc, bbox, parentbbox, pad_x,pad_y=None):
"""
Return the (x, y) position of the *bbox* anchored at the *parentbbox* with
the *loc* code with the *borderpad*.
"""
# This is only called internally and *loc* should already have been
# validated. If 0 (None), we just let ``bbox.anchored`` raise.
c = [None, "NE", "NW", "SW", "SE", "E", "W", "E", "S", "N", "C"][loc]
container = parentbbox.padded(-borderpad)
if pad_y is None:
pad_y=pad_x
container = parentbbox.padded(-pad_x,-pad_y)
Copy link
Member

@rcomer rcomer Jul 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def _get_anchored_bbox(loc, bbox, parentbbox, pad_x,pad_y=None):
"""
Return the (x, y) position of the *bbox* anchored at the *parentbbox* with
the *loc* code with the *borderpad*.
"""
# This is only called internally and *loc* should already have been
# validated. If 0 (None), we just let ``bbox.anchored`` raise.
c = [None, "NE", "NW", "SW", "SE", "E", "W", "E", "S", "N", "C"][loc]
container = parentbbox.padded(-borderpad)
if pad_y is None:
pad_y=pad_x
container = parentbbox.padded(-pad_x,-pad_y)
def _get_anchored_bbox(loc, bbox, parentbbox, pad_x, pad_y=None):
"""
Return the (x, y) position of the *bbox* anchored at the *parentbbox* with
the *loc* code with the *borderpad*.
"""
# This is only called internally and *loc* should already have been
# validated. If 0 (None), we just let ``bbox.anchored`` raise.
c = [None, "NE", "NW", "SW", "SE", "E", "W", "E", "S", "N", "C"][loc]
if pad_y is None:
pad_y = pad_x
container = parentbbox.padded(-pad_x, -pad_y)

Spaces after commas and around the equals sign. The linter should have picked these up - I'm not sure why it didn't.

Comment on lines 259 to 260
versionchanged:: 3.11
The *borderpad* parameter now accepts a tuple of (x, y) paddings.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be versionadded because you are introducing a new option but the old option still works. Also it should go under the parameter description. For a similar example see

.. versionadded:: 3.9
Support for list input

@Aaratrika-Shelly Aaratrika-Shelly force-pushed the feature/tuple-borderpad branch from c84ef64 to 2b60116 Compare July 27, 2025 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Waiting for author
Development

Successfully merging this pull request may close these issues.

[ENH]: inset_axes has borderpadding, but not x/y individually.
2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy