chore(palette): migrate matplotlib impls from Okabe-Ito to imprint#7776
Merged
Conversation
Positional hex replacement across 137 matplotlib impls that already ship light+dark renders. Code-only — metadata YAMLs are untouched and will refresh on the next regular daily-regen cycle. Images are not regenerated in this PR; they will be re-rendered locally and pushed to GCS production immediately after merge via the companion script. Scope filter (per metadata YAML): - include: preview_url_light AND preview_url_dark both populated - skip: single-theme impls (handled by daily-regen rotation) - skip: specs without an existing matplotlib impl (no new ones created) Mapping is positional slot-to-slot, deterministic, idempotent: - Okabe-Ito #D55E00 #0072B2 #CC79A7 #E69F00 #56B4E9 #F0E442 - variant-D #9418DB #B71D27 #16B8F3 #99B314 #D359A7 #BA843E both collapse into the imprint 8-hue pool defined in core/palette.py. OKABE_ITO / ANYPLOT_PALETTE constants are renamed to IMPRINT in the same file when present. Drive-by: removes a duplicate per-file-ignores entry in pyproject.toml that was breaking ruff parsing on these files. New scripts (used to drive this and the remaining ~1.2k impls): - scripts/migrate_to_imprint.py deterministic hex replace - scripts/migrate_render_and_upload.py local render + GCS upload Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR accelerates the palette unification effort by mechanically migrating existing dual-theme matplotlib implementations from legacy Okabe-Ito / variant-D hex literals to the canonical imprint palette (as defined in core/palette.py), without going through full daily regen. It also adds two standalone scripts to drive the migration and fixes a Ruff config parsing issue.
Changes:
- Add Stage A/Stage B migration scripts to (A) rewrite palette hex literals in-place and (B) re-render + upload light/dark assets to GCS.
- Replace legacy palette hex codes/constants with imprint equivalents across the touched matplotlib implementations.
- Remove a duplicate Ruff per-file-ignores entry in
pyproject.toml.
Reviewed changes
Copilot reviewed 140 out of 140 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/migrate_to_imprint.py | Stage A script to rewrite legacy palette hex literals/constants to imprint using a deterministic mapping. |
| scripts/migrate_render_and_upload.py | Stage B script to re-render light/dark previews and upload/promote artifacts in GCS. |
| pyproject.toml | Removes duplicate Ruff per-file-ignores entry (fixes config parsing). |
| plots/wordcloud-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/windrose-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/waterfall-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/waffle-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/voronoi-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/volcano-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/violin-swarm/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/violin-split/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/violin-grouped-swarm/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/venn-labeled-items/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/venn-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/upset-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/treemap-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/timeseries-forecast-uncertainty/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/timeseries-decomposition/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/timeline-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/swarm-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/sunburst-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/subplot-mosaic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/strip-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/streamgraph-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/spectrum-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/span-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/sn-curve-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/smith-chart-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/slope-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/skewt-logp-atmospheric/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/silhouette-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/shap-waterfall/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-text/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-regression-polynomial/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-regression-lowess/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-regression-linear/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-matrix/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-matrix-interactive/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-map-geographic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-embedding/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-categorical/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/scatter-animated-controls/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/roc-curve/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/renko-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/radar-multi/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/radar-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/qq-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/polar-scatter/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/polar-line/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/polar-bar/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/point-and-figure-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/phase-diagram/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/pdp-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/parliament-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/parallel-categories-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/ohlc-bar/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-weighted/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-transport-static/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-hierarchical/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-force-directed/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-directed/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-bipartite/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/network-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/mosaic-categorical/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/maze-circular/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/marimekko-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/map-route-path/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/map-projections/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/map-marker-clustered/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/map-drilldown-geographic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/manhattan-gwas/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/logistic-regression/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/linked-views-selection/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-timeseries-rolling/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-styled/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-stock-comparison/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-stepwise/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-multi/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-loss-training/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-confidence/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/line-annotated-events/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/lift-curve/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/learning-curve-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/kagi-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/indicator-sma/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/indicator-rsi/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/indicator-macd/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/indicator-ema/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/indicator-bollinger/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/ice-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/horizon-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/hive-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-stepwise/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-stacked/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-returns-distribution/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-overlapping/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-kde/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-density/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/histogram-cumulative/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/hierarchy-toggle-view/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/heatmap-geographic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/heatmap-adjacency/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/gauge-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint (note: semantic zone colors need adjustment). |
| plots/gantt-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/gain-curve/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/funnel-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/frequency-polygon-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/forest-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/facet-grid/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/dumbbell-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/drawdown-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/dot-matrix-proportional/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/donut-nested/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/donut-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/dendrogram-radial/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/datamatrix-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/dashboard-synchronized-crosshair/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/dashboard-metrics-tiles/implementations/python/matplotlib.py | Replace legacy palette usage with imprint (note: semantic severity colors need adjustment). |
| plots/contour-decision-boundary/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/circos-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/circlepacking-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/cat-box-strip/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/candlestick-volume/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/calibration-curve/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/box-notched/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/box-grouped/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bland-altman-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-stacked/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-stacked-percent/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-stacked-labeled/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-spine/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-race-animated/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-grouped/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/bar-diverging/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/area-stacked/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/area-stacked-percent/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/area-stacked-confidence/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/area-cumulative-flow/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/andrews-curves/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
| plots/alluvial-basic/implementations/python/matplotlib.py | Replace legacy palette usage with imprint. |
Comment on lines
+115
to
+121
| def _rename_palette_constant(text: str) -> str: | ||
| """Rename common old palette variable names to IMPRINT (Python, R, Julia). | ||
|
|
||
| Only renames identifiers that look like a standalone palette constant | ||
| (whole-word match, all-caps name). Conservative — does not touch | ||
| inline comments or string literals. | ||
| """ |
Comment on lines
+10
to
+29
| """Stage B of the imprint migration: re-render light+dark images locally and | ||
| overwrite the GCS production bucket. | ||
|
|
||
| For every (spec, language, library) listed in ``.migration-list.json`` (or | ||
| discovered from a freshly-applied Stage A), this script: | ||
|
|
||
| 1. Renders ``plot-light.png`` and ``plot-dark.png`` in ``.regen-preview/{library}/`` | ||
| by running the impl with ``ANYPLOT_THEME`` set to each theme. | ||
| 2. Optimizes each PNG in place and emits responsive variants (400/800/1200 px, | ||
| PNG + WebP) via ``core.images``. | ||
| 3. Uploads the bundle to ``gs://anyplot-images/staging/{spec}/{language}/{library}/``. | ||
| 4. Promotes staging → ``gs://anyplot-images/plots/{spec}/{language}/{library}/`` | ||
| with public-read ACL, then deletes staging. | ||
|
|
||
| Resumable via ``.migration-progress.json`` — Ctrl-C and re-run to continue from | ||
| where you stopped. Skips items already marked ``done``. | ||
|
|
||
| Self-contained: does NOT depend on the regen module, so it works for R and | ||
| Julia impls too (the regen module is Python-only). | ||
| """ |
Comment on lines
+154
to
+156
| gcloud_ok = _check_command(["gcloud", "auth", "list", "--format=value(account)"]) | ||
| if not gcloud_ok: | ||
| notes.append("gcloud not authenticated → gcloud auth login") |
Comment on lines
21
to
+24
| # Okabe-Ito palette for waterfall categories | ||
| INCREASE_COLOR = "#009E73" # Brand green (position 1) | ||
| DECREASE_COLOR = "#D55E00" # Vermillion (position 2) | ||
| TOTAL_COLOR = "#0072B2" # Blue (position 3) | ||
| DECREASE_COLOR = "#C475FD" # Vermillion (position 2) | ||
| TOTAL_COLOR = "#4467A3" # Blue (position 3) |
Comment on lines
18
to
21
| # Okabe-Ito base colors for level-1 departments (positions 1–3) | ||
| OKABE_ITO = ["#009E73", "#D55E00", "#0072B2"] | ||
| OKABE_RGB = [tuple(int(c[j : j + 2], 16) / 255 for j in (1, 3, 5)) for c in OKABE_ITO] | ||
| IMPRINT = ["#009E73", "#C475FD", "#4467A3"] | ||
| OKABE_RGB = [tuple(int(c[j : j + 2], 16) / 255 for j in (1, 3, 5)) for c in IMPRINT] | ||
|
|
| ax.set_facecolor(PAGE_BG) | ||
|
|
||
| BRIDGE_COLOR = "#E69F00" # Okabe-Ito amber — distinct cross-department highlight | ||
| BRIDGE_COLOR = "#AE3030" # Okabe-Ito amber — distinct cross-department highlight |
Comment on lines
20
to
22
| # Status colors — semantic alarm indicators using Okabe-Ito positions 1, 5, 2 | ||
| STATUS_COLORS = {"good": "#009E73", "warning": "#E69F00", "critical": "#D55E00"} | ||
| STATUS_COLORS = {"good": "#009E73", "warning": "#AE3030", "critical": "#C475FD"} | ||
| STATUS_LABELS = {"good": "GOOD", "warning": "WARNING", "critical": "CRITICAL"} |
Comment on lines
22
to
25
| # Okabe-Ito zone colors (colorblind-safe red/yellow/green) | ||
| ZONE_BAD = "#D55E00" # vermillion | ||
| ZONE_WARN = "#E69F00" # orange | ||
| ZONE_BAD = "#C475FD" # vermillion | ||
| ZONE_WARN = "#AE3030" # orange | ||
| ZONE_GOOD = "#009E73" # bluish green (brand) |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
5 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
## Summary Follow-up to #7776. The positional Okabe-Ito → imprint swap broke charts where the old hex carried **semantic** meaning (red = bad, green = good, amber = warning), not just categorical separation. Slot 1 became lavender, which silently turned "bearish" / "negative" / "critical" / "decrease" markers into purple. Reaches for imprint **semantic anchors** (red `#AE3030`, amber `#DDCC77`, green `#009E73`) on the 12 matplotlib impls where the variable name or comment made the semantic intent explicit. Categorical, non-semantic uses of `#C475FD` (lavender) are left alone. ## Files touched | File | Fix | |---|---| | gauge-basic | `ZONE_BAD` → red, `ZONE_WARN` → amber | | dashboard-metrics-tiles | `STATUS_COLORS` warning → amber, critical → red | | kagi-basic | `COLOR_YIN` (bearish) → red | | point-and-figure-basic | `O_COLOR` (falling) → red | | horizon-basic | `neg_base` (negative) → red | | bar-diverging | negative bars + legend → red | | renko-basic | `BEARISH` → red | | slope-basic | `COLOR_DEC` → red | | waterfall-basic | `DECREASE_COLOR` → red | | shap-waterfall | `COLOR_POS` (positive SHAP) → red (against blue) | | indicator-macd | `NEGATIVE_COLOR` → red; `SIGNAL` → ochre (re-establishes contrast vs the red NEGATIVE bars) | | indicator-ema | `GOLDEN_COLOR` → green, `DEATH_COLOR` → red; short/long EMA → blue/ochre categorical | Also addresses three nits on the helper scripts from the same review round: - `migrate_to_imprint.py` — docstring for `_rename_palette_constant` no longer overstates the conservatism of the plain-regex rename - `migrate_render_and_upload.py` — module docstring matches the actual target-discovery flow (working tree or `--from-commit`), drops a stale reference to a never-implemented `.migration-list.json` - `migrate_render_and_upload.py` — pre-flight now also checks `gsutil version`, not just `gcloud auth list` ## What this PR doesn't do Comment rot in the other ~125 untouched matplotlib impls (e.g. comments still saying "Okabe-Ito vermillion" next to imprint hex codes) is **deferred** — those refresh naturally on the next daily-regen cycle. The image regeneration for **all** matplotlib impls (the 137 from #7776 + the 12 fixed here) hasn't run yet against GCS. That happens locally via `scripts/migrate_render_and_upload.py --from-commit <merge-sha> --library matplotlib` immediately after this PR merges. ## Test plan - [x] `ruff check .` + `ruff format --check .` green (matches CI) - [ ] CI green (lint + tests + frontend-tests) - [ ] Copilot triage - [ ] After merge: local Stage B for all 137+12 matplotlib impls → GCS production overwrite - [ ] Spot-check gauge-basic, dashboard-metrics-tiles, kagi-basic on anyplot.ai 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
## Summary Two small follow-ups uncovered while running Stage B of the imprint migration locally on the 137 matplotlib impls (PRs #7776 / #7777). **1. `scripts/migrate_render_and_upload.py` — savefig fallback** A handful of impls call `plt.savefig(os.path.join(script_dir, ...))` instead of plain `plt.savefig("plot-{theme}.png")`, so the PNG lands next to the impl file instead of inside `.regen-preview/{library}/`. Stage B now moves stray PNGs into the preview dir before checking for completeness — keeps the script compatible with these impls without rewriting them. Affected on the matplotlib pass: `area-cumulative-flow`, `bar-spine`, `histogram-stepwise`, `indicator-macd`, `line-stepwise`, `linked-views-selection`. Likely a few more across other Python libraries once we run those. **2. `pyproject.toml` — add cartopy / wordcloud / matplotlib-venn to `plotting` extra** Three matplotlib add-ons that some specs depend on (`map-projections` → cartopy, `wordcloud-basic` → wordcloud, `venn-basic` → matplotlib-venn). Without them, `uv sync --extra plotting` produces a venv that can't render those three. CI paths are unaffected — the per-library `lib-matplotlib` extra is intentionally minimal. ## Result on the 137 matplotlib impls After both fixes + a `--resume` rerun: **137 / 137 ✓** in GCS production. Without them the first run was 128 / 137 (the 9 failures above). ## Test plan - [x] `ruff check .` + `ruff format --check .` green (matches CI) - [ ] CI green (lint + tests + frontend-tests) - [ ] Copilot triage 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
## Summary - Positional hex replacement across **138 seaborn impls** that already ship light+dark renders, moving them from Okabe-Ito + variant-D to the canonical **imprint** palette in [core/palette.py](https://github.com/MarkusNeusinger/anyplot/blob/main/core/palette.py). Mirrors #7776 for matplotlib. - Includes proactive **semantic-anchor fixes for 11 seaborn impls** where slot-1 (now lavender) carried explicit meaning (red = bad/loss/bearish, amber = warning, green = good). Same pattern as #7777 but applied preemptively before Copilot's first review. - Picks up the `uv.lock` entries for cartopy / wordcloud / matplotlib-venn that were missing from #7778. - Adds `.migration-progress.json` to `.gitignore` (local-only Stage-B state file). ## Scope filter Per metadata YAML, only impls with **both** `preview_url_light` and `preview_url_dark` set are migrated. Single-theme impls are left to the regular daily-regen rotation. Specs without an existing seaborn impl don't get a new one. | Library | Migrated | Already imprint | Skip (single-theme) | |---|---:|---:|---:| | seaborn | **138** | 86 | 96 | ## Semantic fixes (proactive, 11 files) | File | Fix | |---|---| | bar-diverging | `LOSS_COLOR` → red | | candlestick-volume | `SECONDARY` (bear) → red | | dashboard-metrics-tiles | warning → amber, critical → red | | gauge-basic | `ZONE_LOW`/`MED` → red/amber traffic-light | | indicator-macd | `HIST_NEGATIVE` → red, `SIGNAL` → ochre | | kagi-basic | `color_yin` → red | | point-and-figure-basic | `BEAR_COLOR` → red | | renko-basic | `BEARISH` → red | | shap-waterfall | `COLOR_POS` → red (vs blue NEG) | | slope-basic | `COLOR_DECREASE` → red | | waterfall-basic | `ACCENT_RED` → red (was lavender despite the name) | ## What this PR doesn't do Image regen for the 138 seaborn impls hasn't run yet against GCS. That happens locally via `scripts/migrate_render_and_upload.py --from-commit <merge-sha> --library seaborn` immediately after this PR merges. ## Test plan - [x] `ruff check .` + `ruff format --check .` green - [x] Idempotency check (second Stage-A run on a sample spec = 0 changes) - [ ] CI green (lint + tests + frontend-tests) - [ ] Copilot triage (should be minimal — semantic bugs pre-fixed) - [ ] After merge: local Stage B for all 138 seaborn impls → GCS production overwrite - [ ] Spot-check gauge-basic, dashboard-metrics-tiles, candlestick-volume on anyplot.ai 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
## Summary - Positional hex replacement across **132 plotnine impls** with light+dark renders, moving them from Okabe-Ito + variant-D to **imprint**. Same pattern as #7776 (matplotlib) and #7779 (seaborn). - Includes proactive **semantic-anchor fixes for 11 plotnine impls** where slot-1 (now lavender) carried explicit meaning. Variable `ORANGE` in indicator-macd renamed to `OCHRE` so the name matches the actual imprint hex. ## Semantic fixes (proactive) | File | Fix | |---|---| | bar-diverging | "Negative" → red | | candlestick-volume | DOWN_COLOR → red | | dashboard-metrics-tiles | status warn → amber, critical → red | | gauge-basic | ZONE_BAD/WARN → red/amber traffic-light | | indicator-macd | ORANGE → OCHRE (var rename + #BD8233) | | kagi-basic | YIN_COLOR → red | | logistic-regression | FAIL_COLOR → red | | ohlc-bar | DOWN_COLOR → red | | point-and-figure-basic | O_COLOR → red | | renko-basic | BEARISH → red | | shap-waterfall | COLOR_POS → red (vs blue NEG) | ## Test plan - [x] `ruff check .` + `ruff format --check .` green - [ ] CI green - [ ] Copilot triage - [ ] After merge: Stage B for 132 plotnine impls → GCS production 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
…basic Extends scripts/migrate_to_imprint.py with an rgba(r,g,b,a) substitution pass: same positional Okabe-Ito / variant-D → imprint mapping, but matching ints inside `rgba(r, g, b, ...)` literals instead of `#RRGGBB`. Whitespace inside the tuple is tolerated. This is what we should have had from the start — the hex-only regex in PR #7776/#7779 missed every rgba() fill across plotly (and likely across bokeh + altair in upcoming passes). Without this, every plotly PR turned into "ship outline migration, Copilot finds rgba fill mismatches, manual cleanup". With it, the next library passes catch them on the first Stage-A run. The new pass also catches one plotly file the manual sweep missed — drawdown-basic uses `rgba(183,29,39,...)` which is variant-D's #B71D27 (not Okabe-Ito); now correctly migrated to imprint red rgb 174/48/48. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
## Summary - Positional hex replacement across **139 plotly impls** with light+dark renders → imprint. Mirrors #7776/#7779/#7780. - Proactive semantic-anchor fixes for **13 plotly impls** (red/amber/green where slot-1 lavender broke the meaning). ## Semantic fixes (proactive) bar-diverging, candlestick-volume, gauge-basic (traffic-light), indicator-ema (golden cross → amber), indicator-macd (signal → ochre for contrast), indicator-rsi (overbought 70 → red), kagi-basic, ohlc-bar, point-and-figure-basic, renko-basic, shap-waterfall, slope-basic, waterfall-basic. ## Test plan - [x] `ruff check .` + format green - [ ] CI green - [ ] Copilot triage - [ ] After merge: Stage B for 139 plotly impls → GCS 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MarkusNeusinger
added a commit
that referenced
this pull request
May 27, 2026
Positional hex + rgba replacement across 135 bokeh impls that already ship light+dark renders. Mirrors PRs #7776/#7779/#7780/#7781. Stage A now handles rgba(r,g,b,a) literals natively (added in #7781), so the outline/fill mismatch class that bit the plotly PR doesn't recur here. Proactive semantic-anchor fixes for 13 bokeh impls where slot-1 (now lavender) or slot-5 (now red) carried explicit meaning: - bar-diverging BRAND_NEG → red - candlestick-volume COLOR_DOWN → red - dashboard-metrics-tiles status warn→amber, critical→red, UNFAVORABLE→red - gain-curve SECONDARY → blue (perfect-model reference) - gauge-basic ZONE_LOW/MID → red/amber traffic-light - horizon-basic neg_colors → warm-red ramp (light→mid→dark red) - indicator-macd HIST_NEGATIVE → red - kagi-basic YIN_COLOR → red - point-and-figure-basic O_COLOR → red - renko-basic BEARISH_COLOR → red - shap-waterfall POS_COLOR → red (vs blue NEG) - slope-basic DECREASE_COLOR → red - waterfall-basic NEGATIVE → red Drive-by: add squarify to the [plotting] extra. It's required by `plots/treemap-basic/implementations/python/seaborn.py` and was the last spec to fail Stage B during the seaborn pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pyproject.toml— removes a duplicate per-file-ignores entry that was breaking ruff parsing on these files.Scope filter
Per metadata YAML, only impls with both
preview_url_lightandpreview_url_darkset are migrated. Single-theme impls are left to the regular daily-regen rotation (they're the oldest specs anyway). Specs without an existing matplotlib impl are not given a new one — that's still the job of the regular spec workflow.Stage-A dry-run distribution:
Color mapping (positional, deterministic)
Both pre-imprint palettes share
#009E73(brand green) with imprint, so series-index-0 is unchanged. The remaining slots collapse:#009E73#009E73#009E73(green, unchanged)#D55E00#9418DB#C475FD(lavender)#0072B2#B71D27#4467A3/#AE3030#CC79A7#16B8F3#BD8233/#4467A3#E69F00#99B314#AE3030/#99B314#56B4E9#D359A7#2ABCCD/#954477#F0E442#BA843E#954477/#BD8233OKABE_ITO/ANYPLOT_PALETTEconstants are renamed toIMPRINTin the same file when present.Why this PR (and not the daily-regen pipeline)
The daily-regen runs 10× per day and rotates over 327 specs — at the current cadence it would take weeks to unify all impls on imprint. Each regen also burns tokens on spec-polish + impl-generate + AI-review × 11 libraries, even though here we only swap hex codes. This is a one-shot fix that bypasses all of that.
Test plan
voronoi-basic / matplotlibruff check .+ruff format --check .green (matches CI)🤖 Generated with Claude Code