From 986f4f3c9366a6f720ca575a684f0bded6bd0764 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 07:44:42 +0000 Subject: [PATCH 1/3] chore(highcharts): add metadata for spectrogram-basic --- .../implementations/python/highcharts.py | 150 ++++++------ .../metadata/python/highcharts.yaml | 216 ++---------------- 2 files changed, 100 insertions(+), 266 deletions(-) diff --git a/plots/spectrogram-basic/implementations/python/highcharts.py b/plots/spectrogram-basic/implementations/python/highcharts.py index 80fc049a82..60d28e3035 100644 --- a/plots/spectrogram-basic/implementations/python/highcharts.py +++ b/plots/spectrogram-basic/implementations/python/highcharts.py @@ -1,12 +1,13 @@ -""" pyplots.ai +"""anyplot.ai spectrogram-basic: Spectrogram Time-Frequency Heatmap -Library: highcharts unknown | Python 3.13.11 -Quality: 91/100 | Created: 2025-12-31 +Library: highcharts | Python 3.13 +Quality: pending | Created: 2025-05-15 """ -import tempfile +import os +import threading import time -import urllib.request +from http.server import HTTPServer, SimpleHTTPRequestHandler from pathlib import Path import numpy as np @@ -18,7 +19,15 @@ from selenium.webdriver.chrome.options import Options -# Generate chirp signal (frequency increases over time) +# 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.10)" if THEME == "light" else "rgba(240,239,232,0.10)" + +# Data np.random.seed(42) sample_rate = 1000 # 1000 Hz sampling rate duration = 2.0 # 2 seconds @@ -28,7 +37,7 @@ f0, f1 = 10, 200 chirp_signal = signal.chirp(t, f0=f0, f1=f1, t1=duration, method="linear") -# Add some noise for realism +# Add noise for realism noise = 0.1 * np.random.randn(len(t)) combined_signal = chirp_signal + noise @@ -40,7 +49,7 @@ # Convert to dB scale for better visualization Sxx_db = 10 * np.log10(Sxx + 1e-10) -# Get dB range for colorbar (use actual dB values, not normalized) +# Get dB range for colorbar Sxx_min = float(Sxx_db.min()) Sxx_max = float(Sxx_db.max()) @@ -70,40 +79,46 @@ "type": "heatmap", "width": 4800, "height": 2700, - "backgroundColor": "#ffffff", - "marginTop": 160, # Increased for subtitle + "backgroundColor": PAGE_BG, + "marginTop": 160, "marginBottom": 250, "marginLeft": 200, - "marginRight": 320, # Increased for legend title spacing + "marginRight": 320, } -# Title and subtitle +# Title chart.options.title = { - "text": "spectrogram-basic · highcharts · pyplots.ai", - "style": {"fontSize": "48px", "fontWeight": "bold"}, + "text": "spectrogram-basic · highcharts · anyplot.ai", + "style": {"fontSize": "28px", "fontWeight": "bold", "color": INK}, } +# Subtitle chart.options.subtitle = { "text": "Linear chirp signal (10-200 Hz) with linear frequency axis", - "style": {"fontSize": "32px", "color": "#666666"}, + "style": {"fontSize": "22px", "color": INK_SOFT}, } # X-axis (time) time_labels = [f"{t:.2f}" for t in times_ds] chart.options.x_axis = { "categories": time_labels, - "title": {"text": "Time (seconds)", "style": {"fontSize": "36px"}}, - "labels": {"style": {"fontSize": "24px"}, "step": max(1, len(time_labels) // 10)}, - "tickLength": 10, + "title": {"text": "Time (seconds)", "style": {"fontSize": "22px", "color": INK}}, + "labels": {"style": {"fontSize": "18px", "color": INK_SOFT}, "step": max(1, len(time_labels) // 10)}, + "lineColor": INK_SOFT, + "tickColor": INK_SOFT, + "gridLineColor": GRID, } # Y-axis (frequency) freq_labels = [f"{f:.0f}" for f in frequencies_ds] chart.options.y_axis = { "categories": freq_labels, - "title": {"text": "Frequency (Hz)", "style": {"fontSize": "36px"}}, - "labels": {"style": {"fontSize": "24px"}, "step": max(1, len(freq_labels) // 10)}, + "title": {"text": "Frequency (Hz)", "style": {"fontSize": "22px", "color": INK}}, + "labels": {"style": {"fontSize": "18px", "color": INK_SOFT}, "step": max(1, len(freq_labels) // 10)}, "reversed": False, + "lineColor": INK_SOFT, + "tickColor": INK_SOFT, + "gridLineColor": GRID, } # Color axis (legend for heatmap intensity) - use actual dB values @@ -117,7 +132,7 @@ [0.75, "#5ec962"], # green [1, "#fde725"], # yellow ], - "labels": {"style": {"fontSize": "24px"}, "format": "{value:.0f} dB"}, + "labels": {"style": {"fontSize": "18px", "color": INK_SOFT}, "format": "{value:.0f} dB"}, } # Legend @@ -127,15 +142,19 @@ "verticalAlign": "middle", "symbolHeight": 800, "symbolWidth": 40, - "x": -20, # Shift legend left to avoid edge cramping - "title": {"text": "Power (dB)", "style": {"fontSize": "28px"}}, + "x": -20, + "title": {"text": "Power (dB)", "style": {"fontSize": "22px", "color": INK}}, + "itemStyle": {"color": INK_SOFT}, + "backgroundColor": ELEVATED_BG, + "borderColor": INK_SOFT, + "borderWidth": 1, } -# Tooltip - show actual dB values +# Tooltip chart.options.tooltip = { "headerFormat": "", "pointFormat": "Time: {point.x_label} s
Frequency: {point.y_label} Hz
Power: {point.value:.1f} dB", - "style": {"fontSize": "20px"}, + "style": {"fontSize": "16px"}, } # Series @@ -146,35 +165,41 @@ chart.add_series(series) -# Download Highcharts JS and heatmap module -highcharts_url = "https://code.highcharts.com/highcharts.js" -with urllib.request.urlopen(highcharts_url, timeout=30) as response: - highcharts_js = response.read().decode("utf-8") - -heatmap_url = "https://code.highcharts.com/modules/heatmap.js" -with urllib.request.urlopen(heatmap_url, timeout=30) as response: - heatmap_js = response.read().decode("utf-8") - -# Generate HTML with inline scripts +# Generate chart JavaScript html_str = chart.to_js_literal() + +# HTML with unpkg CDN (Cloudflare-friendly alternative) html_content = f""" - - + + - +
""" -# Write temp HTML and take screenshot -with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f: +# Save interactive HTML +with open(f"plot-{THEME}.html", "w", encoding="utf-8") as f: f.write(html_content) - temp_path = f.name + +# Start simple HTTP server in background thread to serve HTML +class QuietHTTPRequestHandler(SimpleHTTPRequestHandler): + def log_message(self, format, *args): + pass + + +html_dir = Path.cwd() +server = HTTPServer(("127.0.0.1", 0), QuietHTTPRequestHandler) +port = server.server_port +server_thread = threading.Thread(target=server.serve_forever, daemon=True) +server_thread.start() + +# Take screenshot with Selenium via HTTP chrome_options = Options() chrome_options.add_argument("--headless") chrome_options.add_argument("--no-sandbox") @@ -182,27 +207,22 @@ chrome_options.add_argument("--disable-gpu") chrome_options.add_argument("--window-size=4800,2700") -driver = webdriver.Chrome(options=chrome_options) -driver.get(f"file://{temp_path}") -time.sleep(5) # Wait for chart to render -driver.save_screenshot("plot.png") -driver.quit() - -Path(temp_path).unlink() # Clean up temp file - -# Also save HTML for interactive version -with open("plot.html", "w", encoding="utf-8") as f: - interactive_html = f""" - - - - spectrogram-basic · highcharts · pyplots.ai - - - - -
- - -""" - f.write(interactive_html) +try: + driver = webdriver.Chrome(options=chrome_options) + driver.set_page_load_timeout(30) + driver.get(f"http://127.0.0.1:{port}/plot-{THEME}.html") + + # Wait for container to be visible and chart to render + time.sleep(20) + + # Additional wait to ensure rendering is complete + try: + driver.execute_script("return document.readyState === 'complete' && window.Highcharts !== undefined") + except Exception: + pass + + time.sleep(2) + driver.save_screenshot(f"plot-{THEME}.png") + driver.quit() +finally: + server.shutdown() diff --git a/plots/spectrogram-basic/metadata/python/highcharts.yaml b/plots/spectrogram-basic/metadata/python/highcharts.yaml index cacee0527b..f628b1cd60 100644 --- a/plots/spectrogram-basic/metadata/python/highcharts.yaml +++ b/plots/spectrogram-basic/metadata/python/highcharts.yaml @@ -1,207 +1,21 @@ +# Per-library metadata for highcharts implementation of spectrogram-basic +# Auto-generated by impl-generate.yml + library: highcharts +language: python specification_id: spectrogram-basic created: '2025-12-31T05:36:53Z' -updated: '2025-12-31T06:07:15Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20612809126 +updated: '2026-05-15T07:44:42Z' +generated_by: claude-haiku +workflow_run: 25906243314 issue: 2927 -python_version: 3.13.11 +python_version: 3.13.13 library_version: unknown -preview_url: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/highcharts/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/highcharts/plot.html -quality_score: 91 -impl_tags: - dependencies: - - scipy - - selenium - techniques: - - colorbar - - html-export - patterns: - - data-generation - dataprep: [] - styling: [] +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.html +quality_score: null review: - strengths: - - Clear visualization of the chirp signal with frequency increasing over time (diagonal - yellow band is unmistakable) - - Excellent use of viridis colormap for colorblind accessibility - - Proper dB scale labeling on colorbar with actual dB values (-100 to -10 dB range) - - Clean code structure with scipy spectrogram computation - - Both PNG and interactive HTML outputs generated - - Appropriate downsampling for Highcharts heatmap performance - weaknesses: - - No grid lines on the heatmap area (would improve readability at specific time/frequency - points) - - Y-axis shows frequencies up to ~469 Hz but the chirp only goes to 200 Hz (wasted - vertical space showing noise) - image_description: The spectrogram displays a heatmap of a linear chirp signal. - The plot shows time (0.06 to 1.91 seconds) on the x-axis and frequency (0 to ~469 - Hz) on the y-axis. A clear diagonal yellow band sweeps from low frequencies at - early times to high frequencies at later times, representing the increasing frequency - of the chirp signal. The background is predominantly teal/green (mid-power levels) - with scattered darker blue/purple spots (low power). A vertical colorbar on the - right shows "Power (dB)" ranging from approximately -100 dB (purple) to -10 dB - (yellow), using a viridis colormap. The title reads "spectrogram-basic · highcharts - · pyplots.ai" with a subtitle "Linear chirp signal (10-200 Hz) with linear frequency - axis". - criteria_checklist: - visual_quality: - score: 36 - max: 40 - items: - - id: VQ-01 - name: Text Legibility - score: 9 - max: 10 - passed: true - comment: Title and axis labels are clearly readable; tick labels slightly - small but legible - - id: VQ-02 - name: No Overlap - score: 8 - max: 8 - passed: true - comment: No overlapping text elements - - id: VQ-03 - name: Element Visibility - score: 8 - max: 8 - passed: true - comment: Heatmap cells are appropriately sized for the data density - - id: VQ-04 - name: Color Accessibility - score: 5 - max: 5 - passed: true - comment: Viridis colormap is colorblind-safe - - id: VQ-05 - name: Layout Balance - score: 4 - max: 5 - passed: true - comment: Good canvas utilization; slight imbalance with right margin for legend - - id: VQ-06 - name: Axis Labels - score: 2 - max: 2 - passed: true - comment: '"Time (seconds)" and "Frequency (Hz)" with proper units' - - id: VQ-07 - name: Grid & Legend - score: 0 - max: 2 - passed: true - comment: No visible grid lines; legend/colorbar is present but lacks subtle - gridlines on plot - spec_compliance: - score: 25 - max: 25 - items: - - id: SC-01 - name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct heatmap spectrogram visualization - - id: SC-02 - name: Data Mapping - score: 5 - max: 5 - passed: true - comment: Time on x-axis, frequency on y-axis, power as color intensity - - id: SC-03 - name: Required Features - score: 5 - max: 5 - passed: true - comment: Colorbar with dB units, proper axis labels, perceptually uniform - colormap - - id: SC-04 - name: Data Range - score: 3 - max: 3 - passed: true - comment: Full time and frequency range displayed - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Colorbar correctly labeled "Power (dB)" - - id: SC-06 - name: Title Format - score: 2 - max: 2 - passed: true - comment: Uses correct format "{spec-id} · {library} · pyplots.ai" - data_quality: - score: 18 - max: 20 - items: - - id: DQ-01 - name: Feature Coverage - score: 7 - max: 8 - passed: true - comment: Chirp signal clearly shows frequency increasing over time; could - show additional signal features - - id: DQ-02 - name: Realistic Context - score: 7 - max: 7 - passed: true - comment: Signal processing context is realistic and neutral - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 5 - passed: true - comment: Frequencies 10-200 Hz appropriate; y-axis extends to ~500 Hz which - is fine but shows noise above signal range - code_quality: - score: 9 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear flow: imports → data → plot → save' - - id: CQ-02 - name: Reproducibility - score: 3 - max: 3 - passed: true - comment: Uses np.random.seed(42) - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: All imports are used - - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 - passed: true - comment: Uses current APIs - - id: CQ-05 - name: Output Correct - score: 0 - max: 1 - passed: false - comment: Saves as plot.png (correct) - library_features: - score: 3 - max: 5 - items: - - id: LF-01 - name: Uses distinctive library features - score: 3 - max: 5 - passed: true - comment: Uses Highcharts heatmap with proper color axis and tooltip; could - leverage more interactive features - verdict: APPROVED + strengths: [] + weaknesses: [] From 6093e318d711f264d9f5ae567c9359e75dbe8a64 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 21:58:55 +0000 Subject: [PATCH 2/3] chore(highcharts): update quality score 82 and review feedback for spectrogram-basic --- .../implementations/python/highcharts.py | 6 +- .../metadata/python/highcharts.yaml | 263 +++++++++++++++++- 2 files changed, 259 insertions(+), 10 deletions(-) diff --git a/plots/spectrogram-basic/implementations/python/highcharts.py b/plots/spectrogram-basic/implementations/python/highcharts.py index 60d28e3035..7d6c5366b3 100644 --- a/plots/spectrogram-basic/implementations/python/highcharts.py +++ b/plots/spectrogram-basic/implementations/python/highcharts.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai spectrogram-basic: Spectrogram Time-Frequency Heatmap -Library: highcharts | Python 3.13 -Quality: pending | Created: 2025-05-15 +Library: highcharts unknown | Python 3.13.13 +Quality: 82/100 | Updated: 2026-05-15 """ import os diff --git a/plots/spectrogram-basic/metadata/python/highcharts.yaml b/plots/spectrogram-basic/metadata/python/highcharts.yaml index f628b1cd60..229ebe0bcf 100644 --- a/plots/spectrogram-basic/metadata/python/highcharts.yaml +++ b/plots/spectrogram-basic/metadata/python/highcharts.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for highcharts implementation of spectrogram-basic -# Auto-generated by impl-generate.yml - library: highcharts language: python specification_id: spectrogram-basic created: '2025-12-31T05:36:53Z' -updated: '2026-05-15T07:44:42Z' +updated: '2026-05-15T21:58:54Z' generated_by: claude-haiku workflow_run: 25906243314 issue: 2927 @@ -15,7 +12,259 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/spectrogr preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.html -quality_score: null +quality_score: 82 review: - strengths: [] - weaknesses: [] + strengths: + - Correct spectrogram implementation using scipy.signal.spectrogram with real FFT + computation and dB scale + - Viridis colormap (via explicit stops) is perceptually uniform and colorblind-safe + — matches spec requirement + - 'Full theme-adaptive chrome: PAGE_BG, INK, INK_SOFT, ELEVATED_BG, GRID tokens + all correctly wired to ANYPLOT_THEME for both light and dark renders' + - Realistic chirp signal data (10-200 Hz sweep, 1000 Hz sample rate, 2 s duration + with noise) makes the spectrogram concept immediately comprehensible + - Title format is exact ('spectrogram-basic · highcharts · anyplot.ai'), subtitle + adds useful context + - 'Correct output: saves plot-THEME.png and plot-THEME.html with proper naming' + weaknesses: + - 'Y-axis category axis is not constrained: Highcharts auto-extends the category + range below index 0, generating spurious negative labels (-3, -9, -15, …, -99 + dB shown as Hz labels) in the lower portion of the chart. Fix: add ''min'': 0, + ''max'': len(frequencies_ds)-1 to the y_axis options to clamp the category axis + to valid range. This causes ~60% of the canvas to be wasted empty space.' + - 'HTTP server + CDN approach is over-engineered and fragile: the library guide + recommends downloading Highcharts JS and embedding it inline to avoid CDN dependency. + The current approach requires a local HTTP server, threading, and CDN availability. + Replace with urllib.request.urlopen to download highcharts.js and heatmap.js inline.' + - 'Design Excellence is generic: no spine removal, no intentional whitespace hierarchy, + legend box is a heavy bordered box. Refine by removing the legend border or reducing + its visual weight.' + - 'CQ-01: class definition (QuietHTTPRequestHandler) and threading add unnecessary + structural complexity for what should be a linear script.' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct theme surface. PASS. + Chrome: Title "spectrogram-basic · highcharts · anyplot.ai" visible at top center (dark text). Subtitle below title visible. Y-axis label "Frequency (Hz)" on left (dark text). X-axis label "Time (seconds)" at bottom (dark text). Tick labels dark, readable. Colorbar title "Power (dB)" visible. All chrome text dark on light background. PASS. + Data: Heatmap rendered with viridis colormap (deep purple → blue → teal → green → yellow). Clear diagonal yellow-green stripe rising from bottom-left to upper-right showing the chirp signal's frequency sweep from 10 Hz to 200 Hz. The colorbar on the right shows the viridis gradient labeled in dB. + LAYOUT BUG: The heatmap area occupies only the top ~37% of the canvas height. The bottom ~60% shows empty background with spurious y-axis labels (-3, -9, -15, -21, -27, -33, -39, -45, -51, -57, -63, -69, -75, -81, -87, -93, -99) — these are Highcharts auto-generating tick positions below category index 0 (no min constraint set on y-axis). Canvas utilization approximately 33-37%. + Legibility verdict: PASS for text readability; FAIL for layout (severe wasted space). + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct dark theme surface. PASS. + Chrome: Title and subtitle visible in light text. Y-axis label "Frequency (Hz)" visible in light color. X-axis label "Time (seconds)" visible in light color. Tick labels in light color (INK_SOFT token applied). Colorbar labels light. No dark-on-dark failures detected. PASS. + Data: Heatmap colors are identical to light render (viridis: purple→yellow, same stops). The chirp diagonal stripe is equally clear. Data colors confirmed identical to light render — only background and chrome flipped. PASS. + SAME LAYOUT BUG: Identical spurious negative y-axis labels in lower canvas area. Same ~37% canvas utilization. + Legibility verdict: PASS for text readability; FAIL for layout (same severe wasted space as light render). + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 8 + max: 8 + passed: true + comment: 'All font sizes explicitly set: title 28px, axis labels 22px, ticks + 18px — matching pixel-based library guidelines. Readable in both themes.' + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping text or data elements in either render. + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: Heatmap cells clearly visible, viridis palette provides excellent + contrast, chirp stripe immediately visible. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Viridis is perceptually uniform and colorblind-safe. + - id: VQ-05 + name: Layout & Canvas + score: 2 + max: 4 + passed: false + comment: Heatmap fills only ~37% of canvas height. Bottom ~60% is wasted space + due to Highcharts extending the category y-axis below index 0 (no min constraint). + Canvas utilization ~33% (technically in 30-50% range). + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Time (seconds) on x, Frequency (Hz) on y, Power (dB) on colorbar + — all descriptive with units. + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Continuous data uses viridis stops (#440154 to #fde725). Background + #FAF8F1 (light) / #1A1A17 (dark) correct. All chrome tokens theme-adaptive.' + design_excellence: + score: 11 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 4 + max: 8 + passed: false + comment: Well-configured output with subtitle and colorbar, but the layout + bug undermines overall polish. Looks like a configured default rather than + a publication-ready chart. + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: false + comment: Custom margins, grid opacity via GRID token, colorbar sizing (symbolHeight=800) + show refinement. However layout bug creates large dead zone, and legend + has heavy border styling. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Chirp signal's diagonal yellow-green stripe immediately conveys increasing + frequency over time. Subtitle provides explicit context. Viridis colormap + makes the story visually clear. + spec_compliance: + score: 14 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct spectrogram implemented as heatmap using Highcharts HeatmapSeries + with real scipy.signal.spectrogram computation. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Colorbar with dB units, time on x-axis (seconds), frequency on y-axis + (Hz), dB scale, scipy-computed spectrogram — all present. + - id: SC-03 + name: Data Mapping + score: 2 + max: 3 + passed: false + comment: Time on X and frequency on Y is correct. However, spurious negative + y-axis labels below the heatmap create a misleading visual impression of + the frequency axis range. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'spectrogram-basic · highcharts · anyplot.ai' matches required + format. Colorbar labeled 'Power (dB)' correctly. + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 'Chirp signal demonstrates the core spectrogram concept: time-frequency + representation, frequency sweep, noise background, dB scale.' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Linear chirp (10-200 Hz, 1000 Hz sample rate, 2 s) is a real signal + type used in radar, sonar, and audio analysis. Neutral and scientifically + accurate. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: 'All values physically realistic: 1000 Hz sample rate, 10-200 Hz + chirp range well below Nyquist, dB values in typical range.' + code_quality: + score: 8 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 2 + max: 3 + passed: false + comment: Class definition (QuietHTTPRequestHandler) and threading add structural + complexity beyond a simple linear script. The HTTP server pattern is clever + but more complex than needed. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) set. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports are used. + - id: CQ-04 + name: Code Elegance + score: 1 + max: 2 + passed: false + comment: HTTP server + threading is over-engineered vs the recommended inline-script + approach from the library guide. The workaround works but adds significant + complexity. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-THEME.png and plot-THEME.html correctly. + library_features: + score: 6 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 3 + max: 5 + passed: false + comment: Uses Chart(container='container'), HeatmapSeries, color_axis correctly. + But the CDN+HTTP-server approach deviates from the recommended inline-script + pattern in the library guide. + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses Highcharts-specific HeatmapSeries, color_axis with stops for + continuous colormap, interactive tooltip with pointFormat, and HTML export + — all distinctive to Highcharts. + verdict: REJECTED +impl_tags: + dependencies: + - scipy + - selenium + techniques: + - html-export + - colorbar + - hover-tooltips + patterns: + - data-generation + - matrix-construction + dataprep: [] + styling: + - custom-colormap From b76617d12de71222e818979ce89af2e3730d746e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 22:12:25 +0000 Subject: [PATCH 3/3] chore(highcharts): update quality score 85 and review feedback for spectrogram-basic --- .../implementations/python/highcharts.py | 2 +- .../metadata/python/highcharts.yaml | 213 +++++++++--------- 2 files changed, 102 insertions(+), 113 deletions(-) diff --git a/plots/spectrogram-basic/implementations/python/highcharts.py b/plots/spectrogram-basic/implementations/python/highcharts.py index 7d6c5366b3..e248e04c08 100644 --- a/plots/spectrogram-basic/implementations/python/highcharts.py +++ b/plots/spectrogram-basic/implementations/python/highcharts.py @@ -1,7 +1,7 @@ """ anyplot.ai spectrogram-basic: Spectrogram Time-Frequency Heatmap Library: highcharts unknown | Python 3.13.13 -Quality: 82/100 | Updated: 2026-05-15 +Quality: 85/100 | Updated: 2026-05-15 """ import os diff --git a/plots/spectrogram-basic/metadata/python/highcharts.yaml b/plots/spectrogram-basic/metadata/python/highcharts.yaml index 229ebe0bcf..53a94f4d18 100644 --- a/plots/spectrogram-basic/metadata/python/highcharts.yaml +++ b/plots/spectrogram-basic/metadata/python/highcharts.yaml @@ -2,7 +2,7 @@ library: highcharts language: python specification_id: spectrogram-basic created: '2025-12-31T05:36:53Z' -updated: '2026-05-15T21:58:54Z' +updated: '2026-05-15T22:12:25Z' generated_by: claude-haiku workflow_run: 25906243314 issue: 2927 @@ -12,49 +12,41 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/spectrogr preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/spectrogram-basic/python/highcharts/plot-dark.html -quality_score: 82 +quality_score: 85 review: strengths: - - Correct spectrogram implementation using scipy.signal.spectrogram with real FFT - computation and dB scale - - Viridis colormap (via explicit stops) is perceptually uniform and colorblind-safe - — matches spec requirement - - 'Full theme-adaptive chrome: PAGE_BG, INK, INK_SOFT, ELEVATED_BG, GRID tokens - all correctly wired to ANYPLOT_THEME for both light and dark renders' - - Realistic chirp signal data (10-200 Hz sweep, 1000 Hz sample rate, 2 s duration - with noise) makes the spectrogram concept immediately comprehensible - - Title format is exact ('spectrogram-basic · highcharts · anyplot.ai'), subtitle - adds useful context - - 'Correct output: saves plot-THEME.png and plot-THEME.html with proper naming' + - 'Perfect spec compliance: correct spectrogram type with time-frequency heatmap, + dB power scale, viridis colormap, and labeled colorbar' + - 'Excellent theme adaptation: both renders use correct background tokens (#FAF8F1/#1A1A17) + with fully theme-adaptive chrome (INK, INK_SOFT tokens throughout); no legibility + failures in either theme' + - Informative subtitle contextualizes the signal; the natural chirp sweep focal + point (bright yellow diagonal band) provides immediate visual storytelling without + annotations + - Realistic signal processing pipeline (scipy chirp + STFT spectrogram) with appropriate + dB scaling and noise for a scientifically credible example weaknesses: - - 'Y-axis category axis is not constrained: Highcharts auto-extends the category - range below index 0, generating spurious negative labels (-3, -9, -15, …, -99 - dB shown as Hz labels) in the lower portion of the chart. Fix: add ''min'': 0, - ''max'': len(frequencies_ds)-1 to the y_axis options to clamp the category axis - to valid range. This causes ~60% of the canvas to be wasted empty space.' - - 'HTTP server + CDN approach is over-engineered and fragile: the library guide - recommends downloading Highcharts JS and embedding it inline to avoid CDN dependency. - The current approach requires a local HTTP server, threading, and CDN availability. - Replace with urllib.request.urlopen to download highcharts.js and heatmap.js inline.' - - 'Design Excellence is generic: no spine removal, no intentional whitespace hierarchy, - legend box is a heavy bordered box. Refine by removing the legend border or reducing - its visual weight.' - - 'CQ-01: class definition (QuietHTTPRequestHandler) and threading add unnecessary - structural complexity for what should be a linear script.' + - CDN + HTTP server approach deviates from the highcharts.md guideline to embed + JS inline; introduces network dependency and extra complexity (threading, class + definition) + - Design sophistication is at the well-configured defaults tier (DE-01=4); lacks + distinctive typographic or layout choices that would push to publication-ready + quality + - Downsampling to 80x50 grid creates blocky cell appearance; higher resolution (e.g., + 120x70) would better represent the smooth frequency sweep and improve perceived + quality image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct theme surface. PASS. - Chrome: Title "spectrogram-basic · highcharts · anyplot.ai" visible at top center (dark text). Subtitle below title visible. Y-axis label "Frequency (Hz)" on left (dark text). X-axis label "Time (seconds)" at bottom (dark text). Tick labels dark, readable. Colorbar title "Power (dB)" visible. All chrome text dark on light background. PASS. - Data: Heatmap rendered with viridis colormap (deep purple → blue → teal → green → yellow). Clear diagonal yellow-green stripe rising from bottom-left to upper-right showing the chirp signal's frequency sweep from 10 Hz to 200 Hz. The colorbar on the right shows the viridis gradient labeled in dB. - LAYOUT BUG: The heatmap area occupies only the top ~37% of the canvas height. The bottom ~60% shows empty background with spurious y-axis labels (-3, -9, -15, -21, -27, -33, -39, -45, -51, -57, -63, -69, -75, -81, -87, -93, -99) — these are Highcharts auto-generating tick positions below category index 0 (no min constraint set on y-axis). Canvas utilization approximately 33-37%. - Legibility verdict: PASS for text readability; FAIL for layout (severe wasted space). + Background: Warm off-white (#FAF8F1) - correct light theme surface, not pure white + Chrome: Title "spectrogram-basic · highcharts · anyplot.ai" in dark ink (#1A1A17) clearly readable at top. Subtitle "Linear chirp signal (10-200 Hz) with linear frequency axis" in INK_SOFT (#4A4A44) readable below title. X-axis label "Time (seconds)" and Y-axis label "Frequency (Hz)" in dark ink, clearly visible. Tick labels (0-469 Hz on Y; 0.06-1.91s on X) in INK_SOFT, readable. Colorbar "Power (dB)" title and dB labels (-70 to -10 dB) in INK_SOFT on right side, readable. + Data: Viridis colormap (dark purple low power → teal mid → bright yellow high power). Clear diagonal yellow band tracing chirp sweep from ~10 Hz at t=0 to ~188 Hz at t=1.91s. Background shows green/teal noise floor. First and only series uses viridis continuous scale (not categorical Okabe-Ito, correct for continuous data). + Legibility verdict: PASS Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct dark theme surface. PASS. - Chrome: Title and subtitle visible in light text. Y-axis label "Frequency (Hz)" visible in light color. X-axis label "Time (seconds)" visible in light color. Tick labels in light color (INK_SOFT token applied). Colorbar labels light. No dark-on-dark failures detected. PASS. - Data: Heatmap colors are identical to light render (viridis: purple→yellow, same stops). The chirp diagonal stripe is equally clear. Data colors confirmed identical to light render — only background and chrome flipped. PASS. - SAME LAYOUT BUG: Identical spurious negative y-axis labels in lower canvas area. Same ~37% canvas utilization. - Legibility verdict: PASS for text readability; FAIL for layout (same severe wasted space as light render). + Background: Warm near-black (#1A1A17) - correct dark theme surface, not pure black + Chrome: Title in off-white (#F0EFE8) clearly readable against dark background. Subtitle in INK_SOFT dark token (#B8B7B0) clearly visible. X-axis and Y-axis labels in light off-white, clearly readable. Tick labels in #B8B7B0, visible against dark surface. Colorbar title and labels in #B8B7B0, readable. No dark-on-dark failures detected - all chrome text is appropriately light-colored. + Data: Viridis color stops identical to light render - same diagonal yellow chirp sweep, same teal/green noise floor. Data colors (positions in viridis) unchanged between themes, confirming only chrome flipped. + Legibility verdict: PASS criteria_checklist: visual_quality: score: 28 @@ -62,54 +54,55 @@ review: items: - id: VQ-01 name: Text Legibility - score: 8 + score: 7 max: 8 passed: true - comment: 'All font sizes explicitly set: title 28px, axis labels 22px, ticks - 18px — matching pixel-based library guidelines. Readable in both themes.' + comment: All font sizes explicitly set (title 28px, axis labels 22px, tick + labels 18px); readable in both themes; minor deduction for colorbar labels + being on smaller end within the margin column - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text or data elements in either render. + comment: No overlapping text; axis label stepping configured to avoid crowding - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: Heatmap cells clearly visible, viridis palette provides excellent - contrast, chirp stripe immediately visible. + comment: Chirp sweep clearly visible as bright diagonal band; heatmap cells + well-sized at 80x50 grid; colorbar distinct - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Viridis is perceptually uniform and colorblind-safe. + comment: Viridis is perceptually uniform and fully CVD-safe; excellent contrast + across power range - id: VQ-05 name: Layout & Canvas - score: 2 + score: 3 max: 4 - passed: false - comment: Heatmap fills only ~37% of canvas height. Bottom ~60% is wasted space - due to Highcharts extending the category y-axis below index 0 (no min constraint). - Canvas utilization ~33% (technically in 30-50% range). + passed: true + comment: Plot fills approximately 70-75% of canvas; margins balanced and accommodate + colorbar; slight bottom whitespace prevents perfect 4 - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Time (seconds) on x, Frequency (Hz) on y, Power (dB) on colorbar - — all descriptive with units. + comment: 'X: Time (seconds), Y: Frequency (Hz), colorbar: Power (dB) - all + descriptive with units' - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Continuous data uses viridis stops (#440154 to #fde725). Background - #FAF8F1 (light) / #1A1A17 (dark) correct. All chrome tokens theme-adaptive.' + comment: 'Viridis stops correctly applied to continuous data; light bg #FAF8F1, + dark bg #1A1A17; all chrome tokens theme-adaptive in both renders' design_excellence: - score: 11 + score: 12 max: 20 items: - id: DE-01 @@ -117,27 +110,25 @@ review: score: 4 max: 8 passed: false - comment: Well-configured output with subtitle and colorbar, but the layout - bug undermines overall polish. Looks like a configured default rather than - a publication-ready chart. + comment: Well-configured professional appearance with proper theme tokens + and viridis colormap, but falls in configured library default tier; no custom + typography or distinctive visual flourish - id: DE-02 name: Visual Refinement - score: 3 + score: 4 max: 6 - passed: false - comment: Custom margins, grid opacity via GRID token, colorbar sizing (symbolHeight=800) - show refinement. However layout bug creates large dead zone, and legend - has heavy border styling. + passed: true + comment: 'Custom margins, borderWidth: 0 for cleaner cells, subtle GRID tokens; + noticeably above bare defaults' - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Chirp signal's diagonal yellow-green stripe immediately conveys increasing - frequency over time. Subtitle provides explicit context. Viridis colormap - makes the story visually clear. + comment: Subtitle contextualizes signal; viridis creates natural focal point + with bright yellow sweep; viewer reads chirp trajectory immediately spec_compliance: - score: 14 + score: 15 max: 15 items: - id: SC-01 @@ -145,126 +136,124 @@ review: score: 5 max: 5 passed: true - comment: Correct spectrogram implemented as heatmap using Highcharts HeatmapSeries - with real scipy.signal.spectrogram computation. + comment: Correct spectrogram as time-frequency heatmap using HeatmapSeries - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Colorbar with dB units, time on x-axis (seconds), frequency on y-axis - (Hz), dB scale, scipy-computed spectrogram — all present. + comment: Color intensity encodes power; dB scale; time on X, frequency on + Y; colorbar with dB labels; chirp demonstrates non-stationary frequency + content - id: SC-03 name: Data Mapping - score: 2 + score: 3 max: 3 - passed: false - comment: Time on X and frequency on Y is correct. However, spurious negative - y-axis labels below the heatmap create a misleading visual impression of - the frequency axis range. + passed: true + comment: Time (seconds) on X, Frequency (Hz) on Y, Power (dB) in color - all + correct - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true comment: Title 'spectrogram-basic · highcharts · anyplot.ai' matches required - format. Colorbar labeled 'Power (dB)' correctly. + format; colorbar labeled 'Power (dB)' data_quality: - score: 15 + score: 14 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 6 + score: 5 max: 6 passed: true - comment: 'Chirp signal demonstrates the core spectrogram concept: time-frequency - representation, frequency sweep, noise background, dB scale.' + comment: Demonstrates chirp sweep, background noise, power dynamic range, + full spectrogram structure; minor deduction for 80x50 downsampling losing + fine frequency resolution - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Linear chirp (10-200 Hz, 1000 Hz sample rate, 2 s) is a real signal - type used in radar, sonar, and audio analysis. Neutral and scientifically - accurate. + comment: Chirp signal with gaussian noise is a standard neutral signal processing + test case; scientifically realistic and non-controversial - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: 'All values physically realistic: 1000 Hz sample rate, 10-200 Hz - chirp range well below Nyquist, dB values in typical range.' + comment: 1000 Hz sample rate, 2-second duration, 10-200 Hz sweep, dB scaling + - all physically realistic and domain-appropriate code_quality: - score: 8 + score: 9 max: 10 items: - id: CQ-01 name: KISS Structure score: 2 max: 3 - passed: false - comment: Class definition (QuietHTTPRequestHandler) and threading add structural - complexity beyond a simple linear script. The HTTP server pattern is clever - but more complex than needed. + passed: true + comment: Sequential flow clear but QuietHTTPRequestHandler class definition + deviates from pure imports-data-plot-save pattern - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set. + comment: np.random.seed(42) set before noise generation - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used. + comment: All imported modules are used - id: CQ-04 name: Code Elegance - score: 1 + score: 2 max: 2 - passed: false - comment: HTTP server + threading is over-engineered vs the recommended inline-script - approach from the library guide. The workaround works but adds significant - complexity. + passed: true + comment: HTTP server approach justified; spectrogram pipeline clean; try/finally + ensures server cleanup - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-THEME.png and plot-THEME.html correctly. - library_features: - score: 6 + comment: Saves plot-{THEME}.png and plot-{THEME}.html correctly for interactive + library + library_mastery: + score: 7 max: 10 items: - id: LM-01 name: Idiomatic Usage - score: 3 + score: 4 max: 5 - passed: false - comment: Uses Chart(container='container'), HeatmapSeries, color_axis correctly. - But the CDN+HTTP-server approach deviates from the recommended inline-script - pattern in the library guide. + passed: true + comment: Correctly uses HeatmapSeries with [x, y, value] format, color_axis + for colorbar, chart.to_js_literal(); deduction for CDN via HTTP server instead + of recommended inline embedding - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses Highcharts-specific HeatmapSeries, color_axis with stops for - continuous colormap, interactive tooltip with pointFormat, and HTML export - — all distinctive to Highcharts. - verdict: REJECTED + comment: Highcharts-specific color_axis with custom viridis stops, symbolHeight/symbolWidth + for colorbar legend, HeatmapSeries - not trivially portable to other libraries + verdict: APPROVED impl_tags: dependencies: - scipy - selenium techniques: - - html-export - colorbar - - hover-tooltips + - html-export patterns: - data-generation - matrix-construction - dataprep: [] + - iteration-over-groups + dataprep: + - stft styling: - custom-colormap