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 6197d1f

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

File tree

5 files changed

+269
-236
lines changed
Filter options

5 files changed

+269
-236
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/_types.py

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

55
from enum import Enum
6-
from matplotlib import cbook
76

7+
from . import cbook
88

99
def _deprecate_case_insensitive_join_cap(s):
1010
s_low = s.lower()
@@ -163,3 +163,236 @@ def demo():
163163

164164
ax.set_ylim(-.5, 1.5)
165165
ax.set_axis_off()
166+
167+
168+
def _get_dash_pattern(style):
169+
"""Convert linestyle to dash pattern."""
170+
# import must be local for validator code to live here
171+
from . import rcParams
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+
.. plot::
222+
:alt: Demo of possible LineStyle's.
223+
224+
from matplotlib._types import LineStyle
225+
LineStyle.demo()
226+
227+
.. note::
228+
229+
In addition to directly taking a ``linestyle`` argument,
230+
`~.lines.Line2D` exposes a ``~.lines.Line2D.set_dashes`` method that
231+
can be used to create a new *LineStyle* by providing just the
232+
``onoffseq``, but does not let you customize the offset. This method is
233+
called when using the keyword *dashes* to the cycler , as shown in
234+
:doc:`property_cycle </tutorials/intermediate/color_cycle>`.
235+
"""
236+
solid = '-'
237+
dashed = '--'
238+
dotted = ':'
239+
dashdot = '-.'
240+
none = 'None'
241+
_custom = 'custom'
242+
243+
_deprecated_lineStyles = { # hidden names deprecated
244+
'-': '_draw_solid',
245+
'--': '_draw_dashed',
246+
'-.': '_draw_dash_dot',
247+
':': '_draw_dotted',
248+
'None': '_draw_nothing',
249+
' ': '_draw_nothing',
250+
'': '_draw_nothing',
251+
}
252+
253+
#: Maps short codes for line style to their full name used by backends.
254+
ls_mapper = {'-': 'solid', '--': 'dashed', '-.': 'dashdot', ':': 'dotted'}
255+
256+
def __init__(self, ls, scale=1):
257+
"""
258+
Parameters
259+
----------
260+
ls : str or dash tuple
261+
A description of the dashing pattern of the line. Allowed string
262+
inputs are {'-', 'solid', '--', 'dashed', '-.', 'dashdot', ':',
263+
'dotted', '', ' ', 'None', 'none'}. Alternatively, the dash tuple
264+
(``offset``, ``onoffseq``) can be specified directly in points.
265+
scale : float
266+
Uniformly scale the internal dash sequence length by a constant
267+
factor.
268+
"""
269+
270+
if isinstance(ls, str):
271+
if ls in [' ', '', 'none']:
272+
ls = 'None'
273+
if ls in ls_mapper:
274+
ls = ls_mapper[ls]
275+
Enum.__init__(self)
276+
offset, onoffseq = _get_dash_pattern(ls)
277+
else:
278+
try:
279+
offset, onoffseq = ls
280+
except ValueError: # not enough/too many values to unpack
281+
raise ValueError('LineStyle should be a string or a 2-tuple, '
282+
'instead received: ' + str(style))
283+
if offset is None:
284+
cbook.warn_deprecated(
285+
"3.3", message="Passing the dash offset as None is deprecated "
286+
"since %(since)s and support for it will be removed "
287+
"%(removal)s; pass it as zero instead.")
288+
offset = 0
289+
290+
if onoffseq is not None:
291+
# normalize offset to be positive and shorter than the dash cycle
292+
dsum = sum(onoffseq)
293+
if dsum:
294+
offset %= dsum
295+
if len(onoffseq) % 2 != 0:
296+
raise ValueError('LineStyle onoffseq must be of even length.')
297+
if not all(isinstance(elem, Number) for elem in onoffseq):
298+
raise ValueError('LineStyle onoffseq must be list of floats.')
299+
self._us_offset = offset
300+
self._us_onoffseq = dashes
301+
self.scale(scale)
302+
303+
@property
304+
def scale(self):
305+
return self._scale
306+
307+
@scale.setter
308+
def scale(self, s):
309+
if s < 0:
310+
raise ValueError('LineStyle cannot be scaled by a negative value.')
311+
self.offset = self._us_offset * s
312+
self.onoffseq = (
313+
[x * s if x is not None else None for x in self._us_onoffseq]
314+
if self._us_onoffseq is not None else None
315+
)
316+
317+
@staticmethod
318+
def from_dashes(seq):
319+
"""
320+
Create a `.LineStyle` from a dash sequence (i.e. the ``onoffseq``).
321+
322+
The dash sequence is a sequence of floats of even length describing
323+
the length of dashes and spaces in points.
324+
325+
Parameters
326+
----------
327+
seq : sequence of floats (on/off ink in points) or (None, None)
328+
If *seq* is empty or ``(None, None)``, the `.LineStyle` will be
329+
solid.
330+
"""
331+
if seq == (None, None) or len(seq) == 0:
332+
return LineStyle('-')
333+
else:
334+
return LineStyle((0, seq))
335+
336+
@staticmethod
337+
def demo():
338+
import numpy as np
339+
import matplotlib.pyplot as plt
340+
341+
linestyle_str = [
342+
('solid', 'solid'), # Same as (0, ()) or '-'
343+
('dotted', 'dotted'), # Same as (0, (1, 1)) or '.'
344+
('dashed', 'dashed'), # Same as '--'
345+
('dashdot', 'dashdot')] # Same as '-.'
346+
347+
linestyle_tuple = [
348+
('loosely dotted', (0, (1, 10))),
349+
('dotted', (0, (1, 1))),
350+
('densely dotted', (0, (1, 1))),
351+
352+
('loosely dashed', (0, (5, 10))),
353+
('dashed', (0, (5, 5))),
354+
('densely dashed', (0, (5, 1))),
355+
356+
('loosely dashdotted', (0, (3, 10, 1, 10))),
357+
('dashdotted', (0, (3, 5, 1, 5))),
358+
('densely dashdotted', (0, (3, 1, 1, 1))),
359+
360+
('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
361+
('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
362+
('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))]
363+
364+
365+
def plot_linestyles(ax, linestyles, title):
366+
X, Y = np.linspace(0, 100, 10), np.zeros(10)
367+
yticklabels = []
368+
369+
for i, (name, linestyle) in enumerate(linestyles):
370+
ax.plot(X, Y+i, linestyle=linestyle, linewidth=1.5, color='black')
371+
yticklabels.append(name)
372+
373+
ax.set_title(title)
374+
ax.set(ylim=(-0.5, len(linestyles)-0.5),
375+
yticks=np.arange(len(linestyles)),
376+
yticklabels=yticklabels)
377+
ax.tick_params(left=False, bottom=False, labelbottom=False)
378+
for spine in ax.spines.values():
379+
spine.set_visible(False)
380+
381+
# For each line style, add a text annotation with a small offset from
382+
# the reference point (0 in Axes coords, y tick value in Data coords).
383+
for i, (name, linestyle) in enumerate(linestyles):
384+
ax.annotate(repr(linestyle),
385+
xy=(0.0, i), xycoords=ax.get_yaxis_transform(),
386+
xytext=(-6, -12), textcoords='offset points',
387+
color="blue", fontsize=8, ha="right", family="monospace")
388+
389+
390+
ax0, ax1 = (plt.figure(figsize=(10, 8))
391+
.add_gridspec(2, 1, height_ratios=[1, 3])
392+
.subplots())
393+
394+
plot_linestyles(ax0, linestyle_str[::-1], title='Named linestyles')
395+
plot_linestyles(ax1, linestyle_tuple[::-1], title='Parametrized linestyles')
396+
397+
plt.tight_layout()
398+
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
@@ -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

0 commit comments

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