From d9fbe25dc1f1b278dd12b22b8f112c4393e6c4f5 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Wed, 28 Aug 2024 21:51:16 +0200 Subject: [PATCH] TimeWeighting __eq__ method added. Improved comments. Tested Python code. Now ready for implementing WindowType Python wrapper --- README.md | 9 ++++++-- examples_py/test_filterbank.ipynb | 4 ++-- examples_py/test_freqweighting.ipynb | 4 ++-- examples_py/test_slm1.ipynb | 33 +++------------------------- python/lasprs/filter/__init__.py | 1 - src/filter/zpkmodel.rs | 11 +++++++++- src/ps/window.rs | 6 ++++- src/slm/tw.rs | 12 +++++++++- 8 files changed, 40 insertions(+), 40 deletions(-) delete mode 100644 python/lasprs/filter/__init__.py diff --git a/README.md b/README.md index 67327f0..43e281e 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,17 @@ and processing of (multi) sensor data in real time on a PC and output results. Documentation is provided at [doc.rs](https://docs.rs/lasprs/latest/lasprs). - ## Python bindings and examples The library has Python bindings (via [pyo3](https://pyo3.rs), which can be installed via: ``` -$ pip install git+https://code.ascee.nl/ascee/lasprs --install-option "python-bindings" +$ pip install lasprs ``` +which pulls the library from [Pypi](https://pypi.org). + +Examples of how to use the library are provided in Jupyter Notebooks, which can be found in the repository, see [lasprs/examples_py](https://code.ascee.nl/ASCEE/lasprs/src/branch/main/examples_py). + +More examples will follow in the near future. + diff --git a/examples_py/test_filterbank.ipynb b/examples_py/test_filterbank.ipynb index d5361b8..06f3e44 100644 --- a/examples_py/test_filterbank.ipynb +++ b/examples_py/test_filterbank.ipynb @@ -41,8 +41,8 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "from numpy import log10, sqrt, exp, pi\n", - "from lasprs._lasprs import StandardFilterDescriptor, SLMSettings, FreqWeighting, TimeWeighting, SLM\n", + "from numpy import log10\n", + "from lasprs import StandardFilterDescriptor\n", "def level(a):\n", " return 20*np.log10(np.abs(a))" ] diff --git a/examples_py/test_freqweighting.ipynb b/examples_py/test_freqweighting.ipynb index 4f1d7d3..cbc8ef2 100644 --- a/examples_py/test_freqweighting.ipynb +++ b/examples_py/test_freqweighting.ipynb @@ -41,8 +41,8 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "from numpy import log10, sqrt, exp, pi\n", - "from lasprs._lasprs import ZPKModel, FreqWeighting\n", + "from numpy import log10\n", + "from lasprs import ZPKModel, FreqWeighting\n", "def level(a):\n", " return 20*np.log10(np.abs(a))" ] diff --git a/examples_py/test_slm1.ipynb b/examples_py/test_slm1.ipynb index 042a375..5ec2b6b 100644 --- a/examples_py/test_slm1.ipynb +++ b/examples_py/test_slm1.ipynb @@ -17,6 +17,7 @@ "source": [ "# Prerequisites, uncomment below in case of errors. Also for ipympl, restart Jupyter Lab if it was not installed\n", "\n", + "# Only do the following if you are in develop mode\n", "!cd .. && maturin develop -F python-bindings\n", "#!pip install ipympl scipy matplotlib" ] @@ -41,7 +42,7 @@ "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", - "from numpy import log10, sqrt, exp, pi\n", + "from numpy import log10\n", "from lasprs._lasprs import StandardFilterDescriptor, SLMSettings, FreqWeighting, TimeWeighting, SLM\n", "def level(a):\n", " return 20*np.log10(np.abs(a))" @@ -105,27 +106,7 @@ "outputs": [], "source": [ "t = np.linspace(0, N/fs, N, endpoint=False)\n", - "out = slm.run(inp)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "37af9b78-73b9-4228-a758-d9a5362f79f4", - "metadata": {}, - "outputs": [], - "source": [ - "len(out[0])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4609a63f-e350-4b6b-b898-93c9e6fef804", - "metadata": {}, - "outputs": [], - "source": [ - "# help(plt.legend)" + "out = slm.run(inp, True)" ] }, { @@ -141,14 +122,6 @@ "plt.ylim(-60, 0)\n", "plt.legend(names)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4303e20e-cc61-4d23-a5f0-cab683d55912", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/python/lasprs/filter/__init__.py b/python/lasprs/filter/__init__.py deleted file mode 100644 index cc9bbc2..0000000 --- a/python/lasprs/filter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .._lasprs import (Biquad, BiquadBank, SeriesBiquad, ZPKModel, FilterSpec) diff --git a/src/filter/zpkmodel.rs b/src/filter/zpkmodel.rs index 2fd8d8c..cc0dfd1 100644 --- a/src/filter/zpkmodel.rs +++ b/src/filter/zpkmodel.rs @@ -569,7 +569,6 @@ impl ZPKModel { let p2 = 2. * pi * f2; let p3 = 2. * pi * f3; let p4 = 2. * pi * f4; - println!("{b} {p1}, {p2}, {p3}, {p4}"); let (zeros, poles) = match wt { FreqWeighting::Z => { @@ -610,11 +609,21 @@ pub enum PoleOrZero { #[cfg(test)] mod test{ + use approx::assert_abs_diff_eq; + use num::complex::ComplexFloat; + + use crate::TransferFunction; use super::ZPKModel; #[test] fn test_A() { let Aw = ZPKModel::freqWeightingFilter(crate::FreqWeighting::A); + assert_abs_diff_eq!(Aw.tf(0., &[1000.])[0].abs(), 1.0); + } + #[test] + fn test_C() { + let Cw = ZPKModel::freqWeightingFilter(crate::FreqWeighting::C); + assert_abs_diff_eq!(Cw.tf(0., &[1000.])[0].abs(), 1.0); } } diff --git a/src/ps/window.rs b/src/ps/window.rs index a13d890..40fb045 100644 --- a/src/ps/window.rs +++ b/src/ps/window.rs @@ -72,7 +72,11 @@ fn hamming(N: usize) -> Dcol { /// * Blackman /// /// The [WindowType::default] is [WindowType::Hann]. -#[derive(Display,Default, Copy, Clone, Debug)] +#[derive(Display,Default, Copy, Clone, Debug, PartialEq)] +// Do the following when Pyo3 0.22 can finally be used combined with rust-numpy: +// #[cfg_attr(feature = "python-bindings", pyclass(eq))] +// For now: +// #[cfg_attr(feature = "python-bindings", pyclass(eq))] pub enum WindowType { /// Von Hann window #[default] diff --git a/src/slm/tw.rs b/src/slm/tw.rs index 7d1b594..8f0fe87 100644 --- a/src/slm/tw.rs +++ b/src/slm/tw.rs @@ -5,11 +5,12 @@ use crate::config::*; // #[cfg_attr(feature = "python-bindings", pyclass(eq))] // For now: #[cfg_attr(feature = "python-bindings", pyclass)] -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum TimeWeighting { // I know that the curly braces here are not required and add some // boilerplate, but this is the only way Pyo3 swallows complex enums at the // moment. + /// Slow time weighting ~ 1 s Slow {}, /// Fast time weighting ~ 1/8 s @@ -30,6 +31,15 @@ pub enum TimeWeighting { tdown: Flt, }, } + +#[cfg_attr(feature = "python-bindings", pymethods)] +impl TimeWeighting { + // This method is still required in Pyo3 0.21, not anymore in 0.22 + fn __eq__(&self, other: &Self) -> bool { + self == other + } +} + impl Default for TimeWeighting { fn default() -> Self { TimeWeighting::Fast {}