Modal-Decomposition 0.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.
- Modal_Decomposition/CEEFD.py +118 -0
- Modal_Decomposition/CEEMD.py +129 -0
- Modal_Decomposition/COLOR/__init__.py +18 -0
- Modal_Decomposition/COLOR/color_define.py +30 -0
- Modal_Decomposition/COLOR/colorful_print.py +66 -0
- Modal_Decomposition/EEMD.py +24 -0
- Modal_Decomposition/EFD.py +94 -0
- Modal_Decomposition/EMD.py +53 -0
- Modal_Decomposition/EWT.py +61 -0
- Modal_Decomposition/FMD.py +69 -0
- Modal_Decomposition/ICEEMDAN.py +152 -0
- Modal_Decomposition/LMD.py +159 -0
- Modal_Decomposition/MEMD.py +233 -0
- Modal_Decomposition/RPSEMD.py +79 -0
- Modal_Decomposition/SSA.py +112 -0
- Modal_Decomposition/SVMD.py +60 -0
- Modal_Decomposition/VMD.py +33 -0
- Modal_Decomposition/__init__.py +84 -0
- Modal_Decomposition/help_function.py +64 -0
- modal_decomposition-0.0.1.dist-info/METADATA +111 -0
- modal_decomposition-0.0.1.dist-info/RECORD +24 -0
- modal_decomposition-0.0.1.dist-info/WHEEL +5 -0
- modal_decomposition-0.0.1.dist-info/licenses/LICENSE +202 -0
- modal_decomposition-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
EMD-signal - 1.9.0
|
|
7
|
+
|
|
8
|
+
Only accessed by: (must)
|
|
9
|
+
Only __init__.py
|
|
10
|
+
|
|
11
|
+
Modify: (must)
|
|
12
|
+
2026.3.25
|
|
13
|
+
|
|
14
|
+
Description: (if None write None)
|
|
15
|
+
Realize the CEEFD and CEEMDAN.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
class CEEFD:
|
|
21
|
+
"""
|
|
22
|
+
CEEFD
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__ \
|
|
26
|
+
(
|
|
27
|
+
self,
|
|
28
|
+
trials=10,
|
|
29
|
+
noise_width=0.05, # default: 0.05-0.3
|
|
30
|
+
noise_seed=42, # seed
|
|
31
|
+
spline_kind='cubic',
|
|
32
|
+
nbsym=2, # Number of boundary symmetry points
|
|
33
|
+
extrema_detection='parabol',
|
|
34
|
+
parallel=False,
|
|
35
|
+
processes=None, # None = auto, int >= 1
|
|
36
|
+
random_state=42,
|
|
37
|
+
noise_scale=1.0, # scale factor of noise
|
|
38
|
+
noise_kind='normal', # noise kind: 'normal', 'uniform'
|
|
39
|
+
range_thr=0.01, # Stop threshold
|
|
40
|
+
total_power_thr=0.005
|
|
41
|
+
):
|
|
42
|
+
|
|
43
|
+
self.trials = trials
|
|
44
|
+
self.noise_width = noise_width
|
|
45
|
+
self.noise_seed = noise_seed
|
|
46
|
+
self.spline_kind = spline_kind
|
|
47
|
+
self.nbsym = nbsym
|
|
48
|
+
self.extrema_detection = extrema_detection
|
|
49
|
+
self.parallel = parallel
|
|
50
|
+
self.processes = processes
|
|
51
|
+
self.random_state = random_state
|
|
52
|
+
self.noise_scale = noise_scale
|
|
53
|
+
self.noise_kind = noise_kind
|
|
54
|
+
self.range_thr = range_thr
|
|
55
|
+
self.total_power_thr = total_power_thr
|
|
56
|
+
|
|
57
|
+
def give_ceemdan(self):
|
|
58
|
+
from PyEMD import CEEMDAN
|
|
59
|
+
|
|
60
|
+
return CEEMDAN \
|
|
61
|
+
(
|
|
62
|
+
trials=self.trials,
|
|
63
|
+
noise_width=self.noise_width,
|
|
64
|
+
noise_seed=self.noise_seed,
|
|
65
|
+
spline_kind=self.spline_kind,
|
|
66
|
+
nbsym=self.nbsym,
|
|
67
|
+
extrema_detection=self.extrema_detection,
|
|
68
|
+
parallel=self.parallel,
|
|
69
|
+
processes=self.processes,
|
|
70
|
+
random_state=self.random_state,
|
|
71
|
+
noise_scale=self.noise_scale,
|
|
72
|
+
noise_kind=self.noise_kind,
|
|
73
|
+
range_thr=self.range_thr,
|
|
74
|
+
total_power_thr=self.total_power_thr
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def ceemdan(self, S, T=None, max_imf=-1):
|
|
78
|
+
CEEMDAN = self.give_ceemdan()
|
|
79
|
+
IMF_Residue = CEEMDAN.ceemdan(S, T, max_imf)
|
|
80
|
+
|
|
81
|
+
IMFs = IMF_Residue[:-1, :] # shape [n_imfs, len(S)]
|
|
82
|
+
Res = IMF_Residue[-1, :]
|
|
83
|
+
|
|
84
|
+
return IMFs, Res
|
|
85
|
+
|
|
86
|
+
def ceefd(self, S, T=None, max_imf=-1):
|
|
87
|
+
"""
|
|
88
|
+
:return: other_IMFs (ndarray-2D), IMF_ (np.ndarray-2D), Res (ndarray), Res_ (ndarray)
|
|
89
|
+
"""
|
|
90
|
+
from .EFD import EFD
|
|
91
|
+
import antropy as ant
|
|
92
|
+
|
|
93
|
+
CEEMDAN = self.give_ceemdan()
|
|
94
|
+
IMF_Residue = CEEMDAN.ceemdan(S, T, max_imf)
|
|
95
|
+
|
|
96
|
+
IMFs = IMF_Residue[:-1, :] # shape [n_imfs, len(S)]
|
|
97
|
+
Res = IMF_Residue[-1, :]
|
|
98
|
+
|
|
99
|
+
# cal sample entropy of IMF
|
|
100
|
+
Entropy = [ant.sample_entropy(IMF) for IMF in IMFs]
|
|
101
|
+
max_entropy_mask = np.argmax(Entropy)
|
|
102
|
+
maxIMF = IMFs[max_entropy_mask]
|
|
103
|
+
|
|
104
|
+
# EMD for max antropy IMF
|
|
105
|
+
if T is None:
|
|
106
|
+
T_efd = np.arange(len(maxIMF))
|
|
107
|
+
else:
|
|
108
|
+
T_efd = T
|
|
109
|
+
IMF_, Res_ = EFD(maxIMF, T_efd)
|
|
110
|
+
|
|
111
|
+
# get other_IMFs
|
|
112
|
+
other_IMFs_list = [IMF for i, IMF in enumerate(IMFs) if i != max_entropy_mask]
|
|
113
|
+
if other_IMFs_list:
|
|
114
|
+
other_IMFs = np.stack(other_IMFs_list)
|
|
115
|
+
else:
|
|
116
|
+
other_IMFs = None
|
|
117
|
+
|
|
118
|
+
return other_IMFs, np.array(IMF_), Res, Res_
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
numpy - 2.2.6
|
|
7
|
+
time - 1.39.2
|
|
8
|
+
tqdm - 4.67.3
|
|
9
|
+
|
|
10
|
+
Only accessed by: (must)
|
|
11
|
+
Only __init__.py
|
|
12
|
+
|
|
13
|
+
Modify: (must)
|
|
14
|
+
2026.3.25
|
|
15
|
+
|
|
16
|
+
Description: (if None write None)
|
|
17
|
+
Realize the CEEMD.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from time import sleep
|
|
21
|
+
import numpy as np
|
|
22
|
+
from .EMD import emd
|
|
23
|
+
from .help_function import is_increasing
|
|
24
|
+
from tqdm import tqdm
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def ceemd(S, T=None, fs=None, beta=0.3, max_imf=None, iterations=30, verbose: bool=False):
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
:param S:
|
|
32
|
+
:param T:
|
|
33
|
+
:param fs:
|
|
34
|
+
:param beta:
|
|
35
|
+
:param max_imf: -1 or other int | 100 is enough, if you choose -1, no one kown when it will finish(^_^)
|
|
36
|
+
:param iterations:
|
|
37
|
+
:param verbose:
|
|
38
|
+
:return:
|
|
39
|
+
"""
|
|
40
|
+
N = len(S)
|
|
41
|
+
|
|
42
|
+
if max_imf is None:
|
|
43
|
+
max_imf = int(np.log2(len(S))) + 2
|
|
44
|
+
|
|
45
|
+
if T is None:
|
|
46
|
+
if fs is not None:
|
|
47
|
+
# smaple
|
|
48
|
+
dt = 1.0 / fs
|
|
49
|
+
T = np.arange(N) * dt
|
|
50
|
+
else:
|
|
51
|
+
# default smaple f = 1
|
|
52
|
+
T = np.arange(N)
|
|
53
|
+
print(f"Warn: T is None,default T = [0, 1, 2, ..., {N - 1}]")
|
|
54
|
+
|
|
55
|
+
# Standard
|
|
56
|
+
MEAN = np.mean(S)
|
|
57
|
+
S = S - MEAN
|
|
58
|
+
STD = np.std(S)
|
|
59
|
+
S = S / STD
|
|
60
|
+
|
|
61
|
+
Res = S
|
|
62
|
+
IMFs = []
|
|
63
|
+
|
|
64
|
+
std_dev = np.std(S)
|
|
65
|
+
mean = np.mean(S)
|
|
66
|
+
|
|
67
|
+
count = 0
|
|
68
|
+
while True:
|
|
69
|
+
IMF = np.zeros(N)
|
|
70
|
+
|
|
71
|
+
if verbose:
|
|
72
|
+
for i in tqdm(range(iterations // 2), position=0, file=sys.stdout, desc="iter: "):
|
|
73
|
+
white_noise = np.random.normal(mean, std_dev * beta, N)
|
|
74
|
+
|
|
75
|
+
S_plus = Res + white_noise
|
|
76
|
+
S_minus = Res - white_noise
|
|
77
|
+
|
|
78
|
+
IMFs_plus, _ = emd(S_plus, T)
|
|
79
|
+
IMFs_minus, _ = emd(S_minus, T)
|
|
80
|
+
|
|
81
|
+
if len(IMFs_plus) == 0 or len(IMFs_minus) == 0:
|
|
82
|
+
continue
|
|
83
|
+
|
|
84
|
+
IMFs_avg = (IMFs_plus[0, :] + IMFs_minus[0, :]) / 2
|
|
85
|
+
|
|
86
|
+
IMF += IMFs_avg
|
|
87
|
+
|
|
88
|
+
else:
|
|
89
|
+
for i in range(iterations // 2):
|
|
90
|
+
white_noise = np.random.normal(mean, std_dev * beta, N)
|
|
91
|
+
|
|
92
|
+
S_plus = Res + white_noise
|
|
93
|
+
S_minus = Res - white_noise
|
|
94
|
+
|
|
95
|
+
IMFs_plus, _ = emd(S_plus, T)
|
|
96
|
+
IMFs_minus, _ = emd(S_minus, T)
|
|
97
|
+
|
|
98
|
+
if len(IMFs_plus) == 0 or len(IMFs_minus) == 0:
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
IMFs_avg = (IMFs_plus[0, :] + IMFs_minus[0, :]) / 2
|
|
102
|
+
|
|
103
|
+
IMF += IMFs_avg
|
|
104
|
+
|
|
105
|
+
IMF = IMF / (iterations / 2)
|
|
106
|
+
IMFs.append(IMF * STD + MEAN)
|
|
107
|
+
count += 1
|
|
108
|
+
|
|
109
|
+
if verbose:
|
|
110
|
+
if count % 10 == 0:
|
|
111
|
+
tqdm.write(f"has get {count} IMFs...")
|
|
112
|
+
sleep(1)
|
|
113
|
+
|
|
114
|
+
if max_imf != -1:
|
|
115
|
+
if count >= max_imf:
|
|
116
|
+
Res = Res - IMF
|
|
117
|
+
Res = Res * STD + MEAN
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
Res = Res - IMF
|
|
121
|
+
|
|
122
|
+
if np.std(Res) < 1e-10 * np.std(S):
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
if is_increasing(Res):
|
|
126
|
+
Res = Res * STD + MEAN
|
|
127
|
+
break
|
|
128
|
+
|
|
129
|
+
return np.array(IMFs), np.array(Res)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: 3.11
|
|
3
|
+
|
|
4
|
+
Lib and Version:
|
|
5
|
+
colorama - 0.4.6
|
|
6
|
+
|
|
7
|
+
Only accessed by:
|
|
8
|
+
__init__.py, colorful_print.py
|
|
9
|
+
|
|
10
|
+
Modify:
|
|
11
|
+
2026.3.4
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import colorama as cm
|
|
15
|
+
|
|
16
|
+
__all__ = ["Color"]
|
|
17
|
+
|
|
18
|
+
Fore = cm.Fore
|
|
19
|
+
|
|
20
|
+
Color = \
|
|
21
|
+
{
|
|
22
|
+
"black": Fore.BLACK,
|
|
23
|
+
"red": Fore.RED,
|
|
24
|
+
"green": Fore.GREEN,
|
|
25
|
+
"yellow": Fore.YELLOW,
|
|
26
|
+
"blue": Fore.BLUE,
|
|
27
|
+
"magenta": Fore.MAGENTA,
|
|
28
|
+
"cyan": Fore.CYAN,
|
|
29
|
+
"white": Fore.WHITE,
|
|
30
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: 3.11
|
|
3
|
+
|
|
4
|
+
Lib and Version:
|
|
5
|
+
colorama - 0.4.6
|
|
6
|
+
|
|
7
|
+
Only accessed by:
|
|
8
|
+
All
|
|
9
|
+
|
|
10
|
+
Modify:
|
|
11
|
+
2026.3.4
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import colorama as cm
|
|
15
|
+
from typing import Literal, Any
|
|
16
|
+
|
|
17
|
+
__all__ = ["printc"]
|
|
18
|
+
|
|
19
|
+
Fore = cm.Fore
|
|
20
|
+
|
|
21
|
+
Color = \
|
|
22
|
+
{
|
|
23
|
+
"black": Fore.BLACK,
|
|
24
|
+
"red": Fore.RED,
|
|
25
|
+
"green": Fore.GREEN,
|
|
26
|
+
"yellow": Fore.YELLOW,
|
|
27
|
+
"blue": Fore.BLUE,
|
|
28
|
+
"magenta": Fore.MAGENTA,
|
|
29
|
+
"cyan": Fore.CYAN,
|
|
30
|
+
"white": Fore.WHITE,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def printc(*values: Any, color: Literal["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"] = None, sep: str = ' ', end: str = '\n') -> bool:
|
|
34
|
+
"""
|
|
35
|
+
(don't think much, just use as print)\n
|
|
36
|
+
A function that can make output be colorful.\n
|
|
37
|
+
If the function is successful, will default return True. If 'R' parameter is not change, when fail will Raise.(make 'R'=False, will return False only)\n
|
|
38
|
+
If you don't choose color or input a error parameter, default white.\n
|
|
39
|
+
kwargs: you can input 'c' to cover the "color" parameter, and use 'R' to choose whether raise the error, default is raise(R=True).\n
|
|
40
|
+
Reference Lib: colorama
|
|
41
|
+
|
|
42
|
+
:param values: Any, like values in print
|
|
43
|
+
:param color: color for output
|
|
44
|
+
:param sep: print parameter
|
|
45
|
+
:param end: print parameter
|
|
46
|
+
:return: bool: the result of print
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
if not hasattr(printc, '_initialized'):
|
|
50
|
+
cm.init(autoreset=True)
|
|
51
|
+
printc._initialized = True
|
|
52
|
+
|
|
53
|
+
# deal color
|
|
54
|
+
if color is None:
|
|
55
|
+
print(*values, sep=sep, end=end)
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
c = Color.get(color, Color["white"]) # check and appoint color
|
|
59
|
+
|
|
60
|
+
# for values' type
|
|
61
|
+
if len(values) == 1: # only one element been input
|
|
62
|
+
text: str = str(values[0])
|
|
63
|
+
|
|
64
|
+
text: str = sep.join(str(args) for args in values)
|
|
65
|
+
|
|
66
|
+
print(c + text, end=end)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
EMD-signal - 1.9.0
|
|
7
|
+
|
|
8
|
+
Only accessed by: (must)
|
|
9
|
+
Only __init__.py
|
|
10
|
+
|
|
11
|
+
Modify: (must)
|
|
12
|
+
2026.3.25
|
|
13
|
+
|
|
14
|
+
Description: (if None write None)
|
|
15
|
+
Realize the EEMD.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from PyEMD import EEMD
|
|
19
|
+
|
|
20
|
+
Origin_EEMD = EEMD
|
|
21
|
+
|
|
22
|
+
EEMD = EEMD()
|
|
23
|
+
def eemd(S):
|
|
24
|
+
return EEMD.eemd(S)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
numpy - 2.2.6
|
|
7
|
+
scipy - 1.15.3
|
|
8
|
+
matplotlib - 3.10.8
|
|
9
|
+
|
|
10
|
+
Only accessed by: (must)
|
|
11
|
+
Only __init__.py
|
|
12
|
+
|
|
13
|
+
Modify: (must)
|
|
14
|
+
2026.3.25
|
|
15
|
+
|
|
16
|
+
Description: (if None write None)
|
|
17
|
+
Realize the EFD.
|
|
18
|
+
Optimize the use of scipy.signal
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
from .COLOR import printc
|
|
23
|
+
|
|
24
|
+
def EFD(S, T=None, fs=None):
|
|
25
|
+
"""
|
|
26
|
+
:param S: Signal (1-dim)
|
|
27
|
+
:param T: Time axis (uniform spacing)
|
|
28
|
+
:return: IMFs: np.ndarray (2-dim) | Res: np.ndarray (1-dim)
|
|
29
|
+
"""
|
|
30
|
+
from scipy.signal import find_peaks
|
|
31
|
+
|
|
32
|
+
if not isinstance(S, np.ndarray):
|
|
33
|
+
S = np.array(S)
|
|
34
|
+
|
|
35
|
+
N = len(S)
|
|
36
|
+
|
|
37
|
+
if T is None:
|
|
38
|
+
if fs is not None:
|
|
39
|
+
dt = 1.0 / fs # smaple for time axis
|
|
40
|
+
T = np.arange(N) * dt
|
|
41
|
+
else:
|
|
42
|
+
T = np.arange(N) # default fs = 1
|
|
43
|
+
printc(f"Warn: T is None,default T = [0, 1, 2, ..., {N - 1}]", color="red")
|
|
44
|
+
|
|
45
|
+
if len(T) != N:
|
|
46
|
+
raise ValueError(f"len of T: ({len(T)}) doesn't match ({N})")
|
|
47
|
+
|
|
48
|
+
dt = np.diff(T)
|
|
49
|
+
if not np.allclose(dt, dt[0], rtol=1e-10, atol=1e-14):
|
|
50
|
+
raise ValueError("Time series should be uniform intervals")
|
|
51
|
+
|
|
52
|
+
# FFT
|
|
53
|
+
fft = np.fft.fft
|
|
54
|
+
F = fft(S)
|
|
55
|
+
freq = np.fft.fftfreq(len(T), d=T[1]-T[0])
|
|
56
|
+
|
|
57
|
+
f = np.abs(F)
|
|
58
|
+
idx = np.where(freq >= 0)[0]
|
|
59
|
+
freq_positive = freq[idx]
|
|
60
|
+
spectrum = f[idx]
|
|
61
|
+
|
|
62
|
+
# boundary
|
|
63
|
+
part_max, _ = find_peaks(spectrum)
|
|
64
|
+
part_min, _ = find_peaks(-spectrum)
|
|
65
|
+
boundary = np.concatenate([np.array([0]), part_min, part_max, np.array([len(freq_positive) - 1])])
|
|
66
|
+
boundary = np.unique(boundary)
|
|
67
|
+
boundary = np.sort(boundary)
|
|
68
|
+
|
|
69
|
+
IMFs = []
|
|
70
|
+
|
|
71
|
+
freq_set = []
|
|
72
|
+
spectrum_set = []
|
|
73
|
+
|
|
74
|
+
for b in range(1, len(boundary)):
|
|
75
|
+
down_bound = boundary[b - 1]
|
|
76
|
+
up_bound = boundary[b]
|
|
77
|
+
|
|
78
|
+
filter_mask = np.zeros(N)
|
|
79
|
+
filter_mask[N // 2 + down_bound : N // 2 + up_bound + 1] = 1
|
|
80
|
+
filter_mask[N // 2 - up_bound : N // 2 - down_bound + 1] = 1
|
|
81
|
+
|
|
82
|
+
if down_bound == 0:
|
|
83
|
+
filter_mask[N // 2 + 1 : N // 2 + up_bound + 1] = 1
|
|
84
|
+
|
|
85
|
+
F_band = F * filter_mask
|
|
86
|
+
|
|
87
|
+
IMF = np.fft.ifft(F_band)
|
|
88
|
+
IMFs.append(np.real(IMF))
|
|
89
|
+
|
|
90
|
+
sum_IMFs = np.sum(IMFs, axis=0)
|
|
91
|
+
Res: np.ndarray = np.array(S - sum_IMFs)
|
|
92
|
+
IMFs: np.ndarray = np.array(IMFs)
|
|
93
|
+
|
|
94
|
+
return IMFs, Res
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
EMD-signal - 1.9.0
|
|
7
|
+
numpy - 2.2.6
|
|
8
|
+
|
|
9
|
+
Only accessed by: (must)
|
|
10
|
+
Only __init__.py
|
|
11
|
+
|
|
12
|
+
Modify: (must)
|
|
13
|
+
2026.3.25
|
|
14
|
+
|
|
15
|
+
Description: (if None write None)
|
|
16
|
+
Realize the EMD
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from PyEMD import EMD
|
|
20
|
+
import numpy as np
|
|
21
|
+
from .COLOR.colorful_print import printc
|
|
22
|
+
from typing import Tuple
|
|
23
|
+
|
|
24
|
+
EMD_cls = EMD
|
|
25
|
+
|
|
26
|
+
def emd(S, T=None, spline_kind: str = "cubic", nbsym: int = 2, max_imf=-1, fs=None) -> Tuple[np.ndarray, np.ndarray]:
|
|
27
|
+
"""
|
|
28
|
+
:param S:
|
|
29
|
+
:param T:
|
|
30
|
+
:param spline_kind:
|
|
31
|
+
:param nbsym:
|
|
32
|
+
:param max_imf:
|
|
33
|
+
:param fs:
|
|
34
|
+
:return: IMFs (2-dim), Res: None
|
|
35
|
+
"""
|
|
36
|
+
if not isinstance(S, np.ndarray):
|
|
37
|
+
S = np.array(S)
|
|
38
|
+
|
|
39
|
+
N = len(S)
|
|
40
|
+
|
|
41
|
+
if T is None:
|
|
42
|
+
if fs is not None:
|
|
43
|
+
dt = 1.0 / fs # smaple for time axis
|
|
44
|
+
T = np.arange(N) * dt
|
|
45
|
+
else:
|
|
46
|
+
T = np.arange(N) # default fs = 1
|
|
47
|
+
printc(f"Warn: T is None,default T = [0, 1, 2, ..., {N - 1}]", color="red")
|
|
48
|
+
|
|
49
|
+
EMD_cls = EMD(spline_kind, nbsym)
|
|
50
|
+
|
|
51
|
+
IMFs = EMD_cls.emd(S, T, max_imf=max_imf)
|
|
52
|
+
|
|
53
|
+
return IMFs[:-1, :], IMFs[-1, :]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
ewtpy - 0.2
|
|
7
|
+
numpy - 2.2.6
|
|
8
|
+
|
|
9
|
+
Only accessed by: (must)
|
|
10
|
+
Only __init__.py
|
|
11
|
+
|
|
12
|
+
Modify: (must)
|
|
13
|
+
2026.3.25
|
|
14
|
+
|
|
15
|
+
Description: (if None write None)
|
|
16
|
+
Realize the EWT
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import Tuple, Union
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
def ewt \
|
|
23
|
+
(
|
|
24
|
+
S,
|
|
25
|
+
N: int = 5,
|
|
26
|
+
log: int = 0,
|
|
27
|
+
detect: str = "locmax",
|
|
28
|
+
completion: int = 0,
|
|
29
|
+
reg: str = 'average',
|
|
30
|
+
lengthFilter: int = 10,
|
|
31
|
+
sigmaFilter: int = 5,
|
|
32
|
+
need_mfd: bool = False,
|
|
33
|
+
need_boundaries: bool = False) -> Union[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]]:
|
|
34
|
+
"""
|
|
35
|
+
:param S: Signal
|
|
36
|
+
:param N:
|
|
37
|
+
:param log:
|
|
38
|
+
:param detect:
|
|
39
|
+
:param completion:
|
|
40
|
+
:param reg:
|
|
41
|
+
:param lengthFilter:
|
|
42
|
+
:param sigmaFilter:
|
|
43
|
+
:return: IMFs(N, len(S)) (2-dim)
|
|
44
|
+
"""
|
|
45
|
+
from ewtpy import EWT1D
|
|
46
|
+
|
|
47
|
+
ewt, mfb, boundaries = EWT1D(S, N, log, detect, completion, reg, lengthFilter, sigmaFilter)
|
|
48
|
+
ewt = ewt.T
|
|
49
|
+
mfb = mfb.T
|
|
50
|
+
|
|
51
|
+
if need_mfd and not need_boundaries:
|
|
52
|
+
return ewt[:-1, :], ewt[-1, :], mfb
|
|
53
|
+
|
|
54
|
+
if need_boundaries and not need_mfd:
|
|
55
|
+
return ewt[:-1, :], ewt[-1, :], boundaries
|
|
56
|
+
|
|
57
|
+
if need_mfd and need_boundaries:
|
|
58
|
+
return ewt[:-1, :], ewt[-1, :], mfb, boundaries
|
|
59
|
+
|
|
60
|
+
if not need_mfd and not need_boundaries:
|
|
61
|
+
return ewt[:-1, :], ewt[-1, :]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python version: (must)
|
|
3
|
+
3.10.11
|
|
4
|
+
|
|
5
|
+
Lib and Version: (if None write None)
|
|
6
|
+
scipy - 1.15.3
|
|
7
|
+
matplotlib - 3.10.8
|
|
8
|
+
numpy - 2.2.6
|
|
9
|
+
|
|
10
|
+
Only accessed by: (must)
|
|
11
|
+
Only __init__.py
|
|
12
|
+
|
|
13
|
+
Modify: (must)
|
|
14
|
+
2026.3.25
|
|
15
|
+
|
|
16
|
+
Description: (if None write None)
|
|
17
|
+
Realize the FMD
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
def initialize_filters(L, K):
|
|
23
|
+
from scipy.signal import firwin
|
|
24
|
+
|
|
25
|
+
filters = []
|
|
26
|
+
for k in range(1, K + 1):
|
|
27
|
+
cutoff = 0.5 / k
|
|
28
|
+
filter = firwin(L, cutoff, window='hann')
|
|
29
|
+
filters.append(filter)
|
|
30
|
+
return filters
|
|
31
|
+
|
|
32
|
+
def estimate_period(signal):
|
|
33
|
+
from scipy.signal import correlate, find_peaks
|
|
34
|
+
|
|
35
|
+
correlation = correlate(signal, signal, mode='full')
|
|
36
|
+
correlation = correlation[len(correlation) // 2:]
|
|
37
|
+
peaks, _ = find_peaks(correlation)
|
|
38
|
+
if len(peaks) > 1:
|
|
39
|
+
period = peaks[1]
|
|
40
|
+
else:
|
|
41
|
+
period = len(signal)
|
|
42
|
+
return period
|
|
43
|
+
|
|
44
|
+
def fmd(S, n=10, L=100, max_iters=10):
|
|
45
|
+
"""
|
|
46
|
+
:param S: Signal (2-dim)
|
|
47
|
+
:param n: store n IMFs
|
|
48
|
+
:param L:
|
|
49
|
+
:param max_iters:
|
|
50
|
+
:return:
|
|
51
|
+
"""
|
|
52
|
+
from scipy.signal import lfilter
|
|
53
|
+
|
|
54
|
+
if not isinstance(S, np.ndarray):
|
|
55
|
+
S = np.array(S)
|
|
56
|
+
|
|
57
|
+
K = min(10, max(5, n))
|
|
58
|
+
filters = initialize_filters(L, K)
|
|
59
|
+
modes = []
|
|
60
|
+
S = np.array(S) if isinstance(S, list) else S
|
|
61
|
+
for i in range(max_iters):
|
|
62
|
+
for filter in filters:
|
|
63
|
+
filtered_signal = lfilter(filter, 1.0, S)
|
|
64
|
+
period = estimate_period(filtered_signal)
|
|
65
|
+
modes.append(filtered_signal)
|
|
66
|
+
if len(modes) >= n:
|
|
67
|
+
break
|
|
68
|
+
|
|
69
|
+
return modes[:n]
|