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,529 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Internal utilities.
4
+ """
5
+ # Import statements
6
+ import inspect
7
+ from numbers import Integral, Real
8
+
9
+ import numpy as np
10
+ from matplotlib import rcParams as rc_matplotlib
11
+
12
+ try: # print debugging (used with internal modules)
13
+ from icecream import ic
14
+ except ImportError: # graceful fallback if IceCream isn't installed
15
+ ic = lambda *args: print(*args) # noqa: E731
16
+
17
+ from . import warnings as warns
18
+
19
+
20
+ def _not_none(*args, default=None, **kwargs):
21
+ """
22
+ Return the first non-``None`` value. This is used with keyword arg aliases and
23
+ for setting default values. Use `kwargs` to issue warnings when multiple passed.
24
+ """
25
+ first = default
26
+ if args and kwargs:
27
+ raise ValueError("_not_none can only be used with args or kwargs.")
28
+ elif args:
29
+ for arg in args:
30
+ if arg is not None:
31
+ first = arg
32
+ break
33
+ elif kwargs:
34
+ for name, arg in list(kwargs.items()):
35
+ if arg is not None:
36
+ first = arg
37
+ break
38
+ kwargs = {name: arg for name, arg in kwargs.items() if arg is not None}
39
+ if len(kwargs) > 1:
40
+ warnings._warn_ultraplot(
41
+ f"Got conflicting or duplicate keyword arguments: {kwargs}. "
42
+ "Using the first keyword argument."
43
+ )
44
+ return first
45
+
46
+
47
+ # Internal import statements
48
+ # WARNING: Must come after _not_none because this is leveraged inside other funcs
49
+ from . import ( # noqa: F401
50
+ benchmarks,
51
+ context,
52
+ docstring,
53
+ fonts,
54
+ guides,
55
+ inputs,
56
+ labels,
57
+ rcsetup,
58
+ versions,
59
+ warnings,
60
+ )
61
+ from .versions import _version_mpl, _version_cartopy # noqa: F401
62
+ from .warnings import UltraplotWarning # noqa: F401
63
+
64
+
65
+ # Style aliases. We use this rather than matplotlib's normalize_kwargs and _alias_maps.
66
+ # NOTE: We add aliases 'edgewidth' and 'fillcolor' for patch edges and faces
67
+ # NOTE: Alias cannot appear as key or else _translate_kwargs will overwrite with None!
68
+ _alias_maps = {
69
+ "rgba": {
70
+ "red": ("r",),
71
+ "green": ("g",),
72
+ "blue": ("b",),
73
+ "alpha": ("a",),
74
+ },
75
+ "hsla": {
76
+ "hue": ("h",),
77
+ "saturation": ("s", "c", "chroma"),
78
+ "luminance": ("l",),
79
+ "alpha": ("a",),
80
+ },
81
+ "patch": {
82
+ "alpha": (
83
+ "a",
84
+ "alphas",
85
+ "fa",
86
+ "facealpha",
87
+ "facealphas",
88
+ "fillalpha",
89
+ "fillalphas",
90
+ ), # noqa: E501
91
+ "color": ("c", "colors"),
92
+ "edgecolor": ("ec", "edgecolors"),
93
+ "facecolor": ("fc", "facecolors", "fillcolor", "fillcolors"),
94
+ "hatch": ("h", "hatching"),
95
+ "linestyle": ("ls", "linestyles"),
96
+ "linewidth": ("lw", "linewidths", "ew", "edgewidth", "edgewidths"),
97
+ "zorder": ("z", "zorders"),
98
+ },
99
+ "line": { # copied from lines.py but expanded to include plurals
100
+ "alpha": ("a", "alphas"),
101
+ "color": ("c", "colors"),
102
+ "dashes": ("d", "dash"),
103
+ "drawstyle": ("ds", "drawstyles"),
104
+ "fillstyle": ("fs", "fillstyles", "mfs", "markerfillstyle", "markerfillstyles"),
105
+ "linestyle": ("ls", "linestyles"),
106
+ "linewidth": ("lw", "linewidths"),
107
+ "marker": ("m", "markers"),
108
+ "markersize": ("s", "ms", "markersizes"), # WARNING: no 'sizes' here for barb
109
+ "markeredgewidth": ("ew", "edgewidth", "edgewidths", "mew", "markeredgewidths"),
110
+ "markeredgecolor": ("ec", "edgecolor", "edgecolors", "mec", "markeredgecolors"),
111
+ "markerfacecolor": (
112
+ "fc",
113
+ "facecolor",
114
+ "facecolors",
115
+ "fillcolor",
116
+ "fillcolors",
117
+ "mc",
118
+ "markercolor",
119
+ "markercolors",
120
+ "mfc",
121
+ "markerfacecolors",
122
+ ),
123
+ "zorder": ("z", "zorders"),
124
+ },
125
+ "collection": { # WARNING: face color ignored for line collections
126
+ "alpha": ("a", "alphas"), # WARNING: collections and contours use singular!
127
+ "colors": ("c", "color"),
128
+ "edgecolors": ("ec", "edgecolor", "mec", "markeredgecolor", "markeredgecolors"),
129
+ "facecolors": (
130
+ "fc",
131
+ "facecolor",
132
+ "fillcolor",
133
+ "fillcolors",
134
+ "mc",
135
+ "markercolor",
136
+ "markercolors",
137
+ "mfc",
138
+ "markerfacecolor",
139
+ "markerfacecolors", # noqa: E501
140
+ ),
141
+ "linestyles": ("ls", "linestyle"),
142
+ "linewidths": (
143
+ "lw",
144
+ "linewidth",
145
+ "ew",
146
+ "edgewidth",
147
+ "edgewidths",
148
+ "mew",
149
+ "markeredgewidth",
150
+ "markeredgewidths",
151
+ ), # noqa: E501
152
+ "marker": ("m", "markers"),
153
+ "sizes": ("s", "ms", "markersize", "markersizes"),
154
+ "zorder": ("z", "zorders"),
155
+ },
156
+ "text": {
157
+ "color": ("c", "fontcolor"), # NOTE: see text.py source code
158
+ "fontfamily": ("family", "name", "fontname"),
159
+ "fontsize": ("size",),
160
+ "fontstretch": ("stretch",),
161
+ "fontstyle": ("style",),
162
+ "fontvariant": ("variant",),
163
+ "fontweight": ("weight",),
164
+ "fontproperties": ("fp", "font", "font_properties"),
165
+ "zorder": ("z", "zorders"),
166
+ },
167
+ }
168
+
169
+
170
+ # Unit docstrings
171
+ # NOTE: Try to fit this into a single line. Cannot break up with newline as that will
172
+ # mess up docstring indentation since this is placed in indented param lines.
173
+ _units_docstring = "If float, units are {units}. If string, interpreted by `~ultraplot.utils.units`." # noqa: E501
174
+ docstring._snippet_manager["units.pt"] = _units_docstring.format(units="points")
175
+ docstring._snippet_manager["units.in"] = _units_docstring.format(units="inches")
176
+ docstring._snippet_manager["units.em"] = _units_docstring.format(units="em-widths")
177
+
178
+
179
+ # Style docstrings
180
+ # NOTE: These are needed in a few different places
181
+ _line_docstring = """
182
+ lw, linewidth, linewidths : unit-spec, default: :rc:`lines.linewidth`
183
+ The width of the line(s).
184
+ %(units.pt)s
185
+ ls, linestyle, linestyles : str, default: :rc:`lines.linestyle`
186
+ The style of the line(s).
187
+ c, color, colors : color-spec, optional
188
+ The color of the line(s). The property `cycle` is used by default.
189
+ a, alpha, alphas : float, optional
190
+ The opacity of the line(s). Inferred from `color` by default.
191
+ """
192
+ _patch_docstring = """
193
+ lw, linewidth, linewidths : unit-spec, default: :rc:`patch.linewidth`
194
+ The edge width of the patch(es).
195
+ %(units.pt)s
196
+ ls, linestyle, linestyles : str, default: '-'
197
+ The edge style of the patch(es).
198
+ ec, edgecolor, edgecolors : color-spec, default: '{edgecolor}'
199
+ The edge color of the patch(es).
200
+ fc, facecolor, facecolors, fillcolor, fillcolors : color-spec, optional
201
+ The face color of the patch(es). The property `cycle` is used by default.
202
+ a, alpha, alphas : float, optional
203
+ The opacity of the patch(es). Inferred from `facecolor` and `edgecolor` by default.
204
+ """
205
+ _pcolor_collection_docstring = """
206
+ lw, linewidth, linewidths : unit-spec, default: 0.3
207
+ The width of lines between grid boxes.
208
+ %(units.pt)s
209
+ ls, linestyle, linestyles : str, default: '-'
210
+ The style of lines between grid boxes.
211
+ ec, edgecolor, edgecolors : color-spec, default: 'k'
212
+ The color of lines between grid boxes.
213
+ a, alpha, alphas : float, optional
214
+ The opacity of the grid boxes. Inferred from `cmap` by default.
215
+ """
216
+ _contour_collection_docstring = """
217
+ lw, linewidth, linewidths : unit-spec, default: 0.3 or :rc:`lines.linewidth`
218
+ The width of the line contours. Default is ``0.3`` when adding to filled contours
219
+ or :rc:`lines.linewidth` otherwise. %(units.pt)s
220
+ ls, linestyle, linestyles : str, default: '-' or :rc:`contour.negative_linestyle`
221
+ The style of the line contours. Default is ``'-'`` for positive contours and
222
+ :rcraw:`contour.negative_linestyle` for negative contours.
223
+ ec, edgecolor, edgecolors : color-spec, default: 'k' or inferred
224
+ The color of the line contours. Default is ``'k'`` when adding to filled contours
225
+ or inferred from `color` or `cmap` otherwise.
226
+ a, alpha, alpha : float, optional
227
+ The opacity of the contours. Inferred from `edgecolor` by default.
228
+ """
229
+ _text_docstring = """
230
+ name, fontname, family, fontfamily : str, optional
231
+ The font typeface name (e.g., ``'Fira Math'``) or font family name (e.g.,
232
+ ``'serif'``). Matplotlib falls back to the system default if not found.
233
+ size, fontsize : unit-spec or str, optional
234
+ The font size. %(units.pt)s
235
+ This can also be a string indicating some scaling relative to
236
+ :rcraw:`font.size`. The sizes and scalings are shown below. The
237
+ scalings ``'med'``, ``'med-small'``, and ``'med-large'`` are
238
+ added by ultraplot while the rest are native matplotlib sizes.
239
+
240
+ .. _font_table:
241
+
242
+ ========================== =====
243
+ Size Scale
244
+ ========================== =====
245
+ ``'xx-small'`` 0.579
246
+ ``'x-small'`` 0.694
247
+ ``'small'``, ``'smaller'`` 0.833
248
+ ``'med-small'`` 0.9
249
+ ``'med'``, ``'medium'`` 1.0
250
+ ``'med-large'`` 1.1
251
+ ``'large'``, ``'larger'`` 1.2
252
+ ``'x-large'`` 1.440
253
+ ``'xx-large'`` 1.728
254
+ ``'larger'`` 1.2
255
+ ========================== =====
256
+
257
+ """
258
+ docstring._snippet_manager["artist.line"] = _line_docstring
259
+ docstring._snippet_manager["artist.text"] = _text_docstring
260
+ docstring._snippet_manager["artist.patch"] = _patch_docstring.format(edgecolor="none")
261
+ docstring._snippet_manager["artist.patch_black"] = _patch_docstring.format(
262
+ edgecolor="black"
263
+ ) # noqa: E501
264
+ docstring._snippet_manager["artist.collection_pcolor"] = _pcolor_collection_docstring
265
+ docstring._snippet_manager["artist.collection_contour"] = _contour_collection_docstring
266
+
267
+
268
+ def _get_aliases(category, *keys):
269
+ """
270
+ Get all available aliases.
271
+ """
272
+ aliases = []
273
+ for key in keys:
274
+ aliases.append(key)
275
+ aliases.extend(_alias_maps[category][key])
276
+ return tuple(aliases)
277
+
278
+
279
+ def _kwargs_to_args(options, *args, allow_extra=False, **kwargs):
280
+ """
281
+ Translate keyword arguments to positional arguments. Permit omitted
282
+ arguments so that plotting functions can infer values.
283
+ """
284
+ nargs, nopts = len(args), len(options)
285
+ if nargs > nopts and not allow_extra:
286
+ raise ValueError(f"Expected up to {nopts} positional arguments. Got {nargs}.")
287
+ args = list(args) # WARNING: Axes.text() expects return type of list
288
+ args.extend(None for _ in range(nopts - nargs)) # fill missing args
289
+ for idx, keys in enumerate(options):
290
+ if isinstance(keys, str):
291
+ keys = (keys,)
292
+ opts = {}
293
+ if args[idx] is not None: # positional args have first priority
294
+ opts[keys[0] + "_positional"] = args[idx]
295
+ for key in keys: # keyword args
296
+ opts[key] = kwargs.pop(key, None)
297
+ args[idx] = _not_none(**opts) # may reassign None
298
+ return args, kwargs
299
+
300
+
301
+ def _pop_kwargs(kwargs, *keys, **aliases):
302
+ """
303
+ Pop the input properties and return them in a new dictionary.
304
+ """
305
+ output = {}
306
+ aliases.update({key: () for key in keys})
307
+ for key, aliases in aliases.items():
308
+ aliases = (aliases,) if isinstance(aliases, str) else aliases
309
+ opts = {key: kwargs.pop(key, None) for key in (key, *aliases)}
310
+ value = _not_none(**opts)
311
+ if value is not None:
312
+ output[key] = value
313
+ return output
314
+
315
+
316
+ def _pop_params(kwargs, *funcs, ignore_internal=False):
317
+ """
318
+ Pop parameters of the input functions or methods.
319
+ """
320
+ internal_params = {
321
+ "default_cmap",
322
+ "default_discrete",
323
+ "inbounds",
324
+ "plot_contours",
325
+ "plot_lines",
326
+ "skip_autolev",
327
+ "to_centers",
328
+ }
329
+ output = {}
330
+ for func in funcs:
331
+ if isinstance(func, inspect.Signature):
332
+ sig = func
333
+ elif callable(func):
334
+ sig = inspect.signature(func)
335
+ elif func is None:
336
+ continue
337
+ else:
338
+ raise RuntimeError(f"Internal error. Invalid function {func!r}.")
339
+ for key in sig.parameters:
340
+ value = kwargs.pop(key, None)
341
+ if ignore_internal and key in internal_params:
342
+ continue
343
+ if value is not None:
344
+ output[key] = value
345
+ return output
346
+
347
+
348
+ def _pop_props(input, *categories, prefix=None, ignore=None, skip=None):
349
+ """
350
+ Pop the registered properties and return them in a new dictionary.
351
+ """
352
+ output = {}
353
+ skip = skip or ()
354
+ ignore = ignore or ()
355
+ if isinstance(skip, str): # e.g. 'sizes' for barbs() input
356
+ skip = (skip,)
357
+ if isinstance(ignore, str): # e.g. 'marker' to ignore marker properties
358
+ ignore = (ignore,)
359
+ prefix = prefix or "" # e.g. 'box' for boxlw, boxlinewidth, etc.
360
+ for category in categories:
361
+ for key, aliases in _alias_maps[category].items():
362
+ if isinstance(aliases, str):
363
+ aliases = (aliases,)
364
+ opts = {
365
+ prefix + alias: input.pop(prefix + alias, None)
366
+ for alias in (key, *aliases)
367
+ if alias not in skip
368
+ }
369
+ prop = _not_none(**opts)
370
+ if prop is None:
371
+ continue
372
+ if any(string in key for string in ignore):
373
+ warnings._warn_ultraplot(f"Ignoring property {key}={prop!r}.")
374
+ continue
375
+ if isinstance(prop, str): # ad-hoc unit conversion
376
+ if key in ("fontsize",):
377
+ from ..utils import _fontsize_to_pt
378
+
379
+ prop = _fontsize_to_pt(prop)
380
+ if key in ("linewidth", "linewidths", "markersize"):
381
+ from ..utils import units
382
+
383
+ prop = units(prop, "pt")
384
+ output[key] = prop
385
+ return output
386
+
387
+
388
+ def _pop_rc(src, *, ignore_conflicts=True):
389
+ """
390
+ Pop the rc setting names and mode for a `~Configurator.context` block.
391
+ """
392
+ # NOTE: Must ignore deprected or conflicting rc params
393
+ # NOTE: rc_mode == 2 applies only the updated params. A power user
394
+ # could use ax.format(rc_mode=0) to re-apply all the current settings
395
+ conflict_params = (
396
+ "alpha",
397
+ "color",
398
+ "facecolor",
399
+ "edgecolor",
400
+ "linewidth",
401
+ "basemap",
402
+ "backend",
403
+ "share",
404
+ "span",
405
+ "tight",
406
+ "span",
407
+ )
408
+ kw = src.pop("rc_kw", None) or {}
409
+ if "mode" in src:
410
+ src["rc_mode"] = src.pop("mode")
411
+ warnings._warn_ultraplot(
412
+ "Keyword 'mode' was deprecated in v0.6. Please use 'rc_mode' instead."
413
+ )
414
+ mode = src.pop("rc_mode", None)
415
+ mode = _not_none(mode, 2) # only apply updated params by default
416
+ for key, value in tuple(src.items()):
417
+ name = rcsetup._rc_nodots.get(key, None)
418
+ if ignore_conflicts and name in conflict_params:
419
+ name = None # former renamed settings
420
+ if name is not None:
421
+ kw[name] = src.pop(key)
422
+ return kw, mode
423
+
424
+
425
+ def _translate_loc(loc, mode, *, default=None, **kwargs):
426
+ """
427
+ Translate the location string `loc` into a standardized form. The `mode`
428
+ must be a string for which there is a :rcraw:`mode.loc` setting. Additional
429
+ options can be added with keyword arguments.
430
+ """
431
+ # Create specific options dictionary
432
+ # NOTE: This is not inside validators.py because it is also used to
433
+ # validate various user-input locations.
434
+ if mode == "align":
435
+ loc_dict = rcsetup.ALIGN_LOCS
436
+ elif mode == "panel":
437
+ loc_dict = rcsetup.PANEL_LOCS
438
+ elif mode == "legend":
439
+ loc_dict = rcsetup.LEGEND_LOCS
440
+ elif mode == "colorbar":
441
+ loc_dict = rcsetup.COLORBAR_LOCS
442
+ elif mode == "text":
443
+ loc_dict = rcsetup.TEXT_LOCS
444
+ else:
445
+ raise ValueError(f"Invalid mode {mode!r}.")
446
+ loc_dict = loc_dict.copy()
447
+ loc_dict.update(kwargs)
448
+
449
+ # Translate location
450
+ if loc in (None, True):
451
+ loc = default
452
+ elif isinstance(loc, (str, Integral)):
453
+ try:
454
+ loc = loc_dict[loc]
455
+ except KeyError:
456
+ raise KeyError(
457
+ f"Invalid {mode} location {loc!r}. Options are: "
458
+ + ", ".join(map(repr, loc_dict))
459
+ + "."
460
+ )
461
+ elif (
462
+ mode == "legend"
463
+ and np.iterable(loc)
464
+ and len(loc) == 2
465
+ and all(isinstance(l, Real) for l in loc)
466
+ ):
467
+ loc = tuple(loc)
468
+ else:
469
+ raise KeyError(f"Invalid {mode} location {loc!r}.")
470
+
471
+ # Kludge / white lie
472
+ # TODO: Implement 'best' colorbar location
473
+ if mode == "colorbar" and loc == "best":
474
+ loc = "lower right"
475
+
476
+ return loc
477
+
478
+
479
+ def _translate_grid(b, key):
480
+ """
481
+ Translate an instruction to turn either major or minor gridlines on or off into a
482
+ boolean and string applied to :rcraw:`axes.grid` and :rcraw:`axes.grid.which`.
483
+ """
484
+ ob = rc_matplotlib["axes.grid"]
485
+ owhich = rc_matplotlib["axes.grid.which"]
486
+
487
+ # Instruction is to turn off gridlines
488
+ if not b:
489
+ # Gridlines are already off, or they are on for the particular
490
+ # ones that we want to turn off. Instruct to turn both off.
491
+ if (
492
+ not ob
493
+ or key == "grid"
494
+ and owhich == "major"
495
+ or key == "gridminor"
496
+ and owhich == "minor"
497
+ ):
498
+ which = "both" # disable both sides
499
+ # Gridlines are currently on for major and minor ticks, so we
500
+ # instruct to turn on gridlines for the one we *don't* want off
501
+ elif owhich == "both": # and ob is True, as already tested
502
+ # if gridminor=False, enable major, and vice versa
503
+ b = True
504
+ which = "major" if key == "gridminor" else "minor"
505
+ # Gridlines are on for the ones that we *didn't* instruct to
506
+ # turn off, and off for the ones we do want to turn off. This
507
+ # just re-asserts the ones that are already on.
508
+ else:
509
+ b = True
510
+ which = owhich
511
+
512
+ # Instruction is to turn on gridlines
513
+ else:
514
+ # Gridlines are already both on, or they are off only for the
515
+ # ones that we want to turn on. Turn on gridlines for both.
516
+ if (
517
+ owhich == "both"
518
+ or key == "grid"
519
+ and owhich == "minor"
520
+ or key == "gridminor"
521
+ and owhich == "major"
522
+ ):
523
+ which = "both"
524
+ # Gridlines are off for both, or off for the ones that we
525
+ # don't want to turn on. We can just turn on these ones.
526
+ else:
527
+ which = owhich
528
+
529
+ return b, which
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Utilities for benchmarking ultraplot performance.
4
+ """
5
+ import time
6
+
7
+ from . import ic # noqa: F401
8
+
9
+ BENCHMARK = False # toggle this to turn on benchmarking (see timers.py)
10
+
11
+
12
+ class _benchmark(object):
13
+ """
14
+ Context object for timing arbitrary blocks of code.
15
+ """
16
+
17
+ def __init__(self, message):
18
+ self.message = message
19
+
20
+ def __enter__(self):
21
+ if BENCHMARK:
22
+ self.time = time.perf_counter()
23
+
24
+ def __exit__(self, *args): # noqa: U100
25
+ if BENCHMARK:
26
+ print(f"{self.message}: {time.perf_counter() - self.time}s")
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Utilities for manging context.
4
+ """
5
+ from . import ic # noqa: F401
6
+
7
+
8
+ class _empty_context(object):
9
+ """
10
+ A dummy context manager.
11
+ """
12
+
13
+ def __init__(self):
14
+ pass
15
+
16
+ def __enter__(self):
17
+ pass
18
+
19
+ def __exit__(self, *args): # noqa: U100
20
+ pass
21
+
22
+
23
+ class _state_context(object):
24
+ """
25
+ Temporarily modify attribute(s) for an arbitrary object.
26
+ """
27
+
28
+ def __init__(self, obj, **kwargs):
29
+ self._obj = obj
30
+ self._attrs_new = kwargs
31
+ self._attrs_prev = {
32
+ key: getattr(obj, key) for key in kwargs if hasattr(obj, key)
33
+ }
34
+
35
+ def __enter__(self):
36
+ for key, value in self._attrs_new.items():
37
+ setattr(self._obj, key, value)
38
+
39
+ def __exit__(self, *args): # noqa: U100
40
+ for key in self._attrs_new.keys():
41
+ if key in self._attrs_prev:
42
+ setattr(self._obj, key, self._attrs_prev[key])
43
+ else:
44
+ delattr(self._obj, key)