Skip to content

Commit ed79353

Browse files
authored
Merge pull request #16615 from anntzer/boxstyles
Update custom boxstyles example.
2 parents a6bd231 + 8db6d05 commit ed79353

File tree

3 files changed

+114
-117
lines changed

3 files changed

+114
-117
lines changed
+114-27
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,142 @@
1-
"""
1+
r"""
22
=================
3-
Custom Boxstyle01
3+
Custom box styles
44
=================
55
6+
This example demonstrates the implementation of a custom `.BoxStyle`.
7+
Custom `.ConnectionStyle`\s and `.ArrowStyle`\s can be similarly defined.
68
"""
9+
10+
from matplotlib.patches import BoxStyle
711
from matplotlib.path import Path
12+
import matplotlib.pyplot as plt
13+
14+
15+
###############################################################################
16+
# Custom box styles can be implemented as a function that takes arguments
17+
# specifying both a rectangular box and the amount of "mutation", and
18+
# returns the "mutated" path. The specific signature is the one of
19+
# ``custom_box_style`` below.
20+
#
21+
# Here, we return a new path which adds an "arrow" shape on the left of the
22+
# box.
23+
#
24+
# The custom box style can then be used by passing
25+
# ``bbox=dict(boxstyle=custom_box_style, ...)`` to `.Axes.text`.
826

927

1028
def custom_box_style(x0, y0, width, height, mutation_size, mutation_aspect=1):
1129
"""
12-
Given the location and size of the box, return the path of
13-
the box around it.
14-
15-
- *x0*, *y0*, *width*, *height* : location and size of the box
16-
- *mutation_size* : a reference scale for the mutation.
17-
- *aspect_ratio* : aspect-ration for the mutation.
30+
Given the location and size of the box, return the path of the box around
31+
it.
32+
33+
Rotation is automatically taken care of.
34+
35+
Parameters
36+
----------
37+
x0, y0, width, height : float
38+
Box location and size.
39+
mutation_size : float
40+
Mutation reference scale, typically the text font size.
41+
mutation_aspect
42+
Mutation aspect ratio.
1843
"""
19-
20-
# note that we are ignoring mutation_aspect. This is okay in general.
44+
# We ignore mutation_aspect. This is okay in general.
2145

2246
# padding
2347
mypad = 0.3
2448
pad = mutation_size * mypad
25-
2649
# width and height with padding added.
2750
width = width + 2 * pad
2851
height = height + 2 * pad
29-
3052
# boundary of the padded box
3153
x0, y0 = x0 - pad, y0 - pad
3254
x1, y1 = x0 + width, y0 + height
55+
# return the new path
56+
return Path([(x0, y0),
57+
(x1, y0), (x1, y1), (x0, y1),
58+
(x0-pad, (y0+y1)/2), (x0, y0),
59+
(x0, y0)],
60+
closed=True)
3361

34-
cp = [(x0, y0),
35-
(x1, y0), (x1, y1), (x0, y1),
36-
(x0-pad, (y0+y1)/2.), (x0, y0),
37-
(x0, y0)]
38-
39-
com = [Path.MOVETO,
40-
Path.LINETO, Path.LINETO, Path.LINETO,
41-
Path.LINETO, Path.LINETO,
42-
Path.CLOSEPOLY]
4362

44-
path = Path(cp, com)
45-
46-
return path
63+
fig, ax = plt.subplots(figsize=(3, 3))
64+
ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", rotation=30,
65+
bbox=dict(boxstyle=custom_box_style, alpha=0.2))
4766

4867

49-
import matplotlib.pyplot as plt
68+
###############################################################################
69+
# Alternatively, custom box styles can be implemented as subclasses of
70+
# ``matplotlib.patches.BoxStyle._Base``, by overriding the ``transmute``
71+
# method, as demonstrated below.
72+
#
73+
# The subclass can then be registered into the ``BoxStyle._style_list`` dict,
74+
# which allows specifying the box style as a string,
75+
# ``bbox=dict(boxstyle="registered_name,param=value,...", ...)``.
76+
#
77+
# Note that this approach relies on internal APIs and is therefore not
78+
# officially supported.
79+
80+
81+
class MyStyle(BoxStyle._Base):
82+
"""A simple box."""
83+
84+
def __init__(self, pad=0.3):
85+
"""
86+
The arguments must be floats and have default values.
87+
88+
Parameters
89+
----------
90+
pad : float
91+
amount of padding
92+
"""
93+
self.pad = pad
94+
super().__init__()
95+
96+
def transmute(self, x0, y0, width, height, mutation_size):
97+
"""
98+
Given the location and size of the box, return the path of the box
99+
around it.
100+
101+
Rotation is automatically taken care of.
102+
103+
Parameters
104+
----------
105+
x0, y0, width, height : float
106+
Box location and size.
107+
mutation_size : float
108+
Reference scale for the mutation, typically the text font size.
109+
110+
Notes
111+
-----
112+
Unlike when defining the box style as a function (as in
113+
`custom_box_style`), here there is no *mutation_aspect* parameter.
114+
Matplotlib will first squeeze the box's y-axis by *mutation_aspect*
115+
before calling the `transmute` method, and then later reexpand the
116+
y-axis by the same amount.
117+
"""
118+
# padding
119+
pad = mutation_size * self.pad
120+
# width and height with padding added
121+
width = width + 2.*pad
122+
height = height + 2.*pad
123+
# boundary of the padded box
124+
x0, y0 = x0 - pad, y0 - pad
125+
x1, y1 = x0 + width, y0 + height
126+
# return the new path
127+
return Path([(x0, y0),
128+
(x1, y0), (x1, y1), (x0, y1),
129+
(x0-pad, (y0+y1)/2.), (x0, y0),
130+
(x0, y0)],
131+
closed=True)
132+
133+
134+
BoxStyle._style_list["angled"] = MyStyle # Register the custom style.
50135

51136
fig, ax = plt.subplots(figsize=(3, 3))
52-
ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center",
53-
bbox=dict(boxstyle=custom_box_style, alpha=0.2))
137+
ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", rotation=30,
138+
bbox=dict(boxstyle="angled,pad=0.5", alpha=0.2))
139+
140+
del BoxStyle._style_list["angled"] # Unregister it.
54141

55142
plt.show()

examples/userdemo/custom_boxstyle02.py

-79
This file was deleted.

tutorials/text/annotations.py

-11
Original file line numberDiff line numberDiff line change
@@ -590,17 +590,6 @@ def __call__(self, x0, y0, width, height, mutation_size,
590590
591591
Custom Boxstyle01
592592
593-
However, it is recommended that you derive from the
594-
matplotlib.patches.BoxStyle._Base as demonstrated below.
595-
596-
.. figure:: ../../gallery/userdemo/images/sphx_glr_custom_boxstyle02_001.png
597-
:target: ../../gallery/userdemo/custom_boxstyle02.html
598-
:align: center
599-
:scale: 50
600-
601-
Custom Boxstyle02
602-
603-
604593
Similarly, you can define a custom ConnectionStyle and a custom ArrowStyle.
605594
See the source code of ``lib/matplotlib/patches.py`` and check
606595
how each style class is defined.

0 commit comments

Comments
 (0)