Skip to content

feat(bokeh): implement map-route-path#7603

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/map-route-path/bokeh
May 21, 2026
Merged

feat(bokeh): implement map-route-path#7603
MarkusNeusinger merged 6 commits into
mainfrom
implementation/map-route-path/bokeh

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: map-route-path - python/bokeh

Implements the python/bokeh version of map-route-path.

File: plots/map-route-path/implementations/python/bokeh.py

Parent Issue: #3768


🤖 impl-generate workflow

github-actions Bot added 2 commits May 21, 2026 05:41
Regen from quality 91. Addressed:
- Canvas fixed to 3200x1800 (was 4800x2700) with toolbar_location=None
- Replaced export_png with Selenium CDP captureBeyondViewport screenshot
- Added full theme-adaptive chrome (INK, INK_SOFT, ELEVATED_BG tokens)
- Dark theme uses CartoDB Dark Matter tile; light uses CartoDB Positron
- Font sizes updated: 50pt title, 42pt axis labels, 34pt tick/legend labels
- Output filenames now theme-suffixed: plot-light.png, plot-dark.png
- Route path more directional (NE trend) with viridis waypoint gradient
- Start marker: #009E73, End marker: #D55E00 (Okabe-Ito positions 1 & 2)
- Grid alpha reduced to 0.06 (was 0.3) to not distract from basemap
- Title includes python language token per anyplot.ai format
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 21, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white (#FAF8F1) border surrounds a CartoDB Positron basemap (light teal/mint) with muted road and terrain detail. Title "Rocky Mountain Trail · map-route-path · python · bokeh · anyplot.ai" renders in near-black ink spanning ~85% of the plot width — expected for the long mandated format. X/Y axis labels ("Longitude", "Latitude") and geographic tick labels (~−105.7 to ~−105.63, ~40.345 to ~40.37) are clearly readable in dark INK/INK_SOFT. The #009E73 green route line (5px) traces 200 waypoints overlaid with Viridis256-colored dots (purple→teal→green→yellow) showing trail progression. A large green circle marks the start (lower-left); a large orange square marks the end (upper-right). Small top-right legend shows Start/End labels legibly. The route exhibits multiple self-intersecting loops from the oscillating meander function. All text is readable against the light background.

Dark render (plot-dark.png): Near-black (#1A1A17) border surrounds CartoDB Dark Matter basemap (very dark, near-pure black with faint gray roads). Title renders in light (#F0EFE8) text — clearly readable. Axis labels in light INK; tick labels in #B8B7B0 gray — readable, no dark-on-dark failures. Legend renders with ELEVATED_BG (#242420) fill and INK_SOFT label text — legible. Data colors are identical to the light render: #009E73 route line, Viridis256 gradient on waypoints, #D55E00 end marker. The darker basemap provides better contrast for the bright yellow/green viridis section. No dark-on-dark text failures detected. All text is readable against the dark background.

Score: 82/100

Category Score Max
Visual Quality 28 30
Design Excellence 10 20
Spec Compliance 14 15
Data Quality 12 15
Code Quality 10 10
Library Mastery 8 10
Total 82 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All sizes explicitly set (50pt title, 42pt axis labels, 34pt ticks/legend). Readable in both themes. Minor: legend text appears compact in top-right corner.
  • VQ-02: No Overlap (6/6) — No text overlaps anywhere; route line doesn't interfere with labels.
  • VQ-03: Element Visibility (5/6) — Route line and markers clearly visible. Viridis dots (size=12) adequate for 200 waypoints. Dark purple dots near start blend slightly with light basemap.
  • VQ-04: Color Accessibility (2/2) — Viridis is perceptually uniform and colorblind-safe; Okabe-Ito for categorical start/end markers.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed (3200×1800). Proper min_border reservations; basemap fills chart area well.
  • VQ-06: Axis Labels & Title (2/2) — "Longitude" and "Latitude" are descriptive geographic labels; title format correct.
  • VQ-07: Palette Compliance (2/2) — Route line #009E73 (Okabe-Ito Add workflow diagram for new prototype discovery #1); end marker #D55E00 (Okabe-Ito Add Claude Code GitHub Workflow #2); Viridis256 for continuous gradient; backgrounds #FAF8F1/#1A1A17; both theme chromes correct.

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (5/8) — Theme-appropriate basemap selection (CartoDB Positron/Dark Matter) is a deliberate aesthetic choice adding significant visual context. Viridis gradient + green route line + Okabe-Ito start/end markers shows intentional design layering. Above default but missing colorbar reduces sophistication.
  • DE-02: Visual Refinement (3/6) — Minimal grid (alpha=0.06) is appropriately restrained for a basemap overlay. Carefully set min_border values; legend styled with ELEVATED_BG. Moderate refinement.
  • DE-03: Data Storytelling (2/6) — Start/end markers communicate journey direction. Viridis gradient implies progression but without a colorbar cannot communicate the actual progression story. Self-intersecting route loops undermine the visual narrative of a coherent hiking journey.

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct geographic route path map with basemap and connected waypoints.
  • SC-02: Required Features (3/4) — Route line ✓, distinct start/end markers ✓, color gradient ✓, geographic basemap ✓. Missing: no ColorBar to make the viridis gradient interpretable as "time progression."
  • SC-03: Data Mapping (3/3) — Lat/lon correctly mapped via Web Mercator projection; all 200 waypoints shown.
  • SC-04: Title & Legend (3/3) — "Rocky Mountain Trail · map-route-path · python · bokeh · anyplot.ai" matches required format; Start/End legend correct.

Data Quality (12/15)

  • DQ-01: Feature Coverage (5/6) — Shows route path, start/end markers, gradient progression, basemap geographic context. Missing colorbar prevents full demonstration of the time/progression feature.
  • DQ-02: Realistic Context (3/5) — Rocky Mountain National Park context is plausible. However, the trail self-intersects 3+ times due to np.sin(10*pi*t) oscillations — no real GPS hiking track crosses its own path repeatedly like this.
  • DQ-03: Appropriate Scale (4/4) — Coordinates (40.343°N, 105.683°W) are accurate for Rocky Mountain National Park. 200 waypoints is appropriate for a smooth GPS track.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat sequential script: imports → data → figure → render → save.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports used: base64, os, time, pathlib, numpy, bokeh modules, selenium.
  • CQ-04: Code Elegance (2/2) — Appropriate complexity; CDP captureBeyondViewport is a valid workaround for the Selenium viewport gap.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.html and plot-{THEME}.png using current bokeh API.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource, figure(), add_tile(), add_layout() for title, mercator axis types — idiomatic bokeh geo patterns.
  • LM-02: Distinctive Features (4/5) — add_tile() with CartoDB tile providers and x_axis_type/y_axis_type='mercator' are genuinely distinctive bokeh geo features unavailable in matplotlib/seaborn/plotnine.

Score Caps Applied

  • None

Strengths

  • Bokeh tile map integration via add_tile() with theme-appropriate CartoDB Positron (light) and Dark Matter (dark) — a genuinely distinctive bokeh geo feature
  • Correct Web Mercator projection conversion (lat/lon → x/y) enabling accurate basemap alignment
  • Full theme-adaptive chrome: all text, tick, grid, and legend elements use INK/INK_SOFT tokens — both renders are clean
  • Good use of ColumnDataSource with explicit color arrays; proper min_border reservations prevent label clipping
  • CaptureScreenshot with captureBeyondViewport:true correctly handles the Selenium viewport gap

Weaknesses

  • Viridis waypoint gradient has no ColorBar — viewers cannot decode what purple-to-yellow encodes (distance? time? elevation?). Add a ColorBar mapped to waypoint index or timestamp.
  • Simulated route self-intersects 3+ times due to np.sin(10pit) and np.sin(7pit) creating Lissajous-like loops — no real GPS hiking trail crosses its own path repeatedly. Use a monotonically-offset meander (e.g. decaying sin amplitude, or a single-frequency low-amplitude meander that stays within a corridor).
  • DE-03 storytelling is incomplete without the colorbar: the gradient visually hints at progression but tells no decipherable story without a legend mapping colors to a variable.

Issues Found

  1. SC-02 / DE-03 / DQ-01 LOW: No ColorBar for the Viridis gradient
    • Fix: Add from bokeh.models import ColorBar, LinearColorMapper, create a LinearColorMapper over [0, n_points-1], configure a ColorBar, and attach it to the figure with p.add_layout(color_bar, 'right'). Label it "Trail Progression" or "Waypoint Index".
  2. DQ-02 LOW: Route self-intersects due to high-frequency sin meander
    • Fix: Reduce meander frequency so the trail looks like a natural ridge/valley path. E.g., replace np.sin(10 * np.pi * t) with np.sin(3 * np.pi * t) and limit amplitude to 0.002–0.003° so the trail stays within a narrow corridor without crossing itself.

AI Feedback for Next Attempt

Two changes will meaningfully improve this implementation: (1) Add a ColorBar for the Viridis gradient so the trail progression story becomes interpretable — use a LinearColorMapper over [0, n_points-1] and attach it to the right side of the figure, labeled "Trail Progression". (2) Fix the meander to avoid self-intersections — use lower-frequency sin terms (e.g., sin(3pit)) with smaller amplitude (≤0.002°) so the trail looks like a realistic switchback ridge path rather than Lissajous loops. These two changes will bring DE-03 and DQ-02 up significantly.

Verdict: REJECTED

@github-actions github-actions Bot added quality:82 Quality score 82/100 ai-rejected Quality not OK, triggers update labels May 21, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels May 21, 2026
Attempt 1/3 - fixes based on AI review
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 21, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white border (#FAF8F1) surrounding a CartoDB Positron basemap tile. A green route line (#009E73) traces a trail from the lower-left (SW) to upper-right (NE), overlaid with 200 viridis-gradient dots (deep purple at start → green mid-trail → yellow at end). A large green circle marks the start (lower-left, lat ≈ 40.343, lon ≈ −105.683) and a large orange square marks the end (upper-right, lat ≈ 40.370, lon ≈ −105.645). A viridis colorbar labeled "Trail Progress (%)" runs vertically on the right. The legend (top-right) shows "Start" and "End" entries with correct colors. Title "Rocky Mountain Trail · map-route-path · python · bokeh · anyplot.ai" in dark ink at top. Axis labels "Longitude" (x) and "Latitude" (y) visible. All text is readable against the light background — no light-on-light failures.

Dark render (plot-dark.png): Same layout on CartoDB Dark Matter basemap with a near-black border (#1A1A17). The route line, viridis dots, start marker, and end marker are pixel-for-pixel identical in color to the light render — only the basemap tile and chrome flip. Title, axis labels, tick labels, legend text, and colorbar labels all render in the correct light-ink tokens (#F0EFE8 / #B8B7B0), clearly readable against the dark background. No dark-on-dark text failures detected. The theme-switch from Positron to Dark Matter basemap is smooth and appropriate.

Both paragraphs are required. A review that only describes one render is invalid.

Score: 90/100

Category Score Max
Visual Quality 29 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 8 10
Total 90 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (50pt title, 42pt axis labels, 34pt ticks, 34pt legend, 28pt/30pt colorbar labels). All text readable in both themes. Minor: colorbar major labels at 28pt are slightly undersized relative to the 34pt tick labels elsewhere, creating a small inconsistency in the chrome hierarchy.
  • VQ-02: No Overlap (6/6) — No overlapping text elements. Legend and colorbar don't conflict. Route dots overlap each other by design (path density), not a layout failure.
  • VQ-03: Element Visibility (6/6) — Route line (width 5), waypoint dots (size 12), start/end markers (size 32) are all well-adapted to 200 waypoints. Size differentiation between waypoints and terminal markers is effective.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito for categorical elements, viridis for continuous gradient. Colorblind-safe throughout.
  • VQ-05: Layout & Canvas (4/4) — Plot fills ~75% of canvas. Balanced margins. Colorbar and legend well-placed. No wasted space.
  • VQ-06: Axis Labels & Title (2/2) — "Longitude" and "Latitude" are correctly descriptive for geographic coordinates.
  • VQ-07: Palette Compliance (2/2) — Route line uses #009E73 (Okabe-Ito pos 1), end marker uses #D55E00 (pos 2). Continuous waypoint gradient uses Viridis (correct for continuous data). Light background is #FAF8F1 (via border_fill_color); dark is #1A1A17. Both renders theme-correct.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — The CartoDB theme-aware basemap switching (Positron ↔ Dark Matter) is elegant and deliberate. Dual encoding (green connectivity line + viridis progression dots) shows intentional design thinking. Distinct start/end marker shapes (circle vs square) add clarity. Not quite FiveThirtyEight-level polish — no directional cues along the trail, and the green route line is visually overridden by the dots stacked on top.
  • DE-02: Visual Refinement (4/6) — Very subtle grid (alpha 0.06–0.09), well-themed colorbar and legend chrome. The outline/spine is retained (appropriate for a bounded map frame). Generous min_border reservations prevent clipping. Solid refinement, though spines could be softened further.
  • DE-03: Data Storytelling (4/6) — The viridis progression (dark purple → yellow) immediately communicates trail direction. Start/end markers create clear focal anchors. Route shape suggests a real terrain-following path. Visual hierarchy guides the eye along the journey from SW to NE.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: route path map with connected waypoints on geographic basemap.
  • SC-02: Required Features (4/4) — Sequential waypoint connection ✓, distinct start/end markers with different shapes ✓, viridis color gradient along path ✓, geographic basemap (CartoDB) ✓, HTML interactive output ✓. Direction arrows listed as optional in spec; omission is acceptable.
  • SC-03: Data Mapping (3/3) — Longitude → X (Mercator), Latitude → Y (Mercator); all 200 waypoints visible; correct geographic orientation.
  • SC-04: Title & Legend (3/3) — Title "Rocky Mountain Trail · map-route-path · python · bokeh · anyplot.ai" matches {Descriptive Title} · {spec-id} · {language} · {library} · anyplot.ai. Legend labels "Start" and "End" match the markers.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all plot-type features: smooth connected path, progression gradient, distinct terminal markers, geographic basemap context, colorbar scale.
  • DQ-02: Realistic Context (5/5) — Rocky Mountain National Park hiking trail is a real, compelling, neutral scenario. Coordinates (~40.34°N, ~105.68°W) are geographically accurate for RMNP.
  • DQ-03: Appropriate Scale (4/4) — Trail spans ~4 km east and ~2.7 km north — plausible for a hiking segment. Lat/lon values are in the correct RMNP range. Meander amplitude is realistic for trail GPS data.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat: sys.path fix → theme tokens → data generation → figure → layers → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) ✓.
  • CQ-03: Clean Imports (2/2) — All imports used: base64 (CDP decode), os, sys, time (JS render wait), Path, numpy, bokeh.io/models/palettes/plotting, selenium.
  • CQ-04: Code Elegance (2/2) — sys.path fix for the bokeh.py shadow is documented and correct. captureBeyondViewport: True CDP approach elegantly captures the full canvas. Appropriate complexity.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.html + plot-{THEME}.png for both themes ✓.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource, LinearColorMapper, ColorBar, Title layout object, add_layout(..., "above"), add_tile(...) — all idiomatic Bokeh patterns for geographic visualization.
  • LM-02: Distinctive Features (4/5) — Theme-aware tile switching (CartoDB Positron vs CartoDB Dark Matter) based on ANYPLOT_THEME is distinctively Bokeh. LinearColorMapper + ColorBar with full chrome theming is Bokeh-specific. The Page.captureScreenshot CDP command with captureBeyondViewport demonstrates deep library-ecosystem knowledge.

Score Caps Applied

  • None

Strengths

  • Theme-aware CartoDB basemap switching (Positron for light, Dark Matter for dark) is elegant and fully automatic based on ANYPLOT_THEME
  • Dual encoding — green route line for connectivity + viridis gradient dots for progression — is intentional and effective
  • Full chrome token coverage: title, axis labels, ticks, legend, colorbar all use INK/INK_SOFT tokens throughout both themes
  • Geographically accurate RMNP coordinates with plausible trail meander and realistic scale
  • captureBeyondViewport: True CDP approach correctly captures the full 3200×1800 canvas

Weaknesses

  • Colorbar major labels at 28pt are slightly smaller than the main tick labels at 34pt — a minor chrome hierarchy inconsistency; unify to 34pt for perfect balance
  • The green route line (#009E73) is visually overridden by the viridis dots stacked on top; consider drawing the dots first (or reducing dot alpha slightly) so the green line remains visible as a separate layer
  • DE-01 held back (5/8): no directional arrows along the trail path and no distance markers — adding even optional direction glyphs would elevate the storytelling

AI Feedback for Next Attempt

Implementation is publication-quality. If regeneration is triggered: unify colorbar label size to 34pt (matching tick labels), draw waypoint dots before the route line so the green connectivity line stays visible, and optionally add a few direction arrow segments (using Bokeh's segment + triangle glyphs) every N waypoints to indicate travel direction.

Verdict: APPROVED

@github-actions github-actions Bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge and removed quality:82 Quality score 82/100 labels May 21, 2026
@MarkusNeusinger MarkusNeusinger merged commit 2185fb6 into main May 21, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/map-route-path/bokeh branch May 21, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant