chore(palette): migrate plotly impls from Okabe-Ito to imprint#7781
Conversation
Positional hex replacement across 139 plotly impls with light+dark renders, moving them from Okabe-Ito + variant-D to imprint. Mirrors the same pattern as #7776 / #7779 / #7780. Proactive semantic-anchor fixes for 13 plotly impls where slot-1 (now lavender) or slot-5 (now red) carried explicit meaning: - bar-diverging NEGATIVE_COLOR → red - candlestick-volume COLOR_DOWN → red - gauge-basic ZONE_LOW/MID → red/amber traffic-light - indicator-ema GOLDEN_CLR → amber (was ochre after swap) - indicator-macd SIGNAL_COLOR → ochre (categorical contrast) - indicator-rsi overbought 70 → red (line + label) - kagi-basic YIN_COLOR → red - ohlc-bar DOWN_COLOR → red - point-and-figure-basic COLOR_O → red - renko-basic BEARISH → red - shap-waterfall POS_COLOR → red (vs blue NEG) - slope-basic COLOR_DOWN → red - waterfall-basic COLOR_NEGATIVE → red Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Bulk positional palette migration of 139 Plotly implementations from Okabe-Ito / variant-D to the canonical imprint palette defined in core/palette.py, mirroring the matplotlib (#7776), seaborn (#7779) and plotnine (#7780) migrations. Includes 13 hand-picked semantic-anchor fixes (red/amber/green) for specs where the lavender at slot 1 would have broken meaning (gauges, candlesticks, indicators, waterfalls, slope/diverging bars, etc.). Metadata YAMLs and rendered PNGs are intentionally not touched here — they are handled by the post-merge Stage B render step.
Changes:
- Positional hex substitution
#D55E00 → #C475FD,#0072B2 → #4467A3,#CC79A7 → #BD8233,#E69F00 → #AE3030,#56B4E9 → #2ABCCD,#F0E442 → #954477(plus the variant-D mappings formap-marker-clustered,line-stock-comparison,bar-drilldown,dashboard-synchronized-crosshair,drawdown-basic,map-drilldown-geographic). - Rename
OKABE_ITO/ANYPLOT_PALETTEconstants toIMPRINT. - Targeted semantic fixes (red/amber/green) in 13 specs called out in the description.
Reviewed changes
Copilot reviewed 139 out of 139 changed files in this pull request and generated 13 comments.
Show a summary per file
Given the sheer number of files (~95 plotly impls in the diff), the table below groups them by the change pattern rather than listing each file individually.
| File | Description |
|---|---|
plots/*/implementations/python/plotly.py (categorical-list specs, ~70 files such as wordcloud-basic, waffle-basic, treemap-basic, radar-basic, scatter-matrix, histogram-stacked, bar-stacked*, line-multi, polar-*, subplot-*, network-*, dendrogram-radial, manhattan-gwas, circos-basic, gantt-basic, area-stacked, alluvial-basic, …) |
Rename OKABE_ITO → IMPRINT (or update inline palette literals) and remap slot hexes to imprint. |
plots/{bar-diverging,candlestick-volume,gauge-basic,indicator-ema,indicator-macd,indicator-rsi,kagi-basic,ohlc-bar,point-and-figure-basic,renko-basic,shap-waterfall,slope-basic,waterfall-basic}/implementations/python/plotly.py |
Semantic-anchor remapping (red/amber/green/ochre) so semantic roles survive the slot-1→lavender shift. |
plots/{bar-drilldown,line-stock-comparison,map-marker-clustered,dashboard-synchronized-crosshair,drawdown-basic,map-drilldown-geographic}/implementations/python/plotly.py |
variant-D → imprint remapping (in addition to the Okabe-Ito mapping). |
plots/{windrose-basic,maze-circular,contour-density}/implementations/python/plotly.py |
Partial substitution inside hand-tuned sequential ramps / accent literals. |
plots/{sunburst-basic,area-cumulative-flow,venn-basic,venn-labeled-items,sankey-basic,radar-basic,radar-multi}/implementations/python/plotly.py |
Categorical hex list migrated, but companion rgba(...) fill arrays / lighter-shade variants left on the old palette — flagged in review. |
plots/{bar-spine,gain-curve,precision-recall}/implementations/python/plotly.py |
Positional remap put semantic-red (#AE3030) into non-semantic roles ("On Trial", "Perfect model", PR secondary line) — flagged in review. |
| "#C475FD", # Sales — Okabe-Ito #2 | ||
| "#4467A3", # Marketing — Okabe-Ito #3 | ||
| "#BD8233", # Operations — Okabe-Ito #4 | ||
| "#00B589", # Backend — lighter green | ||
| "#009E73", # Frontend — base green | ||
| "#007A58", # DevOps — darker green | ||
| "#F07030", # Enterprise — lighter vermillion | ||
| "#D55E00", # SMB — base vermillion | ||
| "#C475FD", # SMB — base vermillion | ||
| "#2090CC", # Digital — lighter blue | ||
| "#0072B2", # Brand — base blue | ||
| "#4467A3", # Brand — base blue | ||
| "#DD99C0", # HR — lighter pink | ||
| "#CC79A7", # Finance — base pink | ||
| "#BD8233", # Finance — base pink |
| FILL_COLORS = [ | ||
| "rgba(0,158,115,0.80)", # #009E73 Done | ||
| "rgba(213,94,0,0.80)", # #D55E00 Testing | ||
| "rgba(0,114,178,0.80)", # #0072B2 Development | ||
| "rgba(204,121,167,0.80)", # #CC79A7 Analysis | ||
| "rgba(230,159,0,0.80)", # #E69F00 Backlog | ||
| "rgba(213,94,0,0.80)", # #C475FD Testing | ||
| "rgba(0,114,178,0.80)", # #4467A3 Development | ||
| "rgba(204,121,167,0.80)", # #BD8233 Analysis | ||
| "rgba(230,159,0,0.80)", # #AE3030 Backlog | ||
| ] | ||
| LINE_COLORS = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00"] | ||
| LINE_COLORS = ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030"] |
| IMPRINT = ["#009E73", "#C475FD", "#4467A3"] | ||
| fill_colors = ["rgba(0,158,115,0.45)", "rgba(213,94,0,0.45)", "rgba(0,114,178,0.45)"] |
| CIRCLE_COLORS = ["#009E73", "#C475FD", "#4467A3"] | ||
| CIRCLE_FILLS = ["rgba(0,158,115,0.26)", "rgba(213,94,0,0.26)", "rgba(0,114,178,0.26)"] |
| IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233"] | ||
| SOURCE_RGBA = ["rgba(0,158,115,0.4)", "rgba(213,94,0,0.4)", "rgba(0,114,178,0.4)", "rgba(204,121,167,0.4)"] |
| BRAND = "#009E73" # First series — always | ||
| BASELINE = "#888888" # Neutral for reference | ||
| PERFECT = "#E69F00" # Orange for perfect model | ||
| PERFECT = "#AE3030" # Orange for perfect model |
| # Okabe-Ito palette | ||
| BRAND = "#009E73" # Position 1, first series | ||
| SECONDARY = "#E69F00" # Position 5, orange | ||
| SECONDARY = "#AE3030" # Position 5, orange |
| y=[0.0], | ||
| mode="markers", | ||
| marker={"symbol": "star", "size": 20, "color": "#F0E442", "line": {"color": ACCENT, "width": 2}}, | ||
| marker={"symbol": "star", "size": 20, "color": "#954477", "line": {"color": ACCENT, "width": 2}}, |
| speed_bins = [0, 3, 6, 9, 12, np.inf] | ||
| speed_labels = ["0-3 m/s", "3-6 m/s", "6-9 m/s", "9-12 m/s", ">12 m/s"] | ||
| speed_colors = ["#4A90E2", "#0072B2", "#FFD43B", "#FF9F40", "#FF5252"] | ||
| speed_colors = ["#4A90E2", "#4467A3", "#FFD43B", "#FF9F40", "#FF5252"] |
| IMPRINT = [ | ||
| "#009E73", # bluish green (brand) | ||
| "#D55E00", # vermillion | ||
| "#0072B2", # blue | ||
| "#CC79A7", # reddish purple | ||
| "#E69F00", # orange | ||
| "#56B4E9", # sky blue | ||
| "#F0E442", # yellow | ||
| "#C475FD", # vermillion | ||
| "#4467A3", # blue | ||
| "#BD8233", # reddish purple | ||
| "#AE3030", # orange | ||
| "#2ABCCD", # sky blue | ||
| "#954477", # yellow |
Copilot caught a pattern Stage A's hex-literal regex doesn't reach:
inline `rgba(r,g,b,a)` triples carry the same Okabe-Ito colors but
escape the migration. The result was outline/fill mismatches in
charts where the stroke is a named hex but the fill is an rgba()
literal. Patched in 6 files:
- area-cumulative-flow FILL_COLORS rgba ↔ LINE_COLORS hex
- venn-basic circle stroke vs fill
- venn-labeled-items circle stroke vs fill
- sankey-basic IMPRINT node colors vs SOURCE_RGBA ribbons
- radar-basic line vs polygon fillcolor
- radar-multi line vs polygon fillcolor
Plus 6 more semantic refinements:
- sunburst-basic regenerate per-family child shades from new base hex
(old shades were lighter Okabe-Ito tints, no longer
related to the new imprint bases)
- bar-spine "On Trial" was migrated to imprint red (semantic bad),
"Cancelled" to lavender (neutral) — flipped: warning
is now amber, cancelled is red
- gain-curve PERFECT line → blue (red is reserved for semantic bad;
a reference line for the ideal model shouldn't read
as a failure indicator)
- precision-recall SECONDARY (no-skill reference) → ochre, same reasoning
- maze-circular center "treasure" star → amber, restores the
high-luminance accent the original yellow had
- windrose-basic speed bins reordered to cyan → blue → green → amber →
red so the cool→warm intensity ramp is monotonic again
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous commit accidentally deleted two committed plot-{light,dark}.html
files under plots/network-directed/implementations/python/. They were
swept up by the Stage B savefig fallback when the seaborn background
run touched that spec — the fallback assumed any plot-*.html sitting next
to the impl was its own output and moved it into .regen-preview/ (where
it then got rmtree'd).
Restore the two files and tighten the fallback: skip the move when the
stray file is git-tracked. Tracked files are pre-existing artifacts from
old daily-regen passes (typically shared across all impls in the same
spec directory), not output from the current render.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233"] | ||
| FILL_COLORS = ["rgba(0,158,115,0.18)", "rgba(213,94,0,0.18)", "rgba(0,114,178,0.18)", "rgba(204,121,167,0.18)"] |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Copilot's second review pass on this PR caught one more file with the outline/fill rgba mismatch (swarm-basic). A grep for any remaining Okabe-Ito or variant-D RGB triples inside rgba(...) literals across the changed plotly set turned up five more: area-stacked-confidence, frequency-polygon-basic, indicator-rsi, skewt-logp-atmospheric, timeseries-forecast-uncertainty. Stage A's hex-literal regex doesn't reach rgba(r,g,b,a); this is a manual cleanup over the affected files using the same positional slot mapping. Will fold the rgba pattern into scripts/migrate_to_imprint.py before running the remaining library passes so this stops recurring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The seaborn Stage B background run was still using the pre-fix
script (subprocess loaded before the git-tracked-skip patch
landed) and ended up deleting two more committed plot-{light,dark}.html
files under plots/subplot-grid/implementations/python/ via the
same fallback path that already hit network-directed earlier.
Restored from HEAD~1. Killed the running background task and will
restart it now using the patched script so this stops recurring.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…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>
| OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7"] | ||
| FILL_COLORS = ["rgba(0,158,115,0.18)", "rgba(213,94,0,0.18)", "rgba(0,114,178,0.18)", "rgba(204,121,167,0.18)"] | ||
| IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233"] | ||
| FILL_COLORS = ["rgba(0,158,115,0.18)", "rgba(196, 117, 253,0.18)", "rgba(68, 103, 163,0.18)", "rgba(189, 130, 51,0.18)"] |
| C_DRY = "rgba(196, 117, 253,0.22)" if THEME == "light" else "rgba(196, 117, 253,0.38)" | ||
| C_MOIST = "rgba(68, 103, 163,0.22)" if THEME == "light" else "rgba(68, 103, 163,0.38)" |
| except Exception: | ||
| pass |
- Stage A rgba substitution now preserves the source spacing pattern on the alpha component instead of always producing "a, b, c,d" — consistent "a, b, c, d" output across files. - Backfill: normalized the 13 plotly files where the previous regex had left mixed-style "rgba(196, 117, 253,0.18)" tuples next to surrounding "rgba(196, 117, 253, 0.18)" style. - Stage B: narrow the `except Exception` swallowing git failures down to `FileNotFoundError` (the only realistic case — git not on PATH) so genuine programmer errors propagate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
## Summary - Positional hex + rgba replacement across **135 bokeh impls** with light+dark renders → imprint. - Stage A's rgba pass (added in #7781) catches the same outline/fill mismatch class that bit plotly, so this PR ships with that already clean. - Proactive **semantic-anchor fixes for 13 bokeh impls** (red/amber/green where slot-1 lavender broke meaning). - Drive-by: `squarify` added to `[plotting]` extra (was the last spec to fail Stage B during the seaborn pass — needed by `treemap-basic/seaborn.py`). ## Semantic fixes (proactive) bar-diverging, candlestick-volume, dashboard-metrics-tiles (traffic-light + UNFAVORABLE), gain-curve (perfect-line not red), gauge-basic, horizon-basic (red ramp restored), indicator-macd, kagi-basic, 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 135 bokeh impls → GCS 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
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
ruff check .+ format green🤖 Generated with Claude Code