rapidtide 3.0.11__py3-none-any.whl → 3.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.
- rapidtide/Colortables.py +492 -27
- rapidtide/OrthoImageItem.py +1049 -46
- rapidtide/RapidtideDataset.py +1533 -86
- rapidtide/_version.py +3 -3
- rapidtide/calccoherence.py +196 -29
- rapidtide/calcnullsimfunc.py +191 -40
- rapidtide/calcsimfunc.py +245 -42
- rapidtide/correlate.py +1210 -393
- rapidtide/data/examples/src/testLD +56 -0
- rapidtide/data/examples/src/testalign +1 -1
- rapidtide/data/examples/src/testdelayvar +0 -1
- rapidtide/data/examples/src/testfmri +19 -1
- rapidtide/data/examples/src/testglmfilt +5 -5
- rapidtide/data/examples/src/testhappy +25 -3
- rapidtide/data/examples/src/testppgproc +17 -0
- rapidtide/data/examples/src/testrolloff +11 -0
- rapidtide/data/models/model_cnn_pytorch/best_model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
- rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
- rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
- rapidtide/decorators.py +91 -0
- rapidtide/dlfilter.py +2225 -108
- rapidtide/dlfiltertorch.py +4843 -0
- rapidtide/externaltools.py +327 -12
- rapidtide/fMRIData_class.py +79 -40
- rapidtide/filter.py +1899 -810
- rapidtide/fit.py +2004 -574
- rapidtide/genericmultiproc.py +93 -18
- rapidtide/happy_supportfuncs.py +2044 -171
- rapidtide/helper_classes.py +584 -43
- rapidtide/io.py +2363 -370
- rapidtide/linfitfiltpass.py +341 -75
- rapidtide/makelaggedtcs.py +211 -20
- rapidtide/maskutil.py +423 -53
- rapidtide/miscmath.py +827 -121
- rapidtide/multiproc.py +210 -22
- rapidtide/patchmatch.py +234 -33
- rapidtide/peakeval.py +32 -30
- rapidtide/ppgproc.py +2203 -0
- rapidtide/qualitycheck.py +352 -39
- rapidtide/refinedelay.py +422 -57
- rapidtide/refineregressor.py +498 -184
- rapidtide/resample.py +671 -185
- rapidtide/scripts/applyppgproc.py +28 -0
- rapidtide/simFuncClasses.py +1052 -77
- rapidtide/simfuncfit.py +260 -46
- rapidtide/stats.py +540 -238
- rapidtide/tests/happycomp +9 -0
- rapidtide/tests/test_dlfiltertorch.py +627 -0
- rapidtide/tests/test_findmaxlag.py +24 -8
- rapidtide/tests/test_fullrunhappy_v1.py +0 -2
- rapidtide/tests/test_fullrunhappy_v2.py +0 -2
- rapidtide/tests/test_fullrunhappy_v3.py +1 -0
- rapidtide/tests/test_fullrunhappy_v4.py +2 -2
- rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
- rapidtide/tests/test_simroundtrip.py +8 -8
- rapidtide/tests/utils.py +9 -8
- rapidtide/tidepoolTemplate.py +142 -38
- rapidtide/tidepoolTemplate_alt.py +165 -44
- rapidtide/tidepoolTemplate_big.py +189 -52
- rapidtide/util.py +1217 -118
- rapidtide/voxelData.py +684 -37
- rapidtide/wiener.py +19 -12
- rapidtide/wiener2.py +113 -7
- rapidtide/wiener_doc.py +255 -0
- rapidtide/workflows/adjustoffset.py +105 -3
- rapidtide/workflows/aligntcs.py +85 -2
- rapidtide/workflows/applydlfilter.py +87 -10
- rapidtide/workflows/applyppgproc.py +522 -0
- rapidtide/workflows/atlasaverage.py +210 -47
- rapidtide/workflows/atlastool.py +100 -3
- rapidtide/workflows/calcSimFuncMap.py +294 -64
- rapidtide/workflows/calctexticc.py +201 -9
- rapidtide/workflows/ccorrica.py +97 -4
- rapidtide/workflows/cleanregressor.py +168 -29
- rapidtide/workflows/delayvar.py +163 -10
- rapidtide/workflows/diffrois.py +81 -3
- rapidtide/workflows/endtidalproc.py +144 -4
- rapidtide/workflows/fdica.py +195 -15
- rapidtide/workflows/filtnifti.py +70 -3
- rapidtide/workflows/filttc.py +74 -3
- rapidtide/workflows/fitSimFuncMap.py +206 -48
- rapidtide/workflows/fixtr.py +73 -3
- rapidtide/workflows/gmscalc.py +113 -3
- rapidtide/workflows/happy.py +801 -199
- rapidtide/workflows/happy2std.py +144 -12
- rapidtide/workflows/happy_parser.py +138 -9
- rapidtide/workflows/histnifti.py +118 -2
- rapidtide/workflows/histtc.py +84 -3
- rapidtide/workflows/linfitfilt.py +117 -4
- rapidtide/workflows/localflow.py +328 -28
- rapidtide/workflows/mergequality.py +79 -3
- rapidtide/workflows/niftidecomp.py +322 -18
- rapidtide/workflows/niftistats.py +174 -4
- rapidtide/workflows/pairproc.py +88 -2
- rapidtide/workflows/pairwisemergenifti.py +85 -2
- rapidtide/workflows/parser_funcs.py +1421 -40
- rapidtide/workflows/physiofreq.py +137 -11
- rapidtide/workflows/pixelcomp.py +208 -5
- rapidtide/workflows/plethquality.py +103 -21
- rapidtide/workflows/polyfitim.py +151 -11
- rapidtide/workflows/proj2flow.py +75 -2
- rapidtide/workflows/rankimage.py +111 -4
- rapidtide/workflows/rapidtide.py +272 -15
- rapidtide/workflows/rapidtide2std.py +98 -2
- rapidtide/workflows/rapidtide_parser.py +109 -9
- rapidtide/workflows/refineDelayMap.py +143 -33
- rapidtide/workflows/refineRegressor.py +682 -93
- rapidtide/workflows/regressfrommaps.py +152 -31
- rapidtide/workflows/resamplenifti.py +85 -3
- rapidtide/workflows/resampletc.py +91 -3
- rapidtide/workflows/retrolagtcs.py +98 -6
- rapidtide/workflows/retroregress.py +165 -9
- rapidtide/workflows/roisummarize.py +173 -5
- rapidtide/workflows/runqualitycheck.py +71 -3
- rapidtide/workflows/showarbcorr.py +147 -4
- rapidtide/workflows/showhist.py +86 -2
- rapidtide/workflows/showstxcorr.py +160 -3
- rapidtide/workflows/showtc.py +159 -3
- rapidtide/workflows/showxcorrx.py +184 -4
- rapidtide/workflows/showxy.py +185 -15
- rapidtide/workflows/simdata.py +262 -36
- rapidtide/workflows/spatialfit.py +77 -2
- rapidtide/workflows/spatialmi.py +251 -27
- rapidtide/workflows/spectrogram.py +305 -32
- rapidtide/workflows/synthASL.py +154 -3
- rapidtide/workflows/tcfrom2col.py +76 -2
- rapidtide/workflows/tcfrom3col.py +74 -2
- rapidtide/workflows/tidepool.py +2969 -130
- rapidtide/workflows/utils.py +19 -14
- rapidtide/workflows/utils_doc.py +293 -0
- rapidtide/workflows/variabilityizer.py +116 -3
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/METADATA +3 -2
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/RECORD +139 -122
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/entry_points.txt +1 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/WHEEL +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/licenses/LICENSE +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/top_level.txt +0 -0
rapidtide/miscmath.py
CHANGED
|
@@ -17,10 +17,14 @@
|
|
|
17
17
|
#
|
|
18
18
|
#
|
|
19
19
|
import warnings
|
|
20
|
+
from typing import Callable, Optional, Tuple, Union
|
|
20
21
|
|
|
21
22
|
import matplotlib.pyplot as plt
|
|
22
23
|
import numpy as np
|
|
23
24
|
from numpy.polynomial import Polynomial
|
|
25
|
+
from numpy.typing import NDArray
|
|
26
|
+
|
|
27
|
+
from rapidtide.decorators import conditionaljit, conditionaljit2
|
|
24
28
|
|
|
25
29
|
with warnings.catch_warnings():
|
|
26
30
|
warnings.simplefilter("ignore")
|
|
@@ -44,70 +48,87 @@ if pyfftwpresent:
|
|
|
44
48
|
# ---------------------------------------- Global constants -------------------------------------------
|
|
45
49
|
defaultbutterorder = 6
|
|
46
50
|
MAXLINES = 10000000
|
|
47
|
-
donotbeaggressive = True
|
|
48
|
-
|
|
49
|
-
# ----------------------------------------- Conditional imports ---------------------------------------
|
|
50
|
-
try:
|
|
51
|
-
from numba import jit
|
|
52
|
-
except ImportError:
|
|
53
|
-
donotusenumba = True
|
|
54
|
-
else:
|
|
55
|
-
donotusenumba = False
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# ----------------------------------------- Conditional jit handling ----------------------------------
|
|
59
|
-
def conditionaljit():
|
|
60
|
-
def resdec(f):
|
|
61
|
-
if donotusenumba:
|
|
62
|
-
return f
|
|
63
|
-
return jit(f, nopython=True)
|
|
64
|
-
|
|
65
|
-
return resdec
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def conditionaljit2():
|
|
69
|
-
def resdec(f):
|
|
70
|
-
if donotusenumba or donotbeaggressive:
|
|
71
|
-
return f
|
|
72
|
-
return jit(f, nopython=True)
|
|
73
|
-
|
|
74
|
-
return resdec
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def disablenumba():
|
|
78
|
-
global donotusenumba
|
|
79
|
-
donotusenumba = True
|
|
80
51
|
|
|
81
52
|
|
|
82
53
|
# --------------------------- Spectral analysis functions ---------------------------------------
|
|
83
|
-
def phase(mcv):
|
|
84
|
-
|
|
54
|
+
def phase(mcv: NDArray) -> NDArray:
|
|
55
|
+
"""
|
|
56
|
+
Return phase of complex numbers.
|
|
85
57
|
|
|
86
58
|
Parameters
|
|
87
59
|
----------
|
|
88
|
-
mcv :
|
|
89
|
-
A complex vector
|
|
60
|
+
mcv : NDArray
|
|
61
|
+
A complex vector. The input array can be of any shape, but must contain
|
|
62
|
+
complex numbers.
|
|
90
63
|
|
|
91
64
|
Returns
|
|
92
65
|
-------
|
|
93
|
-
|
|
94
|
-
The phase angle of the numbers, in radians
|
|
95
|
-
|
|
66
|
+
NDArray
|
|
67
|
+
The phase angle of the numbers, in radians. The return array has the same
|
|
68
|
+
shape as the input array. Phase angles are in the range [-π, π].
|
|
69
|
+
|
|
70
|
+
Notes
|
|
71
|
+
-----
|
|
72
|
+
This function computes the element-wise phase angle of complex numbers using
|
|
73
|
+
the arctan2 function, which correctly handles the quadrant of the angle.
|
|
74
|
+
The phase is computed as atan2(imaginary_part, real_part).
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
>>> import numpy as np
|
|
79
|
+
>>> z = np.array([1+1j, -1+1j, -1-1j, 1-1j])
|
|
80
|
+
>>> phase(z)
|
|
81
|
+
array([ 0.78539816, 2.35619449, -2.35619449, -0.78539816])
|
|
82
|
+
|
|
83
|
+
>>> z = np.array([[1+1j, -1+1j], [-1-1j, 1-1j]])
|
|
84
|
+
>>> phase(z)
|
|
85
|
+
array([[ 0.78539816, 2.35619449],
|
|
86
|
+
[-2.35619449, -0.78539816]])
|
|
96
87
|
"""
|
|
97
88
|
return np.arctan2(mcv.imag, mcv.real)
|
|
98
89
|
|
|
99
90
|
|
|
100
|
-
def polarfft(invec, samplerate):
|
|
91
|
+
def polarfft(invec: NDArray, samplerate: float) -> Tuple[NDArray, NDArray, NDArray]:
|
|
101
92
|
"""
|
|
93
|
+
Compute polar FFT representation of input signal.
|
|
94
|
+
|
|
95
|
+
This function applies a Hamming window to the input signal, computes the FFT,
|
|
96
|
+
and returns the frequency spectrum, magnitude spectrum, and phase spectrum.
|
|
102
97
|
|
|
103
98
|
Parameters
|
|
104
99
|
----------
|
|
105
|
-
invec
|
|
106
|
-
|
|
100
|
+
invec : ndarray
|
|
101
|
+
Input signal vector to be transformed
|
|
102
|
+
samplerate : float
|
|
103
|
+
Sampling rate of the input signal in Hz
|
|
107
104
|
|
|
108
105
|
Returns
|
|
109
106
|
-------
|
|
110
|
-
|
|
107
|
+
tuple of ndarray
|
|
108
|
+
A tuple containing:
|
|
109
|
+
- freqs : ndarray
|
|
110
|
+
Frequency values corresponding to the spectrum
|
|
111
|
+
- magspec : ndarray
|
|
112
|
+
Magnitude spectrum of the input signal
|
|
113
|
+
- phspec : ndarray
|
|
114
|
+
Phase spectrum of the input signal
|
|
115
|
+
|
|
116
|
+
Notes
|
|
117
|
+
-----
|
|
118
|
+
- If the input vector length is odd, the last element is removed to make it even
|
|
119
|
+
- A Hamming window is applied before FFT computation
|
|
120
|
+
- Only the first half of the FFT result is returned (positive frequencies)
|
|
121
|
+
- The maximum frequency is half the sampling rate (Nyquist frequency)
|
|
122
|
+
|
|
123
|
+
Examples
|
|
124
|
+
--------
|
|
125
|
+
>>> import numpy as np
|
|
126
|
+
>>> from scipy import fftpack
|
|
127
|
+
>>> # Create a test signal
|
|
128
|
+
>>> t = np.linspace(0, 1, 1000)
|
|
129
|
+
>>> signal = np.sin(2 * np.pi * 50 * t) + 0.5 * np.sin(2 * np.pi * 120 * t)
|
|
130
|
+
>>> freqs, mags, phs = polarfft(signal, 1000.0)
|
|
131
|
+
>>> print(f"Frequency range: {freqs[0]} to {freqs[-1]} Hz")
|
|
111
132
|
"""
|
|
112
133
|
if np.shape(invec)[0] % 2 == 1:
|
|
113
134
|
thevec = invec[:-1]
|
|
@@ -123,20 +144,84 @@ def polarfft(invec, samplerate):
|
|
|
123
144
|
return freqs, magspec, phspec
|
|
124
145
|
|
|
125
146
|
|
|
126
|
-
def complex_cepstrum(x):
|
|
147
|
+
def complex_cepstrum(x: NDArray) -> Tuple[NDArray, NDArray]:
|
|
127
148
|
"""
|
|
149
|
+
Compute the complex cepstrum of a real sequence.
|
|
150
|
+
|
|
151
|
+
The complex cepstrum is the inverse Fourier transform of the logarithm of the
|
|
152
|
+
complex spectrum. It is commonly used in signal processing for analyzing
|
|
153
|
+
periodicities and harmonics in signals.
|
|
128
154
|
|
|
129
155
|
Parameters
|
|
130
156
|
----------
|
|
131
|
-
x
|
|
157
|
+
x : ndarray
|
|
158
|
+
Real sequence to compute complex cepstrum of.
|
|
132
159
|
|
|
133
160
|
Returns
|
|
134
161
|
-------
|
|
135
|
-
|
|
162
|
+
ceps : ndarray
|
|
163
|
+
Complex cepstrum of the input sequence.
|
|
164
|
+
ndelay : ndarray
|
|
165
|
+
The number of samples of circular delay added to the input sequence.
|
|
166
|
+
|
|
167
|
+
Notes
|
|
168
|
+
-----
|
|
169
|
+
This implementation follows the approach described in [1]_ and handles
|
|
170
|
+
the unwrapping of the phase to avoid discontinuities in the cepstral
|
|
171
|
+
domain.
|
|
172
|
+
|
|
173
|
+
References
|
|
174
|
+
----------
|
|
175
|
+
.. [1] M. R. Schroeder, "Periodicity and cepstral analysis," IEEE Transactions
|
|
176
|
+
on Audio and Electroacoustics, vol. 19, no. 3, pp. 233-238, 1971.
|
|
177
|
+
|
|
178
|
+
Examples
|
|
179
|
+
--------
|
|
180
|
+
>>> import numpy as np
|
|
181
|
+
>>> x = np.array([1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0])
|
|
182
|
+
>>> ceps, ndelay = complex_cepstrum(x)
|
|
183
|
+
>>> print(ceps)
|
|
184
|
+
>>> print(ndelay)
|
|
136
185
|
"""
|
|
137
186
|
|
|
138
187
|
# adapted from https://github.com/python-acoustics/python-acoustics/blob/master/acoustics/cepstrum.py
|
|
139
|
-
def _unwrap(phase):
|
|
188
|
+
def _unwrap(phase: NDArray) -> Tuple[NDArray, NDArray]:
|
|
189
|
+
"""
|
|
190
|
+
Unwrap phase and compute delay correction.
|
|
191
|
+
|
|
192
|
+
This function unwraps a phase array to remove discontinuities and computes
|
|
193
|
+
the necessary delay correction to align the unwrapped phase at the center
|
|
194
|
+
of the array.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
phase : NDArray
|
|
199
|
+
Input phase array with shape (..., samples) where the last dimension
|
|
200
|
+
represents the phase samples to be unwrapped.
|
|
201
|
+
|
|
202
|
+
Returns
|
|
203
|
+
-------
|
|
204
|
+
unwrapped : NDArray
|
|
205
|
+
Unwrapped phase array with the same shape as input phase.
|
|
206
|
+
ndelay : NDArray
|
|
207
|
+
Delay correction array with shape (...,) containing the number of
|
|
208
|
+
π phase jumps to correct for each sample in the batch.
|
|
209
|
+
|
|
210
|
+
Notes
|
|
211
|
+
-----
|
|
212
|
+
The unwrapping process removes discontinuities by adding multiples of 2π
|
|
213
|
+
to eliminate phase jumps greater than π. The delay correction is computed
|
|
214
|
+
by finding the phase at the center sample and adjusting the entire array
|
|
215
|
+
to align this reference point.
|
|
216
|
+
|
|
217
|
+
Examples
|
|
218
|
+
--------
|
|
219
|
+
>>> import numpy as np
|
|
220
|
+
>>> phase = np.array([[0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi]])
|
|
221
|
+
>>> unwrapped, ndelay = _unwrap(phase)
|
|
222
|
+
>>> print(unwrapped)
|
|
223
|
+
>>> print(ndelay)
|
|
224
|
+
"""
|
|
140
225
|
samples = phase.shape[-1]
|
|
141
226
|
unwrapped = np.unwrap(phase)
|
|
142
227
|
center = (samples + 1) // 2
|
|
@@ -154,34 +239,82 @@ def complex_cepstrum(x):
|
|
|
154
239
|
return ceps, ndelay
|
|
155
240
|
|
|
156
241
|
|
|
157
|
-
def real_cepstrum(x):
|
|
242
|
+
def real_cepstrum(x: NDArray) -> NDArray:
|
|
158
243
|
"""
|
|
244
|
+
Compute the real cepstrum of a signal.
|
|
245
|
+
|
|
246
|
+
The cepstrum is the inverse Fourier transform of the logarithm of the magnitude
|
|
247
|
+
of the Fourier transform of a signal. It is commonly used in speech processing
|
|
248
|
+
and audio analysis to analyze the periodicity and structure of signals.
|
|
159
249
|
|
|
160
250
|
Parameters
|
|
161
251
|
----------
|
|
162
|
-
x
|
|
252
|
+
x : ndarray
|
|
253
|
+
Input signal array of real numbers.
|
|
163
254
|
|
|
164
255
|
Returns
|
|
165
256
|
-------
|
|
166
|
-
|
|
257
|
+
ndarray
|
|
258
|
+
Real cepstrum of the input signal. The result has the same shape as the input.
|
|
259
|
+
|
|
260
|
+
Notes
|
|
261
|
+
-----
|
|
262
|
+
This implementation uses the FFT-based approach:
|
|
263
|
+
1. Compute the Fourier transform of the input signal
|
|
264
|
+
2. Take the absolute value and logarithm
|
|
265
|
+
3. Apply inverse FFT and take the real part
|
|
266
|
+
|
|
267
|
+
The cepstrum is useful for identifying periodic structures in signals and
|
|
268
|
+
is particularly important in speech analysis for determining pitch and
|
|
269
|
+
formant frequencies.
|
|
270
|
+
|
|
271
|
+
Examples
|
|
272
|
+
--------
|
|
273
|
+
>>> import numpy as np
|
|
274
|
+
>>> x = np.array([1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0])
|
|
275
|
+
>>> cepstrum = real_cepstrum(x)
|
|
276
|
+
>>> print(cepstrum)
|
|
277
|
+
[ 2.53444207 0.74508512 -0.23302092 -0.34635144 -0.23302092
|
|
278
|
+
0.74508512 2.53444207]
|
|
167
279
|
"""
|
|
168
280
|
# adapted from https://github.com/python-acoustics/python-acoustics/blob/master/acoustics/cepstrum.py
|
|
169
281
|
return fftpack.ifft(np.log(np.abs(fftpack.fft(x)))).real
|
|
170
282
|
|
|
171
283
|
|
|
172
284
|
# --------------------------- miscellaneous math functions -------------------------------------------------
|
|
173
|
-
def thederiv(y):
|
|
285
|
+
def thederiv(y: NDArray) -> NDArray:
|
|
174
286
|
"""
|
|
287
|
+
Compute the first derivative of an array using finite differences.
|
|
288
|
+
|
|
289
|
+
This function calculates the derivative of an array `y` using a central difference
|
|
290
|
+
scheme for interior points and forward/backward differences for the first and
|
|
291
|
+
last points respectively.
|
|
175
292
|
|
|
176
293
|
Parameters
|
|
177
294
|
----------
|
|
178
|
-
y
|
|
295
|
+
y : ndarray
|
|
296
|
+
Input array of values to differentiate. Shape (n,) where n is the number of points.
|
|
179
297
|
|
|
180
298
|
Returns
|
|
181
299
|
-------
|
|
182
|
-
|
|
300
|
+
ndarray
|
|
301
|
+
Array of same shape as `y` containing the computed derivative values.
|
|
302
|
+
|
|
303
|
+
Notes
|
|
304
|
+
-----
|
|
305
|
+
The derivative is computed using the following scheme:
|
|
306
|
+
- First point: dyc[0] = (y[0] - y[1]) / 2.0
|
|
307
|
+
- Interior points: dyc[i] = (y[i+1] - y[i-1]) / 2.0
|
|
308
|
+
- Last point: dyc[-1] = (y[-1] - y[-2]) / 2.0
|
|
309
|
+
|
|
310
|
+
Examples
|
|
311
|
+
--------
|
|
312
|
+
>>> import numpy as np
|
|
313
|
+
>>> y = np.array([1, 2, 4, 7, 11])
|
|
314
|
+
>>> thederiv(y)
|
|
315
|
+
array([-0.5, 1. , 2. , 3. , 4.5])
|
|
183
316
|
"""
|
|
184
|
-
dyc =
|
|
317
|
+
dyc = np.zeros_like(y)
|
|
185
318
|
dyc[0] = (y[0] - y[1]) / 2.0
|
|
186
319
|
for i in range(1, len(y) - 1):
|
|
187
320
|
dyc[i] = (y[i + 1] - y[i - 1]) / 2.0
|
|
@@ -189,16 +322,38 @@ def thederiv(y):
|
|
|
189
322
|
return dyc
|
|
190
323
|
|
|
191
324
|
|
|
192
|
-
def primes(n):
|
|
325
|
+
def primes(n: int) -> list:
|
|
193
326
|
"""
|
|
327
|
+
Compute the prime factorization of a positive integer.
|
|
328
|
+
|
|
329
|
+
Returns the prime factors of n in ascending order, including repeated factors.
|
|
194
330
|
|
|
195
331
|
Parameters
|
|
196
332
|
----------
|
|
197
|
-
n
|
|
333
|
+
n : int
|
|
334
|
+
A positive integer to factorize. Must be greater than 0.
|
|
198
335
|
|
|
199
336
|
Returns
|
|
200
337
|
-------
|
|
338
|
+
list of int
|
|
339
|
+
A list of prime factors of n in ascending order. If n is 1, returns an empty list.
|
|
340
|
+
|
|
341
|
+
Notes
|
|
342
|
+
-----
|
|
343
|
+
This implementation uses trial division starting from 2, incrementing by 1
|
|
344
|
+
until the square root of n. It is based on a StackOverflow answer and
|
|
345
|
+
efficiently handles repeated prime factors.
|
|
346
|
+
|
|
347
|
+
Examples
|
|
348
|
+
--------
|
|
349
|
+
>>> primes(12)
|
|
350
|
+
[2, 2, 3]
|
|
351
|
+
|
|
352
|
+
>>> primes(17)
|
|
353
|
+
[17]
|
|
201
354
|
|
|
355
|
+
>>> primes(1)
|
|
356
|
+
[]
|
|
202
357
|
"""
|
|
203
358
|
# found on stackoverflow: https://stackoverflow.com/questions/16996217/prime-factorization-list
|
|
204
359
|
primfac = []
|
|
@@ -213,31 +368,77 @@ def primes(n):
|
|
|
213
368
|
return primfac
|
|
214
369
|
|
|
215
370
|
|
|
216
|
-
def largestfac(n):
|
|
371
|
+
def largestfac(n: int) -> int:
|
|
217
372
|
"""
|
|
373
|
+
Return the largest prime factor of n.
|
|
218
374
|
|
|
219
375
|
Parameters
|
|
220
376
|
----------
|
|
221
|
-
n
|
|
377
|
+
n : int
|
|
378
|
+
The integer to find the largest prime factor for. Must be a positive integer.
|
|
222
379
|
|
|
223
380
|
Returns
|
|
224
381
|
-------
|
|
225
|
-
|
|
382
|
+
int
|
|
383
|
+
The largest prime factor of n.
|
|
384
|
+
|
|
385
|
+
Notes
|
|
386
|
+
-----
|
|
387
|
+
This function relies on a `primes(n)` function that returns all prime numbers up to n.
|
|
388
|
+
The largest prime factor is obtained by taking the last element from this list.
|
|
389
|
+
|
|
390
|
+
Examples
|
|
391
|
+
--------
|
|
392
|
+
>>> largestfac(13)
|
|
393
|
+
13
|
|
394
|
+
>>> largestfac(315)
|
|
395
|
+
7
|
|
226
396
|
"""
|
|
227
397
|
return primes(n)[-1]
|
|
228
398
|
|
|
229
399
|
|
|
230
400
|
# --------------------------- Normalization functions -------------------------------------------------
|
|
231
|
-
def normalize(vector, method="stddev"):
|
|
401
|
+
def normalize(vector: NDArray, method: str = "stddev") -> NDArray:
|
|
232
402
|
"""
|
|
403
|
+
Normalize a vector using the specified normalization method.
|
|
233
404
|
|
|
234
405
|
Parameters
|
|
235
406
|
----------
|
|
236
|
-
vector
|
|
407
|
+
vector : NDArray
|
|
408
|
+
Input vector to be normalized.
|
|
409
|
+
method : str, default="stddev"
|
|
410
|
+
Normalization method to apply. Options are:
|
|
411
|
+
- "None": Subtract mean from vector
|
|
412
|
+
- "percent": Apply percentage normalization
|
|
413
|
+
- "variance": Apply variance normalization
|
|
414
|
+
- "stddev" or "z": Apply standard deviation normalization (Z-score)
|
|
415
|
+
- "p2p": Apply peak-to-peak normalization
|
|
416
|
+
- "mad": Apply median absolute deviation normalization
|
|
237
417
|
|
|
238
418
|
Returns
|
|
239
419
|
-------
|
|
240
|
-
|
|
420
|
+
NDArray
|
|
421
|
+
Normalized vector according to the specified method.
|
|
422
|
+
|
|
423
|
+
Raises
|
|
424
|
+
------
|
|
425
|
+
ValueError
|
|
426
|
+
If an invalid normalization method is specified.
|
|
427
|
+
|
|
428
|
+
Notes
|
|
429
|
+
-----
|
|
430
|
+
This function provides multiple normalization techniques for preprocessing
|
|
431
|
+
data. The default "stddev" method (also available as "z") performs Z-score
|
|
432
|
+
normalization, which centers the data around zero with unit variance.
|
|
433
|
+
|
|
434
|
+
Examples
|
|
435
|
+
--------
|
|
436
|
+
>>> import numpy as np
|
|
437
|
+
>>> vector = np.array([1, 2, 3, 4, 5])
|
|
438
|
+
>>> normalize(vector, "stddev")
|
|
439
|
+
array([-1.41421356, -0.70710678, 0. , 0.70710678, 1.41421356])
|
|
440
|
+
>>> normalize(vector, "None")
|
|
441
|
+
array([-2., -1., 0., 1., 2.])
|
|
241
442
|
"""
|
|
242
443
|
if method == "None":
|
|
243
444
|
return vector - np.mean(vector)
|
|
@@ -255,21 +456,41 @@ def normalize(vector, method="stddev"):
|
|
|
255
456
|
raise ValueError("Illegal normalization type")
|
|
256
457
|
|
|
257
458
|
|
|
258
|
-
def znormalize(vector):
|
|
459
|
+
def znormalize(vector: NDArray) -> NDArray:
|
|
460
|
+
return stdnormalize(vector)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def removeoutliers(
|
|
464
|
+
vector: NDArray, zerobad: bool = True, outlierfac: float = 3.0
|
|
465
|
+
) -> Tuple[NDArray, float, float]:
|
|
259
466
|
"""
|
|
467
|
+
Normalize a vector using standard normalization (z-score normalization).
|
|
468
|
+
|
|
469
|
+
Standard normalization transforms the vector by subtracting the mean and
|
|
470
|
+
dividing by the standard deviation, resulting in a vector with mean=0 and std=1.
|
|
260
471
|
|
|
261
472
|
Parameters
|
|
262
473
|
----------
|
|
263
|
-
vector
|
|
474
|
+
vector : array-like
|
|
475
|
+
Input vector to be normalized. Should be a 1D array-like object.
|
|
264
476
|
|
|
265
477
|
Returns
|
|
266
478
|
-------
|
|
267
|
-
|
|
479
|
+
ndarray
|
|
480
|
+
Normalized vector with mean=0 and standard deviation=1.
|
|
481
|
+
|
|
482
|
+
Notes
|
|
483
|
+
-----
|
|
484
|
+
This function is equivalent to calling `stdnormalize(vector)` and performs
|
|
485
|
+
the standard z-score normalization: (x - mean) / std.
|
|
486
|
+
|
|
487
|
+
Examples
|
|
488
|
+
--------
|
|
489
|
+
>>> import numpy as np
|
|
490
|
+
>>> vector = np.array([1, 2, 3, 4, 5])
|
|
491
|
+
>>> znormalize(vector)
|
|
492
|
+
array([-1.41421356, -0.70710678, 0. , 0.70710678, 1.41421356])
|
|
268
493
|
"""
|
|
269
|
-
return stdnormalize(vector)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
def removeoutliers(vector, zerobad=True, outlierfac=3.0):
|
|
273
494
|
themedian = np.median(vector)
|
|
274
495
|
sigmad = mad(vector - themedian).astype(np.float64)
|
|
275
496
|
if zerobad:
|
|
@@ -281,16 +502,47 @@ def removeoutliers(vector, zerobad=True, outlierfac=3.0):
|
|
|
281
502
|
return cleaneddata, themedian, sigmad
|
|
282
503
|
|
|
283
504
|
|
|
284
|
-
def madnormalize(
|
|
505
|
+
def madnormalize(
|
|
506
|
+
vector: NDArray, returnnormfac: bool = False
|
|
507
|
+
) -> Union[NDArray, Tuple[NDArray, float]]:
|
|
285
508
|
"""
|
|
509
|
+
Normalize a vector using the median absolute deviation (MAD).
|
|
510
|
+
|
|
511
|
+
This function normalizes a vector by subtracting the median and dividing by the
|
|
512
|
+
median absolute deviation. The MAD is computed as the median of the absolute
|
|
513
|
+
deviations from the median, scaled by a constant factor (1.4826) to make it
|
|
514
|
+
consistent with the standard deviation for normally distributed data.
|
|
286
515
|
|
|
287
516
|
Parameters
|
|
288
517
|
----------
|
|
289
|
-
vector
|
|
518
|
+
vector : array_like
|
|
519
|
+
Input vector to be normalized.
|
|
520
|
+
returnnormfac : bool, optional
|
|
521
|
+
If True, also return the normalization factor (MAD). Default is False.
|
|
290
522
|
|
|
291
523
|
Returns
|
|
292
524
|
-------
|
|
293
|
-
|
|
525
|
+
ndarray or tuple
|
|
526
|
+
If `returnnormfac` is False, returns the normalized vector.
|
|
527
|
+
If `returnnormfac` is True, returns a tuple of (normalized_vector, mad).
|
|
528
|
+
|
|
529
|
+
Notes
|
|
530
|
+
-----
|
|
531
|
+
The normalization is performed as: (vector - median(vector)) / MAD
|
|
532
|
+
where MAD is the median absolute deviation. If MAD is zero or negative,
|
|
533
|
+
the original vector is returned without normalization.
|
|
534
|
+
|
|
535
|
+
Examples
|
|
536
|
+
--------
|
|
537
|
+
>>> import numpy as np
|
|
538
|
+
>>> vector = np.array([1, 2, 3, 4, 5])
|
|
539
|
+
>>> normalized = madnormalize(vector)
|
|
540
|
+
>>> print(normalized)
|
|
541
|
+
[-1.4826 -0.7413 0. 0.7413 1.4826]
|
|
542
|
+
|
|
543
|
+
>>> normalized, mad_val = madnormalize(vector, returnnormfac=True)
|
|
544
|
+
>>> print(f"Normalized: {normalized}")
|
|
545
|
+
>>> print(f"MAD: {mad_val}")
|
|
294
546
|
"""
|
|
295
547
|
demedianed = vector - np.median(vector)
|
|
296
548
|
sigmad = mad(demedianed).astype(np.float64)
|
|
@@ -307,16 +559,37 @@ def madnormalize(vector, returnnormfac=False):
|
|
|
307
559
|
|
|
308
560
|
|
|
309
561
|
@conditionaljit()
|
|
310
|
-
def stdnormalize(vector):
|
|
562
|
+
def stdnormalize(vector: NDArray) -> NDArray:
|
|
311
563
|
"""
|
|
564
|
+
Standardize a vector by removing mean and scaling by standard deviation.
|
|
312
565
|
|
|
313
566
|
Parameters
|
|
314
567
|
----------
|
|
315
|
-
vector
|
|
568
|
+
vector : numpy.ndarray
|
|
569
|
+
Input vector to be standardized.
|
|
316
570
|
|
|
317
571
|
Returns
|
|
318
572
|
-------
|
|
319
|
-
|
|
573
|
+
numpy.ndarray
|
|
574
|
+
Standardized vector with zero mean and unit variance. If the input vector
|
|
575
|
+
has zero standard deviation, the demeaned vector is returned unchanged.
|
|
576
|
+
|
|
577
|
+
Notes
|
|
578
|
+
-----
|
|
579
|
+
This function performs standardization (z-score normalization) by:
|
|
580
|
+
1. Removing the mean from each element (demeaning)
|
|
581
|
+
2. Dividing by the standard deviation (if non-zero)
|
|
582
|
+
|
|
583
|
+
Examples
|
|
584
|
+
--------
|
|
585
|
+
>>> import numpy as np
|
|
586
|
+
>>> x = np.array([1, 2, 3, 4, 5])
|
|
587
|
+
>>> stdnormalize(x)
|
|
588
|
+
array([-1.41421356, -0.70710678, 0. , 0.70710678, 1.41421356])
|
|
589
|
+
|
|
590
|
+
>>> y = np.array([5, 5, 5, 5])
|
|
591
|
+
>>> stdnormalize(y)
|
|
592
|
+
array([0., 0., 0., 0.])
|
|
320
593
|
"""
|
|
321
594
|
demeaned = vector - np.mean(vector)
|
|
322
595
|
sigstd = np.std(demeaned)
|
|
@@ -326,16 +599,42 @@ def stdnormalize(vector):
|
|
|
326
599
|
return demeaned
|
|
327
600
|
|
|
328
601
|
|
|
329
|
-
def varnormalize(vector):
|
|
602
|
+
def varnormalize(vector: NDArray) -> NDArray:
|
|
330
603
|
"""
|
|
604
|
+
Normalize a vector by subtracting the mean and dividing by variance.
|
|
605
|
+
|
|
606
|
+
This function performs variance normalization on the input vector. It first
|
|
607
|
+
demeanes the vector by subtracting its mean, then divides by the variance
|
|
608
|
+
if it's greater than zero. If the variance is zero (constant vector), the
|
|
609
|
+
demeaned vector is returned unchanged.
|
|
331
610
|
|
|
332
611
|
Parameters
|
|
333
612
|
----------
|
|
334
|
-
vector
|
|
613
|
+
vector : ndarray
|
|
614
|
+
Input vector to be normalized. Should be a numpy array of numeric values.
|
|
335
615
|
|
|
336
616
|
Returns
|
|
337
617
|
-------
|
|
338
|
-
|
|
618
|
+
ndarray
|
|
619
|
+
Normalized vector with mean zero and variance one (when input has non-zero variance).
|
|
620
|
+
If input vector has zero variance, returns the demeaned vector.
|
|
621
|
+
|
|
622
|
+
Notes
|
|
623
|
+
-----
|
|
624
|
+
This normalization is similar to standardization but uses variance instead of
|
|
625
|
+
standard deviation for the normalization factor. The function handles edge cases
|
|
626
|
+
where variance is zero by returning the demeaned vector without division.
|
|
627
|
+
|
|
628
|
+
Examples
|
|
629
|
+
--------
|
|
630
|
+
>>> import numpy as np
|
|
631
|
+
>>> vec = np.array([1, 2, 3, 4, 5])
|
|
632
|
+
>>> varnormalize(vec)
|
|
633
|
+
array([-2., -1., 0., 1., 2.])
|
|
634
|
+
|
|
635
|
+
>>> constant_vec = np.array([5, 5, 5, 5])
|
|
636
|
+
>>> varnormalize(constant_vec)
|
|
637
|
+
array([0., 0., 0., 0.])
|
|
339
638
|
"""
|
|
340
639
|
demeaned = vector - np.mean(vector)
|
|
341
640
|
sigvar = np.var(demeaned)
|
|
@@ -345,16 +644,41 @@ def varnormalize(vector):
|
|
|
345
644
|
return demeaned
|
|
346
645
|
|
|
347
646
|
|
|
348
|
-
def pcnormalize(vector):
|
|
647
|
+
def pcnormalize(vector: NDArray) -> NDArray:
|
|
349
648
|
"""
|
|
649
|
+
Normalize a vector using percentage change normalization.
|
|
650
|
+
|
|
651
|
+
This function performs percentage change normalization by dividing each element
|
|
652
|
+
by the mean of the vector and subtracting 1.0.
|
|
350
653
|
|
|
351
654
|
Parameters
|
|
352
655
|
----------
|
|
353
|
-
vector
|
|
656
|
+
vector : NDArray
|
|
657
|
+
Input vector to be normalized.
|
|
354
658
|
|
|
355
659
|
Returns
|
|
356
660
|
-------
|
|
357
|
-
|
|
661
|
+
NDArray
|
|
662
|
+
Normalized vector where each element is (vector[i] / mean) - 1.0.
|
|
663
|
+
If the mean is less than or equal to zero, the original vector is returned.
|
|
664
|
+
|
|
665
|
+
Notes
|
|
666
|
+
-----
|
|
667
|
+
The normalization formula is: (vector / mean) - 1.0
|
|
668
|
+
If the mean of the vector is less than or equal to zero, the function returns
|
|
669
|
+
the original vector to avoid division by zero or negative normalization.
|
|
670
|
+
|
|
671
|
+
Examples
|
|
672
|
+
--------
|
|
673
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
674
|
+
>>> normalized = pcnormalize(data)
|
|
675
|
+
>>> print(normalized)
|
|
676
|
+
[-0.6 -0.2 0.2 0.6 1. ]
|
|
677
|
+
|
|
678
|
+
>>> data = np.array([10, 20, 30])
|
|
679
|
+
>>> normalized = pcnormalize(data)
|
|
680
|
+
>>> print(normalized)
|
|
681
|
+
[-0.5 0.5 1.5]
|
|
358
682
|
"""
|
|
359
683
|
sigmean = np.mean(vector)
|
|
360
684
|
if sigmean > 0.0:
|
|
@@ -363,16 +687,36 @@ def pcnormalize(vector):
|
|
|
363
687
|
return vector
|
|
364
688
|
|
|
365
689
|
|
|
366
|
-
def ppnormalize(vector):
|
|
690
|
+
def ppnormalize(vector: NDArray) -> NDArray:
|
|
367
691
|
"""
|
|
692
|
+
Normalize a vector using peak-to-peak normalization.
|
|
693
|
+
|
|
694
|
+
This function performs peak-to-peak normalization by subtracting the mean
|
|
695
|
+
and dividing by the range (max - min) of the demeaned vector.
|
|
368
696
|
|
|
369
697
|
Parameters
|
|
370
698
|
----------
|
|
371
|
-
vector
|
|
699
|
+
vector : NDArray
|
|
700
|
+
Input vector to be normalized
|
|
372
701
|
|
|
373
702
|
Returns
|
|
374
703
|
-------
|
|
375
|
-
|
|
704
|
+
NDArray
|
|
705
|
+
Normalized vector with values ranging from -0.5 to 0.5 when the range is non-zero,
|
|
706
|
+
or zero vector when the range is zero
|
|
707
|
+
|
|
708
|
+
Notes
|
|
709
|
+
-----
|
|
710
|
+
The normalization is performed as: (vector - mean) / (max - min)
|
|
711
|
+
If the range (max - min) is zero, the function returns the demeaned vector
|
|
712
|
+
(which will be all zeros) to avoid division by zero.
|
|
713
|
+
|
|
714
|
+
Examples
|
|
715
|
+
--------
|
|
716
|
+
>>> data = np.array([1, 2, 3, 4, 5])
|
|
717
|
+
>>> normalized = ppnormalize(data)
|
|
718
|
+
>>> print(normalized)
|
|
719
|
+
[-0.5 -0.25 0. 0.25 0.5 ]
|
|
376
720
|
"""
|
|
377
721
|
demeaned = vector - np.mean(vector)
|
|
378
722
|
sigpp = np.max(demeaned) - np.min(demeaned)
|
|
@@ -382,7 +726,53 @@ def ppnormalize(vector):
|
|
|
382
726
|
return demeaned
|
|
383
727
|
|
|
384
728
|
|
|
385
|
-
def imagevariance(
|
|
729
|
+
def imagevariance(
|
|
730
|
+
thedata: NDArray,
|
|
731
|
+
thefilter: Optional[object],
|
|
732
|
+
samplefreq: float,
|
|
733
|
+
meannorm: bool = True,
|
|
734
|
+
debug: bool = False,
|
|
735
|
+
) -> NDArray:
|
|
736
|
+
"""
|
|
737
|
+
Calculate variance of filtered image data, optionally normalized by mean.
|
|
738
|
+
|
|
739
|
+
This function applies a filter to each voxel's time series data and computes
|
|
740
|
+
the variance along the time dimension. The result can be optionally normalized
|
|
741
|
+
by the mean of the original data.
|
|
742
|
+
|
|
743
|
+
Parameters
|
|
744
|
+
----------
|
|
745
|
+
thedata : NDArray
|
|
746
|
+
Input image data with shape (n_voxels, n_timepoints).
|
|
747
|
+
thefilter : Optional[object]
|
|
748
|
+
Filter object with an 'apply' method that takes (samplefreq, data) as arguments.
|
|
749
|
+
If None, no filtering is applied.
|
|
750
|
+
samplefreq : float
|
|
751
|
+
Sampling frequency used for filter application.
|
|
752
|
+
meannorm : bool, optional
|
|
753
|
+
If True, normalize variance by mean of original data. Default is True.
|
|
754
|
+
debug : bool, optional
|
|
755
|
+
If True, print debug information. Default is False.
|
|
756
|
+
|
|
757
|
+
Returns
|
|
758
|
+
-------
|
|
759
|
+
NDArray
|
|
760
|
+
Array of variance values for each voxel. Shape is (n_voxels,).
|
|
761
|
+
|
|
762
|
+
Notes
|
|
763
|
+
-----
|
|
764
|
+
- NaN values are converted to zero in the final result.
|
|
765
|
+
- When `meannorm=True`, the variance is normalized by the mean of the original data.
|
|
766
|
+
- The filter is applied to each voxel's time series independently.
|
|
767
|
+
- If no filter is provided, the original data is used directly.
|
|
768
|
+
|
|
769
|
+
Examples
|
|
770
|
+
--------
|
|
771
|
+
>>> data = np.random.randn(100, 50)
|
|
772
|
+
>>> filter_obj = SomeFilter()
|
|
773
|
+
>>> variance = imagevariance(data, filter_obj, samplefreq=2.0)
|
|
774
|
+
>>> variance = imagevariance(data, None, samplefreq=2.0, meannorm=False)
|
|
775
|
+
"""
|
|
386
776
|
if debug:
|
|
387
777
|
print(f"IMAGEVARIANCE: {thedata.shape}, {thefilter}, {samplefreq}")
|
|
388
778
|
filteredim = thedata * 0.0
|
|
@@ -398,19 +788,47 @@ def imagevariance(thedata, thefilter, samplefreq, meannorm=True, debug=False):
|
|
|
398
788
|
|
|
399
789
|
|
|
400
790
|
# @conditionaljit()
|
|
401
|
-
def corrnormalize(thedata, detrendorder=1, windowfunc="hamming"):
|
|
791
|
+
def corrnormalize(thedata: NDArray, detrendorder: int = 1, windowfunc: str = "hamming") -> NDArray:
|
|
402
792
|
"""
|
|
793
|
+
Normalize data by detrending and applying a window function, then standardize.
|
|
794
|
+
|
|
795
|
+
This function first detrends the input data, applies a window function if specified,
|
|
796
|
+
and then normalizes the result using standard normalization.
|
|
403
797
|
|
|
404
798
|
Parameters
|
|
405
799
|
----------
|
|
406
|
-
thedata
|
|
407
|
-
|
|
408
|
-
|
|
800
|
+
thedata : NDArray
|
|
801
|
+
Input data to be normalized.
|
|
802
|
+
detrendorder : int, optional
|
|
803
|
+
Order of detrending to apply. A value of 0 skips detrending, while values > 0
|
|
804
|
+
apply polynomial detrending (default is 1 for linear detrending).
|
|
805
|
+
windowfunc : str, optional
|
|
806
|
+
Window function to apply (e.g., 'hamming', 'hanning'). Use 'None' to skip
|
|
807
|
+
windowing (default is 'hamming').
|
|
409
808
|
|
|
410
809
|
Returns
|
|
411
810
|
-------
|
|
412
|
-
|
|
811
|
+
NDArray
|
|
812
|
+
Normalized data array with detrending, windowing (if applicable), and standard
|
|
813
|
+
normalization applied, followed by division by sqrt(n), where n is the length
|
|
814
|
+
of the input data.
|
|
815
|
+
|
|
816
|
+
Notes
|
|
817
|
+
-----
|
|
818
|
+
The normalization process is performed in the following steps:
|
|
819
|
+
1. Detrend the data using polynomial fitting if `detrendorder` > 0.
|
|
820
|
+
2. Apply a window function if `windowfunc` is not 'None'.
|
|
821
|
+
3. Standard normalize the result.
|
|
822
|
+
4. Divide the normalized result by sqrt(n), where n is the length of the data.
|
|
823
|
+
|
|
824
|
+
Examples
|
|
825
|
+
--------
|
|
826
|
+
>>> import numpy as np
|
|
827
|
+
>>> data = np.random.randn(100)
|
|
828
|
+
>>> normalized = corrnormalize(data)
|
|
829
|
+
>>> normalized = corrnormalize(data, detrendorder=2, windowfunc='hanning')
|
|
413
830
|
"""
|
|
831
|
+
|
|
414
832
|
# detrend first
|
|
415
833
|
if detrendorder > 0:
|
|
416
834
|
intervec = stdnormalize(tide_fit.detrend(thedata, order=detrendorder, demean=True))
|
|
@@ -426,17 +844,58 @@ def corrnormalize(thedata, detrendorder=1, windowfunc="hamming"):
|
|
|
426
844
|
return stdnormalize(intervec) / np.sqrt(np.shape(thedata)[0])
|
|
427
845
|
|
|
428
846
|
|
|
429
|
-
def noiseamp(
|
|
847
|
+
def noiseamp(
|
|
848
|
+
vector: NDArray, Fs: float, windowsize: float = 40.0
|
|
849
|
+
) -> Tuple[NDArray, NDArray, float, float, float, float]:
|
|
430
850
|
"""
|
|
851
|
+
Compute noise amplitude characteristics from a vector using band-pass filtering and trend analysis.
|
|
852
|
+
|
|
853
|
+
This function applies a non-causal band-pass filter to the squared input vector to extract
|
|
854
|
+
envelope information, then computes root-mean-square (RMS) values over time. A linear trend
|
|
855
|
+
is fitted to the RMS values to determine the start and end amplitudes, and the percentage
|
|
856
|
+
change and rate of change are calculated over the signal duration.
|
|
431
857
|
|
|
432
858
|
Parameters
|
|
433
859
|
----------
|
|
434
|
-
vector
|
|
435
|
-
|
|
860
|
+
vector : ndarray
|
|
861
|
+
Input signal vector (1D array) from which noise amplitude is computed.
|
|
862
|
+
Fs : float
|
|
863
|
+
Sampling frequency of the input signal in Hz.
|
|
864
|
+
windowsize : float, optional
|
|
865
|
+
Size of the filtering window in seconds, used to define the cutoff frequency.
|
|
866
|
+
Default is 40.0 seconds.
|
|
436
867
|
|
|
437
868
|
Returns
|
|
438
869
|
-------
|
|
439
|
-
|
|
870
|
+
tuple of (filtrms, thefittc, startamp, endamp, changepct, changerate)
|
|
871
|
+
- filtrms : ndarray
|
|
872
|
+
Root-mean-square (RMS) values of the filtered signal.
|
|
873
|
+
- thefittc : ndarray
|
|
874
|
+
Linear trend fit applied to the RMS values.
|
|
875
|
+
- startamp : float
|
|
876
|
+
Starting amplitude value from the trend fit.
|
|
877
|
+
- endamp : float
|
|
878
|
+
Ending amplitude value from the trend fit.
|
|
879
|
+
- changepct : float
|
|
880
|
+
Percentage change in amplitude from start to end.
|
|
881
|
+
- changerate : float
|
|
882
|
+
Rate of amplitude change per second (percentage per second).
|
|
883
|
+
|
|
884
|
+
Notes
|
|
885
|
+
-----
|
|
886
|
+
- The function uses a non-causal filter (`tide_filt.NoncausalFilter`) with an
|
|
887
|
+
arbitrary band-pass configuration.
|
|
888
|
+
- The cutoff frequency is computed as 1 / windowsize.
|
|
889
|
+
- Padding and unpadding are applied to avoid edge effects in filtering.
|
|
890
|
+
- If a RankWarning occurs during polynomial fitting, the coefficients are set to [0.0, 0.0].
|
|
891
|
+
|
|
892
|
+
Examples
|
|
893
|
+
--------
|
|
894
|
+
>>> import numpy as np
|
|
895
|
+
>>> vector = np.random.randn(1000)
|
|
896
|
+
>>> Fs = 10.0
|
|
897
|
+
>>> rms_vals, trend_vals, start, end, pct_chg, rate_chg = noiseamp(vector, Fs)
|
|
898
|
+
>>> print(f"Start amplitude: {start:.3f}, End amplitude: {end:.3f}")
|
|
440
899
|
"""
|
|
441
900
|
cutoff = 1.0 / windowsize
|
|
442
901
|
padlen = int(len(vector) // 2)
|
|
@@ -451,7 +910,7 @@ def noiseamp(vector, Fs, windowsize=40.0):
|
|
|
451
910
|
thetimepoints = np.arange(0.0, len(filtrms), 1.0) - len(filtrms) / 2.0
|
|
452
911
|
try:
|
|
453
912
|
thecoffs = Polynomial.fit(thetimepoints, filtrms, 1).convert().coef[::-1]
|
|
454
|
-
except np.
|
|
913
|
+
except np.exceptions.RankWarning:
|
|
455
914
|
thecoffs = [0.0, 0.0]
|
|
456
915
|
thefittc = tide_fit.trendgen(thetimepoints, thecoffs, True)
|
|
457
916
|
startamp = thefittc[0]
|
|
@@ -465,37 +924,76 @@ def noiseamp(vector, Fs, windowsize=40.0):
|
|
|
465
924
|
return filtrms, thefittc, startamp, endamp, changepct, changerate
|
|
466
925
|
|
|
467
926
|
|
|
468
|
-
def rms(vector):
|
|
927
|
+
def rms(vector: NDArray) -> float:
|
|
469
928
|
"""
|
|
929
|
+
Compute the root mean square (RMS) of a vector.
|
|
930
|
+
|
|
931
|
+
The root mean square is a statistical measure that represents the magnitude
|
|
932
|
+
of a varying quantity. It is especially useful in physics and engineering
|
|
933
|
+
applications.
|
|
470
934
|
|
|
471
935
|
Parameters
|
|
472
936
|
----------
|
|
473
|
-
vector
|
|
937
|
+
vector : array_like
|
|
938
|
+
Input vector for which to compute the root mean square.
|
|
474
939
|
|
|
475
940
|
Returns
|
|
476
941
|
-------
|
|
477
|
-
|
|
942
|
+
float
|
|
943
|
+
The root mean square value of the input vector.
|
|
944
|
+
|
|
945
|
+
Notes
|
|
946
|
+
-----
|
|
947
|
+
The RMS is calculated as sqrt(mean(square(vector))).
|
|
948
|
+
|
|
949
|
+
Examples
|
|
950
|
+
--------
|
|
951
|
+
>>> import numpy as np
|
|
952
|
+
>>> rms([1, 2, 3, 4])
|
|
953
|
+
2.7386127875258306
|
|
954
|
+
>>> rms(np.array([1, 2, 3, 4]))
|
|
955
|
+
2.7386127875258306
|
|
478
956
|
"""
|
|
479
957
|
return np.sqrt(np.mean(np.square(vector)))
|
|
480
958
|
|
|
481
959
|
|
|
482
|
-
def envdetect(Fs, inputdata, cutoff=0.25, padlen=10):
|
|
960
|
+
def envdetect(Fs: float, inputdata: NDArray, cutoff: float = 0.25, padlen: int = 10) -> NDArray:
|
|
483
961
|
"""
|
|
962
|
+
Compute the envelope of input signal using band-pass filtering.
|
|
963
|
+
|
|
964
|
+
This function calculates the envelope of a signal by first removing the mean,
|
|
965
|
+
taking the absolute value, and then applying a band-pass filter to isolate
|
|
966
|
+
the envelope components. The filtering is performed using a non-causal filter
|
|
967
|
+
to avoid phase distortion.
|
|
484
968
|
|
|
485
969
|
Parameters
|
|
486
970
|
----------
|
|
487
971
|
Fs : float
|
|
488
|
-
|
|
489
|
-
inputdata :
|
|
490
|
-
|
|
491
|
-
cutoff : float
|
|
492
|
-
|
|
972
|
+
Sampling frequency of the input signal in Hz.
|
|
973
|
+
inputdata : NDArray
|
|
974
|
+
Input signal array to process.
|
|
975
|
+
cutoff : float, optional
|
|
976
|
+
Cutoff frequency for the band-pass filter. Default is 0.25.
|
|
977
|
+
padlen : int, optional
|
|
978
|
+
Padding length used for filtering to avoid edge effects. Default is 10.
|
|
493
979
|
|
|
494
980
|
Returns
|
|
495
981
|
-------
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
982
|
+
NDArray
|
|
983
|
+
Envelope of the input signal with the same shape as inputdata.
|
|
984
|
+
|
|
985
|
+
Notes
|
|
986
|
+
-----
|
|
987
|
+
The function uses a non-causal filter (two-pass filtering) which avoids
|
|
988
|
+
phase distortion but requires padding the signal. The filter is set to
|
|
989
|
+
pass frequencies between 0 and cutoff, with a stop band starting at 1.1*cutoff.
|
|
990
|
+
|
|
991
|
+
Examples
|
|
992
|
+
--------
|
|
993
|
+
>>> import numpy as np
|
|
994
|
+
>>> Fs = 100.0
|
|
995
|
+
>>> signal = np.sin(2 * np.pi * 10 * np.linspace(0, 1, Fs))
|
|
996
|
+
>>> envelope = envdetect(Fs, signal)
|
|
499
997
|
"""
|
|
500
998
|
demeaned = inputdata - np.mean(inputdata)
|
|
501
999
|
sigabs = abs(demeaned)
|
|
@@ -504,20 +1002,39 @@ def envdetect(Fs, inputdata, cutoff=0.25, padlen=10):
|
|
|
504
1002
|
return tide_filt.unpadvec(theenvbpf.apply(Fs, tide_filt.padvec(sigabs, padlen)), padlen)
|
|
505
1003
|
|
|
506
1004
|
|
|
507
|
-
def phasemod(phase, centric=True):
|
|
1005
|
+
def phasemod(phase: NDArray, centric: bool = True) -> NDArray:
|
|
508
1006
|
"""
|
|
1007
|
+
Perform phase modulation with optional centric adjustment.
|
|
1008
|
+
|
|
1009
|
+
This function applies phase modulation to the input phase array, with an option
|
|
1010
|
+
to apply a centric transformation that maps the phase range to [-π, π].
|
|
509
1011
|
|
|
510
1012
|
Parameters
|
|
511
1013
|
----------
|
|
512
|
-
phase :
|
|
513
|
-
|
|
514
|
-
centric:
|
|
515
|
-
|
|
1014
|
+
phase : ndarray
|
|
1015
|
+
Input phase array in radians.
|
|
1016
|
+
centric : bool, optional
|
|
1017
|
+
If True, applies centric transformation to map phase to [-π, π] range.
|
|
1018
|
+
If False, returns phase modulo 2π. Default is True.
|
|
516
1019
|
|
|
517
1020
|
Returns
|
|
518
1021
|
-------
|
|
519
|
-
|
|
520
|
-
|
|
1022
|
+
ndarray
|
|
1023
|
+
Modulated phase array with same shape as input.
|
|
1024
|
+
|
|
1025
|
+
Notes
|
|
1026
|
+
-----
|
|
1027
|
+
When `centric=True`, the transformation is equivalent to:
|
|
1028
|
+
`((-phase + π) % (2π) - π) * -1`
|
|
1029
|
+
|
|
1030
|
+
Examples
|
|
1031
|
+
--------
|
|
1032
|
+
>>> import numpy as np
|
|
1033
|
+
>>> phase = np.array([0, np.pi/2, np.pi, 3*np.pi/2, 2*np.pi])
|
|
1034
|
+
>>> phasemod(phase)
|
|
1035
|
+
array([ 0. , 1.57079633, 3.14159265, -1.57079633, 0. ])
|
|
1036
|
+
>>> phasemod(phase, centric=False)
|
|
1037
|
+
array([0. , 1.57079633, 3.14159265, 4.71238898, 0. ])
|
|
521
1038
|
"""
|
|
522
1039
|
if centric:
|
|
523
1040
|
return ((-phase + np.pi) % (2.0 * np.pi) - np.pi) * -1.0
|
|
@@ -525,23 +1042,51 @@ def phasemod(phase, centric=True):
|
|
|
525
1042
|
return phase % (2.0 * np.pi)
|
|
526
1043
|
|
|
527
1044
|
|
|
528
|
-
def trendfilt(
|
|
1045
|
+
def trendfilt(
|
|
1046
|
+
inputdata: NDArray, order: int = 3, ndevs: float = 3.0, debug: bool = False
|
|
1047
|
+
) -> NDArray:
|
|
529
1048
|
"""
|
|
1049
|
+
Apply trend filtering to remove polynomial trends and outliers from time series data.
|
|
1050
|
+
|
|
1051
|
+
This function fits a polynomial trend to the input data using least squares,
|
|
1052
|
+
removes the trend to obtain detrended data, and then applies outlier detection
|
|
1053
|
+
using median absolute deviation (MAD) normalization to identify and mask outliers.
|
|
530
1054
|
|
|
531
1055
|
Parameters
|
|
532
1056
|
----------
|
|
533
|
-
inputdata :
|
|
534
|
-
|
|
1057
|
+
inputdata : NDArray
|
|
1058
|
+
Input time series data to be filtered.
|
|
1059
|
+
order : int, optional
|
|
1060
|
+
Order of the polynomial trend to fit (default is 3).
|
|
1061
|
+
ndevs : float, optional
|
|
1062
|
+
Number of standard deviations for outlier detection (default is 3.0).
|
|
1063
|
+
debug : bool, optional
|
|
1064
|
+
If True, display debug plots showing the detrended data and outliers (default is False).
|
|
535
1065
|
|
|
536
1066
|
Returns
|
|
537
1067
|
-------
|
|
538
|
-
|
|
539
|
-
|
|
1068
|
+
NDArray
|
|
1069
|
+
Filtered time series data with polynomial trend removed and outliers masked as zeros.
|
|
1070
|
+
|
|
1071
|
+
Notes
|
|
1072
|
+
-----
|
|
1073
|
+
The function uses `Polynomial.fit` to fit a polynomial trend and `tide_fit.trendgen`
|
|
1074
|
+
to generate the trend values. Outliers are detected using median absolute deviation
|
|
1075
|
+
normalization and masked by setting them to zero. The original trend is added back
|
|
1076
|
+
to the filtered data to maintain the overall signal structure.
|
|
1077
|
+
|
|
1078
|
+
Examples
|
|
1079
|
+
--------
|
|
1080
|
+
>>> import numpy as np
|
|
1081
|
+
>>> data = np.random.randn(100)
|
|
1082
|
+
>>> filtered_data = trendfilt(data, order=2, ndevs=2.0)
|
|
1083
|
+
>>> # With debug mode enabled
|
|
1084
|
+
>>> filtered_data = trendfilt(data, debug=True)
|
|
540
1085
|
"""
|
|
541
1086
|
thetimepoints = np.arange(0.0, len(inputdata), 1.0) - len(inputdata) / 2.0
|
|
542
1087
|
try:
|
|
543
1088
|
thecoffs = Polynomial.fit(thetimepoints, inputdata, order).convert().coef[::-1]
|
|
544
|
-
except np.
|
|
1089
|
+
except np.exceptions.RankWarning:
|
|
545
1090
|
thecoffs = [0.0, 0.0]
|
|
546
1091
|
thefittc = tide_fit.trendgen(thetimepoints, thecoffs, True)
|
|
547
1092
|
detrended = inputdata - thefittc
|
|
@@ -558,15 +1103,113 @@ def trendfilt(inputdata, order=3, ndevs=3.0, debug=False):
|
|
|
558
1103
|
# found here: https://datascience.stackexchange.com/questions/75733/pca-for-complex-valued-data
|
|
559
1104
|
class ComplexPCA:
|
|
560
1105
|
def __init__(self, n_components):
|
|
1106
|
+
"""
|
|
1107
|
+
Initialize the PCA model with the specified number of components.
|
|
1108
|
+
|
|
1109
|
+
Parameters
|
|
1110
|
+
----------
|
|
1111
|
+
n_components : int
|
|
1112
|
+
Number of components to keep.
|
|
1113
|
+
|
|
1114
|
+
Returns
|
|
1115
|
+
-------
|
|
1116
|
+
None
|
|
1117
|
+
Initializes the PCA model with the specified number of components and
|
|
1118
|
+
sets internal attributes to None.
|
|
1119
|
+
|
|
1120
|
+
Notes
|
|
1121
|
+
-----
|
|
1122
|
+
This constructor initializes the PCA model with the specified number of
|
|
1123
|
+
components. The actual computation of principal components is performed
|
|
1124
|
+
during the fit method.
|
|
1125
|
+
|
|
1126
|
+
Examples
|
|
1127
|
+
--------
|
|
1128
|
+
>>> from sklearn.decomposition import PCA
|
|
1129
|
+
>>> pca = PCA(n_components=2)
|
|
1130
|
+
>>> print(pca.n_components)
|
|
1131
|
+
2
|
|
1132
|
+
"""
|
|
561
1133
|
self.n_components = n_components
|
|
562
1134
|
self.u = self.s = self.components_ = None
|
|
563
1135
|
self.mean_ = None
|
|
564
1136
|
|
|
565
1137
|
@property
|
|
566
1138
|
def explained_variance_ratio_(self):
|
|
1139
|
+
"""
|
|
1140
|
+
Return the explained variance ratio.
|
|
1141
|
+
|
|
1142
|
+
This function returns the explained variance ratio stored in the object's
|
|
1143
|
+
`s` attribute, which typically represents the proportion of variance
|
|
1144
|
+
explained by each component in dimensionality reduction techniques.
|
|
1145
|
+
|
|
1146
|
+
Returns
|
|
1147
|
+
-------
|
|
1148
|
+
explained_variance_ratio : array-like
|
|
1149
|
+
The explained variance ratio for each component. Each element
|
|
1150
|
+
represents the fraction of the total variance explained by the
|
|
1151
|
+
corresponding component.
|
|
1152
|
+
|
|
1153
|
+
Notes
|
|
1154
|
+
-----
|
|
1155
|
+
The explained variance ratio is commonly used in Principal Component
|
|
1156
|
+
Analysis (PCA) and similar dimensionality reduction methods to determine
|
|
1157
|
+
the importance of each component and to decide how many components to
|
|
1158
|
+
retain for analysis.
|
|
1159
|
+
|
|
1160
|
+
Examples
|
|
1161
|
+
--------
|
|
1162
|
+
>>> from sklearn.decomposition import PCA
|
|
1163
|
+
>>> pca = PCA()
|
|
1164
|
+
>>> pca.fit(X)
|
|
1165
|
+
>>> ratio = pca.explained_variance_ratio_
|
|
1166
|
+
>>> print(ratio)
|
|
1167
|
+
[0.856, 0.123, 0.021]
|
|
1168
|
+
"""
|
|
567
1169
|
return self.s
|
|
568
1170
|
|
|
569
1171
|
def fit(self, matrix, use_gpu=False):
|
|
1172
|
+
"""
|
|
1173
|
+
Fit the model with the given matrix using Singular Value Decomposition.
|
|
1174
|
+
|
|
1175
|
+
This method computes the mean of the input matrix and performs SVD decomposition
|
|
1176
|
+
to obtain the principal components. The decomposition can be performed using
|
|
1177
|
+
either CPU (numpy) or GPU (tensorflow) depending on the use_gpu parameter.
|
|
1178
|
+
|
|
1179
|
+
Parameters
|
|
1180
|
+
----------
|
|
1181
|
+
matrix : array-like of shape (n_samples, n_features)
|
|
1182
|
+
Input matrix to fit the model on. The matrix should be numeric.
|
|
1183
|
+
use_gpu : bool, default=False
|
|
1184
|
+
If True, use TensorFlow for SVD computation on GPU. If False, use NumPy.
|
|
1185
|
+
Note: TensorFlow is used for GPU computation as PyTorch doesn't handle
|
|
1186
|
+
complex values well.
|
|
1187
|
+
|
|
1188
|
+
Returns
|
|
1189
|
+
-------
|
|
1190
|
+
self : object
|
|
1191
|
+
Returns the instance itself.
|
|
1192
|
+
|
|
1193
|
+
Notes
|
|
1194
|
+
-----
|
|
1195
|
+
- The SVD is performed with `full_matrices=False`, which means the number of
|
|
1196
|
+
components will be min(n_samples, n_features).
|
|
1197
|
+
- For better performance when only a subset of components is needed, consider
|
|
1198
|
+
truncating the SVD to `n_components` instead of computing all components.
|
|
1199
|
+
- The `components_` attribute stores the right singular vectors (principal components).
|
|
1200
|
+
- The `mean_` attribute stores the mean of each feature across samples.
|
|
1201
|
+
- The `s` attribute stores the singular values from the SVD decomposition.
|
|
1202
|
+
|
|
1203
|
+
Examples
|
|
1204
|
+
--------
|
|
1205
|
+
>>> import numpy as np
|
|
1206
|
+
>>> from sklearn.decomposition import PCA
|
|
1207
|
+
>>> X = np.random.rand(100, 10)
|
|
1208
|
+
>>> pca = PCA()
|
|
1209
|
+
>>> pca.fit(X)
|
|
1210
|
+
>>> print(pca.components_.shape)
|
|
1211
|
+
(10, 10)
|
|
1212
|
+
"""
|
|
570
1213
|
self.mean_ = matrix.mean(axis=0)
|
|
571
1214
|
if use_gpu:
|
|
572
1215
|
import tensorflow as tf # torch doesn't handle complex values.
|
|
@@ -585,10 +1228,73 @@ class ComplexPCA:
|
|
|
585
1228
|
# Leave those components as rows of matrix so that it is compatible with Sklearn PCA.
|
|
586
1229
|
|
|
587
1230
|
def transform(self, matrix):
|
|
1231
|
+
"""
|
|
1232
|
+
Transform matrix using the fitted components.
|
|
1233
|
+
|
|
1234
|
+
Parameters
|
|
1235
|
+
----------
|
|
1236
|
+
matrix : array-like of shape (n_samples, n_features)
|
|
1237
|
+
The data to be transformed.
|
|
1238
|
+
|
|
1239
|
+
Returns
|
|
1240
|
+
-------
|
|
1241
|
+
array-like of shape (n_samples, n_components)
|
|
1242
|
+
The transformed data.
|
|
1243
|
+
|
|
1244
|
+
Notes
|
|
1245
|
+
-----
|
|
1246
|
+
This function applies the transformation defined by the fitted components
|
|
1247
|
+
to the input matrix. It subtracts the mean and projects onto the component
|
|
1248
|
+
space.
|
|
1249
|
+
|
|
1250
|
+
Examples
|
|
1251
|
+
--------
|
|
1252
|
+
>>> from sklearn.decomposition import PCA
|
|
1253
|
+
>>> import numpy as np
|
|
1254
|
+
>>> pca = PCA(n_components=2)
|
|
1255
|
+
>>> X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
1256
|
+
>>> pca.fit(X)
|
|
1257
|
+
>>> transformed = pca.transform(X)
|
|
1258
|
+
>>> print(transformed.shape)
|
|
1259
|
+
(3, 2)
|
|
1260
|
+
"""
|
|
588
1261
|
data = matrix - self.mean_
|
|
589
1262
|
result = data @ self.components_.T
|
|
590
1263
|
return result
|
|
591
1264
|
|
|
592
1265
|
def inverse_transform(self, matrix):
|
|
1266
|
+
"""
|
|
1267
|
+
Apply inverse transformation to the input matrix.
|
|
1268
|
+
|
|
1269
|
+
Parameters
|
|
1270
|
+
----------
|
|
1271
|
+
matrix : array-like of shape (n_samples, n_components)
|
|
1272
|
+
The transformed data to be inverse transformed.
|
|
1273
|
+
|
|
1274
|
+
Returns
|
|
1275
|
+
-------
|
|
1276
|
+
ndarray of shape (n_samples, n_features)
|
|
1277
|
+
The inverse transformed data in the original feature space.
|
|
1278
|
+
|
|
1279
|
+
Notes
|
|
1280
|
+
-----
|
|
1281
|
+
This function applies the inverse transformation using the stored components
|
|
1282
|
+
and mean values. The transformation is defined as:
|
|
1283
|
+
result = matrix @ conj(self.components_) + self.mean_
|
|
1284
|
+
|
|
1285
|
+
Examples
|
|
1286
|
+
--------
|
|
1287
|
+
>>> from sklearn.decomposition import PCA
|
|
1288
|
+
>>> import numpy as np
|
|
1289
|
+
>>> # Create sample data
|
|
1290
|
+
>>> data = np.random.rand(100, 10)
|
|
1291
|
+
>>> # Fit PCA
|
|
1292
|
+
>>> pca = PCA(n_components=5)
|
|
1293
|
+
>>> transformed = pca.fit_transform(data)
|
|
1294
|
+
>>> # Inverse transform
|
|
1295
|
+
>>> reconstructed = pca.inverse_transform(transformed)
|
|
1296
|
+
>>> print(reconstructed.shape)
|
|
1297
|
+
(100, 10)
|
|
1298
|
+
"""
|
|
593
1299
|
result = matrix @ np.conj(self.components_)
|
|
594
1300
|
return self.mean_ + result
|