Skip to content

feat(plotly): implement bubble-map-geographic#7290

Merged
MarkusNeusinger merged 4 commits into
mainfrom
implementation/bubble-map-geographic/plotly
May 18, 2026
Merged

feat(plotly): implement bubble-map-geographic#7290
MarkusNeusinger merged 4 commits into
mainfrom
implementation/bubble-map-geographic/plotly

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: bubble-map-geographic - python/plotly

Implements the python/plotly version of bubble-map-geographic.

File: plots/bubble-map-geographic/implementations/python/plotly.py

Parent Issue: #3625


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 18, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 background. A world map with Natural Earth projection is displayed with beige/tan land (#E8E4D8) and soft blue ocean (#D0E4F0). Bubbles represent 30 major world cities, sized proportionally to population, and colored by region using the Okabe-Ito palette: Asia = #009E73 (greenish, largest cluster in East/South Asia), Europe = #D55E00 (vermillion), North America = #0072B2 (blue), South America = #CC79A7 (reddish purple), Africa = #E69F00 (orange), Oceania = #56B4E9 (sky blue). A region legend sits in the upper-left with an elevated-background box. A custom population-scale legend in the lower-left shows three reference circles (5M, 20M, 35M). Title at top reads "World City Populations · bubble-map-geographic · python · plotly · anyplot.ai" in dark ink. All text is clearly readable against the light background — no light-on-light issues detected.

Dark render (plot-dark.png): The same map renders on near-black #1A1A17 background, with dark land (#2E2E28) and dark-navy ocean (#1A2535). Data colors are identical to the light render — Asia bubbles are the same #009E73 green, Europe the same vermillion, etc. — only the chrome has flipped: title, legend text, and scale labels are now light-colored against the dark surface. Map frame is visible with lighter tones. Region legend and population-scale legend backgrounds use the elevated dark token (#242420). No dark-on-dark failures detected — all text is clearly legible against the near-black background. Brand green #009E73 reads well on the dark surface.

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

Score: 85/100

Category Score Max
Visual Quality 26 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 10 10
Library Mastery 7 10
Total 85 100

Visual Quality (26/30)

  • VQ-01: Text Legibility (7/8) — Title=28, legend title=20, legend=18, scale labels=15 all explicitly set; both themes fully readable. Minor: scale-legend labels at 15 are slightly small.
  • VQ-02: No Overlap (5/6) — Expected bubble crowding in the Asia cluster handled cleanly with 0.65 opacity; no text overlap anywhere.
  • VQ-03: Element Visibility (5/6) — Minimum size of 15 keeps small cities visible; transparency prevents the dense Asia cluster from becoming a solid blob.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe; color + size dual encoding reduces reliance on hue alone.
  • VQ-05: Layout & Canvas (3/4) — Map fills canvas well; size-legend circles appear slightly small at display scale.
  • VQ-06: Axis Labels & Title (2/2) — Descriptive title; geographic maps have no traditional axis labels.
  • VQ-07: Palette Compliance (2/2) — First series (Asia) = #009E73 ✓; Okabe-Ito order followed for all 6 regions ✓; backgrounds #FAF8F1/#1A1A17 ✓; data colors identical across both renders ✓.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above a configured default: theme-adaptive geographic color tokens (land, ocean, coast, country all flip with theme), Okabe-Ito palette applied correctly, and the manually-built population-scale legend shows design thought. Not yet at "clearly above defaults" (6) — typographic hierarchy could be stronger and the overall composition lacks a distinctive focal point.
  • DE-02: Visual Refinement (4/6) — Clean layout; white bubble edges add definition; transparency is well-chosen; elevated background boxes on legends are polished. Good refinement for a geo map (no traditional spines to remove).
  • DE-03: Data Storytelling (4/6) — Asia's megacity dominance is immediately apparent through the large clustered bubbles; the dual size+color encoding guides the reader. The population scale legend enables magnitude interpretation. Visual hierarchy through dramatic size variation is effective, though no city-name callouts or annotations anchor specific insights.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct bubble map using go.Scattergeo with size-encoded geographic markers.
  • SC-02: Required Features (4/4) — Area-proportional bubble sizing ✓, transparency 0.65 ✓, geographic basemap with country borders and coastlines ✓, size legend ✓, hover tooltips showing city name and population ✓.
  • SC-03: Data Mapping (3/3) — Lat/lon correctly mapped; population drives marker size; optional category (region) drives color.
  • SC-04: Title & Legend (3/3) — Title: "World City Populations · bubble-map-geographic · python · plotly · anyplot.ai" matches required format ✓; legend labels match region data ✓.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — 30 cities across all 6 inhabited continents with a wide population range (5.0M–37.4M); good size variation showcases the bubble map's encoding strength.
  • DQ-02: Realistic Context (5/5) — Real-world major-city populations; neutral, factual topic with no controversial elements.
  • DQ-03: Appropriate Scale (4/4) — Population values are factually accurate and proportionally correct for the chosen cities.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat linear flow: theme tokens → data → figure → style → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — os, numpy, pandas, plotly.graph_objects all used.
  • CQ-04: Code Elegance (2/2) — Clean region loop; manual size legend via paper-coordinate shapes is appropriately complex for the task.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png + plot-{THEME}.html using current plotly API ✓.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct use of go.Scattergeo with comprehensive geo layout dict; idiomatic hovertemplate with <extra></extra> to suppress trace name box.
  • LM-02: Distinctive Features (3/5) — Uses geographic projection (natural earth), showland/showocean/showcoastlines/showcountries, and paper-coordinate shapes for the size legend. These are distinctly plotly geo features, but the HTML interactivity is not fully leveraged (e.g., no custom click events or animation).

Score Caps Applied

  • None — no caps triggered.

Strengths

  • Complete spec compliance: all required features (size encoding, transparency, basemap, size legend, tooltips) are present and working.
  • Excellent theme adaptation: geographic chrome tokens (land, ocean, coast, country borders) flip correctly between light and dark themes, which is non-trivial for geo maps.
  • Clean, readable code with proper flat structure; size legend implementation using paper-coordinate shapes is elegant.
  • Okabe-Ito palette applied correctly with Asia as first series (#009E73); correct background tokens in both renders.
  • Population data is real-world accurate and the 30-city dataset shows clear size variation across continents.

Weaknesses

  • DE-01 (5/8): Design sophistication stops at "correctly configured" — the composition lacks a strong typographic focal point or any city-name labels for the largest bubbles (Tokyo, Delhi, Shanghai) that would elevate it toward publication quality.
  • LM-02 (3/5): Plotly's interactive distinctiveness is underused — the hover tooltip only shows city name and population; adding formatted multi-line tooltips (e.g., rank, region) or custom marker symbol variation would better showcase plotly's interactive strengths.
  • VQ-01 (7/8): Population-scale legend labels at font size 15 are slightly below the recommended 18px for secondary text at this canvas resolution.

Issues Found

  1. DE-01 LOW (5/8): Composition lacks a dominant focal point beyond size variation. The largest cities (Tokyo cluster) don't have explicit callouts or city-name labels.
    • Fix: Add city-name text labels for the top 5 most-populous cities positioned near their bubbles; this would both improve storytelling and push DE-01 toward 6–7.
  2. LM-02 MODERATE (3/5): Hover tooltips are minimal; plotly's interactive geo features are not showcased beyond basic hover.
    • Fix: Enrich hovertemplate to include population rank and region; consider using customdata for richer tooltip content.
  3. VQ-01 MINOR (7/8): Population scale label font size 15 is below the 18px recommended secondary-text size.
    • Fix: Increase scale legend annotation font from 15 → 18.

AI Feedback for Next Attempt

Add city-name text labels for the top 5–6 most-populous cities (Tokyo, Delhi, Shanghai, Dhaka, São Paulo, Mumbai) positioned adjacent to their bubbles — this is the single highest-impact improvement for both DE-01 and DE-03. Enrich the hovertemplate with population rank and a formatted population string (e.g., "#1 globally · 37.4M") to better leverage plotly's interactive strength (LM-02). Increase population-scale annotation font size from 15 → 18 (VQ-01). These three targeted fixes should push the score above 90.

Verdict: REJECTED

@github-actions github-actions Bot added quality:85 Quality score 85/100 ai-rejected Quality not OK, triggers update labels May 18, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels May 18, 2026
@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 18, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 surface — correct. A world map using the Natural Earth projection spans the canvas with beige land masses (#E8E4D8) and soft light-blue ocean (#D0E4F0). Bubble markers sized by city population appear across all continents: large green clusters dominate East/South Asia (Tokyo, Delhi, Shanghai, Mumbai in #009E73), several orange/vermillion dots mark Europe (Istanbul, Moscow) in #D55E00, blue markers denote North America in #0072B2, pink marks South America in #CC79A7, yellow-orange Africa (Cairo, Lagos) in #E69F00, and two small sky-blue dots represent Oceania in #56B4E9. All bubble colors follow Okabe-Ito order. The title "World City Populations · bubble-map-geographic · python · plotly · anyplot.ai" appears at top center in dark #1A1A17 ink at 28px, fully readable. The Region legend sits in the upper-left map area with dark text. A "Population scale" box with three reference circles (5M, 20M, 35M) occupies the lower-left corner. All text is clearly readable against the light background. Legibility verdict: PASS

Dark render (plot-dark.png): The plot renders on a near-black #1A1A17 surface — correct. Land masses render in dark charcoal (#2E2E28), ocean in dark navy (#1A2535), providing clear geographic distinction. The title appears in light #F0EFE8 text — readable. Data bubble colors are identical to the light render (same green Asia cluster, orange Europe, blue North America, etc.) — only the chrome flips. The Region legend text renders in lighter #B8B7B0 ink against the dark #242420 elevated background. The Population scale box also uses themed colors. No dark-on-dark text failures observed; all labels remain legible against the dark background. Legibility verdict: PASS

Both renders are theme-correct. Okabe-Ito data colors are identical across both themes.

Score: 86/100

Category Score Max
Visual Quality 28 30
Design Excellence 11 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 86 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All rendered text has explicitly set font sizes (title 28px, legend title 20px, legend text 18px, size annotations 15px). The 15px size-legend annotations fall just below the 16px minimum, minor deduction.
  • VQ-02: No Overlap (5/6) — East Asian cities physically overlap (Tokyo, Osaka, Seoul, Beijing, Shanghai all clustered), but this is geographically inherent. The 0.65 opacity and white borders handle it gracefully. No text collision observed.
  • VQ-03: Element Visibility (6/6) — All bubbles clearly visible, including the smallest Oceania cities (Sydney, Melbourne). The min_size=15 ensures no value disappears.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe. Adequate contrast between all six region colors and both map surfaces.
  • VQ-05: Layout & Canvas (4/4) — Map fills the landscape canvas well. Legends are well-placed in map corners. Margins appropriate.
  • VQ-06: Axis Labels & Title (2/2) — Descriptive title present. No axis labels needed for a geographic map — N/A.
  • VQ-07: Palette Compliance (2/2) — First series (Asia) = #009E73 ✓. Multi-series follows Okabe-Ito canonical order ✓. Background #FAF8F1 (light) / #1A1A17 (dark) ✓. Theme-adaptive chrome correct in both renders ✓.

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above the default 4: custom theme-adaptive geographic colors (land, ocean, coastline, country borders all themed for both surfaces), custom size legend with styled annotation box, proper Okabe-Ito implementation. However, falls short of "FiveThirtyEight-level" — no subtitle, no focal annotations, no visual emphasis on standout data points.
  • DE-02: Visual Refinement (3/6) — Slightly above default 2: white marker edges provide definition against both map surfaces, 0.65 opacity for overlap, themed legend boxes with ELEVATED_BG borders. Geographic maps offer limited chrome reduction opportunities (no axis spines), so refinement options are constrained.
  • DE-03: Data Storytelling (3/6) — Slightly above default 2: bubble size variation immediately conveys Asia's population dominance, and six distinct region colors allow instant multi-dimensional comparison. However, no annotations highlight the largest cities, no callout draws attention to the Asia cluster insight, and viewers must extract the narrative themselves.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: geographic bubble map with go.Scattergeo using Natural Earth projection.
  • SC-02: Required Features (4/4) — Area-proportional sizing (sqrt normalization + diameter mode) ✓, transparency (0.65) ✓, geographic context with country boundaries and coastlines ✓, size legend ✓, hover tooltips with city + population ✓.
  • SC-03: Data Mapping (3/3) — lat/lon correctly mapped to geographic coordinates, population mapped to bubble size, region mapped to color ✓.
  • SC-04: Title & Legend (3/3) — Title "World City Populations · bubble-map-geographic · python · plotly · anyplot.ai" matches required format ✓. Region legend labels match data ✓.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 30 real world cities spanning all inhabited continents, covering a wide population range (5M–37.4M). Both small and large cities present. Six regions with multiple members each demonstrate the categorical dimension.
  • DQ-02: Realistic Context (5/5) — Real-world world city populations — neutral, comprehensible, science/geography topic.
  • DQ-03: Appropriate Scale (4/4) — Population values (Tokyo 37.4M, Delhi 31.2M, Sydney 5.4M, etc.) match real-world data closely. Coordinates are accurate.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script: theme tokens → data → sizing calculation → plot → layout → size legend → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set (defensive; data is hardcoded). Fully deterministic output.
  • CQ-03: Clean Imports (2/2) — os, numpy, pandas, plotly.graph_objects — all used.
  • CQ-04: Code Elegance (2/2) — Clean, readable. sizemode="diameter" with sqrt-normalized values is the correct approach for area-proportional encoding.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html ✓.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct use of go.Scattergeo with hovertemplate, fig.update_layout() for geo configuration, fig.add_shape() and fig.add_annotation() for the custom size legend in paper coordinates. Idiomatic throughout.
  • LM-02: Distinctive Features (3/5) — Natural Earth geographic projection (Plotly-specific), interactive hover with formatted hovertemplate, HTML export alongside PNG, and the custom paper-coordinate size legend using fig.add_shape() circles. These features are Plotly-distinctive, though the usage is not exceptionally advanced.

Score Caps Applied

  • None — No caps apply. DE-01=5 > 2, DE-02=3 > 2, no VQ/SC/DQ zeros.

Strengths

  • Full spec compliance: all required features (size encoding, transparency, geographic context, size legend, hover tooltips) implemented correctly
  • Excellent theme-adaptive implementation: both renders pass legibility and color checks; geographic chrome (land, ocean, coast, country) is also theme-adaptive
  • Real, factually accurate world city data with good geographic distribution and population range
  • Correct area-proportional sizing (sqrt normalization + sizemode="diameter")

Weaknesses

  • DE-01/DE-03: No visual emphasis or callout on notable data points — the Asia population dominance is visually obvious but not reinforced by any annotation or focal treatment
  • DE-03: No subtitle or caption providing geographic insight (e.g., "Asia hosts 10 of the world's 15 largest cities")
  • VQ-01: Size legend annotation text at 15px is just below the 16px minimum for legend-level text

Issues Found

  1. DE-01/DE-03 MODERATE: No annotations or emphasis on standout cities (Tokyo/Delhi as the two largest). The plot displays data but doesn't guide the viewer to the key insight.
    • Fix: Add a subtle annotation callout for Tokyo and/or Delhi as the largest cities, or add a subtitle like "Asia accounts for 10 of the 15 largest cities"
  2. VQ-01 MINOR: Population scale annotation text at 15px is slightly below the 16px threshold.
    • Fix: Increase size legend annotation font size from 15 to 16px

AI Feedback for Next Attempt

This is a strong implementation that meets all spec requirements with correct theming. To push further, add visual storytelling: (1) annotate Tokyo and Delhi as the two standout data points with brief callouts, or add a subtitle summarizing the Asia dominance insight; (2) increase size legend annotation font to 16px. These are targeted, low-risk changes that would boost DE-03 from 3 to 4 and VQ-01 from 7 to 8.

Verdict: APPROVED

@github-actions github-actions Bot added quality:86 Quality score 86/100 ai-approved Quality OK, ready for merge and removed quality:85 Quality score 85/100 labels May 18, 2026
@MarkusNeusinger MarkusNeusinger merged commit a970bdc into main May 18, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/bubble-map-geographic/plotly branch May 18, 2026 23:02
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:86 Quality score 86/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant