PySDKit 0.1__py3-none-any.whl
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.1.dist-info/METADATA +27 -0
- PySDKit-0.1.dist-info/RECORD +11 -0
- PySDKit-0.1.dist-info/WHEEL +5 -0
- PySDKit-0.1.dist-info/top_level.txt +5 -0
- emd/__init__.py +0 -0
- ewt/__init__.py +0 -0
- mvmd/__init__.py +0 -0
- vmd/__init__.py +2 -0
- vmd/vmd_c.py +129 -0
- vmd/vmd_f.py +159 -0
- vncmd/__init__.py +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: PySDKit
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: name
|
|
5
|
+
Home-page: https://github.com/wwhenxuan/PySDKit
|
|
6
|
+
Author: whenxuan
|
|
7
|
+
Author-email: wwhenxuan@gmail.com
|
|
8
|
+
Keywords: signal,decomposition
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
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
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Requires-Python: >=3.6
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: numpy (>=1.24.3)
|
|
23
|
+
Requires-Dist: scipy (>=1.11.1)
|
|
24
|
+
Requires-Dist: matplotlib (>=3.7.2)
|
|
25
|
+
|
|
26
|
+
# PySDKit
|
|
27
|
+
A Python library for signal decomposition algorithms
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
emd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
ewt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
mvmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
vmd/__init__.py,sha256=yoyBg52MTOUcajkYfbtVLdM_IKnsc5NTwEAzkfBGaQM,48
|
|
5
|
+
vmd/vmd_c.py,sha256=Oy6Re6R-gXPuYtklmfnQgNkRpfygE6Jpi0VeWiXyMVc,4788
|
|
6
|
+
vmd/vmd_f.py,sha256=89Tu0hhCTokyB4QPndO07hr0ArOq6W60MuLyxua896g,5766
|
|
7
|
+
vncmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
PySDKit-0.1.dist-info/METADATA,sha256=AyVRpdGrG8qPNbLBEex5KWdgHGA9g-Rn8DZvdzyN82U,1021
|
|
9
|
+
PySDKit-0.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
10
|
+
PySDKit-0.1.dist-info/top_level.txt,sha256=Mn_ZYJ167ryWAHmWUC5gBa0hZ6W0tnSslxynaV2nnj0,23
|
|
11
|
+
PySDKit-0.1.dist-info/RECORD,,
|
emd/__init__.py
ADDED
|
File without changes
|
ewt/__init__.py
ADDED
|
File without changes
|
mvmd/__init__.py
ADDED
|
File without changes
|
vmd/__init__.py
ADDED
vmd/vmd_c.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class VMD(object):
|
|
6
|
+
|
|
7
|
+
def __init__(self):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
def fit_transform(self, f, alpha, tau, K, DC, init, tol):
|
|
11
|
+
if len(f) % 2:
|
|
12
|
+
f = f[:-1]
|
|
13
|
+
|
|
14
|
+
# Period and sampling frequency of input signal
|
|
15
|
+
fs = 1. / len(f)
|
|
16
|
+
|
|
17
|
+
ltemp = len(f) // 2
|
|
18
|
+
fMirr = np.append(np.flip(f[:ltemp], axis=0), f)
|
|
19
|
+
fMirr = np.append(fMirr, np.flip(f[-ltemp:], axis=0))
|
|
20
|
+
|
|
21
|
+
# Time Domain 0 to T (of mirrored signal)
|
|
22
|
+
T = len(fMirr)
|
|
23
|
+
t = np.arange(1, T + 1) / T
|
|
24
|
+
|
|
25
|
+
# Spectral Domain discretization
|
|
26
|
+
freqs = t - 0.5 - (1 / T)
|
|
27
|
+
|
|
28
|
+
# Maximum number of iterations (if not converged yet, then it won't anyway)
|
|
29
|
+
Niter = 500
|
|
30
|
+
# For future generalizations: individual alpha for each mode
|
|
31
|
+
Alpha = alpha * np.ones(K)
|
|
32
|
+
|
|
33
|
+
# Construct and center f_hat
|
|
34
|
+
f_hat = np.fft.fftshift((np.fft.fft(fMirr)))
|
|
35
|
+
f_hat_plus = np.copy(f_hat) # copy f_hat
|
|
36
|
+
f_hat_plus[:T // 2] = 0
|
|
37
|
+
|
|
38
|
+
# Initialization of omega_k
|
|
39
|
+
omega_plus = np.zeros([Niter, K])
|
|
40
|
+
|
|
41
|
+
if init == 1:
|
|
42
|
+
for i in range(K):
|
|
43
|
+
omega_plus[0, i] = (0.5 / K) * (i)
|
|
44
|
+
elif init == 2:
|
|
45
|
+
omega_plus[0, :] = np.sort(np.exp(np.log(fs) + (np.log(0.5) - np.log(fs)) * np.random.rand(1, K)))
|
|
46
|
+
else:
|
|
47
|
+
omega_plus[0, :] = 0
|
|
48
|
+
|
|
49
|
+
# if DC mode imposed, set its omega to 0
|
|
50
|
+
if DC:
|
|
51
|
+
omega_plus[0, 0] = 0
|
|
52
|
+
|
|
53
|
+
# start with empty dual variables
|
|
54
|
+
lambda_hat = np.zeros([Niter, len(freqs)], dtype=complex)
|
|
55
|
+
|
|
56
|
+
# other inits
|
|
57
|
+
uDiff = tol + np.spacing(1) # update step
|
|
58
|
+
n = 0 # loop counter
|
|
59
|
+
sum_uk = 0 # accumulator
|
|
60
|
+
# matrix keeping track of every iterant // could be discarded for mem
|
|
61
|
+
u_hat_plus = np.zeros([Niter, len(freqs), K], dtype=complex)
|
|
62
|
+
|
|
63
|
+
# *** Main loop for iterative updates***
|
|
64
|
+
|
|
65
|
+
while (uDiff > tol and n < Niter - 1): # not converged and below iterations limit
|
|
66
|
+
# update first mode accumulator
|
|
67
|
+
k = 0
|
|
68
|
+
sum_uk = u_hat_plus[n, :, K - 1] + sum_uk - u_hat_plus[n, :, 0]
|
|
69
|
+
|
|
70
|
+
# update spectrum of first mode through Wiener filter of residuals
|
|
71
|
+
u_hat_plus[n + 1, :, k] = (f_hat_plus - sum_uk - lambda_hat[n, :] / 2) / (
|
|
72
|
+
1. + Alpha[k] * (freqs - omega_plus[n, k]) ** 2)
|
|
73
|
+
|
|
74
|
+
# update first omega if not held at 0
|
|
75
|
+
if not (DC):
|
|
76
|
+
omega_plus[n + 1, k] = np.dot(freqs[T // 2:T], (abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)) / np.sum(
|
|
77
|
+
abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)
|
|
78
|
+
|
|
79
|
+
# update of any other mode
|
|
80
|
+
for k in np.arange(1, K):
|
|
81
|
+
# accumulator
|
|
82
|
+
sum_uk = u_hat_plus[n + 1, :, k - 1] + sum_uk - u_hat_plus[n, :, k]
|
|
83
|
+
# mode spectrum
|
|
84
|
+
u_hat_plus[n + 1, :, k] = (f_hat_plus - sum_uk - lambda_hat[n, :] / 2) / (
|
|
85
|
+
1 + Alpha[k] * (freqs - omega_plus[n, k]) ** 2)
|
|
86
|
+
# center frequencies
|
|
87
|
+
omega_plus[n + 1, k] = np.dot(freqs[T // 2:T], (abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)) / np.sum(
|
|
88
|
+
abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)
|
|
89
|
+
|
|
90
|
+
# Dual ascent
|
|
91
|
+
lambda_hat[n + 1, :] = lambda_hat[n, :] + tau * (np.sum(u_hat_plus[n + 1, :, :], axis=1) - f_hat_plus)
|
|
92
|
+
|
|
93
|
+
# loop counter
|
|
94
|
+
n = n + 1
|
|
95
|
+
|
|
96
|
+
# converged yet?
|
|
97
|
+
uDiff = np.spacing(1)
|
|
98
|
+
for i in range(K):
|
|
99
|
+
uDiff = uDiff + (1 / T) * np.dot((u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i]),
|
|
100
|
+
np.conj((u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i])))
|
|
101
|
+
|
|
102
|
+
uDiff = np.abs(uDiff)
|
|
103
|
+
|
|
104
|
+
# Postprocessing and cleanup
|
|
105
|
+
|
|
106
|
+
# discard empty space if converged early
|
|
107
|
+
Niter = np.min([Niter, n])
|
|
108
|
+
omega = omega_plus[:Niter, :]
|
|
109
|
+
|
|
110
|
+
idxs = np.flip(np.arange(1, T // 2 + 1), axis=0)
|
|
111
|
+
# Signal reconstruction
|
|
112
|
+
u_hat = np.zeros([T, K], dtype=complex)
|
|
113
|
+
u_hat[T // 2:T, :] = u_hat_plus[Niter - 1, T // 2:T, :]
|
|
114
|
+
u_hat[idxs, :] = np.conj(u_hat_plus[Niter - 1, T // 2:T, :])
|
|
115
|
+
u_hat[0, :] = np.conj(u_hat[-1, :])
|
|
116
|
+
|
|
117
|
+
u = np.zeros([K, len(t)])
|
|
118
|
+
for k in range(K):
|
|
119
|
+
u[k, :] = np.real(np.fft.ifft(np.fft.ifftshift(u_hat[:, k])))
|
|
120
|
+
|
|
121
|
+
# remove mirror part
|
|
122
|
+
u = u[:, T // 4:3 * T // 4]
|
|
123
|
+
|
|
124
|
+
# recompute spectrum
|
|
125
|
+
u_hat = np.zeros([u.shape[1], K], dtype=complex)
|
|
126
|
+
for k in range(K):
|
|
127
|
+
u_hat[:, k] = np.fft.fftshift(np.fft.fft(u[k, :]))
|
|
128
|
+
|
|
129
|
+
return u, u_hat, omega
|
vmd/vmd_f.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Wed Feb 20 19:24:58 2019
|
|
4
|
+
|
|
5
|
+
@author: Vinícius Rezende Carvalho
|
|
6
|
+
"""
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def vmd(f, alpha, tau, K, DC, init, tol):
|
|
11
|
+
"""
|
|
12
|
+
u,u_hat,omega = VMD(f, alpha, tau, K, DC, init, tol)
|
|
13
|
+
Variational mode decomposition
|
|
14
|
+
Python implementation by Vinícius Rezende Carvalho - vrcarva@gmail.com
|
|
15
|
+
code based on Dominique Zosso's MATLAB code, available at:
|
|
16
|
+
https://www.mathworks.com/matlabcentral/fileexchange/44765-variational-mode-decomposition
|
|
17
|
+
Original paper:
|
|
18
|
+
Dragomiretskiy, K. and Zosso, D. (2014) ‘Variational Mode Decomposition’,
|
|
19
|
+
IEEE Transactions on Signal Processing, 62(3), pp. 531–544. doi: 10.1109/TSP.2013.2288675.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Input and Parameters:
|
|
23
|
+
---------------------
|
|
24
|
+
f - the time domain signal (1D) to be decomposed
|
|
25
|
+
alpha - the balancing parameter of the data-fidelity constraint
|
|
26
|
+
tau - time-step of the dual ascent ( pick 0 for noise-slack )
|
|
27
|
+
K - the number of modes to be recovered
|
|
28
|
+
DC - true if the first mode is put and kept at DC (0-freq)
|
|
29
|
+
init - 0 = all omegas start at 0
|
|
30
|
+
1 = all omegas start uniformly distributed
|
|
31
|
+
2 = all omegas initialized randomly
|
|
32
|
+
tol - tolerance of convergence criterion; typically around 1e-6
|
|
33
|
+
|
|
34
|
+
Output:
|
|
35
|
+
-------
|
|
36
|
+
u - the collection of decomposed modes
|
|
37
|
+
u_hat - spectra of the modes
|
|
38
|
+
omega - estimated mode center-frequencies
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
if len(f) % 2:
|
|
42
|
+
f = f[:-1]
|
|
43
|
+
|
|
44
|
+
# Period and sampling frequency of input signal
|
|
45
|
+
fs = 1. / len(f)
|
|
46
|
+
|
|
47
|
+
ltemp = len(f) // 2
|
|
48
|
+
fMirr = np.append(np.flip(f[:ltemp], axis=0), f)
|
|
49
|
+
fMirr = np.append(fMirr, np.flip(f[-ltemp:], axis=0))
|
|
50
|
+
|
|
51
|
+
# Time Domain 0 to T (of mirrored signal)
|
|
52
|
+
T = len(fMirr)
|
|
53
|
+
t = np.arange(1, T + 1) / T
|
|
54
|
+
|
|
55
|
+
# Spectral Domain discretization
|
|
56
|
+
freqs = t - 0.5 - (1 / T)
|
|
57
|
+
|
|
58
|
+
# Maximum number of iterations (if not converged yet, then it won't anyway)
|
|
59
|
+
Niter = 500
|
|
60
|
+
# For future generalizations: individual alpha for each mode
|
|
61
|
+
Alpha = alpha * np.ones(K)
|
|
62
|
+
|
|
63
|
+
# Construct and center f_hat
|
|
64
|
+
f_hat = np.fft.fftshift((np.fft.fft(fMirr)))
|
|
65
|
+
f_hat_plus = np.copy(f_hat) # copy f_hat
|
|
66
|
+
f_hat_plus[:T // 2] = 0
|
|
67
|
+
|
|
68
|
+
# Initialization of omega_k
|
|
69
|
+
omega_plus = np.zeros([Niter, K])
|
|
70
|
+
|
|
71
|
+
if init == 1:
|
|
72
|
+
for i in range(K):
|
|
73
|
+
omega_plus[0, i] = (0.5 / K) * (i)
|
|
74
|
+
elif init == 2:
|
|
75
|
+
omega_plus[0, :] = np.sort(np.exp(np.log(fs) + (np.log(0.5) - np.log(fs)) * np.random.rand(1, K)))
|
|
76
|
+
else:
|
|
77
|
+
omega_plus[0, :] = 0
|
|
78
|
+
|
|
79
|
+
# if DC mode imposed, set its omega to 0
|
|
80
|
+
if DC:
|
|
81
|
+
omega_plus[0, 0] = 0
|
|
82
|
+
|
|
83
|
+
# start with empty dual variables
|
|
84
|
+
lambda_hat = np.zeros([Niter, len(freqs)], dtype=complex)
|
|
85
|
+
|
|
86
|
+
# other inits
|
|
87
|
+
uDiff = tol + np.spacing(1) # update step
|
|
88
|
+
n = 0 # loop counter
|
|
89
|
+
sum_uk = 0 # accumulator
|
|
90
|
+
# matrix keeping track of every iterant // could be discarded for mem
|
|
91
|
+
u_hat_plus = np.zeros([Niter, len(freqs), K], dtype=complex)
|
|
92
|
+
|
|
93
|
+
# *** Main loop for iterative updates***
|
|
94
|
+
|
|
95
|
+
while (uDiff > tol and n < Niter - 1): # not converged and below iterations limit
|
|
96
|
+
# update first mode accumulator
|
|
97
|
+
k = 0
|
|
98
|
+
sum_uk = u_hat_plus[n, :, K - 1] + sum_uk - u_hat_plus[n, :, 0]
|
|
99
|
+
|
|
100
|
+
# update spectrum of first mode through Wiener filter of residuals
|
|
101
|
+
u_hat_plus[n + 1, :, k] = (f_hat_plus - sum_uk - lambda_hat[n, :] / 2) / (
|
|
102
|
+
1. + Alpha[k] * (freqs - omega_plus[n, k]) ** 2)
|
|
103
|
+
|
|
104
|
+
# update first omega if not held at 0
|
|
105
|
+
if not (DC):
|
|
106
|
+
omega_plus[n + 1, k] = np.dot(freqs[T // 2:T], (abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)) / np.sum(
|
|
107
|
+
abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)
|
|
108
|
+
|
|
109
|
+
# update of any other mode
|
|
110
|
+
for k in np.arange(1, K):
|
|
111
|
+
# accumulator
|
|
112
|
+
sum_uk = u_hat_plus[n + 1, :, k - 1] + sum_uk - u_hat_plus[n, :, k]
|
|
113
|
+
# mode spectrum
|
|
114
|
+
u_hat_plus[n + 1, :, k] = (f_hat_plus - sum_uk - lambda_hat[n, :] / 2) / (
|
|
115
|
+
1 + Alpha[k] * (freqs - omega_plus[n, k]) ** 2)
|
|
116
|
+
# center frequencies
|
|
117
|
+
omega_plus[n + 1, k] = np.dot(freqs[T // 2:T], (abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)) / np.sum(
|
|
118
|
+
abs(u_hat_plus[n + 1, T // 2:T, k]) ** 2)
|
|
119
|
+
|
|
120
|
+
# Dual ascent
|
|
121
|
+
lambda_hat[n + 1, :] = lambda_hat[n, :] + tau * (np.sum(u_hat_plus[n + 1, :, :], axis=1) - f_hat_plus)
|
|
122
|
+
|
|
123
|
+
# loop counter
|
|
124
|
+
n = n + 1
|
|
125
|
+
|
|
126
|
+
# converged yet?
|
|
127
|
+
uDiff = np.spacing(1)
|
|
128
|
+
for i in range(K):
|
|
129
|
+
uDiff = uDiff + (1 / T) * np.dot((u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i]),
|
|
130
|
+
np.conj((u_hat_plus[n, :, i] - u_hat_plus[n - 1, :, i])))
|
|
131
|
+
|
|
132
|
+
uDiff = np.abs(uDiff)
|
|
133
|
+
|
|
134
|
+
# Postprocessing and cleanup
|
|
135
|
+
|
|
136
|
+
# discard empty space if converged early
|
|
137
|
+
Niter = np.min([Niter, n])
|
|
138
|
+
omega = omega_plus[:Niter, :]
|
|
139
|
+
|
|
140
|
+
idxs = np.flip(np.arange(1, T // 2 + 1), axis=0)
|
|
141
|
+
# Signal reconstruction
|
|
142
|
+
u_hat = np.zeros([T, K], dtype=complex)
|
|
143
|
+
u_hat[T // 2:T, :] = u_hat_plus[Niter - 1, T // 2:T, :]
|
|
144
|
+
u_hat[idxs, :] = np.conj(u_hat_plus[Niter - 1, T // 2:T, :])
|
|
145
|
+
u_hat[0, :] = np.conj(u_hat[-1, :])
|
|
146
|
+
|
|
147
|
+
u = np.zeros([K, len(t)])
|
|
148
|
+
for k in range(K):
|
|
149
|
+
u[k, :] = np.real(np.fft.ifft(np.fft.ifftshift(u_hat[:, k])))
|
|
150
|
+
|
|
151
|
+
# remove mirror part
|
|
152
|
+
u = u[:, T // 4:3 * T // 4]
|
|
153
|
+
|
|
154
|
+
# recompute spectrum
|
|
155
|
+
u_hat = np.zeros([u.shape[1], K], dtype=complex)
|
|
156
|
+
for k in range(K):
|
|
157
|
+
u_hat[:, k] = np.fft.fftshift(np.fft.fft(u[k, :]))
|
|
158
|
+
|
|
159
|
+
return u, u_hat, omega
|
vncmd/__init__.py
ADDED
|
File without changes
|