Skip to content

feat(plotly): implement ecdf-basic#9485

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/ecdf-basic/plotly
Jun 25, 2026
Merged

feat(plotly): implement ecdf-basic#9485
MarkusNeusinger merged 6 commits into
mainfrom
implementation/ecdf-basic/plotly

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: ecdf-basic - python/plotly

Implements the python/plotly version of ecdf-basic.

File: plots/ecdf-basic/implementations/python/plotly.py

Parent Issue: #976


🤖 impl-generate workflow

github-actions Bot added 2 commits June 25, 2026 09:29
Regen from quality 88. Addressed:
- Canvas: fixed from width=1600,height=900,scale=3 (4800×2700) to width=800,height=450,scale=4 (3200×1800)
- Change request: switched domain from marathon times to HTTP API latency (lognormal distribution)
- GRID opacity: corrected from 0.10 to 0.15 per style guide
- Font sizes: aligned to canonical plotly sizes (title=16px, axis=12px, ticks=10px)
- Added sys.path fix to prevent plotly.py filename from shadowing the installed package
@claude

claude Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot displays an ECDF step function on a warm off-white (#FAF8F1) background. The brand green (#009E73) line rises steeply from ~50ms to ~350ms (covering 0%–99% of requests), then flattens to a long right tail extending to ~850ms. The Y-axis shows cumulative proportion from 0%–100% in 10% increments; the X-axis shows response time from ~50ms to 850ms. Title "HTTP API Latency · ecdf-basic · python · plotly · anyplot.ai" is centered in dark text, clearly readable. Axis labels "Cumulative Proportion of Requests" (Y) and "Response Time (ms)" (X) are visible in dark ink. All tick labels (0%–100%, 100–800) are clearly legible against the light background. Subtle grid lines add readability without competing with data. No text is light-on-light. Legibility verdict: PASS.

Dark render (plot-dark.png): Same plot on the warm near-black (#1A1A17) surface. The brand green ECDF line is identical in color and shape to the light render — only chrome flips. Title and axis labels render in near-white (#F0EFE8), clearly readable against the dark background. Tick labels in the secondary ink (#B8B7B0) are legible. Grid lines are subtle with appropriate light-on-dark opacity. No dark-on-dark failures detected. No text is obscured or inverted. Brand green #009E73 reads clearly on the dark surface. Legibility verdict: PASS.

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

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 (7/8) — Title, axis labels, and tick labels are all clearly readable in both themes. Font sizes follow style-guide defaults (title 16px, axis labels 12px, tick labels 10px). Minor: rotated Y-axis label could benefit from slightly larger weight at the source canvas size, but is acceptable.
  • VQ-02: No Overlap (6/6) — No element collisions. Clean spacing throughout.
  • VQ-03: Element Visibility (6/6) — Medium-density data (400 points) rendered as a line — appropriate choice. Brand green reads crisply in both themes. Step function shape is clear.
  • VQ-04: Color Accessibility (2/2) — Single-series brand green is CVD-safe. No red-green-only encoding.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed (3200×1800). Margins set correctly (l=80, r=40, t=80, b=60). No overflow or clipping.
  • VQ-06: Axis Labels & Title (2/2) — "Response Time (ms)" and "Cumulative Proportion of Requests" are descriptive and include units.
  • VQ-07: Palette Compliance (2/2) — First (only) series is #009E73. Plot backgrounds are #FAF8F1 (light) / #1A1A17 (dark). All chrome tokens theme-adaptive.

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Realistic lognormal latency scenario elevates above a generic random-normal ECDF. Clean use of brand green on warm surface. The data story is clear. However, no annotations for key percentiles (P50, P90, P99) which would add immediate analytical value for the API latency context.
  • DE-02: Visual Refinement (3/6) — Top/right spines removed (mirror=False). Grid uses the correct 15% opacity token. L-shaped axis frame. Hover tooltip is clean. Room to further reduce chrome (e.g., hide tick marks entirely) for a more stripped-back look.
  • DE-03: Data Storytelling (3/6) — Lognormal latency distribution tells a realistic story (bulk of requests 100–300ms, long right tail). The step function naturally exposes percentiles, but no reference lines or annotations guide the reader to key quantiles (P50 ≈ 120ms, P90 ≈ 220ms) — a missed opportunity given the API latency context.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct ECDF step function using go.Scatter with shape="hv".
  • SC-02: Required Features (4/4) — Step function increases by 1/n at each point; Y-axis 0–1 (rendered as 0%–100%); grid lines present; 2.5px line width provides clarity.
  • SC-03: Data Mapping (3/3) — X = sorted latency values; Y = cumulative proportion. All 400 data points covered.
  • SC-04: Title & Legend (3/3) — Title "HTTP API Latency · ecdf-basic · python · plotly · anyplot.ai" follows required format with descriptive prefix. No legend needed for single series.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Full ECDF range (0%–100%), step function shape clearly visible, Y-axis correctly range-locked with dtick=0.1.
  • DQ-02: Realistic Context (5/5) — HTTP API response latency is a canonical ECDF use case. Lognormal distribution with mean=4.8, sigma=0.5 models real-world latency well. Neutral, professional.
  • DQ-03: Appropriate Scale (4/4) — 400 requests, latency range ~40–850ms is realistic for a web API. Seed=42 for reproducibility.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script, no functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) ensures deterministic output.
  • CQ-03: Clean Imports (2/2) — Only os, sys, numpy, plotly.graph_objects — all used.
  • CQ-04: Code Elegance (2/2) — sys.path manipulation to avoid script shadowing the plotly package is well-handled and clearly motivated. Appropriate complexity.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html correctly.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — go.Scatter with line.shape="hv" is the correct Plotly idiom for ECDF step functions. hovertemplate and hovermode="x unified" are well-configured. Custom toolbar via write_html config is idiomatic. Minor: px.ecdf() exists as a higher-level convenience specifically for ECDF — not using it is acceptable but worth noting.
  • LM-02: Distinctive Features (3/5) — Uses hover tooltips with formatted template, unified hover mode, HTML export with custom modeBar config. These are genuinely Plotly-distinctive (not available in static libraries). Interactive hover showing latency + cumulative % is a real UX benefit.

Score Caps Applied

  • None

Strengths

  • Correct ECDF implementation using go.Scatter shape="hv" — proper step-function semantics
  • Realistic lognormal latency data with appropriate domain context (HTTP API)
  • Perfect theme-adaptive chrome: all tokens correctly applied for both light and dark renders
  • Clean, flat code with reproducible seed and idiomatic Plotly patterns
  • Correct canvas size (3200×1800) and output files (PNG + HTML)

Weaknesses

  • No percentile reference lines or annotations (P50, P90, P99) — adding dashed horizontal reference lines at key quantiles with annotations would significantly boost storytelling for an API latency ECDF
  • Top/right spines not fully suppressed: showline=True with mirror=False keeps left/bottom lines. Consider setting showline=False and relying on the plot area boundary alone for a cleaner look
  • The long right tail (400ms–850ms) occupies ~50% of the X-axis width but contains only ~1% of data points — consider trimming the x-axis range to P99.5 (~450ms) and annotating the tail behavior

Issues Found

  1. DE-03 MEDIUM: No key-percentile annotations to guide interpretation of the API latency distribution.
    • Fix: Add dashed horizontal reference lines at P50, P90, P99 with text annotations showing the ms values.
  2. DE-02 MEDIUM: Visible axis spine lines (showline=True) add chrome without adding information.
    • Fix: Set showline=False on both axes; the step function and grid already define the data space.
  3. DE-01 MINOR: Right portion of X-axis (~400–850ms) is nearly empty — very sparse data in the tail.
    • Fix: Consider setting x-range to np.percentile(sorted_latency, 99.5) and adding a tail annotation.

AI Feedback for Next Attempt

This is a solid ECDF implementation. To push into the 90+ range, add percentile reference lines: compute P50/P90/P99 values and draw dashed horizontal lines at y=0.50/0.90/0.99 with annotations showing the corresponding ms value. Also remove the axis spine lines (showline=False) for cleaner minimalism, and consider trimming the x-range to cut wasted space in the tail. The hover template and HTML output are good — keep them.

Verdict: APPROVED

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

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The ECDF step function is plotted on a warm off-white background (#FAF8F1). A single green (#009E73) step line rises from 0 to ~100% cumulative proportion of requests against response time (ms) on the x-axis. Three annotated percentile crosshairs appear as dotted horizontal and vertical reference lines labeled P50 (125 ms, at 50%), P90 (220 ms, at 90%), and P99 (364 ms, at 99%). The title "HTTP API Latency · ecdf-basic · python · plotly · anyplot.ai" is centered at the top and clearly readable. Axis labels "Response Time (ms)" and "Cumulative Proportion of Requests" are visible and descriptive. Tick labels use dark muted ink, all legible. Subtle grid lines span both axes. No text is light-on-light — all elements are clearly readable against the warm off-white background.

Dark render (plot-dark.png): The same plot on a warm near-black (#1A1A17) background. The ECDF step line remains identical green (#009E73) — data color is unchanged from the light render. The title, axis labels, and tick labels now render in light-colored text (warm cream) against the dark background. The percentile annotations (P50, P90, P99) also render in the muted light-gray (INK_SOFT dark variant). Dotted reference lines remain subtle. Grid lines are appropriately faint on the dark surface. No dark-on-dark issues — all text is clearly readable against the dark background. Chrome flipped correctly; data color stayed constant.

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

Score: 88/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title=16, axis=12, ticks=10, annotations=10); proportions balanced; both themes fully legible. Minus 1 for the P50 annotation being slightly crowded against the ECDF step line near that region.
  • VQ-02: No Overlap (5/6) — Clean overall; minor visual crowding where the P50 annotation sits very close to the ECDF curve at the 50% mark. All text readable but not perfectly separated from data.
  • VQ-03: Element Visibility (6/6) — ECDF step line (width=2.5) is well-sized for 400 data points; sharp and clear against both backgrounds.
  • VQ-04: Color Accessibility (2/2) — Single series with brand green; percentile lines in muted gray; no red-green sole-distinction encoding.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed; margins (l=80, r=40, t=80, b=60) appropriate; plot area well-utilized; no clipping.
  • VQ-06: Axis Labels & Title (2/2) — "Response Time (ms)" and "Cumulative Proportion of Requests" — both descriptive with units/context.
  • VQ-07: Palette Compliance (2/2) — First (only) series is #009E73; backgrounds #FAF8F1 (light) / #1A1A17 (dark); all chrome tokens theme-adaptive; data color identical in both renders.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above generic defaults: real-world domain (HTTP latency), lognormal distribution for authentic shape, P50/P90/P99 crosshairs add analytical value. Clean Inter typography. Not yet at publication-ready FiveThirtyEight level.
  • DE-02: Visual Refinement (4/6) — Spines removed (showline=False on both axes), subtle 15%-opacity grid, explicit font family (Inter), theme-aware hover labels. Good refinement; zeroline removed; clean layout.
  • DE-03: Data Storytelling (4/6) — The P50/P90/P99 annotated percentile crosshairs actively guide the viewer to key SLA-relevant percentiles. The lognormal distribution shows the realistic long right tail of latency. Viewer immediately sees where the 90th and 99th percentiles fall.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct ECDF step function using go.Scatter with shape="hv" (horizontal-then-vertical); cumulative proportion mapped to y-axis.
  • SC-02: Required Features (4/4) — Step function increasing by 1/n; y-axis 0–1 range; grid lines present; distinct line style; percentile reference lines add value beyond spec.
  • SC-03: Data Mapping (3/3) — X: sorted latency values (continuous); Y: cumulative proportion (0–1); all 400 data points represented.
  • SC-04: Title & Legend (3/3) — Title "HTTP API Latency · ecdf-basic · python · plotly · anyplot.ai" follows the optional-prefix format correctly. No legend (single series, showlegend=False) — appropriate.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Demonstrates the full ECDF shape, long right tail from lognormal distribution, and direct percentile reading at P50/P90/P99.
  • DQ-02: Realistic Context (5/5) — HTTP API response latency is a highly realistic, business-relevant scenario. Lognormal distribution is the standard model for real-world latency. Neutral topic.
  • DQ-03: Appropriate Scale (4/4) — P50≈125ms, P90≈220ms, P99≈364ms — completely plausible for a web service API. 400 requests is realistic for a benchmark sample.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear flow: imports → sys.path fix → data → ECDF → shapes/annotations → layout → save. No functions/classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) ✓
  • CQ-03: Clean Imports (2/2) — os, sys, numpy, plotly.graph_objects — all used.
  • CQ-04: Code Elegance (2/2) — Clean loop for percentile reference lines; sys.path manipulation is necessary and commented; no over-engineering.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html with current Plotly API ✓

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — add_trace/add_shape/add_annotation idiom; hovermode="x unified"; hovertemplate with <extra></extra>; update_layout pattern. Very idiomatic. Minor: px.ecdf() would be even higher-level for this use case.
  • LM-02: Distinctive Features (3/5) — line.shape="hv" (native Plotly step rendering); hovermode="x unified" (traces synchronized on hover); custom modeBar configuration in HTML export; theme-aware hoverlabel — multiple Plotly-specific features used together.

Score Caps Applied

  • None

Strengths

  • Lognormal distribution for HTTP latency is a technically accurate data choice that produces a realistic and instructive ECDF shape
  • P50/P90/P99 annotated crosshairs transform a basic ECDF into an actionable performance analysis tool — directly reads SLA thresholds
  • Full theme-adaptive chrome using all correct tokens (INK, INK_SOFT, GRID, PAGE_BG, ELEVATED_BG); dark render passes the dark-on-dark readability check cleanly
  • sys.path manipulation is a legitimate and well-commented fix for the plotly.py filename-shadowing issue
  • Compact, well-structured code with no unnecessary abstraction

Weaknesses

  • P50 annotation ("P50 125 ms") placement at xanchor="left"/yanchor="bottom" at the 50% intersection point sits very close to the ECDF step line, causing minor visual crowding — consider shifting yshift up to 8-10 or placing the label above the line with more breathing room
  • Design excellence is solid but not at the top tier — adding a subtle shaded region (e.g., fill between 0 and the ECDF line, or a shaded p90-p99 tail zone in a muted color) could elevate the storytelling and aesthetic sophistication further

Issues Found

  1. VQ-02 MINOR: P50 annotation crowding — the "P50 125 ms" text at yshift=4 sits very close to the rising ECDF step line at that y-value
    • Fix: Increase yshift to 8–12 for P50 annotation, or offset xshift more aggressively (12–15) so the label clears the step line
  2. DE-01 MEDIUM: Aesthetic could advance further — the design is clean and analytical but lacks a distinctive visual anchor
    • Fix: Consider adding a very subtle filled area under the ECDF curve (low alpha fill) or a shaded band highlighting the p90-p99 region to create stronger visual hierarchy

AI Feedback for Next Attempt

The implementation is clean, technically sound, and tells a clear performance story through percentile annotations. The main improvement areas are: (1) increase the yshift/xshift on the P50 annotation to prevent it from touching the ECDF step line, and (2) add a subtle design accent — e.g., a low-opacity fill under the ECDF curve using the brand green at alpha=0.08–0.12 — to elevate from "well-configured default" to "publication-ready." Both changes are minor and could push this from 88 to 92+.

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-approved Quality OK, ready for merge and removed quality:87 Quality score 87/100 labels Jun 25, 2026
@MarkusNeusinger MarkusNeusinger merged commit a2518d7 into main Jun 25, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/ecdf-basic/plotly branch June 25, 2026 09:44
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:88 Quality score: 88/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant