Skip to content

feat(pygal): implement errorbar-basic#9524

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/errorbar-basic/pygal
Jun 30, 2026
Merged

feat(pygal): implement errorbar-basic#9524
MarkusNeusinger merged 6 commits into
mainfrom
implementation/errorbar-basic/pygal

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: errorbar-basic - python/pygal

Implements the python/pygal version of errorbar-basic.

File: plots/errorbar-basic/implementations/python/pygal.py

Parent Issue: #973


🤖 impl-generate workflow

github-actions Bot added 2 commits June 30, 2026 20:33
Regen from quality 88. Addressed:
- Canvas: 4800×2700 → 3200×1800 (canonical landscape per Step 0 contract)
- VQ-07 palette compliance: reordered series so Mean ± error is added first,
  giving it BRAND (#009E73, Imprint position 1); Vehicle baseline added second,
  getting INK_MUTED. colors_tuple updated to match: (BRAND, INK_MUTED) + (BRAND,)*62
- Title: added python language token → "errorbar-basic · python · pygal · anyplot.ai"
- Font sizes: updated to canonical values for 3200×1800 (title 66, labels 56, ticks 44)
- sys.path fix: added script-dir removal so 'import pygal' resolves installed package
- Added explicit y_labels for clean tick spacing
- Comment: fixed "Okabe-Ito" → "Imprint palette"
@claude

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot sits on a warm off-white background (#FAF8F1), consistent with the Imprint theme. Six data points for the dose groups (Vehicle, 1 mg/kg, 3 mg/kg, 10 mg/kg, 30 mg/kg, 100 mg/kg) are rendered as large brand-green (#009E73) circles with symmetric or asymmetric error bars (vertical stems + horizontal caps) in the same green. A dashed muted-grey horizontal reference line marks the Vehicle baseline at ~25.3. The title "errorbar-basic · python · pygal · anyplot.ai" appears in dark ink and is clearly readable. Y-axis label "Response Value (units)" and X-axis label "Dose" are visible; tick labels (20–50, category names) are legible. A bottom legend labels "Mean ± error" (green square) and "Vehicle baseline" (grey square). No text is light-on-light; all elements are fully readable against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): The plot sits on a warm near-black background (#1A1A17). The same six data points are rendered in the identical brand green (#009E73) — data colors match the light render exactly. Error bars and caps remain green; the vehicle baseline dashed line is muted-grey. Title, axis labels, axis tick labels (both numeric 20–50 and categorical dose names), and legend text all appear in light ink and are clearly readable against the near-black background. No dark-on-dark failure detected. Legibility verdict: PASS.

Both renders are present and both pass the theme-readability check.

Score: 88/100

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

Visual Quality (30/30)

  • VQ-01: Text Legibility (8/8) — All text explicitly sized (title=66, axis=56, ticks=44, legend=44). Readable in both themes at full and scaled resolution.
  • VQ-02: No Overlap (6/6) — No collisions between data points, error bars, labels, or legend entries.
  • VQ-03: Element Visibility (6/6) — Large markers (dots_size=28) are prominent for sparse 6-point data; error bar stems and caps are clearly visible in both renders.
  • VQ-04: Color Accessibility (2/2) — Brand green on warm cream/near-black passes contrast. Baseline uses INK_MUTED semantic anchor. CVD-safe Imprint palette applied correctly.
  • VQ-05: Layout & Canvas (4/4) — Landscape 3200×1800 canvas confirmed. Title fills ~55% of width; bottom legend has generous space. No overflow or clipping detected.
  • VQ-06: Axis Labels & Title (2/2) — X-axis "Dose", Y-axis "Response Value (units)" — descriptive with units.
  • VQ-07: Palette Compliance (2/2) — First (and only data) series is #009E73 ✓. Background #FAF8F1 (light) and #1A1A17 (dark) ✓. INK_MUTED baseline is correctly theme-adaptive ✓.

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Vehicle baseline reference line demonstrates intentional analytical hierarchy; asymmetric errors at 10 mg/kg tell a pharmacological story. Clean, professional presentation. Above default but no annotations, callouts, or focal-point emphasis.
  • DE-02: Visual Refinement (3/6) — Y-axis grid only (no X guides) and subtle dotted lines — good choice for a dot plot. Clean bottom legend. Pygal's default frame/spines cannot be fully removed, adding minor chrome.
  • DE-03: Data Storytelling (3/6) — Vehicle baseline line effectively guides viewer to see dose-response progression vs. control. No additional annotation or callout highlights the key insight (10 mg/kg peak asymmetric variability).

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Error bar plot correctly implemented via XY chart with manual stem-and-cap construction (the canonical approach in pygal, which lacks a native error bar type).
  • SC-02: Required Features (4/4) — Visible caps on all error bars ✓; asymmetric errors at 10 mg/kg (lower=6.2, upper=2.8) ✓; consistent cap width across groups ✓; 6 groups within the spec's 3–20 range ✓.
  • SC-03: Data Mapping (3/3) — Doses on X, response values on Y; all six groups fully visible within the padded y-range (19.2–53.7).
  • SC-04: Title & Legend (3/3) — "errorbar-basic · python · pygal · anyplot.ai" ✓. Legend entries: "Mean ± error" and "Vehicle baseline" ✓.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Demonstrates central values, symmetric errors (Vehicle, 1 mg/kg, 100 mg/kg), asymmetric errors (10 mg/kg), escalating dose-response trend, and baseline reference — full feature coverage.
  • DQ-02: Realistic Context (5/5) — Dose-response pharmacological study with escalating doses (mg/kg) is a textbook real-world use case for error bars. Values and error magnitudes are plausible. No controversial content.
  • DQ-03: Appropriate Scale (4/4) — Response values 23–50, error magnitudes 2–6 — realistic for biological assay data with clearly motivated asymmetry at peak-variability dose.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear top-to-bottom structure; no functions or classes; well-commented purpose.
  • CQ-02: Reproducibility (2/2) — Fully deterministic; all data is hardcoded.
  • CQ-03: Clean Imports (2/2) — Only os, sys, pygal, and Style imported; sys.path fix is necessary and well-explained.
  • CQ-04: Code Elegance (2/2) — Error bar loop is clean; color tuple construction is logical; data and configuration are clearly separated.
  • 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 pygal.XY, Style object with all theme tokens, x_labels with value/label dicts, x_labels_major, and range/xrange parameters — idiomatic pygal patterns throughout.
  • LM-02: Distinctive Features (3/5) — Leverages pygal's interactive HTML export (a distinctive pygal capability), per-point tooltip labels in mean_points, and the XY chart's ability to mix stroke and no-stroke series in a single chart.

Score Caps Applied

  • None

Strengths

  • Both light and dark renders are visually clean with correct Imprint theme adaptation — no dark-on-dark failures
  • Vehicle baseline reference line adds genuine analytical value beyond the spec's minimum requirements
  • Asymmetric error bar data at 10 mg/kg (lower=6.2, upper=2.8) is scientifically motivated and highlights a key pharmacological pattern
  • Manual stem-and-cap error bar construction is the correct idiomatic approach for pygal's XY chart
  • Dose-response clinical context is realistic, plausible, and engaging

Weaknesses

  • DE-03 could be strengthened by annotating the 10 mg/kg asymmetric variability or the peak response at 30 mg/kg to create a clearer focal point
  • Pygal's default frame chrome (axis lines/spines) cannot be suppressed, which adds minor visual weight that a matplotlib implementation would remove with ax.spines['top'].set_visible(False)

Issues Found

  1. DE-03 MODERATE: No annotation highlights the most interesting data feature — the notable lower-tail variability at 10 mg/kg (err_lower=6.2 vs err_upper=2.8). A callout would improve data storytelling.
    • Fix: Add a pygal add() annotation or adjust the tooltip label to draw attention to the asymmetric pattern.

AI Feedback for Next Attempt

Implementation is high quality. If regenerated: consider adding a direct annotation or data label callout at the 10 mg/kg point to highlight its notable lower-tail asymmetry — this would elevate DE-03 from adequate to strong. The vehicle baseline and clean XY-as-errorbar construction should be preserved.

Verdict: APPROVED

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

claude Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The chart renders on a warm off-white background (#FAF8F1). Six data points are plotted as large teal-green circular markers (Imprint brand green #009E73) at dose categories Vehicle through 100 mg/kg on the X-axis. Each marker has a clearly visible vertical error bar with horizontal caps extending above and below. At 10 mg/kg, a larger amber/yellow marker (Imprint amber #DDCC77) is overlaid as an asymmetry callout. A dashed horizontal reference line runs at the vehicle baseline (~25.3). Y-axis gridlines are subtle and horizontal-only. The title "errorbar-basic · python · pygal · anyplot.ai" is displayed in dark text at the top (~55% canvas width). Axis labels "Dose" (X) and "Response Value (units)" (Y) are clearly visible. The legend at the bottom shows three entries but the asymmetric callout entry is truncated as "down Asymmetric at 10 m...". There is a noticeable empty cream-coloured area (~20% of canvas height) below the legend. All text is readable against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): The same chart is rendered on a warm near-black background (#1A1A17). Data colors are identical to the light render: green markers, amber callout at 10 mg/kg, green error bars, and dashed baseline. The title and axis labels are rendered in light/cream-colored text, clearly readable against the dark background. Tick labels and legend text are likewise light-colored and legible. Grid lines remain subtle. The same empty near-black area is present below the legend. No dark-on-dark failures detected -- all text elements use theme-adaptive light ink. Data colors (green, amber) are identical across both renders; only chrome flips. Legibility verdict: PASS.

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

Score: 84/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) -- Font sizes all explicitly set (title=66, label=56, major_label=44, legend=44). All text readable in both themes. Minor deduction: legend entry for the amber callout is truncated to "down Asymmetric at 10 m..." -- the full label is not visible to the reader.
  • VQ-02: No Overlap (6/6) -- No overlapping text or data elements. The amber callout overlaid on the green marker at 10 mg/kg is intentional and both are visually distinct.
  • VQ-03: Element Visibility (6/6) -- Six sparse data points use large markers (dots_size=28) with clearly visible error bars and caps. Amber callout marker is oversized (dots_size=38) to create appropriate visual emphasis.
  • VQ-04: Color Accessibility (2/2) -- Brand green #009E73 and amber #DDCC77 are CVD-safe and distinguishable. Muted baseline reference is appropriately low-contrast. No red-green sole-signal issues.
  • VQ-05: Layout & Canvas (3/4) -- Canvas is correctly 3200x1800. Plot area and legend together occupy ~80% of canvas height. However, there is a significant empty area (~20% of canvas height) below the legend that wastes canvas space and makes the layout feel bottom-heavy.
  • VQ-06: Axis Labels & Title (2/2) -- Y-axis "Response Value (units)" is descriptive with units; X-axis "Dose" is clear; title follows the mandated format.
  • VQ-07: Palette Compliance (2/2) -- First series is brand green #009E73. Amber (#DDCC77) used correctly as warning semantic anchor for the asymmetric callout. INK_MUTED used for baseline reference. Background is #FAF8F1 (light) / #1A1A17 (dark), never pure white/black. Data colors identical between themes; only chrome flips.

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (4/8) -- Thoughtful design choices: amber callout at the asymmetric data point and a dashed baseline reference line both add genuine meaning. This is above a plain default chart. However, pygal's SVG rendering style (uniform sans-serif, minimal visual hierarchy) keeps this at the "well-configured default" level rather than sophisticated publication-quality design.
  • DE-02: Visual Refinement (2/6) -- Y-axis-only grid is a good choice. Beyond that, pygal's limited customization options constrain refinement: spines cannot easily be removed, the large bottom-margin empty space hurts polish. At library-default refinement level.
  • DE-03: Data Storytelling (4/6) -- The amber callout at 10 mg/kg creates a clear visual focal point highlighting the asymmetric error bar -- the chart's key insight. The vehicle baseline reference line enables immediate dose-response comparison. These are genuine storytelling choices above the "data display" default.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) -- Correct: XY scatter with manually constructed error bars (vertical stem + upper/lower caps per point). Pygal has no native error bar type; this is the idiomatic workaround.
  • SC-02: Required Features (4/4) -- Visible caps on all error bars. Consistent error bar widths. Asymmetric error bars demonstrated (10 mg/kg: lower 6.2 vs upper 2.8). Multiple groups (6 categories).
  • SC-03: Data Mapping (3/3) -- X-axis: categorical dose groups, correctly mapped. Y-axis: response values (20-50 range), all data visible. Asymmetric lower/upper errors correctly split.
  • SC-04: Title & Legend (3/3) -- Title is exactly "errorbar-basic · python · pygal · anyplot.ai". Legend shows all three series (Mean +/- error, asymmetric callout, Vehicle baseline).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) -- Demonstrates all key aspects of error bar plots: symmetric errors, notably asymmetric errors (10 mg/kg), a dose-response pattern with varying magnitudes, visible caps, and a baseline reference. Full feature coverage.
  • DQ-02: Realistic Context (5/5) -- Dose-response study with vehicle control + escalating doses (1, 3, 10, 30, 100 mg/kg) is a standard pharmacology/toxicology scenario. Neutral scientific domain, real-world plausible.
  • DQ-03: Appropriate Scale (4/4) -- Response values in the 25-47 range with errors of 2-6 units are realistic. Doses span a standard 2-log range. Peak response at 30 mg/kg with slight taper at 100 mg/kg models a realistic bell-shaped dose-response curve.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) -- Flat sequential structure: imports -> sys.path fix -> style tokens -> data -> chart creation -> series -> save. No functions, classes, or unnecessary abstractions.
  • CQ-02: Reproducibility (2/2) -- All data is hardcoded. No randomness, no seed needed.
  • CQ-03: Clean Imports (2/2) -- Only os, sys, pygal, and Style are imported; all are used.
  • CQ-04: Code Elegance (2/2) -- The sys.path manipulation is a necessary workaround (file named pygal.py would shadow the package). The loop for error bars is the correct approach. Code is clean and readable.
  • CQ-05: Output & API (1/1) -- Saves plot-{THEME}.png and plot-{THEME}.html (pygal is interactive). Current pygal API used.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) -- Correctly uses XY chart type with the value-label dict format for x_labels. Style object is properly wired with all theme tokens. stroke_style dasharray for the baseline, show_dots=False for lines, stroke=False for point series -- all idiomatic. Above default.
  • LM-02: Distinctive Features (2/5) -- HTML export producing interactive tooltips with per-point rich labels is a genuine pygal differentiator. However, the error bars are not a native pygal feature (they are manually simulated via many XY series), which limits the distinctive library showcase.

Score Caps Applied

  • None -- DE-01=4 (above the <=2 threshold for the "boring" cap). No other caps triggered.

Strengths

  • Excellent error bar implementation for a library without native support -- vertical stems and capped ends are clearly visible on all 6 groups
  • Amber callout at 10 mg/kg is a sophisticated focal-point design choice that highlights the asymmetric error story
  • Dose-response baseline reference line enables immediate visual comparison at every dose
  • Correctly uses the Imprint palette in both themes with no chrome failures in either render
  • All code quality criteria met perfectly, including the subtle sys.path workaround for the filename conflict
  • Rich per-point tooltip labels in the HTML output provide excellent interactivity

Weaknesses

  • Legend label truncation: the amber callout entry shows as "down Asymmetric at 10 m..." -- the legend_at_bottom area may need wider allocation or the label should be shortened (e.g. "Asymmetric at 10 mg/kg") so readers see the full entry
  • Empty canvas below legend: ~20% of canvas height is unused cream/dark space below the legend, making the layout bottom-heavy. Adjust margin settings to reclaim this space.

Issues Found

  1. VQ-01 MINOR / VQ-05: Legend label truncated + large empty bottom margin
    • Fix: Shorten the amber callout legend label so it fits within pygal's legend width (e.g. "Asymmetric at 10 mg/kg (-6.2/+2.8)"), and reduce the bottom dead-space by adjusting margin settings so the chart fills the canvas more evenly.

AI Feedback for Next Attempt

The implementation is strong on correctness, data storytelling, and code quality -- 84/100 is solid. The main remaining improvement areas are: (1) shorten the amber callout legend label so it is not truncated; (2) reduce the empty bottom-canvas area below the legend by adjusting margin settings. Design polish (DE-02) is limited by pygal's constraints, but the visual hierarchy (amber callout + baseline reference) already lifts DE-03 above default.

Verdict: APPROVED

@github-actions github-actions Bot added quality:84 Quality score 84/100 ai-approved Quality OK, ready for merge and removed quality:88 Quality score: 88/100 labels Jun 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit 2f88785 into main Jun 30, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/errorbar-basic/pygal branch June 30, 2026 20:54
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:84 Quality score 84/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant