modewise_hilbert/
spectrum.rs1use modewise_decomposition::InstantaneousModes;
2use modewise_method::MethodError;
3use modewise_spectral::{FrequencyGrid, TimeFrequencyMap};
4use ndarray::Array3;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum Weight {
9 #[default]
11 Power,
12 Amplitude,
13}
14
15pub struct HilbertSpectrum {
16 pub map: TimeFrequencyMap,
17 pub dropped: usize,
19 pub total: usize,
20}
21
22pub fn hilbert_spectrum(
25 modes: &InstantaneousModes,
26 grid: &FrequencyGrid,
27 weight: Weight,
28) -> Result<HilbertSpectrum, MethodError> {
29 let (n_modes, n_channels, n_samples) = modes.amplitude().dim();
30 let mut power = Array3::zeros((n_channels, grid.n_bins(), n_samples));
31 let amplitude = modes.amplitude();
32 let frequency = modes.frequency_hz();
33 let mut dropped = 0;
34 for k in 0..n_modes {
35 for c in 0..n_channels {
36 for t in 0..n_samples {
37 match grid.bin(frequency[[k, c, t]]) {
38 Some(bin) => {
39 let a = amplitude[[k, c, t]];
40 power[[c, bin, t]] += match weight {
41 Weight::Power => a * a,
42 Weight::Amplitude => a,
43 };
44 }
45 None => dropped += 1,
46 }
47 }
48 }
49 }
50 let fs = modes.sampling_rate().hz();
51 let times = (0..n_samples).map(|t| t as f64 / fs).collect();
52 let map = TimeFrequencyMap::new(power, grid.centres(), times, modes.labels().to_vec())?
53 .with_sampling_rate(modes.sampling_rate())?;
54 Ok(HilbertSpectrum {
55 map,
56 dropped,
57 total: n_modes * n_channels * n_samples,
58 })
59}