From 84e3d8e2497a98e72010bb488fb6b8df197ccd81 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 10:31:19 +0000 Subject: [PATCH 1/4] chore(plotly): add metadata for ternary-density --- .../implementations/python/plotly.py | 122 +++++----- .../metadata/python/plotly.yaml | 230 ++---------------- 2 files changed, 82 insertions(+), 270 deletions(-) diff --git a/plots/ternary-density/implementations/python/plotly.py b/plots/ternary-density/implementations/python/plotly.py index 7c6f962faf..12da29b555 100644 --- a/plots/ternary-density/implementations/python/plotly.py +++ b/plots/ternary-density/implementations/python/plotly.py @@ -1,93 +1,96 @@ -""" pyplots.ai +"""anyplot.ai ternary-density: Ternary Density Plot -Library: plotly 6.5.1 | Python 3.13.11 -Quality: 91/100 | Created: 2026-01-11 +Library: plotly | Python 3.13 +Quality: 91/100 | Updated: 2026-05-19 """ +import os + import numpy as np import plotly.graph_objects as go from scipy.stats import gaussian_kde -# Generate synthetic sediment composition data (sand/silt/clay) -np.random.seed(42) +# Theme tokens +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +GRID = "rgba(26,26,23,0.25)" if THEME == "light" else "rgba(240,239,232,0.25)" -# Create clustered compositional data with 3 distinct modes +# Data — synthetic sediment composition (sand/silt/clay) +np.random.seed(42) n_samples = 500 -# Cluster 1: Sand-dominant samples (common in beaches/rivers) -cluster1_a = np.random.beta(8, 2, n_samples // 3) * 70 + 25 # Sand: 25-95% -cluster1_b = np.random.beta(2, 5, n_samples // 3) * 40 # Silt: 0-40% +# Cluster 1: Sand-dominant samples (beaches/river channels) +cluster1_a = np.random.beta(8, 2, n_samples // 3) * 70 + 25 +cluster1_b = np.random.beta(2, 5, n_samples // 3) * 40 cluster1_c = 100 - cluster1_a - cluster1_b mask1 = cluster1_c >= 0 cluster1_a, cluster1_b, cluster1_c = cluster1_a[mask1], cluster1_b[mask1], cluster1_c[mask1] -# Cluster 2: Silt-dominant samples (common in floodplains) -cluster2_b = np.random.beta(6, 2, n_samples // 3) * 60 + 30 # Silt: 30-90% -cluster2_a = np.random.beta(2, 4, n_samples // 3) * 35 # Sand: 0-35% +# Cluster 2: Silt-dominant samples (floodplains/estuaries) +cluster2_b = np.random.beta(7, 2, n_samples // 3) * 55 + 35 +cluster2_a = np.random.beta(2, 5, n_samples // 3) * 30 cluster2_c = 100 - cluster2_a - cluster2_b mask2 = cluster2_c >= 0 cluster2_a, cluster2_b, cluster2_c = cluster2_a[mask2], cluster2_b[mask2], cluster2_c[mask2] -# Cluster 3: Mixed samples (balanced composition) -cluster3_a = np.random.beta(3, 3, n_samples // 3) * 50 + 20 # Sand: 20-70% -cluster3_b = np.random.beta(3, 3, n_samples // 3) * 50 + 10 # Silt: 10-60% -cluster3_c = 100 - cluster3_a - cluster3_b -mask3 = cluster3_c >= 0 +# Cluster 3: Clay-dominant mixed samples (deep lake sediments) +cluster3_c = np.random.beta(6, 2, n_samples // 3) * 50 + 30 +cluster3_a = np.random.beta(2, 4, n_samples // 3) * 35 +cluster3_b = 100 - cluster3_a - cluster3_c +mask3 = cluster3_b >= 0 cluster3_a, cluster3_b, cluster3_c = cluster3_a[mask3], cluster3_b[mask3], cluster3_c[mask3] -# Combine all clusters +# Combine clusters sand = np.concatenate([cluster1_a, cluster2_a, cluster3_a]) silt = np.concatenate([cluster1_b, cluster2_b, cluster3_b]) clay = np.concatenate([cluster1_c, cluster2_c, cluster3_c]) -# Normalize to ensure sum = 100 +# Normalize to sum = 100 total = sand + silt + clay sand = sand / total * 100 silt = silt / total * 100 clay = clay / total * 100 -# Convert ternary coordinates to Cartesian for KDE -# Using standard ternary to Cartesian transformation +# Convert ternary → Cartesian for KDE x_cart = 0.5 * (2 * silt + clay) / 100 y_cart = (np.sqrt(3) / 2) * clay / 100 -# Perform 2D kernel density estimation +# 2D kernel density estimation coords = np.vstack([x_cart, y_cart]) kde = gaussian_kde(coords, bw_method="scott") -# Create grid for density estimation (in Cartesian space) +# Evaluation grid (Cartesian space) grid_size = 100 x_grid = np.linspace(0, 1, grid_size) y_grid = np.linspace(0, np.sqrt(3) / 2, grid_size) xx, yy = np.meshgrid(x_grid, y_grid) grid_coords = np.vstack([xx.ravel(), yy.ravel()]) -# Evaluate KDE on grid density = kde(grid_coords).reshape(xx.shape) -# Mask points outside the triangle -# Point is inside triangle if: y >= 0, y <= sqrt(3)*x, y <= sqrt(3)*(1-x) +# Mask outside the ternary triangle inside_triangle = (yy >= 0) & (yy <= np.sqrt(3) * xx) & (yy <= np.sqrt(3) * (1 - xx)) density[~inside_triangle] = np.nan -# Convert grid back to ternary coordinates for plotting -# Inverse transformation: clay = y * 2/sqrt(3) * 100, silt = (x - clay/200) * 100 +# Back to ternary coordinates for plotting clay_grid = yy * (2 / np.sqrt(3)) * 100 silt_grid = (xx - clay_grid / 200) * 100 sand_grid = 100 - silt_grid - clay_grid -# Create figure with ternary axes +# Plot fig = go.Figure() -# Add density heatmap using scatterternary with colored markers +# Density layer — Viridis-colored scatter markers valid_mask = inside_triangle & ~np.isnan(density) a_flat = sand_grid[valid_mask] b_flat = silt_grid[valid_mask] c_flat = clay_grid[valid_mask] d_flat = density[valid_mask] -# Add filled contours as a scatter ternary with colorscale fig.add_trace( go.Scatterternary( a=a_flat, @@ -100,32 +103,33 @@ "colorscale": "Viridis", "showscale": True, "colorbar": { - "title": {"text": "Density", "font": {"size": 20}}, - "tickfont": {"size": 16}, + "title": {"text": "Density", "font": {"size": 20, "color": INK}}, + "tickfont": {"size": 16, "color": INK_SOFT}, "len": 0.7, "thickness": 25, "x": 1.02, + "bgcolor": ELEVATED_BG, + "bordercolor": INK_SOFT, + "borderwidth": 1, }, - "opacity": 0.8, + "opacity": 0.85, }, hovertemplate="Sand: %{a:.1f}%
Silt: %{b:.1f}%
Clay: %{c:.1f}%", showlegend=False, ) ) -# Add contour lines for key density levels +# Contour lines at key density percentiles +contour_color = "rgba(255,255,255,0.85)" if THEME == "light" else "rgba(240,239,232,0.85)" contour_levels = np.percentile(d_flat, [25, 50, 75, 90]) for level in contour_levels: - # Find points near this density level level_mask = np.abs(density - level) < (np.nanmax(density) - np.nanmin(density)) * 0.02 level_mask = level_mask & valid_mask if np.sum(level_mask) > 10: - # Sort points by angle from centroid for contour line a_level = sand_grid[level_mask] b_level = silt_grid[level_mask] c_level = clay_grid[level_mask] - # Convert to Cartesian, compute angles, sort x_level = 0.5 * (2 * b_level + c_level) / 100 y_level = (np.sqrt(3) / 2) * c_level / 100 cx, cy = np.mean(x_level), np.mean(y_level) @@ -138,52 +142,58 @@ b=np.append(b_level[sort_idx], b_level[sort_idx][0]), c=np.append(c_level[sort_idx], c_level[sort_idx][0]), mode="lines", - line={"color": "rgba(255, 255, 255, 0.6)", "width": 2}, + line={"color": contour_color, "width": 2.5}, hoverinfo="skip", showlegend=False, ) ) -# Update layout for ternary plot +# Style fig.update_layout( title={ - "text": "Sediment Composition Distribution · ternary-density · plotly · pyplots.ai", - "font": {"size": 28}, + "text": "Sediment Composition Distribution · ternary-density · python · plotly · anyplot.ai", + "font": {"size": 26, "color": INK}, "x": 0.5, "xanchor": "center", }, + paper_bgcolor=PAGE_BG, + plot_bgcolor=PAGE_BG, + font={"color": INK}, ternary={ "sum": 100, + "bgcolor": PAGE_BG, "aaxis": { - "title": {"text": "Sand (%)", "font": {"size": 22}}, - "tickfont": {"size": 16}, + "title": {"text": "Sand (%)", "font": {"size": 22, "color": INK}}, + "tickfont": {"size": 16, "color": INK_SOFT}, "tickangle": 0, "dtick": 20, - "gridcolor": "rgba(0, 0, 0, 0.15)", + "gridcolor": GRID, + "linecolor": INK_SOFT, "linewidth": 2, }, "baxis": { - "title": {"text": "Silt (%)", "font": {"size": 22}}, - "tickfont": {"size": 16}, + "title": {"text": "Silt (%)", "font": {"size": 22, "color": INK}}, + "tickfont": {"size": 16, "color": INK_SOFT}, "tickangle": 45, "dtick": 20, - "gridcolor": "rgba(0, 0, 0, 0.15)", + "gridcolor": GRID, + "linecolor": INK_SOFT, "linewidth": 2, }, "caxis": { - "title": {"text": "Clay (%)", "font": {"size": 22}}, - "tickfont": {"size": 16}, + "title": {"text": "Clay (%)", "font": {"size": 22, "color": INK}}, + "tickfont": {"size": 16, "color": INK_SOFT}, "tickangle": -45, "dtick": 20, - "gridcolor": "rgba(0, 0, 0, 0.15)", + "gridcolor": GRID, + "linecolor": INK_SOFT, "linewidth": 2, }, - "bgcolor": "rgba(255, 255, 255, 1)", }, - template="plotly_white", + template="none", margin={"l": 80, "r": 120, "t": 100, "b": 80}, ) -# Save outputs -fig.write_image("plot.png", width=1600, height=900, scale=3) -fig.write_html("plot.html", include_plotlyjs="cdn") +# Save +fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3) +fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn") diff --git a/plots/ternary-density/metadata/python/plotly.yaml b/plots/ternary-density/metadata/python/plotly.yaml index 8a1ac883a3..3b23ef5f38 100644 --- a/plots/ternary-density/metadata/python/plotly.yaml +++ b/plots/ternary-density/metadata/python/plotly.yaml @@ -1,219 +1,21 @@ +# Per-library metadata for plotly implementation of ternary-density +# Auto-generated by impl-generate.yml + library: plotly +language: python specification_id: ternary-density created: '2026-01-11T09:31:17Z' -updated: '2026-01-11T09:35:45Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20892890889 +updated: '2026-05-19T10:31:19Z' +generated_by: claude-sonnet +workflow_run: 26091196427 issue: 3696 -python_version: 3.13.11 -library_version: 6.5.1 -preview_url: https://storage.googleapis.com/anyplot-images/plots/ternary-density/plotly/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/ternary-density/plotly/plot.html -quality_score: 91 +language_version: 3.13.13 +library_version: 6.7.0 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.html +quality_score: null review: - strengths: - - Excellent implementation of ternary density using Scatterternary with KDE-colored - markers - - Proper Viridis colormap as specified for perceptually uniform density visualization - - Grid lines visible beneath density layer as required - - Interactive hover tooltips showing Sand/Silt/Clay percentages - - Clean, well-structured code with proper seed for reproducibility - - Contour lines at percentile levels (25th, 50th, 75th, 90th) enhance interpretation - - Realistic sediment composition context with distinct clusters - weaknesses: - - Contour lines (white with alpha 0.6) could be more prominent for easier density - level interpretation - - Grid at alpha 0.15 is quite subtle; alpha 0.25-0.3 might improve readability - - Silt-dominant and mixed clusters are less visually distinct than the sand-dominant - cluster - image_description: 'The plot displays a ternary density visualization for sediment - composition with three vertices labeled Sand (%), Silt (%), and Clay (%). The - density is rendered using small circular markers colored according to the Viridis - colormap, ranging from dark purple (low density ~0) to yellow (high density ~6). - The triangular plot shows multiple density hotspots: a prominent high-density - region (yellow) near the Sand vertex indicating sand-dominant samples, and additional - concentration areas visible in teal/green colors in the mid-regions. White contour - lines overlay the density field at key percentile levels. Grid lines at 20% intervals - are visible beneath the density layer. A vertical colorbar on the right shows - the density scale. The title follows the correct format with the spec-id, library, - and pyplots.ai branding.' - criteria_checklist: - visual_quality: - score: 37 - max: 40 - items: - - id: VQ-01 - name: Text Legibility - score: 10 - max: 10 - passed: true - comment: Title at 28pt, axis labels at 22pt, tick labels at 16pt - all clearly - readable - - id: VQ-02 - name: No Overlap - score: 8 - max: 8 - passed: true - comment: No overlapping text elements; labels well positioned outside triangle - - id: VQ-03 - name: Element Visibility - score: 7 - max: 8 - passed: true - comment: Marker size of 6 works well for density visualization; slightly small - but density pattern is clear - - id: VQ-04 - name: Color Accessibility - score: 5 - max: 5 - passed: true - comment: Viridis colormap is perceptually uniform and colorblind-safe - - id: VQ-05 - name: Layout Balance - score: 4 - max: 5 - passed: true - comment: Good canvas utilization; triangle fills ~60% of plot area; colorbar - well positioned - - id: VQ-06 - name: Axis Labels - score: 2 - max: 2 - passed: true - comment: 'All three axes labeled with units: Sand (%), Silt (%), Clay (%)' - - id: VQ-07 - name: Grid & Legend - score: 1 - max: 2 - passed: true - comment: Grid visible at alpha 0.15; colorbar present but grid could be slightly - more prominent - spec_compliance: - score: 24 - max: 25 - items: - - id: SC-01 - name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct ternary density plot with KDE overlay - - id: SC-02 - name: Data Mapping - score: 5 - max: 5 - passed: true - comment: Three components correctly mapped to ternary axes - - id: SC-03 - name: Required Features - score: 4 - max: 5 - passed: true - comment: Density heatmap via KDE present; contour lines present; contours - are subtle white lines - - id: SC-04 - name: Data Range - score: 3 - max: 3 - passed: true - comment: All data visible; axes span 0-100% - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Colorbar accurately shows density scale - - id: SC-06 - name: Title Format - score: 2 - max: 2 - passed: true - comment: Title correctly formatted with description, spec-id, library, and - pyplots.ai - data_quality: - score: 18 - max: 20 - items: - - id: DQ-01 - name: Feature Coverage - score: 7 - max: 8 - passed: true - comment: Shows 3 distinct clusters as intended; mixed cluster less visible - than sand-dominant - - id: DQ-02 - name: Realistic Context - score: 7 - max: 7 - passed: true - comment: Sediment composition is classic geological application; neutral scientific - context - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 5 - passed: true - comment: Percentages 0-100 appropriate; cluster distributions plausible for - real sediment - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Simple linear structure: imports, data generation, KDE, plot, save' - - id: CQ-02 - name: Reproducibility - score: 3 - max: 3 - passed: true - comment: np.random.seed(42) set at beginning - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: 'Only necessary imports: numpy, plotly.graph_objects, scipy.stats.gaussian_kde' - - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 - passed: true - comment: Uses current Plotly API - - id: CQ-05 - name: Output Correct - score: 1 - max: 1 - passed: true - comment: Saves as plot.png and plot.html - library_features: - score: 5 - max: 5 - items: - - id: LF-01 - name: Distinctive Features - score: 5 - max: 5 - passed: true - comment: Uses Plotly Scatterternary with interactive hover tooltips; exports - both PNG and HTML - verdict: APPROVED -impl_tags: - dependencies: - - scipy - techniques: - - colorbar - - hover-tooltips - - html-export - patterns: - - data-generation - - iteration-over-groups - dataprep: - - kde - styling: - - custom-colormap - - alpha-blending - - grid-styling + strengths: [] + weaknesses: [] From aea4845baf8eb6ff095b09614551193f56cc70d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 10:36:08 +0000 Subject: [PATCH 2/4] chore(plotly): update quality score 85 and review feedback for ternary-density --- .../implementations/python/plotly.py | 6 +- .../metadata/python/plotly.yaml | 241 +++++++++++++++++- 2 files changed, 237 insertions(+), 10 deletions(-) diff --git a/plots/ternary-density/implementations/python/plotly.py b/plots/ternary-density/implementations/python/plotly.py index 12da29b555..428836507f 100644 --- a/plots/ternary-density/implementations/python/plotly.py +++ b/plots/ternary-density/implementations/python/plotly.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai ternary-density: Ternary Density Plot -Library: plotly | Python 3.13 -Quality: 91/100 | Updated: 2026-05-19 +Library: plotly 6.7.0 | Python 3.13.13 +Quality: 85/100 | Updated: 2026-05-19 """ import os diff --git a/plots/ternary-density/metadata/python/plotly.yaml b/plots/ternary-density/metadata/python/plotly.yaml index 3b23ef5f38..df275f9905 100644 --- a/plots/ternary-density/metadata/python/plotly.yaml +++ b/plots/ternary-density/metadata/python/plotly.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for plotly implementation of ternary-density -# Auto-generated by impl-generate.yml - library: plotly language: python specification_id: ternary-density created: '2026-01-11T09:31:17Z' -updated: '2026-05-19T10:31:19Z' +updated: '2026-05-19T10:36:08Z' generated_by: claude-sonnet workflow_run: 26091196427 issue: 3696 @@ -15,7 +12,237 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/ternary-d preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.html -quality_score: null +quality_score: 85 review: - strengths: [] - weaknesses: [] + strengths: + - Correct use of go.Scatterternary with viridis density colorscale + - 'Full spec compliance: KDE overlay, contour lines, vertex labels with units, perceptually-uniform + colormap' + - Theme-adaptive chrome correctly implemented for both light and dark renders + - Realistic sediment composition data with three geologically plausible clusters + - All font sizes explicitly set; text readable in both renders + - Clean flat-script structure with seed, clean imports, both PNG and HTML output + weaknesses: + - Contour lines are noisy and jagged due to angle-sort approach — use smooth interpolation + or scipy.ndimage for cleaner contours + - Title font size is 26px instead of the recommended 28px + - Grid opacity is 0.25, slightly above the recommended 10-15% range + - DE-01 reduced by messy contour rendering; consider using go.Contour projected + onto ternary or proper contour smoothing + - Some canvas corner waste inherent to triangular layout — could be improved with + adjusted margins or a square canvas + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct, not pure white. + Chrome: Title "Sediment Composition Distribution · ternary-density · python · plotly · anyplot.ai" in dark ink, clearly readable. Axis labels "Sand (%)", "Silt (%)", "Clay (%)" readable. Tick labels small but legible (16px). Colorbar label "Density" visible. + Data: Viridis colorscale density markers filling the ternary triangle (purple=low density, yellow=high density). White contour lines visible but jagged/noisy — scatter-point contours sorted by angle produce a dotted/irregular appearance rather than smooth isolines. Three density hotspots visible (sand-dominant lower-right, silt-dominant left, clay-dominant lower-left). + Legibility verdict: PASS — all text readable against light background. + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct, not pure black. + Chrome: Title and axis labels render in light ink on dark background, clearly readable. Tick labels visible. No dark-on-dark failures. + Data: Viridis colorscale colors are identical to light render — only chrome flips. Contour lines now render as light-on-dark, still noisy/jagged but visible. + Legibility verdict: PASS — all text readable against dark background. + criteria_checklist: + visual_quality: + score: 27 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All sizes explicitly set; title 26px (spec recommends 28px), axis + labels 22px, ticks 16px — all readable in both themes + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping elements in ternary layout + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Density markers size=6 create effective mosaic; viridis makes density + differences clear, but slightly small for 4800x2700 canvas + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Viridis is perceptually uniform and CVD-safe + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: Triangle fills ~60-70% of canvas; corner waste is inherent to triangular + geometry but could be improved + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: 'All axes labeled with units: Sand (%), Silt (%), Clay (%)' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Viridis for continuous density data; correct backgrounds #FAF8F1/#1A1A17; + theme-adaptive chrome in both renders' + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 4 + max: 8 + passed: false + comment: Well-configured with viridis and theme chrome, but contour lines + are noisy/jagged (angle-sort produces scattered dots, not smooth isolines) + — reduces professional polish + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: false + comment: template='none' removes defaults, margins explicitly set, colorbar + styled; grid opacity 0.25 slightly above recommended 10-15% + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: false + comment: Three distinct geological clusters create visual hierarchy; viridis + draws eye to density hotspots; no cluster annotations but focal points are + clear + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct ternary density plot using go.Scatterternary with KDE density + coloring and contour lines + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Viridis colormap, grid lines beneath density, vertex labels, contour + lines at percentile levels — all present + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: a=sand, b=silt, c=clay correctly mapped; KDE conversion Cartesian<->ternary + correct + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: 'Title: ''Sediment Composition Distribution · ternary-density · python + · plotly · anyplot.ai'' matches format; colorbar labeled correctly' + data_quality: + score: 14 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 5 + max: 6 + passed: true + comment: Three clusters (sand-dominant, silt-dominant, clay-dominant) cover + most ternary space; good density variation + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Sediment composition (sand/silt/clay) is a real geological application; + cluster labels (beaches, floodplains, deep lake sediments) are realistic + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Components normalized to sum to 100%; geologically plausible proportions + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Flat script: imports → data → KDE → plot → save' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: 'All imports used: os, numpy, plotly.graph_objects, scipy.stats.gaussian_kde' + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean Pythonic code; contour angle-sort is manual but reasonable + for ternary + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html; current plotly API + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: go.Scatterternary with colorbar, hovertemplate, update_layout(ternary={...}) + — idiomatic graph_objects usage + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: go.Scatterternary is Plotly-specific; interactive HTML export; custom + hover tooltips with ternary coordinates + verdict: REJECTED +impl_tags: + dependencies: + - scipy + techniques: + - colorbar + - hover-tooltips + - html-export + patterns: + - data-generation + dataprep: + - kde + - normalization + styling: + - custom-colormap + - alpha-blending From 22943c3fe1906e675922164150a631e63ca7a0bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 10:42:58 +0000 Subject: [PATCH 3/4] fix(plotly): address review feedback for ternary-density Attempt 1/3 - fixes based on AI review --- .../implementations/python/plotly.py | 81 ++++++++++++------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/plots/ternary-density/implementations/python/plotly.py b/plots/ternary-density/implementations/python/plotly.py index 428836507f..13b8f8c82d 100644 --- a/plots/ternary-density/implementations/python/plotly.py +++ b/plots/ternary-density/implementations/python/plotly.py @@ -1,13 +1,26 @@ -""" anyplot.ai +"""anyplot.ai ternary-density: Ternary Density Plot Library: plotly 6.7.0 | Python 3.13.13 Quality: 85/100 | Updated: 2026-05-19 """ import os +import sys + +# Remove the script directory from sys.path so that sibling implementations +# (e.g. matplotlib.py) do not shadow installed packages. +_script_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path = [p for p in sys.path if os.path.abspath(p or os.getcwd()) != _script_dir] + +import matplotlib + + +matplotlib.use("Agg") +import matplotlib.pyplot as plt import numpy as np import plotly.graph_objects as go +from scipy import ndimage from scipy.stats import gaussian_kde @@ -17,7 +30,7 @@ ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" -GRID = "rgba(26,26,23,0.25)" if THEME == "light" else "rgba(240,239,232,0.25)" +GRID = "rgba(26,26,23,0.12)" if THEME == "light" else "rgba(240,239,232,0.12)" # Data — synthetic sediment composition (sand/silt/clay) np.random.seed(42) @@ -119,40 +132,50 @@ ) ) -# Contour lines at key density percentiles +# Smooth density for clean contour extraction +density_filled = density.copy() +density_filled[np.isnan(density_filled)] = 0 +smoothed = ndimage.gaussian_filter(density_filled, sigma=2) + +# Contour levels from smoothed valid region +smoothed_valid_vals = smoothed[inside_triangle] +contour_levels = np.percentile(smoothed_valid_vals[smoothed_valid_vals > 0], [25, 50, 75, 90]) + +# Extract smooth contour paths via matplotlib (data extraction only, no display) +fig_tmp, ax_tmp = plt.subplots() +CS = ax_tmp.contour(xx, yy, smoothed, levels=contour_levels) +plt.close(fig_tmp) + contour_color = "rgba(255,255,255,0.85)" if THEME == "light" else "rgba(240,239,232,0.85)" -contour_levels = np.percentile(d_flat, [25, 50, 75, 90]) -for level in contour_levels: - level_mask = np.abs(density - level) < (np.nanmax(density) - np.nanmin(density)) * 0.02 - level_mask = level_mask & valid_mask - if np.sum(level_mask) > 10: - a_level = sand_grid[level_mask] - b_level = silt_grid[level_mask] - c_level = clay_grid[level_mask] - - x_level = 0.5 * (2 * b_level + c_level) / 100 - y_level = (np.sqrt(3) / 2) * c_level / 100 - cx, cy = np.mean(x_level), np.mean(y_level) - angles = np.arctan2(y_level - cy, x_level - cx) - sort_idx = np.argsort(angles) - - fig.add_trace( - go.Scatterternary( - a=np.append(a_level[sort_idx], a_level[sort_idx][0]), - b=np.append(b_level[sort_idx], b_level[sort_idx][0]), - c=np.append(c_level[sort_idx], c_level[sort_idx][0]), - mode="lines", - line={"color": contour_color, "width": 2.5}, - hoverinfo="skip", - showlegend=False, +for segs in CS.allsegs: + for seg in segs: + if len(seg) < 5: + continue + x_c, y_c = seg[:, 0], seg[:, 1] + # Cartesian → ternary + clay_c = y_c * (2 / np.sqrt(3)) * 100 + silt_c = (x_c - clay_c / 200) * 100 + sand_c = 100 - silt_c - clay_c + # Filter to valid ternary region + valid = (sand_c >= 0) & (silt_c >= 0) & (clay_c >= 0) + if valid.sum() > 5: + fig.add_trace( + go.Scatterternary( + a=sand_c[valid], + b=silt_c[valid], + c=clay_c[valid], + mode="lines", + line={"color": contour_color, "width": 2.5}, + hoverinfo="skip", + showlegend=False, + ) ) - ) # Style fig.update_layout( title={ "text": "Sediment Composition Distribution · ternary-density · python · plotly · anyplot.ai", - "font": {"size": 26, "color": INK}, + "font": {"size": 28, "color": INK}, "x": 0.5, "xanchor": "center", }, From bb68c47aaba5d0fdab8954b8c606f125272c918c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 10:48:58 +0000 Subject: [PATCH 4/4] chore(plotly): update quality score 91 and review feedback for ternary-density --- .../implementations/python/plotly.py | 4 +- .../metadata/python/plotly.yaml | 163 +++++++++--------- 2 files changed, 83 insertions(+), 84 deletions(-) diff --git a/plots/ternary-density/implementations/python/plotly.py b/plots/ternary-density/implementations/python/plotly.py index 13b8f8c82d..35eafa4f0b 100644 --- a/plots/ternary-density/implementations/python/plotly.py +++ b/plots/ternary-density/implementations/python/plotly.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai ternary-density: Ternary Density Plot Library: plotly 6.7.0 | Python 3.13.13 -Quality: 85/100 | Updated: 2026-05-19 +Quality: 91/100 | Updated: 2026-05-19 """ import os diff --git a/plots/ternary-density/metadata/python/plotly.yaml b/plots/ternary-density/metadata/python/plotly.yaml index df275f9905..4f990d6c8c 100644 --- a/plots/ternary-density/metadata/python/plotly.yaml +++ b/plots/ternary-density/metadata/python/plotly.yaml @@ -2,7 +2,7 @@ library: plotly language: python specification_id: ternary-density created: '2026-01-11T09:31:17Z' -updated: '2026-05-19T10:36:08Z' +updated: '2026-05-19T10:48:57Z' generated_by: claude-sonnet workflow_run: 26091196427 issue: 3696 @@ -12,40 +12,41 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/ternary-d preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/ternary-density/python/plotly/plot-dark.html -quality_score: 85 +quality_score: 91 review: strengths: - - Correct use of go.Scatterternary with viridis density colorscale - - 'Full spec compliance: KDE overlay, contour lines, vertex labels with units, perceptually-uniform - colormap' - - Theme-adaptive chrome correctly implemented for both light and dark renders - - Realistic sediment composition data with three geologically plausible clusters - - All font sizes explicitly set; text readable in both renders - - Clean flat-script structure with seed, clean imports, both PNG and HTML output + - 'Perfect spec compliance: KDE, contour lines at percentile levels, vertex labels, + grid, and viridis density colormap all delivered' + - Geologically realistic three-cluster dataset (beach/floodplain/deep-lake) makes + excellent use of the sediment composition context + - 'Theme-adaptive chrome correctly applied across all elements: title, axis labels, + tick fonts, colorbar, backgrounds' + - Flat canvas size (4800x2700) and font sizes within spec + - Matplotlib used only for data extraction (contour paths) with plt.close() properly + called — no fake interactivity weaknesses: - - Contour lines are noisy and jagged due to angle-sort approach — use smooth interpolation - or scipy.ndimage for cleaner contours - - Title font size is 26px instead of the recommended 28px - - Grid opacity is 0.25, slightly above the recommended 10-15% range - - DE-01 reduced by messy contour rendering; consider using go.Contour projected - onto ternary or proper contour smoothing - - Some canvas corner waste inherent to triangular layout — could be improved with - adjusted margins or a square canvas + - Tick font size is 16px vs recommended 18px for pixel-based libraries — minor readability + reduction at full canvas + - White contour color (rgba(255,255,255,0.85)) in the light theme has variable contrast + against bright viridis regions; a dark semi-transparent color would maintain contrast + across both themes more robustly + - Scatter-marker density approach creates a slightly dotted texture rather than + a fully smooth continuous heatmap surface image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct, not pure white. - Chrome: Title "Sediment Composition Distribution · ternary-density · python · plotly · anyplot.ai" in dark ink, clearly readable. Axis labels "Sand (%)", "Silt (%)", "Clay (%)" readable. Tick labels small but legible (16px). Colorbar label "Density" visible. - Data: Viridis colorscale density markers filling the ternary triangle (purple=low density, yellow=high density). White contour lines visible but jagged/noisy — scatter-point contours sorted by angle produce a dotted/irregular appearance rather than smooth isolines. Three density hotspots visible (sand-dominant lower-right, silt-dominant left, clay-dominant lower-left). - Legibility verdict: PASS — all text readable against light background. + Background: Warm off-white #FAF8F1 — correct theme surface, not pure white + Chrome: Title "Sediment Composition Distribution · ternary-density · python · plotly · anyplot.ai" in dark ink, clearly readable. Axis labels Sand (%), Silt (%), Clay (%) in dark ink at 22px, readable. Tick labels at 0/20/40/60/80/100 in secondary ink at 16px, readable though slightly small. + Data: Viridis-colored scatter markers (~10000 points) fill the ternary triangle showing three distinct density clusters — sand apex (top), silt corner (bottom-left), clay corner (bottom-right). White contour lines at 25/50/75/90th percentile density levels overlay the surface. Viridis colorbar on right labeled "Density". + Legibility verdict: PASS Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct, not pure black. - Chrome: Title and axis labels render in light ink on dark background, clearly readable. Tick labels visible. No dark-on-dark failures. - Data: Viridis colorscale colors are identical to light render — only chrome flips. Contour lines now render as light-on-dark, still noisy/jagged but visible. - Legibility verdict: PASS — all text readable against dark background. + Background: Warm near-black #1A1A17 — correct dark theme surface, not pure black + Chrome: Title in light text (#F0EFE8), clearly readable against dark background. Axis labels and tick labels in secondary light text (#B8B7B0), readable. Colorbar fonts are light-themed. No dark-on-dark failures observed. + Data: Same viridis colorscale as light render — data colors identical, only chrome flips. Three density clusters more visually dramatic against the dark surface; yellow-green peaks contrast sharply with deep-purple low-density areas. White contour lines highly visible in dark theme. + Legibility verdict: PASS criteria_checklist: visual_quality: - score: 27 + score: 28 max: 30 items: - id: VQ-01 @@ -53,74 +54,69 @@ review: score: 7 max: 8 passed: true - comment: All sizes explicitly set; title 26px (spec recommends 28px), axis - labels 22px, ticks 16px — all readable in both themes + comment: All text readable in both themes; tick font 16px slightly below recommended + 18px for pixel-based libs - id: VQ-02 name: No Overlap - score: 6 + score: 5 max: 6 passed: true - comment: No overlapping elements in ternary layout + comment: Minor tick label crowding on ternary axes at lower values - id: VQ-03 name: Element Visibility - score: 5 + score: 6 max: 6 passed: true - comment: Density markers size=6 create effective mosaic; viridis makes density - differences clear, but slightly small for 4800x2700 canvas + comment: Density surface and contour lines clearly visible in both themes - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Viridis is perceptually uniform and CVD-safe + comment: Viridis is perceptually uniform and colorblind-safe - id: VQ-05 name: Layout & Canvas - score: 3 + score: 4 max: 4 passed: true - comment: Triangle fills ~60-70% of canvas; corner waste is inherent to triangular - geometry but could be improved + comment: 4800x2700 px, good proportions, nothing cut off - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: 'All axes labeled with units: Sand (%), Silt (%), Clay (%)' + comment: Sand (%), Silt (%), Clay (%) with units; descriptive title - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Viridis for continuous density data; correct backgrounds #FAF8F1/#1A1A17; - theme-adaptive chrome in both renders' + comment: 'Viridis for continuous density data; correct backgrounds #FAF8F1/#1A1A17' design_excellence: - score: 12 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 4 + score: 6 max: 8 - passed: false - comment: Well-configured with viridis and theme chrome, but contour lines - are noisy/jagged (angle-sort produces scattered dots, not smooth isolines) - — reduces professional polish + passed: true + comment: Viridis density surface + contour lines at percentile levels + themed + colorbar show deliberate design choices - id: DE-02 name: Visual Refinement score: 4 max: 6 - passed: false - comment: template='none' removes defaults, margins explicitly set, colorbar - styled; grid opacity 0.25 slightly above recommended 10-15% + passed: true + comment: template=none removes defaults; styled colorbar with themed fonts/border/bg; + ternary bg matches page surface - id: DE-03 name: Data Storytelling score: 4 max: 6 - passed: false - comment: Three distinct geological clusters create visual hierarchy; viridis - draws eye to density hotspots; no cluster annotations but focal points are - clear + passed: true + comment: Three clusters map to distinct geological environments; contours + guide viewer; viridis naturally encodes density spec_compliance: score: 15 max: 15 @@ -130,53 +126,53 @@ review: score: 5 max: 5 passed: true - comment: Correct ternary density plot using go.Scatterternary with KDE density - coloring and contour lines + comment: Correct ternary density chart using go.Scatterternary with KDE-colored + markers - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Viridis colormap, grid lines beneath density, vertex labels, contour - lines at percentile levels — all present + comment: KDE via gaussian_kde, contour lines at 25/50/75/90th percentiles, + vertex labels, visible grid - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: a=sand, b=silt, c=clay correctly mapped; KDE conversion Cartesian<->ternary - correct + comment: Sand/silt/clay correctly mapped; all values normalized to sum to + 100% - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: 'Title: ''Sediment Composition Distribution · ternary-density · python - · plotly · anyplot.ai'' matches format; colorbar labeled correctly' + comment: Title matches required format; colorbar labeled Density data_quality: - score: 14 + score: 15 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 5 + score: 6 max: 6 passed: true - comment: Three clusters (sand-dominant, silt-dominant, clay-dominant) cover - most ternary space; good density variation + comment: Three geologically distinct clusters demonstrate sand/silt/clay dominated + sediment environments - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Sediment composition (sand/silt/clay) is a real geological application; - cluster labels (beaches, floodplains, deep lake sediments) are realistic + comment: Sediment composition is canonical ternary dataset from geoscience; + cluster parameters are geologically plausible - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Components normalized to sum to 100%; geologically plausible proportions + comment: 500 samples within 100-5000 recommended range; values 0-100% summing + to 100% code_quality: score: 10 max: 10 @@ -186,60 +182,63 @@ review: score: 3 max: 3 passed: true - comment: 'Flat script: imports → data → KDE → plot → save' + comment: Flat script, no functions or classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) + comment: np.random.seed(42) set - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: 'All imports used: os, numpy, plotly.graph_objects, scipy.stats.gaussian_kde' + comment: All imports used; matplotlib for contour extraction, scipy for KDE + and smoothing - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean Pythonic code; contour angle-sort is manual but reasonable - for ternary + comment: Matplotlib contour extraction is legitimate data-extraction pattern, + not fake UI - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html; current plotly API + comment: Saves plot-{THEME}.png (4800x2700) and plot-{THEME}.html library_mastery: - score: 7 + score: 9 max: 10 items: - id: LM-01 name: Idiomatic Usage - score: 4 + score: 5 max: 5 passed: true - comment: go.Scatterternary with colorbar, hovertemplate, update_layout(ternary={...}) - — idiomatic graph_objects usage + comment: go.Scatterternary is correct Plotly trace for ternary coordinates; + layout ternary dict properly configured - id: LM-02 name: Distinctive Features - score: 3 + score: 4 max: 5 passed: true - comment: go.Scatterternary is Plotly-specific; interactive HTML export; custom - hover tooltips with ternary coordinates - verdict: REJECTED + comment: Colorbar in marker dict, hovertemplate with ternary formatting, HTML + export; slight deduction for matplotlib contour workaround + verdict: APPROVED impl_tags: dependencies: - scipy + - matplotlib techniques: - colorbar - hover-tooltips - html-export patterns: - data-generation + - iteration-over-groups dataprep: - kde - normalization