rapidtide 3.0.2__py3-none-any.whl → 3.0.3__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/calcsimfunc.py +3 -0
- rapidtide/correlate.py +18 -1
- rapidtide/data/examples/src/testfmri +7 -4
- rapidtide/data/examples/src/testretro +10 -4
- rapidtide/helper_classes.py +4 -4
- rapidtide/io.py +2 -0
- rapidtide/maskutil.py +144 -0
- rapidtide/tests/test_cleanregressor.py +185 -0
- rapidtide/tests/test_fullrunrapidtide_v1.py +4 -0
- rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
- rapidtide/tests/test_io.py +58 -13
- rapidtide/voxelData.py +1 -0
- rapidtide/workflows/cleanregressor.py +43 -6
- rapidtide/workflows/rapidtide.py +239 -106
- rapidtide/workflows/rapidtide_parser.py +115 -66
- rapidtide/workflows/retroregress.py +170 -34
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/METADATA +1 -1
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/RECORD +22 -20
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/WHEEL +1 -1
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/entry_points.txt +0 -0
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/licenses/LICENSE +0 -0
- {rapidtide-3.0.2.dist-info → rapidtide-3.0.3.dist-info}/top_level.txt +0 -0
rapidtide/calcsimfunc.py
CHANGED
|
@@ -69,6 +69,7 @@ def correlationpass(
|
|
|
69
69
|
chunksize=1000,
|
|
70
70
|
rt_floatset=np.float64,
|
|
71
71
|
rt_floattype="float64",
|
|
72
|
+
debug=False,
|
|
72
73
|
):
|
|
73
74
|
"""
|
|
74
75
|
|
|
@@ -96,6 +97,8 @@ def correlationpass(
|
|
|
96
97
|
-------
|
|
97
98
|
|
|
98
99
|
"""
|
|
100
|
+
if debug:
|
|
101
|
+
print(f"calling setreftc in calcsimfunc with length {len(referencetc)}")
|
|
99
102
|
theCorrelator.setreftc(referencetc)
|
|
100
103
|
theCorrelator.setlimits(lagmininpts, lagmaxinpts)
|
|
101
104
|
|
rapidtide/correlate.py
CHANGED
|
@@ -86,11 +86,12 @@ def disablenumba():
|
|
|
86
86
|
def check_autocorrelation(
|
|
87
87
|
corrscale,
|
|
88
88
|
thexcorr,
|
|
89
|
-
delta=0.
|
|
89
|
+
delta=0.05,
|
|
90
90
|
acampthresh=0.1,
|
|
91
91
|
aclagthresh=10.0,
|
|
92
92
|
displayplots=False,
|
|
93
93
|
detrendorder=1,
|
|
94
|
+
debug=False,
|
|
94
95
|
):
|
|
95
96
|
"""Check for autocorrelation in an array.
|
|
96
97
|
|
|
@@ -110,10 +111,23 @@ def check_autocorrelation(
|
|
|
110
111
|
sidelobetime
|
|
111
112
|
sidelobeamp
|
|
112
113
|
"""
|
|
114
|
+
if debug:
|
|
115
|
+
print("check_autocorrelation:")
|
|
116
|
+
print(f"delta: {delta}")
|
|
117
|
+
print(f"acampthresh: {acampthresh}")
|
|
118
|
+
print(f"aclagthresh: {aclagthresh}")
|
|
119
|
+
print(f"displayplots: {displayplots}")
|
|
113
120
|
lookahead = 2
|
|
121
|
+
if displayplots:
|
|
122
|
+
print(f"check_autocorrelation: {displayplots=}")
|
|
123
|
+
plt.plot(corrscale, thexcorr)
|
|
124
|
+
plt.show()
|
|
114
125
|
peaks = tide_fit.peakdetect(thexcorr, x_axis=corrscale, delta=delta, lookahead=lookahead)
|
|
115
126
|
maxpeaks = np.asarray(peaks[0], dtype="float64")
|
|
116
127
|
if len(peaks[0]) > 0:
|
|
128
|
+
if debug:
|
|
129
|
+
print(f"found {len(peaks[0])} peaks")
|
|
130
|
+
print(peaks)
|
|
117
131
|
LGR.debug(peaks)
|
|
118
132
|
zeropkindex = np.argmin(abs(maxpeaks[:, 0]))
|
|
119
133
|
for i in range(zeropkindex + 1, maxpeaks.shape[0]):
|
|
@@ -155,6 +169,9 @@ def check_autocorrelation(
|
|
|
155
169
|
)
|
|
156
170
|
plt.show()
|
|
157
171
|
return sidelobetime, sidelobeamp
|
|
172
|
+
else:
|
|
173
|
+
if debug:
|
|
174
|
+
print("no peaks found")
|
|
158
175
|
return None, None
|
|
159
176
|
|
|
160
177
|
|
|
@@ -5,8 +5,11 @@ rapidtide \
|
|
|
5
5
|
--nprocs -1 \
|
|
6
6
|
--searchrange -5 20 \
|
|
7
7
|
--simcalcrange 50 -1 \
|
|
8
|
-
--outputlevel
|
|
9
|
-
--
|
|
8
|
+
--outputlevel more \
|
|
9
|
+
--dofinalrefine \
|
|
10
|
+
--graymattermask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_GRAY \
|
|
11
|
+
--brainmask sub-RAPIDTIDETEST_brainmask.nii.gz \
|
|
12
|
+
--whitemattermask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_WHITE \
|
|
13
|
+
--csfmask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_CSF \
|
|
10
14
|
sub-RAPIDTIDETEST.nii.gz \
|
|
11
|
-
../dst/sub-
|
|
12
|
-
|
|
15
|
+
../dst/sub-RAPIDTIDETEST
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
3
|
rapidtide \
|
|
4
|
+
--spatialfilt -1 \
|
|
4
5
|
--nprocs -1 \
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--
|
|
6
|
+
--searchrange -5 20 \
|
|
7
|
+
--simcalcrange 50 -1 \
|
|
8
|
+
--outputlevel more \
|
|
9
|
+
--dofinalrefine \
|
|
10
|
+
--graymattermask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_GRAY \
|
|
11
|
+
--brainmask sub-RAPIDTIDETEST_brainmask.nii.gz \
|
|
12
|
+
--whitemattermask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_WHITE \
|
|
13
|
+
--csfmask sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_CSF \
|
|
8
14
|
sub-RAPIDTIDETEST.nii.gz \
|
|
9
15
|
../dst/sub-RAPIDTIDETEST
|
|
10
16
|
|
|
@@ -15,7 +21,7 @@ retroregress \
|
|
|
15
21
|
../dst/sub-RAPIDTIDETEST \
|
|
16
22
|
--alternateoutput ../dst/specialtest \
|
|
17
23
|
--nprocs -1 \
|
|
18
|
-
--outputlevel
|
|
24
|
+
--outputlevel normal
|
|
19
25
|
|
|
20
26
|
#retroregress sub-RAPIDTIDETEST.nii.gz ../dst/sub-RAPIDTIDETEST --alternateoutput ../dst/0deriv_refined --nprocs -1 --regressderivs 0 --makepseudofile --outputlevel max --refinedelay --nofilterwithrefineddelay
|
|
21
27
|
#retroregress sub-RAPIDTIDETEST.nii.gz ../dst/sub-RAPIDTIDETEST --alternateoutput ../dst/0deriv_refinedfit --nprocs -1 --regressderivs 0 --makepseudofile --outputlevel max --refinedelay
|
rapidtide/helper_classes.py
CHANGED
|
@@ -310,7 +310,7 @@ class MutualInformationator(SimilarityFunctionator):
|
|
|
310
310
|
def run(self, thetc, locs=None, trim=True, gettimeaxis=True):
|
|
311
311
|
if len(thetc) != len(self.reftc):
|
|
312
312
|
print(
|
|
313
|
-
"timecourses are of different sizes:",
|
|
313
|
+
"MutualInformationator: timecourses are of different sizes:",
|
|
314
314
|
len(thetc),
|
|
315
315
|
"!=",
|
|
316
316
|
len(self.reftc),
|
|
@@ -434,7 +434,7 @@ class Correlator(SimilarityFunctionator):
|
|
|
434
434
|
def run(self, thetc, trim=True):
|
|
435
435
|
if len(thetc) != len(self.reftc):
|
|
436
436
|
print(
|
|
437
|
-
"timecourses are of different sizes:",
|
|
437
|
+
"Correlator: timecourses are of different sizes:",
|
|
438
438
|
len(thetc),
|
|
439
439
|
"!=",
|
|
440
440
|
len(self.reftc),
|
|
@@ -580,7 +580,7 @@ class Coherer:
|
|
|
580
580
|
def run(self, thetc, trim=True, alt=False):
|
|
581
581
|
if len(thetc) != len(self.reftc):
|
|
582
582
|
print(
|
|
583
|
-
"timecourses are of different sizes:",
|
|
583
|
+
"Coherer: timecourses are of different sizes:",
|
|
584
584
|
len(thetc),
|
|
585
585
|
"!=",
|
|
586
586
|
len(self.reftc),
|
|
@@ -1076,7 +1076,7 @@ class SimilarityFunctionFitter:
|
|
|
1076
1076
|
maxval_init = 0.0
|
|
1077
1077
|
if self.debug:
|
|
1078
1078
|
print("bad initial amp:", maxval_init, "is less than 0.0")
|
|
1079
|
-
if maxval_init > 1.0:
|
|
1079
|
+
if (maxval_init > 1.0) and self.enforcethresh:
|
|
1080
1080
|
failreason |= self.FML_INITAMPHIGH
|
|
1081
1081
|
maxval_init = 1.0
|
|
1082
1082
|
if self.debug:
|
rapidtide/io.py
CHANGED
|
@@ -1996,12 +1996,14 @@ def colspectolist(colspec, debug=False):
|
|
|
1996
1996
|
("APARC_CORTGRAY", "1000-1035,2000-2035"),
|
|
1997
1997
|
("APARC_GRAY", "8-13,17-20,26-28,47-56,58-60,96,97,1000-1035,2000-2035"),
|
|
1998
1998
|
("APARC_WHITE", "2,7,41,46,177,219,3000-3035,4000-4035,5001,5002"),
|
|
1999
|
+
("APARC_CSF", "4,5,14,15,24,31,43,44,63,72"),
|
|
1999
2000
|
(
|
|
2000
2001
|
"APARC_ALLBUTCSF",
|
|
2001
2002
|
"2,7-13,17-20,26-28,41,46-56,58-60,96,97,177,219,1000-1035,2000-2035,3000-3035,4000-4035,5001,5002",
|
|
2002
2003
|
),
|
|
2003
2004
|
("SSEG_GRAY", "3,8,10-13,16-18,26,42,47,49-54,58"),
|
|
2004
2005
|
("SSEG_WHITE", "2,7,41,46"),
|
|
2006
|
+
("SSEG_CSF", "4,5,14,15,24,43,44"),
|
|
2005
2007
|
)
|
|
2006
2008
|
preprocessedranges = []
|
|
2007
2009
|
for thisrange in theranges:
|
rapidtide/maskutil.py
CHANGED
|
@@ -21,8 +21,10 @@ import logging
|
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
from nilearn import masking
|
|
24
|
+
from sklearn.decomposition import PCA
|
|
24
25
|
|
|
25
26
|
import rapidtide.io as tide_io
|
|
27
|
+
import rapidtide.miscmath as tide_math
|
|
26
28
|
import rapidtide.stats as tide_stats
|
|
27
29
|
|
|
28
30
|
LGR = logging.getLogger("GENERAL")
|
|
@@ -67,8 +69,16 @@ def readamask(
|
|
|
67
69
|
thresh=None,
|
|
68
70
|
maskname="the",
|
|
69
71
|
tolerance=1.0e-3,
|
|
72
|
+
debug=False,
|
|
70
73
|
):
|
|
71
74
|
LGR.debug(f"readamask called with filename: {maskfilename} vals: {valslist}")
|
|
75
|
+
if debug:
|
|
76
|
+
print("getmaskset:")
|
|
77
|
+
print(f"{maskname=}")
|
|
78
|
+
print(f"\tincludefilename={maskfilename}")
|
|
79
|
+
print(f"\tincludevals={valslist}")
|
|
80
|
+
print(f"\t{istext=}")
|
|
81
|
+
print(f"\t{tolerance=}")
|
|
72
82
|
if istext:
|
|
73
83
|
maskarray = tide_io.readvecs(maskfilename).astype("uint16")
|
|
74
84
|
theshape = np.shape(maskarray)
|
|
@@ -109,11 +119,24 @@ def getmaskset(
|
|
|
109
119
|
extramaskthresh=0.1,
|
|
110
120
|
istext=False,
|
|
111
121
|
tolerance=1.0e-3,
|
|
122
|
+
debug=False,
|
|
112
123
|
):
|
|
113
124
|
internalincludemask = None
|
|
114
125
|
internalexcludemask = None
|
|
115
126
|
internalextramask = None
|
|
116
127
|
|
|
128
|
+
if debug:
|
|
129
|
+
print("getmaskset:")
|
|
130
|
+
print(f"{maskname=}")
|
|
131
|
+
print(f"\t{includename=}")
|
|
132
|
+
print(f"\t{includevals=}")
|
|
133
|
+
print(f"\t{excludename=}")
|
|
134
|
+
print(f"\t{excludevals=}")
|
|
135
|
+
print(f"\t{istext=}")
|
|
136
|
+
print(f"\t{tolerance=}")
|
|
137
|
+
print(f"\t{extramask=}")
|
|
138
|
+
print(f"\t{extramaskthresh=}")
|
|
139
|
+
|
|
117
140
|
if includename is not None:
|
|
118
141
|
LGR.info(f"constructing {maskname} include mask")
|
|
119
142
|
theincludemask = readamask(
|
|
@@ -178,3 +201,124 @@ def getmaskset(
|
|
|
178
201
|
)
|
|
179
202
|
|
|
180
203
|
return internalincludemask, internalexcludemask, internalextramask
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def getregionsignal(
|
|
207
|
+
indata,
|
|
208
|
+
filter=None,
|
|
209
|
+
Fs=1.0,
|
|
210
|
+
includemask=None,
|
|
211
|
+
excludemask=None,
|
|
212
|
+
signalgenmethod="sum",
|
|
213
|
+
pcacomponents=0.8,
|
|
214
|
+
signame="global mean",
|
|
215
|
+
rt_floatset=np.float64,
|
|
216
|
+
debug=False,
|
|
217
|
+
):
|
|
218
|
+
# Start with all voxels
|
|
219
|
+
themask = indata[:, 0] * 0 + 1
|
|
220
|
+
|
|
221
|
+
# modify the mask if needed
|
|
222
|
+
if includemask is not None:
|
|
223
|
+
themask = themask * includemask
|
|
224
|
+
if excludemask is not None:
|
|
225
|
+
themask = themask * (1 - excludemask)
|
|
226
|
+
|
|
227
|
+
# combine all the voxels using one of the three methods
|
|
228
|
+
globalmean = rt_floatset(indata[0, :])
|
|
229
|
+
thesize = np.shape(themask)
|
|
230
|
+
numvoxelsused = int(np.sum(np.where(themask > 0.0, 1, 0)))
|
|
231
|
+
selectedvoxels = indata[np.where(themask > 0.0), :][0]
|
|
232
|
+
if debug:
|
|
233
|
+
print(f"getregionsignal: {selectedvoxels.shape=}")
|
|
234
|
+
LGR.info(f"constructing global mean signal using {signalgenmethod}")
|
|
235
|
+
if signalgenmethod == "sum":
|
|
236
|
+
globalmean = np.mean(selectedvoxels, axis=0)
|
|
237
|
+
globalmean -= np.mean(globalmean)
|
|
238
|
+
elif signalgenmethod == "meanscale":
|
|
239
|
+
themean = np.mean(indata, axis=1)
|
|
240
|
+
for vox in range(0, thesize[0]):
|
|
241
|
+
if themask[vox] > 0.0:
|
|
242
|
+
if themean[vox] != 0.0:
|
|
243
|
+
globalmean += indata[vox, :] / themean[vox] - 1.0
|
|
244
|
+
elif signalgenmethod == "pca":
|
|
245
|
+
themean = np.mean(indata, axis=1)
|
|
246
|
+
thevar = np.var(indata, axis=1)
|
|
247
|
+
scaledvoxels = selectedvoxels * 0.0
|
|
248
|
+
for vox in range(0, selectedvoxels.shape[0]):
|
|
249
|
+
scaledvoxels[vox, :] = selectedvoxels[vox, :] - themean[vox]
|
|
250
|
+
if thevar[vox] > 0.0:
|
|
251
|
+
scaledvoxels[vox, :] = selectedvoxels[vox, :] / thevar[vox]
|
|
252
|
+
try:
|
|
253
|
+
thefit = PCA(n_components=pcacomponents).fit(np.transpose(scaledvoxels))
|
|
254
|
+
except ValueError:
|
|
255
|
+
if pcacomponents == "mle":
|
|
256
|
+
LGR.warning("mle estimation failed - falling back to pcacomponents=0.8")
|
|
257
|
+
thefit = PCA(n_components=0.8).fit(np.transpose(scaledvoxels))
|
|
258
|
+
else:
|
|
259
|
+
raise ValueError("unhandled math exception in PCA refinement - exiting")
|
|
260
|
+
|
|
261
|
+
varex = 100.0 * np.cumsum(thefit.explained_variance_ratio_)[len(thefit.components_) - 1]
|
|
262
|
+
thetransform = thefit.transform(np.transpose(scaledvoxels))
|
|
263
|
+
if debug:
|
|
264
|
+
print(f"getregionsignal: {thetransform.shape=}")
|
|
265
|
+
globalmean = np.mean(thetransform, axis=0)
|
|
266
|
+
globalmean -= np.mean(globalmean)
|
|
267
|
+
if debug:
|
|
268
|
+
print(f"getregionsignal: {varex=}")
|
|
269
|
+
LGR.info(
|
|
270
|
+
f"Using {len(thefit.components_)} component(s), accounting for "
|
|
271
|
+
f"{varex:.2f}% of the variance"
|
|
272
|
+
)
|
|
273
|
+
elif signalgenmethod == "random":
|
|
274
|
+
globalmean = np.random.standard_normal(size=len(globalmean))
|
|
275
|
+
else:
|
|
276
|
+
raise ValueError(f"illegal signal generation method: {signalgenmethod}")
|
|
277
|
+
LGR.info(f"used {numvoxelsused} voxels to calculate {signame} signal")
|
|
278
|
+
if filter is not None:
|
|
279
|
+
globalmean = filter.apply(Fs, globalmean)
|
|
280
|
+
if debug:
|
|
281
|
+
print(f"getregionsignal: {globalmean=}")
|
|
282
|
+
return tide_math.stdnormalize(globalmean), themask
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def saveregionaltimeseries(
|
|
286
|
+
tcdesc,
|
|
287
|
+
tcname,
|
|
288
|
+
fmridata,
|
|
289
|
+
includemask,
|
|
290
|
+
fmrifreq,
|
|
291
|
+
outputname,
|
|
292
|
+
filter=None,
|
|
293
|
+
initfile=False,
|
|
294
|
+
excludemask=None,
|
|
295
|
+
filedesc="regional",
|
|
296
|
+
suffix="",
|
|
297
|
+
signalgenmethod="sum",
|
|
298
|
+
pcacomponents=0.8,
|
|
299
|
+
rt_floatset=np.float64,
|
|
300
|
+
debug=False,
|
|
301
|
+
):
|
|
302
|
+
thetimecourse, themask = getregionsignal(
|
|
303
|
+
fmridata,
|
|
304
|
+
filter=filter,
|
|
305
|
+
Fs=fmrifreq,
|
|
306
|
+
includemask=includemask,
|
|
307
|
+
excludemask=excludemask,
|
|
308
|
+
signalgenmethod=signalgenmethod,
|
|
309
|
+
pcacomponents=pcacomponents,
|
|
310
|
+
signame=tcdesc,
|
|
311
|
+
rt_floatset=rt_floatset,
|
|
312
|
+
debug=debug,
|
|
313
|
+
)
|
|
314
|
+
tide_io.writebidstsv(
|
|
315
|
+
f"{outputname}_desc-{filedesc}_timeseries",
|
|
316
|
+
thetimecourse,
|
|
317
|
+
fmrifreq,
|
|
318
|
+
columns=[f"{tcname}{suffix}"],
|
|
319
|
+
extraheaderinfo={
|
|
320
|
+
"Description": "Regional timecourse averages",
|
|
321
|
+
},
|
|
322
|
+
append=(not initfile),
|
|
323
|
+
)
|
|
324
|
+
return thetimecourse, themask
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2016-2025 Blaise Frederick
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
import matplotlib as mpl
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
import rapidtide.filter as tide_filt
|
|
25
|
+
import rapidtide.helper_classes as tide_classes
|
|
26
|
+
import rapidtide.miscmath as tide_math
|
|
27
|
+
import rapidtide.resample as tide_resample
|
|
28
|
+
import rapidtide.workflows.cleanregressor as tide_cleanregressor
|
|
29
|
+
from rapidtide.tests.utils import get_examples_path, get_test_temp_path, mse
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_cleanregressor(debug=False, local=False, displayplots=False):
|
|
33
|
+
# set input and output directories
|
|
34
|
+
if local:
|
|
35
|
+
exampleroot = "../data/examples/src"
|
|
36
|
+
testtemproot = "./tmp"
|
|
37
|
+
else:
|
|
38
|
+
exampleroot = get_examples_path()
|
|
39
|
+
testtemproot = get_test_temp_path()
|
|
40
|
+
|
|
41
|
+
outputname = os.path.join(testtemproot, "cleanregressortest")
|
|
42
|
+
thepass = 1
|
|
43
|
+
padtrs = 30
|
|
44
|
+
fmrifreq = 1.0
|
|
45
|
+
oversampfac = 2
|
|
46
|
+
oversampfreq = oversampfac * fmrifreq
|
|
47
|
+
theprefilter = tide_filt.NoncausalFilter("lfo")
|
|
48
|
+
lagmin = -30
|
|
49
|
+
lagmax = 30
|
|
50
|
+
lagmininpts = int((lagmin * oversampfreq) - 0.5)
|
|
51
|
+
lagmaxinpts = int((lagmax * oversampfreq) + 0.5)
|
|
52
|
+
lagmod = 1000.0
|
|
53
|
+
noiseamp = 0.25
|
|
54
|
+
detrendorder = 3
|
|
55
|
+
windowfunc = "hamming"
|
|
56
|
+
|
|
57
|
+
tclen = 500
|
|
58
|
+
osvalidsimcalcstart = 0
|
|
59
|
+
osvalidsimcalcend = tclen * oversampfac
|
|
60
|
+
|
|
61
|
+
theCorrelator = tide_classes.Correlator(
|
|
62
|
+
Fs=oversampfreq,
|
|
63
|
+
ncprefilter=theprefilter,
|
|
64
|
+
detrendorder=1,
|
|
65
|
+
windowfunc="hamming",
|
|
66
|
+
corrweighting="phat",
|
|
67
|
+
)
|
|
68
|
+
theFitter = tide_classes.SimilarityFunctionFitter(
|
|
69
|
+
lagmod=lagmod,
|
|
70
|
+
lagmin=lagmin,
|
|
71
|
+
lagmax=lagmax,
|
|
72
|
+
debug=debug,
|
|
73
|
+
allowhighfitamps=True,
|
|
74
|
+
enforcethresh=False,
|
|
75
|
+
zerooutbadfit=False,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# make a reference timecourse
|
|
79
|
+
rng = np.random.default_rng(seed=1234)
|
|
80
|
+
basewave = theprefilter.apply(fmrifreq, rng.normal(loc=0.0, scale=1.0, size=tclen))
|
|
81
|
+
noisewave = rng.normal(loc=0.0, scale=noiseamp, size=tclen)
|
|
82
|
+
theparamsets = [
|
|
83
|
+
[2.0, 0.0, False, 0],
|
|
84
|
+
[2.5, 0.8, True, 0],
|
|
85
|
+
[5.0, 0.5, True, 0],
|
|
86
|
+
[7.5, 0.25, True, 100],
|
|
87
|
+
[10.0, 0.1, True, 0],
|
|
88
|
+
]
|
|
89
|
+
for paramset in theparamsets:
|
|
90
|
+
echotime = paramset[0]
|
|
91
|
+
echoamp = paramset[1]
|
|
92
|
+
check_autocorrelation = paramset[2]
|
|
93
|
+
osvalidsimcalcstart = paramset[3]
|
|
94
|
+
if debug:
|
|
95
|
+
print(
|
|
96
|
+
"**********Start******************************************************************"
|
|
97
|
+
)
|
|
98
|
+
print(f"{echotime=}, {echoamp=}, {check_autocorrelation=}, {osvalidsimcalcstart=}")
|
|
99
|
+
print(
|
|
100
|
+
"*********************************************************************************"
|
|
101
|
+
)
|
|
102
|
+
theechotc, dummy, dummy, dummy = tide_resample.timeshift(
|
|
103
|
+
basewave, echotime * oversampfreq, padtrs, doplot=displayplots, debug=debug
|
|
104
|
+
)
|
|
105
|
+
resampnonosref_y = basewave + echoamp * theechotc + noisewave
|
|
106
|
+
resampref_y = tide_resample.upsample(resampnonosref_y, fmrifreq, oversampfreq)
|
|
107
|
+
theCorrelator.setreftc(resampnonosref_y)
|
|
108
|
+
referencetc = tide_math.corrnormalize(
|
|
109
|
+
resampref_y[osvalidsimcalcstart:],
|
|
110
|
+
detrendorder=detrendorder,
|
|
111
|
+
windowfunc=windowfunc,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
resampref_y = tide_resample.upsample(resampnonosref_y, fmrifreq, oversampfreq)
|
|
115
|
+
|
|
116
|
+
(
|
|
117
|
+
cleaned_resampref_y,
|
|
118
|
+
cleaned_referencetc,
|
|
119
|
+
cleaned_nonosreferencetc,
|
|
120
|
+
despeckle_thresh,
|
|
121
|
+
sidelobeamp,
|
|
122
|
+
sidelobetime,
|
|
123
|
+
lagmod,
|
|
124
|
+
acwidth,
|
|
125
|
+
absmaxsigma,
|
|
126
|
+
) = tide_cleanregressor.cleanregressor(
|
|
127
|
+
outputname,
|
|
128
|
+
thepass,
|
|
129
|
+
referencetc,
|
|
130
|
+
resampref_y,
|
|
131
|
+
resampnonosref_y,
|
|
132
|
+
fmrifreq,
|
|
133
|
+
oversampfreq,
|
|
134
|
+
osvalidsimcalcstart,
|
|
135
|
+
osvalidsimcalcend,
|
|
136
|
+
lagmininpts,
|
|
137
|
+
lagmaxinpts,
|
|
138
|
+
theFitter,
|
|
139
|
+
theCorrelator,
|
|
140
|
+
lagmin,
|
|
141
|
+
lagmax,
|
|
142
|
+
LGR=None,
|
|
143
|
+
check_autocorrelation=check_autocorrelation,
|
|
144
|
+
fix_autocorrelation=True,
|
|
145
|
+
despeckle_thresh=5.0,
|
|
146
|
+
lthreshval=0.0,
|
|
147
|
+
fixdelay=False,
|
|
148
|
+
detrendorder=detrendorder,
|
|
149
|
+
windowfunc=windowfunc,
|
|
150
|
+
respdelete=False,
|
|
151
|
+
displayplots=displayplots,
|
|
152
|
+
debug=debug,
|
|
153
|
+
rt_floattype="float64",
|
|
154
|
+
rt_floatset=np.float64,
|
|
155
|
+
)
|
|
156
|
+
print(f"\t{len(referencetc)=}")
|
|
157
|
+
print(f"\t{len(resampref_y)=}")
|
|
158
|
+
print(f"\t{len(resampnonosref_y)=}")
|
|
159
|
+
print(f"\t{len(cleaned_resampref_y)=}")
|
|
160
|
+
print(f"\t{len(cleaned_referencetc)=}")
|
|
161
|
+
print(f"\t{len(cleaned_nonosreferencetc)=}")
|
|
162
|
+
print(f"\t{check_autocorrelation=}")
|
|
163
|
+
print(f"\t{despeckle_thresh=}")
|
|
164
|
+
print(f"\t{sidelobeamp=}")
|
|
165
|
+
print(f"\t{sidelobetime=}")
|
|
166
|
+
print(f"\t{lagmod=}")
|
|
167
|
+
print(f"\t{acwidth=}")
|
|
168
|
+
print(f"\t{absmaxsigma=}")
|
|
169
|
+
assert len(referencetc) == len(cleaned_referencetc)
|
|
170
|
+
assert len(resampref_y) == len(cleaned_resampref_y)
|
|
171
|
+
assert len(resampnonosref_y) == len(cleaned_nonosreferencetc)
|
|
172
|
+
|
|
173
|
+
if debug:
|
|
174
|
+
print(
|
|
175
|
+
"*********************************************************************************"
|
|
176
|
+
)
|
|
177
|
+
print(f"{echotime=}, {echoamp=}, {check_autocorrelation=}, {osvalidsimcalcstart=}")
|
|
178
|
+
print(
|
|
179
|
+
"**************End****************************************************************"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
mpl.use("TkAgg")
|
|
185
|
+
test_cleanregressor(debug=True, local=True, displayplots=True)
|
|
@@ -23,6 +23,7 @@ import matplotlib as mpl
|
|
|
23
23
|
import rapidtide.qualitycheck as rapidtide_quality
|
|
24
24
|
import rapidtide.workflows.rapidtide as rapidtide_workflow
|
|
25
25
|
import rapidtide.workflows.rapidtide_parser as rapidtide_parser
|
|
26
|
+
import rapidtide.workflows.retroregress as rapidtide_retroregress
|
|
26
27
|
from rapidtide.tests.utils import get_examples_path, get_test_temp_path
|
|
27
28
|
|
|
28
29
|
|
|
@@ -56,6 +57,8 @@ def test_fullrunrapidtide_v1(debug=False, local=False, displayplots=False):
|
|
|
56
57
|
rapidtide_workflow.rapidtide_main(rapidtide_parser.process_args(inputargs=inputargs))
|
|
57
58
|
rapidtide_quality.qualitycheck(os.path.join(testtemproot, "sub-RAPIDTIDETEST1"))
|
|
58
59
|
|
|
60
|
+
|
|
61
|
+
# test fixval
|
|
59
62
|
inputargs = [
|
|
60
63
|
os.path.join(exampleroot, "sub-RAPIDTIDETEST.nii.gz"),
|
|
61
64
|
os.path.join(testtemproot, "sub-RAPIDTIDETEST1_fixval"),
|
|
@@ -77,6 +80,7 @@ def test_fullrunrapidtide_v1(debug=False, local=False, displayplots=False):
|
|
|
77
80
|
]
|
|
78
81
|
rapidtide_workflow.rapidtide_main(rapidtide_parser.process_args(inputargs=inputargs))
|
|
79
82
|
|
|
83
|
+
# test fixmap
|
|
80
84
|
inputargs = [
|
|
81
85
|
os.path.join(exampleroot, "sub-RAPIDTIDETEST.nii.gz"),
|
|
82
86
|
os.path.join(testtemproot, "sub-RAPIDTIDETEST1_fixmap"),
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2016-2025 Blaise Frederick
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
import matplotlib as mpl
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
import rapidtide.io as tide_io
|
|
25
|
+
import rapidtide.workflows.rapidtide as rapidtide_workflow
|
|
26
|
+
import rapidtide.workflows.rapidtide_parser as rapidtide_parser
|
|
27
|
+
import rapidtide.workflows.retroregress as rapidtide_retroregress
|
|
28
|
+
from rapidtide.tests.utils import get_examples_path, get_test_temp_path, mse
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_fullrunrapidtide_v7(debug=False, local=False, displayplots=False):
|
|
32
|
+
# set input and output directories
|
|
33
|
+
if local:
|
|
34
|
+
exampleroot = "../data/examples/src"
|
|
35
|
+
testtemproot = "./tmp"
|
|
36
|
+
else:
|
|
37
|
+
exampleroot = get_examples_path()
|
|
38
|
+
testtemproot = get_test_temp_path()
|
|
39
|
+
|
|
40
|
+
# test anatomic masks
|
|
41
|
+
inputargs = [
|
|
42
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST.nii.gz"),
|
|
43
|
+
os.path.join(testtemproot, "sub-RAPIDTIDETEST_seg"),
|
|
44
|
+
"--nprocs",
|
|
45
|
+
"-1",
|
|
46
|
+
"--passes",
|
|
47
|
+
"3",
|
|
48
|
+
"--brainmask",
|
|
49
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST_brainmask.nii.gz"),
|
|
50
|
+
"--graymattermask",
|
|
51
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_GRAY"),
|
|
52
|
+
"--whitemattermask",
|
|
53
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_WHITE"),
|
|
54
|
+
"--csfmask",
|
|
55
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST_synthseg.nii.gz:SSEG_CSF"),
|
|
56
|
+
]
|
|
57
|
+
rapidtide_workflow.rapidtide_main(rapidtide_parser.process_args(inputargs=inputargs))
|
|
58
|
+
|
|
59
|
+
inputargs = [
|
|
60
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST.nii.gz"),
|
|
61
|
+
os.path.join(testtemproot, "sub-RAPIDTIDETEST_seg"),
|
|
62
|
+
"--alternateoutput",
|
|
63
|
+
os.path.join(testtemproot, "segtest"),
|
|
64
|
+
"--nprocs",
|
|
65
|
+
"-1",
|
|
66
|
+
"--outputlevel",
|
|
67
|
+
"max",
|
|
68
|
+
]
|
|
69
|
+
rapidtide_retroregress.retroregress(rapidtide_retroregress.process_args(inputargs=inputargs))
|
|
70
|
+
|
|
71
|
+
inputargs = [
|
|
72
|
+
os.path.join(exampleroot, "sub-RAPIDTIDETEST.nii.gz"),
|
|
73
|
+
os.path.join(testtemproot, "sub-RAPIDTIDETEST_seg"),
|
|
74
|
+
"--alternateoutput",
|
|
75
|
+
os.path.join(testtemproot, "regressoronly"),
|
|
76
|
+
"--nprocs",
|
|
77
|
+
"-1",
|
|
78
|
+
"--outputlevel",
|
|
79
|
+
"onlyregressors",
|
|
80
|
+
]
|
|
81
|
+
rapidtide_retroregress.retroregress(rapidtide_retroregress.process_args(inputargs=inputargs))
|
|
82
|
+
|
|
83
|
+
# check to see that rapidtide and retroregress output match
|
|
84
|
+
msethresh = 1e-6
|
|
85
|
+
aethresh = 2
|
|
86
|
+
tclist = ["brain", "GM", "WM", "CSF"]
|
|
87
|
+
for timecourse in tclist:
|
|
88
|
+
infilespec = os.path.join(
|
|
89
|
+
testtemproot,
|
|
90
|
+
f"sub-RAPIDTIDETEST_seg_desc-regionalpostfilter_timeseries.json:{timecourse}",
|
|
91
|
+
)
|
|
92
|
+
insamplerate, instarttime, incolumns, indata, incompressed, infiletype = (
|
|
93
|
+
tide_io.readvectorsfromtextfile(infilespec, onecol=True, debug=debug)
|
|
94
|
+
)
|
|
95
|
+
outfilespec = os.path.join(
|
|
96
|
+
testtemproot, f"segtest_desc-regionalpostfilter_timeseries.json:{timecourse}"
|
|
97
|
+
)
|
|
98
|
+
outsamplerate, outstarttime, outcolumns, outdata, outcompressed, outfiletype = (
|
|
99
|
+
tide_io.readvectorsfromtextfile(outfilespec, onecol=True, debug=debug)
|
|
100
|
+
)
|
|
101
|
+
assert insamplerate == outsamplerate
|
|
102
|
+
assert instarttime == outstarttime
|
|
103
|
+
assert incompressed == outcompressed
|
|
104
|
+
assert infiletype == outfiletype
|
|
105
|
+
assert incolumns == outcolumns
|
|
106
|
+
assert indata.shape == outdata.shape
|
|
107
|
+
assert indata.shape[0] == indata.shape[0]
|
|
108
|
+
assert mse(indata, outdata) < msethresh
|
|
109
|
+
np.testing.assert_almost_equal(indata, outdata, aethresh)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
mpl.use("TkAgg")
|
|
114
|
+
test_fullrunrapidtide_v7(debug=True, local=True, displayplots=True)
|