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,381 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Polar axes using azimuth and radius instead of *x* and *y*.
4
+ """
5
+ import inspect
6
+
7
+ import matplotlib.projections.polar as mpolar
8
+ import numpy as np
9
+
10
+ from .. import constructor
11
+ from .. import ticker as pticker
12
+ from ..config import rc
13
+ from ..internals import ic # noqa: F401
14
+ from ..internals import _not_none, _pop_rc, docstring
15
+ from . import plot, shared
16
+
17
+ __all__ = ["PolarAxes"]
18
+
19
+
20
+ # Format docstring
21
+ _format_docstring = """
22
+ r0 : float, default: 0
23
+ The radial origin.
24
+ theta0 : {'N', 'NW', 'W', 'SW', 'S', 'SE', 'E', 'NE'}, optional
25
+ The zero azimuth location.
26
+ thetadir : {1, -1, 'anticlockwise', 'counterclockwise', 'clockwise'}, optional
27
+ The positive azimuth direction. Clockwise corresponds to
28
+ ``-1`` and anticlockwise corresponds to ``1``.
29
+ thetamin, thetamax : float, optional
30
+ The lower and upper azimuthal bounds in degrees. If
31
+ ``thetamax != thetamin + 360``, this produces a sector plot.
32
+ thetalim : 2-tuple of float or None, optional
33
+ Specifies `thetamin` and `thetamax` at once.
34
+ rmin, rmax : float, optional
35
+ The inner and outer radial limits. If ``r0 != rmin``, this
36
+ produces an annular plot.
37
+ rlim : 2-tuple of float or None, optional
38
+ Specifies `rmin` and `rmax` at once.
39
+ rborder : bool, optional
40
+ Whether to draw the polar axes border. Visibility of the "inner"
41
+ radial spine and "start" and "end" azimuthal spines is controlled
42
+ automatically by matplotlib.
43
+ thetagrid, rgrid, grid : bool, optional
44
+ Whether to draw major gridlines for the azimuthal and radial axis.
45
+ Use the keyword `grid` to toggle both.
46
+ thetagridminor, rgridminor, gridminor : bool, optional
47
+ Whether to draw minor gridlines for the azimuthal and radial axis.
48
+ Use the keyword `gridminor` to toggle both.
49
+ thetagridcolor, rgridcolor, gridcolor : color-spec, optional
50
+ Color for the major and minor azimuthal and radial gridlines.
51
+ Use the keyword `gridcolor` to set both at once.
52
+ thetalocator, rlocator : locator-spec, optional
53
+ Used to determine the azimuthal and radial gridline positions.
54
+ Passed to the `~ultraplot.constructor.Locator` constructor. Can be
55
+ float, list of float, string, or `matplotlib.ticker.Locator` instance.
56
+ thetalines, rlines
57
+ Aliases for `thetalocator`, `rlocator`.
58
+ thetalocator_kw, rlocator_kw : dict-like, optional
59
+ The azimuthal and radial locator settings. Passed to
60
+ `~ultraplot.constructor.Locator`.
61
+ thetaminorlocator, rminorlocator : optional
62
+ As for `thetalocator`, `rlocator`, but for the minor gridlines.
63
+ thetaminorticks, rminorticks : optional
64
+ Aliases for `thetaminorlocator`, `rminorlocator`.
65
+ thetaminorlocator_kw, rminorlocator_kw
66
+ As for `thetalocator_kw`, `rlocator_kw`, but for the minor locator.
67
+ rlabelpos : float, optional
68
+ The azimuth at which radial coordinates are labeled.
69
+ thetaformatter, rformatter : formatter-spec, optional
70
+ Used to determine the azimuthal and radial label format.
71
+ Passed to the `~ultraplot.constructor.Formatter` constructor.
72
+ Can be string, list of string, or `matplotlib.ticker.Formatter`
73
+ instance. Use ``[]``, ``'null'``, or ``'none'`` for no labels.
74
+ thetalabels, rlabels : optional
75
+ Aliases for `thetaformatter`, `rformatter`.
76
+ thetaformatter_kw, rformatter_kw : dict-like, optional
77
+ The azimuthal and radial label formatter settings. Passed to
78
+ `~ultraplot.constructor.Formatter`.
79
+ color : color-spec, default: :rc:`meta.color`
80
+ Color for the axes edge. Propagates to `labelcolor` unless specified
81
+ otherwise (similar to `ultraplot.axes.CartesianAxes.format`).
82
+ labelcolor, gridlabelcolor : color-spec, default: `color` or :rc:`grid.labelcolor`
83
+ Color for the gridline labels.
84
+ labelpad, gridlabelpad : unit-spec, default: :rc:`grid.labelpad`
85
+ The padding between the axes edge and the radial and azimuthal labels.
86
+ %(units.pt)s
87
+ labelsize, gridlabelsize : unit-spec or str, default: :rc:`grid.labelsize`
88
+ Font size for the gridline labels.
89
+ %(units.pt)s
90
+ labelweight, gridlabelweight : str, default: :rc:`grid.labelweight`
91
+ Font weight for the gridline labels.
92
+ """
93
+ docstring._snippet_manager["polar.format"] = _format_docstring
94
+
95
+
96
+ class PolarAxes(shared._SharedAxes, plot.PlotAxes, mpolar.PolarAxes):
97
+ """
98
+ Axes subclass for plotting in polar coordinates. Adds the `~PolarAxes.format`
99
+ method and overrides several existing methods.
100
+
101
+ Important
102
+ ---------
103
+ This axes subclass can be used by passing ``proj='polar'``
104
+ to axes-creation commands like `~ultraplot.figure.Figure.add_axes`,
105
+ `~ultraplot.figure.Figure.add_subplot`, and `~ultraplot.figure.Figure.subplots`.
106
+ """
107
+
108
+ _name = "polar"
109
+
110
+ @docstring._snippet_manager
111
+ def __init__(self, *args, **kwargs):
112
+ """
113
+ Parameters
114
+ ----------
115
+ *args
116
+ Passed to `matplotlib.axes.Axes`.
117
+ %(polar.format)s
118
+
119
+ Other parameters
120
+ ----------------
121
+ %(axes.format)s
122
+ %(rc.init)s
123
+
124
+ See also
125
+ --------
126
+ PolarAxes.format
127
+ ultraplot.axes.Axes
128
+ ultraplot.axes.PlotAxes
129
+ matplotlib.projections.PolarAxes
130
+ ultraplot.figure.Figure.subplot
131
+ ultraplot.figure.Figure.add_subplot
132
+ """
133
+ # Set tick length to zero so azimuthal labels are not too offset
134
+ # Change default radial axis formatter but keep default theta one
135
+ super().__init__(*args, **kwargs)
136
+ self.yaxis.set_major_formatter(pticker.AutoFormatter())
137
+ self.yaxis.isDefault_majfmt = True
138
+ for axis in (self.xaxis, self.yaxis):
139
+ axis.set_tick_params(which="both", size=0)
140
+
141
+ def _update_formatter(self, x, *, formatter=None, formatter_kw=None):
142
+ """
143
+ Update the gridline label formatter.
144
+ """
145
+ # Tick formatter and toggling
146
+ axis = getattr(self, x + "axis")
147
+ formatter_kw = formatter_kw or {}
148
+ if formatter is not None:
149
+ formatter = constructor.Formatter(formatter, **formatter_kw) # noqa: E501
150
+ axis.set_major_formatter(formatter)
151
+
152
+ def _update_limits(self, x, *, min_=None, max_=None, lim=None):
153
+ """
154
+ Update the limits.
155
+ """
156
+ # Try to use public API where possible
157
+ r = "theta" if x == "x" else "r"
158
+ min_, max_ = self._min_max_lim(r, min_, max_, lim)
159
+ if min_ is not None:
160
+ getattr(self, f"set_{r}min")(min_)
161
+ if max_ is not None:
162
+ getattr(self, f"set_{r}max")(max_)
163
+
164
+ def _update_locators(
165
+ self,
166
+ x,
167
+ *,
168
+ locator=None,
169
+ locator_kw=None,
170
+ minorlocator=None,
171
+ minorlocator_kw=None,
172
+ ):
173
+ """
174
+ Update the gridline locator.
175
+ """
176
+ # TODO: Add minor tick 'toggling' as with cartesian axes?
177
+ # NOTE: Must convert theta locator input to radians, then back to deg.
178
+ r = "theta" if x == "x" else "r"
179
+ axis = getattr(self, x + "axis")
180
+ min_ = getattr(self, f"get_{r}min")()
181
+ max_ = getattr(self, f"get_{r}max")()
182
+ for i, (loc, loc_kw) in enumerate(
183
+ zip((locator, minorlocator), (locator_kw, minorlocator_kw))
184
+ ):
185
+ if loc is None:
186
+ continue
187
+ # Get locator
188
+ loc_kw = loc_kw or {}
189
+ loc = constructor.Locator(loc, **loc_kw)
190
+ # Sanitize values
191
+ array = loc.tick_values(min_, max_)
192
+ array = array[(array >= min_) & (array <= max_)]
193
+ if x == "x":
194
+ array = np.deg2rad(array)
195
+ if np.isclose(array[-1], min_ + 2 * np.pi): # exclusive if 360 deg
196
+ array = array[:-1]
197
+ # Assign fixed location
198
+ loc = constructor.Locator(array) # convert to FixedLocator
199
+ if i == 0:
200
+ axis.set_major_locator(loc)
201
+ else:
202
+ axis.set_minor_locator(loc)
203
+
204
+ @docstring._snippet_manager
205
+ def format(
206
+ self,
207
+ *,
208
+ r0=None,
209
+ theta0=None,
210
+ thetadir=None,
211
+ thetamin=None,
212
+ thetamax=None,
213
+ thetalim=None,
214
+ rmin=None,
215
+ rmax=None,
216
+ rlim=None,
217
+ thetagrid=None,
218
+ rgrid=None,
219
+ thetagridminor=None,
220
+ rgridminor=None,
221
+ thetagridcolor=None,
222
+ rgridcolor=None,
223
+ rlabelpos=None,
224
+ rscale=None,
225
+ rborder=None,
226
+ thetalocator=None,
227
+ rlocator=None,
228
+ thetalines=None,
229
+ rlines=None,
230
+ thetalocator_kw=None,
231
+ rlocator_kw=None,
232
+ thetaminorlocator=None,
233
+ rminorlocator=None,
234
+ thetaminorlines=None,
235
+ rminorlines=None, # noqa: E501
236
+ thetaminorlocator_kw=None,
237
+ rminorlocator_kw=None,
238
+ thetaformatter=None,
239
+ rformatter=None,
240
+ thetalabels=None,
241
+ rlabels=None,
242
+ thetaformatter_kw=None,
243
+ rformatter_kw=None,
244
+ labelpad=None,
245
+ labelsize=None,
246
+ labelcolor=None,
247
+ labelweight=None,
248
+ **kwargs,
249
+ ):
250
+ """
251
+ Modify axes limits, radial and azimuthal gridlines, and more. Note that
252
+ all of the ``theta`` arguments are specified in degrees, not radians.
253
+
254
+ Parameters
255
+ ----------
256
+ %(polar.format)s
257
+
258
+ Other parameters
259
+ ----------------
260
+ %(axes.format)s
261
+ %(figure.format)s
262
+ %(rc.format)s
263
+
264
+ See also
265
+ --------
266
+ ultraplot.axes.Axes.format
267
+ ultraplot.config.Configurator.context
268
+ """
269
+ # NOTE: Here we capture 'label.pad' rc argument normally used for
270
+ # x and y axis labels as shorthand for 'tick.labelpad'.
271
+ rc_kw, rc_mode = _pop_rc(kwargs)
272
+ labelcolor = _not_none(labelcolor, kwargs.get("color", None))
273
+ with rc.context(rc_kw, mode=rc_mode):
274
+ # Not mutable default args
275
+ thetalocator_kw = thetalocator_kw or {}
276
+ thetaminorlocator_kw = thetaminorlocator_kw or {}
277
+ thetaformatter_kw = thetaformatter_kw or {}
278
+ rlocator_kw = rlocator_kw or {}
279
+ rminorlocator_kw = rminorlocator_kw or {}
280
+ rformatter_kw = rformatter_kw or {}
281
+
282
+ # Flexible input
283
+ thetalocator = _not_none(thetalines=thetalines, thetalocator=thetalocator)
284
+ thetaformatter = _not_none(
285
+ thetalabels=thetalabels, thetaformatter=thetaformatter
286
+ ) # noqa: E501
287
+ thetaminorlocator = _not_none(
288
+ thetaminorlines=thetaminorlines, thetaminorlocator=thetaminorlocator
289
+ ) # noqa: E501
290
+ rlocator = _not_none(rlines=rlines, rlocator=rlocator)
291
+ rformatter = _not_none(rlabels=rlabels, rformatter=rformatter)
292
+ rminorlocator = _not_none(
293
+ rminorlines=rminorlines, rminorlocator=rminorlocator
294
+ ) # noqa: E501
295
+
296
+ # Special radius settings
297
+ if r0 is not None:
298
+ self.set_rorigin(r0)
299
+ if rlabelpos is not None:
300
+ self.set_rlabel_position(rlabelpos)
301
+ if rscale is not None:
302
+ self.set_rscale(rscale)
303
+ if rborder is not None:
304
+ self.spines["polar"].set_visible(bool(rborder))
305
+
306
+ # Special azimuth settings
307
+ if theta0 is not None:
308
+ self.set_theta_zero_location(theta0)
309
+ if thetadir is not None:
310
+ self.set_theta_direction(thetadir)
311
+
312
+ # Loop over axes
313
+ for (
314
+ x,
315
+ min_,
316
+ max_,
317
+ lim,
318
+ grid,
319
+ gridminor,
320
+ gridcolor,
321
+ locator,
322
+ locator_kw,
323
+ formatter,
324
+ formatter_kw,
325
+ minorlocator,
326
+ minorlocator_kw,
327
+ ) in zip(
328
+ ("x", "y"),
329
+ (thetamin, rmin),
330
+ (thetamax, rmax),
331
+ (thetalim, rlim),
332
+ (thetagrid, rgrid),
333
+ (thetagridminor, rgridminor),
334
+ (thetagridcolor, rgridcolor),
335
+ (thetalocator, rlocator),
336
+ (thetalocator_kw, rlocator_kw),
337
+ (thetaformatter, rformatter),
338
+ (thetaformatter_kw, rformatter_kw),
339
+ (thetaminorlocator, rminorlocator),
340
+ (thetaminorlocator_kw, rminorlocator_kw),
341
+ ):
342
+ # Axis limits
343
+ self._update_limits(x, min_=min_, max_=max_, lim=lim)
344
+
345
+ # Axis tick settings
346
+ # NOTE: Here use 'grid.labelpad' instead of 'tick.labelpad'. Default
347
+ # offset for grid labels is larger than for tick labels.
348
+ self._update_ticks(
349
+ x,
350
+ grid=grid,
351
+ gridminor=gridminor,
352
+ gridcolor=gridcolor,
353
+ gridpad=True,
354
+ labelpad=labelpad,
355
+ labelcolor=labelcolor,
356
+ labelsize=labelsize,
357
+ labelweight=labelweight,
358
+ )
359
+
360
+ # Axis locator
361
+ self._update_locators(
362
+ x,
363
+ locator=locator,
364
+ locator_kw=locator_kw,
365
+ minorlocator=minorlocator,
366
+ minorlocator_kw=minorlocator_kw,
367
+ )
368
+
369
+ # Axis formatter
370
+ self._update_formatter(
371
+ x, formatter=formatter, formatter_kw=formatter_kw
372
+ )
373
+
374
+ # Parent format method
375
+ super().format(rc_kw=rc_kw, rc_mode=rc_mode, **kwargs)
376
+
377
+
378
+ # Apply signature obfuscation after storing previous signature
379
+ # NOTE: This is needed for __init__
380
+ PolarAxes._format_signatures[PolarAxes] = inspect.signature(PolarAxes.format)
381
+ PolarAxes.format = docstring._obfuscate_kwargs(PolarAxes.format)
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ An axes used to jointly format Cartesian and polar axes.
4
+ """
5
+ # NOTE: We could define these in base.py but idea is projection-specific formatters
6
+ # should never be defined on the base class. Might add to this class later anyway.
7
+ import numpy as np
8
+
9
+ from ..config import rc
10
+ from ..internals import ic # noqa: F401
11
+ from ..internals import _pop_kwargs
12
+ from ..utils import _fontsize_to_pt, _not_none, units
13
+
14
+
15
+ class _SharedAxes(object):
16
+ """
17
+ Mix-in class with methods shared between `~ultraplot.axes.CartesianAxes`
18
+ and `~ultraplot.axes.PolarAxes`.
19
+ """
20
+
21
+ @staticmethod
22
+ def _min_max_lim(key, min_=None, max_=None, lim=None):
23
+ """
24
+ Translate and standardize minimum, maximum, and limit keyword arguments.
25
+ """
26
+ if lim is None:
27
+ lim = (None, None)
28
+ if not np.iterable(lim) or not len(lim) == 2:
29
+ raise ValueError(f"Invalid {key}{lim!r}. Must be 2-tuple of values.")
30
+ min_ = _not_none(**{f"{key}min": min_, f"{key}lim_0": lim[0]})
31
+ max_ = _not_none(**{f"{key}max": max_, f"{key}lim_1": lim[1]})
32
+ return min_, max_
33
+
34
+ def _update_background(self, x=None, tickwidth=None, tickwidthratio=None, **kwargs):
35
+ """
36
+ Update the background patch and spines.
37
+ """
38
+ # Update the background patch
39
+ kw_face, kw_edge = rc._get_background_props(**kwargs)
40
+ self.patch.update(kw_face)
41
+ if x is None:
42
+ opts = self.spines
43
+ elif x == "x":
44
+ opts = ("bottom", "top", "inner", "polar")
45
+ else:
46
+ opts = ("left", "right", "start", "end")
47
+ for opt in opts:
48
+ self.spines.get(opt, {}).update(kw_edge)
49
+
50
+ # Update the tick colors
51
+ axis = "both" if x is None else x
52
+ x = _not_none(x, "x")
53
+ obj = getattr(self, x + "axis")
54
+ edgecolor = kw_edge.get("edgecolor", None)
55
+ if edgecolor is not None:
56
+ self.tick_params(axis=axis, which="both", color=edgecolor)
57
+
58
+ # Update the tick widths
59
+ # NOTE: Only use 'linewidth' if it was explicitly passed. Do not
60
+ # include 'linewidth' inferred from rc['axes.linewidth'] setting.
61
+ kwmajor = getattr(obj, "_major_tick_kw", {}) # graceful fallback if API changes
62
+ kwminor = getattr(obj, "_minor_tick_kw", {})
63
+ if "linewidth" in kwargs:
64
+ tickwidth = _not_none(tickwidth, kwargs["linewidth"])
65
+ tickwidth = _not_none(tickwidth, rc.find("tick.width", context=True))
66
+ tickwidthratio = _not_none(
67
+ tickwidthratio, rc.find("tick.widthratio", context=True)
68
+ ) # noqa: E501
69
+ tickwidth_prev = kwmajor.get("width", rc[x + "tick.major.width"])
70
+ if tickwidth_prev == 0:
71
+ tickwidthratio_prev = rc["tick.widthratio"] # no other way of knowing
72
+ else:
73
+ tickwidthratio_prev = (
74
+ kwminor.get("width", rc[x + "tick.minor.width"]) / tickwidth_prev
75
+ ) # noqa: E501
76
+ for which in ("major", "minor"):
77
+ kwticks = {}
78
+ if tickwidth is not None or tickwidthratio is not None:
79
+ tickwidth = _not_none(tickwidth, tickwidth_prev)
80
+ kwticks["width"] = tickwidth = units(tickwidth, "pt")
81
+ if tickwidth == 0: # avoid unnecessary padding
82
+ kwticks["size"] = 0
83
+ elif which == "minor":
84
+ tickwidthratio = _not_none(tickwidthratio, tickwidthratio_prev)
85
+ kwticks["width"] *= tickwidthratio
86
+ self.tick_params(axis=axis, which=which, **kwticks)
87
+
88
+ def _update_ticks(
89
+ self,
90
+ x,
91
+ *,
92
+ grid=None,
93
+ gridminor=None,
94
+ gridpad=None,
95
+ gridcolor=None,
96
+ ticklen=None,
97
+ ticklenratio=None,
98
+ tickdir=None,
99
+ tickcolor=None,
100
+ labeldir=None,
101
+ labelpad=None,
102
+ labelcolor=None,
103
+ labelsize=None,
104
+ labelweight=None,
105
+ ):
106
+ """
107
+ Update the gridlines and labels. Set `gridpad` to ``True`` to use grid padding.
108
+ """
109
+ # Filter out text properties
110
+ axis = "both" if x is None else x
111
+ kwtext = rc._get_ticklabel_props(axis)
112
+ kwtext_extra = _pop_kwargs(kwtext, "weight", "family")
113
+ kwtext = {"label" + key: value for key, value in kwtext.items()}
114
+ if labelcolor is not None:
115
+ kwtext["labelcolor"] = labelcolor
116
+ if labelsize is not None:
117
+ kwtext["labelsize"] = labelsize
118
+ if labelweight is not None:
119
+ kwtext_extra["weight"] = labelweight
120
+
121
+ # Apply tick settings with tick_params when possible
122
+ x = _not_none(x, "x")
123
+ obj = getattr(self, x + "axis")
124
+ kwmajor = getattr(obj, "_major_tick_kw", {}) # graceful fallback if API changes
125
+ kwminor = getattr(obj, "_minor_tick_kw", {})
126
+ ticklen_prev = kwmajor.get("size", rc[x + "tick.major.size"])
127
+ if ticklen_prev == 0:
128
+ ticklenratio_prev = rc["tick.lenratio"] # no other way of knowing
129
+ else:
130
+ ticklenratio_prev = (
131
+ kwminor.get("size", rc[x + "tick.minor.size"]) / ticklen_prev
132
+ ) # noqa: E501
133
+ for b, which in zip((grid, gridminor), ("major", "minor")):
134
+ # Tick properties
135
+ # NOTE: Must make 'tickcolor' overwrite 'labelcolor' or else 'color'
136
+ # passed to __init__ will not apply correctly. Annoying but unavoidable
137
+ kwticks = rc._get_tickline_props(axis, which=which)
138
+ if labelpad is not None:
139
+ kwticks["pad"] = labelpad
140
+ if tickcolor is not None:
141
+ kwticks["color"] = tickcolor
142
+ if ticklen is not None or ticklenratio is not None:
143
+ ticklen = _not_none(ticklen, ticklen_prev)
144
+ kwticks["size"] = ticklen = units(ticklen, "pt")
145
+ if ticklen > 0 and which == "minor":
146
+ ticklenratio = _not_none(ticklenratio, ticklenratio_prev)
147
+ kwticks["size"] *= ticklenratio
148
+ if gridpad: # use grid.labelpad instead of tick.labelpad
149
+ kwticks.pop("pad", None)
150
+ pad = rc.find("grid.labelpad", context=True)
151
+ if pad is not None:
152
+ kwticks["pad"] = units(pad, "pt")
153
+
154
+ # Tick direction properties
155
+ # NOTE: These have no x and y-specific versions but apply here anyway
156
+ if labeldir == "in": # put tick labels inside the plot
157
+ tickdir = "in"
158
+ kwticks.setdefault(
159
+ "pad",
160
+ -rc[f"{axis}tick.major.size"]
161
+ - _not_none(labelpad, rc[f"{axis}tick.major.pad"])
162
+ - _fontsize_to_pt(rc[f"{axis}tick.labelsize"]),
163
+ )
164
+ if tickdir is not None:
165
+ kwticks["direction"] = tickdir
166
+
167
+ # Gridline properties
168
+ # NOTE: Internally ax.grid() passes gridOn to ax.tick_params() but this
169
+ # is undocumented and might have weird side effects. Just use ax.grid()
170
+ b = rc._get_gridline_bool(b, axis=axis, which=which)
171
+ if b is not None:
172
+ self.grid(b, axis=axis, which=which)
173
+ kwlines = rc._get_gridline_props(which=which)
174
+ if "axisbelow" in kwlines:
175
+ self.set_axisbelow(kwlines.pop("axisbelow"))
176
+ if gridcolor is not None:
177
+ kwlines["grid_color"] = gridcolor
178
+
179
+ # Apply tick and gridline properties
180
+ kwticks.pop("ndivs", None) # not in mpl
181
+ self.tick_params(axis=axis, which=which, **kwticks, **kwlines, **kwtext)
182
+
183
+ # Apply settings that can't be controlled with tick_params
184
+ if kwtext_extra:
185
+ for lab in obj.get_ticklabels():
186
+ lab.update(kwtext_extra)
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ The "3D" axes class.
4
+ """
5
+ from . import base, shared
6
+
7
+ try:
8
+ from mpl_toolkits.mplot3d import Axes3D
9
+ except ImportError:
10
+ Axes3D = object
11
+
12
+
13
+ class ThreeAxes(shared._SharedAxes, base.Axes, Axes3D):
14
+ """
15
+ Simple mix-in of `ultraplot.axes.Axes` with `~mpl_toolkits.mplot3d.axes3d.Axes3D`.
16
+
17
+ Important
18
+ ---------
19
+ Note that this subclass does *not* implement the `~ultraplot.axes.PlotAxes`
20
+ plotting overrides. This axes subclass can be used by passing ``proj='3d'`` or
21
+ ``proj='three'`` to axes-creation commands like `~ultraplot.figure.Figure.add_axes`,
22
+ `~ultraplot.figure.Figure.add_subplot`, and `~ultraplot.figure.Figure.subplots`.
23
+ """
24
+
25
+ # TODO: Figure out a way to have internal Axes3D calls to plotting commands
26
+ # access the overrides rather than the originals? May be impossible.
27
+ _name = "three"
28
+ _name_aliases = ("3d",)
29
+
30
+ def __init__(self, *args, **kwargs):
31
+ import mpl_toolkits.mplot3d # noqa: F401 verify package is available
32
+
33
+ kwargs.setdefault("alpha", 0.0)
34
+ super().__init__(*args, **kwargs)