rapidtide 3.0.11__py3-none-any.whl → 3.1.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 +188 -40
- rapidtide/calcsimfunc.py +242 -42
- rapidtide/correlate.py +1203 -383
- 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 +53 -3
- rapidtide/data/examples/src/testglmfilt +5 -5
- rapidtide/data/examples/src/testhappy +29 -7
- 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 +2226 -110
- rapidtide/dlfiltertorch.py +4842 -0
- rapidtide/externaltools.py +327 -12
- rapidtide/fMRIData_class.py +79 -40
- rapidtide/filter.py +1899 -810
- rapidtide/fit.py +2011 -581
- rapidtide/genericmultiproc.py +93 -18
- rapidtide/happy_supportfuncs.py +2047 -172
- rapidtide/helper_classes.py +584 -43
- rapidtide/io.py +2370 -372
- rapidtide/linfitfiltpass.py +346 -99
- rapidtide/makelaggedtcs.py +210 -24
- rapidtide/maskutil.py +448 -62
- rapidtide/miscmath.py +827 -121
- rapidtide/multiproc.py +210 -22
- rapidtide/patchmatch.py +242 -42
- rapidtide/peakeval.py +31 -31
- rapidtide/ppgproc.py +2203 -0
- rapidtide/qualitycheck.py +352 -39
- rapidtide/refinedelay.py +431 -57
- rapidtide/refineregressor.py +494 -189
- rapidtide/resample.py +671 -185
- rapidtide/scripts/applyppgproc.py +28 -0
- rapidtide/scripts/showxcorr_legacy.py +7 -7
- rapidtide/scripts/stupidramtricks.py +15 -17
- rapidtide/simFuncClasses.py +1052 -77
- rapidtide/simfuncfit.py +269 -69
- rapidtide/stats.py +540 -238
- rapidtide/tests/happycomp +9 -0
- rapidtide/tests/test_cleanregressor.py +1 -2
- 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 +11 -4
- rapidtide/tests/test_fullrunhappy_v4.py +10 -2
- rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
- rapidtide/tests/test_getparsers.py +11 -3
- rapidtide/tests/test_refinedelay.py +0 -1
- rapidtide/tests/test_simroundtrip.py +16 -8
- rapidtide/tests/test_stcorrelate.py +3 -1
- 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 +136 -23
- rapidtide/wiener2.py +113 -7
- rapidtide/workflows/adjustoffset.py +105 -3
- rapidtide/workflows/aligntcs.py +85 -2
- rapidtide/workflows/applydlfilter.py +87 -10
- rapidtide/workflows/applyppgproc.py +540 -0
- rapidtide/workflows/atlasaverage.py +210 -47
- rapidtide/workflows/atlastool.py +100 -3
- rapidtide/workflows/calcSimFuncMap.py +288 -69
- rapidtide/workflows/calctexticc.py +201 -9
- rapidtide/workflows/ccorrica.py +101 -6
- rapidtide/workflows/cleanregressor.py +165 -31
- rapidtide/workflows/delayvar.py +171 -23
- 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 +202 -51
- 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 +163 -23
- 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 +98 -4
- rapidtide/workflows/pairwisemergenifti.py +85 -2
- rapidtide/workflows/parser_funcs.py +1421 -40
- rapidtide/workflows/physiofreq.py +137 -11
- rapidtide/workflows/pixelcomp.py +207 -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 +368 -76
- rapidtide/workflows/rapidtide2std.py +98 -2
- rapidtide/workflows/rapidtide_parser.py +109 -9
- rapidtide/workflows/refineDelayMap.py +144 -33
- rapidtide/workflows/refineRegressor.py +675 -96
- rapidtide/workflows/regressfrommaps.py +161 -37
- rapidtide/workflows/resamplenifti.py +85 -3
- rapidtide/workflows/resampletc.py +91 -3
- rapidtide/workflows/retrolagtcs.py +99 -9
- rapidtide/workflows/retroregress.py +176 -26
- rapidtide/workflows/roisummarize.py +174 -5
- rapidtide/workflows/runqualitycheck.py +71 -3
- rapidtide/workflows/showarbcorr.py +149 -6
- rapidtide/workflows/showhist.py +86 -2
- rapidtide/workflows/showstxcorr.py +160 -3
- rapidtide/workflows/showtc.py +159 -3
- rapidtide/workflows/showxcorrx.py +190 -10
- rapidtide/workflows/showxy.py +185 -15
- rapidtide/workflows/simdata.py +264 -38
- rapidtide/workflows/spatialfit.py +77 -2
- rapidtide/workflows/spatialmi.py +250 -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 +2971 -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.1.dist-info}/METADATA +10 -8
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/RECORD +144 -128
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/entry_points.txt +1 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/WHEEL +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/licenses/LICENSE +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/top_level.txt +0 -0
rapidtide/linfitfiltpass.py
CHANGED
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
# limitations under the License.
|
|
17
17
|
#
|
|
18
18
|
#
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
19
21
|
import numpy as np
|
|
22
|
+
from numpy.typing import NDArray
|
|
20
23
|
from scipy.special import factorial
|
|
21
24
|
from tqdm import tqdm
|
|
22
25
|
|
|
@@ -27,38 +30,89 @@ import rapidtide.multiproc as tide_multiproc
|
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
def _procOneRegressionFitItem(
|
|
30
|
-
vox
|
|
31
|
-
|
|
33
|
+
vox: int,
|
|
34
|
+
theevs: NDArray,
|
|
35
|
+
thedata: NDArray,
|
|
36
|
+
rt_floattype: np.dtype = np.float64,
|
|
37
|
+
) -> tuple[int, float, float, float, float | NDArray, Any, NDArray, NDArray]:
|
|
38
|
+
"""
|
|
39
|
+
Perform single regression fit on voxel data and return fit results.
|
|
40
|
+
|
|
41
|
+
This function fits a linear regression model to the provided evs and data,
|
|
42
|
+
handling both univariate and multivariate cases. It computes fit coefficients,
|
|
43
|
+
R-squared value, and residual data.
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
vox : int
|
|
48
|
+
Voxel index.
|
|
49
|
+
theevs : NDArray
|
|
50
|
+
Experimental design matrix. If 2D, dimension 0 is number of points,
|
|
51
|
+
dimension 1 is number of evs.
|
|
52
|
+
thedata : NDArray
|
|
53
|
+
Dependent variable data corresponding to the evs.
|
|
54
|
+
rt_floattype : str, optional
|
|
55
|
+
String representation of the floating-point type, default is ``np.float64``.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
tuple[int, float, float, float, float, Any, NDArray, NDArray]
|
|
60
|
+
A tuple containing:
|
|
61
|
+
- voxel index (`int`)
|
|
62
|
+
- intercept term (`float`)
|
|
63
|
+
- signed square root of R-squared (`float`)
|
|
64
|
+
- R-squared value (`float`)
|
|
65
|
+
- fit coefficients (`float` or `NDArray`)
|
|
66
|
+
- normalized fit coefficients (`Any`)
|
|
67
|
+
- data removed by fitting (`NDArray`)
|
|
68
|
+
- residuals (`NDArray`)
|
|
69
|
+
|
|
70
|
+
Notes
|
|
71
|
+
-----
|
|
72
|
+
For multivariate regressions (2D `theevs`), the function computes the fit
|
|
73
|
+
using `tide_fit.mlregress`. If the fit fails, a zero matrix is returned.
|
|
74
|
+
For univariate regressions (1D `theevs`), the function directly computes
|
|
75
|
+
the fit and handles edge cases such as zero coefficients.
|
|
76
|
+
|
|
77
|
+
Examples
|
|
78
|
+
--------
|
|
79
|
+
>>> import numpy as np
|
|
80
|
+
>>> theevs = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.float64)
|
|
81
|
+
>>> thedata = np.array([1, 2, 3], dtype=np.float64)
|
|
82
|
+
>>> result = _procOneRegressionFitItem(0, theevs, thedata)
|
|
83
|
+
>>> print(result[0]) # voxel index
|
|
84
|
+
0
|
|
85
|
+
"""
|
|
32
86
|
# NOTE: if theevs is 2D, dimension 0 is number of points, dimension 1 is number of evs
|
|
33
87
|
thefit, R2 = tide_fit.mlregress(theevs, thedata)
|
|
34
88
|
if theevs.ndim > 1:
|
|
35
89
|
if thefit is None:
|
|
36
90
|
thefit = np.matrix(np.zeros((1, theevs.shape[1] + 1), dtype=rt_floattype))
|
|
37
|
-
fitcoeffs =
|
|
91
|
+
fitcoeffs = (thefit[0, 1:]).astype(rt_floattype)
|
|
38
92
|
if fitcoeffs[0, 0] < 0.0:
|
|
39
93
|
coeffsign = -1.0
|
|
40
94
|
else:
|
|
41
95
|
coeffsign = 1.0
|
|
42
96
|
datatoremove = theevs[:, 0] * 0.0
|
|
43
97
|
for j in range(theevs.shape[1]):
|
|
44
|
-
datatoremove +=
|
|
98
|
+
datatoremove += (thefit[0, 1 + j] * theevs[:, j]).astype(rt_floattype)
|
|
45
99
|
if np.any(fitcoeffs) != 0.0:
|
|
46
100
|
pass
|
|
47
101
|
else:
|
|
48
102
|
R2 = 0.0
|
|
49
103
|
return (
|
|
50
104
|
vox,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
105
|
+
thefit[0, 0],
|
|
106
|
+
coeffsign * np.sqrt(R2),
|
|
107
|
+
R2,
|
|
54
108
|
fitcoeffs,
|
|
55
|
-
|
|
109
|
+
(thefit[0, 1:] / thefit[0, 0]).astype(rt_floattype),
|
|
56
110
|
datatoremove,
|
|
57
|
-
|
|
111
|
+
(thedata - datatoremove).astype(rt_floattype),
|
|
58
112
|
)
|
|
59
113
|
else:
|
|
60
|
-
fitcoeff =
|
|
61
|
-
datatoremove =
|
|
114
|
+
fitcoeff = (thefit[0, 1]).astype(rt_floattype)
|
|
115
|
+
datatoremove = (fitcoeff * theevs).astype(rt_floattype)
|
|
62
116
|
if fitcoeff < 0.0:
|
|
63
117
|
coeffsign = -1.0
|
|
64
118
|
else:
|
|
@@ -67,47 +121,140 @@ def _procOneRegressionFitItem(
|
|
|
67
121
|
R2 = 0.0
|
|
68
122
|
return (
|
|
69
123
|
vox,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
124
|
+
thefit[0, 0],
|
|
125
|
+
coeffsign * np.sqrt(R2),
|
|
126
|
+
R2,
|
|
73
127
|
fitcoeff,
|
|
74
|
-
|
|
128
|
+
(thefit[0, 1] / thefit[0, 0]).astype(rt_floattype),
|
|
75
129
|
datatoremove,
|
|
76
|
-
|
|
130
|
+
(thedata - datatoremove).astype(rt_floattype),
|
|
77
131
|
)
|
|
78
132
|
|
|
79
133
|
|
|
80
134
|
def linfitfiltpass(
|
|
81
|
-
numprocitems,
|
|
82
|
-
fmri_data,
|
|
83
|
-
threshval,
|
|
84
|
-
theevs,
|
|
85
|
-
meanvalue,
|
|
86
|
-
rvalue,
|
|
87
|
-
r2value,
|
|
88
|
-
fitcoeff,
|
|
89
|
-
fitNorm,
|
|
90
|
-
datatoremove,
|
|
91
|
-
filtereddata,
|
|
92
|
-
nprocs=1,
|
|
93
|
-
alwaysmultiproc=False,
|
|
94
|
-
|
|
95
|
-
confoundregress=False,
|
|
96
|
-
coefficientsonly=False,
|
|
97
|
-
procbyvoxel=True,
|
|
98
|
-
showprogressbar=True,
|
|
99
|
-
chunksize=1000,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
135
|
+
numprocitems: int,
|
|
136
|
+
fmri_data: NDArray,
|
|
137
|
+
threshval: float | None,
|
|
138
|
+
theevs: NDArray,
|
|
139
|
+
meanvalue: NDArray | None,
|
|
140
|
+
rvalue: NDArray | None,
|
|
141
|
+
r2value: NDArray,
|
|
142
|
+
fitcoeff: NDArray | None,
|
|
143
|
+
fitNorm: NDArray | None,
|
|
144
|
+
datatoremove: NDArray | None,
|
|
145
|
+
filtereddata: NDArray | None,
|
|
146
|
+
nprocs: int = 1,
|
|
147
|
+
alwaysmultiproc: bool = False,
|
|
148
|
+
constantevs: bool = False,
|
|
149
|
+
confoundregress: bool = False,
|
|
150
|
+
coefficientsonly: bool = False,
|
|
151
|
+
procbyvoxel: bool = True,
|
|
152
|
+
showprogressbar: bool = True,
|
|
153
|
+
chunksize: int = 1000,
|
|
154
|
+
rt_floattype: np.dtype = np.float64,
|
|
155
|
+
verbose: bool = True,
|
|
156
|
+
debug: bool = False,
|
|
157
|
+
) -> int:
|
|
158
|
+
"""
|
|
159
|
+
Perform linear regression fitting and filtering on fMRI data.
|
|
160
|
+
|
|
161
|
+
This function fits a linear model to fMRI data using specified experimental variables
|
|
162
|
+
and applies filtering to remove noise. It supports both voxel-wise and timepoint-wise
|
|
163
|
+
processing, with optional multiprocessing for performance.
|
|
164
|
+
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
numprocitems : int
|
|
168
|
+
Number of items to process (voxels or timepoints depending on ``procbyvoxel``).
|
|
169
|
+
fmri_data : ndarray
|
|
170
|
+
Input fMRI data array with shape ``(n_voxels, n_timepoints)`` or ``(n_timepoints, n_voxels)``.
|
|
171
|
+
threshval : float, optional
|
|
172
|
+
Threshold value for masking. If ``None``, no masking is applied.
|
|
173
|
+
theevs : ndarray
|
|
174
|
+
Experimental variables (design matrix) with shape ``(n_voxels, n_timepoints)`` or ``(n_timepoints, n_voxels)``.
|
|
175
|
+
meanvalue : ndarray, optional
|
|
176
|
+
Array to store mean values of the data. Shape depends on ``procbyvoxel``.
|
|
177
|
+
rvalue : ndarray, optional
|
|
178
|
+
Array to store correlation coefficients. Shape depends on ``procbyvoxel``.
|
|
179
|
+
r2value : ndarray
|
|
180
|
+
Array to store R-squared values. Shape depends on ``procbyvoxel``.
|
|
181
|
+
fitcoeff : ndarray, optional
|
|
182
|
+
Array to store fit coefficients. Shape depends on ``procbyvoxel`` and ``constantevs``.
|
|
183
|
+
fitNorm : ndarray, optional
|
|
184
|
+
Array to store normalized fit coefficients. Shape depends on ``procbyvoxel``.
|
|
185
|
+
datatoremove : ndarray, optional
|
|
186
|
+
Array to store data to be removed after fitting. Shape depends on ``procbyvoxel``.
|
|
187
|
+
filtereddata : ndarray
|
|
188
|
+
Array to store filtered data after regression. Shape depends on ``procbyvoxel``.
|
|
189
|
+
nprocs : int, default: 1
|
|
190
|
+
Number of processes to use for multiprocessing. If 1 and ``alwaysmultiproc`` is False, uses single-threaded processing.
|
|
191
|
+
alwaysmultiproc : bool, default: False
|
|
192
|
+
If True, always use multiprocessing even if ``nprocs`` is 1.
|
|
193
|
+
constantevs : bool, default: False
|
|
194
|
+
If True, treat experimental variables as constant across voxels/timepoints.
|
|
195
|
+
confoundregress : bool, default: False
|
|
196
|
+
If True, perform confound regression only (no output of coefficients or residuals).
|
|
197
|
+
coefficientsonly : bool, default: False
|
|
198
|
+
If True, store only regression coefficients and R-squared values.
|
|
199
|
+
procbyvoxel : bool, default: True
|
|
200
|
+
If True, process data voxel-wise; otherwise, process by timepoint.
|
|
201
|
+
showprogressbar : bool, default: True
|
|
202
|
+
If True, display a progress bar during processing.
|
|
203
|
+
chunksize : int, default: 1000
|
|
204
|
+
Size of chunks for multiprocessing.
|
|
205
|
+
rt_floattype : str, default: np.float64
|
|
206
|
+
Data type for internal floating-point calculations.
|
|
207
|
+
verbose : bool, default: True
|
|
208
|
+
If True, print verbose output.
|
|
209
|
+
debug : bool, default: False
|
|
210
|
+
If True, enable debug printing.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
int
|
|
215
|
+
Total number of items processed.
|
|
216
|
+
|
|
217
|
+
Notes
|
|
218
|
+
-----
|
|
219
|
+
- The function modifies the output arrays in-place.
|
|
220
|
+
- For ``confoundregress=True``, only ``r2value`` and ``filtereddata`` are populated.
|
|
221
|
+
- When ``coefficientsonly=True``, only ``meanvalue``, ``rvalue``, ``r2value``, ``fitcoeff``, and ``fitNorm`` are populated.
|
|
222
|
+
- If ``threshval`` is provided, a mask is generated based on mean or standard deviation of the data.
|
|
223
|
+
|
|
224
|
+
Examples
|
|
225
|
+
--------
|
|
226
|
+
>>> import numpy as np
|
|
227
|
+
>>> from typing import NDArray
|
|
228
|
+
>>> fmri_data = np.random.rand(100, 200)
|
|
229
|
+
>>> theevs = np.random.rand(100, 200)
|
|
230
|
+
>>> r2value = np.zeros(100)
|
|
231
|
+
>>> filtereddata = np.zeros_like(fmri_data)
|
|
232
|
+
>>> numprocitems = 100
|
|
233
|
+
>>> items_processed = linfitfiltpass(
|
|
234
|
+
... numprocitems=numprocitems,
|
|
235
|
+
... fmri_data=fmri_data,
|
|
236
|
+
... threshval=None,
|
|
237
|
+
... theevs=theevs,
|
|
238
|
+
... meanvalue=None,
|
|
239
|
+
... rvalue=None,
|
|
240
|
+
... r2value=r2value,
|
|
241
|
+
... fitcoeff=None,
|
|
242
|
+
... fitNorm=None,
|
|
243
|
+
... datatoremove=None,
|
|
244
|
+
... filtereddata=filtereddata,
|
|
245
|
+
... nprocs=4,
|
|
246
|
+
... procbyvoxel=True,
|
|
247
|
+
... showprogressbar=True
|
|
248
|
+
... )
|
|
249
|
+
>>> print(f"Processed {items_processed} items.")
|
|
250
|
+
"""
|
|
105
251
|
inputshape = np.shape(fmri_data)
|
|
106
252
|
if debug:
|
|
107
253
|
print(f"{numprocitems=}")
|
|
108
254
|
print(f"{fmri_data.shape=}")
|
|
109
255
|
print(f"{threshval=}")
|
|
110
|
-
print(f"{theevs.shape=}")
|
|
256
|
+
print(f"{theevs.shape=}, {np.min(theevs)=}, {np.max(theevs)=}")
|
|
257
|
+
print(f"{theevs=}")
|
|
111
258
|
if procbyvoxel:
|
|
112
259
|
indexaxis = 0
|
|
113
260
|
procunit = "voxels"
|
|
@@ -143,13 +290,12 @@ def linfitfiltpass(
|
|
|
143
290
|
|
|
144
291
|
# process and send the data
|
|
145
292
|
if procbyvoxel:
|
|
146
|
-
if confoundregress or
|
|
293
|
+
if confoundregress or constantevs:
|
|
147
294
|
outQ.put(
|
|
148
295
|
_procOneRegressionFitItem(
|
|
149
296
|
val,
|
|
150
297
|
theevs,
|
|
151
298
|
fmri_data[val, :],
|
|
152
|
-
rt_floatset=rt_floatset,
|
|
153
299
|
rt_floattype=rt_floattype,
|
|
154
300
|
)
|
|
155
301
|
)
|
|
@@ -159,18 +305,16 @@ def linfitfiltpass(
|
|
|
159
305
|
val,
|
|
160
306
|
theevs[val, :],
|
|
161
307
|
fmri_data[val, :],
|
|
162
|
-
rt_floatset=rt_floatset,
|
|
163
308
|
rt_floattype=rt_floattype,
|
|
164
309
|
)
|
|
165
310
|
)
|
|
166
311
|
else:
|
|
167
|
-
if confoundregress or
|
|
312
|
+
if confoundregress or constantevs:
|
|
168
313
|
outQ.put(
|
|
169
314
|
_procOneRegressionFitItem(
|
|
170
315
|
val,
|
|
171
316
|
theevs,
|
|
172
317
|
fmri_data[:, val],
|
|
173
|
-
rt_floatset=rt_floatset,
|
|
174
318
|
rt_floattype=rt_floattype,
|
|
175
319
|
)
|
|
176
320
|
)
|
|
@@ -180,7 +324,6 @@ def linfitfiltpass(
|
|
|
180
324
|
val,
|
|
181
325
|
theevs[:, val],
|
|
182
326
|
fmri_data[:, val],
|
|
183
|
-
rt_floatset=rt_floatset,
|
|
184
327
|
rt_floattype=rt_floattype,
|
|
185
328
|
)
|
|
186
329
|
)
|
|
@@ -214,7 +357,7 @@ def linfitfiltpass(
|
|
|
214
357
|
meanvalue[voxel[0]] = voxel[1]
|
|
215
358
|
rvalue[voxel[0]] = voxel[2]
|
|
216
359
|
r2value[voxel[0]] = voxel[3]
|
|
217
|
-
if
|
|
360
|
+
if fitcoeff.ndim > 1:
|
|
218
361
|
fitcoeff[voxel[0], :] = voxel[4]
|
|
219
362
|
fitNorm[voxel[0], :] = voxel[5]
|
|
220
363
|
else:
|
|
@@ -226,7 +369,7 @@ def linfitfiltpass(
|
|
|
226
369
|
meanvalue[voxel[0]] = voxel[1]
|
|
227
370
|
rvalue[voxel[0]] = voxel[2]
|
|
228
371
|
r2value[voxel[0]] = voxel[3]
|
|
229
|
-
if
|
|
372
|
+
if fitcoeff.ndim > 1:
|
|
230
373
|
fitcoeff[voxel[0], :] = voxel[4]
|
|
231
374
|
fitNorm[voxel[0], :] = voxel[5]
|
|
232
375
|
else:
|
|
@@ -246,7 +389,7 @@ def linfitfiltpass(
|
|
|
246
389
|
meanvalue[timepoint[0]] = timepoint[1]
|
|
247
390
|
rvalue[timepoint[0]] = timepoint[2]
|
|
248
391
|
r2value[timepoint[0]] = timepoint[3]
|
|
249
|
-
if
|
|
392
|
+
if fitcoeff.ndim > 1:
|
|
250
393
|
fitcoeff[:, timepoint[0]] = timepoint[4]
|
|
251
394
|
fitNorm[:, timepoint[0]] = timepoint[5]
|
|
252
395
|
else:
|
|
@@ -258,7 +401,7 @@ def linfitfiltpass(
|
|
|
258
401
|
meanvalue[timepoint[0]] = timepoint[1]
|
|
259
402
|
rvalue[timepoint[0]] = timepoint[2]
|
|
260
403
|
r2value[timepoint[0]] = timepoint[3]
|
|
261
|
-
if
|
|
404
|
+
if fitcoeff.ndim > 1:
|
|
262
405
|
fitcoeff[:, timepoint[0]] = timepoint[4]
|
|
263
406
|
fitNorm[:, timepoint[0]] = timepoint[5]
|
|
264
407
|
else:
|
|
@@ -270,6 +413,7 @@ def linfitfiltpass(
|
|
|
270
413
|
|
|
271
414
|
del data_out
|
|
272
415
|
else:
|
|
416
|
+
# this is the single proc path
|
|
273
417
|
itemstotal = 0
|
|
274
418
|
if procbyvoxel:
|
|
275
419
|
for vox in tqdm(
|
|
@@ -294,11 +438,10 @@ def linfitfiltpass(
|
|
|
294
438
|
vox,
|
|
295
439
|
theevs,
|
|
296
440
|
thedata,
|
|
297
|
-
rt_floatset=rt_floatset,
|
|
298
441
|
rt_floattype=rt_floattype,
|
|
299
442
|
)
|
|
300
443
|
elif coefficientsonly:
|
|
301
|
-
if
|
|
444
|
+
if not constantevs:
|
|
302
445
|
(
|
|
303
446
|
dummy,
|
|
304
447
|
meanvalue[vox],
|
|
@@ -312,7 +455,6 @@ def linfitfiltpass(
|
|
|
312
455
|
vox,
|
|
313
456
|
theevs[vox, :],
|
|
314
457
|
thedata,
|
|
315
|
-
rt_floatset=rt_floatset,
|
|
316
458
|
rt_floattype=rt_floattype,
|
|
317
459
|
)
|
|
318
460
|
else:
|
|
@@ -329,7 +471,6 @@ def linfitfiltpass(
|
|
|
329
471
|
vox,
|
|
330
472
|
theevs,
|
|
331
473
|
thedata,
|
|
332
|
-
rt_floatset=rt_floatset,
|
|
333
474
|
rt_floattype=rt_floattype,
|
|
334
475
|
)
|
|
335
476
|
else:
|
|
@@ -346,7 +487,6 @@ def linfitfiltpass(
|
|
|
346
487
|
vox,
|
|
347
488
|
theevs[vox, :],
|
|
348
489
|
thedata,
|
|
349
|
-
rt_floatset=rt_floatset,
|
|
350
490
|
rt_floattype=rt_floattype,
|
|
351
491
|
)
|
|
352
492
|
itemstotal += 1
|
|
@@ -373,26 +513,41 @@ def linfitfiltpass(
|
|
|
373
513
|
timepoint,
|
|
374
514
|
theevs,
|
|
375
515
|
thedata,
|
|
376
|
-
rt_floatset=rt_floatset,
|
|
377
516
|
rt_floattype=rt_floattype,
|
|
378
517
|
)
|
|
379
518
|
elif coefficientsonly:
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
519
|
+
if not constantevs:
|
|
520
|
+
(
|
|
521
|
+
dummy,
|
|
522
|
+
meanvalue[timepoint],
|
|
523
|
+
rvalue[timepoint],
|
|
524
|
+
r2value[timepoint],
|
|
525
|
+
fitcoeff[timepoint],
|
|
526
|
+
fitNorm[timepoint],
|
|
527
|
+
dummy,
|
|
528
|
+
dummy,
|
|
529
|
+
) = _procOneRegressionFitItem(
|
|
530
|
+
timepoint,
|
|
531
|
+
theevs[:, timepoint],
|
|
532
|
+
thedata,
|
|
533
|
+
rt_floattype=rt_floattype,
|
|
534
|
+
)
|
|
535
|
+
else:
|
|
536
|
+
(
|
|
537
|
+
dummy,
|
|
538
|
+
meanvalue[timepoint],
|
|
539
|
+
rvalue[timepoint],
|
|
540
|
+
r2value[timepoint],
|
|
541
|
+
fitcoeff[timepoint],
|
|
542
|
+
fitNorm[timepoint],
|
|
543
|
+
dummy,
|
|
544
|
+
dummy,
|
|
545
|
+
) = _procOneRegressionFitItem(
|
|
546
|
+
timepoint,
|
|
547
|
+
theevs,
|
|
548
|
+
thedata,
|
|
549
|
+
rt_floattype=rt_floattype,
|
|
550
|
+
)
|
|
396
551
|
else:
|
|
397
552
|
(
|
|
398
553
|
dummy,
|
|
@@ -407,33 +562,58 @@ def linfitfiltpass(
|
|
|
407
562
|
timepoint,
|
|
408
563
|
theevs[:, timepoint],
|
|
409
564
|
thedata,
|
|
410
|
-
rt_floatset=rt_floatset,
|
|
411
565
|
rt_floattype=rt_floattype,
|
|
412
566
|
)
|
|
567
|
+
|
|
413
568
|
itemstotal += 1
|
|
414
569
|
if showprogressbar:
|
|
415
570
|
print()
|
|
416
571
|
return itemstotal
|
|
417
572
|
|
|
418
573
|
|
|
419
|
-
def makevoxelspecificderivs(theevs, nderivs=1, debug=False):
|
|
420
|
-
|
|
421
|
-
|
|
574
|
+
def makevoxelspecificderivs(theevs: NDArray, nderivs: int = 1, debug: bool = False) -> NDArray:
|
|
575
|
+
"""
|
|
576
|
+
Perform multicomponent expansion on voxel-specific explanatory variables by computing
|
|
577
|
+
derivatives up to a specified order.
|
|
578
|
+
|
|
579
|
+
This function takes an array of voxel-specific timecourses and expands each one
|
|
580
|
+
into a set of components representing the original signal and its derivatives.
|
|
581
|
+
Each component corresponds to a higher-order derivative of the signal, scaled by
|
|
582
|
+
the inverse factorial of the derivative order (Taylor series coefficients).
|
|
422
583
|
|
|
423
584
|
Parameters
|
|
424
585
|
----------
|
|
425
586
|
theevs : 2D numpy array
|
|
426
|
-
NxP array of voxel
|
|
427
|
-
|
|
587
|
+
NxP array of voxel-specific explanatory variables, where N is the number of voxels
|
|
588
|
+
and P is the number of timepoints.
|
|
589
|
+
nderivs : int, optional
|
|
590
|
+
Number of derivative components to compute for each voxel. Default is 1.
|
|
591
|
+
If 0, the original `theevs` are returned without modification.
|
|
592
|
+
debug : bool, optional
|
|
593
|
+
If True, print debugging information including input and output shapes.
|
|
594
|
+
Default is False.
|
|
428
595
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
596
|
+
Returns
|
|
597
|
+
-------
|
|
598
|
+
3D numpy array
|
|
599
|
+
Array of shape (N, P, nderivs + 1) containing the original signal and its
|
|
600
|
+
derivatives up to order `nderivs` for each voxel. The first component is the
|
|
601
|
+
original signal, followed by the first, second, ..., up to `nderivs`-th derivative.
|
|
433
602
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
603
|
+
Notes
|
|
604
|
+
-----
|
|
605
|
+
- The function uses `numpy.gradient` to compute numerical derivatives.
|
|
606
|
+
- Each derivative component is scaled by the inverse factorial of the derivative order
|
|
607
|
+
to align with Taylor series expansion coefficients.
|
|
608
|
+
- If `nderivs=0`, the function returns a copy of the input `theevs`.
|
|
609
|
+
|
|
610
|
+
Examples
|
|
611
|
+
--------
|
|
612
|
+
>>> import numpy as np
|
|
613
|
+
>>> theevs = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
|
|
614
|
+
>>> result = makevoxelspecificderivs(theevs, nderivs=2)
|
|
615
|
+
>>> print(result.shape)
|
|
616
|
+
(2, 4, 3)
|
|
437
617
|
"""
|
|
438
618
|
if debug:
|
|
439
619
|
print(f"{theevs.shape=}")
|
|
@@ -459,19 +639,86 @@ def makevoxelspecificderivs(theevs, nderivs=1, debug=False):
|
|
|
459
639
|
|
|
460
640
|
|
|
461
641
|
def confoundregress(
|
|
462
|
-
theregressors,
|
|
463
|
-
theregressorlabels,
|
|
464
|
-
thedataarray,
|
|
465
|
-
tr,
|
|
466
|
-
nprocs=1,
|
|
467
|
-
orthogonalize=True,
|
|
468
|
-
tcstart=0,
|
|
469
|
-
tcend
|
|
470
|
-
tchp=None,
|
|
471
|
-
tclp=None,
|
|
472
|
-
showprogressbar=True,
|
|
473
|
-
debug=False,
|
|
474
|
-
):
|
|
642
|
+
theregressors: NDArray,
|
|
643
|
+
theregressorlabels: list[str],
|
|
644
|
+
thedataarray: NDArray,
|
|
645
|
+
tr: float,
|
|
646
|
+
nprocs: int = 1,
|
|
647
|
+
orthogonalize: bool = True,
|
|
648
|
+
tcstart: int = 0,
|
|
649
|
+
tcend: int = -1,
|
|
650
|
+
tchp: float | None = None,
|
|
651
|
+
tclp: float | None = None,
|
|
652
|
+
showprogressbar: bool = True,
|
|
653
|
+
debug: bool = False,
|
|
654
|
+
) -> tuple[NDArray, list[str], NDArray, NDArray]:
|
|
655
|
+
"""
|
|
656
|
+
Perform confound regression on fMRI data using linear regression.
|
|
657
|
+
|
|
658
|
+
This function applies confound regression to remove noise from fMRI time series
|
|
659
|
+
by regressing out specified confounding variables (e.g., motion parameters,
|
|
660
|
+
physiological signals). It supports optional filtering, orthogonalization of
|
|
661
|
+
regressors, and parallel processing for performance.
|
|
662
|
+
|
|
663
|
+
Parameters
|
|
664
|
+
----------
|
|
665
|
+
theregressors : ndarray
|
|
666
|
+
Array of confounding variables with shape (n_regressors, n_timepoints).
|
|
667
|
+
theregressorlabels : list of str
|
|
668
|
+
List of labels corresponding to each regressor.
|
|
669
|
+
thedataarray : ndarray
|
|
670
|
+
3D or 4D array of fMRI data with shape (n_voxels, n_timepoints) or
|
|
671
|
+
(n_voxels, n_timepoints, n_volumes).
|
|
672
|
+
tr : float
|
|
673
|
+
Repetition time (TR) in seconds.
|
|
674
|
+
nprocs : int, optional
|
|
675
|
+
Number of processes to use for parallel processing. Default is 1.
|
|
676
|
+
orthogonalize : bool, optional
|
|
677
|
+
If True, orthogonalize the regressors to reduce multicollinearity.
|
|
678
|
+
Default is True.
|
|
679
|
+
tcstart : int, optional
|
|
680
|
+
Start timepoint index for regressor data. Default is 0.
|
|
681
|
+
tcend : int, optional
|
|
682
|
+
End timepoint index for regressor data. If -1, use all timepoints
|
|
683
|
+
from `tcstart`. Default is -1.
|
|
684
|
+
tchp : float, optional
|
|
685
|
+
High-pass cutoff frequency for filtering. If None, no high-pass filtering
|
|
686
|
+
is applied.
|
|
687
|
+
tclp : float, optional
|
|
688
|
+
Low-pass cutoff frequency for filtering. If None, no low-pass filtering
|
|
689
|
+
is applied.
|
|
690
|
+
showprogressbar : bool, optional
|
|
691
|
+
If True, display a progress bar during processing. Default is True.
|
|
692
|
+
debug : bool, optional
|
|
693
|
+
If True, enable debug output. Default is False.
|
|
694
|
+
|
|
695
|
+
Returns
|
|
696
|
+
-------
|
|
697
|
+
tuple of (NDArray, list of str, NDArray, NDArray)
|
|
698
|
+
- `theregressors`: Processed regressors (possibly orthogonalized).
|
|
699
|
+
- `theregressorlabels`: Updated labels for the regressors.
|
|
700
|
+
- `filtereddata`: Data with confounds removed.
|
|
701
|
+
- `r2value`: R-squared values for each voxel (or None if not computed).
|
|
702
|
+
|
|
703
|
+
Notes
|
|
704
|
+
-----
|
|
705
|
+
- The function applies standard deviation normalization to regressors for
|
|
706
|
+
numerical stability.
|
|
707
|
+
- If `orthogonalize` is True, Gram-Schmidt orthogonalization is applied to
|
|
708
|
+
the regressors.
|
|
709
|
+
- Filtering is applied using a trapezoidal filter if `tchp` or `tclp` are provided.
|
|
710
|
+
- The function uses `linfitfiltpass` internally for the actual regression.
|
|
711
|
+
|
|
712
|
+
Examples
|
|
713
|
+
--------
|
|
714
|
+
>>> regressors = np.random.rand(3, 100)
|
|
715
|
+
>>> labels = ['motion_x', 'motion_y', 'motion_z']
|
|
716
|
+
>>> data = np.random.rand(50, 100)
|
|
717
|
+
>>> tr = 2.0
|
|
718
|
+
>>> processed_regressors, labels, filtered_data, r2 = confoundregress(
|
|
719
|
+
... regressors, labels, data, tr, nprocs=4
|
|
720
|
+
... )
|
|
721
|
+
"""
|
|
475
722
|
if tcend == -1:
|
|
476
723
|
theregressors = theregressors[:, tcstart:]
|
|
477
724
|
else:
|