diff --git a/plots/ternary-density/implementations/python/plotly.py b/plots/ternary-density/implementations/python/plotly.py
index 7c6f962faf..35eafa4f0b 100644
--- a/plots/ternary-density/implementations/python/plotly.py
+++ b/plots/ternary-density/implementations/python/plotly.py
@@ -1,93 +1,109 @@
-""" 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 6.7.0 | Python 3.13.13
+Quality: 91/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
-# 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.12)" if THEME == "light" else "rgba(240,239,232,0.12)"
-# 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,90 +116,107 @@
"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_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)
- 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": "rgba(255, 255, 255, 0.6)", "width": 2},
- hoverinfo="skip",
- showlegend=False,
+# 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)"
+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,
+ )
)
- )
-# 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": 28, "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..4f990d6c8c 100644
--- a/plots/ternary-density/metadata/python/plotly.yaml
+++ b/plots/ternary-density/metadata/python/plotly.yaml
@@ -1,160 +1,178 @@
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:48:57Z'
+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
+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: 91
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
+ - '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 (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.'
+ - 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 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 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: 37
- max: 40
+ score: 28
+ max: 30
items:
- id: VQ-01
name: Text Legibility
- score: 10
- max: 10
+ score: 7
+ max: 8
passed: true
- comment: Title at 28pt, axis labels at 22pt, tick labels at 16pt - all clearly
- readable
+ 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: 8
- max: 8
+ score: 5
+ max: 6
passed: true
- comment: No overlapping text elements; labels well positioned outside triangle
+ comment: Minor tick label crowding on ternary axes at lower values
- id: VQ-03
name: Element Visibility
- score: 7
- max: 8
+ score: 6
+ max: 6
passed: true
- comment: Marker size of 6 works well for density visualization; slightly small
- but density pattern is clear
+ comment: Density surface and contour lines clearly visible in both themes
- id: VQ-04
name: Color Accessibility
- score: 5
- max: 5
+ score: 2
+ max: 2
passed: true
- comment: Viridis colormap is perceptually uniform and colorblind-safe
+ comment: Viridis is perceptually uniform and colorblind-safe
- id: VQ-05
- name: Layout Balance
+ name: Layout & Canvas
score: 4
- max: 5
+ max: 4
passed: true
- comment: Good canvas utilization; triangle fills ~60% of plot area; colorbar
- well positioned
+ comment: 4800x2700 px, good proportions, nothing cut off
- id: VQ-06
- name: Axis Labels
+ name: Axis Labels & Title
score: 2
max: 2
passed: true
- comment: 'All three axes labeled with units: Sand (%), Silt (%), Clay (%)'
+ comment: Sand (%), Silt (%), Clay (%) with units; descriptive title
- id: VQ-07
- name: Grid & Legend
- score: 1
+ name: Palette Compliance
+ score: 2
max: 2
passed: true
- comment: Grid visible at alpha 0.15; colorbar present but grid could be slightly
- more prominent
+ comment: 'Viridis for continuous density data; correct backgrounds #FAF8F1/#1A1A17'
+ design_excellence:
+ score: 14
+ max: 20
+ items:
+ - id: DE-01
+ name: Aesthetic Sophistication
+ score: 6
+ max: 8
+ 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: 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: true
+ comment: Three clusters map to distinct geological environments; contours
+ guide viewer; viridis naturally encodes density
spec_compliance:
- score: 24
- max: 25
+ score: 15
+ max: 15
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
+ comment: Correct ternary density chart using go.Scatterternary with KDE-colored
+ markers
+ - id: SC-02
name: Required Features
score: 4
- max: 5
+ max: 4
passed: true
- comment: Density heatmap via KDE present; contour lines present; contours
- are subtle white lines
- - id: SC-04
- name: Data Range
+ 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: 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
+ 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 correctly formatted with description, spec-id, library, and
- pyplots.ai
+ comment: Title matches required format; colorbar labeled Density
data_quality:
- score: 18
- max: 20
+ score: 15
+ max: 15
items:
- id: DQ-01
name: Feature Coverage
- score: 7
- max: 8
+ score: 6
+ max: 6
passed: true
- comment: Shows 3 distinct clusters as intended; mixed cluster less visible
- than sand-dominant
+ comment: Three geologically distinct clusters demonstrate sand/silt/clay dominated
+ sediment environments
- id: DQ-02
name: Realistic Context
- score: 7
- max: 7
+ score: 5
+ max: 5
passed: true
- comment: Sediment composition is classic geological application; neutral scientific
- context
+ comment: Sediment composition is canonical ternary dataset from geoscience;
+ cluster parameters are geologically plausible
- id: DQ-03
name: Appropriate Scale
score: 4
- max: 5
+ max: 4
passed: true
- comment: Percentages 0-100 appropriate; cluster distributions plausible for
- real sediment
+ comment: 500 samples within 100-5000 recommended range; values 0-100% summing
+ to 100%
code_quality:
score: 10
max: 10
@@ -164,46 +182,56 @@ review:
score: 3
max: 3
passed: true
- comment: 'Simple linear structure: imports, data generation, KDE, plot, save'
+ comment: Flat script, no functions or classes
- id: CQ-02
name: Reproducibility
- score: 3
- max: 3
+ score: 2
+ max: 2
passed: true
- comment: np.random.seed(42) set at beginning
+ comment: np.random.seed(42) set
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
- comment: 'Only necessary imports: 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: No Deprecated API
- score: 1
- max: 1
+ name: Code Elegance
+ score: 2
+ max: 2
passed: true
- comment: Uses current Plotly API
+ comment: Matplotlib contour extraction is legitimate data-extraction pattern,
+ not fake UI
- id: CQ-05
- name: Output Correct
+ name: Output & API
score: 1
max: 1
passed: true
- comment: Saves as plot.png and plot.html
- library_features:
- score: 5
- max: 5
+ comment: Saves plot-{THEME}.png (4800x2700) and plot-{THEME}.html
+ library_mastery:
+ score: 9
+ max: 10
items:
- - id: LF-01
- name: Distinctive Features
+ - id: LM-01
+ name: Idiomatic Usage
score: 5
max: 5
passed: true
- comment: Uses Plotly Scatterternary with interactive hover tooltips; exports
- both PNG and HTML
+ comment: go.Scatterternary is correct Plotly trace for ternary coordinates;
+ layout ternary dict properly configured
+ - id: LM-02
+ name: Distinctive Features
+ score: 4
+ max: 5
+ passed: true
+ 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
@@ -213,7 +241,7 @@ impl_tags:
- iteration-over-groups
dataprep:
- kde
+ - normalization
styling:
- custom-colormap
- alpha-blending
- - grid-styling