use scirs2_core::ndarray::{Array1, Array2};
use scirs2_core::Complex64;
use scirs2_fft::{
apply_colormap, fft, spectrogram, spectrogram_normalized, waterfall_3d, waterfall_lines,
window::Window,
};
#[allow(dead_code)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Spectrogram Visualization Example");
println!("---------------------------------\n");
let fs = 1000.0; let t_max = 10.0; let n_samples = (t_max * fs) as usize;
let t: Vec<f64> = (0..n_samples).map(|i| i as f64 / fs).collect();
let mut signal = Vec::with_capacity(n_samples);
for &ti in &t {
let freq = 10.0 + (200.0 - 10.0) * (ti / t_max);
let phase = 2.0 * PI * (10.0 * ti + 0.5 * (200.0 - 10.0) / t_max * ti.powi(2));
signal.push(phase.sin());
}
for (i, s) in signal.iter_mut().enumerate() {
let ti = i as f64 / fs;
if (ti * 0.5).sin() > 0.0 {
*s += 0.5 * (2.0 * PI * 250.0 * ti).sin();
}
if ti > 3.0 && ti < 7.0 {
let window = 0.5 * (1.0 - ((ti - 5.0) * PI / 2.0).cos());
*s += 0.7 * window * (2.0 * PI * 300.0 * ti).sin();
}
}
println!("Generated chirp signal with intermittent tones");
println!(" - Duration: {} seconds", t_max);
println!(" - Sample rate: {} Hz", fs);
println!(" - Samples: {}", n_samples);
println!("\n1. Basic Spectrogram");
let nperseg = 256;
let noverlap = 192;
let (freqs, times, spect) = spectrogram(
&signal,
Some(fs),
Some(Window::Hann),
Some(nperseg),
Some(noverlap),
None, None, Some(true), Some("power"), )?;
println!(" Computed spectrogram with:");
println!(" - Window: Hann");
println!(" - Window size: {} samples", nperseg);
println!(" - Overlap: {} samples", noverlap);
println!(" - Frequency bins: {}", freqs.len());
println!(" - Time frames: {}", times.len());
let db_floor = -80.0;
let mut spect_db = Array2::zeros(spect.dim());
for ((i, j), &val) in spect.indexed_iter() {
let db_val = 10.0 * val.log10();
spect_db[[i, j]] = if db_val.is_finite() { db_val.max(db_floor) } else { db_floor };
}
let spect_norm = spectrogram_normalized(&signal,
Some(fs),
Some(Window::Hann),
Some(nperseg),
Some(noverlap),
None,
None,
Some(true))?;
println!(" Normalized spectrogram data range: [0.0, 1.0]");
println!("\n2. Colormap Visualization");
let n_test = 100;
let test_amplitudes: Vec<f64> = (0..n_test).map(|i| i as f64 / (n_test as f64 - 1.0)).collect();
let colormaps = vec!["jet", "viridis", "plasma", "grayscale", "hot"];
println!(" Available colormaps:");
for &cmap in &colormaps {
let colors = apply_colormap(&test_amplitudes, cmap)?;
println!(" - {}: {} RGB triplets", cmap, colors.shape()[0]);
}
println!("\n3. Waterfall Plot Data");
let (wf_freqs, wf_times, wf_vals) = waterfall_lines(
&signal,
Some(fs),
Some(nperseg),
Some(noverlap),
None,
Some("dB"),
Some("jet"),
None, )?;
println!(" Generated waterfall plot data:");
println!(" - Frequency bins: {}", wf_freqs.len());
println!(" - Time frames: {}", wf_times.len());
println!(" - 3D points: {} × {} × 3", wf_vals.shape()[0], wf_vals.shape()[1]);
println!("\n4. 3D Surface Data");
let (surf_x, surf_y, surf_z, surf_c) = waterfall_3d(
&signal,
Some(fs),
Some(nperseg),
Some(noverlap),
None,
Some("dB"),
Some("viridis"),
Some(-60.0), )?;
println!(" Generated 3D surface data:");
println!(" - X points (time): {}", surf_x.shape()[0]);
println!(" - Y points (frequency): {}", surf_y.shape()[0]);
println!(" - Z mesh: {} × {}", surf_z.shape()[0], surf_z.shape()[1]);
println!(" - Colors: {} × {} × 3", surf_c.shape()[0], surf_c.shape()[1]);
println!("\n5. Time-Varying Spectrum Analysis");
let quarter_idx = times.len() / 4;
let mid_idx = times.len() / 2;
let three_quarter_idx = 3 * times.len() / 4;
let times_of_interest = vec![
(0, "Start"),
(quarter_idx, "25%"),
(mid_idx, "Middle"),
(three_quarter_idx, "75%"),
(times.len() - 1, "End")
];
println!(" Analyzing spectrum at specific time points:");
for &(idx, label) in ×_of_interest {
let time = times[idx];
let mut freq_powers: Vec<(usize, f64)> = freqs.iter()
.zip(spect.column(idx).iter())
.enumerate()
.map(|(i, (_, &power))| (i, power))
.collect();
freq_powers.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).expect("Operation failed"));
println!(" * Time {} ({:.2} s):", label, time);
for i in 0..3.min(freq_powers.len()) {
let (idx, power) = freq_powers[i];
let freq = freqs[idx];
println!(" - {:.1} Hz: {:.1} dB", freq, 10.0 * power.log10());
}
}
println!("\nSpectrogram visualization complete!");
Ok(())
}