Skip to content

feat(ggplot2): implement flowmap-origin-destination#7504

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/flowmap-origin-destination/ggplot2
May 20, 2026
Merged

feat(ggplot2): implement flowmap-origin-destination#7504
MarkusNeusinger merged 6 commits into
mainfrom
implementation/flowmap-origin-destination/ggplot2

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: flowmap-origin-destination - r/ggplot2

Implements the r/ggplot2 version of flowmap-origin-destination.

File: plots/flowmap-origin-destination/implementations/r/ggplot2.R

Parent Issue: #3765


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 20, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot displays on a warm off-white #FAF8F1 background. A bold title "Global Air Passenger Flows · flowmap-origin-destination · r · ggplot2 · anyplot.ai" is clearly readable in dark text at the top. Curved arcs connect 10 global airports: NYC (Americas, green #009E73), LHR/AMS/CDG/FRA (Europe, orange-brown #D55E00), DXB (Middle East, blue #0072B2), and TYO/HKG/SIN/SYD (Asia Pacific, pink-purple #CC79A7). Arc widths vary proportionally with flow magnitude (2.3–6.5M pax/yr) and arrowheads mark direction. Airport nodes are colored circles with IATA code labels in dark bold text. Two legend boxes appear at right: "Origin Region" and "Flow (M pax/yr)". Grid lines are very subtle (INK_SOFT, linewidth=0.1). All text is clearly readable against the light background — PASS.

Dark render (plot-dark.png): The same plot renders on a near-black #1A1A17 background. The title and all text elements (axis labels "Longitude"/"Latitude", tick values, legend labels, IATA codes) correctly flip to near-white/light text — no dark-on-dark failures. Data arc colors are identical to the light render: same green, orange-brown, blue, and pink-purple arcs at the same widths. Airport dots retain their region fill colors with a dark outline. The legend box uses the elevated dark background #242420 with a subtle border; text is clearly readable. The "Flow (M pax/yr)" legend line samples are grey against the dark elevated background and distinguishable. All text is clearly readable against the dark background — PASS.

Both renders pass the theme-readability check. Data colors are identical between themes; only chrome flips.

Score: 79/100

Category Score Max
Visual Quality 24 30
Design Excellence 11 20
Spec Compliance 14 15
Data Quality 14 15
Code Quality 9 10
Library Mastery 7 10
Total 79 100

Visual Quality (24/30)

  • VQ-01: Text Legibility (6/8) — All sizes explicitly set and readable; title at 9pt yields ~50 source-px vs. recommended ~67 (12pt @ 400 dpi) — slightly small
  • VQ-02: No Overlap (4/6) — European cluster (LHR, AMS, CDG, FRA) remains crowded with closely-spaced labels and overlapping arc bundles despite manual nudging
  • VQ-03: Element Visibility (5/6) — Arcs clearly visible with proportional widths; arrowheads slightly small but directionally informative
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe; four region colors distinguishable without relying on hue alone
  • VQ-05: Layout & Canvas (3/4) — Canvas well-utilized; lower half slightly empty (few flows south of Singapore/Hong Kong)
  • VQ-06: Axis Labels & Title (2/2) — Longitude/Latitude appropriate for geographic axes; title format correct
  • VQ-07: Palette Compliance (2/2) — Americas = #009E73 first; Okabe-Ito positions 1–4 in order; backgrounds #FAF8F1 / #1A1A17; chrome fully theme-adaptive

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (4/8) — Well-configured above generic defaults; prescribed Okabe-Ito palette, subtle grid, themed legend, manual label nudging show care — but no standout design innovation and absence of a basemap limits visual richness
  • DE-02: Visual Refinement (4/6) — Subtle major grid (linewidth=0.1), no minor grid, axis ticks removed, legend box styled with border and elevated background fill
  • DE-03: Data Storytelling (3/6) — Hub-and-spoke patterns are visually evident through color+width encoding; but no basemap removes geographic anchoring and no highlighting of the dominant LHR-DXB corridor limits immediate insight

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct origin-destination flow map with curved arcs, proportional line widths, directional arrows
  • SC-02: Required Features (3/4) — Curved arcs, proportional widths, transparency (alpha=0.65), color encoding, location labels all present. Missing: basemap with country boundaries/coastlines — explicitly required by spec
  • SC-03: Data Mapping (3/3) — lon→x, lat→y, flow→linewidth, origin_region→color all correct
  • SC-04: Title & Legend (3/3) — Title format correct with descriptive prefix; legend labels "Origin Region" and "Flow (M pax/yr)" are descriptive

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Multiple hubs, varying flow magnitudes (2.3–6.5M), multi-region coverage, directional encoding; flows are one-directional which slightly limits showing bidirectional imbalances
  • DQ-02: Realistic Context (5/5) — Real IATA codes, accurate geographic coordinates, neutral topic, plausible intercontinental routes
  • DQ-03: Appropriate Scale (4/4) — Flow values 2.3–6.5M pax/year plausible for major hub-to-hub routes; LHR-DXB as busiest is factually consistent

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → tokens → data → joins → plot → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — set.seed(42) present; data is fully deterministic
  • CQ-03: Clean Imports (1/2) — library(scales) imported but no scales:: functions explicitly called in the code — unused import
  • CQ-04: Code Elegance (2/2) — Clean idiomatic R; manual nudge vectors are pragmatic; no fake UI elements
  • CQ-05: Output & API (1/1) — sprintf("plot-%s.png", THEME) correct; ragg::agg_png device; modern linewidth= API

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct grammar-of-graphics layering; proper aes() mapping; guides() with order argument for multi-legend arrangement; all scale functions used correctly
  • LM-02: Distinctive Features (3/5) — geom_curve with curvature and arrow arguments is ggplot2-distinctive; scale_linewidth_continuous uses the modern ggplot2 ≥3.4 API; guides(fill=, color=, linewidth=, order=) for merged legend control is ggplot2-specific

Score Caps Applied

  • None — no caps triggered

Strengths

  • Correct Okabe-Ito palette with Americas (green #009E73) as first series, canonical Okabe-Ito order for all four regions
  • Fully theme-adaptive chrome: INK/INK_SOFT/PAGE_BG/ELEVATED_BG tokens applied throughout — dark render passes all legibility checks with no dark-on-dark failures
  • Thoughtful manual nudge offsets (per-airport nudge_x/nudge_y) to spread the dense European label cluster
  • Flow magnitude encoded via scale_linewidth_continuous and direction via arrow argument on geom_curve — both key spec encodings
  • Realistic, neutral data: real IATA codes, accurate coordinates, plausible hub-to-hub flow values

Weaknesses

  • Missing basemap: spec explicitly requires country boundaries or coastlines for geographic context — add rnaturalearth/rnaturalearthdata borders or a simplified world polygon as a geom_sf() layer beneath the arcs
  • European cluster crowding: LHR/AMS/CDG/FRA labels and arc bundles are still dense even with nudging — consider reducing label size to 2pt or using ggrepel for that cluster
  • Title font size 9pt is below the recommended 12pt — increase to 12pt to match style-guide sizing defaults
  • library(scales) is unused — remove this import
  • DE storytelling: add a subtitle or highlight the highest-traffic corridor (LHR-DXB at 6.5M) to give the viewer an immediate insight anchor

Issues Found

  1. SC-02 PARTIAL: Missing basemap — the spec states "Include a basemap with country boundaries or coastlines for geographic context." Without it the flows float in abstract lat/lon space.
    • Fix: Add library(rnaturalearth); library(rnaturalearthdata) and a geom_sf(data = ne_countries(scale = "medium", returnclass = "sf"), fill = NA, color = INK_SOFT, linewidth = 0.15) layer as the first layer before geom_curve.
  2. VQ-01 LOW: Title at 9pt yields ~50 source-pixels; style guide recommends 12pt (~67 source-px).
    • Fix: Change plot.title = element_text(color = INK, size = 9, ...) to size = 12.
  3. CQ-03 MINOR: library(scales) imported but unused.
    • Fix: Remove library(scales) from imports.
  4. DE-03 LOW: No geographic anchoring or storytelling emphasis.

AI Feedback for Next Attempt

Priority 1: Add a world basemap (rnaturalearth + geom_sf()) as the first layer before geom_curve — this is the single biggest missing feature and will most improve both spec compliance and visual storytelling. Use fill = NA, color = INK_SOFT, linewidth = 0.15 so it doesn't compete with the arcs. Priority 2: Increase title size from 9pt to 12pt. Priority 3: Remove the unused library(scales). Priority 4: Consider reducing IATA label size for the European cluster to 2pt or using ggrepel::geom_text_repel() for automatic non-overlapping placement. Priority 5: Add a subtitle highlighting the dominant corridor to improve DE-03.

Verdict: REJECTED

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

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot shows a world map with a warm off-white background (#FAF8F1) and thin gray country borders. Fifteen curved flow arcs connect major international airports, colored by origin region: green (Americas/NYC), orange (Europe), blue (Middle East/Dubai), and pink (Asia Pacific). Line thickness varies by passenger volume. Airport nodes are rendered as filled circles with white stroke, labeled with 3-letter IATA codes (NYC, LHR, CDG, FRA, DXB, SIN, HKG, TYO, AMS, SYD). Directional arrows tip each arc. The right-side legend shows "Origin Region" and "Flow (M pax/yr)". The title and subtitle text are dark on the light background and clearly readable. One concern: the title "Global Air Passenger Flows · flowmap-origin-destination · r · ggplot2 · anyplot.ai" extends very close to — and appears slightly clipped at — the right canvas edge. European airport labels (LHR, AMS, CDG, FRA) are tightly clustered and show near-overlap despite manual nudges. Overall legibility: PASS with noted crowding.

Dark render (plot-dark.png): The same plot on a warm near-black background (#1A1A17). Country borders are rendered in the soft gray INK_SOFT token, clearly visible against the dark surface. All four data-color arcs are identical to the light render — green, orange, blue, pink — confirming the Okabe-Ito data colors are theme-invariant. Title, subtitle, axis labels, tick labels, and legend text all render in light tones (INK and INK_SOFT tokens) and are clearly readable against the dark background. No dark-on-dark failure detected. The same title truncation concern applies. Overall legibility: PASS with noted title edge clipping.

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

Score: 81/100

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

Visual Quality (22/30)

  • VQ-01: Text Legibility (5/8) — Font sizes explicitly set throughout. Title at 12pt bold, axis at 8pt, ticks at 7pt. However, the long mandatory title runs to the canvas edge and appears slightly clipped. European cluster labels (LHR/AMS/CDG/FRA) are cramped.
  • VQ-02: No Overlap (3/6) — European cluster (LHR, AMS, CDG, FRA) despite manual nudges are very tightly packed; labels nearly overlap each other and the arc bundle in that area.
  • VQ-03: Element Visibility (5/6) — Arcs are clearly visible with well-chosen linewidth range (0.4–2.8), alpha 0.65, and directional arrows. Airport nodes at size 3.5 are distinct.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette; CVD-safe; no red-green-only encoding.
  • VQ-05: Layout & Canvas (3/4) — Map fills the canvas well. Minor issue: title appears to clip the right canvas edge.
  • VQ-06: Axis Labels & Title (2/2) — "Longitude" / "Latitude" labels with subtitle providing storytelling context.
  • VQ-07: Palette Compliance (2/2) — First categorical series (Americas) = #009E73 ✓. Subsequent series follow Okabe-Ito order. Backgrounds are #FAF8F1 (light) and #1A1A17 (dark). Chrome (text, grid, legend) adapts correctly in both themes.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Professional map-based flow visualization. Intentional use of color by region, arrow directionality, and subtitle callout for the busiest route elevates this above a default chart. Not quite FiveThirtyEight-level but clearly above generic defaults.
  • DE-02: Visual Refinement (4/6) — Grid at linewidth 0.1 (very subtle), panel.grid.minor blank, axis ticks removed, legend with fine border. Good whitespace with 8pt plot margins.
  • DE-03: Data Storytelling (4/6) — Subtitle explicitly calls out the LHR–DXB corridor as busiest. Line-width encoding of passenger volume plus directional arrows create clear visual hierarchy around the major hubs (Dubai, London).

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct flow map with curved arcs (geom_curve), basemap, origin/destination nodes, and line-width proportional to flow.
  • SC-02: Required Features (4/4) — Curved arcs, flow-proportional linewidth, alpha transparency (0.65), world basemap, airport labels, color encoding of a meaningful dimension.
  • SC-03: Data Mapping (3/3) — Coordinates correctly mapped; flow magnitude drives linewidth; region drives color.
  • SC-04: Title & Legend (2/3) — Title follows the format correctly. However the title appears clipped at the right edge, making "anyplot.ai" partially illegible. Legends for region and flow are correct.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 15 flows across 10 global hubs. Hub structure, varying corridor volumes, and multi-directional flow patterns all represented.
  • DQ-02: Realistic Context (5/5) — Real international airports with IATA codes, genuine air-traffic corridors (LHR-DXB, SIN-HKG, TYO-HKG), neutral aviation theme.
  • DQ-03: Appropriate Scale (4/4) — Flow values 2.3–6.5M pax/yr are realistic for major international routes. LHR-DXB as the busiest corridor is factually plausible.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Imports → tokens → data → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — at top.
  • CQ-03: Clean Imports (2/2) — ggplot2, dplyr, maps, ragg — all used.
  • CQ-04: Code Elegance (2/2) — Clean pipeline using , well-organized join logic, manual nudge table is clearly motivated by the dense European cluster.
  • CQ-05: Output & API (1/1) — with . Modern not deprecated .

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct grammar-of-graphics layering, , , , for legend ordering. Could benefit from for proper geographic projection.
  • LM-02: Distinctive Features (3/5) — for arc drawing and are ggplot2-specific. Combined color + linewidth aesthetics is a good use of ggplot2's grammar. Does not reach the top tier but clearly above generic usage.

Score Caps Applied

  • None — no caps triggered (VQ-02=3, VQ-03=5, SC-01=5, DQ-02=5, DE-01=5>2, CQ-04=2).

Strengths

  • Correct Okabe-Ito regional color assignment with Americas first (#009E73) and full theme-adaptive chrome in both renders.
  • Excellent data quality: real airports, realistic passenger volumes, neutral subject.
      • directional arrows form a cohesive, idiomatic ggplot2 flow map.
  • Subtitle callout (LHR–DXB busiest corridor) adds meaningful storytelling without annotations.
  • Manual label nudges for the dense European cluster show thoughtful layout work.

Weaknesses

  • Title clips the right canvas edge in both renders — reduce title fontsize from 12pt to ~10pt to prevent overflow, or add more right margin.
  • European airport labels (LHR, AMS, CDG, FRA) near-overlap despite nudges — nudge distances need increase or label sizes need reduction (from 2.5 to 2.0).

Issues Found

  1. VQ-01/VQ-05 MINOR: Title "Global Air Passenger Flows · flowmap-origin-destination · r · ggplot2 · anyplot.ai" overflows to the right canvas edge.
    • Fix: Reduce fontsize from 12 to 10, or increase right from 8 to 20.
  2. VQ-02 MODERATE: European hub labels crowd at 2.5pt size with current nudge offsets.
    • Fix: Reduce airport label from 2.5 to 2.0 or increase nudge magnitudes for LHR/AMS/CDG/FRA.

AI Feedback for Next Attempt

Fix the two layout issues: (1) title overflows right edge — reduce plot.title size to 10pt or increase right margin to ~20pt; (2) European cluster labels (LHR, AMS, CDG, FRA) near-overlap — reduce geom_text size to 2.0 or widen the nudge offsets. Everything else is strong — keep the color scheme, arrow directionality, world basemap, and subtitle.

Verdict: APPROVED

@github-actions github-actions Bot added quality:81 Quality score 81/100 ai-approved Quality OK, ready for merge and removed quality:79 Quality score 79/100 labels May 20, 2026
@MarkusNeusinger MarkusNeusinger merged commit 61ac100 into main May 20, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/flowmap-origin-destination/ggplot2 branch May 20, 2026 10:21
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:81 Quality score 81/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant