Skip to content

Navigation Menu

Sign in
Appearance settings

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 ca4dfe0

Browse filesBrowse files
committed
REORG: LineStyle class
1 parent 6eb9867 commit ca4dfe0
Copy full SHA for ca4dfe0

File tree

5 files changed

+276
-239
lines changed
Filter options

5 files changed

+276
-239
lines changed

‎examples/lines_bars_and_markers/linestyles.py

Copy file name to clipboardExpand all lines: examples/lines_bars_and_markers/linestyles.py
-77Lines changed: 0 additions & 77 deletions
This file was deleted.

‎lib/matplotlib/_enums.py

Copy file name to clipboardExpand all lines: lib/matplotlib/_enums.py
+240-3Lines changed: 240 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"""
1212

1313
from enum import Enum, auto
14-
from matplotlib import cbook, docstring
14+
from numbers import Number
15+
16+
from matplotlib import _api, docstring
1517

1618

1719
class _AutoStringNameEnum(Enum):
@@ -28,12 +30,12 @@ def _deprecate_case_insensitive_join_cap(s):
2830
s_low = s.lower()
2931
if s != s_low:
3032
if s_low in ['miter', 'round', 'bevel']:
31-
cbook.warn_deprecated(
33+
_api.warn_deprecated(
3234
"3.3", message="Case-insensitive capstyles are deprecated "
3335
"since %(since)s and support for them will be removed "
3436
"%(removal)s; please pass them in lowercase.")
3537
elif s_low in ['butt', 'round', 'projecting']:
36-
cbook.warn_deprecated(
38+
_api.warn_deprecated(
3739
"3.3", message="Case-insensitive joinstyles are deprecated "
3840
"since %(since)s and support for them will be removed "
3941
"%(removal)s; please pass them in lowercase.")
@@ -206,3 +208,238 @@ def demo():
206208

207209
docstring.interpd.update({'JoinStyle': JoinStyle.input_description,
208210
'CapStyle': CapStyle.input_description})
211+
212+
213+
def _get_dash_pattern(style):
214+
"""Convert linestyle to dash pattern."""
215+
# import must be local for validator code to live here
216+
from . import rcParams
217+
# un-dashed styles
218+
if style in ['solid', 'None']:
219+
offset = 0
220+
dashes = None
221+
# dashed styles
222+
elif style in ['dashed', 'dashdot', 'dotted']:
223+
offset = 0
224+
dashes = tuple(rcParams['lines.{}_pattern'.format(style)])
225+
return offset, dashes
226+
227+
228+
class LineStyle(Enum):
229+
"""
230+
Describe if the line is solid or dashed, and the dash pattern, if any.
231+
232+
All lines in Matplotlib are considered either solid or "dashed". Some
233+
common dashing patterns are built-in, and are sufficient for a majority of
234+
uses:
235+
236+
=============================== =================
237+
Linestyle Description
238+
=============================== =================
239+
``'-'`` or ``'solid'`` solid line
240+
``'--'`` or ``'dashed'`` dashed line
241+
``'-.'`` or ``'dashdot'`` dash-dotted line
242+
``':'`` or ``'dotted'`` dotted line
243+
``'None'`` or ``' '`` or ``''`` draw nothing
244+
=============================== =================
245+
246+
However, for more fine-grained control, one can directly specify the
247+
dashing pattern by specifying::
248+
249+
(offset, onoffseq)
250+
251+
where ``onoffseq`` is an even length tuple specifying the lengths of each
252+
subsequent dash and space, and ``offset`` controls at which point in this
253+
pattern the start of the line will begin (to allow you to e.g. prevent
254+
corners from happening to land in between dashes).
255+
256+
For example, (5, 2, 1, 2) describes a sequence of 5 point and 1 point
257+
dashes separated by 2 point spaces.
258+
259+
Setting ``onoffseq`` to ``None`` results in a solid *LineStyle*.
260+
261+
The default dashing patterns described in the table above are themselves
262+
all described in this notation, and can therefore be customized by editing
263+
the appropriate ``lines.*_pattern`` *rc* parameter, as described in
264+
:doc:`/tutorials/introductory/customizing`.
265+
266+
.. plot::
267+
:alt: Demo of possible LineStyle's.
268+
269+
from matplotlib._types import LineStyle
270+
LineStyle.demo()
271+
272+
.. note::
273+
274+
In addition to directly taking a ``linestyle`` argument,
275+
`~.lines.Line2D` exposes a ``~.lines.Line2D.set_dashes`` method that
276+
can be used to create a new *LineStyle* by providing just the
277+
``onoffseq``, but does not let you customize the offset. This method is
278+
called when using the keyword *dashes* to the cycler , as shown in
279+
:doc:`property_cycle </tutorials/intermediate/color_cycle>`.
280+
"""
281+
solid = '-'
282+
dashed = '--'
283+
dotted = ':'
284+
dashdot = '-.'
285+
none = 'None'
286+
_custom = 'custom'
287+
288+
_deprecated_lineStyles = { # hidden names deprecated
289+
'-': '_draw_solid',
290+
'--': '_draw_dashed',
291+
'-.': '_draw_dash_dot',
292+
':': '_draw_dotted',
293+
'None': '_draw_nothing',
294+
' ': '_draw_nothing',
295+
'': '_draw_nothing',
296+
}
297+
298+
#: Maps short codes for line style to their full name used by backends.
299+
ls_mapper = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
300+
301+
def __init__(self, ls, scale=1):
302+
"""
303+
Parameters
304+
----------
305+
ls : str or dash tuple
306+
A description of the dashing pattern of the line. Allowed string
307+
inputs are {'-', 'solid', '--', 'dashed', '-.', 'dashdot', ':',
308+
'dotted', '', ' ', 'None', 'none'}. Alternatively, the dash tuple
309+
(``offset``, ``onoffseq``) can be specified directly in points.
310+
scale : float
311+
Uniformly scale the internal dash sequence length by a constant
312+
factor.
313+
"""
314+
315+
if isinstance(ls, str):
316+
if ls in [' ', '', 'none']:
317+
ls = 'None'
318+
if ls in LineStyle.ls_mapper:
319+
ls = LineStyle.ls_mapper[ls]
320+
Enum.__init__(self)
321+
offset, onoffseq = _get_dash_pattern(ls)
322+
else:
323+
try:
324+
offset, onoffseq = ls
325+
except ValueError: # not enough/too many values to unpack
326+
raise ValueError('LineStyle should be a string or a 2-tuple, '
327+
'instead received: ' + str(ls))
328+
if offset is None:
329+
_api.warn_deprecated(
330+
"3.3", message="Passing the dash offset as None is deprecated "
331+
"since %(since)s and support for it will be removed "
332+
"%(removal)s; pass it as zero instead.")
333+
offset = 0
334+
335+
if onoffseq is not None:
336+
# normalize offset to be positive and shorter than the dash cycle
337+
dsum = sum(onoffseq)
338+
if dsum:
339+
offset %= dsum
340+
if len(onoffseq) % 2 != 0:
341+
raise ValueError('LineStyle onoffseq must be of even length.')
342+
if not all(isinstance(elem, Number) for elem in onoffseq):
343+
raise ValueError('LineStyle onoffseq must be list of floats.')
344+
self._us_offset = offset
345+
self._us_onoffseq = dashes
346+
self.scale(scale)
347+
348+
@property
349+
def scale(self):
350+
return self._scale
351+
352+
@scale.setter
353+
def scale(self, s):
354+
if s < 0:
355+
raise ValueError('LineStyle cannot be scaled by a negative value.')
356+
self.offset = self._us_offset * s
357+
self.onoffseq = (
358+
[x * s if x is not None else None for x in self._us_onoffseq]
359+
if self._us_onoffseq is not None else None
360+
)
361+
362+
@staticmethod
363+
def from_dashes(seq):
364+
"""
365+
Create a `.LineStyle` from a dash sequence (i.e. the ``onoffseq``).
366+
367+
The dash sequence is a sequence of floats of even length describing
368+
the length of dashes and spaces in points.
369+
370+
Parameters
371+
----------
372+
seq : sequence of floats (on/off ink in points) or (None, None)
373+
If *seq* is empty or ``(None, None)``, the `.LineStyle` will be
374+
solid.
375+
"""
376+
if seq == (None, None) or len(seq) == 0:
377+
return LineStyle('-')
378+
else:
379+
return LineStyle((0, seq))
380+
381+
@staticmethod
382+
def demo():
383+
import numpy as np
384+
import matplotlib.pyplot as plt
385+
386+
linestyle_str = [
387+
('solid', 'solid'), # Same as (0, ()) or '-'
388+
('dotted', 'dotted'), # Same as (0, (1, 1)) or '.'
389+
('dashed', 'dashed'), # Same as '--'
390+
('dashdot', 'dashdot')] # Same as '-.'
391+
392+
linestyle_tuple = [
393+
('loosely dotted', (0, (1, 10))),
394+
('dotted', (0, (1, 1))),
395+
('densely dotted', (0, (1, 1))),
396+
397+
('loosely dashed', (0, (5, 10))),
398+
('dashed', (0, (5, 5))),
399+
('densely dashed', (0, (5, 1))),
400+
401+
('loosely dashdotted', (0, (3, 10, 1, 10))),
402+
('dashdotted', (0, (3, 5, 1, 5))),
403+
('densely dashdotted', (0, (3, 1, 1, 1))),
404+
405+
('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
406+
('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
407+
('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))]
408+
409+
def plot_linestyles(ax, linestyles, title):
410+
X, Y = np.linspace(0, 100, 10), np.zeros(10)
411+
yticklabels = []
412+
413+
for i, (name, linestyle) in enumerate(linestyles):
414+
ax.plot(X, Y+i, linestyle=linestyle, linewidth=1.5,
415+
color='black')
416+
yticklabels.append(name)
417+
418+
ax.set_title(title)
419+
ax.set(ylim=(-0.5, len(linestyles)-0.5),
420+
yticks=np.arange(len(linestyles)),
421+
yticklabels=yticklabels)
422+
ax.tick_params(left=False, bottom=False, labelbottom=False)
423+
for spine in ax.spines.values():
424+
spine.set_visible(False)
425+
426+
# For each line style, add a text annotation with a small offset
427+
# from the reference point (0 in Axes coords, y tick value in Data
428+
# coords).
429+
for i, (name, linestyle) in enumerate(linestyles):
430+
ax.annotate(repr(linestyle),
431+
xy=(0.0, i), xycoords=ax.get_yaxis_transform(),
432+
xytext=(-6, -12), textcoords='offset points',
433+
color="blue", fontsize=8, ha="right",
434+
family="monospace")
435+
436+
ax0, ax1 = (plt.figure(figsize=(10, 8))
437+
.add_gridspec(2, 1, height_ratios=[1, 3])
438+
.subplots())
439+
440+
plot_linestyles(ax0, linestyle_str[::-1], title='Named linestyles')
441+
plot_linestyles(ax1, linestyle_tuple[::-1],
442+
title='Parametrized linestyles')
443+
444+
plt.tight_layout()
445+
plt.show()

‎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
@@ -1242,12 +1242,6 @@ def _compute_conf_interval(data, med, iqr, bootstrap):
12421242
return bxpstats
12431243

12441244

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

0 commit comments

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