| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,18 @@ | |||
| 1 | + ``borderpad`` accepts a tuple for separate x/y padding | ||
| 2 | + ------------------------------------------------------- | ||
| 3 | + | ||
| 4 | + The ``borderpad`` parameter used for placing anchored artists (such as inset axes) now accepts a tuple of ``(x_pad, y_pad)``. | ||
| 5 | + | ||
| 6 | + This allows for specifying separate padding values for the horizontal and | ||
| 7 | + vertical directions, providing finer control over placement. For example, when | ||
| 8 | + placing an inset in a corner, one might want horizontal padding to avoid | ||
| 9 | + overlapping with the main plot's axis labels, but no vertical padding to keep | ||
| 10 | + the inset flush with the plot area edge. | ||
| 11 | + | ||
| 12 | + Example usage with :func:`~mpl_toolkits.axes_grid1.inset_locator.inset_axes`: | ||
| 13 | + | ||
| 14 | + .. code-block:: python | ||
| 15 | + | ||
| 16 | + ax_inset = inset_axes( | ||
| 17 | + ax, width="30%", height="30%", loc='upper left', | ||
| 18 | + borderpad=(4, 0)) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1140,9 +1140,10 @@ def _get_anchored_bbox(self, loc, bbox, parentbbox, renderer): | |||
| 1140 | 1140 | parentbbox : `~matplotlib.transforms.Bbox` | |
| 1141 | 1141 | A parent box which will contain the bbox, in display coordinates. | |
| 1142 | 1142 | """ | |
| 1143 | + pad = self.borderaxespad * renderer.points_to_pixels(self._fontsize) | ||
| 1143 | 1144 | return offsetbox._get_anchored_bbox( | |
| 1144 | 1145 | loc, bbox, parentbbox, | |
| 1145 | - self.borderaxespad * renderer.points_to_pixels(self._fontsize)) | ||
| 1146 | + pad, pad) | ||
| 1146 | 1147 | ||
| 1147 | 1148 | def _find_best_position(self, width, height, renderer): | |
| 1148 | 1149 | """Determine the best location to place the legend.""" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -946,8 +946,13 @@ def __init__(self, loc, *, | |||
| 946 | 946 | See the parameter *loc* of `.Legend` for details. | |
| 947 | 947 | pad : float, default: 0.4 | |
| 948 | 948 | Padding around the child as fraction of the fontsize. | |
| 949 | - borderpad : float, default: 0.5 | ||
| 949 | + borderpad : float or (float, float), default: 0.5 | ||
| 950 | 950 | Padding between the offsetbox frame and the *bbox_to_anchor*. | |
| 951 | + If a float, the same padding is used for both x and y. | ||
| 952 | + If a tuple of two floats, it specifies the (x, y) padding. | ||
| 953 | + | ||
| 954 | + .. versionadded:: 3.11 | ||
| 955 | + The *borderpad* parameter now accepts a tuple of (x, y) paddings. | ||
| 951 | 956 | child : `.OffsetBox` | |
| 952 | 957 | The box that will be anchored. | |
| 953 | 958 | prop : `.FontProperties` | |
@@ -1054,12 +1059,22 @@ def set_bbox_to_anchor(self, bbox, transform=None): | |||
| 1054 | 1059 | @_compat_get_offset | |
| 1055 | 1060 | def get_offset(self, bbox, renderer): | |
| 1056 | 1061 | # docstring inherited | |
| 1057 | - pad = (self.borderpad | ||
| 1058 | - * renderer.points_to_pixels(self.prop.get_size_in_points())) | ||
| 1062 | + fontsize_in_pixels = renderer.points_to_pixels(self.prop.get_size_in_points()) | ||
| 1063 | + try: | ||
| 1064 | + borderpad_x, borderpad_y = self.borderpad | ||
| 1065 | + except TypeError: | ||
| 1066 | + borderpad_x = self.borderpad | ||
| 1067 | + borderpad_y = self.borderpad | ||
| 1068 | + pad_x_pixels = borderpad_x * fontsize_in_pixels | ||
| 1069 | + pad_y_pixels = borderpad_y * fontsize_in_pixels | ||
| 1059 | 1070 | bbox_to_anchor = self.get_bbox_to_anchor() | |
| 1060 | 1071 | x0, y0 = _get_anchored_bbox( | |
| 1061 | - self.loc, Bbox.from_bounds(0, 0, bbox.width, bbox.height), | ||
| 1062 | - bbox_to_anchor, pad) | ||
| 1072 | + self.loc, | ||
| 1073 | + Bbox.from_bounds(0, 0, bbox.width, bbox.height), | ||
| 1074 | + bbox_to_anchor, | ||
| 1075 | + pad_x_pixels, | ||
| 1076 | + pad_y_pixels | ||
| 1077 | + ) | ||
| 1063 | 1078 | return x0 - bbox.x0, y0 - bbox.y0 | |
| 1064 | 1079 | ||
| 1065 | 1080 | def update_frame(self, bbox, fontsize=None): | |
@@ -1084,15 +1099,15 @@ def draw(self, renderer): | |||
| 1084 | 1099 | self.stale = False | |
| 1085 | 1100 | ||
| 1086 | 1101 | ||
| 1087 | - def _get_anchored_bbox(loc, bbox, parentbbox, borderpad): | ||
| 1102 | + def _get_anchored_bbox(loc, bbox, parentbbox, pad_x, pad_y): | ||
| 1088 | 1103 | """ | |
| 1089 | 1104 | Return the (x, y) position of the *bbox* anchored at the *parentbbox* with | |
| 1090 | - the *loc* code with the *borderpad*. | ||
| 1105 | + the *loc* code with the *borderpad* and padding *pad_x*, *pad_y*. | ||
| 1091 | 1106 | """ | |
| 1092 | 1107 | # This is only called internally and *loc* should already have been | |
| 1093 | 1108 | # validated. If 0 (None), we just let ``bbox.anchored`` raise. | |
| 1094 | 1109 | c = [None, "NE", "NW", "SW", "SE", "E", "W", "E", "S", "N", "C"][loc] | |
| 1095 | - container = parentbbox.padded(-borderpad) | ||
| 1110 | + container = parentbbox.padded(-pad_x, -pad_y) | ||
| 1096 | 1111 | return bbox.anchored(c, container=container).p0 | |
| 1097 | 1112 | ||
| 1098 | 1113 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -157,7 +157,7 @@ class AnchoredOffsetbox(OffsetBox): | |||
| 157 | 157 | loc: str, | |
| 158 | 158 | *, | |
| 159 | 159 | pad: float = ..., | |
| 160 | - borderpad: float = ..., | ||
| 160 | + borderpad: float | tuple[float, float] = ..., | ||
| 161 | 161 | child: OffsetBox | None = ..., | |
| 162 | 162 | prop: FontProperties | None = ..., | |
| 163 | 163 | frameon: bool = ..., | |
@@ -185,7 +185,7 @@ class AnchoredText(AnchoredOffsetbox): | |||
| 185 | 185 | loc: str, | |
| 186 | 186 | *, | |
| 187 | 187 | pad: float = ..., | |
| 188 | - borderpad: float = ..., | ||
| 188 | + borderpad: float | tuple[float, float] = ..., | ||
| 189 | 189 | prop: dict[str, Any] | None = ..., | |
| 190 | 190 | **kwargs | |
| 191 | 191 | ) -> None: ... | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -470,3 +470,40 @@ def test_draggable_in_subfigure(): | |||
| 470 | 470 | bbox = ann.get_window_extent() | |
| 471 | 471 | MouseEvent("button_press_event", fig.canvas, bbox.x1+2, bbox.y1+2)._process() | |
| 472 | 472 | assert not ann._draggable.got_artist | |
| 473 | + | ||
| 474 | + | ||
| 475 | + def test_anchored_offsetbox_tuple_and_float_borderpad(): | ||
| 476 | + """ | ||
| 477 | + Test AnchoredOffsetbox correctly handles both float and tuple for borderpad. | ||
| 478 | + """ | ||
| 479 | + | ||
| 480 | + fig, ax = plt.subplots() | ||
| 481 | + | ||
| 482 | + # Case 1: Establish a baseline with float value | ||
| 483 | + text_float = AnchoredText("float", loc='lower left', borderpad=5) | ||
| 484 | + ax.add_artist(text_float) | ||
| 485 | + | ||
| 486 | + # Case 2: Test that a symmetric tuple gives the exact same result. | ||
| 487 | + text_tuple_equal = AnchoredText("tuple", loc='lower left', borderpad=(5, 5)) | ||
| 488 | + ax.add_artist(text_tuple_equal) | ||
| 489 | + | ||
| 490 | + # Case 3: Test that an asymmetric tuple with different values works as expected. | ||
| 491 | + text_tuple_asym = AnchoredText("tuple_asym", loc='lower left', borderpad=(10, 4)) | ||
| 492 | + ax.add_artist(text_tuple_asym) | ||
| 493 | + | ||
| 494 | + # Draw the canvas to calculate final positions | ||
| 495 | + fig.canvas.draw() | ||
| 496 | + | ||
| 497 | + pos_float = text_float.get_window_extent() | ||
| 498 | + pos_tuple_equal = text_tuple_equal.get_window_extent() | ||
| 499 | + pos_tuple_asym = text_tuple_asym.get_window_extent() | ||
| 500 | + | ||
| 501 | + # Assertion 1: Prove that borderpad=5 is identical to borderpad=(5, 5). | ||
| 502 | + assert pos_tuple_equal.x0 == pos_float.x0 | ||
| 503 | + assert pos_tuple_equal.y0 == pos_float.y0 | ||
| 504 | + | ||
| 505 | + # Assertion 2: Prove that the asymmetric padding moved the box | ||
| 506 | + # further from the origin than the baseline in the x-direction and less far | ||
| 507 | + # in the y-direction. | ||
| 508 | + assert pos_tuple_asym.x0 > pos_float.x0 | ||
| 509 | + assert pos_tuple_asym.y0 < pos_float.y0 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -341,11 +341,16 @@ def inset_axes(parent_axes, width, height, loc='upper right', | |||
| 341 | 341 | ||
| 342 | 342 | %(Axes:kwdoc)s | |
| 343 | 343 | ||
| 344 | - borderpad : float, default: 0.5 | ||
| 344 | + borderpad : float or (float, float), default: 0.5 | ||
| 345 | 345 | Padding between inset axes and the bbox_to_anchor. | |
| 346 | + If a float, the same padding is used for both x and y. | ||
| 347 | + If a tuple of two floats, it specifies the (x, y) padding. | ||
| 346 | 348 | The units are axes font size, i.e. for a default font size of 10 points | |
| 347 | 349 | *borderpad = 0.5* is equivalent to a padding of 5 points. | |
| 348 | 350 | ||
| 351 | + .. versionadded:: 3.11 | ||
| 352 | + The *borderpad* parameter now accepts a tuple of (x, y) paddings. | ||
| 353 | + | ||
| 349 | 354 | Returns | |
| 350 | 355 | ------- | |
| 351 | 356 | inset_axes : *axes_class* | |
| Back | FazBrowse Home | New Git URL |
0 commit comments