From 42045da5cceb1aa602cb6a1052732efbc0fe56dc Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F." Date: Thu, 26 Sep 2024 21:13:11 +0200 Subject: [PATCH] Added overlap to Python wrappers. Moved overlap to different file. Added default and helper methods for Python instantiation of structs for AvPowerSpectra. Added frequency weighting to AvPowerSpectra --> to be tested! --- src/lib.rs | 1 + src/ps/aps.rs | 37 +++++++++++++++++++++++++--- src/ps/freqweighting.rs | 5 ++++ src/ps/mod.rs | 1 + src/ps/overlap.rs | 54 +++++++++++++++++++++++++++++++++++++++++ src/ps/window.rs | 5 ++++ 6 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 src/ps/overlap.rs diff --git a/src/lib.rs b/src/lib.rs index c39754b..6cd2602 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,6 +63,7 @@ fn lasprs(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/src/ps/aps.rs b/src/ps/aps.rs index 2306a3f..100a58e 100644 --- a/src/ps/aps.rs +++ b/src/ps/aps.rs @@ -179,6 +179,25 @@ impl Overlap { fn __eq__(&self, other: &Self) -> bool { self == other } + + #[staticmethod] + #[pyo3(name = "default")] + fn default_py() -> Self { + Self::default() + } + + /// Export some typical settings to Python. Customs are also possible by + /// directly creating them. This is to fill up the list. + #[staticmethod] + fn some_settings() -> Vec { + use Overlap::*; + vec![ + NoOverlap {}, + Percentage { pct: 25. }, + Percentage { pct: 50. }, + Percentage { pct: 90. }, + ] + } } /// The 'mode' used in computing averaged power spectra. When providing data in @@ -239,7 +258,9 @@ pub struct AvPowerSpectra { /// Storage for sample data. timebuf: TimeBuffer, - /// Power scaling for of applied frequency weighting. + /// Power scaling for of applied frequency weighting. Multiply each power + /// and cross-power value with these constants to apply the frequency + /// weighting. freqWeighting_pwr: Option, // Current estimation of the power spectra @@ -328,16 +349,26 @@ impl AvPowerSpectra { } // Update result for single block fn update_singleblock(&mut self, timedata: ArrayView2) { + // Compute updated block of cross-spectral density let Cpsnew = { let mut Cpsnew = self.ps.compute(timedata); + let dim = Cpsnew.dim(); if let Some(fw_pwr) = &self.freqWeighting_pwr { + // Frequency weighting on power is available, multiply all values with frequency weighting - Zip::from(Cpsnew.) + // Option 1: azip with indexing + // azip!((index (i,_,_), cps in &mut Cpsnew) { + // *cps = Cflt::new(cps.re * fw_pwr[[i]], cps.im * fw_pwr[[i]]); + // }); + + // Option 2: broadcasting with an unwrap. + azip!((c in &mut Cpsnew, f in fw_pwr.broadcast(dim).unwrap()) { + *c = Cflt::new(c.re * f, c.im * f); + }); } Cpsnew }; - // println!("Cpsnew: {:?}", Cpsnew[[0, 0, 0]]); // Initialize to zero if self.cur_est.is_empty() { diff --git a/src/ps/freqweighting.rs b/src/ps/freqweighting.rs index 80c5f32..869ecea 100644 --- a/src/ps/freqweighting.rs +++ b/src/ps/freqweighting.rs @@ -25,6 +25,11 @@ impl FreqWeighting { fn all() -> Vec { Self::iter().collect() } + #[staticmethod] + #[pyo3(name = "default")] + fn default_py() -> Self { + Self::default() + } } #[cfg(test)] diff --git a/src/ps/mod.rs b/src/ps/mod.rs index e1e87bc..3fae073 100644 --- a/src/ps/mod.rs +++ b/src/ps/mod.rs @@ -10,6 +10,7 @@ mod ps; mod timebuffer; mod window; mod freqweighting; +mod overlap; use crate::config::*; diff --git a/src/ps/overlap.rs b/src/ps/overlap.rs new file mode 100644 index 0000000..018ab88 --- /dev/null +++ b/src/ps/overlap.rs @@ -0,0 +1,54 @@ +use crate::config::*; +/// Provide the overlap of blocks for computing averaged (cross) power spectra. +/// Can be provided as a percentage of the block size, or as a number of +/// samples. +#[cfg_attr(feature = "python-bindings", pyclass)] +#[derive(Clone, Debug, PartialEq)] +pub enum Overlap { + /// Overlap specified as a percentage of the total FFT length. Value should + /// be 0<=pct<100. + Percentage { + /// Percentage + pct: Flt, + }, + /// Number of samples to overlap + Number { + /// N: Number of samples + N: usize, + }, + /// No overlap at all, which is the same as Overlap::Number(0) + NoOverlap {}, +} +impl Default for Overlap { + fn default() -> Self { + Overlap::Percentage { pct: 50. } + } +} + +#[cfg(feature = "python-bindings")] +#[cfg_attr(feature = "python-bindings", pymethods)] +impl Overlap { + #[inline] + fn __eq__(&self, other: &Self) -> bool { + self == other + } + + #[staticmethod] + #[pyo3(name = "default")] + fn default_py() -> Self { + Self::default() + } + + /// Export some typical settings to Python. Customs are also possible by + /// directly creating them. This is to fill up the list. + #[staticmethod] + fn some_settings() -> Vec { + use Overlap::*; + vec![ + NoOverlap {}, + Percentage { pct: 25. }, + Percentage { pct: 50. }, + Percentage { pct: 90. }, + ] + } +} \ No newline at end of file diff --git a/src/ps/window.rs b/src/ps/window.rs index 6205e06..3384c3e 100644 --- a/src/ps/window.rs +++ b/src/ps/window.rs @@ -99,6 +99,11 @@ impl WindowType { fn all() -> Vec { WindowType::iter().collect() } + #[staticmethod] + #[pyo3(name="default")] + fn default_py() -> Self { + Self::default() + } }