ultraplot 0.99.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. ultraplot/__init__.py +115 -0
  2. ultraplot/__init__.py.rej +58 -0
  3. ultraplot/axes/__init__.py +42 -0
  4. ultraplot/axes/base.py +3240 -0
  5. ultraplot/axes/cartesian.py +1425 -0
  6. ultraplot/axes/geo.py +1675 -0
  7. ultraplot/axes/plot.py +4569 -0
  8. ultraplot/axes/polar.py +381 -0
  9. ultraplot/axes/shared.py +186 -0
  10. ultraplot/axes/three.py +34 -0
  11. ultraplot/cmaps/Algae.rgb +256 -0
  12. ultraplot/cmaps/Amp.rgb +256 -0
  13. ultraplot/cmaps/BR.rgb +256 -0
  14. ultraplot/cmaps/Balance.rgb +256 -0
  15. ultraplot/cmaps/Blues1_r.xml +17 -0
  16. ultraplot/cmaps/Blues2.xml +16 -0
  17. ultraplot/cmaps/Blues3.xml +25 -0
  18. ultraplot/cmaps/Blues4_r.xml +17 -0
  19. ultraplot/cmaps/Blues5.xml +16 -0
  20. ultraplot/cmaps/Blues6.xml +25 -0
  21. ultraplot/cmaps/Blues7.xml +16 -0
  22. ultraplot/cmaps/Blues8.xml +17 -0
  23. ultraplot/cmaps/Blues9.xml +1 -0
  24. ultraplot/cmaps/Boreal.json +53 -0
  25. ultraplot/cmaps/Browns1.xml +16 -0
  26. ultraplot/cmaps/Browns2.xml +26 -0
  27. ultraplot/cmaps/Browns3.xml +17 -0
  28. ultraplot/cmaps/Browns4.xml +17 -0
  29. ultraplot/cmaps/Browns5.xml +26 -0
  30. ultraplot/cmaps/Browns6.xml +17 -0
  31. ultraplot/cmaps/Browns7.xml +19 -0
  32. ultraplot/cmaps/Browns8.xml +11 -0
  33. ultraplot/cmaps/Browns9.xml +1 -0
  34. ultraplot/cmaps/ColdHot.rgb +229 -0
  35. ultraplot/cmaps/Crest.rgb +256 -0
  36. ultraplot/cmaps/Curl.rgb +512 -0
  37. ultraplot/cmaps/Deep.rgb +256 -0
  38. ultraplot/cmaps/Delta.rgb +512 -0
  39. ultraplot/cmaps/Dense.rgb +256 -0
  40. ultraplot/cmaps/Div.json +71 -0
  41. ultraplot/cmaps/DryWet.json +73 -0
  42. ultraplot/cmaps/Dusk.json +53 -0
  43. ultraplot/cmaps/Fire.json +53 -0
  44. ultraplot/cmaps/Flare.rgb +256 -0
  45. ultraplot/cmaps/Glacial.json +53 -0
  46. ultraplot/cmaps/Greens1_r.xml +26 -0
  47. ultraplot/cmaps/Greens2.xml +28 -0
  48. ultraplot/cmaps/Greens3_r.xml +28 -0
  49. ultraplot/cmaps/Greens4.xml +17 -0
  50. ultraplot/cmaps/Greens5.xml +16 -0
  51. ultraplot/cmaps/Greens6_r.xml +16 -0
  52. ultraplot/cmaps/Greens7.xml +16 -0
  53. ultraplot/cmaps/Greens8.xml +26 -0
  54. ultraplot/cmaps/Haline.rgb +256 -0
  55. ultraplot/cmaps/Ice.rgb +256 -0
  56. ultraplot/cmaps/IceFire.rgb +256 -0
  57. ultraplot/cmaps/Mako.rgb +256 -0
  58. ultraplot/cmaps/Marine.json +53 -0
  59. ultraplot/cmaps/Matter.rgb +256 -0
  60. ultraplot/cmaps/Mono.txt +256 -0
  61. ultraplot/cmaps/MonoCycle.txt +256 -0
  62. ultraplot/cmaps/NegPos.json +71 -0
  63. ultraplot/cmaps/Oranges1.xml +27 -0
  64. ultraplot/cmaps/Oranges2.xml +26 -0
  65. ultraplot/cmaps/Oranges3.xml +15 -0
  66. ultraplot/cmaps/Oranges4.xml +23 -0
  67. ultraplot/cmaps/Oxy.rgb +256 -0
  68. ultraplot/cmaps/Phase.rgb +256 -0
  69. ultraplot/cmaps/Purples1_r.xml +16 -0
  70. ultraplot/cmaps/Purples2.xml +17 -0
  71. ultraplot/cmaps/Purples3.xml +18 -0
  72. ultraplot/cmaps/Reds1.xml +26 -0
  73. ultraplot/cmaps/Reds2.xml +22 -0
  74. ultraplot/cmaps/Reds3.xml +23 -0
  75. ultraplot/cmaps/Reds4.xml +26 -0
  76. ultraplot/cmaps/Reds5.xml +17 -0
  77. ultraplot/cmaps/Rocket.rgb +256 -0
  78. ultraplot/cmaps/Solar.rgb +256 -0
  79. ultraplot/cmaps/Speed.rgb +256 -0
  80. ultraplot/cmaps/Stellar.json +53 -0
  81. ultraplot/cmaps/Sunrise.json +53 -0
  82. ultraplot/cmaps/Sunset.json +53 -0
  83. ultraplot/cmaps/Tempo.rgb +256 -0
  84. ultraplot/cmaps/Thermal.rgb +256 -0
  85. ultraplot/cmaps/Turbid.rgb +256 -0
  86. ultraplot/cmaps/Vivid.xml +11 -0
  87. ultraplot/cmaps/Vlag.rgb +256 -0
  88. ultraplot/cmaps/Yellows1.xml +17 -0
  89. ultraplot/cmaps/Yellows2.xml +17 -0
  90. ultraplot/cmaps/Yellows3.xml +17 -0
  91. ultraplot/cmaps/Yellows4.xml +17 -0
  92. ultraplot/cmaps/acton.txt +256 -0
  93. ultraplot/cmaps/bam.txt +256 -0
  94. ultraplot/cmaps/bamO.txt +256 -0
  95. ultraplot/cmaps/bamako.txt +256 -0
  96. ultraplot/cmaps/batlow.txt +256 -0
  97. ultraplot/cmaps/batlowK.txt +256 -0
  98. ultraplot/cmaps/batlowW.txt +256 -0
  99. ultraplot/cmaps/berlin.txt +256 -0
  100. ultraplot/cmaps/bilbao.txt +256 -0
  101. ultraplot/cmaps/broc.txt +256 -0
  102. ultraplot/cmaps/brocO.txt +256 -0
  103. ultraplot/cmaps/buda.txt +256 -0
  104. ultraplot/cmaps/bukavu.txt +256 -0
  105. ultraplot/cmaps/cork.txt +256 -0
  106. ultraplot/cmaps/corkO.txt +256 -0
  107. ultraplot/cmaps/davos.txt +256 -0
  108. ultraplot/cmaps/devon.txt +256 -0
  109. ultraplot/cmaps/fes.txt +256 -0
  110. ultraplot/cmaps/hawaii.txt +256 -0
  111. ultraplot/cmaps/imola.txt +256 -0
  112. ultraplot/cmaps/lajolla.txt +256 -0
  113. ultraplot/cmaps/lapaz.txt +256 -0
  114. ultraplot/cmaps/lisbon.txt +256 -0
  115. ultraplot/cmaps/nuuk.txt +256 -0
  116. ultraplot/cmaps/oleron.txt +256 -0
  117. ultraplot/cmaps/oslo.txt +256 -0
  118. ultraplot/cmaps/roma.txt +256 -0
  119. ultraplot/cmaps/romaO.txt +256 -0
  120. ultraplot/cmaps/tofino.txt +256 -0
  121. ultraplot/cmaps/tokyo.txt +256 -0
  122. ultraplot/cmaps/turku.txt +256 -0
  123. ultraplot/cmaps/vanimo.txt +256 -0
  124. ultraplot/cmaps/vik.txt +256 -0
  125. ultraplot/cmaps/vikO.txt +256 -0
  126. ultraplot/colors/opencolor.txt +132 -0
  127. ultraplot/colors/xkcd.txt +951 -0
  128. ultraplot/colors.py +3241 -0
  129. ultraplot/colors.py.rej +243 -0
  130. ultraplot/config.py +1809 -0
  131. ultraplot/constructor.py +1633 -0
  132. ultraplot/cycles/538.hex +2 -0
  133. ultraplot/cycles/FlatUI.hex +1 -0
  134. ultraplot/cycles/Qual1.rgb +7 -0
  135. ultraplot/cycles/Qual2.rgb +13 -0
  136. ultraplot/cycles/bmh.hex +2 -0
  137. ultraplot/cycles/classic.hex +2 -0
  138. ultraplot/cycles/colorblind.hex +2 -0
  139. ultraplot/cycles/colorblind10.hex +2 -0
  140. ultraplot/cycles/default.hex +2 -0
  141. ultraplot/cycles/ggplot.hex +1 -0
  142. ultraplot/cycles/seaborn.hex +2 -0
  143. ultraplot/cycles/tableau.hex +2 -0
  144. ultraplot/demos.py +1201 -0
  145. ultraplot/externals/__init__.py +5 -0
  146. ultraplot/externals/hsluv.py +330 -0
  147. ultraplot/figure.py +2102 -0
  148. ultraplot/fonts/FiraMath-Bold.ttf +0 -0
  149. ultraplot/fonts/FiraMath-ExtraLight.ttf +0 -0
  150. ultraplot/fonts/FiraMath-Heavy.ttf +0 -0
  151. ultraplot/fonts/FiraMath-Light.ttf +0 -0
  152. ultraplot/fonts/FiraMath-Medium.ttf +0 -0
  153. ultraplot/fonts/FiraMath-Regular.ttf +0 -0
  154. ultraplot/fonts/FiraMath-SemiBold.ttf +0 -0
  155. ultraplot/fonts/FiraMath-UltraLight.ttf +0 -0
  156. ultraplot/fonts/FiraSans-Black.ttf +0 -0
  157. ultraplot/fonts/FiraSans-BlackItalic.ttf +0 -0
  158. ultraplot/fonts/FiraSans-Bold.ttf +0 -0
  159. ultraplot/fonts/FiraSans-BoldItalic.ttf +0 -0
  160. ultraplot/fonts/FiraSans-ExtraBold.ttf +0 -0
  161. ultraplot/fonts/FiraSans-ExtraBoldItalic.ttf +0 -0
  162. ultraplot/fonts/FiraSans-ExtraLight.ttf +0 -0
  163. ultraplot/fonts/FiraSans-ExtraLightItalic.ttf +0 -0
  164. ultraplot/fonts/FiraSans-Italic.ttf +0 -0
  165. ultraplot/fonts/FiraSans-Light.ttf +0 -0
  166. ultraplot/fonts/FiraSans-LightItalic.ttf +0 -0
  167. ultraplot/fonts/FiraSans-Medium.ttf +0 -0
  168. ultraplot/fonts/FiraSans-MediumItalic.ttf +0 -0
  169. ultraplot/fonts/FiraSans-Regular.ttf +0 -0
  170. ultraplot/fonts/FiraSans-SemiBold.ttf +0 -0
  171. ultraplot/fonts/FiraSans-SemiBoldItalic.ttf +0 -0
  172. ultraplot/fonts/LICENSE_FIRAMATH.txt +92 -0
  173. ultraplot/fonts/LICENSE_FIRASANS.txt +97 -0
  174. ultraplot/fonts/LICENSE_NOTOSANS.txt +202 -0
  175. ultraplot/fonts/LICENSE_NOTOSERIF.txt +93 -0
  176. ultraplot/fonts/LICENSE_OPENSANS.txt +202 -0
  177. ultraplot/fonts/LICENSE_ROBOTO.txt +202 -0
  178. ultraplot/fonts/LICENSE_SOURCESANS.txt +93 -0
  179. ultraplot/fonts/LICENSE_SOURCESERIF.txt +93 -0
  180. ultraplot/fonts/LICENSE_TEXGYRE.txt +29 -0
  181. ultraplot/fonts/LICENSE_UBUNTU.txt +96 -0
  182. ultraplot/fonts/NotoSans-Bold.ttf +0 -0
  183. ultraplot/fonts/NotoSans-BoldItalic.ttf +0 -0
  184. ultraplot/fonts/NotoSans-Italic.ttf +0 -0
  185. ultraplot/fonts/NotoSans-Regular.ttf +0 -0
  186. ultraplot/fonts/NotoSerif-Bold.ttf +0 -0
  187. ultraplot/fonts/NotoSerif-BoldItalic.ttf +0 -0
  188. ultraplot/fonts/NotoSerif-Italic.ttf +0 -0
  189. ultraplot/fonts/NotoSerif-Regular.ttf +0 -0
  190. ultraplot/fonts/OpenSans-Bold.ttf +0 -0
  191. ultraplot/fonts/OpenSans-BoldItalic.ttf +0 -0
  192. ultraplot/fonts/OpenSans-Italic.ttf +0 -0
  193. ultraplot/fonts/OpenSans-Regular.ttf +0 -0
  194. ultraplot/fonts/OpenSans-Semibold.ttf +0 -0
  195. ultraplot/fonts/OpenSans-SemiboldItalic.ttf +0 -0
  196. ultraplot/fonts/Roboto-Black.ttf +0 -0
  197. ultraplot/fonts/Roboto-BlackItalic.ttf +0 -0
  198. ultraplot/fonts/Roboto-Bold.ttf +0 -0
  199. ultraplot/fonts/Roboto-BoldItalic.ttf +0 -0
  200. ultraplot/fonts/Roboto-Italic.ttf +0 -0
  201. ultraplot/fonts/Roboto-Light.ttf +0 -0
  202. ultraplot/fonts/Roboto-LightItalic.ttf +0 -0
  203. ultraplot/fonts/Roboto-Medium.ttf +0 -0
  204. ultraplot/fonts/Roboto-MediumItalic.ttf +0 -0
  205. ultraplot/fonts/Roboto-Regular.ttf +0 -0
  206. ultraplot/fonts/SourceSansPro-Black.ttf +0 -0
  207. ultraplot/fonts/SourceSansPro-BlackItalic.ttf +0 -0
  208. ultraplot/fonts/SourceSansPro-Bold.ttf +0 -0
  209. ultraplot/fonts/SourceSansPro-BoldItalic.ttf +0 -0
  210. ultraplot/fonts/SourceSansPro-ExtraLight.ttf +0 -0
  211. ultraplot/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
  212. ultraplot/fonts/SourceSansPro-Italic.ttf +0 -0
  213. ultraplot/fonts/SourceSansPro-Light.ttf +0 -0
  214. ultraplot/fonts/SourceSansPro-LightItalic.ttf +0 -0
  215. ultraplot/fonts/SourceSansPro-Regular.ttf +0 -0
  216. ultraplot/fonts/SourceSansPro-SemiBold.ttf +0 -0
  217. ultraplot/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
  218. ultraplot/fonts/SourceSerifPro-Black.ttf +0 -0
  219. ultraplot/fonts/SourceSerifPro-BlackItalic.ttf +0 -0
  220. ultraplot/fonts/SourceSerifPro-Bold.ttf +0 -0
  221. ultraplot/fonts/SourceSerifPro-BoldItalic.ttf +0 -0
  222. ultraplot/fonts/SourceSerifPro-ExtraLight.ttf +0 -0
  223. ultraplot/fonts/SourceSerifPro-ExtraLightItalic.ttf +0 -0
  224. ultraplot/fonts/SourceSerifPro-Italic.ttf +0 -0
  225. ultraplot/fonts/SourceSerifPro-Light.ttf +0 -0
  226. ultraplot/fonts/SourceSerifPro-LightItalic.ttf +0 -0
  227. ultraplot/fonts/SourceSerifPro-Regular.ttf +0 -0
  228. ultraplot/fonts/SourceSerifPro-SemiBold.ttf +0 -0
  229. ultraplot/fonts/SourceSerifPro-SemiBoldItalic.ttf +0 -0
  230. ultraplot/fonts/Ubuntu-Bold.ttf +0 -0
  231. ultraplot/fonts/Ubuntu-BoldItalic.ttf +0 -0
  232. ultraplot/fonts/Ubuntu-Italic.ttf +0 -0
  233. ultraplot/fonts/Ubuntu-Light.ttf +0 -0
  234. ultraplot/fonts/Ubuntu-LightItalic.ttf +0 -0
  235. ultraplot/fonts/Ubuntu-Medium.ttf +0 -0
  236. ultraplot/fonts/Ubuntu-MediumItalic.ttf +0 -0
  237. ultraplot/fonts/Ubuntu-Regular.ttf +0 -0
  238. ultraplot/fonts/texgyreadventor-bold.ttf +0 -0
  239. ultraplot/fonts/texgyreadventor-bolditalic.ttf +0 -0
  240. ultraplot/fonts/texgyreadventor-italic.ttf +0 -0
  241. ultraplot/fonts/texgyreadventor-regular.ttf +0 -0
  242. ultraplot/fonts/texgyrebonum-bold.ttf +0 -0
  243. ultraplot/fonts/texgyrebonum-bolditalic.ttf +0 -0
  244. ultraplot/fonts/texgyrebonum-italic.ttf +0 -0
  245. ultraplot/fonts/texgyrebonum-regular.ttf +0 -0
  246. ultraplot/fonts/texgyrechorus-mediumitalic.ttf +0 -0
  247. ultraplot/fonts/texgyrecursor-bold.ttf +0 -0
  248. ultraplot/fonts/texgyrecursor-bolditalic.ttf +0 -0
  249. ultraplot/fonts/texgyrecursor-italic.ttf +0 -0
  250. ultraplot/fonts/texgyrecursor-regular.ttf +0 -0
  251. ultraplot/fonts/texgyreheros-bold.ttf +0 -0
  252. ultraplot/fonts/texgyreheros-bolditalic.ttf +0 -0
  253. ultraplot/fonts/texgyreheros-italic.ttf +0 -0
  254. ultraplot/fonts/texgyreheros-regular.ttf +0 -0
  255. ultraplot/fonts/texgyrepagella-bold.ttf +0 -0
  256. ultraplot/fonts/texgyrepagella-bolditalic.ttf +0 -0
  257. ultraplot/fonts/texgyrepagella-italic.ttf +0 -0
  258. ultraplot/fonts/texgyrepagella-regular.ttf +0 -0
  259. ultraplot/fonts/texgyreschola-bold.ttf +0 -0
  260. ultraplot/fonts/texgyreschola-bolditalic.ttf +0 -0
  261. ultraplot/fonts/texgyreschola-italic.ttf +0 -0
  262. ultraplot/fonts/texgyreschola-regular.ttf +0 -0
  263. ultraplot/fonts/texgyretermes-bold.ttf +0 -0
  264. ultraplot/fonts/texgyretermes-bolditalic.ttf +0 -0
  265. ultraplot/fonts/texgyretermes-italic.ttf +0 -0
  266. ultraplot/fonts/texgyretermes-regular.ttf +0 -0
  267. ultraplot/gridspec.py +1698 -0
  268. ultraplot/internals/__init__.py +529 -0
  269. ultraplot/internals/benchmarks.py +26 -0
  270. ultraplot/internals/context.py +44 -0
  271. ultraplot/internals/docstring.py +139 -0
  272. ultraplot/internals/fonts.py +75 -0
  273. ultraplot/internals/guides.py +167 -0
  274. ultraplot/internals/inputs.py +862 -0
  275. ultraplot/internals/labels.py +85 -0
  276. ultraplot/internals/rcsetup.py +1933 -0
  277. ultraplot/internals/versions.py +61 -0
  278. ultraplot/internals/warnings.py +122 -0
  279. ultraplot/proj.py +325 -0
  280. ultraplot/scale.py +966 -0
  281. ultraplot/tests/__init__.py +28 -0
  282. ultraplot/tests/baseline/test_align_labels.png +0 -0
  283. ultraplot/tests/baseline/test_aligned_outer_guides.png +0 -0
  284. ultraplot/tests/baseline/test_aspect_ratios.png +0 -0
  285. ultraplot/tests/baseline/test_auto_diverging1.png +0 -0
  286. ultraplot/tests/baseline/test_auto_legend.png +0 -0
  287. ultraplot/tests/baseline/test_auto_reverse.png +0 -0
  288. ultraplot/tests/baseline/test_autodiverging3.png +0 -0
  289. ultraplot/tests/baseline/test_autodiverging4.png +0 -0
  290. ultraplot/tests/baseline/test_autodiverging5.png +0 -0
  291. ultraplot/tests/baseline/test_axes_colors.png +0 -0
  292. ultraplot/tests/baseline/test_bar_vectors.png +0 -0
  293. ultraplot/tests/baseline/test_bar_width.png +0 -0
  294. ultraplot/tests/baseline/test_both_ticklabels.png +0 -0
  295. ultraplot/tests/baseline/test_bounds_ticks.png +0 -0
  296. ultraplot/tests/baseline/test_boxplot_colors.png +0 -0
  297. ultraplot/tests/baseline/test_boxplot_vectors.png +0 -0
  298. ultraplot/tests/baseline/test_cartopy_contours.png +0 -0
  299. ultraplot/tests/baseline/test_cartopy_labels.png +0 -0
  300. ultraplot/tests/baseline/test_cartopy_manual.png +0 -0
  301. ultraplot/tests/baseline/test_centered_legends.png +0 -0
  302. ultraplot/tests/baseline/test_cmap_cycles.png +0 -0
  303. ultraplot/tests/baseline/test_colorbar.png +0 -0
  304. ultraplot/tests/baseline/test_colorbar_ticks.png +0 -0
  305. ultraplot/tests/baseline/test_colormap_mode.png +0 -0
  306. ultraplot/tests/baseline/test_column_iteration.png +0 -0
  307. ultraplot/tests/baseline/test_complex_ticks.png +0 -0
  308. ultraplot/tests/baseline/test_contour_labels.png +0 -0
  309. ultraplot/tests/baseline/test_contour_legend_with_label.png +0 -0
  310. ultraplot/tests/baseline/test_contour_legend_without_label.png +0 -0
  311. ultraplot/tests/baseline/test_contour_negative.png +0 -0
  312. ultraplot/tests/baseline/test_contour_single.png +0 -0
  313. ultraplot/tests/baseline/test_cutoff_ticks.png +0 -0
  314. ultraplot/tests/baseline/test_data_keyword.png +0 -0
  315. ultraplot/tests/baseline/test_discrete_ticks.png +0 -0
  316. ultraplot/tests/baseline/test_discrete_vs_fixed.png +0 -0
  317. ultraplot/tests/baseline/test_drawing_in_projection_with_globe.png +0 -0
  318. ultraplot/tests/baseline/test_drawing_in_projection_without_globe.png +0 -0
  319. ultraplot/tests/baseline/test_edge_fix.png +0 -0
  320. ultraplot/tests/baseline/test_flow_functions.png +0 -0
  321. ultraplot/tests/baseline/test_font_adjustments.png +0 -0
  322. ultraplot/tests/baseline/test_geographic_multiple_projections.png +0 -0
  323. ultraplot/tests/baseline/test_geographic_single_projection.png +0 -0
  324. ultraplot/tests/baseline/test_gray_adjustment.png +0 -0
  325. ultraplot/tests/baseline/test_histogram_legend.png +0 -0
  326. ultraplot/tests/baseline/test_histogram_types.png +0 -0
  327. ultraplot/tests/baseline/test_ignore_message.png +0 -0
  328. ultraplot/tests/baseline/test_inbounds_data.png +0 -0
  329. ultraplot/tests/baseline/test_init_format.png +0 -0
  330. ultraplot/tests/baseline/test_inner_title_zorder.png +0 -0
  331. ultraplot/tests/baseline/test_inset_basic.png +0 -0
  332. ultraplot/tests/baseline/test_inset_colorbars.png +0 -0
  333. ultraplot/tests/baseline/test_inset_colors_1.png +0 -0
  334. ultraplot/tests/baseline/test_inset_colors_2.png +0 -0
  335. ultraplot/tests/baseline/test_inset_zoom_update.png +0 -0
  336. ultraplot/tests/baseline/test_invalid_dist.png +0 -0
  337. ultraplot/tests/baseline/test_invalid_plot.png +0 -0
  338. ultraplot/tests/baseline/test_keep_guide_labels.png +0 -0
  339. ultraplot/tests/baseline/test_label_settings.png +0 -0
  340. ultraplot/tests/baseline/test_level_restriction.png +0 -0
  341. ultraplot/tests/baseline/test_levels_with_vmin_vmax.png +0 -0
  342. ultraplot/tests/baseline/test_locale_formatting.png +0 -0
  343. ultraplot/tests/baseline/test_locale_formatting_en_US.UTF-8.png +0 -0
  344. ultraplot/tests/baseline/test_manual_labels.png +0 -0
  345. ultraplot/tests/baseline/test_multi_formatting.png +0 -0
  346. ultraplot/tests/baseline/test_multiple_calls.png +0 -0
  347. ultraplot/tests/baseline/test_on_the_fly_mappable.png +0 -0
  348. ultraplot/tests/baseline/test_outer_align.png +0 -0
  349. ultraplot/tests/baseline/test_panel_dist.png +0 -0
  350. ultraplot/tests/baseline/test_panels_suplabels_three_hor_panels.png +0 -0
  351. ultraplot/tests/baseline/test_panels_with_sharing.png +0 -0
  352. ultraplot/tests/baseline/test_panels_without_sharing_1.png +0 -0
  353. ultraplot/tests/baseline/test_panels_without_sharing_2.png +0 -0
  354. ultraplot/tests/baseline/test_parametric_colors.png +0 -0
  355. ultraplot/tests/baseline/test_parametric_labels.png +0 -0
  356. ultraplot/tests/baseline/test_patch_format.png +0 -0
  357. ultraplot/tests/baseline/test_pie_charts.png +0 -0
  358. ultraplot/tests/baseline/test_pint_quantities.png +0 -0
  359. ultraplot/tests/baseline/test_polar_projections.png +0 -0
  360. ultraplot/tests/baseline/test_projection_dicts.png +0 -0
  361. ultraplot/tests/baseline/test_qualitative_colormaps_1.png +0 -0
  362. ultraplot/tests/baseline/test_qualitative_colormaps_2.png +0 -0
  363. ultraplot/tests/baseline/test_reversed_levels.png +0 -0
  364. ultraplot/tests/baseline/test_scatter_alpha.png +0 -0
  365. ultraplot/tests/baseline/test_scatter_args.png +0 -0
  366. ultraplot/tests/baseline/test_scatter_cycle.png +0 -0
  367. ultraplot/tests/baseline/test_scatter_inbounds.png +0 -0
  368. ultraplot/tests/baseline/test_scatter_sizes.png +0 -0
  369. ultraplot/tests/baseline/test_seaborn_heatmap.png +0 -0
  370. ultraplot/tests/baseline/test_seaborn_hist.png +0 -0
  371. ultraplot/tests/baseline/test_seaborn_relational.png +0 -0
  372. ultraplot/tests/baseline/test_seaborn_swarmplot.png +0 -0
  373. ultraplot/tests/baseline/test_segmented_norm.png +0 -0
  374. ultraplot/tests/baseline/test_segmented_norm_ticks.png +0 -0
  375. ultraplot/tests/baseline/test_share_all_basic.png +0 -0
  376. ultraplot/tests/baseline/test_singleton_legend.png +0 -0
  377. ultraplot/tests/baseline/test_span_labels.png +0 -0
  378. ultraplot/tests/baseline/test_spine_offset.png +0 -0
  379. ultraplot/tests/baseline/test_spine_side.png +0 -0
  380. ultraplot/tests/baseline/test_standardized_input.png +0 -0
  381. ultraplot/tests/baseline/test_statistical_boxplot.png +0 -0
  382. ultraplot/tests/baseline/test_three_axes.png +0 -0
  383. ultraplot/tests/baseline/test_tick_direction.png +0 -0
  384. ultraplot/tests/baseline/test_tick_labels.png +0 -0
  385. ultraplot/tests/baseline/test_tick_length.png +0 -0
  386. ultraplot/tests/baseline/test_tick_width.png +0 -0
  387. ultraplot/tests/baseline/test_title_deflection.png +0 -0
  388. ultraplot/tests/baseline/test_triangular_functions.png +0 -0
  389. ultraplot/tests/baseline/test_tuple_handles.png +0 -0
  390. ultraplot/tests/baseline/test_twin_axes_1.png +0 -0
  391. ultraplot/tests/baseline/test_twin_axes_2.png +0 -0
  392. ultraplot/tests/baseline/test_twin_axes_3.png +0 -0
  393. ultraplot/tests/baseline/test_uneven_levels.png +0 -0
  394. ultraplot/tests/test_1dplots.py +373 -0
  395. ultraplot/tests/test_2dplots.py +354 -0
  396. ultraplot/tests/test_axes.py +179 -0
  397. ultraplot/tests/test_colorbar.py +253 -0
  398. ultraplot/tests/test_docs.py +78 -0
  399. ultraplot/tests/test_format.py +340 -0
  400. ultraplot/tests/test_geographic.py +116 -0
  401. ultraplot/tests/test_imshow.py +110 -0
  402. ultraplot/tests/test_inset.py +28 -0
  403. ultraplot/tests/test_integration.py +149 -0
  404. ultraplot/tests/test_legend.py +181 -0
  405. ultraplot/tests/test_projections.py +138 -0
  406. ultraplot/tests/test_statistical_plotting.py +77 -0
  407. ultraplot/tests/test_subplots.py +174 -0
  408. ultraplot/ticker.py +879 -0
  409. ultraplot/ui.py +233 -0
  410. ultraplot/utils.py +912 -0
  411. ultraplot-0.99.3.dist-info/LICENSE.txt +427 -0
  412. ultraplot-0.99.3.dist-info/METADATA +88 -0
  413. ultraplot-0.99.3.dist-info/RECORD +416 -0
  414. ultraplot-0.99.3.dist-info/WHEEL +5 -0
  415. ultraplot-0.99.3.dist-info/entry_points.txt +2 -0
  416. ultraplot-0.99.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1933 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Utilities for global configuration.
4
+ """
5
+ import functools
6
+ import re, matplotlib as mpl
7
+ from collections.abc import MutableMapping
8
+ from numbers import Integral, Real
9
+
10
+ import matplotlib.rcsetup as msetup
11
+ import numpy as np
12
+ from cycler import Cycler
13
+ from matplotlib import RcParams
14
+ from matplotlib import rcParamsDefault as _rc_matplotlib_native
15
+ from matplotlib.colors import Colormap
16
+ from matplotlib.font_manager import font_scalings
17
+
18
+ if hasattr(mpl, "_fontconfig_pattern"):
19
+ from matplotlib._fontconfig_pattern import parse_fontconfig_pattern
20
+ else:
21
+ from matplotlib.fontconfig_pattern import parse_fontconfig_pattern
22
+
23
+ from . import ic # noqa: F401
24
+ from . import warnings
25
+ from .versions import _version_mpl
26
+
27
+ # Regex for "probable" unregistered named colors. Try to retain warning message for
28
+ # colors that were most likely a failed literal string evaluation during startup.
29
+ REGEX_NAMED_COLOR = re.compile(r"\A[a-zA-Z0-9:_ -]*\Z")
30
+
31
+ # Configurable validation settings
32
+ # NOTE: These are set to True inside __init__.py
33
+ # NOTE: We really cannot delay creation of 'rc' until after registration because
34
+ # colormap creation depends on rc['cmap.lut'] and rc['cmap.listedthresh'].
35
+ # And anyway to revoke that dependence would require other uglier kludges.
36
+ VALIDATE_REGISTERED_CMAPS = False
37
+ VALIDATE_REGISTERED_COLORS = False
38
+
39
+ # Initial synced properties
40
+ # NOTE: Important that LINEWIDTH is less than matplotlib default of 0.8.
41
+ # In general want axes lines to look about as thick as text.
42
+ # NOTE: Important that default values are equivalent to the *validated* values
43
+ # used in the RcParams dictionaries. Otherwise _user_settings() detects changes.
44
+ # NOTE: We *could* just leave some settings empty and leave it up to Configurator
45
+ # to sync them when ultraplot is imported... but also sync them here so that we can
46
+ # simply compare any Configurator state to these dictionaries and use save() to
47
+ # save only the settings changed by the user.
48
+ BLACK = "black"
49
+ CYCLE = "colorblind"
50
+ CMAPCYC = "twilight"
51
+ CMAPDIV = "BuRd"
52
+ CMAPSEQ = "Fire"
53
+ CMAPCAT = "colorblind10"
54
+ DIVERGING = "div"
55
+ FRAMEALPHA = 0.8 # legend and colorbar
56
+ FONTNAME = "sans-serif"
57
+ FONTSIZE = 9.0
58
+ GRIDALPHA = 0.1
59
+ GRIDBELOW = "line"
60
+ GRIDPAD = 3.0
61
+ GRIDRATIO = 0.5 # differentiated from major by half size reduction
62
+ GRIDSTYLE = "-"
63
+ LABELPAD = 4.0 # default is 4.0, previously was 3.0
64
+ LARGESIZE = "med-large"
65
+ LINEWIDTH = 0.6
66
+ MARGIN = 0.05
67
+ MATHTEXT = False
68
+ SMALLSIZE = "medium"
69
+ TICKDIR = "out"
70
+ TICKLEN = 4.0
71
+ TICKLENRATIO = 0.5 # very noticeable length reduction
72
+ TICKMINOR = True
73
+ TICKPAD = 2.0
74
+ TICKWIDTHRATIO = 0.8 # very slight width reduction
75
+ TITLEPAD = 5.0 # default is 6.0, previously was 3.0
76
+ WHITE = "white"
77
+ ZLINES = 2 # default zorder for lines
78
+ ZPATCHES = 1
79
+
80
+ # Preset legend locations and aliases
81
+ LEGEND_LOCS = {
82
+ "fill": "fill",
83
+ "inset": "best",
84
+ "i": "best",
85
+ 0: "best",
86
+ 1: "upper right",
87
+ 2: "upper left",
88
+ 3: "lower left",
89
+ 4: "lower right",
90
+ 5: "center left",
91
+ 6: "center right",
92
+ 7: "lower center",
93
+ 8: "upper center",
94
+ 9: "center",
95
+ "l": "left",
96
+ "r": "right",
97
+ "b": "bottom",
98
+ "t": "top",
99
+ "c": "center",
100
+ "ur": "upper right",
101
+ "ul": "upper left",
102
+ "ll": "lower left",
103
+ "lr": "lower right",
104
+ "cr": "center right",
105
+ "cl": "center left",
106
+ "uc": "upper center",
107
+ "lc": "lower center",
108
+ }
109
+ for _loc in tuple(LEGEND_LOCS.values()):
110
+ if _loc not in LEGEND_LOCS:
111
+ LEGEND_LOCS[_loc] = _loc # identity assignments
112
+ TEXT_LOCS = {
113
+ key: val
114
+ for key, val in LEGEND_LOCS.items()
115
+ if val
116
+ in (
117
+ "left",
118
+ "center",
119
+ "right",
120
+ "upper left",
121
+ "upper center",
122
+ "upper right",
123
+ "lower left",
124
+ "lower center",
125
+ "lower right",
126
+ )
127
+ }
128
+ COLORBAR_LOCS = {
129
+ key: val
130
+ for key, val in LEGEND_LOCS.items()
131
+ if val
132
+ in (
133
+ "fill",
134
+ "best",
135
+ "left",
136
+ "right",
137
+ "top",
138
+ "bottom",
139
+ "upper left",
140
+ "upper right",
141
+ "lower left",
142
+ "lower right",
143
+ )
144
+ }
145
+ PANEL_LOCS = {
146
+ key: val
147
+ for key, val in LEGEND_LOCS.items()
148
+ if val in ("left", "right", "top", "bottom")
149
+ }
150
+ ALIGN_LOCS = {
151
+ key: val
152
+ for key, val in LEGEND_LOCS.items()
153
+ if isinstance(key, str)
154
+ and val
155
+ in (
156
+ "left",
157
+ "right",
158
+ "top",
159
+ "bottom",
160
+ "center",
161
+ )
162
+ }
163
+
164
+ # Matplotlib setting categories
165
+ EM_KEYS = ( # em-width units
166
+ "legend.borderpad",
167
+ "legend.labelspacing",
168
+ "legend.handlelength",
169
+ "legend.handleheight",
170
+ "legend.handletextpad",
171
+ "legend.borderaxespad",
172
+ "legend.columnspacing",
173
+ )
174
+ PT_KEYS = (
175
+ "font.size", # special case
176
+ "xtick.major.size",
177
+ "xtick.minor.size",
178
+ "ytick.major.size",
179
+ "ytick.minor.size",
180
+ "xtick.major.pad",
181
+ "xtick.minor.pad",
182
+ "ytick.major.pad",
183
+ "ytick.minor.pad",
184
+ "xtick.major.width",
185
+ "xtick.minor.width",
186
+ "ytick.major.width",
187
+ "ytick.minor.width",
188
+ "axes.labelpad",
189
+ "axes.titlepad",
190
+ "axes.linewidth",
191
+ "grid.linewidth",
192
+ "patch.linewidth",
193
+ "hatch.linewidth",
194
+ "lines.linewidth",
195
+ "contour.linewidth",
196
+ )
197
+ FONT_KEYS = set() # dynamically add to this below
198
+
199
+
200
+ def _get_default_param(key):
201
+ """
202
+ Get the default parameter from one of three places. This is used for
203
+ the :rc: role when compiling docs and when saving ultraplotrc files.
204
+ """
205
+ sentinel = object()
206
+ for dict_ in (
207
+ _rc_ultraplot_default,
208
+ _rc_matplotlib_default, # imposed defaults
209
+ _rc_matplotlib_native, # native defaults
210
+ ):
211
+ value = dict_.get(key, sentinel)
212
+ if value is not sentinel:
213
+ return value
214
+ raise KeyError(f"Invalid key {key!r}.")
215
+
216
+
217
+ def _validate_abc(value):
218
+ """
219
+ Validate a-b-c setting.
220
+ """
221
+ try:
222
+ if np.iterable(value):
223
+ return all(map(_validate_bool, value))
224
+ else:
225
+ return _validate_bool(value)
226
+ except ValueError:
227
+ pass
228
+ if isinstance(value, str):
229
+ if "a" in value.lower():
230
+ return value
231
+ else:
232
+ if all(isinstance(_, str) for _ in value):
233
+ return tuple(value)
234
+ raise ValueError(
235
+ "A-b-c setting must be string containing 'a' or 'A' or sequence of strings."
236
+ )
237
+
238
+
239
+ def _validate_belongs(*options):
240
+ """
241
+ Return a validator ensuring the item belongs in the list.
242
+ """
243
+
244
+ def _validate_belongs(value): # noqa: E306
245
+ for opt in options:
246
+ if isinstance(value, str) and isinstance(opt, str):
247
+ if value.lower() == opt.lower(): # noqa: E501
248
+ return opt
249
+ elif value is True or value is False or value is None:
250
+ if value is opt:
251
+ return opt
252
+ elif value == opt:
253
+ return opt
254
+ raise ValueError(
255
+ f"Invalid value {value!r}. Options are: "
256
+ + ", ".join(map(repr, options))
257
+ + "."
258
+ )
259
+
260
+ return _validate_belongs
261
+
262
+
263
+ def _validate_cmap(subtype):
264
+ """
265
+ Validate the colormap or cycle. Possibly skip name registration check
266
+ and assign the colormap name rather than a colormap instance.
267
+ """
268
+
269
+ def _validate_cmap(value):
270
+ name = value
271
+ if isinstance(value, str):
272
+ if VALIDATE_REGISTERED_CMAPS:
273
+ from ..colors import _get_cmap_subtype
274
+
275
+ _get_cmap_subtype(name, subtype) # may trigger useful error message
276
+ return name
277
+ elif isinstance(value, Colormap):
278
+ name = getattr(value, "name", None)
279
+ if isinstance(name, str):
280
+ from ..colors import _cmap_database # avoid circular imports
281
+
282
+ _cmap_database[name] = value
283
+ return name
284
+ raise ValueError(f"Invalid colormap or color cycle name {name!r}.")
285
+
286
+ return _validate_cmap
287
+
288
+
289
+ def _validate_color(value, alternative=None):
290
+ """
291
+ Validate the color. Possibly skip name registration check.
292
+ """
293
+ if alternative and isinstance(value, str) and value.lower() == alternative:
294
+ return value
295
+ try:
296
+ return msetup.validate_color(value)
297
+ except ValueError:
298
+ if (
299
+ VALIDATE_REGISTERED_COLORS
300
+ or not isinstance(value, str)
301
+ or not REGEX_NAMED_COLOR.match(value)
302
+ ):
303
+ raise ValueError(f"{value!r} is not a valid color arg.") from None
304
+ return value
305
+ except Exception as error:
306
+ raise error
307
+
308
+
309
+ def _validate_fontprops(s):
310
+ """
311
+ Parse font property with support for ``'regular'`` placeholder.
312
+ """
313
+ b = s.startswith("regular")
314
+ if b:
315
+ s = s.replace("regular", "sans", 1)
316
+ parse_fontconfig_pattern(s)
317
+ if b:
318
+ s = s.replace("sans", "regular", 1)
319
+ return s
320
+
321
+
322
+ def _validate_fontsize(value):
323
+ """
324
+ Validate font size with new scalings and permitting other units.
325
+ """
326
+ if value is None and None in font_scalings: # has it always been this way?
327
+ return
328
+ if isinstance(value, str):
329
+ value = value.lower()
330
+ if value in font_scalings:
331
+ return value
332
+ try:
333
+ return _validate_pt(value) # note None is also a valid font size!
334
+ except ValueError:
335
+ pass
336
+ raise ValueError(
337
+ f"Invalid font size {value!r}. Can be points or one of the "
338
+ "preset scalings: " + ", ".join(map(repr, font_scalings)) + "."
339
+ )
340
+
341
+
342
+ def _validate_labels(labels, lon=True):
343
+ """
344
+ Convert labels argument to length-4 boolean array.
345
+ """
346
+ if labels is None:
347
+ return [None] * 4
348
+ which = "lon" if lon else "lat"
349
+ if isinstance(labels, str):
350
+ labels = (labels,)
351
+ array = np.atleast_1d(labels).tolist()
352
+ if all(isinstance(_, str) for _ in array):
353
+ bool_ = [False] * 4
354
+ opts = ("left", "right", "bottom", "top")
355
+ for string in array:
356
+ if string in opts:
357
+ string = string[0]
358
+ elif set(string) - set("lrbt"):
359
+ raise ValueError(
360
+ f"Invalid {which}label string {string!r}. Must be one of "
361
+ + ", ".join(map(repr, opts))
362
+ + " or a string of single-letter characters like 'lr'."
363
+ )
364
+ for char in string:
365
+ bool_["lrbt".index(char)] = True
366
+ array = bool_
367
+ if len(array) == 1:
368
+ array.append(False) # default is to label bottom or left
369
+ if len(array) == 2:
370
+ if lon:
371
+ array = [False, False, *array]
372
+ else:
373
+ array = [*array, False, False]
374
+ if len(array) != 4 or any(isinstance(_, str) for _ in array):
375
+ raise ValueError(f"Invalid {which}label spec: {labels}.")
376
+ return array
377
+
378
+
379
+ def _validate_or_none(validator):
380
+ """
381
+ Allow none otherwise pass to the input validator.
382
+ """
383
+
384
+ @functools.wraps(validator)
385
+ def _validate_or_none(value):
386
+ if value is None:
387
+ return
388
+ if isinstance(value, str) and value.lower() == "none":
389
+ return
390
+ return validator(value)
391
+
392
+ _validate_or_none.__name__ = validator.__name__ + "_or_none"
393
+ return _validate_or_none
394
+
395
+
396
+ def _validate_rotation(value):
397
+ """
398
+ Valid rotation arguments.
399
+ """
400
+ if isinstance(value, str) and value.lower() in ("horizontal", "vertical"):
401
+ return value
402
+ return _validate_float(value)
403
+
404
+
405
+ def _validate_units(dest):
406
+ """
407
+ Validate the input using the units function.
408
+ """
409
+
410
+ def _validate_units(value):
411
+ if isinstance(value, str):
412
+ from ..utils import units # avoid circular imports
413
+
414
+ value = units(value, dest) # validation happens here
415
+ return _validate_float(value)
416
+
417
+ return _validate_units
418
+
419
+
420
+ def _rst_table():
421
+ """
422
+ Return the setting names and descriptions in an RST-style table.
423
+ """
424
+ # Initial stuff
425
+ colspace = 2 # spaces between each column
426
+ descrips = tuple(descrip for (_, _, descrip) in _rc_ultraplot_table.values())
427
+ keylen = len(max((*_rc_ultraplot_table, "Key"), key=len)) + 4 # literal backticks
428
+ vallen = len(max((*descrips, "Description"), key=len))
429
+ divider = "=" * keylen + " " * colspace + "=" * vallen + "\n"
430
+ header = "Key" + " " * (keylen - 3 + colspace) + "Description\n"
431
+
432
+ # Build table
433
+ string = divider + header + divider
434
+ for key, (_, _, descrip) in _rc_ultraplot_table.items():
435
+ spaces = " " * (keylen - (len(key) + 4) + colspace)
436
+ string += f"``{key}``{spaces}{descrip}\n"
437
+
438
+ string = string + divider
439
+ return ".. rst-class:: ultraplot-rctable\n\n" + string.strip()
440
+
441
+
442
+ def _to_string(value):
443
+ """
444
+ Translate setting to a string suitable for saving.
445
+ """
446
+ # NOTE: Never safe hex strings with leading '#'. In both matplotlibrc
447
+ # and ultraplotrc this will be read as comment character.
448
+ if value is None or isinstance(value, (str, bool, Integral)):
449
+ value = str(value)
450
+ if value[:1] == "#": # i.e. a HEX string
451
+ value = value[1:]
452
+ elif isinstance(value, Real):
453
+ value = str(round(value, 6)) # truncate decimals
454
+ elif isinstance(value, Cycler):
455
+ value = repr(value) # special case!
456
+ elif isinstance(value, (list, tuple, np.ndarray)):
457
+ value = ", ".join(map(_to_string, value)) # sexy recursion
458
+ else:
459
+ value = None
460
+ return value
461
+
462
+
463
+ def _yaml_table(rcdict, comment=True, description=False):
464
+ """
465
+ Return the settings as a nicely tabulated YAML-style table.
466
+ """
467
+ prefix = "# " if comment else ""
468
+ data = []
469
+ for key, args in rcdict.items():
470
+ # Optionally append description
471
+ includes_descrip = isinstance(args, tuple) and len(args) == 3
472
+ if not description:
473
+ descrip = ""
474
+ value = args[0] if includes_descrip else args
475
+ elif includes_descrip:
476
+ value, validator, descrip = args
477
+ descrip = "# " + descrip # skip the validator
478
+ else:
479
+ raise ValueError(f"Unexpected input {key}={args!r}.")
480
+
481
+ # Translate object to string
482
+ value = _to_string(value)
483
+ if value is not None:
484
+ data.append((key, value, descrip))
485
+ else:
486
+ warnings._warn_ultraplot(
487
+ f"Failed to write rc setting {key} = {value!r}. Must be None, bool, "
488
+ "string, int, float, a list or tuple thereof, or a property cycler."
489
+ )
490
+
491
+ # Generate string
492
+ string = ""
493
+ keylen = len(max(rcdict, key=len))
494
+ vallen = len(max((tup[1] for tup in data), key=len))
495
+ for key, value, descrip in data:
496
+ space1 = " " * (keylen - len(key) + 1)
497
+ space2 = " " * (vallen - len(value) + 2) if descrip else ""
498
+ string += f"{prefix}{key}:{space1}{value}{space2}{descrip}\n"
499
+
500
+ return string.strip()
501
+
502
+
503
+ class _RcParams(MutableMapping, dict):
504
+ """
505
+ A simple dictionary with locked inputs and validated assignments.
506
+ """
507
+
508
+ # NOTE: By omitting __delitem__ in MutableMapping we effectively
509
+ # disable mutability. Also disables deleting items with pop().
510
+ def __init__(self, source, validate):
511
+ self._validate = validate
512
+ for key, value in source.items():
513
+ self.__setitem__(key, value) # trigger validation
514
+
515
+ def __repr__(self):
516
+ return RcParams.__repr__(self)
517
+
518
+ def __str__(self):
519
+ return RcParams.__repr__(self)
520
+
521
+ def __len__(self):
522
+ return dict.__len__(self)
523
+
524
+ def __iter__(self):
525
+ # NOTE: ultraplot doesn't add deprecated args to dictionary so
526
+ # we don't have to suppress warning messages here.
527
+ yield from sorted(dict.__iter__(self))
528
+
529
+ def __getitem__(self, key):
530
+ key, _ = self._check_key(key)
531
+ return dict.__getitem__(self, key)
532
+
533
+ def __setitem__(self, key, value):
534
+ key, value = self._check_key(key, value)
535
+ if key not in self._validate:
536
+ raise KeyError(f"Invalid rc key {key!r}.")
537
+ try:
538
+ value = self._validate[key](value)
539
+ except (ValueError, TypeError) as error:
540
+ raise ValueError(f"Key {key}: {error}") from None
541
+ if key is not None:
542
+ dict.__setitem__(self, key, value)
543
+
544
+ @staticmethod
545
+ def _check_key(key, value=None):
546
+ # NOTE: If we assigned from the Configurator then the deprecated key will
547
+ # still propagate to the same 'children' as the new key.
548
+ # NOTE: This also translates values for special cases of renamed keys.
549
+ # Currently the special cases are 'basemap' and 'cartopy.autoextent'.
550
+ if key in _rc_renamed:
551
+ key_new, version = _rc_renamed[key]
552
+ warnings._warn_ultraplot(
553
+ f"The rc setting {key!r} was deprecated in version {version} and may be " # noqa: E501
554
+ f"removed in {warnings.next_release()}. Please use {key_new!r} instead." # noqa: E501
555
+ )
556
+ if key == "basemap": # special case
557
+ value = ("cartopy", "basemap")[int(bool(value))]
558
+ if key == "cartopy.autoextent":
559
+ value = ("globe", "auto")[int(bool(value))]
560
+ key = key_new
561
+ if key in _rc_removed:
562
+ info, version = _rc_removed[key]
563
+ raise KeyError(
564
+ f"The rc setting {key!r} was removed in version {version}."
565
+ + (info and " " + info)
566
+ )
567
+ return key, value
568
+
569
+ def copy(self):
570
+ source = {key: dict.__getitem__(self, key) for key in self}
571
+ return _RcParams(source, self._validate)
572
+
573
+
574
+ # Borrow validators from matplotlib and construct some new ones
575
+ # WARNING: Instead of validate_fontweight matplotlib used validate_string
576
+ # until version 3.1.2. So use that as backup here.
577
+ # WARNING: We create custom 'or none' validators since their
578
+ # availability seems less consistent across matplotlib versions.
579
+ _validate_pt = _validate_units("pt")
580
+ _validate_em = _validate_units("em")
581
+ _validate_in = _validate_units("in")
582
+ _validate_bool = msetup.validate_bool
583
+ _validate_int = msetup.validate_int
584
+ _validate_float = msetup.validate_float
585
+ _validate_string = msetup.validate_string
586
+ _validate_fontname = msetup.validate_stringlist # same as 'font.family'
587
+ _validate_fontweight = getattr(msetup, "validate_fontweight", _validate_string)
588
+
589
+ # Special style validators
590
+ # See: https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.FancyBboxPatch.html
591
+ _validate_boxstyle = _validate_belongs(
592
+ "square",
593
+ "circle",
594
+ "round",
595
+ "round4",
596
+ "sawtooth",
597
+ "roundtooth",
598
+ )
599
+ if hasattr(msetup, "_validate_linestyle"): # fancy validation including dashes
600
+ _validate_linestyle = msetup._validate_linestyle
601
+ else: # no dashes allowed then but no big deal
602
+ _validate_linestyle = _validate_belongs(
603
+ "-",
604
+ ":",
605
+ "--",
606
+ "-.",
607
+ "solid",
608
+ "dashed",
609
+ "dashdot",
610
+ "dotted",
611
+ "none",
612
+ " ",
613
+ "",
614
+ )
615
+
616
+ # Patch existing matplotlib validators.
617
+ # NOTE: validate_fontsizelist is unused in recent matplotlib versions and
618
+ # validate_colorlist is only used with prop cycle eval (which we don't care about)
619
+ font_scalings["med"] = 1.0 # consistent shorthand
620
+ font_scalings["med-small"] = 0.9 # add scaling
621
+ font_scalings["med-large"] = 1.1 # add scaling
622
+ if not hasattr(RcParams, "validate"): # not mission critical so skip
623
+ warnings._warn_ultraplot("Failed to update matplotlib rcParams validators.")
624
+ else:
625
+ _validate = RcParams.validate
626
+ _validate["image.cmap"] = _validate_cmap("continuous")
627
+ _validate["legend.loc"] = _validate_belongs(*LEGEND_LOCS)
628
+ for _key, _validator in _validate.items():
629
+ if _validator is getattr(msetup, "validate_fontsize", None): # should exist
630
+ FONT_KEYS.add(_key)
631
+ _validate[_key] = _validate_fontsize
632
+ if _validator is getattr(msetup, "validate_fontsize_None", None):
633
+ FONT_KEYS.add(_key)
634
+ _validate[_key] = _validate_or_none(_validate_fontsize)
635
+ if _validator is getattr(msetup, "validate_font_properties", None):
636
+ _validate[_key] = _validate_fontprops
637
+ if _validator is getattr(msetup, "validate_color", None): # should exist
638
+ _validate[_key] = _validate_color
639
+ if _validator is getattr(msetup, "validate_color_or_auto", None):
640
+ _validate[_key] = functools.partial(_validate_color, alternative="auto")
641
+ if _validator is getattr(msetup, "validate_color_or_inherit", None):
642
+ _validate[_key] = functools.partial(_validate_color, alternative="inherit")
643
+ for _keys, _validator_replace in ((EM_KEYS, _validate_em), (PT_KEYS, _validate_pt)):
644
+ for _key in _keys:
645
+ _validator = _validate.get(_key, None)
646
+ if _validator is None:
647
+ continue
648
+ if _validator is msetup.validate_float:
649
+ _validate[_key] = _validator_replace
650
+ if _validator is getattr(msetup, "validate_float_or_None"):
651
+ _validate[_key] = _validate_or_none(_validator_replace)
652
+
653
+
654
+ # ultraplot overrides of matplotlib default style
655
+ # WARNING: Critical to include every parameter here that can be changed by a
656
+ # "meta" setting so that _get_default_param returns the value imposed by *ultraplot*
657
+ # and so that "changed" settings detected by Configurator.save are correct.
658
+ _rc_matplotlib_default = {
659
+ "axes.axisbelow": GRIDBELOW,
660
+ "axes.formatter.use_mathtext": MATHTEXT,
661
+ "axes.grid": True, # enable lightweight transparent grid by default
662
+ "axes.grid.which": "major",
663
+ "axes.edgecolor": BLACK,
664
+ "axes.labelcolor": BLACK,
665
+ "axes.labelpad": LABELPAD, # more compact
666
+ "axes.labelsize": SMALLSIZE,
667
+ "axes.labelweight": "normal",
668
+ "axes.linewidth": LINEWIDTH,
669
+ "axes.titlepad": TITLEPAD, # more compact
670
+ "axes.titlesize": LARGESIZE,
671
+ "axes.titleweight": "normal",
672
+ "axes.xmargin": MARGIN,
673
+ "axes.ymargin": MARGIN,
674
+ "errorbar.capsize": 3.0,
675
+ "figure.autolayout": False,
676
+ "figure.figsize": (4.0, 4.0), # for interactife backends
677
+ "figure.dpi": 100,
678
+ "figure.facecolor": "#f4f4f4", # similar to MATLAB interface
679
+ "figure.titlesize": LARGESIZE,
680
+ "figure.titleweight": "bold", # differentiate from axes titles
681
+ "font.serif": [
682
+ "TeX Gyre Schola", # Century lookalike
683
+ "TeX Gyre Bonum", # Bookman lookalike
684
+ "TeX Gyre Termes", # Times New Roman lookalike
685
+ "TeX Gyre Pagella", # Palatino lookalike
686
+ "DejaVu Serif",
687
+ "Bitstream Vera Serif",
688
+ "Computer Modern Roman",
689
+ "Bookman",
690
+ "Century Schoolbook L",
691
+ "Charter",
692
+ "ITC Bookman",
693
+ "New Century Schoolbook",
694
+ "Nimbus Roman No9 L",
695
+ "Noto Serif",
696
+ "Palatino",
697
+ "Source Serif Pro",
698
+ "Times New Roman",
699
+ "Times",
700
+ "Utopia",
701
+ "serif",
702
+ ],
703
+ "font.sans-serif": [
704
+ "TeX Gyre Heros", # Helvetica lookalike
705
+ "DejaVu Sans",
706
+ "Bitstream Vera Sans",
707
+ "Computer Modern Sans Serif",
708
+ "Arial",
709
+ "Avenir",
710
+ "Fira Math",
711
+ "Fira Sans",
712
+ "Frutiger",
713
+ "Geneva",
714
+ "Gill Sans",
715
+ "Helvetica",
716
+ "Lucid",
717
+ "Lucida Grande",
718
+ "Myriad Pro",
719
+ "Noto Sans",
720
+ "Roboto",
721
+ "Source Sans Pro",
722
+ "Tahoma",
723
+ "Trebuchet MS",
724
+ "Ubuntu",
725
+ "Univers",
726
+ "Verdana",
727
+ "sans-serif",
728
+ ],
729
+ "font.cursive": [
730
+ "TeX Gyre Chorus", # Chancery lookalike
731
+ "Apple Chancery",
732
+ "Felipa",
733
+ "Sand",
734
+ "Script MT",
735
+ "Textile",
736
+ "Zapf Chancery",
737
+ "cursive",
738
+ ],
739
+ "font.fantasy": [
740
+ "TeX Gyre Adventor", # Avant Garde lookalike
741
+ "Avant Garde",
742
+ "Charcoal",
743
+ "Chicago",
744
+ "Comic Sans MS",
745
+ "Futura",
746
+ "Humor Sans",
747
+ "Impact",
748
+ "Optima",
749
+ "Western",
750
+ "xkcd",
751
+ "fantasy",
752
+ ],
753
+ "font.monospace": [
754
+ "TeX Gyre Cursor", # Courier lookalike
755
+ "DejaVu Sans Mono",
756
+ "Bitstream Vera Sans Mono",
757
+ "Computer Modern Typewriter",
758
+ "Andale Mono",
759
+ "Courier New",
760
+ "Courier",
761
+ "Fixed",
762
+ "Nimbus Mono L",
763
+ "Terminal",
764
+ "monospace",
765
+ ],
766
+ "font.family": FONTNAME,
767
+ "font.size": FONTSIZE,
768
+ "grid.alpha": GRIDALPHA, # lightweight unobtrusive gridlines
769
+ "grid.color": BLACK, # lightweight unobtrusive gridlines
770
+ "grid.linestyle": GRIDSTYLE,
771
+ "grid.linewidth": LINEWIDTH,
772
+ "hatch.color": BLACK,
773
+ "hatch.linewidth": LINEWIDTH,
774
+ "image.cmap": CMAPSEQ,
775
+ "image.interpolation": "none",
776
+ "lines.linestyle": "-",
777
+ "lines.linewidth": 1.5,
778
+ "lines.markersize": 6.0,
779
+ "legend.borderaxespad": 0, # i.e. flush against edge
780
+ "legend.borderpad": 0.5, # a bit more roomy
781
+ "legend.columnspacing": 1.5, # a bit more compact (see handletextpad)
782
+ "legend.edgecolor": BLACK,
783
+ "legend.facecolor": WHITE,
784
+ "legend.fancybox": False, # i.e. BboxStyle 'square' not 'round'
785
+ "legend.fontsize": SMALLSIZE,
786
+ "legend.framealpha": FRAMEALPHA,
787
+ "legend.handleheight": 1.0, # default is 0.7
788
+ "legend.handlelength": 2.0, # default is 2.0
789
+ "legend.handletextpad": 0.5, # a bit more compact (see columnspacing)
790
+ "mathtext.default": "it",
791
+ "mathtext.fontset": "custom",
792
+ "mathtext.bf": "regular:bold", # custom settings implemented above
793
+ "mathtext.cal": "cursive",
794
+ "mathtext.it": "regular:italic",
795
+ "mathtext.rm": "regular",
796
+ "mathtext.sf": "regular",
797
+ "mathtext.tt": "monospace",
798
+ "patch.linewidth": LINEWIDTH,
799
+ "savefig.bbox": None, # do not use 'tight'
800
+ "savefig.directory": "", # use the working directory
801
+ "savefig.dpi": 1000, # use academic journal recommendation
802
+ "savefig.facecolor": WHITE, # use white instead of 'auto'
803
+ "savefig.format": "pdf", # use vector graphics
804
+ "savefig.transparent": False,
805
+ "xtick.color": BLACK,
806
+ "xtick.direction": TICKDIR,
807
+ "xtick.labelsize": SMALLSIZE,
808
+ "xtick.major.pad": TICKPAD,
809
+ "xtick.major.size": TICKLEN,
810
+ "xtick.major.width": LINEWIDTH,
811
+ "xtick.minor.pad": TICKPAD,
812
+ "xtick.minor.size": TICKLEN * TICKLENRATIO,
813
+ "xtick.minor.width": LINEWIDTH * TICKWIDTHRATIO,
814
+ "xtick.minor.visible": TICKMINOR,
815
+ "ytick.color": BLACK,
816
+ "ytick.direction": TICKDIR,
817
+ "ytick.labelsize": SMALLSIZE,
818
+ "ytick.major.pad": TICKPAD,
819
+ "ytick.major.size": TICKLEN,
820
+ "ytick.major.width": LINEWIDTH,
821
+ "ytick.minor.pad": TICKPAD,
822
+ "ytick.minor.size": TICKLEN * TICKLENRATIO,
823
+ "ytick.minor.width": LINEWIDTH * TICKWIDTHRATIO,
824
+ "ytick.minor.visible": TICKMINOR,
825
+ }
826
+ if "mathtext.fallback" in _rc_matplotlib_native:
827
+ _rc_matplotlib_default["mathtext.fallback"] = "stixsans"
828
+
829
+ # ultraplot pseudo-setting defaults, validators, and descriptions
830
+ # NOTE: Cannot have different a-b-c and title paddings because they are both controlled
831
+ # by matplotlib's _title_offset_trans transform and want to keep them aligned anyway.
832
+ _addendum_rotation = " Must be 'vertical', 'horizontal', or a float indicating degrees."
833
+ _addendum_em = " Interpreted by `~ultraplot.utils.units`. Numeric units are em-widths."
834
+ _addendum_in = " Interpreted by `~ultraplot.utils.units`. Numeric units are inches."
835
+ _addendum_pt = " Interpreted by `~ultraplot.utils.units`. Numeric units are points."
836
+ _addendum_font = (
837
+ " Must be a :ref:`relative font size <font_table>` or unit string "
838
+ "interpreted by `~ultraplot.utils.units`. Numeric units are points."
839
+ )
840
+ _rc_ultraplot_table = {
841
+ # Stylesheet
842
+ "style": (
843
+ None,
844
+ _validate_or_none(_validate_string),
845
+ "The default matplotlib `stylesheet "
846
+ "<https://matplotlib.org/stable/gallery/style_sheets/style_sheets_reference.html>`__ " # noqa: E501
847
+ "name. If ``None``, a custom ultraplot style is used. "
848
+ "If ``'default'``, the default matplotlib style is used.",
849
+ ),
850
+ # A-b-c labels
851
+ "abc": (
852
+ False,
853
+ _validate_abc,
854
+ "If ``False`` then a-b-c labels are disabled. If ``True`` the default label "
855
+ "style ``a`` is used. If string this indicates the style and must contain the "
856
+ "character ``a`` or ``A``, for example ``'a.'`` or ``'(A)'``.",
857
+ ),
858
+ "abc.border": (
859
+ True,
860
+ _validate_bool,
861
+ "Whether to draw a white border around a-b-c labels "
862
+ "when :rcraw:`abc.loc` is inside the axes.",
863
+ ),
864
+ "abc.borderwidth": (
865
+ 1.5,
866
+ _validate_pt,
867
+ "Width of the white border around a-b-c labels.",
868
+ ),
869
+ "abc.bbox": (
870
+ False,
871
+ _validate_bool,
872
+ "Whether to draw semi-transparent bounding boxes around a-b-c labels "
873
+ "when :rcraw:`abc.loc` is inside the axes.",
874
+ ),
875
+ "abc.bboxcolor": (WHITE, _validate_color, "a-b-c label bounding box color."),
876
+ "abc.bboxstyle": ("square", _validate_boxstyle, "a-b-c label bounding box style."),
877
+ "abc.bboxalpha": (0.5, _validate_float, "a-b-c label bounding box opacity."),
878
+ "abc.bboxpad": (
879
+ None,
880
+ _validate_or_none(_validate_pt),
881
+ "Padding for the a-b-c label bounding box. By default this is scaled "
882
+ "to make the box flush against the subplot edge." + _addendum_pt,
883
+ ),
884
+ "abc.color": (BLACK, _validate_color, "a-b-c label color."),
885
+ "abc.loc": (
886
+ "left", # left side above the axes
887
+ _validate_belongs(*TEXT_LOCS),
888
+ "a-b-c label position. "
889
+ "For options see the :ref:`location table <title_table>`.",
890
+ ),
891
+ "abc.size": (
892
+ LARGESIZE,
893
+ _validate_fontsize,
894
+ "a-b-c label font size." + _addendum_font,
895
+ ),
896
+ "abc.titlepad": (
897
+ LABELPAD,
898
+ _validate_pt,
899
+ "Padding separating the title and a-b-c label when in the same location."
900
+ + _addendum_pt,
901
+ ),
902
+ "abc.weight": ("bold", _validate_fontweight, "a-b-c label font weight."),
903
+ # Autoformatting
904
+ "autoformat": (
905
+ True,
906
+ _validate_bool,
907
+ "Whether to automatically apply labels from `pandas.Series`, "
908
+ "`pandas.DataFrame`, and `xarray.DataArray` objects passed to "
909
+ "plotting functions. See also :rcraw:`unitformat`.",
910
+ ),
911
+ # Axes additions
912
+ "axes.alpha": (
913
+ None,
914
+ _validate_or_none(_validate_float),
915
+ "Opacity of the background axes patch.",
916
+ ),
917
+ "axes.inbounds": (
918
+ True,
919
+ _validate_bool,
920
+ "Whether to exclude out-of-bounds data when determining the default *y* (*x*) "
921
+ "axis limits and the *x* (*y*) axis limits have been locked.",
922
+ ),
923
+ "axes.margin": (
924
+ MARGIN,
925
+ _validate_float,
926
+ "The fractional *x* and *y* axis margins when limits are unset.",
927
+ ),
928
+ # Country borders
929
+ "borders": (False, _validate_bool, "Toggles country border lines on and off."),
930
+ "borders.alpha": (
931
+ None,
932
+ _validate_or_none(_validate_float),
933
+ "Opacity for country border lines.",
934
+ ),
935
+ "borders.color": (BLACK, _validate_color, "Line color for country border lines."),
936
+ "borders.linewidth": (
937
+ LINEWIDTH,
938
+ _validate_pt,
939
+ "Line width for country border lines.",
940
+ ),
941
+ "borders.zorder": (ZLINES, _validate_float, "Z-order for country border lines."),
942
+ # Bottom subplot labels
943
+ "bottomlabel.color": (
944
+ BLACK,
945
+ _validate_color,
946
+ "Font color for column labels on the bottom of the figure.",
947
+ ),
948
+ "bottomlabel.pad": (
949
+ TITLEPAD,
950
+ _validate_pt,
951
+ "Padding between axes content and column labels on the bottom of the figure."
952
+ + _addendum_pt,
953
+ ),
954
+ "bottomlabel.rotation": (
955
+ "horizontal",
956
+ _validate_rotation,
957
+ "Rotation for column labels at the bottom of the figure." + _addendum_rotation,
958
+ ),
959
+ "bottomlabel.size": (
960
+ LARGESIZE,
961
+ _validate_fontsize,
962
+ "Font size for column labels on the bottom of the figure." + _addendum_font,
963
+ ),
964
+ "bottomlabel.weight": (
965
+ "bold",
966
+ _validate_fontweight,
967
+ "Font weight for column labels on the bottom of the figure.",
968
+ ),
969
+ # Coastlines
970
+ "coast": (False, _validate_bool, "Toggles coastline lines on and off."),
971
+ "coast.alpha": (
972
+ None,
973
+ _validate_or_none(_validate_float),
974
+ "Opacity for coast lines",
975
+ ),
976
+ "coast.color": (BLACK, _validate_color, "Line color for coast lines."),
977
+ "coast.linewidth": (LINEWIDTH, _validate_pt, "Line width for coast lines."),
978
+ "coast.zorder": (ZLINES, _validate_float, "Z-order for coast lines."),
979
+ # Colorbars
980
+ "colorbar.edgecolor": (
981
+ BLACK,
982
+ _validate_color,
983
+ "Color for the inset colorbar frame edge.",
984
+ ),
985
+ "colorbar.extend": (
986
+ 1.3,
987
+ _validate_em,
988
+ 'Length of rectangular or triangular "extensions" for panel colorbars.'
989
+ + _addendum_em,
990
+ ),
991
+ "colorbar.fancybox": (
992
+ False,
993
+ _validate_bool,
994
+ 'Whether to use a "fancy" round bounding box for inset colorbar frames.',
995
+ ),
996
+ "colorbar.framealpha": (
997
+ FRAMEALPHA,
998
+ _validate_float,
999
+ "Opacity for inset colorbar frames.",
1000
+ ),
1001
+ "colorbar.facecolor": (
1002
+ WHITE,
1003
+ _validate_color,
1004
+ "Color for the inset colorbar frame.",
1005
+ ),
1006
+ "colorbar.frameon": (
1007
+ True,
1008
+ _validate_bool,
1009
+ "Whether to draw a frame behind inset colorbars.",
1010
+ ),
1011
+ "colorbar.grid": (
1012
+ False,
1013
+ _validate_bool,
1014
+ "Whether to draw borders between each level of the colorbar.",
1015
+ ),
1016
+ "colorbar.insetextend": (
1017
+ 0.9,
1018
+ _validate_em,
1019
+ 'Length of rectangular or triangular "extensions" for inset colorbars.'
1020
+ + _addendum_em,
1021
+ ),
1022
+ "colorbar.insetlength": (
1023
+ 8,
1024
+ _validate_em,
1025
+ "Length of inset colorbars." + _addendum_em,
1026
+ ),
1027
+ "colorbar.insetpad": (
1028
+ 0.7,
1029
+ _validate_em,
1030
+ "Padding between axes edge and inset colorbars." + _addendum_em,
1031
+ ),
1032
+ "colorbar.insetwidth": (
1033
+ 1.2,
1034
+ _validate_em,
1035
+ "Width of inset colorbars." + _addendum_em,
1036
+ ),
1037
+ "colorbar.length": (1, _validate_em, "Length of outer colorbars."),
1038
+ "colorbar.loc": (
1039
+ "right",
1040
+ _validate_belongs(*COLORBAR_LOCS),
1041
+ "Inset colorbar location. "
1042
+ "For options see the :ref:`location table <colorbar_table>`.",
1043
+ ),
1044
+ "colorbar.width": (0.2, _validate_in, "Width of outer colorbars." + _addendum_in),
1045
+ "colorbar.rasterized": (
1046
+ False,
1047
+ _validate_bool,
1048
+ "Whether to use rasterization for colorbar solids.",
1049
+ ),
1050
+ "colorbar.shadow": (
1051
+ False,
1052
+ _validate_bool,
1053
+ "Whether to add a shadow underneath inset colorbar frames.",
1054
+ ),
1055
+ # Color cycle additions
1056
+ "cycle": (
1057
+ CYCLE,
1058
+ _validate_cmap("discrete"),
1059
+ "Name of the color cycle assigned to :rcraw:`axes.prop_cycle`.",
1060
+ ),
1061
+ # Colormap additions
1062
+ "cmap": (
1063
+ CMAPSEQ,
1064
+ _validate_cmap("continuous"),
1065
+ "Alias for :rcraw:`cmap.sequential` and :rcraw:`image.cmap`.",
1066
+ ),
1067
+ "cmap.autodiverging": (
1068
+ True,
1069
+ _validate_bool,
1070
+ "Whether to automatically apply a diverging colormap and "
1071
+ "normalizer based on the data.",
1072
+ ),
1073
+ "cmap.qualitative": (
1074
+ CMAPCAT,
1075
+ _validate_cmap("discrete"),
1076
+ "Default colormap for qualitative datasets.",
1077
+ ),
1078
+ "cmap.cyclic": (
1079
+ CMAPCYC,
1080
+ _validate_cmap("continuous"),
1081
+ "Default colormap for cyclic datasets.",
1082
+ ),
1083
+ "cmap.discrete": (
1084
+ None,
1085
+ _validate_or_none(_validate_bool),
1086
+ "If ``True``, `~ultraplot.colors.DiscreteNorm` is used for every colormap plot. "
1087
+ "If ``False``, it is never used. If ``None``, it is used for all plot types "
1088
+ "except `imshow`, `matshow`, `spy`, `hexbin`, and `hist2d`.",
1089
+ ),
1090
+ "cmap.diverging": (
1091
+ CMAPDIV,
1092
+ _validate_cmap("continuous"),
1093
+ "Default colormap for diverging datasets.",
1094
+ ),
1095
+ "cmap.inbounds": (
1096
+ True,
1097
+ _validate_bool,
1098
+ "If ``True`` and the *x* and *y* axis limits are fixed, only in-bounds data "
1099
+ "is considered when determining the default colormap `vmin` and `vmax`.",
1100
+ ),
1101
+ "cmap.levels": (
1102
+ 11,
1103
+ _validate_int,
1104
+ "Default number of `~ultraplot.colors.DiscreteNorm` levels for plotting "
1105
+ "commands that use colormaps.",
1106
+ ),
1107
+ "cmap.listedthresh": (
1108
+ 64,
1109
+ _validate_int,
1110
+ "Native `~matplotlib.colors.ListedColormap`\\ s with more colors than "
1111
+ "this are converted to `~ultraplot.colors.ContinuousColormap` rather than "
1112
+ "`~ultraplot.colors.DiscreteColormap`. This helps translate continuous "
1113
+ "colormaps from external projects.",
1114
+ ),
1115
+ "cmap.lut": (
1116
+ 256,
1117
+ _validate_int,
1118
+ "Number of colors in the colormap lookup table. "
1119
+ "Alias for :rcraw:`image.lut`.",
1120
+ ),
1121
+ "cmap.robust": (
1122
+ False,
1123
+ _validate_bool,
1124
+ "If ``True``, the default colormap `vmin` and `vmax` are chosen using the "
1125
+ "2nd to 98th percentiles rather than the minimum and maximum.",
1126
+ ),
1127
+ "cmap.sequential": (
1128
+ CMAPSEQ,
1129
+ _validate_cmap("continuous"),
1130
+ "Default colormap for sequential datasets. Alias for :rcraw:`image.cmap`.",
1131
+ ),
1132
+ # Special setting
1133
+ "edgefix": (
1134
+ True,
1135
+ _validate_bool,
1136
+ 'Whether to fix issues with "white lines" appearing between patches '
1137
+ "in saved vector graphics and with vector graphic backends. Applies "
1138
+ "to colorbar levels and bar, area, pcolor, and contour plots.",
1139
+ ),
1140
+ # Font settings
1141
+ "font.name": (FONTNAME, _validate_fontname, "Alias for :rcraw:`font.family`."),
1142
+ "font.small": (SMALLSIZE, _validate_fontsize, "Alias for :rcraw:`font.smallsize`."),
1143
+ "font.smallsize": (
1144
+ SMALLSIZE,
1145
+ _validate_fontsize,
1146
+ "Meta setting that changes the label-like sizes ``axes.labelsize``, "
1147
+ "``legend.fontsize``, ``tick.labelsize``, and ``grid.labelsize``. Default is "
1148
+ "``'medium'`` (equivalent to :rcraw:`font.size`)." + _addendum_font,
1149
+ ),
1150
+ "font.large": (LARGESIZE, _validate_fontsize, "Alias for :rcraw:`font.largesize`."),
1151
+ "font.largesize": (
1152
+ LARGESIZE,
1153
+ _validate_fontsize,
1154
+ "Meta setting that changes the title-like sizes ``abc.size``, ``title.size``, "
1155
+ "``suptitle.size``, ``leftlabel.size``, ``rightlabel.size``, etc. Default is "
1156
+ "``'med-large'`` (i.e. 1.1 times :rcraw:`font.size`)." + _addendum_font,
1157
+ ),
1158
+ # Formatter settings
1159
+ "formatter.timerotation": (
1160
+ "vertical",
1161
+ _validate_rotation,
1162
+ "Rotation for *x* axis datetime tick labels." + _addendum_rotation,
1163
+ ),
1164
+ "formatter.zerotrim": (
1165
+ True,
1166
+ _validate_bool,
1167
+ "Whether to trim trailing decimal zeros on tick labels.",
1168
+ ),
1169
+ "formatter.limits": (
1170
+ [-5, 6], # must be list or else validated
1171
+ _validate["axes.formatter.limits"],
1172
+ "Alias for :rcraw:`axes.formatter.limits`.",
1173
+ ),
1174
+ "formatter.min_exponent": (
1175
+ 0,
1176
+ _validate["axes.formatter.min_exponent"],
1177
+ "Alias for :rcraw:`axes.formatter.min_exponent`.",
1178
+ ),
1179
+ "formatter.offset_threshold": (
1180
+ 4,
1181
+ _validate["axes.formatter.offset_threshold"],
1182
+ "Alias for :rcraw:`axes.formatter.offset_threshold`.",
1183
+ ),
1184
+ "formatter.use_locale": (
1185
+ False,
1186
+ _validate_bool,
1187
+ "Alias for :rcraw:`axes.formatter.use_locale`.",
1188
+ ),
1189
+ "formatter.use_mathtext": (
1190
+ MATHTEXT,
1191
+ _validate_bool,
1192
+ "Alias for :rcraw:`axes.formatter.use_mathtext`.",
1193
+ ),
1194
+ "formatter.use_offset": (
1195
+ True,
1196
+ _validate_bool,
1197
+ "Alias for :rcraw:`axes.formatter.useOffset`.",
1198
+ ),
1199
+ # Geographic axes settings
1200
+ "geo.backend": (
1201
+ "cartopy",
1202
+ _validate_belongs("cartopy", "basemap"),
1203
+ "The backend used for `~ultraplot.axes.GeoAxes`. Must be "
1204
+ "either 'cartopy' or 'basemap'.",
1205
+ ),
1206
+ "geo.extent": (
1207
+ "globe",
1208
+ _validate_belongs("globe", "auto"),
1209
+ "If ``'globe'``, the extent of cartopy `~ultraplot.axes.GeoAxes` is always "
1210
+ "global. If ``'auto'``, the extent is automatically adjusted based on "
1211
+ "plotted content. Default is ``'globe'``.",
1212
+ ),
1213
+ "geo.round": (
1214
+ True,
1215
+ _validate_bool,
1216
+ "If ``True`` (the default), polar `~ultraplot.axes.GeoAxes` like ``'npstere'`` "
1217
+ "and ``'spstere'`` are bounded with circles rather than squares.",
1218
+ ),
1219
+ # Gridlines
1220
+ # NOTE: Here 'grid' and 'gridminor' or *not* aliases for native 'axes.grid' and
1221
+ # invented 'axes.gridminor' because native 'axes.grid' controls both major *and*
1222
+ # minor gridlines. Must handle it independently from these settings.
1223
+ "grid": (True, _validate_bool, "Toggle major gridlines on and off."),
1224
+ "grid.below": (
1225
+ GRIDBELOW, # like axes.axisbelow
1226
+ _validate_belongs(False, "line", True),
1227
+ "Alias for :rcraw:`axes.axisbelow`. If ``True``, draw gridlines below "
1228
+ "everything. If ``True``, draw them above everything. If ``'line'``, "
1229
+ "draw them above patches but below lines and markers.",
1230
+ ),
1231
+ "grid.checkoverlap": (
1232
+ True,
1233
+ _validate_bool,
1234
+ "Whether to have cartopy automatically check for and remove overlapping "
1235
+ "`~ultraplot.axes.GeoAxes` gridline labels.",
1236
+ ),
1237
+ "grid.dmslabels": (
1238
+ True,
1239
+ _validate_bool,
1240
+ "Whether to use degrees-minutes-seconds rather than decimals for "
1241
+ "cartopy `~ultraplot.axes.GeoAxes` gridlines.",
1242
+ ),
1243
+ "grid.geolabels": (
1244
+ True,
1245
+ _validate_bool,
1246
+ "Whether to include the ``'geo'`` spine in cartopy >= 0.20 when otherwise "
1247
+ "toggling left, right, bottom, or top `~ultraplot.axes.GeoAxes` gridline labels.",
1248
+ ),
1249
+ "grid.inlinelabels": (
1250
+ False,
1251
+ _validate_bool,
1252
+ "Whether to add inline labels for cartopy `~ultraplot.axes.GeoAxes` gridlines.",
1253
+ ),
1254
+ "grid.labels": (
1255
+ False,
1256
+ _validate_bool,
1257
+ "Whether to add outer labels for `~ultraplot.axes.GeoAxes` gridlines.",
1258
+ ),
1259
+ "grid.labelcolor": (
1260
+ BLACK,
1261
+ _validate_color,
1262
+ "Font color for `~ultraplot.axes.GeoAxes` gridline labels.",
1263
+ ),
1264
+ "grid.labelpad": (
1265
+ GRIDPAD,
1266
+ _validate_pt,
1267
+ "Padding between the map boundary and cartopy `~ultraplot.axes.GeoAxes` "
1268
+ "gridline labels." + _addendum_pt,
1269
+ ),
1270
+ "grid.labelsize": (
1271
+ SMALLSIZE,
1272
+ _validate_fontsize,
1273
+ "Font size for `~ultraplot.axes.GeoAxes` gridline labels." + _addendum_font,
1274
+ ),
1275
+ "grid.labelweight": (
1276
+ "normal",
1277
+ _validate_fontweight,
1278
+ "Font weight for `~ultraplot.axes.GeoAxes` gridline labels.",
1279
+ ),
1280
+ "grid.nsteps": (
1281
+ 250,
1282
+ _validate_int,
1283
+ "Number of points used to draw cartopy `~ultraplot.axes.GeoAxes` gridlines.",
1284
+ ),
1285
+ "grid.pad": (GRIDPAD, _validate_pt, "Alias for :rcraw:`grid.labelpad`."),
1286
+ "grid.rotatelabels": (
1287
+ False, # False limits projections where labels are available
1288
+ _validate_bool,
1289
+ "Whether to rotate cartopy `~ultraplot.axes.GeoAxes` gridline labels.",
1290
+ ),
1291
+ "grid.style": (
1292
+ "-",
1293
+ _validate_linestyle,
1294
+ "Major gridline style. Alias for :rcraw:`grid.linestyle`.",
1295
+ ),
1296
+ "grid.width": (
1297
+ LINEWIDTH,
1298
+ _validate_pt,
1299
+ "Major gridline width. Alias for :rcraw:`grid.linewidth`.",
1300
+ ),
1301
+ "grid.widthratio": (
1302
+ GRIDRATIO,
1303
+ _validate_float,
1304
+ "Ratio of minor gridline width to major gridline width.",
1305
+ ),
1306
+ # Minor gridlines
1307
+ "gridminor": (False, _validate_bool, "Toggle minor gridlines on and off."),
1308
+ "gridminor.alpha": (GRIDALPHA, _validate_float, "Minor gridline opacity."),
1309
+ "gridminor.color": (BLACK, _validate_color, "Minor gridline color."),
1310
+ "gridminor.linestyle": (GRIDSTYLE, _validate_linestyle, "Minor gridline style."),
1311
+ "gridminor.linewidth": (
1312
+ GRIDRATIO * LINEWIDTH,
1313
+ _validate_pt,
1314
+ "Minor gridline width.",
1315
+ ),
1316
+ "gridminor.style": (
1317
+ GRIDSTYLE,
1318
+ _validate_linestyle,
1319
+ "Minor gridline style. Alias for :rcraw:`gridminor.linestyle`.",
1320
+ ),
1321
+ "gridminor.width": (
1322
+ GRIDRATIO * LINEWIDTH,
1323
+ _validate_pt,
1324
+ "Minor gridline width. Alias for :rcraw:`gridminor.linewidth`.",
1325
+ ),
1326
+ # Backend stuff
1327
+ "inlineformat": (
1328
+ "retina",
1329
+ _validate_belongs("svg", "pdf", "retina", "png", "jpeg"),
1330
+ "The inline backend figure format. Valid formats include "
1331
+ "``'svg'``, ``'pdf'``, ``'retina'``, ``'png'``, and ``jpeg``.",
1332
+ ),
1333
+ # Inner borders
1334
+ "innerborders": (
1335
+ False,
1336
+ _validate_bool,
1337
+ "Toggles internal political border lines (e.g. states and provinces) "
1338
+ "on and off.",
1339
+ ),
1340
+ "innerborders.alpha": (
1341
+ None,
1342
+ _validate_or_none(_validate_float),
1343
+ "Opacity for internal political border lines",
1344
+ ),
1345
+ "innerborders.color": (
1346
+ BLACK,
1347
+ _validate_color,
1348
+ "Line color for internal political border lines.",
1349
+ ),
1350
+ "innerborders.linewidth": (
1351
+ LINEWIDTH,
1352
+ _validate_pt,
1353
+ "Line width for internal political border lines.",
1354
+ ),
1355
+ "innerborders.zorder": (
1356
+ ZLINES,
1357
+ _validate_float,
1358
+ "Z-order for internal political border lines.",
1359
+ ),
1360
+ # Axis label settings
1361
+ "label.color": (BLACK, _validate_color, "Alias for :rcraw:`axes.labelcolor`."),
1362
+ "label.pad": (
1363
+ LABELPAD,
1364
+ _validate_pt,
1365
+ "Alias for :rcraw:`axes.labelpad`." + _addendum_pt,
1366
+ ),
1367
+ "label.size": (
1368
+ SMALLSIZE,
1369
+ _validate_fontsize,
1370
+ "Alias for :rcraw:`axes.labelsize`." + _addendum_font,
1371
+ ),
1372
+ "label.weight": (
1373
+ "normal",
1374
+ _validate_fontweight,
1375
+ "Alias for :rcraw:`axes.labelweight`.",
1376
+ ),
1377
+ # Lake patches
1378
+ "lakes": (False, _validate_bool, "Toggles lake patches on and off."),
1379
+ "lakes.alpha": (
1380
+ None,
1381
+ _validate_or_none(_validate_float),
1382
+ "Opacity for lake patches",
1383
+ ),
1384
+ "lakes.color": (WHITE, _validate_color, "Face color for lake patches."),
1385
+ "lakes.zorder": (ZPATCHES, _validate_float, "Z-order for lake patches."),
1386
+ # Land patches
1387
+ "land": (False, _validate_bool, "Toggles land patches on and off."),
1388
+ "land.alpha": (
1389
+ None,
1390
+ _validate_or_none(_validate_float),
1391
+ "Opacity for land patches",
1392
+ ),
1393
+ "land.color": (BLACK, _validate_color, "Face color for land patches."),
1394
+ "land.zorder": (ZPATCHES, _validate_float, "Z-order for land patches."),
1395
+ # Left subplot labels
1396
+ "leftlabel.color": (
1397
+ BLACK,
1398
+ _validate_color,
1399
+ "Font color for row labels on the left-hand side.",
1400
+ ),
1401
+ "leftlabel.pad": (
1402
+ TITLEPAD,
1403
+ _validate_pt,
1404
+ "Padding between axes content and row labels on the left-hand side."
1405
+ + _addendum_pt,
1406
+ ),
1407
+ "leftlabel.rotation": (
1408
+ "vertical",
1409
+ _validate_rotation,
1410
+ "Rotation for row labels on the left-hand side." + _addendum_rotation,
1411
+ ),
1412
+ "leftlabel.size": (
1413
+ LARGESIZE,
1414
+ _validate_fontsize,
1415
+ "Font size for row labels on the left-hand side." + _addendum_font,
1416
+ ),
1417
+ "leftlabel.weight": (
1418
+ "bold",
1419
+ _validate_fontweight,
1420
+ "Font weight for row labels on the left-hand side.",
1421
+ ),
1422
+ # Meta settings
1423
+ "margin": (
1424
+ MARGIN,
1425
+ _validate_float,
1426
+ "The fractional *x* and *y* axis data margins when limits are unset. "
1427
+ "Alias for :rcraw:`axes.margin`.",
1428
+ ),
1429
+ "meta.edgecolor": (
1430
+ BLACK,
1431
+ _validate_color,
1432
+ "Color of axis spines, tick marks, tick labels, and labels.",
1433
+ ),
1434
+ "meta.color": (
1435
+ BLACK,
1436
+ _validate_color,
1437
+ "Color of axis spines, tick marks, tick labels, and labels. "
1438
+ "Alias for :rcraw:`meta.edgecolor`.",
1439
+ ),
1440
+ "meta.linewidth": (
1441
+ LINEWIDTH,
1442
+ _validate_pt,
1443
+ "Thickness of axis spines and major tick lines.",
1444
+ ),
1445
+ "meta.width": (
1446
+ LINEWIDTH,
1447
+ _validate_pt,
1448
+ "Thickness of axis spines and major tick lines. "
1449
+ "Alias for :rcraw:`meta.linewidth`.",
1450
+ ),
1451
+ # For negative positive patches
1452
+ "negcolor": (
1453
+ "blue7",
1454
+ _validate_color,
1455
+ "Color for negative bars and shaded areas when using ``negpos=True``. "
1456
+ "See also :rcraw:`poscolor`.",
1457
+ ),
1458
+ "poscolor": (
1459
+ "red7",
1460
+ _validate_color,
1461
+ "Color for positive bars and shaded areas when using ``negpos=True``. "
1462
+ "See also :rcraw:`negcolor`.",
1463
+ ),
1464
+ # Ocean patches
1465
+ "ocean": (False, _validate_bool, "Toggles ocean patches on and off."),
1466
+ "ocean.alpha": (
1467
+ None,
1468
+ _validate_or_none(_validate_float),
1469
+ "Opacity for ocean patches",
1470
+ ),
1471
+ "ocean.color": (WHITE, _validate_color, "Face color for ocean patches."),
1472
+ "ocean.zorder": (ZPATCHES, _validate_float, "Z-order for ocean patches."),
1473
+ # Geographic resolution
1474
+ "reso": (
1475
+ "lo",
1476
+ _validate_belongs("lo", "med", "hi", "x-hi", "xx-hi"),
1477
+ "Resolution for `~ultraplot.axes.GeoAxes` geographic features. "
1478
+ "Must be one of ``'lo'``, ``'med'``, ``'hi'``, ``'x-hi'``, or ``'xx-hi'``.",
1479
+ ),
1480
+ # Right subplot labels
1481
+ "rightlabel.color": (
1482
+ BLACK,
1483
+ _validate_color,
1484
+ "Font color for row labels on the right-hand side.",
1485
+ ),
1486
+ "rightlabel.pad": (
1487
+ TITLEPAD,
1488
+ _validate_pt,
1489
+ "Padding between axes content and row labels on the right-hand side."
1490
+ + _addendum_pt,
1491
+ ),
1492
+ "rightlabel.rotation": (
1493
+ "vertical",
1494
+ _validate_rotation,
1495
+ "Rotation for row labels on the right-hand side." + _addendum_rotation,
1496
+ ),
1497
+ "rightlabel.size": (
1498
+ LARGESIZE,
1499
+ _validate_fontsize,
1500
+ "Font size for row labels on the right-hand side." + _addendum_font,
1501
+ ),
1502
+ "rightlabel.weight": (
1503
+ "bold",
1504
+ _validate_fontweight,
1505
+ "Font weight for row labels on the right-hand side.",
1506
+ ),
1507
+ # River lines
1508
+ "rivers": (False, _validate_bool, "Toggles river lines on and off."),
1509
+ "rivers.alpha": (
1510
+ None,
1511
+ _validate_or_none(_validate_float),
1512
+ "Opacity for river lines.",
1513
+ ),
1514
+ "rivers.color": (BLACK, _validate_color, "Line color for river lines."),
1515
+ "rivers.linewidth": (LINEWIDTH, _validate_pt, "Line width for river lines."),
1516
+ "rivers.zorder": (ZLINES, _validate_float, "Z-order for river lines."),
1517
+ # Subplots settings
1518
+ "subplots.align": (
1519
+ False,
1520
+ _validate_bool,
1521
+ "Whether to align axis labels during draw. See `aligning labels "
1522
+ "<https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html>`__.", # noqa: E501
1523
+ ),
1524
+ "subplots.equalspace": (
1525
+ False,
1526
+ _validate_bool,
1527
+ "Whether to make the tight layout algorithm assign the same space for "
1528
+ "every row and the same space for every column.",
1529
+ ),
1530
+ "subplots.groupspace": (
1531
+ True,
1532
+ _validate_bool,
1533
+ "Whether to make the tight layout algorithm consider space between only "
1534
+ 'adjacent subplot "groups" rather than every subplot in the row or column.',
1535
+ ),
1536
+ "subplots.innerpad": (
1537
+ 1,
1538
+ _validate_em,
1539
+ "Padding between adjacent subplots." + _addendum_em,
1540
+ ),
1541
+ "subplots.outerpad": (
1542
+ 0.5,
1543
+ _validate_em,
1544
+ "Padding around figure edge." + _addendum_em,
1545
+ ),
1546
+ "subplots.panelpad": (
1547
+ 0.5,
1548
+ _validate_em,
1549
+ "Padding between subplots and panels, and between stacked panels."
1550
+ + _addendum_em,
1551
+ ),
1552
+ "subplots.panelwidth": (0.5, _validate_in, "Width of side panels." + _addendum_in),
1553
+ "subplots.refwidth": (
1554
+ 2.5,
1555
+ _validate_in,
1556
+ "Default width of the reference subplot." + _addendum_in,
1557
+ ),
1558
+ "subplots.share": (
1559
+ True,
1560
+ _validate_belongs(0, 1, 2, 3, 4, False, "labels", "limits", True, "all"),
1561
+ "The axis sharing level, one of ``0``, ``1``, ``2``, or ``3``, or the "
1562
+ "more intuitive aliases ``False``, ``'labels'``, ``'limits'``, or ``True``. "
1563
+ "See `~ultraplot.figure.Figure` for details.",
1564
+ ),
1565
+ "subplots.span": (
1566
+ True,
1567
+ _validate_bool,
1568
+ "Toggles spanning axis labels. See `~ultraplot.ui.subplots` for details.",
1569
+ ),
1570
+ "subplots.tight": (
1571
+ True,
1572
+ _validate_bool,
1573
+ "Whether to auto-adjust the subplot spaces and figure margins.",
1574
+ ),
1575
+ # Super title settings
1576
+ "suptitle.color": (BLACK, _validate_color, "Figure title color."),
1577
+ "suptitle.pad": (
1578
+ TITLEPAD,
1579
+ _validate_pt,
1580
+ "Padding between axes content and the figure super title." + _addendum_pt,
1581
+ ),
1582
+ "suptitle.size": (
1583
+ LARGESIZE,
1584
+ _validate_fontsize,
1585
+ "Figure title font size." + _addendum_font,
1586
+ ),
1587
+ "suptitle.weight": ("bold", _validate_fontweight, "Figure title font weight."),
1588
+ # Tick settings
1589
+ "tick.color": (BLACK, _validate_color, "Major and minor tick color."),
1590
+ "tick.dir": (
1591
+ TICKDIR,
1592
+ _validate_belongs("in", "out", "inout"),
1593
+ "Major and minor tick direction. Must be one of "
1594
+ "``'out'``, ``'in'``, or ``'inout'``.",
1595
+ ),
1596
+ "tick.labelcolor": (BLACK, _validate_color, "Axis tick label color."),
1597
+ "tick.labelpad": (
1598
+ TICKPAD,
1599
+ _validate_pt,
1600
+ "Padding between ticks and tick labels." + _addendum_pt,
1601
+ ),
1602
+ "tick.labelsize": (
1603
+ SMALLSIZE,
1604
+ _validate_fontsize,
1605
+ "Axis tick label font size." + _addendum_font,
1606
+ ),
1607
+ "tick.labelweight": (
1608
+ "normal",
1609
+ _validate_fontweight,
1610
+ "Axis tick label font weight.",
1611
+ ),
1612
+ "tick.len": (TICKLEN, _validate_pt, "Length of major ticks in points."),
1613
+ "tick.lenratio": (
1614
+ TICKLENRATIO,
1615
+ _validate_float,
1616
+ "Ratio of minor tickline length to major tickline length.",
1617
+ ),
1618
+ "tick.linewidth": (LINEWIDTH, _validate_pt, "Major tickline width."),
1619
+ "tick.minor": (
1620
+ TICKMINOR,
1621
+ _validate_bool,
1622
+ "Toggles minor ticks on and off.",
1623
+ ),
1624
+ "tick.pad": (TICKPAD, _validate_pt, "Alias for :rcraw:`tick.labelpad`."),
1625
+ "tick.width": (
1626
+ LINEWIDTH,
1627
+ _validate_pt,
1628
+ "Major tickline width. Alias for :rcraw:`tick.linewidth`.",
1629
+ ),
1630
+ "tick.widthratio": (
1631
+ TICKWIDTHRATIO,
1632
+ _validate_float,
1633
+ "Ratio of minor tickline width to major tickline width.",
1634
+ ),
1635
+ # Title settings
1636
+ "title.above": (
1637
+ True,
1638
+ _validate_belongs(False, True, "panels"),
1639
+ "Whether to move outer titles and a-b-c labels above panels, colorbars, or "
1640
+ "legends that are above the axes. If the string 'panels' then text is only "
1641
+ "redirected above axes panels. Otherwise should be boolean.",
1642
+ ),
1643
+ "title.border": (
1644
+ True,
1645
+ _validate_bool,
1646
+ "Whether to draw a white border around titles "
1647
+ "when :rcraw:`title.loc` is inside the axes.",
1648
+ ),
1649
+ "title.borderwidth": (1.5, _validate_pt, "Width of the border around titles."),
1650
+ "title.bbox": (
1651
+ False,
1652
+ _validate_bool,
1653
+ "Whether to draw semi-transparent bounding boxes around titles "
1654
+ "when :rcraw:`title.loc` is inside the axes.",
1655
+ ),
1656
+ "title.bboxcolor": (WHITE, _validate_color, "Axes title bounding box color."),
1657
+ "title.bboxstyle": ("square", _validate_boxstyle, "Axes title bounding box style."),
1658
+ "title.bboxalpha": (0.5, _validate_float, "Axes title bounding box opacity."),
1659
+ "title.bboxpad": (
1660
+ None,
1661
+ _validate_or_none(_validate_pt),
1662
+ "Padding for the title bounding box. By default this is scaled "
1663
+ "to make the box flush against the axes edge." + _addendum_pt,
1664
+ ),
1665
+ "title.color": (
1666
+ BLACK,
1667
+ _validate_color,
1668
+ "Axes title color. Alias for :rcraw:`axes.titlecolor`.",
1669
+ ),
1670
+ "title.loc": (
1671
+ "center",
1672
+ _validate_belongs(*TEXT_LOCS),
1673
+ "Title position. For options see the :ref:`location table <title_table>`.",
1674
+ ),
1675
+ "title.pad": (
1676
+ TITLEPAD,
1677
+ _validate_pt,
1678
+ "Padding between the axes edge and the inner and outer titles and "
1679
+ "a-b-c labels. Alias for :rcraw:`axes.titlepad`." + _addendum_pt,
1680
+ ),
1681
+ "title.size": (
1682
+ LARGESIZE,
1683
+ _validate_fontsize,
1684
+ "Axes title font size. Alias for :rcraw:`axes.titlesize`." + _addendum_font,
1685
+ ),
1686
+ "title.weight": (
1687
+ "normal",
1688
+ _validate_fontweight,
1689
+ "Axes title font weight. Alias for :rcraw:`axes.titleweight`.",
1690
+ ),
1691
+ # Top subplot label settings
1692
+ "toplabel.color": (
1693
+ BLACK,
1694
+ _validate_color,
1695
+ "Font color for column labels on the top of the figure.",
1696
+ ),
1697
+ "toplabel.pad": (
1698
+ TITLEPAD,
1699
+ _validate_pt,
1700
+ "Padding between axes content and column labels on the top of the figure."
1701
+ + _addendum_pt,
1702
+ ),
1703
+ "toplabel.rotation": (
1704
+ "horizontal",
1705
+ _validate_rotation,
1706
+ "Rotation for column labels at the top of the figure." + _addendum_rotation,
1707
+ ),
1708
+ "toplabel.size": (
1709
+ LARGESIZE,
1710
+ _validate_fontsize,
1711
+ "Font size for column labels on the top of the figure." + _addendum_font,
1712
+ ),
1713
+ "toplabel.weight": (
1714
+ "bold",
1715
+ _validate_fontweight,
1716
+ "Font weight for column labels on the top of the figure.",
1717
+ ),
1718
+ # Unit formatting
1719
+ "unitformat": (
1720
+ "L",
1721
+ _validate_string,
1722
+ "The format string used to format `pint.Quantity` default unit labels "
1723
+ "using ``format(units, unitformat)``. See also :rcraw:`autoformat`.",
1724
+ ),
1725
+ }
1726
+
1727
+ # Child settings. Changing the parent changes all the children, but
1728
+ # changing any of the children does not change the parent.
1729
+ _rc_children = {
1730
+ "font.smallsize": ( # the 'small' fonts
1731
+ "tick.labelsize",
1732
+ "xtick.labelsize",
1733
+ "ytick.labelsize",
1734
+ "axes.labelsize",
1735
+ "legend.fontsize",
1736
+ "grid.labelsize",
1737
+ ),
1738
+ "font.largesize": ( # the 'large' fonts
1739
+ "abc.size",
1740
+ "figure.titlesize",
1741
+ "suptitle.size",
1742
+ "axes.titlesize",
1743
+ "title.size",
1744
+ "leftlabel.size",
1745
+ "toplabel.size",
1746
+ "rightlabel.size",
1747
+ "bottomlabel.size",
1748
+ ),
1749
+ "meta.color": ( # change the 'color' of an axes
1750
+ "axes.edgecolor",
1751
+ "axes.labelcolor",
1752
+ "legend.edgecolor",
1753
+ "colorbar.edgecolor",
1754
+ "tick.labelcolor",
1755
+ "hatch.color",
1756
+ "xtick.color",
1757
+ "ytick.color",
1758
+ ),
1759
+ "meta.width": ( # change the tick and frame line width
1760
+ "axes.linewidth",
1761
+ "tick.width",
1762
+ "tick.linewidth",
1763
+ "xtick.major.width",
1764
+ "ytick.major.width",
1765
+ "grid.width",
1766
+ "grid.linewidth",
1767
+ ),
1768
+ "axes.margin": ("axes.xmargin", "axes.ymargin"),
1769
+ "grid.color": ("gridminor.color", "grid.labelcolor"),
1770
+ "grid.alpha": ("gridminor.alpha",),
1771
+ "grid.linewidth": ("gridminor.linewidth",),
1772
+ "grid.linestyle": ("gridminor.linestyle",),
1773
+ "tick.color": ("xtick.color", "ytick.color"),
1774
+ "tick.dir": ("xtick.direction", "ytick.direction"),
1775
+ "tick.len": ("xtick.major.size", "ytick.major.size"),
1776
+ "tick.minor": ("xtick.minor.visible", "ytick.minor.visible"),
1777
+ "tick.pad": (
1778
+ "xtick.major.pad",
1779
+ "xtick.minor.pad",
1780
+ "ytick.major.pad",
1781
+ "ytick.minor.pad",
1782
+ ), # noqa: E501
1783
+ "tick.width": ("xtick.major.width", "ytick.major.width"),
1784
+ "tick.labelsize": ("xtick.labelsize", "ytick.labelsize"),
1785
+ }
1786
+
1787
+ # Recently added settings. Update these only if the version is recent enough
1788
+ # NOTE: We don't make 'title.color' a child of 'axes.titlecolor' because
1789
+ # the latter can take on the value 'auto' and can't handle that right now.
1790
+ if _version_mpl >= "3.2":
1791
+ _rc_matplotlib_default["axes.titlecolor"] = BLACK
1792
+ _rc_children["title.color"] = ("axes.titlecolor",)
1793
+ if _version_mpl >= "3.4":
1794
+ _rc_matplotlib_default["xtick.labelcolor"] = BLACK
1795
+ _rc_matplotlib_default["ytick.labelcolor"] = BLACK
1796
+ _rc_children["tick.labelcolor"] = ("xtick.labelcolor", "ytick.labelcolor")
1797
+ _rc_children["grid.labelcolor"] = ("xtick.labelcolor", "ytick.labelcolor")
1798
+ _rc_children["meta.color"] += ("xtick.labelcolor", "ytick.labelcolor")
1799
+
1800
+ # Setting synonyms. Changing one setting changes the other. Also account for existing
1801
+ # children. Most of these are aliased due to ultraplot settings overlapping with
1802
+ # existing matplotlib settings.
1803
+ _rc_synonyms = (
1804
+ ("cmap", "image.cmap", "cmap.sequential"),
1805
+ ("cmap.lut", "image.lut"),
1806
+ ("font.name", "font.family"),
1807
+ ("font.small", "font.smallsize"),
1808
+ ("font.large", "font.largesize"),
1809
+ ("formatter.limits", "axes.formatter.limits"),
1810
+ ("formatter.use_locale", "axes.formatter.use_locale"),
1811
+ ("formatter.use_mathtext", "axes.formatter.use_mathtext"),
1812
+ ("formatter.min_exponent", "axes.formatter.min_exponent"),
1813
+ ("formatter.use_offset", "axes.formatter.useoffset"),
1814
+ ("formatter.offset_threshold", "axes.formatter.offset_threshold"),
1815
+ ("grid.below", "axes.axisbelow"),
1816
+ ("grid.labelpad", "grid.pad"),
1817
+ ("grid.linewidth", "grid.width"),
1818
+ ("grid.linestyle", "grid.style"),
1819
+ ("gridminor.linewidth", "gridminor.width"),
1820
+ ("gridminor.linestyle", "gridminor.style"),
1821
+ ("label.color", "axes.labelcolor"),
1822
+ ("label.pad", "axes.labelpad"),
1823
+ ("label.size", "axes.labelsize"),
1824
+ ("label.weight", "axes.labelweight"),
1825
+ ("margin", "axes.margin"),
1826
+ ("meta.width", "meta.linewidth"),
1827
+ ("meta.color", "meta.edgecolor"),
1828
+ ("tick.labelpad", "tick.pad"),
1829
+ ("tick.labelsize", "grid.labelsize"),
1830
+ ("tick.labelcolor", "grid.labelcolor"),
1831
+ ("tick.labelweight", "grid.labelweight"),
1832
+ ("tick.linewidth", "tick.width"),
1833
+ ("title.pad", "axes.titlepad"),
1834
+ ("title.size", "axes.titlesize"),
1835
+ ("title.weight", "axes.titleweight"),
1836
+ )
1837
+ for _keys in _rc_synonyms:
1838
+ for _key in _keys:
1839
+ _set = {_ for k in _keys for _ in {k, *_rc_children.get(k, ())}} - {_key}
1840
+ _rc_children[_key] = tuple(sorted(_set))
1841
+
1842
+ # Previously removed settings.
1843
+ # NOTE: Initial idea was to defer deprecation warnings in Configurator to the
1844
+ # subsequent RcParams indexing. However this turned out be complicated, because
1845
+ # would have to detect deprecated keys in _get_item_dicts blocks, and need to
1846
+ # validate values before e.g. applying 'tick.lenratio'. So the renamed parameters
1847
+ # do not have to be added as _rc_children, since Configurator translates before
1848
+ # retrieving the list of children in _get_item_dicts.
1849
+ _rc_removed = { # {key: (alternative, version)} dictionary
1850
+ "rgbcycle": ("", "0.6.0"), # no alternative, we no longer offer this feature
1851
+ "geogrid.latmax": ("Please use ax.format(latmax=N) instead.", "0.6.0"),
1852
+ "geogrid.latstep": ("Please use ax.format(latlines=N) instead.", "0.6.0"),
1853
+ "geogrid.lonstep": ("Please use ax.format(lonlines=N) instead.", "0.6.0"),
1854
+ "gridminor.latstep": ("Please use ax.format(latminorlines=N) instead.", "0.6.0"),
1855
+ "gridminor.lonstep": ("Please use ax.format(lonminorlines=N) instead.", "0.6.0"),
1856
+ }
1857
+ _rc_renamed = { # {old_key: (new_key, version)} dictionary
1858
+ "abc.format": ("abc", "0.5.0"),
1859
+ "align": ("subplots.align", "0.6.0"),
1860
+ "axes.facealpha": ("axes.alpha", "0.6.0"),
1861
+ "geoaxes.edgecolor": ("axes.edgecolor", "0.6.0"),
1862
+ "geoaxes.facealpha": ("axes.alpha", "0.6.0"),
1863
+ "geoaxes.facecolor": ("axes.facecolor", "0.6.0"),
1864
+ "geoaxes.linewidth": ("axes.linewidth", "0.6.0"),
1865
+ "geogrid.alpha": ("grid.alpha", "0.6.0"),
1866
+ "geogrid.color": ("grid.color", "0.6.0"),
1867
+ "geogrid.labels": ("grid.labels", "0.6.0"),
1868
+ "geogrid.labelpad": ("grid.pad", "0.6.0"),
1869
+ "geogrid.labelsize": ("grid.labelsize", "0.6.0"),
1870
+ "geogrid.linestyle": ("grid.linestyle", "0.6.0"),
1871
+ "geogrid.linewidth": ("grid.linewidth", "0.6.0"),
1872
+ "share": ("subplots.share", "0.6.0"),
1873
+ "small": ("font.smallsize", "0.6.0"),
1874
+ "large": ("font.largesize", "0.6.0"),
1875
+ "span": ("subplots.span", "0.6.0"),
1876
+ "tight": ("subplots.tight", "0.6.0"),
1877
+ "axes.formatter.timerotation": ("formatter.timerotation", "0.6.0"),
1878
+ "axes.formatter.zerotrim": ("formatter.zerotrim", "0.6.0"),
1879
+ "abovetop": ("title.above", "0.7.0"),
1880
+ "subplots.pad": ("subplots.outerpad", "0.7.0"),
1881
+ "subplots.axpad": ("subplots.innerpad", "0.7.0"),
1882
+ "subplots.axwidth": ("subplots.refwidth", "0.7.0"),
1883
+ "text.labelsize": ("font.smallsize", "0.8.0"),
1884
+ "text.titlesize": ("font.largesize", "0.8.0"),
1885
+ "alpha": ("axes.alpha", "0.8.0"),
1886
+ "facecolor": ("axes.facecolor", "0.8.0"),
1887
+ "edgecolor": ("meta.color", "0.8.0"),
1888
+ "color": ("meta.color", "0.8.0"),
1889
+ "linewidth": ("meta.width", "0.8.0"),
1890
+ "lut": ("cmap.lut", "0.8.0"),
1891
+ "image.levels": ("cmap.levels", "0.8.0"),
1892
+ "image.inbounds": ("cmap.inbounds", "0.8.0"),
1893
+ "image.discrete": ("cmap.discrete", "0.8.0"),
1894
+ "image.edgefix": ("edgefix", "0.8.0"),
1895
+ "tick.ratio": ("tick.widthratio", "0.8.0"),
1896
+ "grid.ratio": ("grid.widthratio", "0.8.0"),
1897
+ "abc.style": ("abc", "0.8.0"),
1898
+ "grid.loninline": ("grid.inlinelabels", "0.8.0"),
1899
+ "grid.latinline": ("grid.inlinelabels", "0.8.0"),
1900
+ "cmap.edgefix": ("edgefix", "0.9.0"),
1901
+ "basemap": ("geo.backend", "0.10.0"),
1902
+ "inlinefmt": ("inlineformat", "0.10.0"),
1903
+ "cartopy.circular": ("geo.round", "0.10.0"),
1904
+ "cartopy.autoextent": ("geo.extent", "0.10.0"),
1905
+ "colorbar.rasterize": ("colorbar.rasterized", "0.10.0"),
1906
+ }
1907
+
1908
+ # Validate the default settings dictionaries using a custom ultraplot _RcParams
1909
+ # and the original matplotlib RcParams. Also surreptitiously add ultraplot
1910
+ # font settings to the font keys list (beoolean below always evalutes to True)
1911
+ # font keys list whlie initializing.
1912
+ _rc_ultraplot_default = {key: value for key, (value, _, _) in _rc_ultraplot_table.items()}
1913
+ _rc_ultraplot_validate = {
1914
+ key: validator
1915
+ for key, (_, validator, _) in _rc_ultraplot_table.items()
1916
+ if not (validator is _validate_fontsize and FONT_KEYS.add(key))
1917
+ }
1918
+ _rc_ultraplot_default = _RcParams(_rc_ultraplot_default, _rc_ultraplot_validate)
1919
+ _rc_matplotlib_default = RcParams(_rc_matplotlib_default)
1920
+
1921
+ # Important joint matplotlib ultraplot constants
1922
+ # NOTE: The 'nodots' dictionary should include removed and renamed settings
1923
+ _rc_categories = {
1924
+ ".".join(name.split(".")[: i + 1])
1925
+ for dict_ in (_rc_ultraplot_default, _rc_matplotlib_native)
1926
+ for name in dict_
1927
+ for i in range(len(name.split(".")) - 1)
1928
+ }
1929
+ _rc_nodots = {
1930
+ name.replace(".", ""): name
1931
+ for dict_ in (_rc_ultraplot_default, _rc_matplotlib_native, _rc_renamed, _rc_removed)
1932
+ for name in dict_.keys()
1933
+ }