marker-transforms · matplotlib/matplotlib@8e92a21 · GitHub
Skip to content

Commit 8e92a21

Browse files
marker-transforms
1 parent a933565 commit 8e92a21

4 files changed

Lines changed: 117 additions & 14 deletions

File tree

Lines changed: 12 additions & 0 deletions

examples/lines_bars_and_markers/scatter_piecharts.py

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
Scatter plot with pie chart markers
44
===================================
55
6-
This example makes custom 'pie charts' as the markers for a scatter plot.
7-
8-
Thanks to Manuel Metz for the example.
6+
This example shows two methods to make custom 'pie charts' as the markers
7+
for a scatter plot.
98
"""
109

10+
##########################################################################
11+
# Manually creating marker vertices
12+
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
#
14+
1115
import numpy as np
1216
import matplotlib.pyplot as plt
1317

14-
# first define the ratios
18+
# first define the cumulative ratios
1519
r1 = 0.2 # 20%
1620
r2 = r1 + 0.4 # 40%
1721

@@ -36,10 +40,55 @@
3640
s3 = np.abs(xy3).max()
3741

3842
fig, ax = plt.subplots()
39-
ax.scatter(range(3), range(3), marker=xy1, s=s1**2 * sizes, facecolor='blue')
40-
ax.scatter(range(3), range(3), marker=xy2, s=s2**2 * sizes, facecolor='green')
41-
ax.scatter(range(3), range(3), marker=xy3, s=s3**2 * sizes, facecolor='red')
43+
ax.scatter(range(3), range(3), marker=xy1, s=s1**2 * sizes, facecolor='C0')
44+
ax.scatter(range(3), range(3), marker=xy2, s=s2**2 * sizes, facecolor='C1')
45+
ax.scatter(range(3), range(3), marker=xy3, s=s3**2 * sizes, facecolor='C2')
46+
47+
plt.show()
48+
49+
50+
##########################################################################
51+
# Using wedges as markers
52+
# ~~~~~~~~~~~~~~~~~~~~~~~
53+
#
54+
# An alternative is to create custom markers from the `~.path.Path` of a
55+
# `~.patches.Wedge`, which might be more versatile.
56+
#
57+
58+
import numpy as np
59+
import matplotlib.pyplot as plt
60+
from matplotlib.patches import Wedge
61+
from matplotlib.markers import MarkerStyle
62+
63+
# first define the ratios
64+
r1 = 0.2 # 20%
65+
r2 = r1 + 0.3 # 50%
66+
r3 = 1 - r1 - r2 # 30%
67+
68+
69+
def markers_from_ratios(ratios, width=1):
70+
markers = []
71+
angles = 360*np.concatenate(([0], np.cumsum(ratios)))
72+
for i in range(len(angles)-1):
73+
# create a Wedge within the unit square in between the given angles...
74+
w = Wedge((0, 0), 0.5, angles[i], angles[i+1], width=width/2)
75+
# ... and create a custom Marker from its path.
76+
markers.append(MarkerStyle(w.get_path(), normalization="none"))
77+
return markers
78+
79+
# define some sizes of the scatter marker
80+
sizes = np.array([100, 200, 400, 800])
81+
# collect the markers and some colors
82+
markers = markers_from_ratios([r1, r2, r3], width=0.6)
83+
colors = plt.cm.tab10.colors[:len(markers)]
84+
85+
fig, ax = plt.subplots()
86+
87+
for marker, color in zip(markers, colors):
88+
ax.scatter(range(len(sizes)), range(len(sizes)), marker=marker, s=sizes,
89+
edgecolor="none", facecolor=color)
4290

91+
ax.margins(0.1)
4392
plt.show()
4493

4594
#############################################################################
@@ -55,3 +104,5 @@
55104
import matplotlib
56105
matplotlib.axes.Axes.scatter
57106
matplotlib.pyplot.scatter
107+
matplotlib.patches.Wedge
108+
matplotlib.markers.MarkerStyle

lib/matplotlib/markers.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ class MarkerStyle:
201201
# TODO: Is this ever used as a non-constant?
202202
_point_size_reduction = 0.5
203203

204-
def __init__(self, marker=None, fillstyle=None):
204+
def __init__(self, marker=None, fillstyle=None, *,
205+
normalization="classic"):
205206
"""
206207
Attributes
207208
----------
@@ -213,12 +214,23 @@ def __init__(self, marker=None, fillstyle=None):
213214
214215
Parameters
215216
----------
216-
marker : str or array-like, optional, default: None
217+
marker : str, array-like, `~.path.Path`, or `~.markers.MarkerStyle`, \
218+
default: None
217219
See the descriptions of possible markers in the module docstring.
218220
219221
fillstyle : str, optional, default: 'full'
220222
'full', 'left", 'right', 'bottom', 'top', 'none'
223+
224+
normalization : str, {'classic', 'none'}, optional, default: "classic"
225+
The normalization of the marker size. Only applies to custom paths
226+
that are provided as array of vertices or `~.path.Path`.
227+
Can take two values:
228+
*'classic'*, being the default, makes sure the marker path is
229+
normalized to fit within a unit-square by affine scaling.
230+
*'none'*, in which case no scaling is performed on the marker path.
221231
"""
232+
cbook._check_in_list(["classic", "none"], normalization=normalization)
233+
self._normalize = normalization
222234
self._marker_function = None
223235
self.set_fillstyle(fillstyle)
224236
self.set_marker(marker)
@@ -303,6 +315,13 @@ def get_path(self):
303315
def get_transform(self):
304316
return self._transform.frozen()
305317

318+
def set_transform(self, transform):
319+
"""
320+
Sets the transform of the marker. This is the transform by which the
321+
marker path is transformed.
322+
"""
323+
self._transform = transform
324+
306325
def get_alt_path(self):
307326
return self._alt_path
308327

@@ -316,8 +335,9 @@ def _set_nothing(self):
316335
self._filled = False
317336

318337
def _set_custom_marker(self, path):
319-
rescale = np.max(np.abs(path.vertices)) # max of x's and y's.
320-
self._transform = Affine2D().scale(0.5 / rescale)
338+
if self._normalize == "classic":
339+
rescale = np.max(np.abs(path.vertices)) # max of x's and y's.
340+
self._transform = Affine2D().scale(0.5 / rescale)
321341
self._path = path
322342

323343
def _set_path_marker(self):
@@ -350,8 +370,6 @@ def _set_tuple_marker(self):
350370
def _set_mathtext_path(self):
351371
"""
352372
Draws mathtext markers '$...$' using TextPath object.
353-
354-
Submitted by tcb
355373
"""
356374
from matplotlib.text import TextPath
357375

lib/matplotlib/tests/test_marker.py

Lines changed: 23 additions & 1 deletion

0 commit comments

Comments
 (0)