rcsetup.py 57 KB

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