PySDKit 0.4.44__tar.gz → 0.4.45__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.44 → pysdkit-0.4.45}/PKG-INFO +31 -24
- {pysdkit-0.4.44 → pysdkit-0.4.45}/PySDKit.egg-info/PKG-INFO +31 -24
- {pysdkit-0.4.44 → pysdkit-0.4.45}/PySDKit.egg-info/SOURCES.txt +1 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/README.md +30 -23
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/__init__.py +1 -1
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/vmd_c.py +116 -50
- pysdkit-0.4.45/pysdkit/_vmd/vmd_f.py +192 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/__init__.py +4 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_generator.py +24 -0
- pysdkit-0.4.45/pysdkit/data/vmd_example.npy +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/__init__.py +1 -1
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/_plot_imfs.py +274 -15
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_vmd.py +26 -0
- pysdkit-0.4.44/pysdkit/_vmd/vmd_f.py +0 -156
- {pysdkit-0.4.44 → pysdkit-0.4.45}/LICENSE +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/PySDKit.egg-info/dependency_links.txt +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/PySDKit.egg-info/requires.txt +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/PySDKit.egg-info/top_level.txt +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pyproject.toml +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/_find_extrema.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/_prepare_points.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/_splines.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/ceemdan.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/eemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/efd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/emd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/esmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/hht/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/hht/frequency.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/hht/hht.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/memd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/remd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/semd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd/tvf_emd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd2d/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd2d/bemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd2d/bmemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_emd2d/emd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_ewt/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_ewt/ewt.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_ewt/ewt2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/extrema.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/faemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/faemd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/faemd3d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_faemd/filter.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_fmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_fmd/fmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_fmd/nfmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_gdmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_gdmd/agncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_gdmd/gdmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_gdmd/ivgnmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_gdmd/vgnmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_imd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_imd/apmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_imd/data/gearbox_fault_snippet.npy +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_imd/data/input_sig.npy +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_imd/imd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_jmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_jmd/jmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_jmd/mjmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_jmd/sjmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_lmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_lmd/lmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_lmd/rlmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_osd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_osd/components.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_osd/osd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_osd/swd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/alif.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/data/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/data/prefixed_double_filter.npy +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/hvd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/itd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/iterative_filtering.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_tid/ssa.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/acmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/avmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/ba_acmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/base.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/mvmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/ovmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/stvmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/svmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd/vme.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd2d/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd2d/cvmd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vmd2d/vmd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vncmd/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vncmd/avncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vncmd/incmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/_vncmd/vncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_add_noise.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_cube.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_image.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_models.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_test_univariate.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/_time_series.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/fmd_demo.npy +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/data/texture.txt +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/entropy/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/entropy/_approxiamte_entropy.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/entropy/_permutation_entropy.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/entropy/_sample_entropy.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/models/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/models/_base.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/models/_kmeans.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/models/_knn.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/models/_pca.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/_fourier_spectra.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/_functions.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/_plot_images.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/plot/_plot_signal.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/data/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/data/test_generator_cube.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/data/test_generator_image.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/data/test_generator_signal.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/data/test_generator_univariate_signal.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/models/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/models/test_knn.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/models/test_pca.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/run_all.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_agncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_alif.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_apmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_avncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_bmemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ceemdan.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_cvmd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_eemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_emd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_esmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ewt.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ewt2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_faemd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_faemd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_faemd3d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_fmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_gdmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_hvd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_imd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_itd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ivgnmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_jmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_lmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_moving_decomp.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_mstl.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_osd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ovmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_rlmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_semd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_sjmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_ssa.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_stl.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_stvmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_svmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_swd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_vgnmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_vmd2d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tests/test_vncmd.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tsa/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tsa/_dtw.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tsa/_moving_decomp.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tsa/_mstl.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/tsa/_stl.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/__init__.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_correlation.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_diagnalization.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_differ.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_fft.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_function.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_hilbert.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_instantaneous.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_kernel_matrix.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_mirror.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_process.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/pysdkit/utils/_smooth1d.py +0 -0
- {pysdkit-0.4.44 → pysdkit-0.4.45}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PySDKit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.45
|
|
4
4
|
Summary: A Python library for signal decomposition algorithms with a unified interface.
|
|
5
5
|
Author: Whenxuan Wang, RuiZhe Wang, Rongkun Zhu, Kai Wu, Lei Wang, josefinez, Deeksha Manjunath, Yuan Feng, WenTong Zhao, JacktheFowler
|
|
6
6
|
Maintainer-email: Whenxuan Wang <wwhenxuan@gmail.com>, RuiZhe Wang <3133986068@qq.com>
|
|
@@ -51,10 +51,10 @@ Requires-Dist: tqdm>=4.66.5
|
|
|
51
51
|
Requires-Dist: requests>=2.32.3
|
|
52
52
|
Dynamic: license-file
|
|
53
53
|
|
|
54
|
-
# PySDKit: signal decomposition in Python
|
|
55
|
-
|
|
56
54
|
<div align="center">
|
|
57
55
|
|
|
56
|
+
# PySDKit: signal decomposition in Python
|
|
57
|
+
|
|
58
58
|
[](https://pypi.org/project/PySDKit/)
|
|
59
59
|

|
|
60
60
|
[](https://www.python.org/)
|
|
@@ -91,50 +91,57 @@ This project integrates simple signal processing methods, signal decomposition a
|
|
|
91
91
|
4. Visualize and analyze the original signal and the intrinsic mode functions IMFs obtained by decomposition.
|
|
92
92
|
|
|
93
93
|
~~~python
|
|
94
|
+
import numpy as np
|
|
94
95
|
from pysdkit import EMD
|
|
95
|
-
from pysdkit.data import test_emd
|
|
96
96
|
from pysdkit.plot import plot_IMFs
|
|
97
97
|
|
|
98
|
-
t
|
|
98
|
+
t = np.linspace(0, 1, 1000)
|
|
99
|
+
signal = np.sin(2 * np.pi * 5 * t) + 0.7 * np.sin(2 * np.pi * 25 * t) + 0.45 * np.sin(2 * np.pi * 80 * t)
|
|
99
100
|
|
|
100
|
-
# create an instance for signal decomposition
|
|
101
101
|
emd = EMD()
|
|
102
|
-
|
|
103
|
-
IMFs =
|
|
104
|
-
plot_IMFs(signal, IMFs)
|
|
102
|
+
IMFs = emd.fit_transform(signal, max_imfs=3)
|
|
103
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=1000, freq_max=150)
|
|
105
104
|
~~~
|
|
106
105
|
|
|
107
|
-

|
|
108
107
|
|
|
109
108
|
The EMD in the above example is the most classic [`empirical mode decomposition`](https://www.mathworks.com/help/signal/ref/emd.html) algorithm in signal decomposition. For more complex signals, you can try other algorithms such as variational mode decomposition ([`VMD`](https://ieeexplore.ieee.org/abstract/document/6655981)).
|
|
110
109
|
|
|
111
110
|
~~~python
|
|
112
|
-
import numpy as np
|
|
113
111
|
from pysdkit import VMD
|
|
112
|
+
from pysdkit.data import test_vmd
|
|
113
|
+
from pysdkit.plot import plot_IMFs
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
signal = np.load("./example/example.npy")
|
|
117
|
-
|
|
118
|
-
# use variational mode decomposition
|
|
119
|
-
vmd = VMD(alpha=500, K=3, tau=0.0, tol=1e-9)
|
|
120
|
-
IMFs = vmd.fit_transform(signal=signal)
|
|
121
|
-
print(IMFs.shape)
|
|
115
|
+
t, signal, fs = test_vmd()
|
|
122
116
|
|
|
123
|
-
vmd
|
|
117
|
+
vmd = VMD(alpha=2000, K=4, tau=0.0, tol=1e-7)
|
|
118
|
+
IMFs = vmd.fit_transform(signal)
|
|
119
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=fs, freq_max=fs / 2)
|
|
124
120
|
~~~
|
|
125
121
|
|
|
126
122
|

|
|
127
123
|
|
|
128
|
-
|
|
124
|
+
For multichannel recordings, algorithms such as multivariate VMD ([`MVMD`](https://doi.org/10.1109/TSP.2019.2951223)) keep shared oscillations **mode-aligned** across channels:
|
|
129
125
|
|
|
130
126
|
~~~python
|
|
131
|
-
|
|
127
|
+
import numpy as np
|
|
128
|
+
from pysdkit import MVMD
|
|
129
|
+
from pysdkit.plot import plot_IMFs
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
t = np.arange(0, 1, 0.001)
|
|
132
|
+
# ch1: 2+36 Hz, ch2: 24+36 Hz, ch3: 80+36 Hz (36 Hz shared)
|
|
133
|
+
signal = np.vstack([
|
|
134
|
+
np.cos(2*np.pi*2*t) + np.cos(2*np.pi*36*t),
|
|
135
|
+
np.cos(2*np.pi*24*t) + np.cos(2*np.pi*36*t),
|
|
136
|
+
np.cos(2*np.pi*80*t) + np.cos(2*np.pi*36*t),
|
|
137
|
+
])
|
|
138
|
+
|
|
139
|
+
mvmd = MVMD(alpha=2000, K=4, tau=0.0, init="uniform")
|
|
140
|
+
IMFs = mvmd.fit_transform(signal) # shape: (K, T, C)
|
|
141
|
+
plot_IMFs(signal, IMFs) # per-channel panels
|
|
135
142
|
~~~
|
|
136
143
|
|
|
137
|
-

|
|
138
145
|
|
|
139
146
|
## Target 🎯 <a id="Target"></a>
|
|
140
147
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PySDKit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.45
|
|
4
4
|
Summary: A Python library for signal decomposition algorithms with a unified interface.
|
|
5
5
|
Author: Whenxuan Wang, RuiZhe Wang, Rongkun Zhu, Kai Wu, Lei Wang, josefinez, Deeksha Manjunath, Yuan Feng, WenTong Zhao, JacktheFowler
|
|
6
6
|
Maintainer-email: Whenxuan Wang <wwhenxuan@gmail.com>, RuiZhe Wang <3133986068@qq.com>
|
|
@@ -51,10 +51,10 @@ Requires-Dist: tqdm>=4.66.5
|
|
|
51
51
|
Requires-Dist: requests>=2.32.3
|
|
52
52
|
Dynamic: license-file
|
|
53
53
|
|
|
54
|
-
# PySDKit: signal decomposition in Python
|
|
55
|
-
|
|
56
54
|
<div align="center">
|
|
57
55
|
|
|
56
|
+
# PySDKit: signal decomposition in Python
|
|
57
|
+
|
|
58
58
|
[](https://pypi.org/project/PySDKit/)
|
|
59
59
|

|
|
60
60
|
[](https://www.python.org/)
|
|
@@ -91,50 +91,57 @@ This project integrates simple signal processing methods, signal decomposition a
|
|
|
91
91
|
4. Visualize and analyze the original signal and the intrinsic mode functions IMFs obtained by decomposition.
|
|
92
92
|
|
|
93
93
|
~~~python
|
|
94
|
+
import numpy as np
|
|
94
95
|
from pysdkit import EMD
|
|
95
|
-
from pysdkit.data import test_emd
|
|
96
96
|
from pysdkit.plot import plot_IMFs
|
|
97
97
|
|
|
98
|
-
t
|
|
98
|
+
t = np.linspace(0, 1, 1000)
|
|
99
|
+
signal = np.sin(2 * np.pi * 5 * t) + 0.7 * np.sin(2 * np.pi * 25 * t) + 0.45 * np.sin(2 * np.pi * 80 * t)
|
|
99
100
|
|
|
100
|
-
# create an instance for signal decomposition
|
|
101
101
|
emd = EMD()
|
|
102
|
-
|
|
103
|
-
IMFs =
|
|
104
|
-
plot_IMFs(signal, IMFs)
|
|
102
|
+
IMFs = emd.fit_transform(signal, max_imfs=3)
|
|
103
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=1000, freq_max=150)
|
|
105
104
|
~~~
|
|
106
105
|
|
|
107
|
-

|
|
108
107
|
|
|
109
108
|
The EMD in the above example is the most classic [`empirical mode decomposition`](https://www.mathworks.com/help/signal/ref/emd.html) algorithm in signal decomposition. For more complex signals, you can try other algorithms such as variational mode decomposition ([`VMD`](https://ieeexplore.ieee.org/abstract/document/6655981)).
|
|
110
109
|
|
|
111
110
|
~~~python
|
|
112
|
-
import numpy as np
|
|
113
111
|
from pysdkit import VMD
|
|
112
|
+
from pysdkit.data import test_vmd
|
|
113
|
+
from pysdkit.plot import plot_IMFs
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
signal = np.load("./example/example.npy")
|
|
117
|
-
|
|
118
|
-
# use variational mode decomposition
|
|
119
|
-
vmd = VMD(alpha=500, K=3, tau=0.0, tol=1e-9)
|
|
120
|
-
IMFs = vmd.fit_transform(signal=signal)
|
|
121
|
-
print(IMFs.shape)
|
|
115
|
+
t, signal, fs = test_vmd()
|
|
122
116
|
|
|
123
|
-
vmd
|
|
117
|
+
vmd = VMD(alpha=2000, K=4, tau=0.0, tol=1e-7)
|
|
118
|
+
IMFs = vmd.fit_transform(signal)
|
|
119
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=fs, freq_max=fs / 2)
|
|
124
120
|
~~~
|
|
125
121
|
|
|
126
122
|

|
|
127
123
|
|
|
128
|
-
|
|
124
|
+
For multichannel recordings, algorithms such as multivariate VMD ([`MVMD`](https://doi.org/10.1109/TSP.2019.2951223)) keep shared oscillations **mode-aligned** across channels:
|
|
129
125
|
|
|
130
126
|
~~~python
|
|
131
|
-
|
|
127
|
+
import numpy as np
|
|
128
|
+
from pysdkit import MVMD
|
|
129
|
+
from pysdkit.plot import plot_IMFs
|
|
132
130
|
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
t = np.arange(0, 1, 0.001)
|
|
132
|
+
# ch1: 2+36 Hz, ch2: 24+36 Hz, ch3: 80+36 Hz (36 Hz shared)
|
|
133
|
+
signal = np.vstack([
|
|
134
|
+
np.cos(2*np.pi*2*t) + np.cos(2*np.pi*36*t),
|
|
135
|
+
np.cos(2*np.pi*24*t) + np.cos(2*np.pi*36*t),
|
|
136
|
+
np.cos(2*np.pi*80*t) + np.cos(2*np.pi*36*t),
|
|
137
|
+
])
|
|
138
|
+
|
|
139
|
+
mvmd = MVMD(alpha=2000, K=4, tau=0.0, init="uniform")
|
|
140
|
+
IMFs = mvmd.fit_transform(signal) # shape: (K, T, C)
|
|
141
|
+
plot_IMFs(signal, IMFs) # per-channel panels
|
|
135
142
|
~~~
|
|
136
143
|
|
|
137
|
-

|
|
138
145
|
|
|
139
146
|
## Target 🎯 <a id="Target"></a>
|
|
140
147
|
|
|
@@ -97,6 +97,7 @@ pysdkit/data/_test_univariate.py
|
|
|
97
97
|
pysdkit/data/_time_series.py
|
|
98
98
|
pysdkit/data/fmd_demo.npy
|
|
99
99
|
pysdkit/data/texture.txt
|
|
100
|
+
pysdkit/data/vmd_example.npy
|
|
100
101
|
pysdkit/entropy/__init__.py
|
|
101
102
|
pysdkit/entropy/_approxiamte_entropy.py
|
|
102
103
|
pysdkit/entropy/_permutation_entropy.py
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# PySDKit: signal decomposition in Python
|
|
2
|
-
|
|
3
1
|
<div align="center">
|
|
4
2
|
|
|
3
|
+
# PySDKit: signal decomposition in Python
|
|
4
|
+
|
|
5
5
|
[](https://pypi.org/project/PySDKit/)
|
|
6
6
|

|
|
7
7
|
[](https://www.python.org/)
|
|
@@ -38,50 +38,57 @@ This project integrates simple signal processing methods, signal decomposition a
|
|
|
38
38
|
4. Visualize and analyze the original signal and the intrinsic mode functions IMFs obtained by decomposition.
|
|
39
39
|
|
|
40
40
|
~~~python
|
|
41
|
+
import numpy as np
|
|
41
42
|
from pysdkit import EMD
|
|
42
|
-
from pysdkit.data import test_emd
|
|
43
43
|
from pysdkit.plot import plot_IMFs
|
|
44
44
|
|
|
45
|
-
t
|
|
45
|
+
t = np.linspace(0, 1, 1000)
|
|
46
|
+
signal = np.sin(2 * np.pi * 5 * t) + 0.7 * np.sin(2 * np.pi * 25 * t) + 0.45 * np.sin(2 * np.pi * 80 * t)
|
|
46
47
|
|
|
47
|
-
# create an instance for signal decomposition
|
|
48
48
|
emd = EMD()
|
|
49
|
-
|
|
50
|
-
IMFs =
|
|
51
|
-
plot_IMFs(signal, IMFs)
|
|
49
|
+
IMFs = emd.fit_transform(signal, max_imfs=3)
|
|
50
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=1000, freq_max=150)
|
|
52
51
|
~~~
|
|
53
52
|
|
|
54
|
-

|
|
55
54
|
|
|
56
55
|
The EMD in the above example is the most classic [`empirical mode decomposition`](https://www.mathworks.com/help/signal/ref/emd.html) algorithm in signal decomposition. For more complex signals, you can try other algorithms such as variational mode decomposition ([`VMD`](https://ieeexplore.ieee.org/abstract/document/6655981)).
|
|
57
56
|
|
|
58
57
|
~~~python
|
|
59
|
-
import numpy as np
|
|
60
58
|
from pysdkit import VMD
|
|
59
|
+
from pysdkit.data import test_vmd
|
|
60
|
+
from pysdkit.plot import plot_IMFs
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
signal = np.load("./example/example.npy")
|
|
64
|
-
|
|
65
|
-
# use variational mode decomposition
|
|
66
|
-
vmd = VMD(alpha=500, K=3, tau=0.0, tol=1e-9)
|
|
67
|
-
IMFs = vmd.fit_transform(signal=signal)
|
|
68
|
-
print(IMFs.shape)
|
|
62
|
+
t, signal, fs = test_vmd()
|
|
69
63
|
|
|
70
|
-
vmd
|
|
64
|
+
vmd = VMD(alpha=2000, K=4, tau=0.0, tol=1e-7)
|
|
65
|
+
IMFs = vmd.fit_transform(signal)
|
|
66
|
+
plot_IMFs(signal, IMFs, view="2d_freq", fs=fs, freq_max=fs / 2)
|
|
71
67
|
~~~
|
|
72
68
|
|
|
73
69
|

|
|
74
70
|
|
|
75
|
-
|
|
71
|
+
For multichannel recordings, algorithms such as multivariate VMD ([`MVMD`](https://doi.org/10.1109/TSP.2019.2951223)) keep shared oscillations **mode-aligned** across channels:
|
|
76
72
|
|
|
77
73
|
~~~python
|
|
78
|
-
|
|
74
|
+
import numpy as np
|
|
75
|
+
from pysdkit import MVMD
|
|
76
|
+
from pysdkit.plot import plot_IMFs
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
t = np.arange(0, 1, 0.001)
|
|
79
|
+
# ch1: 2+36 Hz, ch2: 24+36 Hz, ch3: 80+36 Hz (36 Hz shared)
|
|
80
|
+
signal = np.vstack([
|
|
81
|
+
np.cos(2*np.pi*2*t) + np.cos(2*np.pi*36*t),
|
|
82
|
+
np.cos(2*np.pi*24*t) + np.cos(2*np.pi*36*t),
|
|
83
|
+
np.cos(2*np.pi*80*t) + np.cos(2*np.pi*36*t),
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
mvmd = MVMD(alpha=2000, K=4, tau=0.0, init="uniform")
|
|
87
|
+
IMFs = mvmd.fit_transform(signal) # shape: (K, T, C)
|
|
88
|
+
plot_IMFs(signal, IMFs) # per-channel panels
|
|
82
89
|
~~~
|
|
83
90
|
|
|
84
|
-

|
|
85
92
|
|
|
86
93
|
## Target 🎯 <a id="Target"></a>
|
|
87
94
|
|
|
@@ -14,8 +14,8 @@ class VMD(Base):
|
|
|
14
14
|
"""
|
|
15
15
|
Variational mode decomposition, object-oriented interface.
|
|
16
16
|
|
|
17
|
-
Original paper: Dragomiretskiy, K. and Zosso, D. (2014)
|
|
18
|
-
IEEE Transactions on Signal Processing, 62(3), pp. 531
|
|
17
|
+
Original paper: Dragomiretskiy, K. and Zosso, D. (2014) "Variational Mode Decomposition",
|
|
18
|
+
IEEE Transactions on Signal Processing, 62(3), pp. 531-544. doi: 10.1109/TSP.2013.2288675.
|
|
19
19
|
|
|
20
20
|
The goal of VMD is to decompose the input signal into a series of modes with sparse characteristics.
|
|
21
21
|
The sparse characteristics here refer to the fact that all modes are narrowband signals concentrated near their respective center frequencies.
|
|
@@ -50,6 +50,7 @@ class VMD(Base):
|
|
|
50
50
|
DC: bool = False,
|
|
51
51
|
max_iter: int = 500,
|
|
52
52
|
tol: float = 1e-6,
|
|
53
|
+
store_history: bool = True,
|
|
53
54
|
) -> None:
|
|
54
55
|
"""
|
|
55
56
|
:param alpha: the balancing parameter of the data-fidelity constraint
|
|
@@ -61,6 +62,12 @@ class VMD(Base):
|
|
|
61
62
|
:param DC: true if the first mode is put and kept at DC (0-freq)
|
|
62
63
|
:param max_iter: Maximum number of iterations
|
|
63
64
|
:param tol: tolerance of convergence criterion; typically around 1e-6
|
|
65
|
+
:param store_history: If True (default), keep spectral iterates for every
|
|
66
|
+
ADMM step with shape ``(max_iter, T, K)``. If False, keep only the
|
|
67
|
+
previous / current spectral buffers (``O(T * K)`` memory). Use
|
|
68
|
+
``store_history=False`` for long signals to avoid large allocations.
|
|
69
|
+
Center-frequency history ``omega`` is always retained (cheap).
|
|
70
|
+
Decomposition quality is unchanged; only peak memory differs.
|
|
64
71
|
"""
|
|
65
72
|
super().__init__()
|
|
66
73
|
# parameters of VMD signal decomposition algorithm
|
|
@@ -71,6 +78,7 @@ class VMD(Base):
|
|
|
71
78
|
self.DC = DC
|
|
72
79
|
self.max_iter = max_iter
|
|
73
80
|
self.tol = tol
|
|
81
|
+
self.store_history = bool(store_history)
|
|
74
82
|
|
|
75
83
|
# The last input original signal
|
|
76
84
|
self.signal = None
|
|
@@ -109,18 +117,22 @@ class VMD(Base):
|
|
|
109
117
|
def plot_IMFs(
|
|
110
118
|
self,
|
|
111
119
|
max_imf: int = -1,
|
|
120
|
+
view: str = "2d",
|
|
112
121
|
colors: Optional[List] = None,
|
|
113
122
|
save_figure: bool = False,
|
|
114
123
|
return_figure: bool = False,
|
|
115
|
-
dpi: int =
|
|
124
|
+
dpi: int = 256,
|
|
116
125
|
spine_width: float = 2,
|
|
117
126
|
labelpad: float = 10,
|
|
118
127
|
save_name: Optional[str] = None,
|
|
128
|
+
fs: Optional[float] = None,
|
|
129
|
+
freq_max: Optional[float] = None,
|
|
119
130
|
) -> None:
|
|
120
131
|
"""
|
|
121
132
|
An easy way to visualize signal decomposition results
|
|
122
133
|
|
|
123
134
|
:param max_imf: The number of decomposition modes to be plotted
|
|
135
|
+
:param view: ``\"2d\"`` / ``\"3d\"`` / ``\"2d_freq\"``
|
|
124
136
|
:param colors: List of color strings for plotting
|
|
125
137
|
:param save_figure: Whether to save the figure as an image
|
|
126
138
|
:param return_figure: Whether to return the figure object
|
|
@@ -128,13 +140,17 @@ class VMD(Base):
|
|
|
128
140
|
:param spine_width: The width of the visible axes spines
|
|
129
141
|
:param labelpad: Controls the filling distance of the y-axis coordinate
|
|
130
142
|
:param save_name: The name of the saved image file
|
|
143
|
+
:param fs: sampling frequency for ``view=\"2d_freq\"``
|
|
144
|
+
:param freq_max: spectrum x-limit for ``view=\"2d_freq\"``
|
|
145
|
+
|
|
131
146
|
:return: The figure object for the plot
|
|
132
147
|
"""
|
|
133
148
|
if self.u is not None and self.signal is not None:
|
|
134
|
-
plot_IMFs(
|
|
149
|
+
return plot_IMFs(
|
|
135
150
|
signal=self.signal,
|
|
136
151
|
IMFs=self.u,
|
|
137
152
|
max_imfs=max_imf,
|
|
153
|
+
view=view,
|
|
138
154
|
colors=colors,
|
|
139
155
|
save_figure=save_figure,
|
|
140
156
|
return_figure=return_figure,
|
|
@@ -142,6 +158,8 @@ class VMD(Base):
|
|
|
142
158
|
spine_width=spine_width,
|
|
143
159
|
labelpad=labelpad,
|
|
144
160
|
save_name=save_name,
|
|
161
|
+
fs=fs,
|
|
162
|
+
freq_max=freq_max,
|
|
145
163
|
)
|
|
146
164
|
else:
|
|
147
165
|
raise ValueError
|
|
@@ -182,70 +200,118 @@ class VMD(Base):
|
|
|
182
200
|
|
|
183
201
|
# For future generalizations: individual alpha for each mode
|
|
184
202
|
alpha = np.ones(self.K) * self.alpha
|
|
185
|
-
#
|
|
186
|
-
u_hat_plus = np.zeros([self.max_iter, len(freqs), self.K], dtype=complex)
|
|
187
|
-
# Initialization of omega_k
|
|
203
|
+
# Initialization of omega_k (always keep full history; it is cheap)
|
|
188
204
|
omega_plus = self.__init_omega(fs=fs)
|
|
189
205
|
if self.DC:
|
|
190
206
|
omega_plus[0, 0] = 0
|
|
191
|
-
# start with empty dual variables
|
|
192
|
-
lambda_hat = np.zeros(shape=[self.max_iter, len(freqs)], dtype=complex)
|
|
193
207
|
|
|
194
208
|
sum_uk = 0 # accumulator
|
|
195
209
|
convergence = (
|
|
196
210
|
np.spacing(1) + self.tol
|
|
197
211
|
) # Determine whether the algorithm converges
|
|
212
|
+
n = 0
|
|
198
213
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
u_hat_plus[n + 1, :, 0] = (f_hat_plus - sum_uk - lambda_hat[n, :] / 2) / (
|
|
204
|
-
1.0 + alpha[0] * (freqs - omega_plus[n, 0]) ** 2
|
|
205
|
-
)
|
|
214
|
+
if self.store_history:
|
|
215
|
+
# Full spectral history: O(max_iter * T * K) memory
|
|
216
|
+
u_hat_plus = np.zeros([self.max_iter, len(freqs), self.K], dtype=complex)
|
|
217
|
+
lambda_hat = np.zeros(shape=[self.max_iter, len(freqs)], dtype=complex)
|
|
206
218
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
freqs[T // 2 : T], (abs(u_hat_plus[n + 1, T // 2 : T, 0]) ** 2)
|
|
211
|
-
) / np.sum(abs(u_hat_plus[n + 1, T // 2 : T, 0]) ** 2)
|
|
212
|
-
|
|
213
|
-
# update of any other mode
|
|
214
|
-
for k in range(1, self.K):
|
|
215
|
-
# mode spectrum
|
|
216
|
-
sum_uk = u_hat_plus[n + 1, :, k - 1] + sum_uk - u_hat_plus[n, :, k]
|
|
217
|
-
u_hat_plus[n + 1, :, k] = (
|
|
219
|
+
for n in range(0, self.max_iter - 1):
|
|
220
|
+
sum_uk = u_hat_plus[n, :, self.K - 1] + sum_uk - u_hat_plus[n, :, 0]
|
|
221
|
+
u_hat_plus[n + 1, :, 0] = (
|
|
218
222
|
f_hat_plus - sum_uk - lambda_hat[n, :] / 2
|
|
219
|
-
) / (1 + alpha[
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
) / (1.0 + alpha[0] * (freqs - omega_plus[n, 0]) ** 2)
|
|
224
|
+
|
|
225
|
+
if not self.DC:
|
|
226
|
+
omega_plus[n + 1, 0] = np.dot(
|
|
227
|
+
freqs[T // 2 : T],
|
|
228
|
+
(abs(u_hat_plus[n + 1, T // 2 : T, 0]) ** 2),
|
|
229
|
+
) / np.sum(abs(u_hat_plus[n + 1, T // 2 : T, 0]) ** 2)
|
|
230
|
+
|
|
231
|
+
for k in range(1, self.K):
|
|
232
|
+
sum_uk = u_hat_plus[n + 1, :, k - 1] + sum_uk - u_hat_plus[n, :, k]
|
|
233
|
+
u_hat_plus[n + 1, :, k] = (
|
|
234
|
+
f_hat_plus - sum_uk - lambda_hat[n, :] / 2
|
|
235
|
+
) / (1 + alpha[k] * (freqs - omega_plus[n, k]) ** 2)
|
|
236
|
+
omega_plus[n + 1, k] = np.dot(
|
|
237
|
+
freqs[T // 2 : T],
|
|
238
|
+
(abs(u_hat_plus[n + 1, T // 2 : T, k]) ** 2),
|
|
239
|
+
) / np.sum(abs(u_hat_plus[n + 1, T // 2 : T, k]) ** 2)
|
|
240
|
+
|
|
241
|
+
lambda_hat[n + 1, :] = lambda_hat[n, :] + self.tau * (
|
|
242
|
+
np.sum(u_hat_plus[n + 1, :, :], axis=1) - f_hat_plus
|
|
243
|
+
)
|
|
229
244
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
245
|
+
for i in range(self.K):
|
|
246
|
+
convergence = convergence + (1 / T) * np.dot(
|
|
247
|
+
(u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i]),
|
|
248
|
+
np.conj((u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i])),
|
|
249
|
+
)
|
|
250
|
+
convergence = np.abs(convergence)
|
|
251
|
+
if convergence <= self.tol:
|
|
252
|
+
break
|
|
253
|
+
|
|
254
|
+
niter = np.min([self.max_iter, n])
|
|
255
|
+
omega = omega_plus[:niter, :]
|
|
256
|
+
u_spec = u_hat_plus[niter - 1]
|
|
257
|
+
|
|
258
|
+
else:
|
|
259
|
+
# Low-memory path: only previous / current spectral buffers
|
|
260
|
+
# Memory: O(T * K) instead of O(max_iter * T * K)
|
|
261
|
+
u_old = np.zeros([len(freqs), self.K], dtype=complex)
|
|
262
|
+
u_new = np.zeros([len(freqs), self.K], dtype=complex)
|
|
263
|
+
lambda_hat = np.zeros(len(freqs), dtype=complex)
|
|
264
|
+
u_spec = u_old
|
|
265
|
+
|
|
266
|
+
for n in range(0, self.max_iter - 1):
|
|
267
|
+
sum_uk = u_old[:, self.K - 1] + sum_uk - u_old[:, 0]
|
|
268
|
+
u_new[:, 0] = (f_hat_plus - sum_uk - lambda_hat / 2) / (
|
|
269
|
+
1.0 + alpha[0] * (freqs - omega_plus[n, 0]) ** 2
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if not self.DC:
|
|
273
|
+
omega_plus[n + 1, 0] = np.dot(
|
|
274
|
+
freqs[T // 2 : T],
|
|
275
|
+
(abs(u_new[T // 2 : T, 0]) ** 2),
|
|
276
|
+
) / np.sum(abs(u_new[T // 2 : T, 0]) ** 2)
|
|
277
|
+
|
|
278
|
+
for k in range(1, self.K):
|
|
279
|
+
sum_uk = u_new[:, k - 1] + sum_uk - u_old[:, k]
|
|
280
|
+
u_new[:, k] = (f_hat_plus - sum_uk - lambda_hat / 2) / (
|
|
281
|
+
1 + alpha[k] * (freqs - omega_plus[n, k]) ** 2
|
|
282
|
+
)
|
|
283
|
+
omega_plus[n + 1, k] = np.dot(
|
|
284
|
+
freqs[T // 2 : T],
|
|
285
|
+
(abs(u_new[T // 2 : T, k]) ** 2),
|
|
286
|
+
) / np.sum(abs(u_new[T // 2 : T, k]) ** 2)
|
|
287
|
+
|
|
288
|
+
lambda_hat = lambda_hat + self.tau * (
|
|
289
|
+
np.sum(u_new, axis=1) - f_hat_plus
|
|
235
290
|
)
|
|
236
|
-
convergence = np.abs(convergence)
|
|
237
|
-
if convergence <= self.tol:
|
|
238
|
-
break
|
|
239
291
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
292
|
+
# Per-iteration residual between consecutive spectral iterates
|
|
293
|
+
convergence = np.spacing(1)
|
|
294
|
+
for i in range(self.K):
|
|
295
|
+
delta = u_new[:, i] - u_old[:, i]
|
|
296
|
+
convergence = convergence + (1 / T) * np.dot(delta, np.conj(delta))
|
|
297
|
+
convergence = np.abs(convergence)
|
|
298
|
+
u_spec = u_new
|
|
299
|
+
|
|
300
|
+
if convergence <= self.tol:
|
|
301
|
+
break
|
|
302
|
+
|
|
303
|
+
# Roll buffers for the next iteration
|
|
304
|
+
u_old, u_new = u_new, u_old
|
|
305
|
+
|
|
306
|
+
niter = np.min([self.max_iter, n + 1])
|
|
307
|
+
omega = omega_plus[:niter, :]
|
|
308
|
+
|
|
243
309
|
idxs = np.flip(np.arange(1, T // 2 + 1), axis=0)
|
|
244
310
|
|
|
245
311
|
# signal reconstruction
|
|
246
312
|
u_hat = np.zeros([T, self.K], dtype=complex)
|
|
247
|
-
u_hat[T // 2 : T, :] =
|
|
248
|
-
u_hat[idxs, :] = np.conj(
|
|
313
|
+
u_hat[T // 2 : T, :] = u_spec[T // 2 : T, :]
|
|
314
|
+
u_hat[idxs, :] = np.conj(u_spec[T // 2 : T, :])
|
|
249
315
|
u_hat[0, :] = np.conj(u_hat[-1, :])
|
|
250
316
|
|
|
251
317
|
u = np.zeros([self.K, len(t)])
|