From dd790003ea674a41e14313bc3fe46b734027ab4c Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Tue, 11 Aug 2026 23:25:45 +1000 Subject: [PATCH 1/6] docs: rework Why UltraPlot page with before/after comparison cards --- .gitignore | 1 + docs/_static/custom.css | 55 + docs/_static/why_plots/aesthetics_mpl.svg | 15587 +++++++++++++++ docs/_static/why_plots/aesthetics_uplt.svg | 16408 ++++++++++++++++ docs/_static/why_plots/colorbars_mpl.svg | 5878 ++++++ docs/_static/why_plots/colorbars_uplt.svg | 6899 +++++++ docs/_static/why_plots/geo_mpl.svg | 2597 +++ docs/_static/why_plots/geo_uplt.svg | 18809 +++++++++++++++++++ docs/_static/why_plots/metadata_mpl.svg | 593 + docs/_static/why_plots/metadata_uplt.svg | 1421 ++ docs/_static/why_plots/plotting_mpl.svg | 846 + docs/_static/why_plots/plotting_uplt.svg | 1460 ++ docs/_static/why_plots/spacing_mpl.svg | 1170 ++ docs/_static/why_plots/spacing_uplt.svg | 2714 +++ docs/_static/why_plots/subplots_mpl.svg | 1413 ++ docs/_static/why_plots/subplots_uplt.svg | 2773 +++ docs/why.rst | 960 +- 17 files changed, 78965 insertions(+), 619 deletions(-) create mode 100644 docs/_static/why_plots/aesthetics_mpl.svg create mode 100644 docs/_static/why_plots/aesthetics_uplt.svg create mode 100644 docs/_static/why_plots/colorbars_mpl.svg create mode 100644 docs/_static/why_plots/colorbars_uplt.svg create mode 100644 docs/_static/why_plots/geo_mpl.svg create mode 100644 docs/_static/why_plots/geo_uplt.svg create mode 100644 docs/_static/why_plots/metadata_mpl.svg create mode 100644 docs/_static/why_plots/metadata_uplt.svg create mode 100644 docs/_static/why_plots/plotting_mpl.svg create mode 100644 docs/_static/why_plots/plotting_uplt.svg create mode 100644 docs/_static/why_plots/spacing_mpl.svg create mode 100644 docs/_static/why_plots/spacing_uplt.svg create mode 100644 docs/_static/why_plots/subplots_mpl.svg create mode 100644 docs/_static/why_plots/subplots_uplt.svg diff --git a/.gitignore b/.gitignore index f39747738..fc0755a70 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ docs/_build docs/_static/ultraplotrc docs/_static/rctable.rst docs/_static/* +!docs/_static/why_plots/ *.html docs/gallery/ docs/sg_execution_times.rst diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 4a5390e73..93d6953f8 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1250,3 +1250,58 @@ body.wy-body-for-nav max-width: 100%; height: auto; } + +/* Why UltraPlot page: before/after comparison cards */ +.uplt-why { + border: 1px solid var(--uplt-color-border-muted); + border-radius: 0.8rem; + background: linear-gradient( + 180deg, + var(--uplt-color-white) 0%, + var(--uplt-color-sidebar-bg) 100% + ); + box-shadow: 0 4px 14px var(--uplt-color-shadow); + overflow: hidden; +} + +.uplt-why-mpl { + border-top: 4px solid #b45309; +} + +.uplt-why-uplt { + border-top: 4px solid #178f84; +} + +.uplt-why img { + width: 100%; + height: auto; + border-radius: 0.45rem; + background: var(--uplt-color-panel-bg); +} + +.uplt-why .sd-card-body > p:first-child { + font-weight: 700; + font-size: 0.9rem; + letter-spacing: 0.06em; + text-transform: uppercase; +} + +.uplt-why-mpl .sd-card-body > p:first-child strong { + color: #b45309; +} + +.uplt-why-uplt .sd-card-body > p:first-child strong { + color: #178f84; +} + +.uplt-why .sd-card-body > p:last-child { + margin-top: auto; + padding-top: 0.35rem; + color: var(--uplt-color-text-secondary); +} + +html.dark .uplt-why, +html.dark-theme .uplt-why, +[data-color-mode="dark"] .uplt-why { + background: linear-gradient(180deg, #252525 0%, #1f1f1f 100%); +} diff --git a/docs/_static/why_plots/aesthetics_mpl.svg b/docs/_static/why_plots/aesthetics_mpl.svg new file mode 100644 index 000000000..f3f29661f --- /dev/null +++ b/docs/_static/why_plots/aesthetics_mpl.svg @@ -0,0 +1,15587 @@ + + + + + + + + 2026-08-11T12:57:55.103333 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/aesthetics_uplt.svg b/docs/_static/why_plots/aesthetics_uplt.svg new file mode 100644 index 000000000..c4370cff1 --- /dev/null +++ b/docs/_static/why_plots/aesthetics_uplt.svg @@ -0,0 +1,16408 @@ + + + + + + + + 2026-08-11T12:57:55.774591 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/colorbars_mpl.svg b/docs/_static/why_plots/colorbars_mpl.svg new file mode 100644 index 000000000..5ed02b27c --- /dev/null +++ b/docs/_static/why_plots/colorbars_mpl.svg @@ -0,0 +1,5878 @@ + + + + + + + + 2026-08-11T12:57:49.889271 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/colorbars_uplt.svg b/docs/_static/why_plots/colorbars_uplt.svg new file mode 100644 index 000000000..163ac1496 --- /dev/null +++ b/docs/_static/why_plots/colorbars_uplt.svg @@ -0,0 +1,6899 @@ + + + + + + + + 2026-08-11T12:57:50.883487 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/geo_mpl.svg b/docs/_static/why_plots/geo_mpl.svg new file mode 100644 index 000000000..2413d9339 --- /dev/null +++ b/docs/_static/why_plots/geo_mpl.svg @@ -0,0 +1,2597 @@ + + + + + + + + 2026-08-11T16:11:55.118936 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/geo_uplt.svg b/docs/_static/why_plots/geo_uplt.svg new file mode 100644 index 000000000..12b0a48d4 --- /dev/null +++ b/docs/_static/why_plots/geo_uplt.svg @@ -0,0 +1,18809 @@ + + + + + + + + 2026-08-11T16:11:56.507282 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/metadata_mpl.svg b/docs/_static/why_plots/metadata_mpl.svg new file mode 100644 index 000000000..99619a50f --- /dev/null +++ b/docs/_static/why_plots/metadata_mpl.svg @@ -0,0 +1,593 @@ + + + + + + + + 2026-08-11T12:57:54.683456 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/metadata_uplt.svg b/docs/_static/why_plots/metadata_uplt.svg new file mode 100644 index 000000000..67582f23f --- /dev/null +++ b/docs/_static/why_plots/metadata_uplt.svg @@ -0,0 +1,1421 @@ + + + + + + + + 2026-08-11T12:57:54.932854 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/plotting_mpl.svg b/docs/_static/why_plots/plotting_mpl.svg new file mode 100644 index 000000000..88f5136eb --- /dev/null +++ b/docs/_static/why_plots/plotting_mpl.svg @@ -0,0 +1,846 @@ + + + + + + + + 2026-08-11T12:57:51.205093 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/plotting_uplt.svg b/docs/_static/why_plots/plotting_uplt.svg new file mode 100644 index 000000000..b214ea2ee --- /dev/null +++ b/docs/_static/why_plots/plotting_uplt.svg @@ -0,0 +1,1460 @@ + + + + + + + + 2026-08-11T12:57:51.520802 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/spacing_mpl.svg b/docs/_static/why_plots/spacing_mpl.svg new file mode 100644 index 000000000..44a58c51c --- /dev/null +++ b/docs/_static/why_plots/spacing_mpl.svg @@ -0,0 +1,1170 @@ + + + + + + + + 2026-08-11T16:11:53.624180 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/spacing_uplt.svg b/docs/_static/why_plots/spacing_uplt.svg new file mode 100644 index 000000000..c50801108 --- /dev/null +++ b/docs/_static/why_plots/spacing_uplt.svg @@ -0,0 +1,2714 @@ + + + + + + + + 2026-08-11T16:11:54.382542 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/subplots_mpl.svg b/docs/_static/why_plots/subplots_mpl.svg new file mode 100644 index 000000000..8657ec227 --- /dev/null +++ b/docs/_static/why_plots/subplots_mpl.svg @@ -0,0 +1,1413 @@ + + + + + + + + 2026-08-11T16:11:54.619627 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/_static/why_plots/subplots_uplt.svg b/docs/_static/why_plots/subplots_uplt.svg new file mode 100644 index 000000000..4f211d40f --- /dev/null +++ b/docs/_static/why_plots/subplots_uplt.svg @@ -0,0 +1,2773 @@ + + + + + + + + 2026-08-11T12:57:49.491847 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/why.rst b/docs/why.rst index 74fc644c4..d7cb6b52e 100644 --- a/docs/why.rst +++ b/docs/why.rst @@ -30,28 +30,21 @@ .. _why: -============ +=============== Why UltraPlot? -============ - -Matplotlib is an extremely versatile plotting package used by -scientists and engineers far and wide. However, -matplotlib can be cumbersome or repetitive for users who... - -* Make highly complex figures with many subplots. -* Want to finely tune their annotations and aesthetics. -* Need to make new figures nearly every day. - -UltraPlot's core mission is to provide a smoother plotting experience for -matplotlib's most demanding users. We accomplish this by *expanding upon* -matplotlib's :ref:`object-oriented interface `. UltraPlot -makes changes that would be hard to justify or difficult to incorporate -into matplotlib itself, owing to differing design choices and backwards -compatibility considerations. - -This page enumerates these changes and explains how they address the -limitations of matplotlib's default interface. To start using these -features, see the :ref:`usage introduction ` +=============== + +Matplotlib is an extremely versatile plotting package, but it is cumbersome +and repetitive for users who make complex figures with many subplots, finely +tune their annotations, or need new figures nearly every day. UltraPlot's core +mission is to smooth out the plotting experience for matplotlib's most demanding +users. It does this by *expanding upon* matplotlib's :ref:`object-oriented +interface ` with changes that would be hard to justify inside +matplotlib itself. + +The sections below pair the "before" -- a plain matplotlib result -- with the +"after" -- the same plot made with UltraPlot -- so you can see the difference at +a glance. For the full user guide, see the :ref:`usage introduction ` and the :ref:`user guide `. .. _why_less_typing: @@ -59,40 +52,17 @@ and the :ref:`user guide `. Less typing, more plotting ========================== -Limitation ----------- - -Matplotlib users often need to change lots of plot settings all at once. With -the default interface, this requires calling a series of one-liner setter methods. - -This workflow is quite verbose -- it tends to require "boilerplate code" that -gets copied and pasted a hundred times. It can also be confusing -- it is -often unclear whether properties are applied from an :class:`~matplotlib.axes.Axes` -setter (e.g. :func:`~matplotlib.axes.Axes.set_xlabel` and -:func:`~matplotlib.axes.Axes.set_xticks`), an :class:`~matplotlib.axis.XAxis` or -:class:`~matplotlib.axis.YAxis` setter (e.g. -:func:`~matplotlib.axis.Axis.set_major_locator` and -:func:`~matplotlib.axis.Axis.set_major_formatter`), a :class:`~matplotlib.spines.Spine` -setter (e.g. :func:`~matplotlib.spines.Spine.set_bounds`), or a "bulk" property -setter (e.g. :func:`~matplotlib.axes.Axes.tick_params`), or whether one must dig -into the figure architecture and apply settings to several different objects. -It seems like there should be a more unified, straightforward way to change -settings without sacrificing the advantages of object-oriented design. - -Changes -------- - -UltraPlot includes the :func:`~ultraplot.axes.Axes.format` command to resolve this. -Think of this as an expanded and thoroughly documented version of the -:func:`~matplotlib.artist.Artist.update` command. :func:`~ultraplot.axes.Axes.format` can modify things -like axis labels and titles and apply new :ref:`"rc" settings ` to existing -axes. It also integrates with various :ref:`constructor functions ` -to help keep things succinct. Further, the :func:`~ultraplot.figure.Figure.format` -and :func:`~ultraplot.gridspec.SubplotGrid.format` commands can be used to -:func:`~ultraplot.axes.Axes.format` several subplots at once. - -Together, these features significantly reduce the amount of code needed to create -highly customized figures. As an example, it is trivial to see that... +In matplotlib, changing many plot settings at once means calling a series of +one-liner setter methods -- and it is often unclear whether a property lives on +the :class:`~matplotlib.axes.Axes`, the :class:`~matplotlib.axis.XAxis`, +a :class:`~matplotlib.spines.Spine`, or :func:`~matplotlib.axes.Axes.tick_params`. +UltraPlot replaces all of this with the :func:`~ultraplot.axes.Axes.format` +command: an expanded, thoroughly documented version of +:func:`~matplotlib.artist.Artist.update` that can also apply :ref:`rc settings +` and integrate with the :ref:`constructor functions `. +The figure-level :func:`~ultraplot.figure.Figure.format` and +:func:`~ultraplot.gridspec.SubplotGrid.format` commands format several subplots +at once. .. code-block:: python @@ -134,52 +104,30 @@ Links Class constructor functions =========================== -Limitation ----------- - -Matplotlib and `cartopy`_ define several classes with verbose names like -:class:`~matplotlib.ticker.MultipleLocator`, :class:`~matplotlib.ticker.FormatStrFormatter`, -and :class:`~cartopy.crs.LambertAzimuthalEqualArea`. They also keep them out of the -top-level package namespace. Since plotting code has a half life of about 30 seconds, -typing out these extra class names and import statements can be frustrating. - -Parts of matplotlib's interface were designed with this in mind. -`Backend classes `__, -`native axes projections `__, -`axis scales `__, -`colormaps `__, -`box styles `__, -`arrow styles `__, -and `arc styles `__ -are referenced with "registered" string names, -as are `basemap projections `__. -So, why not "register" everything else? - -Changes -------- - -In UltraPlot, tick locators, tick formatters, axis scales, property cycles, colormaps, -normalizers, and `cartopy`_ projections are all "registered". This is accomplished -by defining "constructor functions" and passing various keyword arguments through -these functions. - -The constructor functions also accept intuitive inputs alongside "registered" -names. For example, a scalar passed to :class:`~ultraplot.constructor.Locator` -returns a :class:`~matplotlib.ticker.MultipleLocator`, a -lists of strings passed to :class:`~ultraplot.constructor.Formatter` returns a -:class:`~matplotlib.ticker.FixedFormatter`, and :class:`~ultraplot.constructor.Cycle` -and :class:`~ultraplot.constructor.Colormap` accept colormap names, individual colors, and -lists of colors. Passing the relevant class instance to a constructor function -simply returns it, and all the registered classes are available in the top-level -namespace -- so class instances can be directly created with e.g. -``uplt.MultipleLocator(...)`` or ``uplt.LogNorm(...)`` rather than -relying on constructor functions. - -The below table lists the constructor functions and the keyword arguments that use them. - -================================ ============================================================ ============================================================================== ================================================================================================================================================================================================ +Matplotlib and `cartopy`_ define verbose class names like +:class:`~matplotlib.ticker.MultipleLocator` and +:class:`~cartopy.crs.LambertAzimuthalEqualArea`, and keep them out of the +top-level namespace. UltraPlot instead "registers" tick locators, tick +formatters, axis scales, property cycles, colormaps, normalizers, and cartopy +projections, so you can refer to them with constructor functions and short +names: + +* A scalar passed to :class:`~ultraplot.constructor.Locator` returns a + :class:`~matplotlib.ticker.MultipleLocator`; a list of strings passed to + :class:`~ultraplot.constructor.Formatter` returns a + :class:`~matplotlib.ticker.FixedFormatter`. +* :class:`~ultraplot.constructor.Colormap` and + :class:`~ultraplot.constructor.Cycle` accept registered names, individual + colors, and lists of colors. +* Every registered class is also available directly in the top-level namespace, + e.g. ``uplt.MultipleLocator(...)`` or ``uplt.LogNorm(...)``. + +The table below lists the constructor functions and the keyword arguments +that use them. + +=============================== ============================================================ ============================================================================== ================================================================================================================================================================================================ Function Return type Used by Keyword argument(s) -================================ ============================================================ ============================================================================== ================================================================================================================================================================================================ +=============================== ============================================================ ============================================================================== ================================================================================================================================================================================================ :class:`~ultraplot.constructor.Proj` :class:`~cartopy.crs.Projection` or :class:`~mpl_toolkits.basemap.Basemap` :func:`~ultraplot.figure.Figure.add_subplot` and :func:`~ultraplot.figure.Figure.add_subplots` ``proj=`` :class:`~ultraplot.constructor.Locator` :class:`~matplotlib.ticker.Locator` :func:`~ultraplot.axes.Axes.format` and :func:`~ultraplot.axes.Axes.colorbar` ``locator=``, ``xlocator=``, ``ylocator=``, ``minorlocator=``, ``xminorlocator=``, ``yminorlocator=``, ``ticks=``, ``xticks=``, ``yticks=``, ``minorticks=``, ``xminorticks=``, ``yminorticks=`` :class:`~ultraplot.constructor.Formatter` :class:`~matplotlib.ticker.Formatter` :func:`~ultraplot.axes.Axes.format` and :func:`~ultraplot.axes.Axes.colorbar` ``formatter=``, ``xformatter=``, ``yformatter=``, ``ticklabels=``, ``xticklabels=``, ``yticklabels=`` @@ -187,7 +135,7 @@ Function Return type :class:`~ultraplot.constructor.Colormap` :class:`~matplotlib.colors.Colormap` 2D :class:`~ultraplot.axes.PlotAxes` commands ``cmap=`` :class:`~ultraplot.constructor.Norm` :class:`~matplotlib.colors.Normalize` 2D :class:`~ultraplot.axes.PlotAxes` commands ``norm=`` :class:`~ultraplot.constructor.Cycle` :class:`~cycler.Cycler` 1D :class:`~ultraplot.axes.PlotAxes` commands ``cycle=`` -================================ ============================================================ ============================================================================== ================================================================================================================================================================================================ +=============================== ============================================================ ============================================================================== ================================================================================================================================================================================================ Links ----- @@ -214,79 +162,37 @@ Links Automatic dimensions and spacing ================================ -Limitation ----------- - -Matplotlib plots tend to require "tweaking" when you have more than one -subplot in the figure. This is partly because you must specify the physical -dimensions of the figure, despite the fact that... - -#. The subplot aspect ratio is generally more relevant than the figure - aspect ratio. A default aspect ratio of ``1`` is desirable for most plots, and - the aspect ratio must be held fixed for :ref:`geographic and polar ` - projections and most :func:`~matplotlib.axes.Axes.imshow` plots. -#. The subplot width and height control the "apparent" size of lines, markers, - text, and other plotted content. If the figure size is fixed, adding more - subplots will decrease the average subplot size and increase the "apparent" - sizes. If the subplot size is fixed instead, this can be avoided. - -Matplotlib also includes `"tight layout" -`__ -and `"constrained layout" -`__ -algorithms that can help users avoid having to tweak -:class:`~matplotlib.gridspec.GridSpec` spacing parameters like `left`, `bottom`, and `wspace`. -However, these algorithms are disabled by default and somewhat `cumbersome to configure -`__. -They also cannot apply different amounts of spacing between different subplot row and -column boundaries. - -Changes -------- - -By default, UltraPlot fixes the physical dimensions of a *reference subplot* rather -than the figure. The reference subplot dimensions are controlled with the `refwidth`, -`refheight`, and `refaspect` :class:`~ultraplot.figure.Figure` keywords, with a default -behavior of ``refaspect=1`` and ``refwidth=2.5`` (inches). If the `data aspect ratio -`__ -of the reference subplot is fixed (as with :ref:`geographic `, -:ref:`polar `, :func:`~matplotlib.axes.Axes.imshow`, and -:func:`~ultraplot.axes.Axes.heatmap` plots) then this is used instead of `refaspect`. - -Alternatively, you can independently specify the width or height of the *figure* -with the `figwidth` and `figheight` parameters. If only one is specified, the -other is adjusted to preserve subplot aspect ratios. This is very often useful -when preparing figures for submission to a publication. To request figure -dimensions suitable for submission to a :ref:`specific publication `, -use the `journal` keyword. - -By default, UltraPlot also uses :ref:`its own tight layout algorithm ` -- -preventing text labels from overlapping with subplots. This algorithm works with the -:class:`~ultraplot.gridspec.GridSpec` subclass rather than :class:`~matplotlib.gridspec.GridSpec`, which -provides the following advantages: - -* The :class:`~ultraplot.gridspec.GridSpec` subclass interprets spacing parameters - with font size-relative units rather than figure size-relative units. - This is more consistent with the tight layout `pad` arguments - (which, like matplotlib, are specified in font size-relative units) - and obviates the need to adjust spaces when the figure size or font size changes. -* The :class:`~ultraplot.gridspec.GridSpec` subclass permits variable spacing - between rows and columns, and the tight layout algorithm takes - this into account. Variable spacing is critical for making - outer :ref:`colorbars and legends ` and - :ref:`axes panels ` without "stealing space" - from the parent subplot -- these objects usually need to be - spaced closer to their parents than other subplots. -* You can :ref:`override ` particular spacing parameters - and leave the tight layout algorithm to adjust the - unspecified spacing parameters. For example, passing ``right=1`` to - :func:`~ultraplot.figure.Figure.add_subplots` fixes the right margin - at 1 font size-width while the others are adjusted automatically. -* Only one :class:`~ultraplot.gridspec.GridSpec` is permitted per figure, - considerably simplifying the tight layout algorithm calculations. - This restriction is enforced by requiring successive - :func:`~ultraplot.figure.Figure.add_subplot` calls to imply the same geometry and - include only subplot specs generated from the same :class:`~ultraplot.gridspec.GridSpec`. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/spacing_mpl.svg + :alt: A 2x2 matplotlib figure where the bottom-row titles overlap the top-row tick labels + :width: 100% + + The figure size is fixed, the margins are tuned by hand, and the bottom-row + titles collide with the tick labels above them. Add a subplot or change the + font size and the whole thing needs retuning. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/spacing_uplt.svg + :alt: The same 2x2 layout made with UltraPlot with clean, automatic spacing + :width: 100% + + UltraPlot fixes the physical dimensions of a *reference subplot* (``refwidth``, + ``refheight``, ``refaspect``) instead of the figure, so subplot size -- and the + apparent size of text -- stays constant no matter how many subplots you add. + Its own tight layout algorithm then handles the spacing. Links ----- @@ -299,48 +205,36 @@ Links Working with multiple subplots ============================== -Limitation ----------- - -When working with multiple subplots in matplotlib, the path of least resistance -often leads to *redundant* figure elements. Namely... - -* Repeated axis tick labels. -* Repeated axis labels. -* Repeated colorbars. -* Repeated legends. - -These sorts of redundancies are very common even in publications, where they waste -valuable page space. It is also generally necessary to add "a-b-c" labels to -figures with multiple subplots before submitting them to publications, but -matplotlib has no built-in way of doing this. - -Changes -------- - -UltraPlot makes it easier to work with multiple subplots and create clear, -concise figures. - -* Axis tick labels and axis labels are automatically - :ref:`shared and aligned ` between subplot in the same - :class:`~ultraplot.gridspec.GridSpec` row or column. This is controlled by the `sharex`, - `sharey`, `spanx`, `spany`, `alignx`, and `aligny` figure keywords. -* The figure :func:`~ultraplot.figure.Figure.colorbar` and :meth:`~ultraplot.figure.Figure.legend`` - commands can easily draw colorbars and legends intended to reference more than - one subplot in arbitrary contiguous rows and columns. See the - :ref:`next section ` for details. -* A-b-c labels can be added to subplots simply using the :rcraw:`abc` - setting -- for example, ``uplt.rc['abc'] = 'A.'`` or ``axs.format(abc='A.')``. - This is possible because :func:`~ultraplot.figure.Figure.add_subplot` assigns a unique - :func:`~ultraplot.axes.Axes.number` to every new subplot. -* The :func:`~ultraplot.gridspec.SubplotGrid.format` command can easily format multiple subplots - at once or add colorbars, legends, panels, twin axes, or inset axes to multiple - subplots at once. A :class:`~ultraplot.gridspec.SubplotGrid` is returned by - :func:`~ultraplot.figure.Figure.subplots`, and can be indexed like a list or a 2D array. -* The :func:`~ultraplot.axes.Axes.panel_axes` (shorthand :func:`~ultraplot.axes.Axes.panel`) commands - draw :ref:`thin panels ` along the edges of subplots. This can be useful - for plotting 1D summary statistics alongside 2D plots. You can also add twin axes and - panel axes to several subplots at once using :class:`~ultraplot.gridspec.SubplotGrid` commands. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/subplots_mpl.svg + :alt: A 2x2 matplotlib figure with repeated tick labels on every subplot and no subplot labels + :width: 100% + + Every subplot repeats its own tick labels and axis labels, wasting page + space. Adding "a-b-c" labels -- required for most publications -- is + entirely manual. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/subplots_uplt.svg + :alt: The same 2x2 layout made with UltraPlot with shared tick labels and a-b-c labels + :width: 100% + + Tick labels and axis labels are shared and aligned automatically (``sharex``, + ``sharey``, ``spanx``, ``spany``), and a-b-c labels are added with a single + :rcraw:`abc` setting, e.g. ``axs.format(abc='A.')``. Links ----- @@ -356,45 +250,37 @@ Links Simpler colorbars and legends ============================= -Limitation ----------- - -In matplotlib, it can be difficult to draw :func:`~matplotlib.figure.Figure.legend`\ s -along the outside of subplots. Generally, you need to position the legend -manually and tweak the spacing to make room for the legend. - -Also, :func:`~matplotlib.figure.Figure.colorbar`\ s drawn along the outside of subplots -with e.g. ``fig.colorbar(..., ax=ax)`` need to "steal" space from the parent subplot. -This can cause asymmetry in figures with more than one subplot. It is also generally -difficult to draw "inset" colorbars in matplotlib and to generate outer colorbars -with consistent widths (i.e., not too "skinny" or "fat"). - -Changes -------- - -UltraPlot includes a simple framework for drawing colorbars and legends -that reference :ref:`individual subplots ` and -:ref:`multiple contiguous subplots `. - -* To draw a colorbar or legend on the outside of a specific subplot, pass an - "outer" location (e.g. ``loc='l'`` or ``loc='left'``) - to :func:`~ultraplot.axes.Axes.colorbar` or :meth:`~ultraplot.axes.Axes.legend`. -* To draw a colorbar or legend on the inside of a specific subplot, pass an - "inner" location (e.g. ``loc='ur'`` or ``loc='upper right'``) - to :func:`~ultraplot.axes.Axes.colorbar` or :meth:`~ultraplot.axes.Axes.legend`. -* To draw a colorbar or legend along the edge of the figure, use - :func:`~ultraplot.figure.Figure.colorbar` and :class:`~ultraplot.figure.Figure.legend`. - The `col`, `row`, and `span` keywords control which - :class:`~ultraplot.gridspec.GridSpec` rows and columns are spanned - by the colorbar or legend. - -Since :class:`~ultraplot.gridspec.GridSpec` permits variable spacing between subplot -rows and columns, "outer" colorbars and legends do not alter subplot -spacing or add whitespace. This is critical e.g. if you have a -colorbar between columns 1 and 2 but nothing between columns 2 and 3. -Also, :class:`~ultraplot.figure.Figure` and :class:`~ultraplot.axes.Axes` colorbar widths are -now specified in *physical* units rather than relative units, which makes -colorbar thickness independent of subplot size and easier to get just right. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/colorbars_mpl.svg + :alt: Two matplotlib panels where the colorbar steals space from its parent subplot, making the panels unequal widths + :width: 100% + + Drawing a colorbar with ``fig.colorbar(m, ax=ax)`` *steals space* from the + parent subplot -- here the left panel is visibly narrower than the right + one. Outer legends have to be positioned by hand and tweaked to fit. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/colorbars_uplt.svg + :alt: The same two panels with outer colorbars drawn in dedicated space, keeping the panels equal width + :width: 100% + + Colorbars and legends get their own space in the + :class:`~ultraplot.gridspec.GridSpec` -- the subplots keep their exact + dimensions. Outer (``loc='l'``) and inset (``loc='ur'``) locations work for + both, and colorbar widths are specified in physical units. Links ----- @@ -413,111 +299,39 @@ Links Improved plotting commands ========================== -Limitation ----------- - -A few common plotting tasks take a lot of work using matplotlib alone. The `seaborn`_, -`xarray`_, and `pandas`_ packages offer improvements, but it would be nice to -have this functionality built right into matplotlib's interface. - -Changes -------- - -UltraPlot uses the :class:`~ultraplot.axes.PlotAxes` subclass to add various `seaborn`_, -`xarray`_, and `pandas`_ features to existing matplotlib plotting commands -along with several additional features designed to make things easier. - -The following features are relevant for "1D" :class:`~ultraplot.axes.PlotAxes` commands -like :func:`~ultraplot.axes.PlotAxes.line` (equivalent to :func:`~ultraplot.axes.PlotAxes.plot`) -and :func:`~ultraplot.axes.PlotAxes.scatter`: - -* The treatment of data arguments passed to the 1D :class:`~ultraplot.axes.PlotAxes` - commands is :ref:`standardized `. This makes them more flexible - and arguably more intuitive to use than their matplotlib counterparts. -* The `cycle` keyword is interpreted by the :class:`~ultraplot.constructor.Cycle` - :ref:`constructor function ` and applies - :ref:`property cyclers ` on-the-fly. This permits succinct - and flexible property cycler declaration. -* The `legend` and `colorbar` keywords draw :ref:`on-the-fly legends and colorbars - ` using the result of the :class:`~ultraplot.axes.PlotAxes` command. - Note that colorbars can be drawn from :ref:`lists of artists `. -* The default `ylim` (`xlim`) in the presence of a fixed `xlim` (`ylim`) is now - adjusted to exclude out-of-bounds data. This can be useful when "zooming in" on - a dependent variable axis but can be disabled by setting :rcraw:`axes.inbounds` - to ``False`` or passing ``inbounds=False`` to :class:`~ultraplot.axes.PlotAxes` commands. -* The :func:`~ultraplot.axes.PlotAxes.bar` and :func:`~ultraplot.axes.PlotAxes.barh` commands accept 2D - arrays and can :ref:`stack or group ` successive columns. Likewise, the - :func:`~ultraplot.axes.PlotAxes.area` and :func:`~ultraplot.axes.PlotAxes.areax` commands (shorthands - for :func:`~ultraplot.axes.PlotAxes.fill_between` and :func:`~ultraplot.axes.PlotAxes.fill_betweenx`) - accept 2D arrays and can :ref:`stack or overlay ` successive columns. -* The :func:`~ultraplot.axes.PlotAxes.bar`, :func:`~ultraplot.axes.PlotAxes.barh`, - :func:`~ultraplot.axes.PlotAxes.vlines`, :func:`~ultraplot.axes.PlotAxes.hlines`, - :func:`~ultraplot.axes.PlotAxes.area`, and :func:`~ultraplot.axes.PlotAxes.areax` - commands accept a `negpos` keyword argument that :ref:`assigns different - colors ` to "negative" and "positive" regions. -* The :func:`~ultraplot.axes.PlotAxes.linex` and :func:`~ultraplot.axes.PlotAxes.scatterx` commands - are just like :func:`~ultraplot.axes.PlotAxes.line` and :func:`~ultraplot.axes.PlotAxes.scatter`, - but positional arguments are interpreted as *x* coordinates or (*y*, *x*) pairs. - There are also the related commands :func:`~ultraplot.axes.PlotAxes.stemx`, - :func:`~ultraplot.axes.PlotAxes.stepx`, :func:`~ultraplot.axes.PlotAxes.boxh` (shorthand for - :func:`~ultraplot.axes.PlotAxes.boxploth`), and :func:`~ultraplot.axes.PlotAxes.violinh` (shorthand - for :func:`~ultraplot.axes.PlotAxes.violinploth`). -* The :func:`~ultraplot.axes.PlotAxes.line`, :func:`~ultraplot.axes.PlotAxes.linex`, - :func:`~ultraplot.axes.PlotAxes.scatter`, :func:`~ultraplot.axes.PlotAxes.scatterx`, - :func:`~ultraplot.axes.PlotAxes.bar`, and :func:`~ultraplot.axes.PlotAxes.barh` commands can - draw vertical or horizontal :ref:`error bars or "shading" ` using a - variety of keyword arguments. This is often more convenient than working directly - with :func:`~matplotlib.axes.Axes.errorbar` or :func:`~matplotlib.axes.Axes.fill_between`. -* The :func:`~ultraplot.axes.PlotAxes.parametric` command draws clean-looking - :ref:`parametric lines ` by encoding the parametric - coordinate using colormap colors rather than text annotations. - -The following features are relevant for "2D" :class:`~ultraplot.axes.PlotAxes` commands -like :func:`~ultraplot.axes.PlotAxes.pcolor` and :func:`~ultraplot.axes.PlotAxes.contour`: - -* The treatment of data arguments passed to the 2D :class:`~ultraplot.axes.PlotAxes` - commands is :ref:`standardized `. This makes them more flexible - and arguably more intuitive to use than their matplotlib counterparts. -* The `cmap` and `norm` :ref:`keyword arguments ` are interpreted - by the :class:`~ultraplot.constructor.Colormap` and :class:`~ultraplot.constructor.Norm` - :ref:`constructor functions `. This permits succinct - and flexible colormap and normalizer application. -* The `colorbar` keyword draws :ref:`on-the-fly colorbars ` using the - result of the plotting command. Note that :ref:`"inset" colorbars ` can - also be drawn, analogous to "inset" legends. -* The :func:`~ultraplot.axes.PlotAxes.contour`, :func:`~ultraplot.axes.PlotAxes.contourf`, - :func:`~ultraplot.axes.PlotAxes.pcolormesh`, and :func:`~ultraplot.axes.PlotAxes.pcolor` commands - all accept a `labels` keyword. This draws :ref:`contour and grid box labels - ` on-the-fly. Labels are automatically colored black or white - according to the luminance of the underlying grid box or filled contour. -* The default `vmin` and `vmax` used to normalize colormaps now excludes data - outside the *x* and *y* axis bounds `xlim` and `ylim` if they were explicitly - fixed. This can be disabled by setting :rcraw:`cmap.inbounds` to ``False`` - or by passing ``inbounds=False`` to :class:`~ultraplot.axes.PlotAxes` commands. -* The :class:`~ultraplot.colors.DiscreteNorm` normalizer is paired with most colormaps by - default. It can easily divide colormaps into distinct levels, similar to contour - plots. This can be disabled by setting :rcraw:`cmap.discrete` to ``False`` or - by passing ``discrete=False`` to :class:`~ultraplot.axes.PlotAxes` commands. -* The :class:`~ultraplot.colors.DivergingNorm` normalizer is perfect for data with a - :ref:`natural midpoint ` and offers both "fair" and "unfair" scaling. - The :class:`~ultraplot.colors.SegmentedNorm` normalizer can generate - uneven color gradations useful for :ref:`unusual data distributions `. -* The :func:`~ultraplot.axes.PlotAxes.heatmap` command invokes - :func:`~ultraplot.axes.PlotAxes.pcolormesh` then applies an `equal axes apect ratio - `__, - adds ticks to the center of each gridbox, and disables minor ticks and gridlines. - This can be convenient for things like covariance matrices. -* Coordinate centers passed to commands like :func:`~ultraplot.axes.PlotAxes.pcolor` are - automatically translated to "edges", and coordinate edges passed to commands like - :func:`~ultraplot.axes.PlotAxes.contour` are automatically translated to "centers". In - matplotlib, ``pcolor`` simply truncates and offsets the data when it receives centers. -* Commands like :func:`~ultraplot.axes.PlotAxes.pcolor`, :func:`~ultraplot.axes.PlotAxes.contourf` - and :func:`~ultraplot.axes.Axes.colorbar` automatically fix an irritating issue where - saved vector graphics appear to have thin white lines between `filled contours - `__, `grid boxes - `__, and `colorbar segments - `__. This can be disabled by - passing ``edgefix=False`` to :class:`~ultraplot.axes.PlotAxes` commands. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/plotting_mpl.svg + :alt: A matplotlib line plot where the fill under the curve uses a single color for both positive and negative regions + :width: 100% + + Filling under a curve means writing :func:`~matplotlib.axes.Axes.fill_between` + yourself, and the obvious call paints the positive and negative regions the + same color. Differentiating the sign requires ``where=`` bookkeeping by hand. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/plotting_uplt.svg + :alt: The same data made with UltraPlot's area command, which colors positive regions blue and negative regions red + :width: 100% + + ``ax.area(x, y, negpos=True)`` colors the positive and negative regions + automatically. The :class:`~ultraplot.axes.PlotAxes` commands bundle many + such `seaborn`_- and `xarray`_-style conveniences, including + :ref:`standardized data arguments `, + :ref:`on-the-fly colorbars and legends `, and + :ref:`error bars and shading `. Links ----- @@ -536,47 +350,39 @@ Links Cartopy and basemap integration =============================== -Limitation ----------- - -There are two widely-used engines for working with geographic data in -matplotlib: `cartopy`_ and `basemap`_. Using cartopy tends to be -verbose and involve boilerplate code, while using basemap requires plotting -with a separate :class:`~mpl_toolkits.basemap.Basemap` object rather than the -:class:`~matplotlib.axes.Axes`. They both require separate import statements and extra -lines of code to configure the projection. - -Furthermore, when you use `cartopy`_ and `basemap`_ plotting -commands, "map projection" coordinates are the default coordinate system -rather than longitude-latitude coordinates. This choice is confusing for -many users, since the vast majority of geophysical data are stored with -longitude-latitude (i.e., "Plate Carrée") coordinates. - -Changes -------- - -UltraPlot can succinctly create detailed geographic plots using either cartopy or -basemap as "backends". By default, cartopy is used, but basemap can be used by passing -``backend='basemap'`` to axes-creation commands or by setting :rcraw:`geo.backend` to -``'basemap'``. To create a geographic plot, simply pass the `PROJ `__ -name to an axes-creation command, e.g. ``fig, ax = uplt.subplots(proj='pcarree')`` -or ``fig.add_subplot(proj='pcarree')``. Alternatively, use the -:class:`~ultraplot.constructor.Proj` constructor function to quickly generate -a :class:`~cartopy.crs.Projection` or :class:`~mpl_toolkits.basemap.Basemap` instance. - -Requesting geographic projections creates a :class:`~ultraplot.axes.GeoAxes` -with unified support for `cartopy`_ and `basemap`_ features via the -:func:`~ultraplot.axes.GeoAxes.format` command. This lets you quickly modify geographic -plot features like latitude and longitude gridlines, gridline labels, continents, -coastlines, and political boundaries. The syntax is conveniently analogous to the -syntax used for :func:`~ultraplot.axes.CartesianAxes.format` and :func:`~ultraplot.axes.PolarAxes.format`. - -The :class:`~ultraplot.axes.GeoAxes` subclass also makes longitude-latitude coordinates -the "default" coordinate system by passing ``transform=ccrs.PlateCarree()`` -or ``latlon=True`` to :class:`~ultraplot.axes.PlotAxes` commands (depending on whether cartopy -or basemap is the backend). And to enforce global coverage over the poles and across -longitude seams, you can pass ``globe=True`` to 2D :class:`~ultraplot.axes.PlotAxes` commands -like :func:`~ultraplot.axes.PlotAxes.contour` and :func:`~ultraplot.axes.PlotAxes.pcolormesh`. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/geo_mpl.svg + :alt: A cartopy map built by hand, with default gridlines and overlapping edge labels + :width: 100% + + Building a map with `cartopy`_ or `basemap`_ means importing a separate + package, configuring the projection, and adding gridlines and labels line + by line. Longitude-latitude ("Plate Carrée") data has to be converted to + map coordinates by hand. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/geo_uplt.svg + :alt: The same map made with UltraPlot's GeoAxes, with clean labeled gridlines + :width: 100% + + A geographic plot is ``uplt.subplots(proj='pcarree')``. The + :class:`~ultraplot.axes.GeoAxes` subclass unifies `cartopy`_ and `basemap`_, + defaults to longitude-latitude coordinates, and exposes gridlines, labels, + coastlines, and borders through the same :func:`~ultraplot.axes.GeoAxes.format` + command used elsewhere. Links ----- @@ -597,46 +403,38 @@ Links Pandas and xarray integration ============================= -Limitation ----------- - -Scientific data is commonly stored in array-like containers -that include metadata -- namely, :class:`~xarray.DataArray`\ s, :class:`~pandas.DataFrame`\ s, -and :class:`~pandas.Series`. When matplotlib receives these objects, it ignores -the associated metadata. To create plots that are labeled with the metadata, -you must use the :func:`~xarray.DataArray.plot`, :func:`~pandas.DataFrame.plot`, -and :func:`~pandas.Series.plot` commands instead. - -This approach is fine for quick plots, but not ideal for complex ones. It requires -learning a different syntax from matplotlib, and tends to encourage using the -:obj:`~matplotlib.pyplot` interface rather than the object-oriented interface. The -``plot`` commands also include features that would be useful additions to matplotlib -in their own right, without requiring special containers and a separate interface. - -Changes -------- - -UltraPlot reproduces many of the :func:`~xarray.DataArray.plot`, -:func:`~pandas.DataFrame.plot`, and :func:`~pandas.Series.plot` -features directly on the :class:`~ultraplot.axes.PlotAxes` commands. -This includes :ref:`grouped or stacked ` bar plots -and :ref:`layered or stacked ` area plots from two-dimensional -input data, auto-detection of :ref:`diverging datasets ` for -application of diverging colormaps and normalizers, and -:ref:`on-the-fly colorbars and legends ` using `colorbar` -and `legend` keywords. - -UltraPlot also handles metadata associated with :class:`~xarray.DataArray`, :class:`~pandas.DataFrame`, -:class:`~pandas.Series`, and :class:`~pint.Quantity` objects. When a plotting command receives these -objects, it updates the axis tick labels, axis labels, subplot title, and -colorbar and legend labels from the metadata. For :class:`~pint.Quantity` arrays (including -:class:`~pint.Quantity` those stored inside :class:`~xarray.DataArray` containers), a unit string -is generated from the `pint.Unit` according to the :rcraw:`unitformat` setting -(note UltraPlot also automatically calls :func:`~pint.UnitRegistry.setup_matplotlib` -whenever a :class:`~pint.Quantity` is used for *x* and *y* coordinates and removes the -units from *z* coordinates to avoid the stripped-units warning message). -These features can be disabled by setting :rcraw:`autoformat` to ``False`` -or passing ``autoformat=False`` to any plotting command. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/metadata_mpl.svg + :alt: A matplotlib plot of an xarray DataArray with no legend and generic axis labels + :width: 100% + + Matplotlib treats a :class:`~xarray.DataArray` or :class:`~pandas.DataFrame` + as a plain array and ignores its metadata -- so no legend, no title, and + generic axis labels. Getting the metadata into the figure means switching to + the ``.plot`` methods and learning a second syntax. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/metadata_uplt.svg + :alt: The same DataArray plotted with UltraPlot, automatically labeled with its title, coordinates, and legend + :width: 100% + + The same data plotted with UltraPlot is labeled automatically: the axis + labels, subplot title, and colorbar and legend labels are all taken from the + metadata. :class:`~pint.Quantity` units are handled too. Disable with + ``autoformat=False``. Links ----- @@ -657,56 +455,39 @@ Links Aesthetic colors and fonts ========================== -Limitation ----------- - -A common problem with scientific visualizations is the use of "misleading" -colormaps like ``'jet'``. These colormaps have jarring jumps in -`hue, saturation, and luminance `_ that can trick the human eye into seeing -non-existing patterns. It is important to use "perceptually uniform" colormaps -instead. Matplotlib comes packaged with `a few of its own `_, plus -the `ColorBrewer `_ colormap series, but external projects offer -a larger variety of aesthetically pleasing "perceptually uniform" colormaps -that would be nice to have in one place. - -Matplotlib also "registers" the X11/CSS4 color names, but these are relatively -limited. The more numerous and arguably more intuitive `XKCD color survey `_ -names can only be accessed with the ``'xkcd:'`` prefix. As with colormaps, there -are also external projects with useful color names like `open color `_. - -Finally, matplotlib comes packaged with ``DejaVu Sans`` as the default font. -This font is open source and include glyphs for a huge variety of characters. -However in our opinion, it is not very aesthetically pleasing. It is also -difficult to switch to other fonts on limited systems or systems with fonts -stored in incompatible file formats (see :ref:`below `). - -Changes -------- - -UltraPlot adds new colormaps, colors, and fonts to help you make more -aesthetically pleasing figures. - -* UltraPlot adds colormaps from the `seaborn `_, `cmocean `_, - `SciVisColor `_, and `Scientific Colour Maps `_ projects. - It also defines a few default :ref:`perceptually uniform colormaps ` - and includes a :class:`~ultraplot.colors.PerceptualColormap` class for generating - new ones. A :ref:`table of colormap ` and - :ref:`color cycles ` can be shown using - :func:`~ultraplot.demos.show_cmaps` and :func:`~ultraplot.demos.show_cycles`. - Colormaps like ``'jet'`` can still be accessed, but this is discouraged. -* UltraPlot adds colors from the `open color `_ project and adds - `XKCD color survey `_ names without the ``'xkcd:'`` prefix after - *filtering* them to exclude perceptually-similar colors and *normalizing* the - naming pattern to make them more self-consistent. Old X11/CSS4 colors can still be - accessed, but this is discouraged. A :ref:`table of color names ` - can be shown using :func:`~ultraplot.demos.show_colors`. -* UltraPlot comes packaged with several additional :ref:`sans-serif fonts - ` and the entire `TeX Gyre `_ font series. TeX Gyre - consists of open-source fonts designed to resemble more popular, commonly-used fonts - like Helvetica and Century. They are used as the new default serif, sans-serif, - monospace, cursive, and "fantasy" fonts, and they are available on all workstations. - A :ref:`table of font names ` can be shown - using :func:`~ultraplot.demos.show_fonts`. +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: + :class-card: uplt-why uplt-why-mpl + :text-align: center + + **Matplotlib** + + .. image:: _static/why_plots/aesthetics_mpl.svg + :alt: A jet-colored matplotlib plot with the default DejaVu font + :width: 100% + + "Misleading" colormaps like ``'jet'`` have jarring jumps in hue, + saturation, and luminance that can trick the eye into seeing patterns that + are not there (`rainbow`_). The default DejaVu font is functional but not + particularly elegant. + + .. grid-item-card:: + :class-card: uplt-why uplt-why-uplt + :text-align: center + + **UltraPlot** + + .. image:: _static/why_plots/aesthetics_uplt.svg + :alt: The same field plotted with a perceptually uniform batlow colormap and the TeX Gyre font + :width: 100% + + UltraPlot ships "perceptually uniform" colormaps from the `seaborn `_, + `cmocean `_, `SciVisColor `_, and + `Scientific Colour Maps `_ projects (here, ``'batlow'``), plus the + `TeX Gyre `_ font series, the `open color `_ palette, + and filtered `XKCD color survey `_ names. Links ----- @@ -725,49 +506,25 @@ Links Manipulating colormaps ====================== -Limitation ----------- - -In matplotlib, colormaps are implemented with the -:class:`~matplotlib.colors.LinearSegmentedColormap` class (representing "smooth" -color gradations) and the :class:`~matplotlib.colors.ListedColormap` class (representing -"categorical" color sets). They are somewhat cumbersome to modify or create from -scratch. Meanwhile, property cycles used for individual plot elements are implemented -with the :class:`~cycler.Cycler` class. They are easier to modify but they cannot be -"registered" by name like colormaps. - -The `seaborn`_ package includes "color palettes" to make working with colormaps -and property cycles easier, but it would be nice to have similar features -integrated more closely with matplotlib's colormap and property cycle constructs. - -Changes -------- - -UltraPlot tries to make it easy to manipulate colormaps and property cycles. - -* All colormaps in UltraPlot are replaced with the :class:`~ultraplot.colors.ContinuousColormap` - and :class:`~ultraplot.colors.DiscreteColormap` subclasses of - :class:`~matplotlib.colors.LinearSegmentedColormap` and :class:`~matplotlib.colors.ListedColormap`. - These classes include several useful features leveraged by the - :ref:`constructor functions ` - :class:`~ultraplot.constructor.Colormap` and :class:`~ultraplot.constructor.Cycle`. -* The :class:`~ultraplot.constructor.Colormap` function can merge, truncate, and - modify existing colormaps or generate brand new colormaps. It can also - create new :class:`~ultraplot.colors.PerceptualColormap`\ s -- a type of - :class:`~ultraplot.colors.ContinuousColormap` with linear transitions in the - :ref:`perceptually uniform-like ` hue, saturation, - and luminance channels rather then the red, blue, and green channels. -* The :class:`~ultraplot.constructor.Cycle` function can make property cycles from - scratch or retrieve "registered" color cycles from their associated - :class:`~ultraplot.colors.DiscreteColormap` instances. It can also make property - cycles by splitting up the colors from registered or on-the-fly - :class:`~ultraplot.colors.ContinuousColormap`\ s and :class:`~ultraplot.colors.PerceptualColormap`\ s. - -UltraPlot also makes all colormap and color cycle names case-insensitive, and -colormaps are automatically reversed or cyclically shifted 180 degrees if you -append ``'_r'`` or ``'_s'`` to any colormap name. These features are powered by -:class:`~ultraplot.colors.ColormapDatabase`, which replaces matplotlib's native -colormap database. +Matplotlib implements colormaps with +:class:`~matplotlib.colors.LinearSegmentedColormap` and +:class:`~matplotlib.colors.ListedColormap`, which are cumbersome to modify or +create from scratch. UltraPlot makes colormaps and property cycles easy to +work with: + +* All colormaps are replaced with the :class:`~ultraplot.colors.ContinuousColormap` + and :class:`~ultraplot.colors.DiscreteColormap` subclasses, adding the features + used by the :class:`~ultraplot.constructor.Colormap` and + :class:`~ultraplot.constructor.Cycle` :ref:`constructor functions `. +* :class:`~ultraplot.constructor.Colormap` can merge, truncate, and modify existing + colormaps, or generate brand-new ones -- including + :class:`~ultraplot.colors.PerceptualColormap`\ s with linear transitions in + hue, saturation, and luminance rather than red, green, and blue. +* :class:`~ultraplot.constructor.Cycle` can build property cycles from scratch, + from registered :class:`~ultraplot.colors.DiscreteColormap` instances, or by + splitting up the colors from continuous colormaps. +* Colormap and cycle names are case-insensitive, and appending ``'_r'`` or ``'_s'`` + reverses or cyclically shifts them. Links ----- @@ -786,38 +543,20 @@ Links Physical units engine ===================== -Limitation ----------- - -Matplotlib uses figure-relative units for the margins `left`, `right`, -`bottom`, and `top`, and axes-relative units for the column and row spacing -`wspace` and `hspace`. Relative units tend to require "tinkering" with -numbers until you find the right one. And since they are *relative*, if you -decide to change your figure size or add a subplot, they will have to be -readjusted. - -Matplotlib also requires users to set the figure size `figsize` in inches. -This may be confusing for users outside of the United States. - -Changes -------- - -UltraPlot uses physical units for the :class:`~ultraplot.gridspec.GridSpec` keywords -`left`, `right`, `top`, `bottom`, `wspace`, `hspace`, `pad`, `outerpad`, and -`innerpad`. The default unit (assumed when a numeric argument is passed) is -`em-widths `__. Em-widths are -particularly appropriate for this context, as plot text can be a useful "ruler" -when figuring out the amount of space you need. UltraPlot also permits arbitrary -string units for these keywords, for the :class:`~ultraplot.figure.Figure` keywords -`figsize`, `figwidth`, `figheight`, `refwidth`, and `refheight`, and in a -few other places. This is powered by the physical units engine :func:`~ultraplot.utils.units`. -Acceptable units include inches, centimeters, millimeters, -pixels, `points `__, and `picas -`__ (a table of acceptable -units is found :ref:`here `). Note the :func:`~ultraplot.utils.units` engine -also translates rc settings assigned to :func:`~ultraplot.config.rc_matplotlib` and -:obj:`~ultraplot.config.rc_UltraPlot`, e.g. :rcraw:`subplots.refwidth`, -:rcraw:`legend.columnspacing`, and :rcraw:`axes.labelpad`. +Matplotlib expresses margins in figure-relative units and spacing in +axes-relative units, so changing the figure size forces you to re-tune the +numbers. UltraPlot instead uses physical units everywhere: + +* The :class:`~ultraplot.gridspec.GridSpec` keywords `left`, `right`, `top`, + `bottom`, `wspace`, `hspace`, `pad`, `outerpad`, and `innerpad` accept physical + units, defaulting to `em-widths` -- plot text is a useful "ruler" for spacing. +* The :class:`~ultraplot.figure.Figure` keywords `figsize`, `figwidth`, + `figheight`, `refwidth`, and `refheight` accept arbitrary string units such as + inches, centimeters, millimeters, pixels, `points`, and `picas` (see the + :ref:`units table `). +* This is powered by the :func:`~ultraplot.utils.units` engine, which also + translates rc settings assigned to :func:`~ultraplot.config.rc_matplotlib` and + :obj:`~ultraplot.config.rc_UltraPlot`. Links ----- @@ -829,35 +568,28 @@ Links * For more on colorbar width units, see :ref:`this page `, * For more on panel width units, - see :ref:`this page `, + see :ref:`this page ` .. _why_rc: Flexible global settings ======================== -Limitation ----------- - -In matplotlib, there are several :obj:`~matplotlib.rcParams` that would be -useful to set all at once, like spine and label colors. It might also -be useful to change these settings for individual subplots rather -than globally. - -Changes -------- - -In UltraPlot, you can use the :obj:`~ultraplot.config.rc` object to change both native -matplotlib settings (found in :obj:`~ultraplot.config.rc_matplotlib`) and added UltraPlot -settings (found in :obj:`~ultraplot.config.rc_UltraPlot`). Assigned settings are always -validated, and "meta" settings like ``meta.edgecolor``, ``meta.linewidth``, and -``font.smallsize`` can be used to update many settings all at once. Settings can -be changed with ``uplt.rc.key = value``, ``uplt.rc[key] = value``, -``uplt.rc.update(key=value)``, using :func:`~ultraplot.axes.Axes.format`, or using -:func:`~ultraplot.config.Configurator.context`. Settings that have changed during the -python session can be saved to a file with :func:`~ultraplot.config.Configurator.save` -(see :func:`~ultraplot.config.Configurator.changed`), and settings can be loaded from -files with :func:`~ultraplot.config.Configurator.load`. +In matplotlib, several :obj:`~matplotlib.rcParams` are only useful if changed +all at once -- like spine and label colors -- and they cannot be changed for +individual subplots. UltraPlot provides a single :obj:`~ultraplot.config.rc` +object for both native matplotlib settings +(:obj:`~ultraplot.config.rc_matplotlib`) and UltraPlot's own settings +(:obj:`~ultraplot.config.rc_UltraPlot`): + +* Assigned settings are always validated, and "meta" settings like + ``meta.edgecolor`` and ``meta.linewidth`` update many settings at once. +* Settings can be changed with ``uplt.rc.key = value``, ``uplt.rc[key] = value``, + ``uplt.rc.update(key=value)``, :func:`~ultraplot.axes.Axes.format`, or the + :func:`~ultraplot.config.Configurator.context` context manager. +* Settings changed during a session can be saved with + :func:`~ultraplot.config.Configurator.save` and loaded with + :func:`~ultraplot.config.Configurator.load`. Links ----- @@ -878,36 +610,26 @@ Links Loading stuff ============= -Limitation ----------- - -Matplotlib :obj:`~matplotlib.rcParams` can be changed persistently by placing -ref:`matplotlibrc ` files in the same directory as your python script. -But it can be difficult to design and store your own colormaps and color cycles for -future use. It is also difficult to get matplotlib to use custom ``.ttf`` and -``.otf`` font files, which may be desirable when you are working on -Linux servers with limited font selections. - -Changes -------- - -UltraPlot settings can be changed persistently by editing the default ``ultraplotrc`` -file in the location given by :func:`~ultraplot.config.Configurator.user_file` (this is -usually ``$HOME/.ultraplot/ultraplotrc``) or by adding loose ``ultraplotrc`` files to -either the current directory or an arbitrary parent directory. Adding files to -parent directories can be useful when working in projects with lots of subfolders. - -UltraPlot also automatically registers colormaps, color cycles, colors, and font -files stored in subfolders named ``cmaps``, ``cycles``, ``colors``, and ``fonts`` -in the location given by :func:`~ultraplot.config.Configurator.user_folder` (this is usually -``$HOME/.ultraplot``), as well as loose subfolders named ``ultraplot_cmaps``, -``ultraplot_cycles``, ``ultraplot_colors``, and ``ultraplot_fonts`` in the current -directory or an arbitrary parent directory. You can save colormaps and color cycles to -:func:`~ultraplot.config.Configurator.user_folder` simply by passing ``save=True`` to -:class:`~ultraplot.constructor.Colormap` and :class:`~ultraplot.constructor.Cycle`. To re-register -these files during an active python session, or to register arbitrary input arguments, -you can use :func:`~ultraplot.config.register_cmaps`, :func:`~ultraplot.config.register_cycles`, -:func:`~ultraplot.config.register_colors`, or :func:`~ultraplot.config.register_fonts`. +Matplotlib makes persistent configuration awkward, and there is no built-in way +to register your own colormaps, color cycles, or fonts. UltraPlot turns this +into dropping files into folders: + +* Edit the default ``ultraplotrc`` file (usually ``$HOME/.ultraplot/ultraplotrc``) + or add loose ``ultraplotrc`` files to the current directory or a parent + directory to change settings persistently. +* Colormaps, color cycles, colors, and fonts stored in subfolders named + ``cmaps``, ``cycles``, ``colors``, and ``fonts`` inside + :func:`~ultraplot.config.Configurator.user_folder` (usually + ``$HOME/.ultraplot``) are registered automatically -- as are loose + ``ultraplot_cmaps``, ``ultraplot_cycles``, ``ultraplot_colors``, and + ``ultraplot_fonts`` folders in the current or a parent directory. +* Pass ``save=True`` to :class:`~ultraplot.constructor.Colormap` and + :class:`~ultraplot.constructor.Cycle` to save new colormaps and cycles, or use + :func:`~ultraplot.config.register_cmaps`, + :func:`~ultraplot.config.register_cycles`, + :func:`~ultraplot.config.register_colors`, and + :func:`~ultraplot.config.register_fonts` to register arbitrary inputs during + a session. Links ----- From abb23e5128f1a86fe5923e444b1979ad71841e06 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Thu, 13 Aug 2026 15:12:06 +1000 Subject: [PATCH 2/6] Replace why-page SVG figures with source plots --- docs/_static/why_plots/aesthetics_mpl.svg | 15587 --------------- docs/_static/why_plots/aesthetics_uplt.svg | 16408 ---------------- docs/_static/why_plots/colorbars_mpl.svg | 5878 ------ docs/_static/why_plots/colorbars_uplt.svg | 6899 ------- docs/_static/why_plots/geo_mpl.svg | 2597 --- docs/_static/why_plots/geo_uplt.svg | 18809 ------------------- docs/_static/why_plots/metadata_mpl.svg | 593 - docs/_static/why_plots/metadata_uplt.svg | 1421 -- docs/_static/why_plots/plotting_mpl.svg | 846 - docs/_static/why_plots/plotting_uplt.svg | 1460 -- docs/_static/why_plots/spacing_mpl.svg | 1170 -- docs/_static/why_plots/spacing_uplt.svg | 2714 --- docs/_static/why_plots/subplots_mpl.svg | 1413 -- docs/_static/why_plots/subplots_uplt.svg | 2773 --- docs/why.rst | 264 +- 15 files changed, 222 insertions(+), 78610 deletions(-) delete mode 100644 docs/_static/why_plots/aesthetics_mpl.svg delete mode 100644 docs/_static/why_plots/aesthetics_uplt.svg delete mode 100644 docs/_static/why_plots/colorbars_mpl.svg delete mode 100644 docs/_static/why_plots/colorbars_uplt.svg delete mode 100644 docs/_static/why_plots/geo_mpl.svg delete mode 100644 docs/_static/why_plots/geo_uplt.svg delete mode 100644 docs/_static/why_plots/metadata_mpl.svg delete mode 100644 docs/_static/why_plots/metadata_uplt.svg delete mode 100644 docs/_static/why_plots/plotting_mpl.svg delete mode 100644 docs/_static/why_plots/plotting_uplt.svg delete mode 100644 docs/_static/why_plots/spacing_mpl.svg delete mode 100644 docs/_static/why_plots/spacing_uplt.svg delete mode 100644 docs/_static/why_plots/subplots_mpl.svg delete mode 100644 docs/_static/why_plots/subplots_uplt.svg diff --git a/docs/_static/why_plots/aesthetics_mpl.svg b/docs/_static/why_plots/aesthetics_mpl.svg deleted file mode 100644 index f3f29661f..000000000 --- a/docs/_static/why_plots/aesthetics_mpl.svg +++ /dev/null @@ -1,15587 +0,0 @@ - - - - - - - - 2026-08-11T12:57:55.103333 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/aesthetics_uplt.svg b/docs/_static/why_plots/aesthetics_uplt.svg deleted file mode 100644 index c4370cff1..000000000 --- a/docs/_static/why_plots/aesthetics_uplt.svg +++ /dev/null @@ -1,16408 +0,0 @@ - - - - - - - - 2026-08-11T12:57:55.774591 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/colorbars_mpl.svg b/docs/_static/why_plots/colorbars_mpl.svg deleted file mode 100644 index 5ed02b27c..000000000 --- a/docs/_static/why_plots/colorbars_mpl.svg +++ /dev/null @@ -1,5878 +0,0 @@ - - - - - - - - 2026-08-11T12:57:49.889271 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/colorbars_uplt.svg b/docs/_static/why_plots/colorbars_uplt.svg deleted file mode 100644 index 163ac1496..000000000 --- a/docs/_static/why_plots/colorbars_uplt.svg +++ /dev/null @@ -1,6899 +0,0 @@ - - - - - - - - 2026-08-11T12:57:50.883487 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/geo_mpl.svg b/docs/_static/why_plots/geo_mpl.svg deleted file mode 100644 index 2413d9339..000000000 --- a/docs/_static/why_plots/geo_mpl.svg +++ /dev/null @@ -1,2597 +0,0 @@ - - - - - - - - 2026-08-11T16:11:55.118936 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/geo_uplt.svg b/docs/_static/why_plots/geo_uplt.svg deleted file mode 100644 index 12b0a48d4..000000000 --- a/docs/_static/why_plots/geo_uplt.svg +++ /dev/null @@ -1,18809 +0,0 @@ - - - - - - - - 2026-08-11T16:11:56.507282 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/metadata_mpl.svg b/docs/_static/why_plots/metadata_mpl.svg deleted file mode 100644 index 99619a50f..000000000 --- a/docs/_static/why_plots/metadata_mpl.svg +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - - 2026-08-11T12:57:54.683456 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/metadata_uplt.svg b/docs/_static/why_plots/metadata_uplt.svg deleted file mode 100644 index 67582f23f..000000000 --- a/docs/_static/why_plots/metadata_uplt.svg +++ /dev/null @@ -1,1421 +0,0 @@ - - - - - - - - 2026-08-11T12:57:54.932854 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/plotting_mpl.svg b/docs/_static/why_plots/plotting_mpl.svg deleted file mode 100644 index 88f5136eb..000000000 --- a/docs/_static/why_plots/plotting_mpl.svg +++ /dev/null @@ -1,846 +0,0 @@ - - - - - - - - 2026-08-11T12:57:51.205093 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/plotting_uplt.svg b/docs/_static/why_plots/plotting_uplt.svg deleted file mode 100644 index b214ea2ee..000000000 --- a/docs/_static/why_plots/plotting_uplt.svg +++ /dev/null @@ -1,1460 +0,0 @@ - - - - - - - - 2026-08-11T12:57:51.520802 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/spacing_mpl.svg b/docs/_static/why_plots/spacing_mpl.svg deleted file mode 100644 index 44a58c51c..000000000 --- a/docs/_static/why_plots/spacing_mpl.svg +++ /dev/null @@ -1,1170 +0,0 @@ - - - - - - - - 2026-08-11T16:11:53.624180 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/spacing_uplt.svg b/docs/_static/why_plots/spacing_uplt.svg deleted file mode 100644 index c50801108..000000000 --- a/docs/_static/why_plots/spacing_uplt.svg +++ /dev/null @@ -1,2714 +0,0 @@ - - - - - - - - 2026-08-11T16:11:54.382542 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/subplots_mpl.svg b/docs/_static/why_plots/subplots_mpl.svg deleted file mode 100644 index 8657ec227..000000000 --- a/docs/_static/why_plots/subplots_mpl.svg +++ /dev/null @@ -1,1413 +0,0 @@ - - - - - - - - 2026-08-11T16:11:54.619627 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/_static/why_plots/subplots_uplt.svg b/docs/_static/why_plots/subplots_uplt.svg deleted file mode 100644 index 4f211d40f..000000000 --- a/docs/_static/why_plots/subplots_uplt.svg +++ /dev/null @@ -1,2773 +0,0 @@ - - - - - - - - 2026-08-11T12:57:49.491847 - image/svg+xml - - - Matplotlib v3.8.4, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/why.rst b/docs/why.rst index d7cb6b52e..eff6f1e4d 100644 --- a/docs/why.rst +++ b/docs/why.rst @@ -171,9 +171,24 @@ Automatic dimensions and spacing **Matplotlib** - .. image:: _static/why_plots/spacing_mpl.svg - :alt: A 2x2 matplotlib figure where the bottom-row titles overlap the top-row tick labels - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + x = np.arange(10) + y = np.random.default_rng(0).normal(size=(4, 10)) + fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.8)) + for i in range(2): + for j in range(2): + axs[i, j].plot(x, y[i, :] * (i + 1) + j + 0.25 * x) + axs[i, j].set_title( + "A long title that collides with neighboring labels", + fontsize=10, + ) + axs[i, j].set_xlabel("x axis", fontsize=10) + axs[i, j].set_ylabel("y axis", fontsize=10) The figure size is fixed, the margins are tuned by hand, and the bottom-row titles collide with the tick labels above them. Add a subplot or change the @@ -185,9 +200,31 @@ Automatic dimensions and spacing **UltraPlot** - .. image:: _static/why_plots/spacing_uplt.svg - :alt: The same 2x2 layout made with UltraPlot with clean, automatic spacing - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + x = np.arange(10) + y = np.random.default_rng(1).normal(size=(4, 10)) + fig, axs = uplt.subplots( + 2, + 2, + refwidth="2.8cm", + refheight="2.2cm", + wspace="3mm", + hspace="4mm", + ) + for ix in range(2): + for jx in range(2): + axs[ix, jx].plot(x, y[ix, :] * (ix + 1) + jx + 0.25 * x) + axs[ix, jx].format( + xlabel="x", + ylabel="y", + title="Automatic spacing across subplot groups", + abc="A.", + ) UltraPlot fixes the physical dimensions of a *reference subplot* (``refwidth``, ``refheight``, ``refaspect``) instead of the figure, so subplot size -- and the @@ -214,9 +251,21 @@ Working with multiple subplots **Matplotlib** - .. image:: _static/why_plots/subplots_mpl.svg - :alt: A 2x2 matplotlib figure with repeated tick labels on every subplot and no subplot labels - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + x = np.arange(5) + fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.8)) + for i in range(2): + for j in range(2): + axs[i, j].plot(x, x * (i + 1) + j, label=f"line_{i}_{j}") + axs[i, j].set_xlabel("x") + axs[i, j].set_ylabel("y") + axs[i, j].set_title("Panel label") + fig.legend(loc="upper right", ncol=1, frameon=False) Every subplot repeats its own tick labels and axis labels, wasting page space. Adding "a-b-c" labels -- required for most publications -- is @@ -228,9 +277,18 @@ Working with multiple subplots **UltraPlot** - .. image:: _static/why_plots/subplots_uplt.svg - :alt: The same 2x2 layout made with UltraPlot with shared tick labels and a-b-c labels - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + x = np.arange(5) + fig, axs = uplt.subplots(2, 2, sharex=1, sharey=1, refwidth="2.8cm", refheight="2.2cm") + for idx, ax in enumerate(np.ravel(axs), start=1): + ax.plot(x, x * ((idx % 2) + 1)) + ax.format(abc=f"{'ABCD'[idx-1]}.") + axs.format(xlabel="x", ylabel="y") Tick labels and axis labels are shared and aligned automatically (``sharex``, ``sharey``, ``spanx``, ``spany``), and a-b-c labels are added with a single @@ -259,9 +317,19 @@ Simpler colorbars and legends **Matplotlib** - .. image:: _static/why_plots/colorbars_mpl.svg - :alt: Two matplotlib panels where the colorbar steals space from its parent subplot, making the panels unequal widths - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + data = np.linspace(0, 1, 200).reshape(20, 10) + fig, axs = plt.subplots(1, 2, figsize=(4.6, 3.0)) + for i in range(2): + m = axs[i].imshow(data * (i + 1), aspect="auto") + axs[i].set_title("Left" if i == 0 else "Right") + if i == 0: + fig.colorbar(m, ax=axs[i]) Drawing a colorbar with ``fig.colorbar(m, ax=ax)`` *steals space* from the parent subplot -- here the left panel is visibly narrower than the right @@ -273,9 +341,18 @@ Simpler colorbars and legends **UltraPlot** - .. image:: _static/why_plots/colorbars_uplt.svg - :alt: The same two panels with outer colorbars drawn in dedicated space, keeping the panels equal width - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + data = np.linspace(0, 1, 200).reshape(20, 10) + fig, axs = uplt.subplots(1, 2, refwidth="3.2cm", refheight="2.4cm", wspace=0.4) + for idx, ax in enumerate(np.ravel(axs), start=1): + m = ax.imshow(data * idx) + fig.colorbar(m, ax=ax, loc="r", width="6mm") + ax.format(title="Right" if idx == 2 else "Left") Colorbars and legends get their own space in the :class:`~ultraplot.gridspec.GridSpec` -- the subplots keep their exact @@ -308,9 +385,18 @@ Improved plotting commands **Matplotlib** - .. image:: _static/why_plots/plotting_mpl.svg - :alt: A matplotlib line plot where the fill under the curve uses a single color for both positive and negative regions - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + x = np.linspace(0, 2 * np.pi, 200) + y = np.sin(x) + fig, ax = plt.subplots(figsize=(4.6, 3.0)) + ax.fill_between(x, 0, y) + ax.plot(x, y, color="black") + ax.set_title("Single fill color for pos/neg regions") Filling under a curve means writing :func:`~matplotlib.axes.Axes.fill_between` yourself, and the obvious call paints the positive and negative regions the @@ -322,9 +408,17 @@ Improved plotting commands **UltraPlot** - .. image:: _static/why_plots/plotting_uplt.svg - :alt: The same data made with UltraPlot's area command, which colors positive regions blue and negative regions red - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + x = np.linspace(0, 2 * np.pi, 200) + y = np.sin(x) + fig, ax = uplt.subplots(figsize="4.6cm x 3cm") + ax.area(x, y, negpos=True) + ax.format(title="Automatic negative/positive fills") ``ax.area(x, y, negpos=True)`` colors the positive and negative regions automatically. The :class:`~ultraplot.axes.PlotAxes` commands bundle many @@ -359,9 +453,20 @@ Cartopy and basemap integration **Matplotlib** - .. image:: _static/why_plots/geo_mpl.svg - :alt: A cartopy map built by hand, with default gridlines and overlapping edge labels - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + x = np.arange(0, 360, 10) + y = np.arange(-90, 100, 10) + X, Y = np.meshgrid(x, y) + Z = np.sin(np.deg2rad(X)) * np.cos(np.deg2rad(Y)) + fig, ax = plt.subplots(figsize=(4.6, 2.8)) + pcm = ax.pcolormesh(X, Y, Z, cmap="viridis") + fig.colorbar(pcm, ax=ax) + ax.set_title("Hand-built pseudo map with manual gridline work") Building a map with `cartopy`_ or `basemap`_ means importing a separate package, configuring the projection, and adding gridlines and labels line @@ -374,9 +479,25 @@ Cartopy and basemap integration **UltraPlot** - .. image:: _static/why_plots/geo_uplt.svg - :alt: The same map made with UltraPlot's GeoAxes, with clean labeled gridlines - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + x = np.arange(0, 360, 10) + y = np.arange(-90, 100, 10) + X, Y = np.meshgrid(x, y) + Z = np.sin(np.deg2rad(X)) * np.cos(np.deg2rad(Y)) + try: + fig, ax = uplt.subplots(proj="pcarree", refwidth="4.2cm", refheight="2.8cm") + pcm = ax.pcolormesh(X, Y, Z, cmap="batlow") + fig.colorbar(pcm, ax=ax, loc="r", width="6mm", label="value") + ax.format(lonlabels="b", latlabels="l") + except Exception: + fig, ax = uplt.subplots(figsize="4.6cm x 2.8cm") + pcm = ax.pcolormesh(X, Y, Z, cmap="batlow") + ax.set_title("Map-style plot (fallback without projection backends)") A geographic plot is ``uplt.subplots(proj='pcarree')``. The :class:`~ultraplot.axes.GeoAxes` subclass unifies `cartopy`_ and `basemap`_, @@ -412,9 +533,27 @@ Pandas and xarray integration **Matplotlib** - .. image:: _static/why_plots/metadata_mpl.svg - :alt: A matplotlib plot of an xarray DataArray with no legend and generic axis labels - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + import pandas as pd + + rng = np.random.RandomState(0) + data = (rng.normal(size=(12, 18)).cumsum(axis=1).cumsum(axis=0)) + df = pd.DataFrame( + (data - data.min()) / (data.max() - data.min()), + index=pd.date_range("2026-01-01", periods=12, freq="MS"), + columns=np.arange(18), + ) + + fig, ax = plt.subplots(figsize=(4.6, 3.0)) + image = ax.imshow(df.to_numpy(), cmap="viridis", aspect="auto") + fig.colorbar(image, ax=ax) + ax.set_title("Matplotlib treats metadata as plain arrays") + ax.set_xlabel("generic x") + ax.set_ylabel("generic y") Matplotlib treats a :class:`~xarray.DataArray` or :class:`~pandas.DataFrame` as a plain array and ignores its metadata -- so no legend, no title, and @@ -427,9 +566,26 @@ Pandas and xarray integration **UltraPlot** - .. image:: _static/why_plots/metadata_uplt.svg - :alt: The same DataArray plotted with UltraPlot, automatically labeled with its title, coordinates, and legend - :width: 100% + .. plot:: + :include-source: true + + import pandas as pd + import numpy as np + import ultraplot as uplt + + rng = np.random.RandomState(0) + df = pd.DataFrame( + (rng.normal(size=(12, 18)).cumsum(axis=1).cumsum(axis=0) - 1), + index=pd.date_range("2026-01-01", periods=12, freq="MS"), + columns=np.arange(18), + ) + df.name = "temperature (\N{DEGREE SIGN}C)" + df.index.name = "month" + df.columns.name = "variable" + + fig, ax = uplt.subplots(figsize="4.6cm x 3.0") + cs = ax.contourf(df, cmap="batlow", colorbar="t") + fig.colorbar(cs, ax=ax, loc="r", width="6mm") The same data plotted with UltraPlot is labeled automatically: the axis labels, subplot title, and colorbar and legend labels are all taken from the @@ -464,9 +620,22 @@ Aesthetic colors and fonts **Matplotlib** - .. image:: _static/why_plots/aesthetics_mpl.svg - :alt: A jet-colored matplotlib plot with the default DejaVu font - :width: 100% + .. plot:: + :include-source: true + + import matplotlib.pyplot as plt + import numpy as np + + x = np.linspace(-4, 4, 180) + y = np.linspace(-4, 4, 180) + X, Y = np.meshgrid(x, y) + Z = np.exp(-(X**2 + Y**2) / 4) * np.cos(X * 2) * np.sin(Y * 2) + + fig, ax = plt.subplots(figsize=(4.6, 3.0)) + ax.pcolormesh(X, Y, Z, cmap="jet") + ax.set_title("A misleading 'jet' colormap") + ax.set_xlabel("x") + ax.set_ylabel("y") "Misleading" colormaps like ``'jet'`` have jarring jumps in hue, saturation, and luminance that can trick the eye into seeing patterns that @@ -479,9 +648,20 @@ Aesthetic colors and fonts **UltraPlot** - .. image:: _static/why_plots/aesthetics_uplt.svg - :alt: The same field plotted with a perceptually uniform batlow colormap and the TeX Gyre font - :width: 100% + .. plot:: + :include-source: true + + import numpy as np + import ultraplot as uplt + + x = np.linspace(-4, 4, 180) + y = np.linspace(-4, 4, 180) + X, Y = np.meshgrid(x, y) + Z = np.exp(-(X**2 + Y**2) / 4) * np.cos(X * 2) * np.sin(Y * 2) + + fig, ax = uplt.subplots(figsize="4.6cm x 3.0") + ax.pcolormesh(X, Y, Z, cmap="batlow") + ax.format(title="Perceptually uniform batlow colormap") UltraPlot ships "perceptually uniform" colormaps from the `seaborn `_, `cmocean `_, `SciVisColor `_, and From 7545e390ac2f9a48b5c487afb85961c6359030f6 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Thu, 13 Aug 2026 15:52:50 +1000 Subject: [PATCH 3/6] Use supported UltraPlot figsize arguments in Why page plot sources --- docs/why.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/why.rst b/docs/why.rst index eff6f1e4d..33e7fd93b 100644 --- a/docs/why.rst +++ b/docs/why.rst @@ -416,7 +416,7 @@ Improved plotting commands x = np.linspace(0, 2 * np.pi, 200) y = np.sin(x) - fig, ax = uplt.subplots(figsize="4.6cm x 3cm") + fig, ax = uplt.subplots(refwidth="4.6cm", refheight="3cm") ax.area(x, y, negpos=True) ax.format(title="Automatic negative/positive fills") @@ -495,7 +495,7 @@ Cartopy and basemap integration fig.colorbar(pcm, ax=ax, loc="r", width="6mm", label="value") ax.format(lonlabels="b", latlabels="l") except Exception: - fig, ax = uplt.subplots(figsize="4.6cm x 2.8cm") + fig, ax = uplt.subplots(refwidth="4.6cm", refheight="2.8cm") pcm = ax.pcolormesh(X, Y, Z, cmap="batlow") ax.set_title("Map-style plot (fallback without projection backends)") @@ -583,7 +583,7 @@ Pandas and xarray integration df.index.name = "month" df.columns.name = "variable" - fig, ax = uplt.subplots(figsize="4.6cm x 3.0") + fig, ax = uplt.subplots(refwidth="4.6cm", refheight="3cm") cs = ax.contourf(df, cmap="batlow", colorbar="t") fig.colorbar(cs, ax=ax, loc="r", width="6mm") @@ -659,7 +659,7 @@ Aesthetic colors and fonts X, Y = np.meshgrid(x, y) Z = np.exp(-(X**2 + Y**2) / 4) * np.cos(X * 2) * np.sin(Y * 2) - fig, ax = uplt.subplots(figsize="4.6cm x 3.0") + fig, ax = uplt.subplots(refwidth="4.6cm", refheight="3cm") ax.pcolormesh(X, Y, Z, cmap="batlow") ax.format(title="Perceptually uniform batlow colormap") From 169d7f180e3c67cd8535bb3eccda0b49644bb2a6 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Thu, 13 Aug 2026 22:11:29 +1000 Subject: [PATCH 4/6] Left-align why docs cards and standardize figure shape --- docs/why.rst | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/why.rst b/docs/why.rst index 33e7fd93b..487f988f8 100644 --- a/docs/why.rst +++ b/docs/why.rst @@ -167,7 +167,7 @@ Automatic dimensions and spacing .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -179,7 +179,7 @@ Automatic dimensions and spacing x = np.arange(10) y = np.random.default_rng(0).normal(size=(4, 10)) - fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.8)) + fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.0)) for i in range(2): for j in range(2): axs[i, j].plot(x, y[i, :] * (i + 1) + j + 0.25 * x) @@ -196,7 +196,7 @@ Automatic dimensions and spacing .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -211,8 +211,8 @@ Automatic dimensions and spacing fig, axs = uplt.subplots( 2, 2, - refwidth="2.8cm", - refheight="2.2cm", + refwidth="4.6cm", + refheight="3.0cm", wspace="3mm", hspace="4mm", ) @@ -247,7 +247,7 @@ Working with multiple subplots .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -258,7 +258,7 @@ Working with multiple subplots import numpy as np x = np.arange(5) - fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.8)) + fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.0)) for i in range(2): for j in range(2): axs[i, j].plot(x, x * (i + 1) + j, label=f"line_{i}_{j}") @@ -273,7 +273,7 @@ Working with multiple subplots .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -284,7 +284,7 @@ Working with multiple subplots import ultraplot as uplt x = np.arange(5) - fig, axs = uplt.subplots(2, 2, sharex=1, sharey=1, refwidth="2.8cm", refheight="2.2cm") + fig, axs = uplt.subplots(2, 2, sharex=1, sharey=1, refwidth="4.6cm", refheight="3.0cm") for idx, ax in enumerate(np.ravel(axs), start=1): ax.plot(x, x * ((idx % 2) + 1)) ax.format(abc=f"{'ABCD'[idx-1]}.") @@ -313,7 +313,7 @@ Simpler colorbars and legends .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -337,7 +337,7 @@ Simpler colorbars and legends .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -348,7 +348,7 @@ Simpler colorbars and legends import ultraplot as uplt data = np.linspace(0, 1, 200).reshape(20, 10) - fig, axs = uplt.subplots(1, 2, refwidth="3.2cm", refheight="2.4cm", wspace=0.4) + fig, axs = uplt.subplots(1, 2, refwidth="4.6cm", refheight="3.0cm", wspace=0.4) for idx, ax in enumerate(np.ravel(axs), start=1): m = ax.imshow(data * idx) fig.colorbar(m, ax=ax, loc="r", width="6mm") @@ -381,7 +381,7 @@ Improved plotting commands .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -404,7 +404,7 @@ Improved plotting commands .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -449,7 +449,7 @@ Cartopy and basemap integration .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -463,7 +463,7 @@ Cartopy and basemap integration y = np.arange(-90, 100, 10) X, Y = np.meshgrid(x, y) Z = np.sin(np.deg2rad(X)) * np.cos(np.deg2rad(Y)) - fig, ax = plt.subplots(figsize=(4.6, 2.8)) + fig, ax = plt.subplots(figsize=(4.6, 3.0)) pcm = ax.pcolormesh(X, Y, Z, cmap="viridis") fig.colorbar(pcm, ax=ax) ax.set_title("Hand-built pseudo map with manual gridline work") @@ -475,7 +475,7 @@ Cartopy and basemap integration .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -490,12 +490,12 @@ Cartopy and basemap integration X, Y = np.meshgrid(x, y) Z = np.sin(np.deg2rad(X)) * np.cos(np.deg2rad(Y)) try: - fig, ax = uplt.subplots(proj="pcarree", refwidth="4.2cm", refheight="2.8cm") + fig, ax = uplt.subplots(proj="pcarree", refwidth="4.6cm", refheight="3cm") pcm = ax.pcolormesh(X, Y, Z, cmap="batlow") fig.colorbar(pcm, ax=ax, loc="r", width="6mm", label="value") ax.format(lonlabels="b", latlabels="l") except Exception: - fig, ax = uplt.subplots(refwidth="4.6cm", refheight="2.8cm") + fig, ax = uplt.subplots(refwidth="4.6cm", refheight="3cm") pcm = ax.pcolormesh(X, Y, Z, cmap="batlow") ax.set_title("Map-style plot (fallback without projection backends)") @@ -529,7 +529,7 @@ Pandas and xarray integration .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -562,7 +562,7 @@ Pandas and xarray integration .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** @@ -616,7 +616,7 @@ Aesthetic colors and fonts .. grid-item-card:: :class-card: uplt-why uplt-why-mpl - :text-align: center + :text-align: left **Matplotlib** @@ -644,7 +644,7 @@ Aesthetic colors and fonts .. grid-item-card:: :class-card: uplt-why uplt-why-uplt - :text-align: center + :text-align: left **UltraPlot** From 4f9680fb8dfe827ec93f2f739359bf34476cc9bb Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Thu, 13 Aug 2026 22:50:50 +1000 Subject: [PATCH 5/6] Standardize why page matplotlib figure sizes to match UltraPlot dimensions --- docs/why.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/why.rst b/docs/why.rst index 487f988f8..08700e282 100644 --- a/docs/why.rst +++ b/docs/why.rst @@ -179,7 +179,7 @@ Automatic dimensions and spacing x = np.arange(10) y = np.random.default_rng(0).normal(size=(4, 10)) - fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.0)) + fig, axs = plt.subplots(2, 2, figsize=(4.6 / 2.54, 3.0 / 2.54)) for i in range(2): for j in range(2): axs[i, j].plot(x, y[i, :] * (i + 1) + j + 0.25 * x) @@ -258,7 +258,7 @@ Working with multiple subplots import numpy as np x = np.arange(5) - fig, axs = plt.subplots(2, 2, figsize=(4.6, 3.0)) + fig, axs = plt.subplots(2, 2, figsize=(4.6 / 2.54, 3.0 / 2.54)) for i in range(2): for j in range(2): axs[i, j].plot(x, x * (i + 1) + j, label=f"line_{i}_{j}") @@ -324,7 +324,7 @@ Simpler colorbars and legends import numpy as np data = np.linspace(0, 1, 200).reshape(20, 10) - fig, axs = plt.subplots(1, 2, figsize=(4.6, 3.0)) + fig, axs = plt.subplots(1, 2, figsize=(4.6 / 2.54, 3.0 / 2.54)) for i in range(2): m = axs[i].imshow(data * (i + 1), aspect="auto") axs[i].set_title("Left" if i == 0 else "Right") @@ -393,7 +393,7 @@ Improved plotting commands x = np.linspace(0, 2 * np.pi, 200) y = np.sin(x) - fig, ax = plt.subplots(figsize=(4.6, 3.0)) + fig, ax = plt.subplots(figsize=(4.6 / 2.54, 3.0 / 2.54)) ax.fill_between(x, 0, y) ax.plot(x, y, color="black") ax.set_title("Single fill color for pos/neg regions") @@ -463,7 +463,7 @@ Cartopy and basemap integration y = np.arange(-90, 100, 10) X, Y = np.meshgrid(x, y) Z = np.sin(np.deg2rad(X)) * np.cos(np.deg2rad(Y)) - fig, ax = plt.subplots(figsize=(4.6, 3.0)) + fig, ax = plt.subplots(figsize=(4.6 / 2.54, 3.0 / 2.54)) pcm = ax.pcolormesh(X, Y, Z, cmap="viridis") fig.colorbar(pcm, ax=ax) ax.set_title("Hand-built pseudo map with manual gridline work") @@ -548,7 +548,7 @@ Pandas and xarray integration columns=np.arange(18), ) - fig, ax = plt.subplots(figsize=(4.6, 3.0)) + fig, ax = plt.subplots(figsize=(4.6 / 2.54, 3.0 / 2.54)) image = ax.imshow(df.to_numpy(), cmap="viridis", aspect="auto") fig.colorbar(image, ax=ax) ax.set_title("Matplotlib treats metadata as plain arrays") @@ -631,7 +631,7 @@ Aesthetic colors and fonts X, Y = np.meshgrid(x, y) Z = np.exp(-(X**2 + Y**2) / 4) * np.cos(X * 2) * np.sin(Y * 2) - fig, ax = plt.subplots(figsize=(4.6, 3.0)) + fig, ax = plt.subplots(figsize=(4.6 / 2.54, 3.0 / 2.54)) ax.pcolormesh(X, Y, Z, cmap="jet") ax.set_title("A misleading 'jet' colormap") ax.set_xlabel("x") From 15938079d71ceb1e6cdb0eceb33d1cf4404c3f37 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Thu, 13 Aug 2026 22:54:35 +1000 Subject: [PATCH 6/6] Add before/after slider UI for Why page figure comparisons --- docs/_static/custom.css | 88 ++++++++++++++++++++++++++++++++++ docs/_static/custom.js | 102 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+) diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 93d6953f8..12802fdc0 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -1279,6 +1279,94 @@ body.wy-body-for-nav background: var(--uplt-color-panel-bg); } +.uplt-why-compare { + margin-bottom: 0.75rem; +} + +.uplt-why-compare .sd-card-body { + padding: 0.75rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.uplt-why-compare .uplt-compare-labels { + display: flex; + justify-content: space-between; + gap: 0.6rem; + font-weight: 700; + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.uplt-why-compare .uplt-compare-labels .uplt-label { + background: var(--uplt-color-panel-bg); + border: 1px solid var(--uplt-color-border-muted); + border-radius: 9999px; + padding: 0.1rem 0.6rem; +} + +.uplt-why-compare .uplt-compare-labels .uplt-label-mpl { + color: #b45309; +} + +.uplt-why-compare .uplt-compare-labels .uplt-label-uplt { + color: #178f84; +} + +.uplt-compare-frame { + position: relative; + width: 100%; + overflow: hidden; + border-radius: 0.45rem; + border: 1px solid var(--uplt-color-border-muted); + background: var(--uplt-color-panel-bg); +} + +.uplt-compare-frame { + --uplt-compare-position: 50%; + aspect-ratio: 4 / 3; +} + +.uplt-compare-img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: contain; +} + +.uplt-compare-mpl { + position: relative; +} + +.uplt-compare-uplt { + clip-path: inset(0 calc(100% - var(--uplt-compare-position)) 0 0); +} + +.uplt-compare-handle { + position: absolute; + top: 0; + left: var(--uplt-compare-position); + transform: translateX(-50%); + width: 2px; + height: 100%; + background: var(--uplt-color-text-secondary); + opacity: 0.95; + pointer-events: none; +} + +.uplt-compare-slider { + display: block; + width: 100%; +} + +.uplt-compare-slider input[type="range"] { + width: 100%; + margin: 0; +} + .uplt-why .sd-card-body > p:first-child { font-weight: 700; font-size: 0.9rem; diff --git a/docs/_static/custom.js b/docs/_static/custom.js index b57f5d3fc..36c6d1ace 100644 --- a/docs/_static/custom.js +++ b/docs/_static/custom.js @@ -38,6 +38,107 @@ function getCodeDetailsBlocks() { return Array.from(document.querySelectorAll("details.uplt-code-details")); } +function initWhyCompareSliders() { + const isWhyPage = /\/why(?:\.html)?$|\/why\.htm$/.test( + (window.location.pathname || "").toLowerCase(), + ); + if (!isWhyPage) return; + + const cards = Array.from(document.querySelectorAll(".sd-card.uplt-why")); + for (let i = 0; i < cards.length - 1; i += 1) { + const mplCard = cards[i]; + const upltCard = cards[i + 1]; + if ( + !mplCard || + !upltCard || + !mplCard.classList.contains("uplt-why-mpl") || + !upltCard.classList.contains("uplt-why-uplt") + ) { + continue; + } + i += 1; + + const mplImg = mplCard.querySelector("img"); + const upltImg = upltCard.querySelector("img"); + if (!mplImg || !upltImg) { + continue; + } + + const slider = document.createElement("div"); + slider.className = "uplt-why-compare"; + + const body = document.createElement("div"); + body.className = "sd-card-body"; + slider.appendChild(body); + + const labels = document.createElement("div"); + labels.className = "uplt-compare-labels"; + const leftLabel = document.createElement("span"); + leftLabel.className = "uplt-label uplt-label-mpl"; + leftLabel.textContent = "Matplotlib"; + const rightLabel = document.createElement("span"); + rightLabel.className = "uplt-label uplt-label-uplt"; + rightLabel.textContent = "UltraPlot"; + labels.appendChild(leftLabel); + labels.appendChild(rightLabel); + body.appendChild(labels); + + const frame = document.createElement("div"); + frame.className = "uplt-compare-frame"; + frame.setAttribute( + "aria-label", + "Matplotlib and UltraPlot before/after comparison", + ); + + const mplClone = mplImg.cloneNode(true); + mplClone.className = "uplt-compare-img uplt-compare-mpl"; + frame.appendChild(mplClone); + + const upltClone = upltImg.cloneNode(true); + upltClone.className = "uplt-compare-img uplt-compare-uplt"; + frame.appendChild(upltClone); + + const handle = document.createElement("div"); + handle.className = "uplt-compare-handle"; + frame.appendChild(handle); + + const sliderInput = document.createElement("input"); + sliderInput.className = "uplt-compare-slider"; + sliderInput.type = "range"; + sliderInput.min = "0"; + sliderInput.max = "100"; + sliderInput.value = "50"; + sliderInput.setAttribute("aria-label", "Comparison reveal amount"); + + const onInput = () => { + frame.style.setProperty("--uplt-compare-position", `${sliderInput.value}%`); + }; + sliderInput.addEventListener("input", onInput); + onInput(); + + body.appendChild(frame); + body.appendChild(sliderInput); + + const probe = new Image(); + const onLoad = () => { + if (probe.naturalWidth && probe.naturalHeight) { + frame.style.aspectRatio = `${probe.naturalWidth} / ${probe.naturalHeight}`; + } + }; + probe.addEventListener("load", onLoad); + probe.src = mplImg.src; + if (probe.complete) { + onLoad(); + } + + mplCard.className = "sd-card uplt-why uplt-why-compare"; + mplCard.replaceChildren(); + mplCard.appendChild(body); + + upltCard.style.display = "none"; + } +} + function initScrollChromeFade() { const topBar = document.querySelector(".sy-head"); const leftBar = document.querySelector(".sy-lside"); @@ -711,6 +812,7 @@ document.addEventListener("DOMContentLoaded", function () { // Re-sync right TOC controls now that code wrappers exist. initShibuyaRightToc(); + initWhyCompareSliders(); const navLinks = document.querySelectorAll( ".wy-menu-vertical a.reference.internal",