Skip to content

Commit fcfea77

Browse files
authored
Merge pull request #20914 from deep-jkl/19195-rotated-markers
19195 rotated markers
2 parents d297e41 + 7101e3c commit fcfea77

File tree

6 files changed

+380
-21
lines changed

6 files changed

+380
-21
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
New customization of MarkerStyle
2+
--------------------------------
3+
4+
New MarkerStyle parameters allow control of join style and cap style, and for
5+
the user to supply a transformation to be applied to the marker (e.g. a rotation).
6+
7+
.. plot::
8+
:include-source: true
9+
10+
import matplotlib.pyplot as plt
11+
from matplotlib.markers import MarkerStyle
12+
from matplotlib.transforms import Affine2D
13+
fig, ax = plt.subplots(figsize=(6, 1))
14+
fig.suptitle('New markers', fontsize=14)
15+
for col, (size, rot) in enumerate(zip([2, 5, 10], [0, 45, 90])):
16+
t = Affine2D().rotate_deg(rot).scale(size)
17+
ax.plot(col, 0, marker=MarkerStyle("*", transform=t))
18+
ax.axis("off")
19+
ax.set_xlim(-0.1, 2.4)

examples/lines_bars_and_markers/marker_reference.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
.. redirect-from:: /gallery/shapes_and_collections/marker_path
2020
"""
2121

22+
from matplotlib.markers import MarkerStyle
2223
import matplotlib.pyplot as plt
2324
from matplotlib.lines import Line2D
25+
from matplotlib.transforms import Affine2D
2426

2527

2628
text_style = dict(horizontalalignment='right', verticalalignment='center',
@@ -159,3 +161,96 @@ def split_list(a_list):
159161
format_axes(ax)
160162

161163
plt.show()
164+
165+
###############################################################################
166+
# Advanced marker modifications with transform
167+
# ============================================
168+
#
169+
# Markers can be modified by passing a transform to the MarkerStyle
170+
# constructor. Following example shows how a supplied rotation is applied to
171+
# several marker shapes.
172+
173+
common_style = {k: v for k, v in filled_marker_style.items() if k != 'marker'}
174+
angles = [0, 10, 20, 30, 45, 60, 90]
175+
176+
fig, ax = plt.subplots()
177+
fig.suptitle('Rotated markers', fontsize=14)
178+
179+
ax.text(-0.5, 0, 'Filled marker', **text_style)
180+
for x, theta in enumerate(angles):
181+
t = Affine2D().rotate_deg(theta)
182+
ax.plot(x, 0, marker=MarkerStyle('o', 'left', t), **common_style)
183+
184+
ax.text(-0.5, 1, 'Un-filled marker', **text_style)
185+
for x, theta in enumerate(angles):
186+
t = Affine2D().rotate_deg(theta)
187+
ax.plot(x, 1, marker=MarkerStyle('1', 'left', t), **common_style)
188+
189+
ax.text(-0.5, 2, 'Equation marker', **text_style)
190+
for x, theta in enumerate(angles):
191+
t = Affine2D().rotate_deg(theta)
192+
eq = r'$\frac{1}{x}$'
193+
ax.plot(x, 2, marker=MarkerStyle(eq, 'left', t), **common_style)
194+
195+
for x, theta in enumerate(angles):
196+
ax.text(x, 2.5, f"{theta}°", horizontalalignment="center")
197+
format_axes(ax)
198+
199+
fig.tight_layout()
200+
plt.show()
201+
202+
###############################################################################
203+
# Setting marker cap style and join style
204+
# =======================================
205+
#
206+
# Markers have default cap and join styles, but these can be
207+
# customized when creating a MarkerStyle.
208+
209+
from matplotlib.markers import JoinStyle, CapStyle
210+
211+
marker_inner = dict(markersize=35,
212+
markerfacecolor='tab:blue',
213+
markerfacecoloralt='lightsteelblue',
214+
markeredgecolor='brown',
215+
markeredgewidth=8,
216+
)
217+
218+
marker_outer = dict(markersize=35,
219+
markerfacecolor='tab:blue',
220+
markerfacecoloralt='lightsteelblue',
221+
markeredgecolor='white',
222+
markeredgewidth=1,
223+
)
224+
225+
fig, ax = plt.subplots()
226+
fig.suptitle('Marker CapStyle', fontsize=14)
227+
fig.subplots_adjust(left=0.1)
228+
229+
for y, cap_style in enumerate(CapStyle):
230+
ax.text(-0.5, y, cap_style.name, **text_style)
231+
for x, theta in enumerate(angles):
232+
t = Affine2D().rotate_deg(theta)
233+
m = MarkerStyle('1', transform=t, capstyle=cap_style)
234+
ax.plot(x, y, marker=m, **marker_inner)
235+
ax.plot(x, y, marker=m, **marker_outer)
236+
ax.text(x, len(CapStyle) - .5, f'{theta}°', ha='center')
237+
format_axes(ax)
238+
plt.show()
239+
240+
###############################################################################
241+
# Modifying the join style:
242+
243+
fig, ax = plt.subplots()
244+
fig.suptitle('Marker JoinStyle', fontsize=14)
245+
fig.subplots_adjust(left=0.05)
246+
247+
for y, join_style in enumerate(JoinStyle):
248+
ax.text(-0.5, y, join_style.name, **text_style)
249+
for x, theta in enumerate(angles):
250+
t = Affine2D().rotate_deg(theta)
251+
m = MarkerStyle('*', transform=t, joinstyle=join_style)
252+
ax.plot(x, y, marker=m, **marker_inner)
253+
ax.text(x, len(JoinStyle) - .5, f'{theta}°', ha='center')
254+
format_axes(ax)
255+
256+
plt.show()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
==============================================
3+
Mapping marker properties to multivariate data
4+
==============================================
5+
6+
This example shows how to use different properties of markers to plot
7+
multivariate datasets. Here we represent a successful baseball throw as a
8+
smiley face with marker size mapped to the skill of thrower, marker rotation to
9+
the take-off angle, and thrust to the marker color.
10+
"""
11+
12+
import numpy as np
13+
import matplotlib.pyplot as plt
14+
from matplotlib.markers import MarkerStyle
15+
from matplotlib.transforms import Affine2D
16+
from matplotlib.textpath import TextPath
17+
from matplotlib.colors import Normalize
18+
19+
SUCCESS_SYMBOLS = [
20+
TextPath((0, 0), "☹"),
21+
TextPath((0, 0), "😒"),
22+
TextPath((0, 0), "☺"),
23+
]
24+
25+
N = 25
26+
np.random.seed(42)
27+
skills = np.random.uniform(5, 80, size=N) * 0.1 + 5
28+
takeoff_angles = np.random.normal(0, 90, N)
29+
thrusts = np.random.uniform(size=N)
30+
successfull = np.random.randint(0, 3, size=N)
31+
positions = np.random.normal(size=(N, 2)) * 5
32+
data = zip(skills, takeoff_angles, thrusts, successfull, positions)
33+
34+
cmap = plt.cm.get_cmap("plasma")
35+
fig, ax = plt.subplots()
36+
fig.suptitle("Throwing success", size=14)
37+
for skill, takeoff, thrust, mood, pos in data:
38+
t = Affine2D().scale(skill).rotate_deg(takeoff)
39+
m = MarkerStyle(SUCCESS_SYMBOLS[mood], transform=t)
40+
ax.plot(pos[0], pos[1], marker=m, color=cmap(thrust))
41+
fig.colorbar(plt.cm.ScalarMappable(norm=Normalize(0, 1), cmap=cmap),
42+
ax=ax, label="Normalized Thrust [a.u.]")
43+
ax.set_xlabel("X position [m]")
44+
ax.set_ylabel("Y position [m]")
45+
46+
plt.show()

lib/matplotlib/lines.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,10 @@ def __init__(self, xdata, ydata,
370370
self.set_color(color)
371371
if marker is None:
372372
marker = 'none' # Default.
373-
self._marker = MarkerStyle(marker, fillstyle)
373+
if not isinstance(marker, MarkerStyle):
374+
self._marker = MarkerStyle(marker, fillstyle)
375+
else:
376+
self._marker = marker
374377

375378
self._markevery = None
376379
self._markersize = None

0 commit comments

Comments
 (0)
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