PySDKit 0.4.21__tar.gz → 0.4.23__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pysdkit-0.4.21 → pysdkit-0.4.23}/LICENSE +21 -21
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PKG-INFO +4 -6
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PySDKit.egg-info/PKG-INFO +4 -6
- {pysdkit-0.4.21 → pysdkit-0.4.23}/README.md +1 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/__init__.py +6 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/__init__.py +27 -27
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/_find_extrema.py +146 -146
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/_prepare_points.py +275 -275
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/_splines.py +130 -130
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/eemd.py +296 -296
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/efd.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/emd.py +2 -2
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/hht/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/hht/frequency.py +105 -105
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/hht/hht.py +5 -5
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/memd.py +6 -8
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/remd.py +14 -8
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/tvf_emd.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd2d/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd2d/bemd.py +6 -6
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd2d/bmemd.py +23 -23
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd2d/emd2d.py +0 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_esmd/__init__.py +6 -6
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_esmd/esmd.py +0 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ewt/__init__.py +9 -9
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ewt/ewt.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ewt/ewt2d.py +11 -11
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/__init__.py +12 -12
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/extrema.py +4 -5
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/faemd.py +2 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/faemd2d.py +35 -35
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/faemd3d.py +32 -32
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_faemd/filter.py +45 -45
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_fmd/__init__.py +7 -6
- pysdkit-0.4.23/pysdkit/_fmd/fmd.py +302 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_fmd/nfmd.py +25 -25
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_hvd/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_hvd/hvd.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ifd/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_itd/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_jmd/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_jmd/jmd.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_jmd/mjmd.py +34 -34
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_lmd/__init__.py +9 -9
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_lmd/rlmd.py +20 -13
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_osd/__init__.py +21 -21
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ssa/__init__.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_ssa/ssa.py +147 -147
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/__init__.py +16 -16
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/acmd.py +246 -246
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/avmd.py +27 -27
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/ba_acmd.py +35 -35
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/mvmd.py +2 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/svmd.py +0 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/vmd_c.py +2 -2
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/vmd_f.py +157 -157
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/vme.py +2 -2
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd2d/__init__.py +9 -9
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd2d/cvmd2d.py +6 -4
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd2d/vmd2d.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vncmd/__init__.py +9 -9
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vncmd/incmd.py +3 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vncmd/mncmd.py +11 -11
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vncmd/vncmd.py +350 -350
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_add_noise.py +29 -29
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_cube.py +291 -291
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_image.py +2 -2
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_time_series.py +137 -137
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/texture.txt +256 -256
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/entropy/__init__.py +21 -21
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/entropy/_approxiamte_entropy.py +7 -7
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/entropy/_permutation_entropy.py +0 -1
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/entropy/_sample_entropy.py +198 -198
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/__init__.py +24 -24
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/_fourier_spectra.py +2 -2
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/_functions.py +102 -102
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/_plot_images.py +222 -222
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/_plot_imfs.py +587 -587
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/plot/_plot_signal.py +135 -135
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/__init__.py +6 -6
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_all.py +23 -23
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_ceemdan.py +294 -294
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_emd.py +276 -276
- pysdkit-0.4.23/pysdkit/tests/test_faemd2d.py +11 -0
- pysdkit-0.4.23/pysdkit/tests/test_faemd3d.py +11 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_vmd.py +193 -193
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tsa/_dtw.py +54 -54
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tsa/_moving_decomp.py +251 -251
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tsa/_mstl.py +24 -24
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tsa/_stl.py +2 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/__init__.py +115 -115
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_cite.py +33 -33
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_diagnalization.py +224 -224
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_differ.py +34 -34
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_fft.py +32 -32
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_function.py +2 -3
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_instantaneous.py +262 -262
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_kernel_matrix.py +4 -5
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_mirror.py +47 -47
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_process.py +156 -156
- {pysdkit-0.4.21 → pysdkit-0.4.23}/setup.py +3 -5
- pysdkit-0.4.21/pysdkit/_fmd/fmd.py +0 -149
- pysdkit-0.4.21/pysdkit/tests/test_faemd2d.py +0 -10
- pysdkit-0.4.21/pysdkit/tests/test_faemd3d.py +0 -10
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PySDKit.egg-info/SOURCES.txt +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PySDKit.egg-info/dependency_links.txt +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PySDKit.egg-info/requires.txt +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/PySDKit.egg-info/top_level.txt +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_emd/ceemdan.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_itd/itd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_lmd/lmd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vmd/base.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/_vncmd/avncmd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/__init__.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_generator.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_models.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/data/_test_univariate.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/models/__init__.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/models/_base.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/models/_kmeans.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/models/_knn.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/models/_pca.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/data/__init__.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/data/test_generator_cube.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/data/test_generator_image.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/data/test_generator_signal.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/data/test_generator_univariate_signal.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/models/__init__.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/models/test_knn.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/models/test_pca.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_ewt.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_faemd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_lmd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_moving_decomp.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_rlmd.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_stl.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tests/test_vmd2d.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/tsa/__init__.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_correlation.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_hilbert.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/pysdkit/utils/_smooth1d.py +0 -0
- {pysdkit-0.4.21 → pysdkit-0.4.23}/setup.cfg +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2019 Whenxuan Wang
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Whenxuan Wang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PySDKit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.23
|
|
4
4
|
Summary: A Python library for signal decomposition algorithms with a unified interface.
|
|
5
5
|
Home-page: https://github.com/wwhenxuan/PySDKit
|
|
6
6
|
Author: whenxuan, changewam, josefinez, Yuan Feng
|
|
@@ -11,13 +11,11 @@ Classifier: Intended Audience :: Science/Research
|
|
|
11
11
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
12
12
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.8
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
19
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Requires-Python: >=3.8
|
|
21
19
|
Description-Content-Type: text/markdown
|
|
22
20
|
License-File: LICENSE
|
|
23
21
|
Requires-Dist: numpy>=1.24.3
|
|
@@ -147,7 +145,7 @@ plot_IMFs_amplitude_spectra(IMFs, smooth="exp") # use exp smooth
|
|
|
147
145
|
| [`ALIF`]() (Adaptive Local Iterative Filtering) | [[paper]](https://arxiv.org/abs/1411.6051) | [[code]](https://ww2.mathworks.cn/matlabcentral/fileexchange/56210-alif) | ✖️ |
|
|
148
146
|
| [`LMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/lmd.py) (Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S1051200418308133?via%3Dihub) | [[code]](https://github.com/shownlin/PyLMD/blob/master/PyLMD/LMD.py) | ✔️ |
|
|
149
147
|
| [`RLMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/rlmd.py) (Robust Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S0888327017301619) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/66935-robust-local-mean-decomposition-rlmd) | ✔️ |
|
|
150
|
-
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) |
|
|
148
|
+
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) | ✔️ |
|
|
151
149
|
| [`NFMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/nfmd.py) (Non-stationary Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://github.com/sheadan/NFMD-ExtractionInstantaneous/blob/master/nfmd/NFMD.py) | ✖️ |
|
|
152
150
|
| [`SSA`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ssa/ssa.py) (Singular Spectral Analysis) | [[paper]](https://orca.cardiff.ac.uk/id/eprint/15208/1/Zhiglavsky_SSA_encyclopedia.pdf) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/58967-singular-spectrum-analysis-beginners-guide) | ✔️ |
|
|
153
151
|
| [`EWT`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ewt/ewt.py) (Empirical Wavelet Transform) | [[paper]](https://ieeexplore.ieee.org/document/6522142) | [[code]](https://www.mathworks.com/help/wavelet/ug/empirical-wavelet-transform.html) | ✔️ |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PySDKit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.23
|
|
4
4
|
Summary: A Python library for signal decomposition algorithms with a unified interface.
|
|
5
5
|
Home-page: https://github.com/wwhenxuan/PySDKit
|
|
6
6
|
Author: whenxuan, changewam, josefinez, Yuan Feng
|
|
@@ -11,13 +11,11 @@ Classifier: Intended Audience :: Science/Research
|
|
|
11
11
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
12
12
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.8
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
19
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Requires-Python: >=3.8
|
|
21
19
|
Description-Content-Type: text/markdown
|
|
22
20
|
License-File: LICENSE
|
|
23
21
|
Requires-Dist: numpy>=1.24.3
|
|
@@ -147,7 +145,7 @@ plot_IMFs_amplitude_spectra(IMFs, smooth="exp") # use exp smooth
|
|
|
147
145
|
| [`ALIF`]() (Adaptive Local Iterative Filtering) | [[paper]](https://arxiv.org/abs/1411.6051) | [[code]](https://ww2.mathworks.cn/matlabcentral/fileexchange/56210-alif) | ✖️ |
|
|
148
146
|
| [`LMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/lmd.py) (Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S1051200418308133?via%3Dihub) | [[code]](https://github.com/shownlin/PyLMD/blob/master/PyLMD/LMD.py) | ✔️ |
|
|
149
147
|
| [`RLMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/rlmd.py) (Robust Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S0888327017301619) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/66935-robust-local-mean-decomposition-rlmd) | ✔️ |
|
|
150
|
-
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) |
|
|
148
|
+
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) | ✔️ |
|
|
151
149
|
| [`NFMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/nfmd.py) (Non-stationary Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://github.com/sheadan/NFMD-ExtractionInstantaneous/blob/master/nfmd/NFMD.py) | ✖️ |
|
|
152
150
|
| [`SSA`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ssa/ssa.py) (Singular Spectral Analysis) | [[paper]](https://orca.cardiff.ac.uk/id/eprint/15208/1/Zhiglavsky_SSA_encyclopedia.pdf) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/58967-singular-spectrum-analysis-beginners-guide) | ✔️ |
|
|
153
151
|
| [`EWT`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ewt/ewt.py) (Empirical Wavelet Transform) | [[paper]](https://ieeexplore.ieee.org/document/6522142) | [[code]](https://www.mathworks.com/help/wavelet/ug/empirical-wavelet-transform.html) | ✔️ |
|
|
@@ -108,7 +108,7 @@ plot_IMFs_amplitude_spectra(IMFs, smooth="exp") # use exp smooth
|
|
|
108
108
|
| [`ALIF`]() (Adaptive Local Iterative Filtering) | [[paper]](https://arxiv.org/abs/1411.6051) | [[code]](https://ww2.mathworks.cn/matlabcentral/fileexchange/56210-alif) | ✖️ |
|
|
109
109
|
| [`LMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/lmd.py) (Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S1051200418308133?via%3Dihub) | [[code]](https://github.com/shownlin/PyLMD/blob/master/PyLMD/LMD.py) | ✔️ |
|
|
110
110
|
| [`RLMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_lmd/rlmd.py) (Robust Local Mean Decomposition) | [[paper]](https://www.sciencedirect.com/science/article/abs/pii/S0888327017301619) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/66935-robust-local-mean-decomposition-rlmd) | ✔️ |
|
|
111
|
-
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) |
|
|
111
|
+
| [`FMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/fmd.py) (Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/108099-feature-mode-decomposition-fmd) | ✔️ |
|
|
112
112
|
| [`NFMD`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_fmd/nfmd.py) (Non-stationary Feature Mode Decomposition) | [[paper]](https://ieeexplore.ieee.org/document/9732251) | [[code]](https://github.com/sheadan/NFMD-ExtractionInstantaneous/blob/master/nfmd/NFMD.py) | ✖️ |
|
|
113
113
|
| [`SSA`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ssa/ssa.py) (Singular Spectral Analysis) | [[paper]](https://orca.cardiff.ac.uk/id/eprint/15208/1/Zhiglavsky_SSA_encyclopedia.pdf) | [[code]](https://www.mathworks.com/matlabcentral/fileexchange/58967-singular-spectrum-analysis-beginners-guide) | ✔️ |
|
|
114
114
|
| [`EWT`](https://github.com/wwhenxuan/PySDKit/blob/main/pysdkit/_ewt/ewt.py) (Empirical Wavelet Transform) | [[paper]](https://ieeexplore.ieee.org/document/6522142) | [[code]](https://www.mathworks.com/help/wavelet/ug/empirical-wavelet-transform.html) | ✔️ |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
A Python library for signal decomposition algorithms.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
__version__ = "0.4.
|
|
5
|
+
__version__ = "0.4.23"
|
|
6
6
|
|
|
7
7
|
# Empirical Mode Decomposition
|
|
8
8
|
from ._emd import EMD
|
|
@@ -76,6 +76,9 @@ from ._ewt import ewt, EWT
|
|
|
76
76
|
# Jump Plus AM-FM Mode Decomposition
|
|
77
77
|
from ._jmd import JMD
|
|
78
78
|
|
|
79
|
+
# Feature Mode Decomposition
|
|
80
|
+
from ._fmd import FMD
|
|
81
|
+
|
|
79
82
|
# Moving Average Decomposition
|
|
80
83
|
from .tsa import Moving_Decomp
|
|
81
84
|
|
|
@@ -132,6 +135,7 @@ Variational Nonlinear Chirp Mode Decomposition | VNCMD
|
|
|
132
135
|
Iterative Nonlinear Chirp Mode Decomposition | INCMD
|
|
133
136
|
Empirical Wavelet Transform | EWT
|
|
134
137
|
Jump Plus AM-FM Mode Decomposition | JMD
|
|
138
|
+
Feature Mode Decomposition | FMD
|
|
135
139
|
Moving Average Decomposition | Moving
|
|
136
140
|
Seasonal-Trend decomposition using LOESS | STL
|
|
137
141
|
Hilbert-Huang Transform | HHT
|
|
@@ -167,6 +171,7 @@ __all__ = [
|
|
|
167
171
|
"ewt",
|
|
168
172
|
"EWT",
|
|
169
173
|
"JMD",
|
|
174
|
+
"FMD",
|
|
170
175
|
"Moving_Decomp",
|
|
171
176
|
"STL",
|
|
172
177
|
"models",
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
Created on 2025/02/03 18:36:18
|
|
4
|
-
@author: Whenxuan Wang
|
|
5
|
-
@email: wwhenxuan@gmail.com
|
|
6
|
-
"""
|
|
7
|
-
from ._splines import akima, cubic, pchip, cubic_hermite, cubic_spline_3pts
|
|
8
|
-
|
|
9
|
-
from ._find_extrema import find_extrema_parabol, find_extrema_simple
|
|
10
|
-
|
|
11
|
-
from ._prepare_points import prepare_points_parabol, prepare_points_simple
|
|
12
|
-
|
|
13
|
-
from .emd import EMD
|
|
14
|
-
|
|
15
|
-
from .eemd import EEMD
|
|
16
|
-
|
|
17
|
-
from .ceemdan import CEEMDAN
|
|
18
|
-
|
|
19
|
-
from .remd import REMD
|
|
20
|
-
|
|
21
|
-
from .memd import MEMD
|
|
22
|
-
|
|
23
|
-
from .tvf_emd import TVF_EMD
|
|
24
|
-
|
|
25
|
-
from .efd import EFD
|
|
26
|
-
|
|
27
|
-
from .hht import HHT
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on 2025/02/03 18:36:18
|
|
4
|
+
@author: Whenxuan Wang
|
|
5
|
+
@email: wwhenxuan@gmail.com
|
|
6
|
+
"""
|
|
7
|
+
from ._splines import akima, cubic, pchip, cubic_hermite, cubic_spline_3pts
|
|
8
|
+
|
|
9
|
+
from ._find_extrema import find_extrema_parabol, find_extrema_simple
|
|
10
|
+
|
|
11
|
+
from ._prepare_points import prepare_points_parabol, prepare_points_simple
|
|
12
|
+
|
|
13
|
+
from .emd import EMD
|
|
14
|
+
|
|
15
|
+
from .eemd import EEMD
|
|
16
|
+
|
|
17
|
+
from .ceemdan import CEEMDAN
|
|
18
|
+
|
|
19
|
+
from .remd import REMD
|
|
20
|
+
|
|
21
|
+
from .memd import MEMD
|
|
22
|
+
|
|
23
|
+
from .tvf_emd import TVF_EMD
|
|
24
|
+
|
|
25
|
+
from .efd import EFD
|
|
26
|
+
|
|
27
|
+
from .hht import HHT
|
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
Created on Sat Mar 5 21:38:26 2024
|
|
4
|
-
@author: Whenxuan Wang
|
|
5
|
-
@email: wwhenxuan@gmail.com
|
|
6
|
-
The following code is mainly used to find extreme points in the EMD algorithm
|
|
7
|
-
|
|
8
|
-
Code taken from https://github.com/laszukdawid/PyEMD/blob/master/PyEMD/EMD.py
|
|
9
|
-
"""
|
|
10
|
-
import numpy as np
|
|
11
|
-
from pysdkit.utils._process import not_duplicate, find_zero_crossings
|
|
12
|
-
from typing import Tuple
|
|
13
|
-
|
|
14
|
-
FindExtremaOutput = Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def find_extrema_parabol(time: np.ndarray, signal: np.ndarray) -> FindExtremaOutput:
|
|
18
|
-
"""
|
|
19
|
-
Performs parabolic estimation of extremum in a one-dimensional signal array S.
|
|
20
|
-
This method not only identifies the positions and values of local maxima and minima
|
|
21
|
-
by fitting a parabola to three consecutive points (where the middle point is the vertex of the parabola),
|
|
22
|
-
but also provides zero crossing points which are essential for signal analysis.
|
|
23
|
-
|
|
24
|
-
:param time: Array representing the time or sequence indices.
|
|
25
|
-
:param signal: One-dimensional array representing the signal values.
|
|
26
|
-
:return: Positions and values of local maxima and minima, and positions of zero crossings.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
# Detect zero crossings by comparing adjacent signal points
|
|
30
|
-
indzer = find_zero_crossings(signal=signal)
|
|
31
|
-
|
|
32
|
-
# Handling duplicate values which are crucial for accurate parabolic fitting
|
|
33
|
-
idx = not_duplicate(signal)
|
|
34
|
-
time = time[idx]
|
|
35
|
-
signal = signal[idx]
|
|
36
|
-
|
|
37
|
-
# Initialize variables for parabolic fitting
|
|
38
|
-
Tp, T0, Tn = time[:-2], time[1:-1], time[2:]
|
|
39
|
-
Sp, S0, Sn = signal[:-2], signal[1:-1], signal[2:]
|
|
40
|
-
TnTp, T0Tn, TpT0 = Tn - Tp, T0 - Tn, Tp - T0
|
|
41
|
-
scale = (
|
|
42
|
-
Tp * Tn * Tn
|
|
43
|
-
+ Tp * Tp * T0
|
|
44
|
-
+ T0 * T0 * Tn
|
|
45
|
-
- Tp * Tp * Tn
|
|
46
|
-
- Tp * T0 * T0
|
|
47
|
-
- T0 * Tn * Tn
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
# Compute coefficients of the parabola: y = ax^2 + bx + c
|
|
51
|
-
a = T0Tn * Sp + TnTp * S0 + TpT0 * Sn
|
|
52
|
-
b = (S0 - Sn) * Tp**2 + (Sn - Sp) * T0**2 + (Sp - S0) * Tn**2
|
|
53
|
-
c = T0 * Tn * T0Tn * Sp + Tn * Tp * TnTp * S0 + Tp * T0 * TpT0 * Sn
|
|
54
|
-
|
|
55
|
-
# Scale and adjust coefficients, and calculate vertex of parabola
|
|
56
|
-
a = a / scale
|
|
57
|
-
b = b / scale
|
|
58
|
-
c = c / scale
|
|
59
|
-
a[a == 0] = 1e-14
|
|
60
|
-
tVertex = -0.5 * b / a
|
|
61
|
-
idx = (tVertex < T0 + 0.5 * (Tn - T0)) & (tVertex >= T0 - 0.5 * (T0 - Tp))
|
|
62
|
-
|
|
63
|
-
# Select valid vertices and classify as maxima or minima based on 'a'
|
|
64
|
-
a, b, c = a[idx], b[idx], c[idx]
|
|
65
|
-
tVertex = tVertex[idx]
|
|
66
|
-
sVertex = a * tVertex * tVertex + b * tVertex + c
|
|
67
|
-
local_max_pos, local_max_val = tVertex[a < 0], sVertex[a < 0]
|
|
68
|
-
local_min_pos, local_min_val = tVertex[a > 0], sVertex[a > 0]
|
|
69
|
-
|
|
70
|
-
return local_max_pos, local_max_val, local_min_pos, local_min_val, indzer
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def find_extrema_simple(time: np.ndarray, signal: np.ndarray) -> FindExtremaOutput:
|
|
74
|
-
"""
|
|
75
|
-
Performs extrema detection in a given one-dimensional signal array S.
|
|
76
|
-
This method identifies local maxima and minima by analyzing the first differences of the signal.
|
|
77
|
-
The approach is straightforward and computationally efficient, making it suitable for signal processing applications
|
|
78
|
-
where quick identification of critical turning points in the signal is required.
|
|
79
|
-
|
|
80
|
-
:param time: Array representing the time or sequence indices.
|
|
81
|
-
:param signal: One-dimensional array representing the signal values.
|
|
82
|
-
:return: Positions and corresponding values of local maxima and minima, and the positions of zero crossings.
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
# Finds indexes of zero-crossings
|
|
86
|
-
indzer = find_zero_crossings(signal=signal)
|
|
87
|
-
|
|
88
|
-
# Finding local extrema points by using first differences
|
|
89
|
-
d = np.diff(signal)
|
|
90
|
-
|
|
91
|
-
# Constructing arrays of previous and next difference values
|
|
92
|
-
# d1 * d2 < 0 checks for sign changes in differences (product being negative),
|
|
93
|
-
# indicating a peak or trough between these difference points in signal S.
|
|
94
|
-
d1, d2 = d[:-1], d[1:]
|
|
95
|
-
indmin = np.nonzero(np.r_[d1 * d2 < 0] & np.r_[d1 < 0])[0] + 1
|
|
96
|
-
indmax = np.nonzero(np.r_[d1 * d2 < 0] & np.r_[d1 > 0])[0] + 1
|
|
97
|
-
|
|
98
|
-
# Handling cases when two or more points have the same value
|
|
99
|
-
if np.any(d == 0):
|
|
100
|
-
imax, imin = [], []
|
|
101
|
-
|
|
102
|
-
bad = d == 0
|
|
103
|
-
dd = np.diff(np.append(np.append(0, bad), 0))
|
|
104
|
-
debs = np.nonzero(dd == 1)[0]
|
|
105
|
-
fins = np.nonzero(dd == -1)[0]
|
|
106
|
-
if debs[0] == 1:
|
|
107
|
-
if len(debs) > 1:
|
|
108
|
-
debs, fins = debs[1:], fins[1:]
|
|
109
|
-
else:
|
|
110
|
-
debs, fins = [], []
|
|
111
|
-
|
|
112
|
-
if len(debs) > 0:
|
|
113
|
-
if fins[-1] == len(signal) - 1:
|
|
114
|
-
if len(debs) > 1:
|
|
115
|
-
debs, fins = debs[:-1], fins[:-1]
|
|
116
|
-
else:
|
|
117
|
-
debs, fins = [], []
|
|
118
|
-
|
|
119
|
-
lc = len(debs)
|
|
120
|
-
if lc > 0:
|
|
121
|
-
for k in range(lc):
|
|
122
|
-
if d[debs[k] - 1] > 0:
|
|
123
|
-
if d[fins[k]] < 0:
|
|
124
|
-
imax.append(np.round((fins[k] + debs[k]) / 2.0))
|
|
125
|
-
else:
|
|
126
|
-
if d[fins[k]] > 0:
|
|
127
|
-
imin.append(np.round((fins[k] + debs[k]) / 2.0))
|
|
128
|
-
|
|
129
|
-
if len(imax) > 0:
|
|
130
|
-
indmax = indmax.tolist()
|
|
131
|
-
for x in imax:
|
|
132
|
-
indmax.append(int(x))
|
|
133
|
-
indmax.sort()
|
|
134
|
-
|
|
135
|
-
if len(imin) > 0:
|
|
136
|
-
indmin = indmin.tolist()
|
|
137
|
-
for x in imin:
|
|
138
|
-
indmin.append(int(x))
|
|
139
|
-
indmin.sort()
|
|
140
|
-
|
|
141
|
-
local_max_pos = time[indmax]
|
|
142
|
-
local_max_val = signal[indmax]
|
|
143
|
-
local_min_pos = time[indmin]
|
|
144
|
-
local_min_val = signal[indmin]
|
|
145
|
-
|
|
146
|
-
return local_max_pos, local_max_val, local_min_pos, local_min_val, indzer
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Sat Mar 5 21:38:26 2024
|
|
4
|
+
@author: Whenxuan Wang
|
|
5
|
+
@email: wwhenxuan@gmail.com
|
|
6
|
+
The following code is mainly used to find extreme points in the EMD algorithm
|
|
7
|
+
|
|
8
|
+
Code taken from https://github.com/laszukdawid/PyEMD/blob/master/PyEMD/EMD.py
|
|
9
|
+
"""
|
|
10
|
+
import numpy as np
|
|
11
|
+
from pysdkit.utils._process import not_duplicate, find_zero_crossings
|
|
12
|
+
from typing import Tuple
|
|
13
|
+
|
|
14
|
+
FindExtremaOutput = Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def find_extrema_parabol(time: np.ndarray, signal: np.ndarray) -> FindExtremaOutput:
|
|
18
|
+
"""
|
|
19
|
+
Performs parabolic estimation of extremum in a one-dimensional signal array S.
|
|
20
|
+
This method not only identifies the positions and values of local maxima and minima
|
|
21
|
+
by fitting a parabola to three consecutive points (where the middle point is the vertex of the parabola),
|
|
22
|
+
but also provides zero crossing points which are essential for signal analysis.
|
|
23
|
+
|
|
24
|
+
:param time: Array representing the time or sequence indices.
|
|
25
|
+
:param signal: One-dimensional array representing the signal values.
|
|
26
|
+
:return: Positions and values of local maxima and minima, and positions of zero crossings.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# Detect zero crossings by comparing adjacent signal points
|
|
30
|
+
indzer = find_zero_crossings(signal=signal)
|
|
31
|
+
|
|
32
|
+
# Handling duplicate values which are crucial for accurate parabolic fitting
|
|
33
|
+
idx = not_duplicate(signal)
|
|
34
|
+
time = time[idx]
|
|
35
|
+
signal = signal[idx]
|
|
36
|
+
|
|
37
|
+
# Initialize variables for parabolic fitting
|
|
38
|
+
Tp, T0, Tn = time[:-2], time[1:-1], time[2:]
|
|
39
|
+
Sp, S0, Sn = signal[:-2], signal[1:-1], signal[2:]
|
|
40
|
+
TnTp, T0Tn, TpT0 = Tn - Tp, T0 - Tn, Tp - T0
|
|
41
|
+
scale = (
|
|
42
|
+
Tp * Tn * Tn
|
|
43
|
+
+ Tp * Tp * T0
|
|
44
|
+
+ T0 * T0 * Tn
|
|
45
|
+
- Tp * Tp * Tn
|
|
46
|
+
- Tp * T0 * T0
|
|
47
|
+
- T0 * Tn * Tn
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Compute coefficients of the parabola: y = ax^2 + bx + c
|
|
51
|
+
a = T0Tn * Sp + TnTp * S0 + TpT0 * Sn
|
|
52
|
+
b = (S0 - Sn) * Tp**2 + (Sn - Sp) * T0**2 + (Sp - S0) * Tn**2
|
|
53
|
+
c = T0 * Tn * T0Tn * Sp + Tn * Tp * TnTp * S0 + Tp * T0 * TpT0 * Sn
|
|
54
|
+
|
|
55
|
+
# Scale and adjust coefficients, and calculate vertex of parabola
|
|
56
|
+
a = a / scale
|
|
57
|
+
b = b / scale
|
|
58
|
+
c = c / scale
|
|
59
|
+
a[a == 0] = 1e-14
|
|
60
|
+
tVertex = -0.5 * b / a
|
|
61
|
+
idx = (tVertex < T0 + 0.5 * (Tn - T0)) & (tVertex >= T0 - 0.5 * (T0 - Tp))
|
|
62
|
+
|
|
63
|
+
# Select valid vertices and classify as maxima or minima based on 'a'
|
|
64
|
+
a, b, c = a[idx], b[idx], c[idx]
|
|
65
|
+
tVertex = tVertex[idx]
|
|
66
|
+
sVertex = a * tVertex * tVertex + b * tVertex + c
|
|
67
|
+
local_max_pos, local_max_val = tVertex[a < 0], sVertex[a < 0]
|
|
68
|
+
local_min_pos, local_min_val = tVertex[a > 0], sVertex[a > 0]
|
|
69
|
+
|
|
70
|
+
return local_max_pos, local_max_val, local_min_pos, local_min_val, indzer
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def find_extrema_simple(time: np.ndarray, signal: np.ndarray) -> FindExtremaOutput:
|
|
74
|
+
"""
|
|
75
|
+
Performs extrema detection in a given one-dimensional signal array S.
|
|
76
|
+
This method identifies local maxima and minima by analyzing the first differences of the signal.
|
|
77
|
+
The approach is straightforward and computationally efficient, making it suitable for signal processing applications
|
|
78
|
+
where quick identification of critical turning points in the signal is required.
|
|
79
|
+
|
|
80
|
+
:param time: Array representing the time or sequence indices.
|
|
81
|
+
:param signal: One-dimensional array representing the signal values.
|
|
82
|
+
:return: Positions and corresponding values of local maxima and minima, and the positions of zero crossings.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
# Finds indexes of zero-crossings
|
|
86
|
+
indzer = find_zero_crossings(signal=signal)
|
|
87
|
+
|
|
88
|
+
# Finding local extrema points by using first differences
|
|
89
|
+
d = np.diff(signal)
|
|
90
|
+
|
|
91
|
+
# Constructing arrays of previous and next difference values
|
|
92
|
+
# d1 * d2 < 0 checks for sign changes in differences (product being negative),
|
|
93
|
+
# indicating a peak or trough between these difference points in signal S.
|
|
94
|
+
d1, d2 = d[:-1], d[1:]
|
|
95
|
+
indmin = np.nonzero(np.r_[d1 * d2 < 0] & np.r_[d1 < 0])[0] + 1
|
|
96
|
+
indmax = np.nonzero(np.r_[d1 * d2 < 0] & np.r_[d1 > 0])[0] + 1
|
|
97
|
+
|
|
98
|
+
# Handling cases when two or more points have the same value
|
|
99
|
+
if np.any(d == 0):
|
|
100
|
+
imax, imin = [], []
|
|
101
|
+
|
|
102
|
+
bad = d == 0
|
|
103
|
+
dd = np.diff(np.append(np.append(0, bad), 0))
|
|
104
|
+
debs = np.nonzero(dd == 1)[0]
|
|
105
|
+
fins = np.nonzero(dd == -1)[0]
|
|
106
|
+
if debs[0] == 1:
|
|
107
|
+
if len(debs) > 1:
|
|
108
|
+
debs, fins = debs[1:], fins[1:]
|
|
109
|
+
else:
|
|
110
|
+
debs, fins = [], []
|
|
111
|
+
|
|
112
|
+
if len(debs) > 0:
|
|
113
|
+
if fins[-1] == len(signal) - 1:
|
|
114
|
+
if len(debs) > 1:
|
|
115
|
+
debs, fins = debs[:-1], fins[:-1]
|
|
116
|
+
else:
|
|
117
|
+
debs, fins = [], []
|
|
118
|
+
|
|
119
|
+
lc = len(debs)
|
|
120
|
+
if lc > 0:
|
|
121
|
+
for k in range(lc):
|
|
122
|
+
if d[debs[k] - 1] > 0:
|
|
123
|
+
if d[fins[k]] < 0:
|
|
124
|
+
imax.append(np.round((fins[k] + debs[k]) / 2.0))
|
|
125
|
+
else:
|
|
126
|
+
if d[fins[k]] > 0:
|
|
127
|
+
imin.append(np.round((fins[k] + debs[k]) / 2.0))
|
|
128
|
+
|
|
129
|
+
if len(imax) > 0:
|
|
130
|
+
indmax = indmax.tolist()
|
|
131
|
+
for x in imax:
|
|
132
|
+
indmax.append(int(x))
|
|
133
|
+
indmax.sort()
|
|
134
|
+
|
|
135
|
+
if len(imin) > 0:
|
|
136
|
+
indmin = indmin.tolist()
|
|
137
|
+
for x in imin:
|
|
138
|
+
indmin.append(int(x))
|
|
139
|
+
indmin.sort()
|
|
140
|
+
|
|
141
|
+
local_max_pos = time[indmax]
|
|
142
|
+
local_max_val = signal[indmax]
|
|
143
|
+
local_min_pos = time[indmin]
|
|
144
|
+
local_min_val = signal[indmin]
|
|
145
|
+
|
|
146
|
+
return local_max_pos, local_max_val, local_min_pos, local_min_val, indzer
|