Skip to content

feat(muix): implement polar-scatter - #12402

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/polar-scatter/muix
Oct 24, 2026
Merged

MarkusNeusinger merged 6 commits into
mainfrom
implementation/polar-scatter/muix

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: polar-scatter - javascript/muix

Implements the javascript/muix version of polar-scatter.

File: plots/polar-scatter/implementations/javascript/muix.tsx

Generation: adopted from 5b2bcb3e5e4dc5b3685a669c07cf3ab1b9918f69 (5b2bcb3) by gemini-4-argon; the model below runs repair

Model: opus

Parent Issue: #2023

Regeneration: previous quality 85 (forced: adopted from 5b2bcb3, fresh-generation review path)


🤖 impl-generate workflow

@github-actions github-actions Bot added the regen:forced Regeneration of an implementation that is live on main label Oct 24, 2026
@claude

claude Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Background: warm off-white #FAF8F1, square 2400x2400 canvas. Chrome: bold dark title "polar-scatter · javascript · muix · anyplot.ai" at the top; four concentric rings (5/10/15/20 m/s) and eight spokes in subtle grey; degree labels 0°-315° every 45° outside the rim (0/90/180/270 bold); ring labels "5 m/s"…"20 m/s" on pills along the ~337° bearing; HTML legend at the bottom (Morning, Afternoon, Evening, Night). All text dark and readable; the "5 m/s" label is partly covered by green Morning markers. Data: 120 translucent circles: Morning #009E73 around 0-60° at 3-10 m/s, Afternoon lavender #C475FD around 60-150° at 7-20 m/s, Evening blue #4467A3 around 155-235°, Night ochre #BD8233 as a tight cluster near 285° at 2-6 m/s. First series is brand green. Disc fills about two thirds of the canvas width, leaving wide empty margins. Legibility verdict: PASS

Dark render (plot-dark.png): Background: warm near-black #1A1A17. Chrome: title in light ink, degree and ring labels in light grey, grid rings and spokes in subtle dark grey, legend text light; no dark-on-dark text. The ring-label pills switch to the dark page color, and the "5 m/s" label is again partly covered by Morning markers. Data: identical positions and identical palette hues (#009E73, #C475FD, #4467A3, #BD8233) as the light render; only chrome flipped. Brand green clearly visible. Legibility verdict: PASS

Score: 83/100

Category Score Max
Visual Quality 27 30
Design Excellence 11 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 9 10
Library Mastery 6 10
Total 83 100

Visual Quality (27/30)

  • VQ-01: Text Legibility (8/8) - Title 22 px, ring/degree labels 14 px, legend 15 px CSS; all readable in both themes and at thumbnail size
  • VQ-02: No Overlap (5/6) - Morning markers are drawn over the "5 m/s" ring label (defect line)
  • VQ-03: Element Visibility (6/6) - 120 markers at size 8 with 0.72 opacity, well suited to the density; legend dots visible in both themes
  • VQ-04: Color Accessibility (2/2) - Four distinct Imprint hue families, no red-green pairing
  • VQ-05: Layout & Canvas (3/4) - Disc fills only about 66 % of the canvas width; large empty band under the title (defect line)
  • VQ-06: Axis Labels & Title (1/2) - Radius ticks carry m/s, but the angle is never named as wind bearing (defect line)
  • VQ-07: Palette Compliance (2/2) - Imprint positions 1-4 in order, first series #009E73; #FAF8F1 / #1A1A17 backgrounds, chrome theme-correct

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) - Above baseline: bold cardinal-angle ticks over regular 45° ticks, ring labels with units on page-colored pills
  • DE-02: Visual Refinement (3/6) - Ring labels placed in the computed least-populated sector, and the outer ring drawn heavier as the rim; the placement still lets the 5 m/s label collide
  • DE-03: Data Storytelling (3/6) - Data built so the prevailing direction rotates clockwise through the day, which the four colored clouds make readable at a glance

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) - Polar scatter with bearing as angle and speed as radius
  • SC-02: Required Features (4/4) - Radial gridlines at 5 m/s, angular ticks every 45° in degrees, centered disc, radius from 0, legend for the color encoding, translucency in dense areas
  • SC-03: Data Mapping (3/3) - Marks at their exact bearing/speed; no jitter or nudging; all points inside the 20 m/s rim
  • SC-04: Title & Legend (3/3) - Title 'polar-scatter · javascript · muix · anyplot.ai'; legend entries Morning/Afternoon/Evening/Night

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) - Prevailing-direction clusters, sparse sectors, varying speeds and outliers near the rim
  • DQ-02: Realistic Context (5/5) - Wind observations by time of day, neutral and plausible
  • DQ-03: Appropriate Scale (4/4) - Speeds 0.5-19.5 m/s and bearings 0-360°, sensible for surface wind; 120 points within the 100-150 range (no Check values in the spec)

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3) - Flat module; the one extra component (PolarGrid) is required to use the scale hooks
  • CQ-02: Reproducibility (2/2) - Fixed-seed LCG
  • CQ-03: Clean Imports (2/2) - ChartsContainer, ScatterPlot, useXScale, useYScale all used
  • CQ-04: Code Elegance (1/2) - Hand-parsed hex to rgba (lines 115-120) and a hand-built HTML legend (lines 268-291) where native options exist (defect line)
  • CQ-05: Output & API (1/1) - Default export, v9 ChartsContainer API, skipAnimation, sized from ANYPLOT_SIZE

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (3/5) - Good v9 composition, but the legend and the opacity are hand-built instead of ChartsLegend / sx styling
  • LM-02: Distinctive Features (3/5) - Uses MUI X's composition API: a custom SVG layer inside ChartsContainer that reads the chart scales through useXScale/useYScale to draw the polar grid

Score Caps Applied

  • None

Strengths

  • A true polar layout composed in community MUI X: ChartsContainer with hidden linear axes, and a custom layer that reads useXScale/useYScale so rings, spokes and labels share the scatter's coordinate system exactly.
  • Radius axis starts at 0 at the center, with nice 5 m/s rings computed from the data up to 20 m/s; every marker sits inside the rim at its own bearing and speed (sin/cos conversion from degrees via radians, as the Notes ask).
  • Ring labels carry the unit ("10 m/s") and are placed in the computed least-populated 45° sector, and the cardinal angles 0/90/180/270 are set in bold above the 45° ticks, giving a clear tick hierarchy.
  • Four time-of-day groups use the Imprint palette in canonical order (#009E73, #C475FD, #4467A3, #BD8233) with 0.72 fill opacity, identical in both themes; the data shows a plausible clockwise diurnal rotation of the prevailing wind.
  • Native MUI X scatter interactivity (hover tooltips and highlighting) carries over to the HTML export, and skipAnimation is set.

Weaknesses

  • VQ-02 (both): the "5 m/s" ring label sits under the Morning markers near bearing 337°: several green dots are drawn over the text, so the label is half covered → the ring labels must stay readable on top of every data mark. Likely cause: (which draws the label pills) is rendered before in ChartsContainer, so the scatter paints over it; render the ring-label group after .
  • VQ-05 (both): the polar disc fills only about 66 % of the 2400 px canvas width, with an empty band of about 230 px between the title and the 0° label and wide side margins → the disc should reach about 80 % of the width (about +14 %). Likely cause: DOMAIN_PAD_FACTOR = 1.26 combined with CHART_MARGIN of 36 px and a 70 px title band; padding the domain only to fit the angular labels (about 1.15) would fix it.
  • VQ-06 (both): the angular axis shows only degree values, so nothing says the angle is the wind bearing (direction the wind comes from) → name it once, e.g. a 'Wind bearing (°)' caption or compass letters N/E/S/W next to 0°/90°/180°/270°. Likely cause: the BEARING column label is never rendered.
  • CQ-04 (code): lines 115–120 parse each palette hex into r/g/b by hand to build an rgba() string, and lines 268–291 build the legend as hand-written HTML → set the opacity with sx={{ '& .MuiScatterChart-marker': { fillOpacity: 0.72 } }} and use the series' palette color, and render inside the composition. Likely cause: hand-rolled replacements for the native styling and legend APIs.
  • Suggestion: a thin page-colored outline on the markers would separate the stacked Night dots more clearly than translucency alone.

@github-actions github-actions Bot added quality:83 Quality score 83/100 ai-rejected Quality not OK, triggers update labels Oct 24, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Oct 24, 2026
Attempt 1/4 - fixes based on AI review

- VQ-02: ring labels drawn in a layer after <ScatterPlot /> so they stay readable
- VQ-05: domain pad 1.26 -> 1.11, tighter margins; disc now ~80% of canvas width
- VQ-06: caption names the angle (Wind Bearing, clockwise from 0 at top) and radius from the column constants
- CQ-04: series use palette colors with fillOpacity via sx on .MuiScatterChart-marker; native ChartsLegend in a ChartsDataProvider/ChartsWrapper composition replaces the hand-built HTML legend

Declined:
- "Suggestion: a thin page-colored outline on the markers" — suggestion, not taken

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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

claude Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white #FAF8F1 page. Bold dark title "polar-scatter · javascript · muix · anyplot.ai" with a grey subtitle "Angle: Wind Bearing (°), clockwise from 0° at top · Radius: Wind Speed (m/s)". A polar disc with four subtle grey rings (5/10/15/20 m/s, outer rim slightly heavier) and eight spokes; angular labels 0°–315° every 45° outside the rim, cardinals bold; ring labels on page-colored pills along the ~337° bearing. 120 translucent circles: Morning green #009E73 clustered N–NE at 5–10 m/s, Afternoon purple E–SE at 8–19 m/s, Evening blue S–SW at 5–15 m/s, Night ochre tightly clustered W–NW at 2–6 m/s, all inside the rim. Bottom legend Morning / Afternoon / Evening / Night. All text is readable dark-on-light. The 5 m/s and 10 m/s pills cover parts of two Morning markers.

Dark render (plot-dark.png): Warm near-black #1A1A17 page. Title, subtitle, angular labels, ring labels and legend flip to light ink; rings and spokes stay subtle but visible. Data colors and positions are identical to the light render (only chrome flips); translucency makes markers read slightly deeper against the dark page, but every series stays distinct and brand green is clearly visible. No dark-on-dark text. The same two Morning markers are partly hidden by the ring-label pills.

Score: 87/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8)
  • VQ-02: No Overlap (5/6) - ring-label pills cover parts of two markers
  • VQ-03: Element Visibility (6/6)
  • VQ-04: Color Accessibility (2/2)
  • VQ-05: Layout & Canvas (4/4)
  • VQ-06: Axis Labels & Title (2/2)
  • VQ-07: Palette Compliance (2/2)

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) - bold cardinals vs regular intercardinals, heavier rim, quiet convention subtitle
  • DE-02: Visual Refinement (3/6) - ring labels placed on the emptiest sector's bearing, though still landing on markers
  • DE-03: Data Storytelling (3/6) - prevailing wind rotates N → E → S → W through the day and calms at night

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5)
  • SC-02: Required Features (4/4)
  • SC-03: Data Mapping (3/3)
  • SC-04: Title & Legend (3/3)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6)
  • DQ-02: Realistic Context (5/5)
  • DQ-03: Appropriate Scale (4/4)

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) - PolarGrid/RingLabels are React components required for the scale hooks
  • CQ-02: Reproducibility (2/2)
  • CQ-03: Clean Imports (2/2)
  • CQ-04: Code Elegance (2/2)
  • CQ-05: Output & API (1/1)

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) - v9 composition (ChartsDataProvider + ChartsWrapper + ChartsSurface + ChartsLegend + ScatterPlot)
  • LM-02: Distinctive Features (3/5) - custom polar grid drawn from useXScale/useYScale inside ChartsSurface, keeping native tooltips and legend

Score Caps Applied

  • None

Strengths

  • Polar layout built on MUI X's own composition API: a ScatterPlot inside ChartsSurface with a custom SVG grid drawn from useXScale/useYScale, so native tooltips and the HTML legend still work
  • Angular ticks every 45° in degrees with bold cardinals, 0° at top clockwise, and a subtitle that states the convention and units
  • Radius axis computed from the data to a nice 5 m/s step, starting at 0 and closing past the 19 m/s maximum so every marker sits inside the rim
  • Fill opacity 0.72 lets the dense Night cluster read darker while single outliers stay visible
  • Imprint palette in canonical order with identical data colors across themes; all chrome uses theme tokens and reads cleanly in both renders
  • Deterministic LCG data tells a clear diurnal story: the prevailing wind rotates N → E → S → W through the day and calms at night

Weaknesses

  • VQ-02 (both): the opaque page-colored pills behind the '5 m/s' and '10 m/s' ring labels sit on top of the scatter layer and hide parts of two Morning markers near bearing 337° (about half of the marker at ~5.5 m/s and an edge of the one at ~10 m/s) → no marker covered by a ring label. Likely cause: <RingLabels /> rendered after <ScatterPlot /> with fill={t.pageBg}, and the "emptiest sector" bearing (337.5°) still holds Morning points; draw the labels below the markers or drop the opaque pill.
  • Suggestion: placing the ring labels on a bearing chosen by distance to the nearest marker rather than by sector count would keep them clear without a pill.
  • Suggestion: a slightly larger angular label size (16 px) would hold up better in the 400 px thumbnail.

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-approved Quality OK, ready for merge and removed quality:83 Quality score 83/100 labels Oct 24, 2026
@MarkusNeusinger
MarkusNeusinger merged commit ec84377 into main Oct 24, 2026
@MarkusNeusinger
MarkusNeusinger deleted the implementation/polar-scatter/muix branch October 24, 2026 12:03
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:87 Quality score 87/100 regen:forced Regeneration of an implementation that is live on main

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant