Skip to content

feat(plotly): implement heatmap-rainflow#4478

Merged
github-actions[bot] merged 6 commits intomainfrom
implementation/heatmap-rainflow/plotly
Mar 2, 2026
Merged

feat(plotly): implement heatmap-rainflow#4478
github-actions[bot] merged 6 commits intomainfrom
implementation/heatmap-rainflow/plotly

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Mar 2, 2026

Implementation: heatmap-rainflow - plotly

Implements the plotly version of heatmap-rainflow.

File: plots/heatmap-rainflow/implementations/plotly.py

Parent Issue: #4465


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 2, 2026

AI Review - Attempt 1/3

Image Description

The plot displays a 20×20 heatmap on a white background with a warm cream-to-orange-to-dark-brown sequential colorscale. The title reads "heatmap-rainflow · plotly · pyplots.ai" in a serif font (Palatino/Georgia) with a smaller gray subtitle "Rainflow cycle counting matrix from a simulated variable-amplitude load history." The x-axis is labeled "Cycle Mean Stress (MPa)" ranging from −50 to 250, and the y-axis is labeled "Cycle Amplitude (MPa)" ranging from approximately 15 to 195. A colorbar on the right shows "Cycle Count" from ~50 to ~750. Zero-count bins appear as white gaps, clearly distinct from the populated bins. The primary cluster of high cycle counts (darkest cells, ~750 cycles) is centered around amplitude ~60 MPa and mean ~100 MPa. A secondary, weaker cluster is visible at low amplitude (~25 MPa) and higher mean (~160 MPa). Sparse faint cells appear at higher amplitudes. Thin white gaps separate each cell. The overall layout is square (3600×3600 px) with balanced margins.

Score: 88/100

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

Visual Quality (27/30)

  • VQ-01: Text Legibility (8/8) — All font sizes explicitly set: title 28pt, subtitle 17px, axis labels 22pt, tick fonts 18pt, colorbar title 20pt, colorbar ticks 16pt. All clearly readable.
  • VQ-02: No Overlap (6/6) — No overlapping text anywhere. Labels, ticks, title, and colorbar are well-separated.
  • VQ-03: Element Visibility (5/6) — Main heatmap cells are clearly visible with good color differentiation. Cell gaps help distinguish bins. However, very-low-count peripheral bins (pale cream #fff7ec) are barely distinguishable from the white zero-count background.
  • VQ-04: Color Accessibility (3/4) — Sequential cream→orange→brown scheme works for colorblind users (no red-green issue). However, the custom colorscale is not perceptually uniform; the library guide recommends viridis/plasma/cividis for sequential data.
  • VQ-05: Layout & Canvas (3/4) — Good square layout with balanced margins. The heatmap and colorbar fill the canvas reasonably well. Some wasted space at the top of the heatmap where NaN/zero cells dominate due to the data distribution.
  • VQ-06: Axis Labels & Title (2/2) — Both axes include descriptive labels with units: "Cycle Mean Stress (MPa)" and "Cycle Amplitude (MPa)."

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (6/8) — Strong design choices: custom serif font family (Palatino, Georgia), custom warm colorscale, intentional typographic hierarchy (title in dark #1a1a1a, labels in [area-basic] plotnine implementation #333, ticks in feat(plotnine): implement scatter-basic #444, subtitle in feat(plotly): implement donut-labeled #555), styled subtitle with letter-spacing. Clearly above defaults.
  • DE-02: Visual Refinement (4/6) — Uses plotly_white template for clean background, removed colorbar outline, cell gaps add polish, generous margins. Good refinement visible but not fully maxed.
  • DE-03: Data Storytelling (3/6) — The dual-cluster data pattern naturally draws the eye to the primary loading cluster, and the subtitle contextualizes the data. However, there are no annotations calling out the primary vs. secondary cluster or explaining their fatigue significance. The viewer must discover the pattern themselves.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct 2D heatmap with amplitude on y-axis and mean on x-axis, color intensity for cycle count.
  • SC-02: Required Features (4/4) — All spec features present: sequential colormap, colorbar with cycle count, axis labels with MPa units, tick labels at bin centers, zero-count bins visually distinct (white/transparent).
  • SC-03: Data Mapping (3/3) — Amplitude correctly on y-axis, mean on x-axis, axes show full data range.
  • SC-04: Title & Legend (3/3) — Title follows exact format "heatmap-rainflow · plotly · pyplots.ai". Colorbar title "Cycle Count" is appropriate. No legend needed for single heatmap.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Excellent: primary cluster (moderate amplitude/mean), secondary cluster (low amplitude/high mean representing vibration fatigue), sparse high-amplitude events, zero-count bins, wide range of cycle counts (0–800).
  • DQ-02: Realistic Context (5/5) — Fatigue analysis is a real engineering application. MPa stress units are correct. Multi-cluster pattern models realistic variable-amplitude loading with a primary loading plus vibration component.
  • DQ-03: Appropriate Scale (4/4) — Amplitude 10–200 MPa and mean −50 to 250 MPa are realistic for steel fatigue analysis. Cycle counts up to ~800 per bin are reasonable for binned rainflow data.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean linear flow: imports → data generation → plot creation → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) ensures deterministic output.
  • CQ-03: Clean Imports (2/2) — Only numpy and plotly.graph_objects imported; both fully used.
  • CQ-04: Code Elegance (2/2) — Clean, well-commented code. Gaussian mixture for data generation is elegant and appropriate. No over-engineering or fake functionality.
  • CQ-05: Output & API (1/1) — Saves as plot.png via write_image() and plot.html via write_html(). Uses current Plotly API.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) — Good use of Graph Objects API (go.Heatmap), dict-based layout configuration, plotly_white template, and hovertemplate for interactive tooltips.
  • LM-02: Distinctive Features (4/5) — Uses several Plotly-specific features: hovertemplate with <extra></extra> tag, xgap/ygap for cell spacing, connectgaps=False for NaN handling, and write_html for dual interactive output.

Score Caps Applied

  • None — No score caps triggered.

Strengths

  • Excellent data quality with multi-cluster Gaussian mixture modeling realistic fatigue loading patterns (primary load + vibration fatigue + sparse high-amplitude events)
  • Full spec compliance: all required features present, correct axes, units, and title format
  • Strong design choices: custom serif typography, warm custom colorscale, intentional typographic hierarchy with graduated font colors
  • Good use of Plotly-specific features (hovertemplate, xgap/ygap, connectgaps, dual PNG+HTML output)
  • Clean, well-commented, reproducible code

Weaknesses

  • Low-count peripheral bins barely distinguishable from zero-count white background due to very light starting color (#fff7ec)
  • Custom colorscale is not perceptually uniform (library guide recommends viridis/plasma/cividis for sequential data)
  • No data storytelling annotations — the dual-cluster pattern has a clear engineering narrative (primary loading vs. vibration fatigue) that goes unexplained

Issues Found

  1. VQ-03 MINOR: Pale cream (#fff7ec) starting color makes low-count bins nearly invisible against white background
    • Fix: Use a slightly more saturated starting color, or switch to a perceptually-uniform colorscale like Plasma or Inferno where low values are more visible
  2. VQ-04 MINOR: Custom colorscale is not perceptually uniform as recommended by library rules
    • Fix: Consider using Plotly's built-in Inferno, Plasma, or Hot colorscale, or adjust custom scale for better perceptual uniformity
  3. DE-03 LOW: No storytelling — viewer must discover the dual-cluster pattern and its engineering significance themselves
    • Fix: Add annotations labeling the primary loading cluster and the secondary vibration fatigue cluster to create a clear narrative

AI Feedback for Next Attempt

To reach 90+: (1) Improve data storytelling by adding 1-2 annotations labeling the primary and secondary clusters with their engineering meaning (e.g., "Primary loading" and "Vibration fatigue"). (2) Consider switching to a perceptually-uniform colorscale (Inferno or Plasma) or adjusting the custom scale's starting color so low-count bins are more visible against the white background. These changes would strengthen DE-03 and VQ-03/VQ-04 by 4+ points.

Verdict: REJECTED

@github-actions github-actions bot added quality:88 Quality score: 88/100 ai-rejected Quality not OK, triggers update labels Mar 2, 2026
@github-actions github-actions bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Mar 2, 2026
Attempt 1/3 - fixes based on AI review
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions bot commented Mar 2, 2026

🔧 Repair Attempt 1/3

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 2, 2026

AI Review - Attempt 2/3

Image Description

The plot displays a 1200×1200 (3600×3600 at scale=3) square heatmap using the Plasma colorscale against a white background. The x-axis shows "Cycle Mean Stress (MPa)" ranging from −50 to 250, and the y-axis shows "Cycle Amplitude (MPa)" ranging from ~15 to 200. Two prominent clusters are visible: a bright yellow primary cluster centered around amplitude ~60 MPa / mean ~100 MPa (reaching ~800 cycles), and a secondary pink/magenta cluster at lower amplitude (~25–30 MPa) / higher mean (~160 MPa). Three callout annotations with arrows explain the engineering significance: "Primary loading — High-cycle fatigue from main service loads", "Vibration fatigue — Low-amplitude, high-mean resonance-induced cycles", and "Rare overload events". Zero-count bins render as white gaps. The colorbar on the right is labeled "Cycle Count". The title reads "heatmap-rainflow · plotly · pyplots.ai" with a subtitle. Typography uses Palatino/Georgia serif. Cell gaps (xgap/ygap=1) provide clean visual separation between bins.

Score: 90/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All major font sizes explicitly set (title 28, axes 22, ticks 18, colorbar title 20, colorbar ticks 16). The "Rare overload events" annotation uses font size 13 which is noticeably smaller than other text, slightly reducing legibility consistency.
  • VQ-02: No Overlap (6/6) — All annotations well-positioned without overlap. Text boxes use semi-transparent backgrounds preventing collisions with data.
  • VQ-03: Element Visibility (6/6) — Heatmap cells clearly visible with good color differentiation. Cell gaps (xgap/ygap=1) make individual bins distinguishable. Plasma colorscale provides excellent perceptual uniformity from dark purple through pink to bright yellow.
  • VQ-04: Color Accessibility (4/4) — Plasma is a perceptually uniform, colorblind-safe sequential colorscale. Good contrast between zero-count (white) and low-count (dark purple) bins.
  • VQ-05: Layout & Canvas (3/4) — Good overall layout with balanced margins. Square 1:1 aspect ratio is appropriate for a matrix. Minor issue: upper rows (amplitudes 160–200) are mostly empty dark blue/zero, creating some visual dead space that slightly reduces canvas utilization.
  • VQ-06: Axis Labels & Title (2/2) — Both axes include physical units: "Cycle Mean Stress (MPa)" and "Cycle Amplitude (MPa)". Colorbar labeled "Cycle Count".

Design Excellence (15/20)

  • DE-01: Aesthetic Sophistication (6/8) — Strong design choices: custom serif typography (Palatino), Plasma colorscale (not default), multi-level text color hierarchy (#1a1a1a, [area-basic] plotnine implementation #333, feat(plotnine): implement scatter-basic #444, feat(plotly): implement donut-labeled #555), styled HTML subtitle, annotation boxes with semi-transparent backgrounds and subtle borders. Clearly above defaults but not quite FiveThirtyEight-level.
  • DE-02: Visual Refinement (4/6) — Good: plotly_white template provides clean look, cell gaps create visual separation, colorbar customized (no outline, appropriate thickness/length), custom margins. Some additional refinement possible.
  • DE-03: Data Storytelling (5/6) — Excellent: three annotations explain the engineering significance of the dual-cluster loading pattern. "Primary loading", "Vibration fatigue", and "Rare overload events" guide the viewer through the data story. The bright yellow primary cluster naturally draws the eye as focal point. Subtitle provides data source context.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct 2D heatmap representation of rainflow counting matrix.
  • SC-02: Required Features (4/4) — All spec requirements met: 2D heatmap with amplitude on y-axis and mean on x-axis, sequential colormap (Plasma), colorbar with cycle count, axis labels with MPa units, tick labels at bin centers, zero-count bins visually distinct (white via NaN).
  • SC-03: Data Mapping (3/3) — Amplitude correctly on y-axis, mean on x-axis, color intensity represents cycle frequency.
  • SC-04: Title & Legend (3/3) — Title follows exact format "heatmap-rainflow · plotly · pyplots.ai". Colorbar serves as legend with appropriate "Cycle Count" label.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows full range: high-frequency bins (800+ cycles in bright yellow), medium-frequency (200–400 in pink/magenta), low-frequency (dark purple), and zero-count (white). Two distinct clusters plus sparse overload events demonstrate multiple loading patterns.
  • DQ-02: Realistic Context (5/5) — Fatigue analysis is a genuine engineering application. Dual-cluster pattern (primary service loading + vibration fatigue) is realistic for mechanical components. Annotations provide meaningful domain context.
  • DQ-03: Appropriate Scale (4/4) — Amplitude range 10–200 MPa and mean stress range −50 to 250 MPa are realistic for fatigue loading. Cycle counts up to ~800 are plausible for a binned rainflow matrix. The Gaussian clustering pattern is representative of real load spectra.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean linear flow: imports → data generation → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) ensures deterministic output.
  • CQ-03: Clean Imports (2/2) — Only numpy and plotly.graph_objects, both fully used.
  • CQ-04: Code Elegance (2/2) — Clean, well-organized code with helpful comments explaining the data generation logic (three Gaussian clusters representing different loading phenomena). Appropriate complexity.
  • CQ-05: Output & API (1/1) — Saves as plot.png via write_image() and plot.html via write_html(). Current Plotly API used throughout.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Good use of go.Figure() with go.Heatmap(), update_layout(), and add_annotation(). Dict-style configuration for colorbar and layout is idiomatic Plotly GO. Could have used px.imshow() for a higher-level approach but GO is appropriate for this level of customization.
  • LM-02: Distinctive Features (3/5) — Uses several Plotly-specific features: hovertemplate for formatted interactive hover text, xgap/ygap for cell spacing, connectgaps=False for NaN handling, HTML in title (<sup>, <br>), and dual output (PNG + HTML) leveraging Plotly's interactive capabilities.

Score Caps Applied

  • None

Strengths

  • Excellent data storytelling with three domain-specific annotations explaining the engineering significance of loading patterns
  • Professional typography using Palatino serif font family with intentional text color hierarchy
  • Plasma colorscale provides excellent colorblind-safe visualization with clear distinction between zero-count and low-count bins
  • Realistic dual-cluster fatigue loading pattern with appropriate physical units
  • Clean, well-commented code structure with proper reproducibility (seed=42)
  • Smart use of NaN for zero-count bins creating white gaps that contrast effectively with the Plasma palette

Weaknesses

  • Minor annotation font size inconsistency (13pt for "Rare overload events" vs 15pt for other annotations)
  • Some visual dead space in upper rows (amplitudes 160–200) where most bins are zero
  • Could leverage Plotly's unique interactive capabilities more deeply (custom buttons, dropdown filters, range sliders)

Issues Found

  1. VQ-01 MINOR: "Rare overload events" annotation uses font size 13 vs 15 for other annotations
    • Fix: Use consistent 15px font size across all annotations
  2. VQ-05 MINOR: Upper amplitude rows (160-200 MPa) mostly empty, creating dead space
    • Fix: Consider tightening y-axis range or adjusting data to better utilize the space

AI Feedback for Next Attempt

Strong implementation that reaches publication quality. The data storytelling with domain-specific annotations is a standout feature. Minor refinements to annotation font consistency and canvas utilization in the upper amplitude range would further polish this already excellent visualization.

Verdict: APPROVED

@github-actions github-actions bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge labels Mar 2, 2026
@github-actions github-actions bot merged commit cb7a17f into main Mar 2, 2026
@github-actions github-actions bot deleted the implementation/heatmap-rainflow/plotly branch March 2, 2026 21:25
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 quality:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants