Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/matplotlib/rcsetup.py : 54%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2The rcsetup module contains the default values and the validation code for
3customization using matplotlib's rc settings.
5Each rc setting is assigned a default value and a function used to validate
6any attempted changes to that setting. The default values and validation
7functions are defined in the rcsetup module, and are used to construct the
8rcParams global object which stores the settings and is referenced throughout
9matplotlib.
11These default values should be consistent with the default matplotlibrc file
12that actually reflects the values given here. Any additions or deletions to the
13parameter set listed here should also be visited to the
14:file:`matplotlibrc.template` in matplotlib's root source directory.
15"""
17from collections.abc import Iterable, Mapping
18from functools import partial, reduce
19import logging
20import operator
21import os
22import re
24import matplotlib as mpl
25from matplotlib import cbook
26from matplotlib.cbook import ls_mapper
27from matplotlib.fontconfig_pattern import parse_fontconfig_pattern
28from matplotlib.colors import is_color_like
30# Don't let the original cycler collide with our validating cycler
31from cycler import Cycler, cycler as ccycler
34_log = logging.getLogger(__name__)
35# The capitalized forms are needed for ipython at present; this may
36# change for later versions.
37interactive_bk = ['GTK3Agg', 'GTK3Cairo',
38 'MacOSX',
39 'nbAgg',
40 'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo',
41 'TkAgg', 'TkCairo',
42 'WebAgg',
43 'WX', 'WXAgg', 'WXCairo']
44non_interactive_bk = ['agg', 'cairo',
45 'pdf', 'pgf', 'ps', 'svg', 'template']
46all_backends = interactive_bk + non_interactive_bk
49class ValidateInStrings:
50 def __init__(self, key, valid, ignorecase=False):
51 'valid is a list of legal strings'
52 self.key = key
53 self.ignorecase = ignorecase
55 def func(s):
56 if ignorecase:
57 return s.lower()
58 else:
59 return s
60 self.valid = {func(k): k for k in valid}
62 def __call__(self, s):
63 if self.ignorecase:
64 s = s.lower()
65 if s in self.valid:
66 return self.valid[s]
67 raise ValueError('Unrecognized %s string %r: valid strings are %s'
68 % (self.key, s, list(self.valid.values())))
71def _listify_validator(scalar_validator, allow_stringlist=False, *, doc=None):
72 def f(s):
73 if isinstance(s, str):
74 try:
75 return [scalar_validator(v.strip()) for v in s.split(',')
76 if v.strip()]
77 except Exception:
78 if allow_stringlist:
79 # Sometimes, a list of colors might be a single string
80 # of single-letter colornames. So give that a shot.
81 return [scalar_validator(v.strip())
82 for v in s if v.strip()]
83 else:
84 raise
85 # We should allow any generic sequence type, including generators,
86 # Numpy ndarrays, and pandas data structures. However, unordered
87 # sequences, such as sets, should be allowed but discouraged unless the
88 # user desires pseudorandom behavior.
89 elif isinstance(s, Iterable) and not isinstance(s, Mapping):
90 # The condition on this list comprehension will preserve the
91 # behavior of filtering out any empty strings (behavior was
92 # from the original validate_stringlist()), while allowing
93 # any non-string/text scalar values such as numbers and arrays.
94 return [scalar_validator(v) for v in s
95 if not isinstance(v, str) or v]
96 else:
97 raise ValueError("{!r} must be of type: str or non-dictionary "
98 "iterable".format(s))
99 try:
100 f.__name__ = "{}list".format(scalar_validator.__name__)
101 except AttributeError: # class instance.
102 f.__name__ = "{}List".format(type(scalar_validator).__name__)
103 f.__doc__ = doc if doc is not None else scalar_validator.__doc__
104 return f
107def validate_any(s):
108 return s
109validate_anylist = _listify_validator(validate_any)
112@cbook.deprecated("3.2", alternative="os.path.exists")
113def validate_path_exists(s):
114 """If s is a path, return s, else False"""
115 if s is None:
116 return None
117 if os.path.exists(s):
118 return s
119 else:
120 raise RuntimeError('"%s" should be a path but it does not exist' % s)
123def validate_bool(b):
124 """Convert b to a boolean or raise"""
125 if isinstance(b, str):
126 b = b.lower()
127 if b in ('t', 'y', 'yes', 'on', 'true', '1', 1, True):
128 return True
129 elif b in ('f', 'n', 'no', 'off', 'false', '0', 0, False):
130 return False
131 else:
132 raise ValueError('Could not convert "%s" to boolean' % b)
135def validate_bool_maybe_none(b):
136 """Convert b to a boolean or raise."""
137 if isinstance(b, str):
138 b = b.lower()
139 if b is None or b == 'none':
140 return None
141 if b in ('t', 'y', 'yes', 'on', 'true', '1', 1, True):
142 return True
143 elif b in ('f', 'n', 'no', 'off', 'false', '0', 0, False):
144 return False
145 else:
146 raise ValueError('Could not convert "%s" to boolean' % b)
149def _validate_tex_preamble(s):
150 if s is None or s == 'None':
151 return ""
152 try:
153 if isinstance(s, str):
154 return s
155 elif isinstance(s, Iterable):
156 return '\n'.join(s)
157 else:
158 raise TypeError
159 except TypeError:
160 raise ValueError('Could not convert "%s" to string' % s)
163def validate_axisbelow(s):
164 try:
165 return validate_bool(s)
166 except ValueError:
167 if isinstance(s, str):
168 s = s.lower()
169 if s.startswith('line'):
170 return 'line'
171 raise ValueError('%s cannot be interpreted as'
172 ' True, False, or "line"' % s)
175def validate_dpi(s):
176 """Confirm s is string 'figure' or convert s to float or raise."""
177 if s == 'figure':
178 return s
179 try:
180 return float(s)
181 except ValueError:
182 raise ValueError('"%s" is not string "figure" or'
183 ' could not convert "%s" to float' % (s, s))
186def _make_type_validator(cls, *, allow_none=False):
187 """
188 Return a validator that converts inputs to *cls* or raises (and possibly
189 allows ``None`` as well).
190 """
192 def validator(s):
193 if (allow_none and
194 (s is None or isinstance(s, str) and s.lower() == "none")):
195 return None
196 try:
197 return cls(s)
198 except ValueError:
199 raise ValueError(f'Could not convert {s!r} to {cls.__name__}')
201 return validator
204validate_string = _make_type_validator(str)
205validate_string_or_None = _make_type_validator(str, allow_none=True)
206validate_stringlist = _listify_validator(
207 validate_string, doc='return a list or strings')
208validate_int = _make_type_validator(int)
209validate_int_or_None = _make_type_validator(int, allow_none=True)
210validate_float = _make_type_validator(float)
211validate_float_or_None = _make_type_validator(float, allow_none=True)
212validate_floatlist = _listify_validator(
213 validate_float, doc='return a list of floats')
216def validate_fonttype(s):
217 """
218 Confirm that this is a Postscript or PDF font type that we know how to
219 convert to.
220 """
221 fonttypes = {'type3': 3,
222 'truetype': 42}
223 try:
224 fonttype = validate_int(s)
225 except ValueError:
226 try:
227 return fonttypes[s.lower()]
228 except KeyError:
229 raise ValueError(
230 'Supported Postscript/PDF font types are %s' % list(fonttypes))
231 else:
232 if fonttype not in fonttypes.values():
233 raise ValueError(
234 'Supported Postscript/PDF font types are %s' %
235 list(fonttypes.values()))
236 return fonttype
239_validate_standard_backends = ValidateInStrings(
240 'backend', all_backends, ignorecase=True)
241_auto_backend_sentinel = object()
244def validate_backend(s):
245 backend = (
246 s if s is _auto_backend_sentinel or s.startswith("module://")
247 else _validate_standard_backends(s))
248 return backend
251@cbook.deprecated("3.1")
252def validate_qt4(s):
253 if s is None:
254 return None
255 return ValidateInStrings("backend.qt4", ['PyQt4', 'PySide', 'PyQt4v2'])(s)
258@cbook.deprecated("3.1")
259def validate_qt5(s):
260 if s is None:
261 return None
262 return ValidateInStrings("backend.qt5", ['PyQt5', 'PySide2'])(s)
265validate_toolbar = ValidateInStrings(
266 'toolbar', ['None', 'toolbar2', 'toolmanager'], ignorecase=True)
269def _make_nseq_validator(cls, n=None, allow_none=False):
271 def validator(s):
272 """Convert *n* objects using ``cls``, or raise."""
273 if isinstance(s, str):
274 s = [x.strip() for x in s.split(',')]
275 if n is not None and len(s) != n:
276 raise ValueError(
277 f'Expected exactly {n} comma-separated values, '
278 f'but got {len(s)} comma-separated values: {s}')
279 else:
280 if n is not None and len(s) != n:
281 raise ValueError(
282 f'Expected exactly {n} values, '
283 f'but got {len(s)} values: {s}')
284 try:
285 return [cls(val) if not allow_none or val is not None else val
286 for val in s]
287 except ValueError:
288 raise ValueError(
289 f'Could not convert all entries to {cls.__name__}s')
291 return validator
294validate_nseq_float = partial(_make_nseq_validator, float)
295validate_nseq_int = partial(_make_nseq_validator, int)
298def validate_color_or_inherit(s):
299 """Return a valid color arg."""
300 if s == 'inherit':
301 return s
302 return validate_color(s)
305def validate_color_or_auto(s):
306 if s == 'auto':
307 return s
308 return validate_color(s)
311def validate_color_for_prop_cycle(s):
312 # Special-case the N-th color cycle syntax, this obviously can not
313 # go in the color cycle.
314 if isinstance(s, bytes):
315 match = re.match(b'^C[0-9]$', s)
316 if match is not None:
317 raise ValueError('Can not put cycle reference ({cn!r}) in '
318 'prop_cycler'.format(cn=s))
319 elif isinstance(s, str):
320 match = re.match('^C[0-9]$', s)
321 if match is not None:
322 raise ValueError('Can not put cycle reference ({cn!r}) in '
323 'prop_cycler'.format(cn=s))
324 return validate_color(s)
327def validate_color(s):
328 """Return a valid color arg."""
329 try:
330 if s.lower() == 'none':
331 return 'none'
332 except AttributeError:
333 pass
335 if isinstance(s, str):
336 if len(s) == 6 or len(s) == 8:
337 stmp = '#' + s
338 if is_color_like(stmp):
339 return stmp
341 if is_color_like(s):
342 return s
344 # If it is still valid, it must be a tuple.
345 colorarg = s
346 msg = ''
347 if s.find(',') >= 0:
348 # get rid of grouping symbols
349 stmp = ''.join([c for c in s if c.isdigit() or c == '.' or c == ','])
350 vals = stmp.split(',')
351 if len(vals) not in [3, 4]:
352 msg = '\nColor tuples must be of length 3 or 4'
353 else:
354 try:
355 colorarg = [float(val) for val in vals]
356 except ValueError:
357 msg = '\nCould not convert all entries to floats'
359 if not msg and is_color_like(colorarg):
360 return colorarg
362 raise ValueError('%s does not look like a color arg%s' % (s, msg))
365validate_colorlist = _listify_validator(
366 validate_color, allow_stringlist=True, doc='return a list of colorspecs')
367validate_orientation = ValidateInStrings(
368 'orientation', ['landscape', 'portrait'])
371def validate_aspect(s):
372 if s in ('auto', 'equal'):
373 return s
374 try:
375 return float(s)
376 except ValueError:
377 raise ValueError('not a valid aspect specification')
380def validate_fontsize_None(s):
381 if s is None or s == 'None':
382 return None
383 else:
384 return validate_fontsize(s)
387def validate_fontsize(s):
388 fontsizes = ['xx-small', 'x-small', 'small', 'medium', 'large',
389 'x-large', 'xx-large', 'smaller', 'larger']
390 if isinstance(s, str):
391 s = s.lower()
392 if s in fontsizes:
393 return s
394 try:
395 return float(s)
396 except ValueError:
397 raise ValueError("%s is not a valid font size. Valid font sizes "
398 "are %s." % (s, ", ".join(fontsizes)))
401validate_fontsizelist = _listify_validator(validate_fontsize)
404def validate_fontweight(s):
405 weights = [
406 'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman',
407 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black']
408 # Note: Historically, weights have been case-sensitive in Matplotlib
409 if s in weights:
410 return s
411 try:
412 return int(s)
413 except (ValueError, TypeError):
414 raise ValueError(f'{s} is not a valid font weight.')
417def validate_font_properties(s):
418 parse_fontconfig_pattern(s)
419 return s
422validate_fontset = ValidateInStrings(
423 'fontset',
424 ['dejavusans', 'dejavuserif', 'cm', 'stix', 'stixsans', 'custom'])
427def validate_mathtext_default(s):
428 if s == "circled":
429 cbook.warn_deprecated(
430 "3.1", message="Support for setting the mathtext.default rcParam "
431 "to 'circled' is deprecated since %(since)s and will be removed "
432 "%(removal)s.")
433 return ValidateInStrings(
434 'default',
435 "rm cal it tt sf bf default bb frak circled scr regular".split())(s)
438_validate_alignment = ValidateInStrings(
439 'alignment',
440 ['center', 'top', 'bottom', 'baseline',
441 'center_baseline'])
444_validate_verbose = ValidateInStrings(
445 'verbose',
446 ['silent', 'helpful', 'debug', 'debug-annoying'])
449@cbook.deprecated("3.1")
450def validate_verbose(s):
451 return _validate_verbose(s)
454def validate_whiskers(s):
455 if s == 'range':
456 cbook.warn_deprecated(
457 "3.2", message="Support for setting the boxplot.whiskers rcParam "
458 "to 'range' is deprecated since %(since)s and will be removed "
459 "%(removal)s; set it to 0, 100 instead.")
460 return 'range'
461 else:
462 try:
463 v = validate_nseq_float(2)(s)
464 return v
465 except (TypeError, ValueError):
466 try:
467 v = float(s)
468 return v
469 except ValueError:
470 raise ValueError("Not a valid whisker value ['range', float, "
471 "(float, float)]")
474@cbook.deprecated("3.2")
475def update_savefig_format(value):
476 # The old savefig.extension could also have a value of "auto", but
477 # the new savefig.format does not. We need to fix this here.
478 value = validate_string(value)
479 if value == 'auto':
480 cbook.warn_deprecated(
481 "3.2", message="Support for setting the 'savefig.format' rcParam "
482 "to 'auto' is deprecated since %(since)s and will be removed "
483 "%(removal)s; set it to 'png' instead.")
484 value = 'png'
485 return value
488# Replace by validate_string once deprecation period passes.
489def _update_savefig_format(value):
490 # The old savefig.extension could also have a value of "auto", but
491 # the new savefig.format does not. We need to fix this here.
492 value = validate_string(value)
493 if value == 'auto':
494 cbook.warn_deprecated(
495 "3.2", message="Support for setting the 'savefig.format' rcParam "
496 "to 'auto' is deprecated since %(since)s and will be removed "
497 "%(removal)s; set it to 'png' instead.")
498 value = 'png'
499 return value
502validate_ps_papersize = ValidateInStrings(
503 'ps_papersize',
504 ['auto', 'letter', 'legal', 'ledger',
505 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'a10',
506 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'b10',
507 ], ignorecase=True)
510def validate_ps_distiller(s):
511 if isinstance(s, str):
512 s = s.lower()
513 if s in ('none', None, 'false', False):
514 return None
515 elif s in ('ghostscript', 'xpdf'):
516 try:
517 mpl._get_executable_info("gs")
518 except mpl.ExecutableNotFoundError:
519 _log.warning("Setting rcParams['ps.usedistiller'] requires "
520 "ghostscript.")
521 return None
522 if s == "xpdf":
523 try:
524 mpl._get_executable_info("pdftops")
525 except mpl.ExecutableNotFoundError:
526 _log.warning("Setting rcParams['ps.usedistiller'] to 'xpdf' "
527 "requires xpdf.")
528 return None
529 return s
530 else:
531 raise ValueError('matplotlibrc ps.usedistiller must either be none, '
532 'ghostscript or xpdf')
535validate_joinstyle = ValidateInStrings('joinstyle',
536 ['miter', 'round', 'bevel'],
537 ignorecase=True)
538validate_joinstylelist = _listify_validator(validate_joinstyle)
540validate_capstyle = ValidateInStrings('capstyle',
541 ['butt', 'round', 'projecting'],
542 ignorecase=True)
543validate_capstylelist = _listify_validator(validate_capstyle)
545validate_fillstyle = ValidateInStrings('markers.fillstyle',
546 ['full', 'left', 'right', 'bottom',
547 'top', 'none'])
548validate_fillstylelist = _listify_validator(validate_fillstyle)
551def validate_markevery(s):
552 """
553 Validate the markevery property of a Line2D object.
555 Parameters
556 ----------
557 s : None, int, float, slice, length-2 tuple of ints,
558 length-2 tuple of floats, list of ints
560 Returns
561 -------
562 s : None, int, float, slice, length-2 tuple of ints,
563 length-2 tuple of floats, list of ints
565 """
566 # Validate s against type slice float int and None
567 if isinstance(s, (slice, float, int, type(None))):
568 return s
569 # Validate s against type tuple
570 if isinstance(s, tuple):
571 if (len(s) == 2
572 and (all(isinstance(e, int) for e in s)
573 or all(isinstance(e, float) for e in s))):
574 return s
575 else:
576 raise TypeError(
577 "'markevery' tuple must be pair of ints or of floats")
578 # Validate s against type list
579 if isinstance(s, list):
580 if all(isinstance(e, int) for e in s):
581 return s
582 else:
583 raise TypeError(
584 "'markevery' list must have all elements of type int")
585 raise TypeError("'markevery' is of an invalid type")
588validate_markeverylist = _listify_validator(validate_markevery)
590validate_legend_loc = ValidateInStrings(
591 'legend_loc',
592 ['best',
593 'upper right',
594 'upper left',
595 'lower left',
596 'lower right',
597 'right',
598 'center left',
599 'center right',
600 'lower center',
601 'upper center',
602 'center'], ignorecase=True)
604validate_svg_fonttype = ValidateInStrings('svg.fonttype', ['none', 'path'])
607def validate_hinting(s):
608 if s in (True, False):
609 cbook.warn_deprecated(
610 "3.2", message="Support for setting the text.hinting rcParam to "
611 "True or False is deprecated since %(since)s and will be removed "
612 "%(removal)s; set it to its synonyms 'auto' or 'none' instead.")
613 return s
614 if s.lower() in ('auto', 'native', 'either', 'none'):
615 return s.lower()
616 raise ValueError("hinting should be 'auto', 'native', 'either' or 'none'")
619validate_pgf_texsystem = ValidateInStrings('pgf.texsystem',
620 ['xelatex', 'lualatex', 'pdflatex'])
622validate_movie_writer = ValidateInStrings('animation.writer',
623 ['ffmpeg', 'ffmpeg_file',
624 'avconv', 'avconv_file',
625 'imagemagick', 'imagemagick_file',
626 'html'])
628validate_movie_frame_fmt = ValidateInStrings('animation.frame_format',
629 ['png', 'jpeg', 'tiff', 'raw', 'rgba'])
631validate_axis_locator = ValidateInStrings('major', ['minor', 'both', 'major'])
633validate_movie_html_fmt = ValidateInStrings('animation.html',
634 ['html5', 'jshtml', 'none'])
637def validate_bbox(s):
638 if isinstance(s, str):
639 s = s.lower()
640 if s == 'tight':
641 return s
642 if s == 'standard':
643 return None
644 raise ValueError("bbox should be 'tight' or 'standard'")
645 elif s is not None:
646 # Backwards compatibility. None is equivalent to 'standard'.
647 raise ValueError("bbox should be 'tight' or 'standard'")
648 return s
651def validate_sketch(s):
652 if isinstance(s, str):
653 s = s.lower()
654 if s == 'none' or s is None:
655 return None
656 if isinstance(s, str):
657 result = tuple([float(v.strip()) for v in s.split(',')])
658 elif isinstance(s, (list, tuple)):
659 result = tuple([float(v) for v in s])
660 if len(result) != 3:
661 raise ValueError("path.sketch must be a tuple (scale, length, randomness)")
662 return result
665@cbook.deprecated("3.2")
666class ValidateInterval:
667 """
668 Value must be in interval
669 """
670 def __init__(self, vmin, vmax, closedmin=True, closedmax=True):
671 self.vmin = vmin
672 self.vmax = vmax
673 self.cmin = closedmin
674 self.cmax = closedmax
676 def __call__(self, s):
677 try:
678 s = float(s)
679 except ValueError:
680 raise RuntimeError('Value must be a float; found "%s"' % s)
682 if self.cmin and s < self.vmin:
683 raise RuntimeError('Value must be >= %f; found "%f"' %
684 (self.vmin, s))
685 elif not self.cmin and s <= self.vmin:
686 raise RuntimeError('Value must be > %f; found "%f"' %
687 (self.vmin, s))
689 if self.cmax and s > self.vmax:
690 raise RuntimeError('Value must be <= %f; found "%f"' %
691 (self.vmax, s))
692 elif not self.cmax and s >= self.vmax:
693 raise RuntimeError('Value must be < %f; found "%f"' %
694 (self.vmax, s))
695 return s
698def _validate_greaterequal0_lessthan1(s):
699 s = validate_float(s)
700 if 0 <= s < 1:
701 return s
702 else:
703 raise RuntimeError(f'Value must be >=0 and <1; got {s}')
706def _validate_greaterequal0_lessequal1(s):
707 s = validate_float(s)
708 if 0 <= s <= 1:
709 return s
710 else:
711 raise RuntimeError(f'Value must be >=0 and <=1; got {s}')
714_range_validators = { # Slightly nicer (internal) API.
715 "0 <= x < 1": _validate_greaterequal0_lessthan1,
716 "0 <= x <= 1": _validate_greaterequal0_lessequal1,
717}
720validate_grid_axis = ValidateInStrings('axes.grid.axis', ['x', 'y', 'both'])
723def validate_hatch(s):
724 r"""
725 Validate a hatch pattern.
726 A hatch pattern string can have any sequence of the following
727 characters: ``\ / | - + * . x o O``.
728 """
729 if not isinstance(s, str):
730 raise ValueError("Hatch pattern must be a string")
731 cbook._check_isinstance(str, hatch_pattern=s)
732 unknown = set(s) - {'\\', '/', '|', '-', '+', '*', '.', 'x', 'o', 'O'}
733 if unknown:
734 raise ValueError("Unknown hatch symbol(s): %s" % list(unknown))
735 return s
738validate_hatchlist = _listify_validator(validate_hatch)
739validate_dashlist = _listify_validator(validate_nseq_float(allow_none=True))
742_prop_validators = {
743 'color': _listify_validator(validate_color_for_prop_cycle,
744 allow_stringlist=True),
745 'linewidth': validate_floatlist,
746 'linestyle': validate_stringlist,
747 'facecolor': validate_colorlist,
748 'edgecolor': validate_colorlist,
749 'joinstyle': validate_joinstylelist,
750 'capstyle': validate_capstylelist,
751 'fillstyle': validate_fillstylelist,
752 'markerfacecolor': validate_colorlist,
753 'markersize': validate_floatlist,
754 'markeredgewidth': validate_floatlist,
755 'markeredgecolor': validate_colorlist,
756 'markevery': validate_markeverylist,
757 'alpha': validate_floatlist,
758 'marker': validate_stringlist,
759 'hatch': validate_hatchlist,
760 'dashes': validate_dashlist,
761 }
762_prop_aliases = {
763 'c': 'color',
764 'lw': 'linewidth',
765 'ls': 'linestyle',
766 'fc': 'facecolor',
767 'ec': 'edgecolor',
768 'mfc': 'markerfacecolor',
769 'mec': 'markeredgecolor',
770 'mew': 'markeredgewidth',
771 'ms': 'markersize',
772 }
775def cycler(*args, **kwargs):
776 """
777 Creates a `~cycler.Cycler` object much like :func:`cycler.cycler`,
778 but includes input validation.
780 Call signatures::
782 cycler(cycler)
783 cycler(label=values[, label2=values2[, ...]])
784 cycler(label, values)
786 Form 1 copies a given `~cycler.Cycler` object.
788 Form 2 creates a `~cycler.Cycler` which cycles over one or more
789 properties simultaneously. If multiple properties are given, their
790 value lists must have the same length.
792 Form 3 creates a `~cycler.Cycler` for a single property. This form
793 exists for compatibility with the original cycler. Its use is
794 discouraged in favor of the kwarg form, i.e. ``cycler(label=values)``.
796 Parameters
797 ----------
798 cycler : Cycler
799 Copy constructor for Cycler.
801 label : str
802 The property key. Must be a valid `.Artist` property.
803 For example, 'color' or 'linestyle'. Aliases are allowed,
804 such as 'c' for 'color' and 'lw' for 'linewidth'.
806 values : iterable
807 Finite-length iterable of the property values. These values
808 are validated and will raise a ValueError if invalid.
810 Returns
811 -------
812 cycler : Cycler
813 A new :class:`~cycler.Cycler` for the given properties.
815 Examples
816 --------
817 Creating a cycler for a single property:
819 >>> c = cycler(color=['red', 'green', 'blue'])
821 Creating a cycler for simultaneously cycling over multiple properties
822 (e.g. red circle, green plus, blue cross):
824 >>> c = cycler(color=['red', 'green', 'blue'],
825 ... marker=['o', '+', 'x'])
827 """
828 if args and kwargs:
829 raise TypeError("cycler() can only accept positional OR keyword "
830 "arguments -- not both.")
831 elif not args and not kwargs:
832 raise TypeError("cycler() must have positional OR keyword arguments")
834 if len(args) == 1:
835 if not isinstance(args[0], Cycler):
836 raise TypeError("If only one positional argument given, it must "
837 " be a Cycler instance.")
838 return validate_cycler(args[0])
839 elif len(args) == 2:
840 pairs = [(args[0], args[1])]
841 elif len(args) > 2:
842 raise TypeError("No more than 2 positional arguments allowed")
843 else:
844 pairs = kwargs.items()
846 validated = []
847 for prop, vals in pairs:
848 norm_prop = _prop_aliases.get(prop, prop)
849 validator = _prop_validators.get(norm_prop, None)
850 if validator is None:
851 raise TypeError("Unknown artist property: %s" % prop)
852 vals = validator(vals)
853 # We will normalize the property names as well to reduce
854 # the amount of alias handling code elsewhere.
855 validated.append((norm_prop, vals))
857 return reduce(operator.add, (ccycler(k, v) for k, v in validated))
860def validate_cycler(s):
861 """Return a Cycler object from a string repr or the object itself."""
862 if isinstance(s, str):
863 try:
864 # TODO: We might want to rethink this...
865 # While I think I have it quite locked down,
866 # it is execution of arbitrary code without
867 # sanitation.
868 # Combine this with the possibility that rcparams
869 # might come from the internet (future plans), this
870 # could be downright dangerous.
871 # I locked it down by only having the 'cycler()' function
872 # available.
873 # UPDATE: Partly plugging a security hole.
874 # I really should have read this:
875 # http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
876 # We should replace this eval with a combo of PyParsing and
877 # ast.literal_eval()
878 if '.__' in s.replace(' ', ''):
879 raise ValueError("'%s' seems to have dunder methods. Raising"
880 " an exception for your safety")
881 s = eval(s, {'cycler': cycler, '__builtins__': {}})
882 except BaseException as e:
883 raise ValueError("'%s' is not a valid cycler construction: %s" %
884 (s, e))
885 # Should make sure what comes from the above eval()
886 # is a Cycler object.
887 if isinstance(s, Cycler):
888 cycler_inst = s
889 else:
890 raise ValueError("object was not a string or Cycler instance: %s" % s)
892 unknowns = cycler_inst.keys - (set(_prop_validators) | set(_prop_aliases))
893 if unknowns:
894 raise ValueError("Unknown artist properties: %s" % unknowns)
896 # Not a full validation, but it'll at least normalize property names
897 # A fuller validation would require v0.10 of cycler.
898 checker = set()
899 for prop in cycler_inst.keys:
900 norm_prop = _prop_aliases.get(prop, prop)
901 if norm_prop != prop and norm_prop in cycler_inst.keys:
902 raise ValueError("Cannot specify both '{0}' and alias '{1}'"
903 " in the same prop_cycle".format(norm_prop, prop))
904 if norm_prop in checker:
905 raise ValueError("Another property was already aliased to '{0}'."
906 " Collision normalizing '{1}'.".format(norm_prop,
907 prop))
908 checker.update([norm_prop])
910 # This is just an extra-careful check, just in case there is some
911 # edge-case I haven't thought of.
912 assert len(checker) == len(cycler_inst.keys)
914 # Now, it should be safe to mutate this cycler
915 for prop in cycler_inst.keys:
916 norm_prop = _prop_aliases.get(prop, prop)
917 cycler_inst.change_key(prop, norm_prop)
919 for key, vals in cycler_inst.by_key().items():
920 _prop_validators[key](vals)
922 return cycler_inst
925def validate_hist_bins(s):
926 valid_strs = ["auto", "sturges", "fd", "doane", "scott", "rice", "sqrt"]
927 if isinstance(s, str) and s in valid_strs:
928 return s
929 try:
930 return int(s)
931 except (TypeError, ValueError):
932 pass
933 try:
934 return validate_floatlist(s)
935 except ValueError:
936 pass
937 raise ValueError("'hist.bins' must be one of {}, an int or"
938 " a sequence of floats".format(valid_strs))
941@cbook.deprecated("3.2")
942def validate_animation_writer_path(p):
943 # Make sure it's a string and then figure out if the animations
944 # are already loaded and reset the writers (which will validate
945 # the path on next call)
946 cbook._check_isinstance(str, path=p)
947 from sys import modules
948 # set dirty, so that the next call to the registry will re-evaluate
949 # the state.
950 # only set dirty if already loaded. If not loaded, the load will
951 # trigger the checks.
952 if "matplotlib.animation" in modules:
953 modules["matplotlib.animation"].writers.set_dirty()
954 return p
957def validate_webagg_address(s):
958 if s is not None:
959 import socket
960 try:
961 socket.inet_aton(s)
962 except socket.error:
963 raise ValueError("'webagg.address' is not a valid IP address")
964 return s
965 raise ValueError("'webagg.address' is not a valid IP address")
968# A validator dedicated to the named line styles, based on the items in
969# ls_mapper, and a list of possible strings read from Line2D.set_linestyle
970_validate_named_linestyle = ValidateInStrings(
971 'linestyle',
972 [*ls_mapper.keys(), *ls_mapper.values(), 'None', 'none', ' ', ''],
973 ignorecase=True)
976def _validate_linestyle(ls):
977 """
978 A validator for all possible line styles, the named ones *and*
979 the on-off ink sequences.
980 """
981 # Look first for a valid named line style, like '--' or 'solid' Also
982 # includes bytes(-arrays) here (they all fail _validate_named_linestyle);
983 # otherwise, if *ls* is of even-length, it will be passed to the instance
984 # of validate_nseq_float, which will return an absurd on-off ink
985 # sequence...
986 if isinstance(ls, (str, bytes, bytearray)):
987 return _validate_named_linestyle(ls)
989 # Look for an on-off ink sequence (in points) *of even length*.
990 # Offset is set to None.
991 try:
992 if len(ls) % 2 != 0:
993 raise ValueError("the linestyle sequence {!r} is not of even "
994 "length.".format(ls))
996 return (None, validate_nseq_float()(ls))
998 except (ValueError, TypeError):
999 # TypeError can be raised inside the instance of validate_nseq_float,
1000 # by wrong types passed to float(), like NoneType.
1001 raise ValueError("linestyle {!r} is not a valid on-off ink "
1002 "sequence.".format(ls))
1005validate_axes_titlelocation = ValidateInStrings('axes.titlelocation', ['left', 'center', 'right'])
1007# a map from key -> value, converter
1008defaultParams = {
1009 'backend': [_auto_backend_sentinel, validate_backend],
1010 'backend_fallback': [True, validate_bool],
1011 'webagg.port': [8988, validate_int],
1012 'webagg.address': ['127.0.0.1', validate_webagg_address],
1013 'webagg.open_in_browser': [True, validate_bool],
1014 'webagg.port_retries': [50, validate_int],
1015 'toolbar': ['toolbar2', validate_toolbar],
1016 'datapath': [None, validate_any], # see _get_data_path_cached
1017 'interactive': [False, validate_bool],
1018 'timezone': ['UTC', validate_string],
1020 # the verbosity setting
1021 'verbose.level': ['silent', _validate_verbose],
1022 'verbose.fileo': ['sys.stdout', validate_string],
1024 # line props
1025 'lines.linewidth': [1.5, validate_float], # line width in points
1026 'lines.linestyle': ['-', _validate_linestyle], # solid line
1027 'lines.color': ['C0', validate_color], # first color in color cycle
1028 'lines.marker': ['None', validate_string], # marker name
1029 'lines.markerfacecolor': ['auto', validate_color_or_auto], # default color
1030 'lines.markeredgecolor': ['auto', validate_color_or_auto], # default color
1031 'lines.markeredgewidth': [1.0, validate_float],
1032 'lines.markersize': [6, validate_float], # markersize, in points
1033 'lines.antialiased': [True, validate_bool], # antialiased (no jaggies)
1034 'lines.dash_joinstyle': ['round', validate_joinstyle],
1035 'lines.solid_joinstyle': ['round', validate_joinstyle],
1036 'lines.dash_capstyle': ['butt', validate_capstyle],
1037 'lines.solid_capstyle': ['projecting', validate_capstyle],
1038 'lines.dashed_pattern': [[3.7, 1.6], validate_nseq_float(allow_none=True)],
1039 'lines.dashdot_pattern': [[6.4, 1.6, 1, 1.6],
1040 validate_nseq_float(allow_none=True)],
1041 'lines.dotted_pattern': [[1, 1.65], validate_nseq_float(allow_none=True)],
1042 'lines.scale_dashes': [True, validate_bool],
1044 # marker props
1045 'markers.fillstyle': ['full', validate_fillstyle],
1047 ## patch props
1048 'patch.linewidth': [1.0, validate_float], # line width in points
1049 'patch.edgecolor': ['black', validate_color],
1050 'patch.force_edgecolor': [False, validate_bool],
1051 'patch.facecolor': ['C0', validate_color], # first color in cycle
1052 'patch.antialiased': [True, validate_bool], # antialiased (no jaggies)
1054 ## hatch props
1055 'hatch.color': ['black', validate_color],
1056 'hatch.linewidth': [1.0, validate_float],
1058 ## Histogram properties
1059 'hist.bins': [10, validate_hist_bins],
1061 ## Boxplot properties
1062 'boxplot.notch': [False, validate_bool],
1063 'boxplot.vertical': [True, validate_bool],
1064 'boxplot.whiskers': [1.5, validate_whiskers],
1065 'boxplot.bootstrap': [None, validate_int_or_None],
1066 'boxplot.patchartist': [False, validate_bool],
1067 'boxplot.showmeans': [False, validate_bool],
1068 'boxplot.showcaps': [True, validate_bool],
1069 'boxplot.showbox': [True, validate_bool],
1070 'boxplot.showfliers': [True, validate_bool],
1071 'boxplot.meanline': [False, validate_bool],
1073 'boxplot.flierprops.color': ['black', validate_color],
1074 'boxplot.flierprops.marker': ['o', validate_string],
1075 'boxplot.flierprops.markerfacecolor': ['none', validate_color_or_auto],
1076 'boxplot.flierprops.markeredgecolor': ['black', validate_color],
1077 'boxplot.flierprops.markeredgewidth': [1.0, validate_float],
1078 'boxplot.flierprops.markersize': [6, validate_float],
1079 'boxplot.flierprops.linestyle': ['none', _validate_linestyle],
1080 'boxplot.flierprops.linewidth': [1.0, validate_float],
1082 'boxplot.boxprops.color': ['black', validate_color],
1083 'boxplot.boxprops.linewidth': [1.0, validate_float],
1084 'boxplot.boxprops.linestyle': ['-', _validate_linestyle],
1086 'boxplot.whiskerprops.color': ['black', validate_color],
1087 'boxplot.whiskerprops.linewidth': [1.0, validate_float],
1088 'boxplot.whiskerprops.linestyle': ['-', _validate_linestyle],
1090 'boxplot.capprops.color': ['black', validate_color],
1091 'boxplot.capprops.linewidth': [1.0, validate_float],
1092 'boxplot.capprops.linestyle': ['-', _validate_linestyle],
1094 'boxplot.medianprops.color': ['C1', validate_color],
1095 'boxplot.medianprops.linewidth': [1.0, validate_float],
1096 'boxplot.medianprops.linestyle': ['-', _validate_linestyle],
1098 'boxplot.meanprops.color': ['C2', validate_color],
1099 'boxplot.meanprops.marker': ['^', validate_string],
1100 'boxplot.meanprops.markerfacecolor': ['C2', validate_color],
1101 'boxplot.meanprops.markeredgecolor': ['C2', validate_color],
1102 'boxplot.meanprops.markersize': [6, validate_float],
1103 'boxplot.meanprops.linestyle': ['--', _validate_linestyle],
1104 'boxplot.meanprops.linewidth': [1.0, validate_float],
1106 ## font props
1107 'font.family': [['sans-serif'], validate_stringlist], # used by text object
1108 'font.style': ['normal', validate_string],
1109 'font.variant': ['normal', validate_string],
1110 'font.stretch': ['normal', validate_string],
1111 'font.weight': ['normal', validate_fontweight],
1112 'font.size': [10, validate_float], # Base font size in points
1113 'font.serif': [['DejaVu Serif', 'Bitstream Vera Serif',
1114 'Computer Modern Roman',
1115 'New Century Schoolbook', 'Century Schoolbook L',
1116 'Utopia', 'ITC Bookman', 'Bookman',
1117 'Nimbus Roman No9 L', 'Times New Roman',
1118 'Times', 'Palatino', 'Charter', 'serif'],
1119 validate_stringlist],
1120 'font.sans-serif': [['DejaVu Sans', 'Bitstream Vera Sans',
1121 'Computer Modern Sans Serif',
1122 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid',
1123 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'],
1124 validate_stringlist],
1125 'font.cursive': [['Apple Chancery', 'Textile', 'Zapf Chancery',
1126 'Sand', 'Script MT', 'Felipa', 'cursive'],
1127 validate_stringlist],
1128 'font.fantasy': [['Comic Neue', 'Comic Sans MS', 'Chicago', 'Charcoal',
1129 'Impact', 'Western', 'Humor Sans', 'xkcd', 'fantasy'],
1130 validate_stringlist],
1131 'font.monospace': [['DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
1132 'Computer Modern Typewriter',
1133 'Andale Mono', 'Nimbus Mono L', 'Courier New',
1134 'Courier', 'Fixed', 'Terminal', 'monospace'],
1135 validate_stringlist],
1137 # text props
1138 'text.color': ['black', validate_color],
1139 'text.usetex': [False, validate_bool],
1140 'text.latex.unicode': [True, validate_bool],
1141 'text.latex.preamble': ['', _validate_tex_preamble],
1142 'text.latex.preview': [False, validate_bool],
1143 'text.hinting': ['auto', validate_hinting],
1144 'text.hinting_factor': [8, validate_int],
1145 'text.kerning_factor': [0, validate_int],
1146 'text.antialiased': [True, validate_bool],
1148 'mathtext.cal': ['cursive', validate_font_properties],
1149 'mathtext.rm': ['sans', validate_font_properties],
1150 'mathtext.tt': ['monospace', validate_font_properties],
1151 'mathtext.it': ['sans:italic', validate_font_properties],
1152 'mathtext.bf': ['sans:bold', validate_font_properties],
1153 'mathtext.sf': ['sans', validate_font_properties],
1154 'mathtext.fontset': ['dejavusans', validate_fontset],
1155 'mathtext.default': ['it', validate_mathtext_default],
1156 'mathtext.fallback_to_cm': [True, validate_bool],
1158 'image.aspect': ['equal', validate_aspect], # equal, auto, a number
1159 'image.interpolation': ['antialiased', validate_string],
1160 'image.cmap': ['viridis', validate_string], # gray, jet, etc.
1161 'image.lut': [256, validate_int], # lookup table
1162 'image.origin': ['upper',
1163 ValidateInStrings('image.origin', ['upper', 'lower'])],
1164 'image.resample': [True, validate_bool],
1165 # Specify whether vector graphics backends will combine all images on a
1166 # set of axes into a single composite image
1167 'image.composite_image': [True, validate_bool],
1169 # contour props
1170 'contour.negative_linestyle': ['dashed', _validate_linestyle],
1171 'contour.corner_mask': [True, validate_bool],
1173 # errorbar props
1174 'errorbar.capsize': [0, validate_float],
1176 # axes props
1177 'axes.axisbelow': ['line', validate_axisbelow],
1178 'axes.facecolor': ['white', validate_color], # background color
1179 'axes.edgecolor': ['black', validate_color], # edge color
1180 'axes.linewidth': [0.8, validate_float], # edge linewidth
1182 'axes.spines.left': [True, validate_bool], # Set visibility of axes
1183 'axes.spines.right': [True, validate_bool], # 'spines', the lines
1184 'axes.spines.bottom': [True, validate_bool], # around the chart
1185 'axes.spines.top': [True, validate_bool], # denoting data boundary
1187 'axes.titlesize': ['large', validate_fontsize], # fontsize of the
1188 # axes title
1189 'axes.titlelocation': ['center', validate_axes_titlelocation], # alignment of axes title
1190 'axes.titleweight': ['normal', validate_fontweight], # font weight of axes title
1191 'axes.titlecolor': ['auto', validate_color_or_auto], # font color of axes title
1192 'axes.titlepad': [6.0, validate_float], # pad from axes top to title in points
1193 'axes.grid': [False, validate_bool], # display grid or not
1194 'axes.grid.which': ['major', validate_axis_locator], # set whether the gid are by
1195 # default draw on 'major'
1196 # 'minor' or 'both' kind of
1197 # axis locator
1198 'axes.grid.axis': ['both', validate_grid_axis], # grid type:
1199 # 'x', 'y', or 'both'
1200 'axes.labelsize': ['medium', validate_fontsize], # fontsize of the
1201 # x any y labels
1202 'axes.labelpad': [4.0, validate_float], # space between label and axis
1203 'axes.labelweight': ['normal', validate_fontweight], # fontsize of the x any y labels
1204 'axes.labelcolor': ['black', validate_color], # color of axis label
1205 'axes.formatter.limits': [[-5, 6], validate_nseq_int(2)],
1206 # use scientific notation if log10
1207 # of the axis range is smaller than the
1208 # first or larger than the second
1209 'axes.formatter.use_locale': [False, validate_bool],
1210 # Use the current locale to format ticks
1211 'axes.formatter.use_mathtext': [False, validate_bool],
1212 'axes.formatter.min_exponent': [0, validate_int], # minimum exponent to format in scientific notation
1213 'axes.formatter.useoffset': [True, validate_bool],
1214 'axes.formatter.offset_threshold': [4, validate_int],
1215 'axes.unicode_minus': [True, validate_bool],
1216 # This entry can be either a cycler object or a
1217 # string repr of a cycler-object, which gets eval()'ed
1218 # to create the object.
1219 'axes.prop_cycle': [
1220 ccycler('color',
1221 ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
1222 '#9467bd', '#8c564b', '#e377c2', '#7f7f7f',
1223 '#bcbd22', '#17becf']),
1224 validate_cycler],
1225 # If 'data', axes limits are set close to the data.
1226 # If 'round_numbers' axes limits are set to the nearest round numbers.
1227 'axes.autolimit_mode': [
1228 'data',
1229 ValidateInStrings('autolimit_mode', ['data', 'round_numbers'])],
1230 'axes.xmargin': [0.05, _range_validators["0 <= x <= 1"]],
1231 'axes.ymargin': [0.05, _range_validators["0 <= x <= 1"]],
1233 'polaraxes.grid': [True, validate_bool], # display polar grid or not
1234 'axes3d.grid': [True, validate_bool], # display 3d grid
1236 # scatter props
1237 'scatter.marker': ['o', validate_string],
1238 'scatter.edgecolors': ['face', validate_string],
1240 # TODO validate that these are valid datetime format strings
1241 'date.autoformatter.year': ['%Y', validate_string],
1242 'date.autoformatter.month': ['%Y-%m', validate_string],
1243 'date.autoformatter.day': ['%Y-%m-%d', validate_string],
1244 'date.autoformatter.hour': ['%m-%d %H', validate_string],
1245 'date.autoformatter.minute': ['%d %H:%M', validate_string],
1246 'date.autoformatter.second': ['%H:%M:%S', validate_string],
1247 'date.autoformatter.microsecond': ['%M:%S.%f', validate_string],
1249 #legend properties
1250 'legend.fancybox': [True, validate_bool],
1251 'legend.loc': ['best', validate_legend_loc],
1252 # the number of points in the legend line
1253 'legend.numpoints': [1, validate_int],
1254 # the number of points in the legend line for scatter
1255 'legend.scatterpoints': [1, validate_int],
1256 'legend.fontsize': ['medium', validate_fontsize],
1257 'legend.title_fontsize': [None, validate_fontsize_None],
1258 # the relative size of legend markers vs. original
1259 'legend.markerscale': [1.0, validate_float],
1260 'legend.shadow': [False, validate_bool],
1261 # whether or not to draw a frame around legend
1262 'legend.frameon': [True, validate_bool],
1263 # alpha value of the legend frame
1264 'legend.framealpha': [0.8, validate_float_or_None],
1266 ## the following dimensions are in fraction of the font size
1267 'legend.borderpad': [0.4, validate_float], # units are fontsize
1268 # the vertical space between the legend entries
1269 'legend.labelspacing': [0.5, validate_float],
1270 # the length of the legend lines
1271 'legend.handlelength': [2., validate_float],
1272 # the length of the legend lines
1273 'legend.handleheight': [0.7, validate_float],
1274 # the space between the legend line and legend text
1275 'legend.handletextpad': [.8, validate_float],
1276 # the border between the axes and legend edge
1277 'legend.borderaxespad': [0.5, validate_float],
1278 # the border between the axes and legend edge
1279 'legend.columnspacing': [2., validate_float],
1280 'legend.facecolor': ['inherit', validate_color_or_inherit],
1281 'legend.edgecolor': ['0.8', validate_color_or_inherit],
1283 # tick properties
1284 'xtick.top': [False, validate_bool], # draw ticks on the top side
1285 'xtick.bottom': [True, validate_bool], # draw ticks on the bottom side
1286 'xtick.labeltop': [False, validate_bool], # draw label on the top
1287 'xtick.labelbottom': [True, validate_bool], # draw label on the bottom
1288 'xtick.major.size': [3.5, validate_float], # major xtick size in points
1289 'xtick.minor.size': [2, validate_float], # minor xtick size in points
1290 'xtick.major.width': [0.8, validate_float], # major xtick width in points
1291 'xtick.minor.width': [0.6, validate_float], # minor xtick width in points
1292 'xtick.major.pad': [3.5, validate_float], # distance to label in points
1293 'xtick.minor.pad': [3.4, validate_float], # distance to label in points
1294 'xtick.color': ['black', validate_color], # color of the xtick labels
1295 'xtick.minor.visible': [False, validate_bool], # visibility of the x axis minor ticks
1296 'xtick.minor.top': [True, validate_bool], # draw x axis top minor ticks
1297 'xtick.minor.bottom': [True, validate_bool], # draw x axis bottom minor ticks
1298 'xtick.major.top': [True, validate_bool], # draw x axis top major ticks
1299 'xtick.major.bottom': [True, validate_bool], # draw x axis bottom major ticks
1301 # fontsize of the xtick labels
1302 'xtick.labelsize': ['medium', validate_fontsize],
1303 'xtick.direction': ['out', validate_string], # direction of xticks
1304 'xtick.alignment': ["center", _validate_alignment],
1306 'ytick.left': [True, validate_bool], # draw ticks on the left side
1307 'ytick.right': [False, validate_bool], # draw ticks on the right side
1308 'ytick.labelleft': [True, validate_bool], # draw tick labels on the left side
1309 'ytick.labelright': [False, validate_bool], # draw tick labels on the right side
1310 'ytick.major.size': [3.5, validate_float], # major ytick size in points
1311 'ytick.minor.size': [2, validate_float], # minor ytick size in points
1312 'ytick.major.width': [0.8, validate_float], # major ytick width in points
1313 'ytick.minor.width': [0.6, validate_float], # minor ytick width in points
1314 'ytick.major.pad': [3.5, validate_float], # distance to label in points
1315 'ytick.minor.pad': [3.4, validate_float], # distance to label in points
1316 'ytick.color': ['black', validate_color], # color of the ytick labels
1317 'ytick.minor.visible': [False, validate_bool], # visibility of the y axis minor ticks
1318 'ytick.minor.left': [True, validate_bool], # draw y axis left minor ticks
1319 'ytick.minor.right': [True, validate_bool], # draw y axis right minor ticks
1320 'ytick.major.left': [True, validate_bool], # draw y axis left major ticks
1321 'ytick.major.right': [True, validate_bool], # draw y axis right major ticks
1323 # fontsize of the ytick labels
1324 'ytick.labelsize': ['medium', validate_fontsize],
1325 'ytick.direction': ['out', validate_string], # direction of yticks
1326 'ytick.alignment': ["center_baseline", _validate_alignment],
1328 'grid.color': ['#b0b0b0', validate_color], # grid color
1329 'grid.linestyle': ['-', _validate_linestyle], # solid
1330 'grid.linewidth': [0.8, validate_float], # in points
1331 'grid.alpha': [1.0, validate_float],
1333 ## figure props
1334 # figure title
1335 'figure.titlesize': ['large', validate_fontsize],
1336 'figure.titleweight': ['normal', validate_fontweight],
1338 # figure size in inches: width by height
1339 'figure.figsize': [[6.4, 4.8], validate_nseq_float(2)],
1340 'figure.dpi': [100, validate_float], # DPI
1341 'figure.facecolor': ['white', validate_color],
1342 'figure.edgecolor': ['white', validate_color],
1343 'figure.frameon': [True, validate_bool],
1344 'figure.autolayout': [False, validate_bool],
1345 'figure.max_open_warning': [20, validate_int],
1347 'figure.subplot.left': [0.125, _range_validators["0 <= x <= 1"]],
1348 'figure.subplot.right': [0.9, _range_validators["0 <= x <= 1"]],
1349 'figure.subplot.bottom': [0.11, _range_validators["0 <= x <= 1"]],
1350 'figure.subplot.top': [0.88, _range_validators["0 <= x <= 1"]],
1351 'figure.subplot.wspace': [0.2, _range_validators["0 <= x < 1"]],
1352 'figure.subplot.hspace': [0.2, _range_validators["0 <= x < 1"]],
1354 # do constrained_layout.
1355 'figure.constrained_layout.use': [False, validate_bool],
1356 # wspace and hspace are fraction of adjacent subplots to use
1357 # for space. Much smaller than above because we don't need
1358 # room for the text.
1359 'figure.constrained_layout.hspace':
1360 [0.02, _range_validators["0 <= x < 1"]],
1361 'figure.constrained_layout.wspace':
1362 [0.02, _range_validators["0 <= x < 1"]],
1363 # This is a buffer around the axes in inches. This is 3pts.
1364 'figure.constrained_layout.h_pad': [0.04167, validate_float],
1365 'figure.constrained_layout.w_pad': [0.04167, validate_float],
1367 ## Saving figure's properties
1368 'savefig.dpi': ['figure', validate_dpi], # DPI
1369 'savefig.facecolor': ['white', validate_color],
1370 'savefig.edgecolor': ['white', validate_color],
1371 'savefig.frameon': [True, validate_bool],
1372 'savefig.orientation': ['portrait', validate_orientation],
1373 'savefig.jpeg_quality': [95, validate_int],
1374 # value checked by backend at runtime
1375 'savefig.format': ['png', _update_savefig_format],
1376 # options are 'tight', or 'standard'. 'standard' validates to None.
1377 'savefig.bbox': ['standard', validate_bbox],
1378 'savefig.pad_inches': [0.1, validate_float],
1379 # default directory in savefig dialog box
1380 'savefig.directory': ['~', validate_string],
1381 'savefig.transparent': [False, validate_bool],
1383 # Maintain shell focus for TkAgg
1384 'tk.window_focus': [False, validate_bool],
1386 # Set the papersize/type
1387 'ps.papersize': ['letter', validate_ps_papersize],
1388 'ps.useafm': [False, validate_bool],
1389 # use ghostscript or xpdf to distill ps output
1390 'ps.usedistiller': [False, validate_ps_distiller],
1391 'ps.distiller.res': [6000, validate_int], # dpi
1392 'ps.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype)
1393 # compression level from 0 to 9; 0 to disable
1394 'pdf.compression': [6, validate_int],
1395 # ignore any color-setting commands from the frontend
1396 'pdf.inheritcolor': [False, validate_bool],
1397 # use only the 14 PDF core fonts embedded in every PDF viewing application
1398 'pdf.use14corefonts': [False, validate_bool],
1399 'pdf.fonttype': [3, validate_fonttype], # 3 (Type3) or 42 (Truetype)
1401 'pgf.debug': [False, validate_bool], # output debug information
1402 # choose latex application for creating pdf files (xelatex/lualatex)
1403 'pgf.texsystem': ['xelatex', validate_pgf_texsystem],
1404 # use matplotlib rc settings for font configuration
1405 'pgf.rcfonts': [True, validate_bool],
1406 # provide a custom preamble for the latex process
1407 'pgf.preamble': ['', _validate_tex_preamble],
1409 # write raster image data directly into the svg file
1410 'svg.image_inline': [True, validate_bool],
1411 # True to save all characters as paths in the SVG
1412 'svg.fonttype': ['path', validate_svg_fonttype],
1413 'svg.hashsalt': [None, validate_string_or_None],
1415 # set this when you want to generate hardcopy docstring
1416 'docstring.hardcopy': [False, validate_bool],
1418 'path.simplify': [True, validate_bool],
1419 'path.simplify_threshold': [1 / 9, _range_validators["0 <= x <= 1"]],
1420 'path.snap': [True, validate_bool],
1421 'path.sketch': [None, validate_sketch],
1422 'path.effects': [[], validate_any],
1423 'agg.path.chunksize': [0, validate_int], # 0 to disable chunking;
1425 # key-mappings (multi-character mappings should be a list/tuple)
1426 'keymap.fullscreen': [['f', 'ctrl+f'], validate_stringlist],
1427 'keymap.home': [['h', 'r', 'home'], validate_stringlist],
1428 'keymap.back': [['left', 'c', 'backspace', 'MouseButton.BACK'],
1429 validate_stringlist],
1430 'keymap.forward': [['right', 'v', 'MouseButton.FORWARD'],
1431 validate_stringlist],
1432 'keymap.pan': [['p'], validate_stringlist],
1433 'keymap.zoom': [['o'], validate_stringlist],
1434 'keymap.save': [['s', 'ctrl+s'], validate_stringlist],
1435 'keymap.quit': [['ctrl+w', 'cmd+w', 'q'], validate_stringlist],
1436 'keymap.quit_all': [['W', 'cmd+W', 'Q'], validate_stringlist],
1437 'keymap.grid': [['g'], validate_stringlist],
1438 'keymap.grid_minor': [['G'], validate_stringlist],
1439 'keymap.yscale': [['l'], validate_stringlist],
1440 'keymap.xscale': [['k', 'L'], validate_stringlist],
1441 'keymap.all_axes': [['a'], validate_stringlist],
1442 'keymap.help': [['f1'], validate_stringlist],
1443 'keymap.copy': [['ctrl+c', 'cmd+c'], validate_stringlist],
1445 # Animation settings
1446 'animation.html': ['none', validate_movie_html_fmt],
1447 # Limit, in MB, of size of base64 encoded animation in HTML
1448 # (i.e. IPython notebook)
1449 'animation.embed_limit': [20, validate_float],
1450 'animation.writer': ['ffmpeg', validate_movie_writer],
1451 'animation.codec': ['h264', validate_string],
1452 'animation.bitrate': [-1, validate_int],
1453 # Controls image format when frames are written to disk
1454 'animation.frame_format': ['png', validate_movie_frame_fmt],
1455 # Additional arguments for HTML writer
1456 'animation.html_args': [[], validate_stringlist],
1457 # Path to ffmpeg binary. If just binary name, subprocess uses $PATH.
1458 'animation.ffmpeg_path': ['ffmpeg', validate_string],
1459 # Additional arguments for ffmpeg movie writer (using pipes)
1460 'animation.ffmpeg_args': [[], validate_stringlist],
1461 # Path to AVConv binary. If just binary name, subprocess uses $PATH.
1462 'animation.avconv_path': ['avconv', validate_string],
1463 # Additional arguments for avconv movie writer (using pipes)
1464 'animation.avconv_args': [[], validate_stringlist],
1465 # Path to convert binary. If just binary name, subprocess uses $PATH.
1466 'animation.convert_path': ['convert', validate_string],
1467 # Additional arguments for convert movie writer (using pipes)
1468 'animation.convert_args': [[], validate_stringlist],
1470 'mpl_toolkits.legacy_colorbar': [True, validate_bool],
1472 # Classic (pre 2.0) compatibility mode
1473 # This is used for things that are hard to make backward compatible
1474 # with a sane rcParam alone. This does *not* turn on classic mode
1475 # altogether. For that use `matplotlib.style.use('classic')`.
1476 '_internal.classic_mode': [False, validate_bool]
1477}