Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
422fdcc
Add gallery infrastructure and examples
cvanelteren Jan 13, 2026
1a7932e
Fix kwarg error in diverging colormap example
cvanelteren Jan 13, 2026
fe36855
Added more intricate examples
cvanelteren Jan 13, 2026
5a399a5
Merge branch 'main' into add-gallery
cvanelteren Jan 13, 2026
1153861
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 13, 2026
acefe25
Update deps
cvanelteren Jan 13, 2026
4dd3d3a
Fix gallery filter and whats new toc
cvanelteren Jan 14, 2026
c4c04a7
Simplify whats new side toc
cvanelteren Jan 14, 2026
c37bb96
Fix whats new sidebar toc
cvanelteren Jan 14, 2026
f661dd6
Downgrade whats new headings in release import
cvanelteren Jan 14, 2026
9247b9d
Improve curved quiver example styling
cvanelteren Jan 14, 2026
6edf141
Fix typo in environment.yml
cvanelteren Jan 14, 2026
eb299ee
Merge branch 'main' into add-gallery
cvanelteren Jan 15, 2026
eaa88b3
Run image compare single thread
cvanelteren Jan 15, 2026
c6a3a52
Fix legend span inference with panels (#469)
cvanelteren Jan 15, 2026
92c37eb
Add gallery infrastructure and examples
cvanelteren Jan 13, 2026
1a33fbe
Update the examples
cvanelteren Jan 15, 2026
95cda8f
Update tests
cvanelteren Jan 15, 2026
bb264ba
Fix some tests
cvanelteren Jan 15, 2026
821e4d2
change alpha ridgeline
cvanelteren Jan 15, 2026
9fd5490
Fixed layout
cvanelteren Jan 15, 2026
03fb44b
Minor tweaks
cvanelteren Jan 15, 2026
9c3f526
Add ridge plot example
cvanelteren Jan 15, 2026
c02cdb4
Remove debug
cvanelteren Jan 15, 2026
799afcb
Remove double gallery from toc
cvanelteren Jan 15, 2026
ec92ca5
Dummy README to trick gallery formation
cvanelteren Jan 15, 2026
75926aa
Merge branch 'main' into add-gallery
cvanelteren Jan 15, 2026
202aee4
Remove left over code from merge
cvanelteren Jan 15, 2026
fef8a82
Consolidate css
cvanelteren Jan 15, 2026
7ae73c3
Merge branch 'main' into add-gallery
cvanelteren Jan 15, 2026
9405c48
Update 03_projections_features.py
cvanelteren Jan 15, 2026
69f4648
Merge branch 'main' into add-gallery
cvanelteren Jan 15, 2026
dcdc9c1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 15, 2026
262f57c
Adjusted curved quiver plot
cvanelteren Jan 15, 2026
b2d6cfe
Merge branch 'main' into add-gallery
cvanelteren Jan 15, 2026
72b07a1
Minor tweaks
cvanelteren Jan 16, 2026
132a350
Remove gallery header directly from index
cvanelteren Jan 16, 2026
8ac0cf7
Fix docstring formatting escapes
cvanelteren Jan 16, 2026
e7d3d12
Harden docs build hooks and rc links
cvanelteren Jan 16, 2026
98fbbb6
Fix docs roles and labels
cvanelteren Jan 16, 2026
0668eeb
Add missing normalizer label
cvanelteren Jan 16, 2026
b2fcb66
Merge branch 'main' into add-gallery
cvanelteren Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Checkout our examples
=====================

Below is a gallery showing random examples of what UltraPlot can do, for more examples checkout our extensive `docs <https://ultraplot.readthedocs.io>`_.
View the full gallery here: `Gallery <https://ultraplot.readthedocs.io/en/latest/gallery/index.html>`_.

.. list-table::
:widths: 33 33 33
Expand Down
58 changes: 58 additions & 0 deletions docs/_static/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,64 @@
max-height: calc(100vh - 150px);
}

.gallery-filter-controls {
margin: 1rem 0 2rem;
padding: 1rem 1.2rem;
border-radius: 16px;
background: linear-gradient(
135deg,
rgba(41, 128, 185, 0.08),
rgba(41, 128, 185, 0.02)
);
box-shadow:
0 10px 24px rgba(41, 128, 185, 0.18),
0 2px 6px rgba(41, 128, 185, 0.08);
}

.gallery-filter-bar {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 1rem;
}

.gallery-filter-button {
border: 1px solid #c5c5c5;
background-color: #ffffff;
color: #333333;
padding: 0.35rem 0.85rem;
border-radius: 999px;
font-size: 0.9em;
cursor: pointer;
transition:
background-color 0.2s ease,
color 0.2s ease,
border-color 0.2s ease;
}

.gallery-filter-button.is-active {
background-color: #2980b9;
border-color: #2980b9;
color: #ffffff;
}

.gallery-section-hidden {
display: none;
}

section#layouts > h1,
section#layouts > p,
section#legends-and-colorbars > h1,
section#legends-and-colorbars > p,
section#geoaxes > h1,
section#geoaxes > p,
section#plot-types > h1,
section#plot-types > p,
section#colors-and-cycles > h1,
section#colors-and-cycles > p {
display: none;
}

/* Responsive adjustments */
@media screen and (max-width: 1200px) {
.right-toc {
Expand Down
158 changes: 147 additions & 11 deletions docs/_static/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {

const tocList = toc.querySelector(".right-toc-list");
const tocContent = toc.querySelector(".right-toc-content");
const tocToggleBtn = toc.querySelector(
".right-toc-toggle-btn",
);
const tocToggleBtn = toc.querySelector(".right-toc-toggle-btn");

// Set up the toggle button
tocToggleBtn.addEventListener("click", function () {
Expand Down Expand Up @@ -118,8 +116,7 @@ document.addEventListener("DOMContentLoaded", function () {

link.textContent = headerText.trim();
link.className =
"right-toc-link right-toc-level-" +
header.tagName.toLowerCase();
"right-toc-link right-toc-level-" + header.tagName.toLowerCase();

item.appendChild(link);
tocList.appendChild(item);
Expand All @@ -141,9 +138,7 @@ document.addEventListener("DOMContentLoaded", function () {
let smallestDistanceFromTop = Infinity;

headerElements.forEach((header) => {
const distance = Math.abs(
header.getBoundingClientRect().top,
);
const distance = Math.abs(header.getBoundingClientRect().top);
if (distance < smallestDistanceFromTop) {
smallestDistanceFromTop = distance;
currentSection = header.id;
Expand All @@ -152,9 +147,7 @@ document.addEventListener("DOMContentLoaded", function () {

tocLinks.forEach((link) => {
link.classList.remove("active");
if (
link.getAttribute("href") === `#${currentSection}`
) {
if (link.getAttribute("href") === `#${currentSection}`) {
link.classList.add("active");
}
});
Expand All @@ -163,6 +156,149 @@ document.addEventListener("DOMContentLoaded", function () {
}
});

document.addEventListener("DOMContentLoaded", function () {
const galleryRoot = document.querySelector("#ultraplot-gallery");
if (galleryRoot) {
const gallerySections = [
"layouts",
"legends-and-colorbars",
"geoaxes",
"plot-types",
"colors-and-cycles",
];
gallerySections.forEach((sectionId) => {
const heading = document.querySelector(
`section#${sectionId} > h1, section#${sectionId} > h2`,
);
if (heading) {
heading.classList.add("no-toc");
}
});
}

const thumbContainers = Array.from(
document.querySelectorAll(".sphx-glr-thumbcontainer"),
);
if (thumbContainers.length < 6) {
return;
}

const topicMap = {
layouts: { label: "Layouts", slug: "layouts" },
"legends and colorbars": {
label: "Legends & Colorbars",
slug: "legends-colorbars",
},
geoaxes: { label: "GeoAxes", slug: "geoaxes" },
"plot types": { label: "Plot Types", slug: "plot-types" },
"colors and cycles": { label: "Colors", slug: "colors" },
};

const topics = [];
const topicOrder = new Set();
const originalSections = new Set();

function normalize(text) {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, "")
.replace(/\s+/g, " ")
.trim();
}

thumbContainers.forEach((thumb) => {
const section = thumb.closest("section");
const heading = section ? section.querySelector("h1, h2") : null;
const key = heading ? normalize(heading.textContent || "") : "";
const info = topicMap[key] || { label: "Other", slug: "other" };
thumb.dataset.topic = info.slug;
if (section) {
originalSections.add(section);
}
if (!topicOrder.has(info.slug) && info.slug !== "other") {
topicOrder.add(info.slug);
topics.push(info);
}
});

if (topics.length === 0) {
return;
}

const firstSection = thumbContainers[0].closest("section");
const parent =
(firstSection && firstSection.parentNode) ||
document.querySelector(".rst-content");
if (!parent) {
return;
}

const controls = document.createElement("div");
controls.className = "gallery-filter-controls";

const filterBar = document.createElement("div");
filterBar.className = "gallery-filter-bar";

function makeButton(label, slug) {
const button = document.createElement("button");
button.type = "button";
button.className = "gallery-filter-button";
button.textContent = label;
button.dataset.topic = slug;
return button;
}

const buttons = [
makeButton("All", "all"),
...topics.map((topic) => makeButton(topic.label, topic.slug)),
];

const counts = {};
thumbContainers.forEach((thumb) => {
const topic = thumb.dataset.topic || "other";
counts[topic] = (counts[topic] || 0) + 1;
});
counts.all = thumbContainers.length;

buttons.forEach((button) => {
const topic = button.dataset.topic;
const count = counts[topic] || 0;
button.textContent = `${button.textContent} (${count})`;
filterBar.appendChild(button);
});

const unified = document.createElement("div");
unified.className = "sphx-glr-thumbnails gallery-unified";
thumbContainers.forEach((thumb) => unified.appendChild(thumb));

controls.appendChild(filterBar);
controls.appendChild(unified);
parent.insertBefore(controls, firstSection);

originalSections.forEach((section) => {
section.classList.add("gallery-section-hidden");
});
document.body.classList.add("gallery-filter-active");

function setFilter(slug) {
buttons.forEach((button) => {
button.classList.toggle("is-active", button.dataset.topic === slug);
});
thumbContainers.forEach((thumb) => {
const matches = slug === "all" || thumb.dataset.topic === slug;
thumb.style.display = matches ? "" : "none";
});
}

buttons.forEach((button) => {
button.addEventListener("click", () => {
setFilter(button.dataset.topic);
});
});

setFilter("all");
});

// Debounce function to limit scroll event firing
function debounce(func, wait) {
let timeout;
Expand Down
47 changes: 44 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ def __getattr__(self, name):

# Print available system fonts
from matplotlib.font_manager import fontManager
from sphinx_gallery.sorting import ExplicitOrder, FileNameSortKey


def _reset_ultraplot(gallery_conf, fname):
"""
Reset UltraPlot rc state between gallery examples.
"""
try:
import ultraplot as uplt
except Exception:
return
uplt.rc.reset()


# -- Project information -------------------------------------------------------
# The basic info
Expand Down Expand Up @@ -144,6 +157,7 @@ def __getattr__(self, name):
"sphinx_copybutton", # add copy button to code
"_ext.notoc",
"nbsphinx", # parse rst books
"sphinx_gallery.gen_gallery",
]


Expand All @@ -165,6 +179,11 @@ def __getattr__(self, name):
"_templates",
"_themes",
"*.ipynb",
"gallery/**/*.codeobj.json",
"gallery/**/*.ipynb",
"gallery/**/*.md5",
"gallery/**/*.py",
"gallery/**/*.zip",
"**.ipynb_checkpoints" ".DS_Store",
"trash",
"tmp",
Expand Down Expand Up @@ -290,6 +309,28 @@ def __getattr__(self, name):

nbsphinx_execute = "auto"

# Sphinx gallery configuration
sphinx_gallery_conf = {
"doc_module": ("ultraplot",),
"examples_dirs": ["examples"],
"gallery_dirs": ["gallery"],
"filename_pattern": r"^((?!sgskip).)*$",
"min_reported_time": 1,
"plot_gallery": "True",
"reset_modules": ("matplotlib", "seaborn", _reset_ultraplot),
"subsection_order": ExplicitOrder(
[
"examples/layouts",
"examples/legends_colorbars",
"examples/geo",
"examples/plot_types",
"examples/colors",
]
),
"within_subsection_order": FileNameSortKey,
"nested_sections": False,
}

# The name of the Pygments (syntax highlighting) style to use.
# The light-dark theme toggler overloads this, but set default anyway
pygments_style = "none"
Expand All @@ -309,13 +350,11 @@ def __getattr__(self, name):
# html_theme = "sphinx_rtd_theme"
html_theme_options = {
"logo_only": True,
"display_version": False,
"collapse_navigation": True,
"navigation_depth": 4,
"prev_next_buttons_location": "bottom", # top and bottom
"includehidden": True,
"titles_only": True,
"display_toc": True,
"sticky_navigation": True,
}

Expand All @@ -330,7 +369,9 @@ def __getattr__(self, name):
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
# html_sidebars = {}
html_sidebars = {
"gallery/index": ["globaltoc.html", "searchbox.html"],
}

# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
Expand Down
6 changes: 6 additions & 0 deletions docs/examples/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UltraPlot Gallery
=================

Curated examples that highlight what UltraPlot does beyond base Matplotlib:
complex layouts, advanced legends and colorbars, GeoAxes, and specialized plot types.
Each script renders a publication-style figure and becomes a gallery entry.
Loading