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
ultraplot/utils.py ADDED
@@ -0,0 +1,912 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Various tools that may be useful while making plots.
4
+ """
5
+ # WARNING: Cannot import 'rc' anywhere in this file or we get circular import
6
+ # issues. The rc param validators need functions in this file.
7
+ import functools
8
+ import re
9
+ from numbers import Integral, Real
10
+
11
+ import matplotlib.colors as mcolors
12
+ import matplotlib.font_manager as mfonts
13
+ import numpy as np
14
+ from matplotlib import rcParams as rc_matplotlib
15
+
16
+ from .externals import hsluv
17
+ from .internals import ic # noqa: F401
18
+ from .internals import _not_none, docstring, warnings
19
+
20
+ __all__ = [
21
+ "arange",
22
+ "edges",
23
+ "edges2d",
24
+ "get_colors",
25
+ "set_hue",
26
+ "set_saturation",
27
+ "set_luminance",
28
+ "set_alpha",
29
+ "shift_hue",
30
+ "scale_saturation",
31
+ "scale_luminance",
32
+ "to_hex",
33
+ "to_rgb",
34
+ "to_xyz",
35
+ "to_rgba",
36
+ "to_xyza",
37
+ "units",
38
+ "shade", # deprecated
39
+ "saturate", # deprecated
40
+ ]
41
+
42
+ UNIT_REGEX = re.compile(
43
+ r"\A([-+]?[0-9._]+(?:[eE][-+]?[0-9_]+)?)(.*)\Z" # float with trailing units
44
+ )
45
+ UNIT_DICT = {
46
+ "in": 1.0,
47
+ "ft": 12.0,
48
+ "yd": 36.0,
49
+ "m": 39.37,
50
+ "dm": 3.937,
51
+ "cm": 0.3937,
52
+ "mm": 0.03937,
53
+ "pc": 1 / 6.0,
54
+ "pt": 1 / 72.0,
55
+ "ly": 3.725e17,
56
+ }
57
+
58
+
59
+ # Color docstrings
60
+ _docstring_rgba = """
61
+ color : color-spec
62
+ The color. Sanitized with `to_rgba`.
63
+ """
64
+ _docstring_to_rgb = """
65
+ color : color-spec
66
+ The color. Can be a 3-tuple or 4-tuple of channel values, a hex
67
+ string, a registered color name, a cycle color like ``'C0'``, or
68
+ a 2-tuple colormap coordinate specification like ``('magma', 0.5)``
69
+ (see `~ultraplot.colors.ColorDatabase` for details).
70
+
71
+ If `space` is ``'rgb'``, this is a tuple of RGB values, and any
72
+ channels are larger than ``2``, the channels are assumed to be
73
+ on the ``0`` to ``255`` scale and are divided by ``255``.
74
+ space : {'rgb', 'hsv', 'hcl', 'hpl', 'hsl'}, optional
75
+ The colorspace for the input channel values. Ignored unless `color`
76
+ is a tuple of numbers.
77
+ cycle : str, default: :rcraw:`cycle`
78
+ The registered color cycle name used to interpret colors that
79
+ look like ``'C0'``, ``'C1'``, etc.
80
+ clip : bool, default: True
81
+ Whether to clip channel values into the valid ``0`` to ``1`` range.
82
+ Setting this to ``False`` can result in invalid colors.
83
+ """
84
+ _docstring_space = """
85
+ space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional
86
+ The hue-saturation-luminance-like colorspace used to transform the color.
87
+ Default is the strictly perceptually uniform colorspace ``'hcl'``.
88
+ """
89
+ _docstring_hex = """
90
+ color : str
91
+ An 8-digit HEX string indicating the
92
+ red, green, blue, and alpha channel values.
93
+ """
94
+ docstring._snippet_manager["utils.color"] = _docstring_rgba
95
+ docstring._snippet_manager["utils.hex"] = _docstring_hex
96
+ docstring._snippet_manager["utils.space"] = _docstring_space
97
+ docstring._snippet_manager["utils.to"] = _docstring_to_rgb
98
+
99
+
100
+ def _keep_units(func):
101
+ """
102
+ Very simple decorator to strip and re-apply the same units.
103
+ """
104
+
105
+ # NOTE: Native UnitRegistry.wraps() is not sufficient since it enforces
106
+ # unit types rather than arbitrary units. This wrapper is similar.
107
+ @functools.wraps(func)
108
+ def _with_stripped_units(data, *args, **kwargs):
109
+ units = 1
110
+ if hasattr(data, "units") and hasattr(data, "magnitude"):
111
+ data, units = data.magnitude, data.units
112
+ result = func(data, *args, **kwargs)
113
+ return result * units
114
+
115
+ return _with_stripped_units
116
+
117
+
118
+ def arange(min_, *args):
119
+ """
120
+ Identical to `numpy.arange` but with inclusive endpoints. For example,
121
+ ``pplt.arange(2, 4)`` returns the numpy array ``[2, 3, 4]`` instead of
122
+ ``[2, 3]``. This is useful for generating lists of tick locations or
123
+ colormap levels, e.g. ``ax.format(xlocator=pplt.arange(0, 10))``
124
+ or ``ax.pcolor(levels=pplt.arange(0, 10))``.
125
+
126
+ Parameters
127
+ ----------
128
+ *args : float
129
+ If three arguments are passed, these are the minimum, maximum, and step
130
+ size. If fewer than three arguments are passed, the step size is ``1``.
131
+ If one argument is passed, this is the maximum, and the minimum is ``0``.
132
+
133
+ Returns
134
+ -------
135
+ numpy.ndarray
136
+ Array of points.
137
+
138
+ See also
139
+ --------
140
+ numpy.arange
141
+ ultraplot.constructor.Locator
142
+ ultraplot.axes.CartesianAxes.format
143
+ ultraplot.axes.PolarAxes.format
144
+ ultraplot.axes.GeoAxes.format
145
+ ultraplot.axes.Axes.colorbar
146
+ ultraplot.axes.PlotAxes
147
+ """
148
+ # Optional arguments just like np.arange
149
+ if len(args) == 0:
150
+ max_ = min_
151
+ min_ = 0
152
+ step = 1
153
+ elif len(args) == 1:
154
+ max_ = args[0]
155
+ step = 1
156
+ elif len(args) == 2:
157
+ max_ = args[0]
158
+ step = args[1]
159
+ else:
160
+ raise ValueError("Function takes from one to three arguments.")
161
+ # All input is integer
162
+ if all(isinstance(val, Integral) for val in (min_, max_, step)):
163
+ min_, max_, step = np.int64(min_), np.int64(max_), np.int64(step)
164
+ max_ += np.sign(step)
165
+ # Input is float or mixed, cast to float64
166
+ # Don't use np.nextafter with np.finfo(np.dtype(np.float64)).max, because
167
+ # round-off errors from continually adding step to min mess this up
168
+ else:
169
+ min_, max_, step = np.float64(min_), np.float64(max_), np.float64(step)
170
+ max_ += 0.5 * step
171
+ return np.arange(min_, max_, step)
172
+
173
+
174
+ @_keep_units
175
+ def edges(z, axis=-1):
176
+ """
177
+ Calculate the approximate "edge" values along an axis given "center" values.
178
+ The size of the axis is increased by one. This is used internally to calculate
179
+ coordinate edges when you supply coordinate centers to pseudocolor commands.
180
+
181
+ Parameters
182
+ ----------
183
+ z : array-like
184
+ An array of any shape.
185
+ axis : int, optional
186
+ The axis along which "edges" are calculated. The size of this
187
+ axis will be increased by one.
188
+
189
+ Returns
190
+ -------
191
+ numpy.ndarray
192
+ Array of "edge" coordinates.
193
+
194
+ See also
195
+ --------
196
+ edges2d
197
+ ultraplot.axes.PlotAxes.pcolor
198
+ ultraplot.axes.PlotAxes.pcolormesh
199
+ ultraplot.axes.PlotAxes.pcolorfast
200
+ """
201
+ z = np.asarray(z)
202
+ z = np.swapaxes(z, axis, -1)
203
+ *dims, n = z.shape
204
+ zb = np.zeros((*dims, n + 1))
205
+
206
+ # Inner edges
207
+ zb[..., 1:-1] = 0.5 * (z[..., :-1] + z[..., 1:])
208
+
209
+ # Outer edges
210
+ zb[..., 0] = 1.5 * z[..., 0] - 0.5 * z[..., 1]
211
+ zb[..., -1] = 1.5 * z[..., -1] - 0.5 * z[..., -2]
212
+
213
+ return np.swapaxes(zb, axis, -1)
214
+
215
+
216
+ @_keep_units
217
+ def edges2d(z):
218
+ """
219
+ Calculate the approximate "edge" values given a 2D grid of "center" values.
220
+ The size of both axes is increased by one. This is used internally to calculate
221
+ coordinate edges when you supply coordinate to pseudocolor commands.
222
+
223
+ Parameters
224
+ ----------
225
+ z : array-like
226
+ A 2D array.
227
+
228
+ Returns
229
+ -------
230
+ numpy.ndarray
231
+ Array of "edge" coordinates.
232
+
233
+ See also
234
+ --------
235
+ edges
236
+ ultraplot.axes.PlotAxes.pcolor
237
+ ultraplot.axes.PlotAxes.pcolormesh
238
+ ultraplot.axes.PlotAxes.pcolorfast
239
+ """
240
+ z = np.asarray(z)
241
+ if z.ndim != 2:
242
+ raise ValueError(f"Input must be a 2D array, but got {z.ndim}D.")
243
+ ny, nx = z.shape
244
+ zb = np.zeros((ny + 1, nx + 1))
245
+
246
+ # Inner edges
247
+ zb[1:-1, 1:-1] = 0.25 * (z[1:, 1:] + z[:-1, 1:] + z[1:, :-1] + z[:-1, :-1])
248
+
249
+ # Outer edges
250
+ zb[0, :] += edges(1.5 * z[0, :] - 0.5 * z[1, :])
251
+ zb[-1, :] += edges(1.5 * z[-1, :] - 0.5 * z[-2, :])
252
+ zb[:, 0] += edges(1.5 * z[:, 0] - 0.5 * z[:, 1])
253
+ zb[:, -1] += edges(1.5 * z[:, -1] - 0.5 * z[:, -2])
254
+ zb[[0, 0, -1, -1], [0, -1, -1, 0]] *= 0.5 # corner correction
255
+
256
+ return zb
257
+
258
+
259
+ def get_colors(*args, **kwargs):
260
+ """
261
+ Get the colors associated with a registered or
262
+ on-the-fly color cycle or colormap.
263
+
264
+ Parameters
265
+ ----------
266
+ *args, **kwargs
267
+ Passed to `~ultraplot.constructor.Cycle`.
268
+
269
+ Returns
270
+ -------
271
+ colors : list of str
272
+ A list of HEX strings.
273
+
274
+ See also
275
+ --------
276
+ ultraplot.constructor.Cycle
277
+ ultraplot.constructor.Colormap
278
+ """
279
+ from .constructor import Cycle # delayed to avoid cyclic imports
280
+
281
+ cycle = Cycle(*args, **kwargs)
282
+ colors = [to_hex(dict_["color"]) for dict_ in cycle]
283
+ return colors
284
+
285
+
286
+ def _transform_color(func, color, space):
287
+ """
288
+ Standardize input for color transformation functions.
289
+ """
290
+ *color, opacity = to_rgba(color)
291
+ color = to_xyz(color, space=space)
292
+ color = func(list(color)) # apply transform
293
+ return to_hex((*color, opacity), space=space)
294
+
295
+
296
+ @docstring._snippet_manager
297
+ def shift_hue(color, shift=0, space="hcl"):
298
+ """
299
+ Shift the hue channel of a color.
300
+
301
+ Parameters
302
+ ----------
303
+ %(utils.color)s
304
+ shift : float, optional
305
+ The HCL hue channel is offset by this value.
306
+ %(utils.space)s
307
+
308
+ Returns
309
+ -------
310
+ %(utils.hex)s
311
+
312
+ See also
313
+ --------
314
+ set_hue
315
+ set_saturation
316
+ set_luminance
317
+ set_alpha
318
+ scale_saturation
319
+ scale_luminance
320
+ """
321
+
322
+ def func(channels):
323
+ channels[0] += shift
324
+ channels[0] %= 360
325
+ return channels
326
+
327
+ return _transform_color(func, color, space)
328
+
329
+
330
+ @docstring._snippet_manager
331
+ def scale_saturation(color, scale=1, space="hcl"):
332
+ """
333
+ Scale the saturation channel of a color.
334
+
335
+ Parameters
336
+ ----------
337
+ %(utils.color)s
338
+ scale : float, optional
339
+ The HCL saturation channel is multiplied by this value.
340
+ %(utils.space)s
341
+
342
+ Returns
343
+ -------
344
+ %(utils.hex)s
345
+
346
+ See also
347
+ --------
348
+ set_hue
349
+ set_saturation
350
+ set_luminance
351
+ set_alpha
352
+ shift_hue
353
+ scale_luminance
354
+ """
355
+
356
+ def func(channels):
357
+ channels[1] *= scale
358
+ return channels
359
+
360
+ return _transform_color(func, color, space)
361
+
362
+
363
+ @docstring._snippet_manager
364
+ def scale_luminance(color, scale=1, space="hcl"):
365
+ """
366
+ Scale the luminance channel of a color.
367
+
368
+ Parameters
369
+ ----------
370
+ %(utils.color)s
371
+ scale : float, optional
372
+ The luminance channel is multiplied by this value.
373
+ %(utils.space)s
374
+
375
+ Returns
376
+ -------
377
+ %(utils.hex)s
378
+
379
+ See also
380
+ --------
381
+ set_hue
382
+ set_saturation
383
+ set_luminance
384
+ set_alpha
385
+ shift_hue
386
+ scale_saturation
387
+ """
388
+
389
+ def func(channels):
390
+ channels[2] *= scale
391
+ return channels
392
+
393
+ return _transform_color(func, color, space)
394
+
395
+
396
+ @docstring._snippet_manager
397
+ def set_hue(color, hue, space="hcl"):
398
+ """
399
+ Return a color with a different hue and the same luminance and saturation
400
+ as the input color.
401
+
402
+ Parameters
403
+ ----------
404
+ %(utils.color)s
405
+ hue : float, optional
406
+ The new hue. Should lie between ``0`` and ``360`` degrees.
407
+ %(utils.space)s
408
+
409
+ Returns
410
+ -------
411
+ %(utils.hex)s
412
+
413
+ See also
414
+ --------
415
+ set_saturation
416
+ set_luminance
417
+ set_alpha
418
+ shift_hue
419
+ scale_saturation
420
+ scale_luminance
421
+ """
422
+
423
+ def func(channels):
424
+ channels[0] = hue
425
+ return channels
426
+
427
+ return _transform_color(func, color, space)
428
+
429
+
430
+ @docstring._snippet_manager
431
+ def set_saturation(color, saturation, space="hcl"):
432
+ """
433
+ Return a color with a different saturation and the same hue and luminance
434
+ as the input color.
435
+
436
+ Parameters
437
+ ----------
438
+ %(utils.color)s
439
+ saturation : float, optional
440
+ The new saturation. Should lie between ``0`` and ``360`` degrees.
441
+ %(utils.space)s
442
+
443
+ Returns
444
+ -------
445
+ %(utils.hex)s
446
+
447
+ See also
448
+ --------
449
+ set_hue
450
+ set_luminance
451
+ set_alpha
452
+ shift_hue
453
+ scale_saturation
454
+ scale_luminance
455
+ """
456
+
457
+ def func(channels):
458
+ channels[1] = saturation
459
+ return channels
460
+
461
+ return _transform_color(func, color, space)
462
+
463
+
464
+ @docstring._snippet_manager
465
+ def set_luminance(color, luminance, space="hcl"):
466
+ """
467
+ Return a color with a different luminance and the same hue and saturation
468
+ as the input color.
469
+
470
+ Parameters
471
+ ----------
472
+ %(utils.color)s
473
+ luminance : float, optional
474
+ The new luminance. Should lie between ``0`` and ``100``.
475
+ %(utils.space)s
476
+
477
+ Returns
478
+ -------
479
+ %(utils.hex)s
480
+
481
+ See also
482
+ --------
483
+ set_hue
484
+ set_saturation
485
+ set_alpha
486
+ shift_hue
487
+ scale_saturation
488
+ scale_luminance
489
+ """
490
+
491
+ def func(channels):
492
+ channels[2] = luminance
493
+ return channels
494
+
495
+ return _transform_color(func, color, space)
496
+
497
+
498
+ @docstring._snippet_manager
499
+ def set_alpha(color, alpha):
500
+ """
501
+ Return a color with the opacity channel set to the specified value.
502
+
503
+ Parameters
504
+ ----------
505
+ %(utils.color)s
506
+ alpha : float, optional
507
+ The new opacity. Should be between ``0`` and ``1``.
508
+
509
+ Returns
510
+ -------
511
+ %(utils.hex)s
512
+
513
+ See also
514
+ --------
515
+ set_hue
516
+ set_saturation
517
+ set_luminance
518
+ shift_hue
519
+ scale_saturation
520
+ scale_luminance
521
+ """
522
+ color = list(to_rgba(color))
523
+ color[3] = alpha
524
+ return to_hex(color)
525
+
526
+
527
+ def _translate_cycle_color(color, cycle=None):
528
+ """
529
+ Parse the input cycle color.
530
+ """
531
+ if isinstance(cycle, str):
532
+ from .colors import _cmap_database
533
+
534
+ try:
535
+ cycle = _cmap_database[cycle].colors
536
+ except (KeyError, AttributeError):
537
+ cycles = sorted(
538
+ name
539
+ for name, cmap in _cmap_database.items()
540
+ if isinstance(cmap, mcolors.ListedColormap)
541
+ )
542
+ raise ValueError(
543
+ f"Invalid color cycle {cycle!r}. Options are: "
544
+ + ", ".join(map(repr, cycles))
545
+ + "."
546
+ )
547
+ elif cycle is None:
548
+ cycle = rc_matplotlib["axes.prop_cycle"].by_key()
549
+ if "color" not in cycle:
550
+ cycle = ["k"]
551
+ else:
552
+ cycle = cycle["color"]
553
+ else:
554
+ raise ValueError(f"Invalid cycle {cycle!r}.")
555
+
556
+ return cycle[int(color[-1]) % len(cycle)]
557
+
558
+
559
+ @docstring._snippet_manager
560
+ def to_hex(color, space="rgb", cycle=None, keep_alpha=True):
561
+ """
562
+ Translate the color from an arbitrary colorspace to a HEX string.
563
+ This is a generalization of `matplotlib.colors.to_hex`.
564
+
565
+ Parameters
566
+ ----------
567
+ %(utils.to)s
568
+ keep_alpha : bool, default: True
569
+ Whether to keep the opacity channel. If ``True`` an 8-digit HEX
570
+ is returned. Otherwise a 6-digit HEX is returned.
571
+
572
+ Returns
573
+ -------
574
+ %(utils.hex)s
575
+
576
+ See also
577
+ --------
578
+ to_rgb
579
+ to_rgba
580
+ to_xyz
581
+ to_xyza
582
+ """
583
+ rgba = to_rgba(color, space=space, cycle=cycle)
584
+ return mcolors.to_hex(rgba, keep_alpha=keep_alpha)
585
+
586
+
587
+ @docstring._snippet_manager
588
+ def to_rgb(color, space="rgb", cycle=None):
589
+ """
590
+ Translate the color from an arbitrary colorspace to an RGB tuple. This is
591
+ a generalization of `matplotlib.colors.to_rgb` and the inverse of `to_xyz`.
592
+
593
+ Parameters
594
+ ----------
595
+ %(utils.to)s
596
+
597
+ Returns
598
+ -------
599
+ color : 3-tuple
600
+ An RGB tuple.
601
+
602
+ See also
603
+ --------
604
+ to_hex
605
+ to_rgba
606
+ to_xyz
607
+ to_xyza
608
+ """
609
+ return to_rgba(color, space=space, cycle=cycle)[:3]
610
+
611
+
612
+ @docstring._snippet_manager
613
+ def to_rgba(color, space="rgb", cycle=None, clip=True):
614
+ """
615
+ Translate the color from an arbitrary colorspace to an RGBA tuple. This is
616
+ a generalization of `matplotlib.colors.to_rgba` and the inverse of `to_xyz`.
617
+
618
+ Parameters
619
+ ----------
620
+ %(utils.to)s
621
+
622
+ Returns
623
+ -------
624
+ color : 4-tuple
625
+ An RGBA tuple.
626
+
627
+ See also
628
+ --------
629
+ to_hex
630
+ to_rgb
631
+ to_xyz
632
+ to_xyza
633
+ """
634
+ # Translate color cycle strings
635
+ if isinstance(color, str) and re.match(r"\AC[0-9]\Z", color):
636
+ color = _translate_cycle_color(color, cycle=cycle)
637
+
638
+ # Translate RGB strings and (colormap, index) tuples
639
+ # NOTE: Cannot use is_color_like because might have HSL channel values
640
+ opacity = 1
641
+ if isinstance(color, str) or np.iterable(color) and len(color) == 2:
642
+ color = mcolors.to_rgba(color) # also enforced validity
643
+ if (
644
+ not np.iterable(color)
645
+ or len(color) not in (3, 4)
646
+ or not all(isinstance(c, Real) for c in color)
647
+ ):
648
+ raise ValueError(f"Invalid color-spec {color!r}.")
649
+ if len(color) == 4:
650
+ *color, opacity = color
651
+
652
+ # Translate arbitrary colorspaces
653
+ if space == "rgb":
654
+ if any(c > 2 for c in color):
655
+ color = tuple(c / 255 for c in color) # scale to within 0-1
656
+ else:
657
+ pass
658
+ elif space == "hsv":
659
+ color = hsluv.hsl_to_rgb(*color)
660
+ elif space == "hcl":
661
+ color = hsluv.hcl_to_rgb(*color)
662
+ elif space == "hsl":
663
+ color = hsluv.hsluv_to_rgb(*color)
664
+ elif space == "hpl":
665
+ color = hsluv.hpluv_to_rgb(*color)
666
+ else:
667
+ raise ValueError(f"Invalid colorspace {space!r}.")
668
+
669
+ # Clip values. This should only be disabled when testing
670
+ # translation functions.
671
+ if clip:
672
+ color = np.clip(color, 0, 1) # clip to valid range
673
+
674
+ # Return RGB or RGBA
675
+ return (*color, opacity)
676
+
677
+
678
+ @docstring._snippet_manager
679
+ def to_xyz(color, space="hcl"):
680
+ """
681
+ Translate color in *any* format to a tuple of channel values in *any*
682
+ colorspace. This is the inverse of `to_rgb`.
683
+
684
+ Parameters
685
+ ----------
686
+ %(utils.color)s
687
+ space : {'hcl', 'hpl', 'hsl', 'hsv', 'rgb'}, optional
688
+ The colorspace for the output channel values.
689
+
690
+ Returns
691
+ -------
692
+ color : 3-tuple
693
+ Tuple of channel values for the colorspace `space`.
694
+
695
+ See also
696
+ --------
697
+ to_hex
698
+ to_rgb
699
+ to_rgba
700
+ to_xyza
701
+ """
702
+ return to_xyza(color, space)[:3]
703
+
704
+
705
+ @docstring._snippet_manager
706
+ def to_xyza(color, space="hcl"):
707
+ """
708
+ Translate color in *any* format to a tuple of channel values in *any*
709
+ colorspace. This is the inverse of `to_rgba`.
710
+
711
+ Parameters
712
+ ----------
713
+ %(utils.color)s
714
+ space : {'hcl', 'hpl', 'hsl', 'hsv', 'rgb'}, optional
715
+ The colorspace for the output channel values.
716
+
717
+ Returns
718
+ -------
719
+ color : 3-tuple
720
+ Tuple of channel values for the colorspace `space`.
721
+
722
+ See also
723
+ --------
724
+ to_hex
725
+ to_rgb
726
+ to_rgba
727
+ to_xyz
728
+ """
729
+ # Run tuple conversions
730
+ # NOTE: Don't pass color tuple, because we may want to permit
731
+ # out-of-bounds RGB values to invert conversion
732
+ *color, opacity = to_rgba(color)
733
+ if space == "rgb":
734
+ pass
735
+ elif space == "hsv":
736
+ color = hsluv.rgb_to_hsl(*color) # rgb_to_hsv would also work
737
+ elif space == "hcl":
738
+ color = hsluv.rgb_to_hcl(*color)
739
+ elif space == "hsl":
740
+ color = hsluv.rgb_to_hsluv(*color)
741
+ elif space == "hpl":
742
+ color = hsluv.rgb_to_hpluv(*color)
743
+ else:
744
+ raise ValueError(f"Invalid colorspace {space}.")
745
+ return (*color, opacity)
746
+
747
+
748
+ def _fontsize_to_pt(size):
749
+ """
750
+ Translate font preset size or unit string to points.
751
+ """
752
+ scalings = mfonts.font_scalings
753
+ if not isinstance(size, str):
754
+ return size
755
+ if size in mfonts.font_scalings:
756
+ return rc_matplotlib["font.size"] * scalings[size]
757
+ try:
758
+ return units(size, "pt")
759
+ except ValueError:
760
+ raise KeyError(
761
+ f"Invalid font size {size!r}. Can be points or one of the preset scalings: "
762
+ + ", ".join(f"{key!r} ({value})" for key, value in scalings.items())
763
+ + "."
764
+ )
765
+
766
+
767
+ @warnings._rename_kwargs("0.6.0", units="dest")
768
+ def units(
769
+ value, numeric=None, dest=None, *, fontsize=None, figure=None, axes=None, width=None
770
+ ):
771
+ """
772
+ Convert values between arbitrary physical units. This is used internally all
773
+ over ultraplot, permitting flexible units for various keyword arguments.
774
+
775
+ Parameters
776
+ ----------
777
+ value : float or str or sequence
778
+ A size specifier or sequence of size specifiers. If numeric, units are
779
+ converted from `numeric` to `dest`. If string, units are converted to
780
+ `dest` according to the string specifier. The string should look like
781
+ ``'123.456unit'``, where the number is the magnitude and ``'unit'``
782
+ matches a key in the below table.
783
+
784
+ .. _units_table:
785
+
786
+ ========= =====================================================
787
+ Key Description
788
+ ========= =====================================================
789
+ ``'m'`` Meters
790
+ ``'dm'`` Decimeters
791
+ ``'cm'`` Centimeters
792
+ ``'mm'`` Millimeters
793
+ ``'yd'`` Yards
794
+ ``'ft'`` Feet
795
+ ``'in'`` Inches
796
+ ``'pc'`` `Pica <pc_>`_ (1/6 inches)
797
+ ``'pt'`` `Points <pt_>`_ (1/72 inches)
798
+ ``'px'`` Pixels on screen, using dpi of :rcraw:`figure.dpi`
799
+ ``'pp'`` Pixels once printed, using dpi of :rcraw:`savefig.dpi`
800
+ ``'em'`` `Em square <em_>`_ for :rcraw:`font.size`
801
+ ``'en'`` `En square <en_>`_ for :rcraw:`font.size`
802
+ ``'Em'`` `Em square <em_>`_ for :rcraw:`axes.titlesize`
803
+ ``'En'`` `En square <en_>`_ for :rcraw:`axes.titlesize`
804
+ ``'ax'`` Axes-relative units (not always available)
805
+ ``'fig'`` Figure-relative units (not always available)
806
+ ``'ly'`` Light years ;)
807
+ ========= =====================================================
808
+
809
+ .. _pt: https://en.wikipedia.org/wiki/Point_(typography)
810
+ .. _pc: https://en.wikipedia.org/wiki/Pica_(typography)
811
+ .. _em: https://en.wikipedia.org/wiki/Em_(typography)
812
+ .. _en: https://en.wikipedia.org/wiki/En_(typography)
813
+
814
+ numeric : str, default: 'in'
815
+ The units associated with numeric input.
816
+ dest : str, default: `numeric`
817
+ The destination units.
818
+ fontsize : str or float, default: :rc:`font.size` or :rc:`axes.titlesize`
819
+ The font size in points used for scaling. Default is
820
+ :rcraw:`font.size` for ``em`` and ``en`` units and
821
+ :rcraw:`axes.titlesize` for ``Em`` and ``En`` units.
822
+ axes : `~matplotlib.axes.Axes`, optional
823
+ The axes to use for scaling units that look like ``'0.1ax'``.
824
+ figure : `~matplotlib.figure.Figure`, optional
825
+ The figure to use for scaling units that look like ``'0.1fig'``.
826
+ If not provided we try to get the figure from ``axes.figure``.
827
+ width : bool, optional
828
+ Whether to use the width or height for the axes and figure
829
+ relative coordinates.
830
+ """
831
+ # Scales for converting physical units to inches
832
+ fontsize_small = _not_none(fontsize, rc_matplotlib["font.size"]) # always absolute
833
+ fontsize_small = _fontsize_to_pt(fontsize_small)
834
+ fontsize_large = _not_none(fontsize, rc_matplotlib["axes.titlesize"])
835
+ fontsize_large = _fontsize_to_pt(fontsize_large)
836
+ unit_dict = UNIT_DICT.copy()
837
+ unit_dict.update(
838
+ {
839
+ "em": fontsize_small / 72.0,
840
+ "en": 0.5 * fontsize_small / 72.0,
841
+ "Em": fontsize_large / 72.0,
842
+ "En": 0.5 * fontsize_large / 72.0,
843
+ }
844
+ )
845
+
846
+ # Scales for converting display units to inches
847
+ # WARNING: In ipython shell these take the value 'figure'
848
+ if not isinstance(rc_matplotlib["figure.dpi"], str):
849
+ unit_dict["px"] = 1 / rc_matplotlib["figure.dpi"] # once generated by backend
850
+ if not isinstance(rc_matplotlib["savefig.dpi"], str):
851
+ unit_dict["pp"] = 1 / rc_matplotlib["savefig.dpi"] # once 'printed' i.e. saved
852
+
853
+ # Scales relative to axes and figure objects
854
+ if axes is not None and hasattr(axes, "_get_size_inches"): # ultraplot axes
855
+ unit_dict["ax"] = axes._get_size_inches()[1 - int(width)]
856
+ if figure is None:
857
+ figure = getattr(axes, "figure", None)
858
+ if figure is not None and hasattr(figure, "get_size_inches"):
859
+ unit_dict["fig"] = figure.get_size_inches()[1 - int(width)]
860
+
861
+ # Scale for converting inches to arbitrary other unit
862
+ if numeric is None and dest is None:
863
+ numeric = dest = "in"
864
+ elif numeric is None:
865
+ numeric = dest
866
+ elif dest is None:
867
+ dest = numeric
868
+ options = "Valid units are " + ", ".join(map(repr, unit_dict)) + "."
869
+ try:
870
+ nscale = unit_dict[numeric]
871
+ except KeyError:
872
+ raise ValueError(f"Invalid numeric units {numeric!r}. " + options)
873
+ try:
874
+ dscale = unit_dict[dest]
875
+ except KeyError:
876
+ raise ValueError(f"Invalid destination units {dest!r}. " + options)
877
+
878
+ # Convert units for each value in list
879
+ result = []
880
+ singleton = not np.iterable(value) or isinstance(value, str)
881
+ for val in (value,) if singleton else value:
882
+ # Silently pass None
883
+ if val is None:
884
+ result.append(val)
885
+ continue
886
+ # Get unit string
887
+ if isinstance(val, Real):
888
+ number, units = val, None
889
+ elif isinstance(val, str):
890
+ regex = UNIT_REGEX.match(val)
891
+ if regex:
892
+ number, units = regex.groups() # second group is exponential
893
+ else:
894
+ raise ValueError(f"Invalid unit size spec {val!r}.")
895
+ else:
896
+ raise ValueError(f"Invalid unit size spec {val!r}.")
897
+ # Convert with units
898
+ if not units:
899
+ result.append(float(number) * nscale / dscale)
900
+ elif units in unit_dict:
901
+ result.append(float(number) * unit_dict[units] / dscale)
902
+ else:
903
+ raise ValueError(f"Invalid input units {units!r}. " + options)
904
+ return result[0] if singleton else result
905
+
906
+
907
+ # Deprecations
908
+ shade, saturate = warnings._rename_objs(
909
+ "0.6.0",
910
+ shade=scale_luminance,
911
+ saturate=scale_saturation,
912
+ )