Function hilbert_spectrum
pub fn hilbert_spectrum(
emd_result: &EMDResult,
sample_rate: f64,
config: &HilbertSpectrumConfig,
) -> Result<HilbertSpectrum>Expand description
Build the HilbertSpectrum for emd_result at the given sample_rate.
IMF::frequency / IMF::amplitude are not consulted — the instantaneous
attributes are recomputed fresh from each imf.data via
hilbert_transform, so two calls with the same EMDResult always yield
the same spectrum regardless of prior mutation.
§Band selection
Samples whose instantaneous frequency falls outside
HilbertSpectrumConfig::freq_range are silently dropped — this is by
design so callers can zoom into a band of interest, but a too-narrow band
will yield a near-empty density without raising an error. Use
(0.0, sample_rate / 2.0) if you want every IMF accounted for.
§Errors
Returns WaveletError::InvalidParameter when:
emd_result.imfsis empty,- any IMF has fewer than 4 samples (the minimum for Hilbert + central- difference frequency),
sample_rateis non-positive or non-finite,num_freq_bins < 2,freq_range.0 >= freq_range.1,freq_range.0 < 0(or≤ 0whenlog_freq = true),freq_range.1 > sample_rate / 2(above Nyquist),time_smoothing = Some(0)(useNoneto disable smoothing).
§Examples
use ferro_wave::transform::{emd, hilbert_spectrum, EMDConfig, HilbertSpectrumConfig};
use ferro_wave::Signal;
use std::f64::consts::PI;
let sample_rate = 256.0;
let n = 1024;
// Pure 40 Hz tone — single IMF, single ridge.
let data: Vec<f64> = (0..n)
.map(|i| (2.0 * PI * 40.0 * i as f64 / sample_rate).cos())
.collect();
let signal = Signal::<f64>::new(data);
let emd_result = emd(&signal, &EMDConfig::default()).unwrap();
let cfg = HilbertSpectrumConfig::new(0.0, sample_rate / 2.0);
let spectrum = hilbert_spectrum(&emd_result, sample_rate, &cfg).unwrap();
assert_eq!(spectrum.density.len(), n);
assert_eq!(spectrum.frequencies.len(), cfg.num_freq_bins);
assert!(spectrum.marginal().iter().any(|&v| v > 0.0));