use scirs2_signal::emd::{eemd, emd, hilbert_huang_spectrum, EmdConfig};
use std::f64::consts::PI;
#[allow(dead_code)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Empirical Mode Decomposition (EMD) Example");
println!("===========================================");
let sample_rate = 1000.0; let duration = 2.0; let n_samples = (sample_rate * duration) as usize;
println!("Generating test signals:");
println!("- Sample rate: {:.1} Hz", sample_rate);
println!("- Duration: {:.1} seconds", duration);
println!("- Samples: {}", n_samples);
let time: Vec<f64> = (0..n_samples).map(|i| i as f64 / sample_rate).collect();
println!("\nTest Signal 1: Sum of sinusoids with frequencies 5 Hz, 20 Hz, and 60 Hz");
let signal1: Vec<f64> = time
.iter()
.map(|&t| {
(2.0 * PI * 5.0 * t).sin() + 0.5 * (2.0 * PI * 20.0 * t).sin() + 0.2 * (2.0 * PI * 60.0 * t).sin() })
.collect();
let config = EmdConfig {
max_imfs: 5, sift_threshold: 0.05, max_sift_iterations: 50, ..Default::default()
};
println!("\nApplying EMD with parameters:");
println!("- Max IMFs: {}", config.max_imfs);
println!("- Sift threshold: {:.3}", config.sift_threshold);
println!("- Max sift iterations: {}", config.max_sift_iterations);
let result1 = emd(&signal1, &config)?;
println!("\nEMD Results for Signal 1:");
println!("- Extracted {} IMFs", result1.imfs.shape()[0]);
for i in 0..result1.imfs.shape()[0] {
let energy = result1.energies[i];
let iterations = result1.iterations[i];
println!(
" IMF {}: Energy = {:.6}, Iterations = {}",
i + 1,
energy,
iterations
);
}
let num_freqs = 100; println!(
"\nComputing Hilbert-Huang spectrum with {} frequency bins",
num_freqs
);
let (times, freqs, hhs) = hilbert_huang_spectrum(&result1, sample_rate, num_freqs)?;
println!(
"- Frequency range: {:.2} Hz to {:.2} Hz",
freqs[0],
freqs[freqs.len() - 1]
);
let mut max_energy = 0.0;
let mut max_time_idx = 0;
let mut max_freq_idx = 0;
for i in 0..freqs.len() {
for j in 0..times.len() {
if hhs[[i, j]] > max_energy {
max_energy = hhs[[i, j]];
max_freq_idx = i;
max_time_idx = j;
}
}
}
println!(
"- Maximum energy at: Time = {:.3} s, Frequency = {:.2} Hz, Energy = {:.6}",
times[max_time_idx], freqs[max_freq_idx], max_energy
);
println!("\nTest Signal 2: Chirp signal with frequency increasing from 10 Hz to 100 Hz");
let signal2: Vec<f64> = time
.iter()
.map(|&t| {
let _instantaneous_freq = 10.0 + 45.0 * t;
let phase = 2.0 * PI * (10.0 * t + 22.5 * t * t);
phase.sin()
})
.collect();
let ensemble_size = 10; let noise_std = 0.1;
println!("\nApplying EEMD with parameters:");
println!("- Ensemble size: {}", ensemble_size);
println!("- Noise standard deviation: {:.2}", noise_std);
let result2 = eemd(&signal2, &config, ensemble_size, noise_std)?;
println!("\nEEMD Results for Signal 2:");
println!("- Extracted {} IMFs", result2.imfs.shape()[0]);
for i in 0..result2.imfs.shape()[0] {
let energy = result2.energies[i];
println!(" IMF {}: Energy = {:.6}", i + 1, energy);
}
println!("\nComputing Hilbert-Huang spectrum for the chirp signal");
let (times2, freqs2, hhs2) = hilbert_huang_spectrum(&result2, sample_rate, num_freqs)?;
println!("Time-frequency analysis of the chirp signal:");
let time_points = [0.2, 0.5, 1.0, 1.5];
for &t in &time_points {
let t_idx = (t * sample_rate) as usize;
if t_idx < times2.len() {
let mut max_energy = 0.0;
let mut max_freq_idx = 0;
for i in 0..freqs2.len() {
if hhs2[[i, t_idx]] > max_energy {
max_energy = hhs2[[i, t_idx]];
max_freq_idx = i;
}
}
let expected_freq = 10.0 + 45.0 * t;
println!(
" Time = {:.1} s: Detected f = {:.1} Hz, Expected f = {:.1} Hz",
t, freqs2[max_freq_idx], expected_freq
);
}
}
println!(
"\nNote: Visualization of IMFs and HHS would be done with external plotting libraries."
);
Ok(())
}