Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b08a67f

Browse filesBrowse files
committed
REORG: LineStyle class
1 parent e8261cb commit b08a67f
Copy full SHA for b08a67f

File tree

4 files changed

+164
-101
lines changed
Filter options

4 files changed

+164
-101
lines changed

‎lib/matplotlib/_types.py

Copy file name to clipboardExpand all lines: lib/matplotlib/_types.py
+155-1Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
"""
44

55
from enum import Enum
6-
from matplotlib import cbook
6+
7+
from . import cbook, rcParams
8+
79

810

911
def _deprecate_case_insensitive_join_cap(s):
@@ -163,3 +165,155 @@ def demo():
163165

164166
ax.set_ylim(-.5, 1.5)
165167
ax.set_axis_off()
168+
169+
170+
def _get_dash_pattern(style):
171+
"""Convert linestyle to dash pattern."""
172+
# un-dashed styles
173+
if style in ['solid', 'None']:
174+
offset = 0
175+
dashes = None
176+
# dashed styles
177+
elif style in ['dashed', 'dashdot', 'dotted']:
178+
offset = 0
179+
dashes = tuple(rcParams['lines.{}_pattern'.format(style)])
180+
return offset, dashes
181+
182+
183+
class LineStyle(Enum):
184+
"""
185+
Describe if the line is solid or dashed, and the dash pattern, if any.
186+
187+
All lines in Matplotlib are considered either solid or "dashed". Some
188+
common dashing patterns are built-in, and are sufficient for a majority of
189+
uses:
190+
191+
=============================== =================
192+
Linestyle Description
193+
=============================== =================
194+
``'-'`` or ``'solid'`` solid line
195+
``'--'`` or ``'dashed'`` dashed line
196+
``'-.'`` or ``'dashdot'`` dash-dotted line
197+
``':'`` or ``'dotted'`` dotted line
198+
``'None'`` or ``' '`` or ``''`` draw nothing
199+
=============================== =================
200+
201+
However, for more fine-grained control, one can directly specify the
202+
dashing pattern by specifying::
203+
204+
(offset, onoffseq)
205+
206+
where ``onoffseq`` is an even length tuple specifying the lengths of each
207+
subsequent dash and space, and ``offset`` controls at which point in this
208+
pattern the start of the line will begin (to allow you to e.g. prevent
209+
corners from happening to land in between dashes).
210+
211+
For example, (5, 2, 1, 2) describes a sequence of 5 point and 1 point
212+
dashes separated by 2 point spaces.
213+
214+
Setting ``onoffseq`` to ``None`` results in a solid *LineStyle*.
215+
216+
The default dashing patterns described in the table above are themselves
217+
all described in this notation, and can therefore be customized by editing
218+
the appropriate ``lines.*_pattern`` *rc* parameter, as described in
219+
:doc:`/tutorials/introductory/customizing`.
220+
"""
221+
solid = '-'
222+
dashed = '--'
223+
dotted = ':'
224+
dashdot = '-.'
225+
_custom = 'custom'
226+
227+
_deprecated_lineStyles = { # hidden names deprecated
228+
'-': '_draw_solid',
229+
'--': '_draw_dashed',
230+
'-.': '_draw_dash_dot',
231+
':': '_draw_dotted',
232+
'None': '_draw_nothing',
233+
' ': '_draw_nothing',
234+
'': '_draw_nothing',
235+
}
236+
#: Maps short codes for line style to their full name used by backends.
237+
ls_mapper = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
238+
239+
def __init__(self, ls, scale=1):
240+
"""
241+
Parameters
242+
----------
243+
ls : str or dash tuple
244+
A description of the dashing pattern of the line. Allowed string
245+
inputs are {'-', 'solid', '--', 'dashed', '-.', 'dashdot', ':',
246+
'dotted', '', ' ', 'None', 'none'}. Alternatively, the dash tuple
247+
(``offset``, ``onoffseq``) can be specified directly in points.
248+
scale : float
249+
Uniformly scale the internal dash sequence length by a constant
250+
factor.
251+
"""
252+
if isinstance(ls, str):
253+
if ls in [' ', '', 'none']:
254+
ls = 'None'
255+
if ls in LineStyle.ls_mapper:
256+
ls = LineStyle.ls_mapper[ls]
257+
super().__init__(ls)
258+
offset, dashes = _get_dash_pattern(ls)
259+
else:
260+
try:
261+
offset, dashes = ls
262+
except ValueError: # not enough/too many values to unpack
263+
raise ValueError('LineStyle should be a string or a 2-tuple, '
264+
'instead received: ' + str(style))
265+
if offset is None:
266+
cbook.warn_deprecated(
267+
"3.3", message="Passing the dash offset as None is deprecated "
268+
"since %(since)s and support for it will be removed "
269+
"%(removal)s; pass it as zero instead.")
270+
offset = 0
271+
272+
if dashes is not None:
273+
# normalize offset to be positive and shorter than the dash cycle
274+
dsum = sum(dashes)
275+
if dsum:
276+
offset %= dsum
277+
# ensure dashes are correct length
278+
if len(dashes) % 2 != 0:
279+
raise ValueError('LineStyle onoffseq must be of even length.')
280+
self._us_offset = offset
281+
self._us_onoffseq = dashes
282+
self.scale(scale)
283+
284+
# compute the linewidth scaled dashes
285+
self._dashOffset, self._dashSeq = _scale_dashes(
286+
self._us_dashOffset, self._us_dashSeq, self._linewidth)
287+
288+
@property
289+
def scale(self):
290+
return self._scale
291+
292+
@scale.setter
293+
def scale(self, s):
294+
if s < 0:
295+
raise ValueError('LineStyle cannot be scaled by a negative value.')
296+
self.offset = self._us_offset * s
297+
self.onoffseq = (
298+
[x * s if x is not None else None for x in self._us_onoffseq]
299+
if self._us_onoffseq is not None else None
300+
)
301+
302+
@staticmethod
303+
def from_dashes(seq):
304+
"""
305+
Create a `.LineStyle` from a dash sequence (i.e. the ``onoffseq``).
306+
307+
The dash sequence is a sequence of floats of even length describing
308+
the length of dashes and spaces in points.
309+
310+
Parameters
311+
----------
312+
seq : sequence of floats (on/off ink in points) or (None, None)
313+
If *seq* is empty or ``(None, None)``, the `.LineStyle` will be
314+
solid.
315+
"""
316+
if seq == (None, None) or len(seq) == 0:
317+
return LineStyle('-')
318+
else:
319+
return LineStyle((0, seq))

‎lib/matplotlib/cbook/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cbook/__init__.py
-6Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,12 +1243,6 @@ def _compute_conf_interval(data, med, iqr, bootstrap):
12431243
return bxpstats
12441244

12451245

1246-
#: Maps short codes for line style to their full name used by backends.
1247-
ls_mapper = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
1248-
#: Maps full names for line styles used by backends to their short codes.
1249-
ls_mapper_r = {v: k for k, v in ls_mapper.items()}
1250-
1251-
12521246
def contiguous_regions(mask):
12531247
"""
12541248
Return a list of (ind0, ind1) such that ``mask[ind0:ind1].all()`` is

‎lib/matplotlib/lines.py

Copy file name to clipboardExpand all lines: lib/matplotlib/lines.py
+9-93Lines changed: 9 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
import matplotlib as mpl
1313
from . import _api, artist, cbook, colors as mcolors, docstring, rcParams
1414
from .artist import Artist, allow_rasterization
15-
from .cbook import (
16-
_to_unmasked_float_array, ls_mapper, ls_mapper_r, STEP_LOOKUP_MAP)
15+
from .cbook import _to_unmasked_float_array, STEP_LOOKUP_MAP
1716
from .colors import is_color_like, get_named_colors_mapping
1817
from .markers import MarkerStyle
1918
from .path import Path
@@ -32,49 +31,6 @@
3231
_log = logging.getLogger(__name__)
3332

3433

35-
def _get_dash_pattern(style):
36-
"""Convert linestyle to dash pattern."""
37-
# go from short hand -> full strings
38-
if isinstance(style, str):
39-
style = ls_mapper.get(style, style)
40-
# un-dashed styles
41-
if style in ['solid', 'None']:
42-
offset = 0
43-
dashes = None
44-
# dashed styles
45-
elif style in ['dashed', 'dashdot', 'dotted']:
46-
offset = 0
47-
dashes = tuple(rcParams['lines.{}_pattern'.format(style)])
48-
#
49-
elif isinstance(style, tuple):
50-
offset, dashes = style
51-
if offset is None:
52-
cbook.warn_deprecated(
53-
"3.3", message="Passing the dash offset as None is deprecated "
54-
"since %(since)s and support for it will be removed "
55-
"%(removal)s; pass it as zero instead.")
56-
offset = 0
57-
else:
58-
raise ValueError('Unrecognized linestyle: %s' % str(style))
59-
60-
# normalize offset to be positive and shorter than the dash cycle
61-
if dashes is not None:
62-
dsum = sum(dashes)
63-
if dsum:
64-
offset %= dsum
65-
66-
return offset, dashes
67-
68-
69-
def _scale_dashes(offset, dashes, lw):
70-
if not rcParams['lines.scale_dashes']:
71-
return offset, dashes
72-
scaled_offset = offset * lw
73-
scaled_dashes = ([x * lw if x is not None else None for x in dashes]
74-
if dashes is not None else None)
75-
return scaled_offset, scaled_dashes
76-
77-
7834
def segment_hits(cx, cy, x, y, radius):
7935
"""
8036
Return the indices of the segments in the polyline with coordinates (*cx*,
@@ -219,15 +175,7 @@ class Line2D(Artist):
219175
can create "stepped" lines in various styles.
220176
"""
221177

222-
lineStyles = _lineStyles = { # hidden names deprecated
223-
'-': '_draw_solid',
224-
'--': '_draw_dashed',
225-
'-.': '_draw_dash_dot',
226-
':': '_draw_dotted',
227-
'None': '_draw_nothing',
228-
' ': '_draw_nothing',
229-
'': '_draw_nothing',
230-
}
178+
lineStyles = _lineStyles = LineStyle._deprecated_lineStyles
231179

232180
_drawStyles_l = {
233181
'default': '_draw_lines',
@@ -297,7 +245,7 @@ def __init__(self, xdata, ydata,
297245
298246
%(_Line2D_docstr)s
299247
300-
See :meth:`set_linestyle` for a description of the line styles,
248+
See `.LineStyle` for a description of the line styles,
301249
:meth:`set_marker` for a description of the markers, and
302250
:meth:`set_drawstyle` for a description of the draw styles.
303251
@@ -1096,13 +1044,12 @@ def set_linewidth(self, w):
10961044
if self._linewidth != w:
10971045
self.stale = True
10981046
self._linewidth = w
1099-
# rescale the dashes + offset
1100-
self._dashOffset, self._dashSeq = _scale_dashes(
1101-
self._us_dashOffset, self._us_dashSeq, self._linewidth)
1047+
if rcParams['lines.scale_dashes']:
1048+
self._linestyle.scale = self._linewidth
11021049

11031050
def set_linestyle(self, ls):
11041051
"""
1105-
Set the linestyle of the line.
1052+
Set the `.LineStyle` of the line.
11061053
11071054
Parameters
11081055
----------
@@ -1131,22 +1078,7 @@ def set_linestyle(self, ls):
11311078
11321079
For examples see :doc:`/gallery/lines_bars_and_markers/linestyles`.
11331080
"""
1134-
if isinstance(ls, str):
1135-
if ls in [' ', '', 'none']:
1136-
ls = 'None'
1137-
1138-
_api.check_in_list([*self._lineStyles, *ls_mapper_r], ls=ls)
1139-
if ls not in self._lineStyles:
1140-
ls = ls_mapper_r[ls]
1141-
self._linestyle = ls
1142-
else:
1143-
self._linestyle = '--'
1144-
1145-
# get the unscaled dashes
1146-
self._us_dashOffset, self._us_dashSeq = _get_dash_pattern(ls)
1147-
# compute the linewidth scaled dashes
1148-
self._dashOffset, self._dashSeq = _scale_dashes(
1149-
self._us_dashOffset, self._us_dashSeq, self._linewidth)
1081+
self._linestyle = LineStyle(ls)
11501082

11511083
@docstring.dedent_interpd
11521084
def set_marker(self, marker):
@@ -1259,25 +1191,9 @@ def set_ydata(self, y):
12591191
self.stale = True
12601192

12611193
def set_dashes(self, seq):
1262-
"""
1263-
Set the dash sequence.
1264-
1265-
The dash sequence is a sequence of floats of even length describing
1266-
the length of dashes and spaces in points.
1267-
1268-
For example, (5, 2, 1, 2) describes a sequence of 5 point and 1 point
1269-
dashes separated by 2 point spaces.
1194+
self.set_linestyle(LineStyle.from_dashes(seq))
12701195

1271-
Parameters
1272-
----------
1273-
seq : sequence of floats (on/off ink in points) or (None, None)
1274-
If *seq* is empty or ``(None, None)``, the linestyle will be set
1275-
to solid.
1276-
"""
1277-
if seq == (None, None) or len(seq) == 0:
1278-
self.set_linestyle('-')
1279-
else:
1280-
self.set_linestyle((0, seq))
1196+
set_dashes.__doc__ = LineStyle.from_dashes.__doc_r
12811197

12821198
def update_from(self, other):
12831199
"""Copy properties from *other* to self."""

‎lib/matplotlib/rcsetup.py

Copy file name to clipboardExpand all lines: lib/matplotlib/rcsetup.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import numpy as np
2424

2525
from matplotlib import animation, cbook
26-
from matplotlib.cbook import ls_mapper
2726
from matplotlib.colors import is_color_like
2827
from matplotlib.fontconfig_pattern import parse_fontconfig_pattern
2928
from matplotlib._types import JoinStyle, CapStyle

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.