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.
- ultraplot/__init__.py +115 -0
- ultraplot/__init__.py.rej +58 -0
- ultraplot/axes/__init__.py +42 -0
- ultraplot/axes/base.py +3240 -0
- ultraplot/axes/cartesian.py +1425 -0
- ultraplot/axes/geo.py +1675 -0
- ultraplot/axes/plot.py +4569 -0
- ultraplot/axes/polar.py +381 -0
- ultraplot/axes/shared.py +186 -0
- ultraplot/axes/three.py +34 -0
- ultraplot/cmaps/Algae.rgb +256 -0
- ultraplot/cmaps/Amp.rgb +256 -0
- ultraplot/cmaps/BR.rgb +256 -0
- ultraplot/cmaps/Balance.rgb +256 -0
- ultraplot/cmaps/Blues1_r.xml +17 -0
- ultraplot/cmaps/Blues2.xml +16 -0
- ultraplot/cmaps/Blues3.xml +25 -0
- ultraplot/cmaps/Blues4_r.xml +17 -0
- ultraplot/cmaps/Blues5.xml +16 -0
- ultraplot/cmaps/Blues6.xml +25 -0
- ultraplot/cmaps/Blues7.xml +16 -0
- ultraplot/cmaps/Blues8.xml +17 -0
- ultraplot/cmaps/Blues9.xml +1 -0
- ultraplot/cmaps/Boreal.json +53 -0
- ultraplot/cmaps/Browns1.xml +16 -0
- ultraplot/cmaps/Browns2.xml +26 -0
- ultraplot/cmaps/Browns3.xml +17 -0
- ultraplot/cmaps/Browns4.xml +17 -0
- ultraplot/cmaps/Browns5.xml +26 -0
- ultraplot/cmaps/Browns6.xml +17 -0
- ultraplot/cmaps/Browns7.xml +19 -0
- ultraplot/cmaps/Browns8.xml +11 -0
- ultraplot/cmaps/Browns9.xml +1 -0
- ultraplot/cmaps/ColdHot.rgb +229 -0
- ultraplot/cmaps/Crest.rgb +256 -0
- ultraplot/cmaps/Curl.rgb +512 -0
- ultraplot/cmaps/Deep.rgb +256 -0
- ultraplot/cmaps/Delta.rgb +512 -0
- ultraplot/cmaps/Dense.rgb +256 -0
- ultraplot/cmaps/Div.json +71 -0
- ultraplot/cmaps/DryWet.json +73 -0
- ultraplot/cmaps/Dusk.json +53 -0
- ultraplot/cmaps/Fire.json +53 -0
- ultraplot/cmaps/Flare.rgb +256 -0
- ultraplot/cmaps/Glacial.json +53 -0
- ultraplot/cmaps/Greens1_r.xml +26 -0
- ultraplot/cmaps/Greens2.xml +28 -0
- ultraplot/cmaps/Greens3_r.xml +28 -0
- ultraplot/cmaps/Greens4.xml +17 -0
- ultraplot/cmaps/Greens5.xml +16 -0
- ultraplot/cmaps/Greens6_r.xml +16 -0
- ultraplot/cmaps/Greens7.xml +16 -0
- ultraplot/cmaps/Greens8.xml +26 -0
- ultraplot/cmaps/Haline.rgb +256 -0
- ultraplot/cmaps/Ice.rgb +256 -0
- ultraplot/cmaps/IceFire.rgb +256 -0
- ultraplot/cmaps/Mako.rgb +256 -0
- ultraplot/cmaps/Marine.json +53 -0
- ultraplot/cmaps/Matter.rgb +256 -0
- ultraplot/cmaps/Mono.txt +256 -0
- ultraplot/cmaps/MonoCycle.txt +256 -0
- ultraplot/cmaps/NegPos.json +71 -0
- ultraplot/cmaps/Oranges1.xml +27 -0
- ultraplot/cmaps/Oranges2.xml +26 -0
- ultraplot/cmaps/Oranges3.xml +15 -0
- ultraplot/cmaps/Oranges4.xml +23 -0
- ultraplot/cmaps/Oxy.rgb +256 -0
- ultraplot/cmaps/Phase.rgb +256 -0
- ultraplot/cmaps/Purples1_r.xml +16 -0
- ultraplot/cmaps/Purples2.xml +17 -0
- ultraplot/cmaps/Purples3.xml +18 -0
- ultraplot/cmaps/Reds1.xml +26 -0
- ultraplot/cmaps/Reds2.xml +22 -0
- ultraplot/cmaps/Reds3.xml +23 -0
- ultraplot/cmaps/Reds4.xml +26 -0
- ultraplot/cmaps/Reds5.xml +17 -0
- ultraplot/cmaps/Rocket.rgb +256 -0
- ultraplot/cmaps/Solar.rgb +256 -0
- ultraplot/cmaps/Speed.rgb +256 -0
- ultraplot/cmaps/Stellar.json +53 -0
- ultraplot/cmaps/Sunrise.json +53 -0
- ultraplot/cmaps/Sunset.json +53 -0
- ultraplot/cmaps/Tempo.rgb +256 -0
- ultraplot/cmaps/Thermal.rgb +256 -0
- ultraplot/cmaps/Turbid.rgb +256 -0
- ultraplot/cmaps/Vivid.xml +11 -0
- ultraplot/cmaps/Vlag.rgb +256 -0
- ultraplot/cmaps/Yellows1.xml +17 -0
- ultraplot/cmaps/Yellows2.xml +17 -0
- ultraplot/cmaps/Yellows3.xml +17 -0
- ultraplot/cmaps/Yellows4.xml +17 -0
- ultraplot/cmaps/acton.txt +256 -0
- ultraplot/cmaps/bam.txt +256 -0
- ultraplot/cmaps/bamO.txt +256 -0
- ultraplot/cmaps/bamako.txt +256 -0
- ultraplot/cmaps/batlow.txt +256 -0
- ultraplot/cmaps/batlowK.txt +256 -0
- ultraplot/cmaps/batlowW.txt +256 -0
- ultraplot/cmaps/berlin.txt +256 -0
- ultraplot/cmaps/bilbao.txt +256 -0
- ultraplot/cmaps/broc.txt +256 -0
- ultraplot/cmaps/brocO.txt +256 -0
- ultraplot/cmaps/buda.txt +256 -0
- ultraplot/cmaps/bukavu.txt +256 -0
- ultraplot/cmaps/cork.txt +256 -0
- ultraplot/cmaps/corkO.txt +256 -0
- ultraplot/cmaps/davos.txt +256 -0
- ultraplot/cmaps/devon.txt +256 -0
- ultraplot/cmaps/fes.txt +256 -0
- ultraplot/cmaps/hawaii.txt +256 -0
- ultraplot/cmaps/imola.txt +256 -0
- ultraplot/cmaps/lajolla.txt +256 -0
- ultraplot/cmaps/lapaz.txt +256 -0
- ultraplot/cmaps/lisbon.txt +256 -0
- ultraplot/cmaps/nuuk.txt +256 -0
- ultraplot/cmaps/oleron.txt +256 -0
- ultraplot/cmaps/oslo.txt +256 -0
- ultraplot/cmaps/roma.txt +256 -0
- ultraplot/cmaps/romaO.txt +256 -0
- ultraplot/cmaps/tofino.txt +256 -0
- ultraplot/cmaps/tokyo.txt +256 -0
- ultraplot/cmaps/turku.txt +256 -0
- ultraplot/cmaps/vanimo.txt +256 -0
- ultraplot/cmaps/vik.txt +256 -0
- ultraplot/cmaps/vikO.txt +256 -0
- ultraplot/colors/opencolor.txt +132 -0
- ultraplot/colors/xkcd.txt +951 -0
- ultraplot/colors.py +3241 -0
- ultraplot/colors.py.rej +243 -0
- ultraplot/config.py +1809 -0
- ultraplot/constructor.py +1633 -0
- ultraplot/cycles/538.hex +2 -0
- ultraplot/cycles/FlatUI.hex +1 -0
- ultraplot/cycles/Qual1.rgb +7 -0
- ultraplot/cycles/Qual2.rgb +13 -0
- ultraplot/cycles/bmh.hex +2 -0
- ultraplot/cycles/classic.hex +2 -0
- ultraplot/cycles/colorblind.hex +2 -0
- ultraplot/cycles/colorblind10.hex +2 -0
- ultraplot/cycles/default.hex +2 -0
- ultraplot/cycles/ggplot.hex +1 -0
- ultraplot/cycles/seaborn.hex +2 -0
- ultraplot/cycles/tableau.hex +2 -0
- ultraplot/demos.py +1201 -0
- ultraplot/externals/__init__.py +5 -0
- ultraplot/externals/hsluv.py +330 -0
- ultraplot/figure.py +2102 -0
- ultraplot/fonts/FiraMath-Bold.ttf +0 -0
- ultraplot/fonts/FiraMath-ExtraLight.ttf +0 -0
- ultraplot/fonts/FiraMath-Heavy.ttf +0 -0
- ultraplot/fonts/FiraMath-Light.ttf +0 -0
- ultraplot/fonts/FiraMath-Medium.ttf +0 -0
- ultraplot/fonts/FiraMath-Regular.ttf +0 -0
- ultraplot/fonts/FiraMath-SemiBold.ttf +0 -0
- ultraplot/fonts/FiraMath-UltraLight.ttf +0 -0
- ultraplot/fonts/FiraSans-Black.ttf +0 -0
- ultraplot/fonts/FiraSans-BlackItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-Bold.ttf +0 -0
- ultraplot/fonts/FiraSans-BoldItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-ExtraBold.ttf +0 -0
- ultraplot/fonts/FiraSans-ExtraBoldItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-ExtraLight.ttf +0 -0
- ultraplot/fonts/FiraSans-ExtraLightItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-Italic.ttf +0 -0
- ultraplot/fonts/FiraSans-Light.ttf +0 -0
- ultraplot/fonts/FiraSans-LightItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-Medium.ttf +0 -0
- ultraplot/fonts/FiraSans-MediumItalic.ttf +0 -0
- ultraplot/fonts/FiraSans-Regular.ttf +0 -0
- ultraplot/fonts/FiraSans-SemiBold.ttf +0 -0
- ultraplot/fonts/FiraSans-SemiBoldItalic.ttf +0 -0
- ultraplot/fonts/LICENSE_FIRAMATH.txt +92 -0
- ultraplot/fonts/LICENSE_FIRASANS.txt +97 -0
- ultraplot/fonts/LICENSE_NOTOSANS.txt +202 -0
- ultraplot/fonts/LICENSE_NOTOSERIF.txt +93 -0
- ultraplot/fonts/LICENSE_OPENSANS.txt +202 -0
- ultraplot/fonts/LICENSE_ROBOTO.txt +202 -0
- ultraplot/fonts/LICENSE_SOURCESANS.txt +93 -0
- ultraplot/fonts/LICENSE_SOURCESERIF.txt +93 -0
- ultraplot/fonts/LICENSE_TEXGYRE.txt +29 -0
- ultraplot/fonts/LICENSE_UBUNTU.txt +96 -0
- ultraplot/fonts/NotoSans-Bold.ttf +0 -0
- ultraplot/fonts/NotoSans-BoldItalic.ttf +0 -0
- ultraplot/fonts/NotoSans-Italic.ttf +0 -0
- ultraplot/fonts/NotoSans-Regular.ttf +0 -0
- ultraplot/fonts/NotoSerif-Bold.ttf +0 -0
- ultraplot/fonts/NotoSerif-BoldItalic.ttf +0 -0
- ultraplot/fonts/NotoSerif-Italic.ttf +0 -0
- ultraplot/fonts/NotoSerif-Regular.ttf +0 -0
- ultraplot/fonts/OpenSans-Bold.ttf +0 -0
- ultraplot/fonts/OpenSans-BoldItalic.ttf +0 -0
- ultraplot/fonts/OpenSans-Italic.ttf +0 -0
- ultraplot/fonts/OpenSans-Regular.ttf +0 -0
- ultraplot/fonts/OpenSans-Semibold.ttf +0 -0
- ultraplot/fonts/OpenSans-SemiboldItalic.ttf +0 -0
- ultraplot/fonts/Roboto-Black.ttf +0 -0
- ultraplot/fonts/Roboto-BlackItalic.ttf +0 -0
- ultraplot/fonts/Roboto-Bold.ttf +0 -0
- ultraplot/fonts/Roboto-BoldItalic.ttf +0 -0
- ultraplot/fonts/Roboto-Italic.ttf +0 -0
- ultraplot/fonts/Roboto-Light.ttf +0 -0
- ultraplot/fonts/Roboto-LightItalic.ttf +0 -0
- ultraplot/fonts/Roboto-Medium.ttf +0 -0
- ultraplot/fonts/Roboto-MediumItalic.ttf +0 -0
- ultraplot/fonts/Roboto-Regular.ttf +0 -0
- ultraplot/fonts/SourceSansPro-Black.ttf +0 -0
- ultraplot/fonts/SourceSansPro-BlackItalic.ttf +0 -0
- ultraplot/fonts/SourceSansPro-Bold.ttf +0 -0
- ultraplot/fonts/SourceSansPro-BoldItalic.ttf +0 -0
- ultraplot/fonts/SourceSansPro-ExtraLight.ttf +0 -0
- ultraplot/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
- ultraplot/fonts/SourceSansPro-Italic.ttf +0 -0
- ultraplot/fonts/SourceSansPro-Light.ttf +0 -0
- ultraplot/fonts/SourceSansPro-LightItalic.ttf +0 -0
- ultraplot/fonts/SourceSansPro-Regular.ttf +0 -0
- ultraplot/fonts/SourceSansPro-SemiBold.ttf +0 -0
- ultraplot/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-Black.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-BlackItalic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-Bold.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-BoldItalic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-ExtraLight.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-ExtraLightItalic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-Italic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-Light.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-LightItalic.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-Regular.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-SemiBold.ttf +0 -0
- ultraplot/fonts/SourceSerifPro-SemiBoldItalic.ttf +0 -0
- ultraplot/fonts/Ubuntu-Bold.ttf +0 -0
- ultraplot/fonts/Ubuntu-BoldItalic.ttf +0 -0
- ultraplot/fonts/Ubuntu-Italic.ttf +0 -0
- ultraplot/fonts/Ubuntu-Light.ttf +0 -0
- ultraplot/fonts/Ubuntu-LightItalic.ttf +0 -0
- ultraplot/fonts/Ubuntu-Medium.ttf +0 -0
- ultraplot/fonts/Ubuntu-MediumItalic.ttf +0 -0
- ultraplot/fonts/Ubuntu-Regular.ttf +0 -0
- ultraplot/fonts/texgyreadventor-bold.ttf +0 -0
- ultraplot/fonts/texgyreadventor-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyreadventor-italic.ttf +0 -0
- ultraplot/fonts/texgyreadventor-regular.ttf +0 -0
- ultraplot/fonts/texgyrebonum-bold.ttf +0 -0
- ultraplot/fonts/texgyrebonum-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyrebonum-italic.ttf +0 -0
- ultraplot/fonts/texgyrebonum-regular.ttf +0 -0
- ultraplot/fonts/texgyrechorus-mediumitalic.ttf +0 -0
- ultraplot/fonts/texgyrecursor-bold.ttf +0 -0
- ultraplot/fonts/texgyrecursor-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyrecursor-italic.ttf +0 -0
- ultraplot/fonts/texgyrecursor-regular.ttf +0 -0
- ultraplot/fonts/texgyreheros-bold.ttf +0 -0
- ultraplot/fonts/texgyreheros-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyreheros-italic.ttf +0 -0
- ultraplot/fonts/texgyreheros-regular.ttf +0 -0
- ultraplot/fonts/texgyrepagella-bold.ttf +0 -0
- ultraplot/fonts/texgyrepagella-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyrepagella-italic.ttf +0 -0
- ultraplot/fonts/texgyrepagella-regular.ttf +0 -0
- ultraplot/fonts/texgyreschola-bold.ttf +0 -0
- ultraplot/fonts/texgyreschola-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyreschola-italic.ttf +0 -0
- ultraplot/fonts/texgyreschola-regular.ttf +0 -0
- ultraplot/fonts/texgyretermes-bold.ttf +0 -0
- ultraplot/fonts/texgyretermes-bolditalic.ttf +0 -0
- ultraplot/fonts/texgyretermes-italic.ttf +0 -0
- ultraplot/fonts/texgyretermes-regular.ttf +0 -0
- ultraplot/gridspec.py +1698 -0
- ultraplot/internals/__init__.py +529 -0
- ultraplot/internals/benchmarks.py +26 -0
- ultraplot/internals/context.py +44 -0
- ultraplot/internals/docstring.py +139 -0
- ultraplot/internals/fonts.py +75 -0
- ultraplot/internals/guides.py +167 -0
- ultraplot/internals/inputs.py +862 -0
- ultraplot/internals/labels.py +85 -0
- ultraplot/internals/rcsetup.py +1933 -0
- ultraplot/internals/versions.py +61 -0
- ultraplot/internals/warnings.py +122 -0
- ultraplot/proj.py +325 -0
- ultraplot/scale.py +966 -0
- ultraplot/tests/__init__.py +28 -0
- ultraplot/tests/baseline/test_align_labels.png +0 -0
- ultraplot/tests/baseline/test_aligned_outer_guides.png +0 -0
- ultraplot/tests/baseline/test_aspect_ratios.png +0 -0
- ultraplot/tests/baseline/test_auto_diverging1.png +0 -0
- ultraplot/tests/baseline/test_auto_legend.png +0 -0
- ultraplot/tests/baseline/test_auto_reverse.png +0 -0
- ultraplot/tests/baseline/test_autodiverging3.png +0 -0
- ultraplot/tests/baseline/test_autodiverging4.png +0 -0
- ultraplot/tests/baseline/test_autodiverging5.png +0 -0
- ultraplot/tests/baseline/test_axes_colors.png +0 -0
- ultraplot/tests/baseline/test_bar_vectors.png +0 -0
- ultraplot/tests/baseline/test_bar_width.png +0 -0
- ultraplot/tests/baseline/test_both_ticklabels.png +0 -0
- ultraplot/tests/baseline/test_bounds_ticks.png +0 -0
- ultraplot/tests/baseline/test_boxplot_colors.png +0 -0
- ultraplot/tests/baseline/test_boxplot_vectors.png +0 -0
- ultraplot/tests/baseline/test_cartopy_contours.png +0 -0
- ultraplot/tests/baseline/test_cartopy_labels.png +0 -0
- ultraplot/tests/baseline/test_cartopy_manual.png +0 -0
- ultraplot/tests/baseline/test_centered_legends.png +0 -0
- ultraplot/tests/baseline/test_cmap_cycles.png +0 -0
- ultraplot/tests/baseline/test_colorbar.png +0 -0
- ultraplot/tests/baseline/test_colorbar_ticks.png +0 -0
- ultraplot/tests/baseline/test_colormap_mode.png +0 -0
- ultraplot/tests/baseline/test_column_iteration.png +0 -0
- ultraplot/tests/baseline/test_complex_ticks.png +0 -0
- ultraplot/tests/baseline/test_contour_labels.png +0 -0
- ultraplot/tests/baseline/test_contour_legend_with_label.png +0 -0
- ultraplot/tests/baseline/test_contour_legend_without_label.png +0 -0
- ultraplot/tests/baseline/test_contour_negative.png +0 -0
- ultraplot/tests/baseline/test_contour_single.png +0 -0
- ultraplot/tests/baseline/test_cutoff_ticks.png +0 -0
- ultraplot/tests/baseline/test_data_keyword.png +0 -0
- ultraplot/tests/baseline/test_discrete_ticks.png +0 -0
- ultraplot/tests/baseline/test_discrete_vs_fixed.png +0 -0
- ultraplot/tests/baseline/test_drawing_in_projection_with_globe.png +0 -0
- ultraplot/tests/baseline/test_drawing_in_projection_without_globe.png +0 -0
- ultraplot/tests/baseline/test_edge_fix.png +0 -0
- ultraplot/tests/baseline/test_flow_functions.png +0 -0
- ultraplot/tests/baseline/test_font_adjustments.png +0 -0
- ultraplot/tests/baseline/test_geographic_multiple_projections.png +0 -0
- ultraplot/tests/baseline/test_geographic_single_projection.png +0 -0
- ultraplot/tests/baseline/test_gray_adjustment.png +0 -0
- ultraplot/tests/baseline/test_histogram_legend.png +0 -0
- ultraplot/tests/baseline/test_histogram_types.png +0 -0
- ultraplot/tests/baseline/test_ignore_message.png +0 -0
- ultraplot/tests/baseline/test_inbounds_data.png +0 -0
- ultraplot/tests/baseline/test_init_format.png +0 -0
- ultraplot/tests/baseline/test_inner_title_zorder.png +0 -0
- ultraplot/tests/baseline/test_inset_basic.png +0 -0
- ultraplot/tests/baseline/test_inset_colorbars.png +0 -0
- ultraplot/tests/baseline/test_inset_colors_1.png +0 -0
- ultraplot/tests/baseline/test_inset_colors_2.png +0 -0
- ultraplot/tests/baseline/test_inset_zoom_update.png +0 -0
- ultraplot/tests/baseline/test_invalid_dist.png +0 -0
- ultraplot/tests/baseline/test_invalid_plot.png +0 -0
- ultraplot/tests/baseline/test_keep_guide_labels.png +0 -0
- ultraplot/tests/baseline/test_label_settings.png +0 -0
- ultraplot/tests/baseline/test_level_restriction.png +0 -0
- ultraplot/tests/baseline/test_levels_with_vmin_vmax.png +0 -0
- ultraplot/tests/baseline/test_locale_formatting.png +0 -0
- ultraplot/tests/baseline/test_locale_formatting_en_US.UTF-8.png +0 -0
- ultraplot/tests/baseline/test_manual_labels.png +0 -0
- ultraplot/tests/baseline/test_multi_formatting.png +0 -0
- ultraplot/tests/baseline/test_multiple_calls.png +0 -0
- ultraplot/tests/baseline/test_on_the_fly_mappable.png +0 -0
- ultraplot/tests/baseline/test_outer_align.png +0 -0
- ultraplot/tests/baseline/test_panel_dist.png +0 -0
- ultraplot/tests/baseline/test_panels_suplabels_three_hor_panels.png +0 -0
- ultraplot/tests/baseline/test_panels_with_sharing.png +0 -0
- ultraplot/tests/baseline/test_panels_without_sharing_1.png +0 -0
- ultraplot/tests/baseline/test_panels_without_sharing_2.png +0 -0
- ultraplot/tests/baseline/test_parametric_colors.png +0 -0
- ultraplot/tests/baseline/test_parametric_labels.png +0 -0
- ultraplot/tests/baseline/test_patch_format.png +0 -0
- ultraplot/tests/baseline/test_pie_charts.png +0 -0
- ultraplot/tests/baseline/test_pint_quantities.png +0 -0
- ultraplot/tests/baseline/test_polar_projections.png +0 -0
- ultraplot/tests/baseline/test_projection_dicts.png +0 -0
- ultraplot/tests/baseline/test_qualitative_colormaps_1.png +0 -0
- ultraplot/tests/baseline/test_qualitative_colormaps_2.png +0 -0
- ultraplot/tests/baseline/test_reversed_levels.png +0 -0
- ultraplot/tests/baseline/test_scatter_alpha.png +0 -0
- ultraplot/tests/baseline/test_scatter_args.png +0 -0
- ultraplot/tests/baseline/test_scatter_cycle.png +0 -0
- ultraplot/tests/baseline/test_scatter_inbounds.png +0 -0
- ultraplot/tests/baseline/test_scatter_sizes.png +0 -0
- ultraplot/tests/baseline/test_seaborn_heatmap.png +0 -0
- ultraplot/tests/baseline/test_seaborn_hist.png +0 -0
- ultraplot/tests/baseline/test_seaborn_relational.png +0 -0
- ultraplot/tests/baseline/test_seaborn_swarmplot.png +0 -0
- ultraplot/tests/baseline/test_segmented_norm.png +0 -0
- ultraplot/tests/baseline/test_segmented_norm_ticks.png +0 -0
- ultraplot/tests/baseline/test_share_all_basic.png +0 -0
- ultraplot/tests/baseline/test_singleton_legend.png +0 -0
- ultraplot/tests/baseline/test_span_labels.png +0 -0
- ultraplot/tests/baseline/test_spine_offset.png +0 -0
- ultraplot/tests/baseline/test_spine_side.png +0 -0
- ultraplot/tests/baseline/test_standardized_input.png +0 -0
- ultraplot/tests/baseline/test_statistical_boxplot.png +0 -0
- ultraplot/tests/baseline/test_three_axes.png +0 -0
- ultraplot/tests/baseline/test_tick_direction.png +0 -0
- ultraplot/tests/baseline/test_tick_labels.png +0 -0
- ultraplot/tests/baseline/test_tick_length.png +0 -0
- ultraplot/tests/baseline/test_tick_width.png +0 -0
- ultraplot/tests/baseline/test_title_deflection.png +0 -0
- ultraplot/tests/baseline/test_triangular_functions.png +0 -0
- ultraplot/tests/baseline/test_tuple_handles.png +0 -0
- ultraplot/tests/baseline/test_twin_axes_1.png +0 -0
- ultraplot/tests/baseline/test_twin_axes_2.png +0 -0
- ultraplot/tests/baseline/test_twin_axes_3.png +0 -0
- ultraplot/tests/baseline/test_uneven_levels.png +0 -0
- ultraplot/tests/test_1dplots.py +373 -0
- ultraplot/tests/test_2dplots.py +354 -0
- ultraplot/tests/test_axes.py +179 -0
- ultraplot/tests/test_colorbar.py +253 -0
- ultraplot/tests/test_docs.py +78 -0
- ultraplot/tests/test_format.py +340 -0
- ultraplot/tests/test_geographic.py +116 -0
- ultraplot/tests/test_imshow.py +110 -0
- ultraplot/tests/test_inset.py +28 -0
- ultraplot/tests/test_integration.py +149 -0
- ultraplot/tests/test_legend.py +181 -0
- ultraplot/tests/test_projections.py +138 -0
- ultraplot/tests/test_statistical_plotting.py +77 -0
- ultraplot/tests/test_subplots.py +174 -0
- ultraplot/ticker.py +879 -0
- ultraplot/ui.py +233 -0
- ultraplot/utils.py +912 -0
- ultraplot-0.99.3.dist-info/LICENSE.txt +427 -0
- ultraplot-0.99.3.dist-info/METADATA +88 -0
- ultraplot-0.99.3.dist-info/RECORD +416 -0
- ultraplot-0.99.3.dist-info/WHEEL +5 -0
- ultraplot-0.99.3.dist-info/entry_points.txt +2 -0
- 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
|
+
)
|