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!

This commit is contained in:
Anne de Jong 2024-09-26 21:13:11 +02:00
parent c843c089dd
commit 42045da5cc
6 changed files with 100 additions and 3 deletions

View File

@ -63,6 +63,7 @@ fn lasprs(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<slm::SLMSettings>()?;
m.add_class::<slm::SLM>()?;
m.add_class::<ps::WindowType>()?;
m.add_class::<ps::Overlap>()?;
Ok(())
}

View File

@ -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<Overlap> {
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<Dcol>,
// Current estimation of the power spectra
@ -328,16 +349,26 @@ impl AvPowerSpectra {
}
// Update result for single block
fn update_singleblock(&mut self, timedata: ArrayView2<Flt>) {
// 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() {

View File

@ -25,6 +25,11 @@ impl FreqWeighting {
fn all() -> Vec<Self> {
Self::iter().collect()
}
#[staticmethod]
#[pyo3(name = "default")]
fn default_py() -> Self {
Self::default()
}
}
#[cfg(test)]

View File

@ -10,6 +10,7 @@ mod ps;
mod timebuffer;
mod window;
mod freqweighting;
mod overlap;
use crate::config::*;

54
src/ps/overlap.rs Normal file
View File

@ -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<Overlap> {
use Overlap::*;
vec![
NoOverlap {},
Percentage { pct: 25. },
Percentage { pct: 50. },
Percentage { pct: 90. },
]
}
}

View File

@ -99,6 +99,11 @@ impl WindowType {
fn all() -> Vec<WindowType> {
WindowType::iter().collect()
}
#[staticmethod]
#[pyo3(name="default")]
fn default_py() -> Self {
Self::default()
}
}