Skip to content

Commit 7f08546

Browse files
feat(plotly): implement spectrogram-basic (#2963)
## Implementation: `spectrogram-basic` - plotly Implements the **plotly** version of `spectrogram-basic`. **File:** `plots/spectrogram-basic/implementations/plotly.py` **Parent Issue:** #2927 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20612803590)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent fe3046b commit 7f08546

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
""" pyplots.ai
2+
spectrogram-basic: Spectrogram Time-Frequency Heatmap
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 93/100 | Created: 2025-12-31
5+
"""
6+
7+
import numpy as np
8+
import plotly.graph_objects as go
9+
from scipy import signal
10+
11+
12+
# Data - Create a chirp signal with increasing frequency
13+
np.random.seed(42)
14+
sample_rate = 4000 # Hz
15+
duration = 2.0 # seconds
16+
t = np.linspace(0, duration, int(sample_rate * duration))
17+
18+
# Chirp signal: frequency sweeps from 100 Hz to 800 Hz
19+
f0, f1 = 100, 800
20+
chirp_signal = signal.chirp(t, f0=f0, f1=f1, t1=duration, method="linear")
21+
22+
# Add some noise for realism
23+
noise = np.random.randn(len(t)) * 0.1
24+
audio_signal = chirp_signal + noise
25+
26+
# Compute spectrogram
27+
nperseg = 256 # Window size
28+
noverlap = 200 # Overlap for smooth visualization
29+
frequencies, times, Sxx = signal.spectrogram(audio_signal, fs=sample_rate, nperseg=nperseg, noverlap=noverlap)
30+
31+
# Convert to dB scale for better visualization
32+
Sxx_db = 10 * np.log10(Sxx + 1e-10)
33+
34+
# Create spectrogram heatmap
35+
fig = go.Figure()
36+
37+
fig.add_trace(
38+
go.Heatmap(
39+
x=times,
40+
y=frequencies,
41+
z=Sxx_db,
42+
colorscale="Viridis",
43+
colorbar={
44+
"title": {"text": "Power (dB)", "font": {"size": 20}},
45+
"tickfont": {"size": 16},
46+
"len": 0.85,
47+
"thickness": 25,
48+
},
49+
hovertemplate="Time: %{x:.3f}s<br>Frequency: %{y:.0f}Hz<br>Power: %{z:.1f}dB<extra></extra>",
50+
)
51+
)
52+
53+
# Layout
54+
fig.update_layout(
55+
title={"text": "spectrogram-basic · plotly · pyplots.ai", "font": {"size": 28}, "x": 0.5, "xanchor": "center"},
56+
xaxis={"title": {"text": "Time (seconds)", "font": {"size": 22}}, "tickfont": {"size": 18}},
57+
yaxis={"title": {"text": "Frequency (Hz)", "font": {"size": 22}}, "tickfont": {"size": 18}},
58+
template="plotly_white",
59+
margin={"l": 100, "r": 120, "t": 100, "b": 100},
60+
)
61+
62+
# Save outputs
63+
fig.write_image("plot.png", width=1600, height=900, scale=3)
64+
fig.write_html("plot.html", include_plotlyjs="cdn")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: plotly
2+
specification_id: spectrogram-basic
3+
created: '2025-12-31T05:35:16Z'
4+
updated: '2025-12-31T05:47:16Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20612803590
7+
issue: 2927
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/spectrogram-basic/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/spectrogram-basic/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/spectrogram-basic/plotly/plot.html
13+
quality_score: 93
14+
review:
15+
strengths:
16+
- Excellent visual clarity with the Viridis colormap showing the chirp signal frequency
17+
sweep distinctly
18+
- Proper use of dB scale for power representation as recommended in spec
19+
- Clean well-structured code following KISS principles
20+
- Interactive hovertemplate provides detailed time/frequency/power information on
21+
mouseover
22+
- Correct title format and axis labeling with appropriate units
23+
weaknesses:
24+
- Missing grid lines (though acceptable for heatmap, subtle grid could help with
25+
time/frequency reading)
26+
- Could utilize more Plotly-specific interactive features like range sliders or
27+
animation controls

0 commit comments

Comments
 (0)