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
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
#
|
|
19
19
|
import argparse
|
|
20
20
|
import sys
|
|
21
|
+
from typing import Any
|
|
21
22
|
|
|
22
23
|
import numpy as np
|
|
24
|
+
from numpy.typing import NDArray
|
|
23
25
|
from statsmodels.robust import mad
|
|
24
26
|
|
|
25
27
|
import rapidtide.io as tide_io
|
|
@@ -28,43 +30,35 @@ import rapidtide.stats as tide_stats
|
|
|
28
30
|
import rapidtide.workflows.parser_funcs as pf
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
numtimepoints = theshape[1]
|
|
35
|
-
else:
|
|
36
|
-
numtimepoints = 1
|
|
33
|
+
def _get_parser() -> Any:
|
|
34
|
+
"""
|
|
35
|
+
Construct and return an argument parser for the atlasaverage command-line tool.
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
else:
|
|
44
|
-
regionsummary = 100.0 * np.nan_to_num(np.std(thevoxels) / np.mean(thevoxels))
|
|
45
|
-
else:
|
|
46
|
-
if method == "mean":
|
|
47
|
-
themethod = np.mean
|
|
48
|
-
elif method == "sum":
|
|
49
|
-
themethod = np.sum
|
|
50
|
-
elif method == "median":
|
|
51
|
-
themethod = np.median
|
|
52
|
-
elif method == "std":
|
|
53
|
-
themethod = np.std
|
|
54
|
-
elif method == "MAD":
|
|
55
|
-
themethod = mad
|
|
56
|
-
else:
|
|
57
|
-
print(f"illegal summary method {method} in summarizevoxels")
|
|
58
|
-
sys.exit()
|
|
37
|
+
This function builds an `argparse.ArgumentParser` object configured with all
|
|
38
|
+
required and optional arguments needed to run the `atlasaverage` utility. It
|
|
39
|
+
handles input validation for file paths and defines various options for
|
|
40
|
+
normalizing, summarizing, and filtering data within atlas regions.
|
|
59
41
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return regionsummary
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
argparse.ArgumentParser
|
|
45
|
+
Configured argument parser object for the atlasaverage tool.
|
|
65
46
|
|
|
47
|
+
Notes
|
|
48
|
+
-----
|
|
49
|
+
The parser is set up with:
|
|
50
|
+
- Two required positional arguments: `datafile` and `templatefile`.
|
|
51
|
+
- One required positional argument: `outputroot`.
|
|
52
|
+
- Several optional arguments controlling normalization, summarization,
|
|
53
|
+
masking, and output formatting.
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
Examples
|
|
56
|
+
--------
|
|
57
|
+
>>> parser = _get_parser()
|
|
58
|
+
>>> args = parser.parse_args(['data.nii', 'atlas.nii', 'output'])
|
|
59
|
+
>>> print(args.datafile)
|
|
60
|
+
'data.nii'
|
|
61
|
+
"""
|
|
68
62
|
# get the command line parameters
|
|
69
63
|
parser = argparse.ArgumentParser(
|
|
70
64
|
prog="atlasaverage",
|
|
@@ -203,7 +197,160 @@ def _get_parser():
|
|
|
203
197
|
return parser
|
|
204
198
|
|
|
205
199
|
|
|
206
|
-
def
|
|
200
|
+
def summarizevoxels(thevoxels: NDArray, method: str = "mean") -> float:
|
|
201
|
+
"""
|
|
202
|
+
Summarize voxel data using specified statistical method.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
thevoxels : ndarray
|
|
207
|
+
Input voxel data array. Can be 1D or 2D, where 2D arrays are interpreted
|
|
208
|
+
as time series with shape (voxels, timepoints).
|
|
209
|
+
method : str, default="mean"
|
|
210
|
+
Summary method to apply. Options are:
|
|
211
|
+
- "mean": Compute mean along axis 0
|
|
212
|
+
- "sum": Compute sum along axis 0
|
|
213
|
+
- "median": Compute median along axis 0
|
|
214
|
+
- "std": Compute standard deviation along axis 0
|
|
215
|
+
- "MAD": Compute median absolute deviation along axis 0
|
|
216
|
+
- "CoV": Compute coefficient of variation (std/mean) along axis 0
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
float or ndarray
|
|
221
|
+
Summary statistic(s) of the voxel data. Returns a scalar for 1D input
|
|
222
|
+
or array of statistics for 2D input along axis 0.
|
|
223
|
+
|
|
224
|
+
Notes
|
|
225
|
+
-----
|
|
226
|
+
- NaN values are converted to zero using `np.nan_to_num` before computation
|
|
227
|
+
- For coefficient of variation ("CoV"), the result is multiplied by 100 to
|
|
228
|
+
express as percentage
|
|
229
|
+
- When input is 1D, time dimension is treated as single timepoint
|
|
230
|
+
- The function handles both 1D and 2D input arrays appropriately
|
|
231
|
+
|
|
232
|
+
Examples
|
|
233
|
+
--------
|
|
234
|
+
>>> import numpy as np
|
|
235
|
+
>>> voxels = np.array([[1, 2, 3], [4, 5, 6]])
|
|
236
|
+
>>> summarizevoxels(voxels, method="mean")
|
|
237
|
+
array([2.5, 3.5, 4.5])
|
|
238
|
+
|
|
239
|
+
>>> summarizevoxels(voxels, method="CoV")
|
|
240
|
+
array([40.82482905, 33.33333333, 25. ])
|
|
241
|
+
"""
|
|
242
|
+
theshape = thevoxels.shape
|
|
243
|
+
if len(theshape) > 1:
|
|
244
|
+
numtimepoints = theshape[1]
|
|
245
|
+
else:
|
|
246
|
+
numtimepoints = 1
|
|
247
|
+
|
|
248
|
+
if method == "CoV":
|
|
249
|
+
if numtimepoints > 1:
|
|
250
|
+
regionsummary = 100.0 * np.nan_to_num(
|
|
251
|
+
np.std(thevoxels, axis=0) / np.mean(thevoxels, axis=0)
|
|
252
|
+
)
|
|
253
|
+
else:
|
|
254
|
+
regionsummary = 100.0 * np.nan_to_num(np.std(thevoxels) / np.mean(thevoxels))
|
|
255
|
+
else:
|
|
256
|
+
if method == "mean":
|
|
257
|
+
themethod = np.mean
|
|
258
|
+
elif method == "sum":
|
|
259
|
+
themethod = np.sum
|
|
260
|
+
elif method == "median":
|
|
261
|
+
themethod = np.median
|
|
262
|
+
elif method == "std":
|
|
263
|
+
themethod = np.std
|
|
264
|
+
elif method == "MAD":
|
|
265
|
+
themethod = mad
|
|
266
|
+
else:
|
|
267
|
+
print(f"illegal summary method {method} in summarizevoxels")
|
|
268
|
+
sys.exit()
|
|
269
|
+
|
|
270
|
+
if numtimepoints > 1:
|
|
271
|
+
regionsummary = np.nan_to_num(themethod(thevoxels, axis=0))
|
|
272
|
+
else:
|
|
273
|
+
regionsummary = np.nan_to_num(themethod(thevoxels))
|
|
274
|
+
return regionsummary
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def atlasaverage(args: Any) -> None:
|
|
278
|
+
"""
|
|
279
|
+
Compute average timecourses or summary statistics for regions defined by an atlas.
|
|
280
|
+
|
|
281
|
+
This function reads fMRI data and a template (atlas) file, extracts timecourses
|
|
282
|
+
or summary statistics for each region in the atlas, and saves the results to
|
|
283
|
+
output files. It supports multiple normalization methods and can process both
|
|
284
|
+
3D and 4D input data.
|
|
285
|
+
|
|
286
|
+
Parameters
|
|
287
|
+
----------
|
|
288
|
+
args : argparse.Namespace
|
|
289
|
+
Arguments parsed from command line. Expected attributes include:
|
|
290
|
+
- datafile : str
|
|
291
|
+
Path to the input fMRI NIfTI file.
|
|
292
|
+
- templatefile : str
|
|
293
|
+
Path to the template NIfTI file defining regions.
|
|
294
|
+
- normmethod : str
|
|
295
|
+
Normalization method for timecourses: 'none', 'pct', 'std', 'var', 'p2p'.
|
|
296
|
+
- outputroot : str
|
|
297
|
+
Root name for output files.
|
|
298
|
+
- debug : bool
|
|
299
|
+
If True, enable debug printing and save intermediate masks.
|
|
300
|
+
- includespec : str or None
|
|
301
|
+
Specification for including voxels in analysis.
|
|
302
|
+
- excludespec : str or None
|
|
303
|
+
Specification for excluding voxels from analysis.
|
|
304
|
+
- extramaskname : str or None
|
|
305
|
+
Path to an additional mask file.
|
|
306
|
+
- regionlabelfile : str or None
|
|
307
|
+
Path to a file containing region labels.
|
|
308
|
+
- regionlistfile : str or None
|
|
309
|
+
Path to a file listing regions to include.
|
|
310
|
+
- summarymethod : str
|
|
311
|
+
Method for summarizing voxel values (e.g., 'mean', 'median').
|
|
312
|
+
- datalabel : str or None
|
|
313
|
+
Label to prepend to output summary.
|
|
314
|
+
- ignorezeros : bool
|
|
315
|
+
If True, exclude zero voxels when computing summaries.
|
|
316
|
+
- numpercentiles : int
|
|
317
|
+
Number of percentiles to compute for each region.
|
|
318
|
+
- headerline : bool
|
|
319
|
+
If True, include a header line in the summary CSV.
|
|
320
|
+
|
|
321
|
+
Returns
|
|
322
|
+
-------
|
|
323
|
+
None
|
|
324
|
+
This function does not return a value but writes output files to disk.
|
|
325
|
+
|
|
326
|
+
Notes
|
|
327
|
+
-----
|
|
328
|
+
For 4D data, the function computes timecourses for each region and saves them
|
|
329
|
+
as a TSV file. For 3D data, it computes summary statistics and saves both
|
|
330
|
+
a labeled NIfTI file and a CSV/TSV summary.
|
|
331
|
+
|
|
332
|
+
Examples
|
|
333
|
+
--------
|
|
334
|
+
>>> import argparse
|
|
335
|
+
>>> args = argparse.Namespace(
|
|
336
|
+
... datafile='fmri.nii.gz',
|
|
337
|
+
... templatefile='atlas.nii.gz',
|
|
338
|
+
... normmethod='std',
|
|
339
|
+
... outputroot='output',
|
|
340
|
+
... debug=False,
|
|
341
|
+
... includespec=None,
|
|
342
|
+
... excludespec=None,
|
|
343
|
+
... extramaskname=None,
|
|
344
|
+
... regionlabelfile=None,
|
|
345
|
+
... regionlistfile=None,
|
|
346
|
+
... summarymethod='mean',
|
|
347
|
+
... datalabel=None,
|
|
348
|
+
... ignorezeros=False,
|
|
349
|
+
... numpercentiles=5,
|
|
350
|
+
... headerline=True
|
|
351
|
+
... )
|
|
352
|
+
>>> atlasaverage(args)
|
|
353
|
+
"""
|
|
207
354
|
if args.normmethod == "none":
|
|
208
355
|
print("will not normalize timecourses")
|
|
209
356
|
elif args.normmethod == "pct":
|
|
@@ -302,14 +449,21 @@ def atlasaverage(args):
|
|
|
302
449
|
)
|
|
303
450
|
|
|
304
451
|
# get the region names
|
|
452
|
+
numregions = np.max(templatevoxels)
|
|
305
453
|
if args.regionlabelfile is None:
|
|
306
454
|
regionlabels = []
|
|
307
|
-
numregions = np.max(templatevoxels)
|
|
308
455
|
numdigits = int(np.log10(numregions)) + 1
|
|
309
456
|
for regnum in range(1, numregions + 1):
|
|
310
457
|
regionlabels.append(f"region_{str(regnum).zfill(numdigits)}")
|
|
311
458
|
else:
|
|
312
459
|
regionlabels = tide_io.readlabels(args.regionlabelfile)
|
|
460
|
+
if len(regionlabels) != numregions:
|
|
461
|
+
print(
|
|
462
|
+
"Error: number of labels in label file does not match the number of regions in the template."
|
|
463
|
+
)
|
|
464
|
+
sys.exit()
|
|
465
|
+
if args.debug:
|
|
466
|
+
print(f"Region labels: {regionlabels}")
|
|
313
467
|
|
|
314
468
|
# decide what regions we will summarize
|
|
315
469
|
if args.regionlistfile is None:
|
|
@@ -322,6 +476,8 @@ def atlasaverage(args):
|
|
|
322
476
|
for theregion in range(numregions):
|
|
323
477
|
newlabels.append(regionlabels[theregion])
|
|
324
478
|
regionlabels = newlabels
|
|
479
|
+
if args.debug:
|
|
480
|
+
print(f"Region labels to use: {regionlabels}")
|
|
325
481
|
|
|
326
482
|
timecourses = np.zeros((numregions, numtimepoints), dtype="float")
|
|
327
483
|
print(f"{numregions=}, {regionlist=}")
|
|
@@ -380,18 +536,21 @@ def atlasaverage(args):
|
|
|
380
536
|
else:
|
|
381
537
|
print("processing 3D input file")
|
|
382
538
|
outputvoxels = inputvoxels * 0.0
|
|
383
|
-
|
|
539
|
+
thereglabels = []
|
|
384
540
|
thevals = []
|
|
385
541
|
thepercentiles = []
|
|
386
|
-
|
|
542
|
+
theregsizes = []
|
|
387
543
|
thefracs = np.linspace(0.0, 1.0, args.numpercentiles + 2, endpoint=True).tolist()
|
|
388
544
|
numsubregions = len(thefracs) - 1
|
|
389
545
|
segmentedatlasvoxels = inputvoxels * 0.0
|
|
546
|
+
if args.debug:
|
|
547
|
+
print(f"{len(regionlist)=}, {regionlist=}")
|
|
548
|
+
print(f"{len(regionlabels)=}, {regionlabels=}")
|
|
390
549
|
if args.datalabel is not None:
|
|
391
|
-
|
|
550
|
+
thereglabels.append("Region")
|
|
392
551
|
thevals.append(args.datalabel)
|
|
393
552
|
for theregion in regionlist:
|
|
394
|
-
|
|
553
|
+
thereglabels.append(regionlabels[theregion - 1])
|
|
395
554
|
theregionvoxels = inputvoxels[np.where(templatevoxels * themask == theregion)]
|
|
396
555
|
initnum = theregionvoxels.shape[0]
|
|
397
556
|
if args.ignorezeros:
|
|
@@ -404,13 +563,15 @@ def atlasaverage(args):
|
|
|
404
563
|
if args.debug:
|
|
405
564
|
print(
|
|
406
565
|
f"extracting {theregionvoxels.shape[0]} "
|
|
407
|
-
f"non-zero voxels from region {theregion} of {numregions}{extrabit}"
|
|
566
|
+
f"non-zero voxels from region {theregion} of {numregions}{extrabit} "
|
|
567
|
+
f"({thereglabels[-1]})"
|
|
408
568
|
)
|
|
409
569
|
else:
|
|
410
570
|
if args.debug:
|
|
411
571
|
print(
|
|
412
572
|
f"extracting {theregionvoxels.shape[0]} "
|
|
413
|
-
f"voxels from region {theregion} of {numregions}"
|
|
573
|
+
f"voxels from region {theregion} of {numregions} "
|
|
574
|
+
f"({thereglabels[-1]})"
|
|
414
575
|
)
|
|
415
576
|
if theregionvoxels.shape[0] > 0:
|
|
416
577
|
regionval = summarizevoxels(theregionvoxels, method=args.summarymethod)
|
|
@@ -426,7 +587,7 @@ def atlasaverage(args):
|
|
|
426
587
|
]
|
|
427
588
|
outputvoxels[np.where(templatevoxels == theregion)] = regionval
|
|
428
589
|
thevals.append(str(regionval))
|
|
429
|
-
|
|
590
|
+
theregsizes.append(str(regionsizes))
|
|
430
591
|
thepercentiles.append(regionpercentiles)
|
|
431
592
|
else:
|
|
432
593
|
if args.debug:
|
|
@@ -462,21 +623,23 @@ def atlasaverage(args):
|
|
|
462
623
|
)
|
|
463
624
|
if args.headerline:
|
|
464
625
|
tide_io.writevec(
|
|
465
|
-
[",".join(
|
|
626
|
+
np.array([",".join(thereglabels), ",".join(thevals)]),
|
|
466
627
|
f"{args.outputroot}_regionsummaries.csv",
|
|
467
628
|
)
|
|
468
629
|
else:
|
|
469
630
|
tide_io.writevec(
|
|
470
|
-
[",".join(thevals)],
|
|
631
|
+
np.array([",".join(thevals)]),
|
|
471
632
|
f"{args.outputroot}_regionsummaries.csv",
|
|
472
633
|
)
|
|
473
634
|
|
|
474
635
|
outlines = []
|
|
475
636
|
pctstrings = [f"{num:.0f}" for num in (np.array(thefracs) * 100.0).tolist()]
|
|
476
637
|
outlines.append("Region\tVoxels\t" + "pct-" + "\tpct-".join(pctstrings))
|
|
477
|
-
for idx, region in enumerate(
|
|
478
|
-
outlines.append(
|
|
638
|
+
for idx, region in enumerate(thereglabels):
|
|
639
|
+
outlines.append(
|
|
640
|
+
region + "\t" + theregsizes[idx] + "\t" + "\t".join(thepercentiles[idx])
|
|
641
|
+
)
|
|
479
642
|
tide_io.writevec(
|
|
480
|
-
outlines,
|
|
643
|
+
np.array(outlines),
|
|
481
644
|
f"{args.outputroot}_regionpercentiles.tsv",
|
|
482
645
|
)
|
rapidtide/workflows/atlastool.py
CHANGED
|
@@ -20,18 +20,42 @@ import argparse
|
|
|
20
20
|
import os
|
|
21
21
|
import subprocess
|
|
22
22
|
import sys
|
|
23
|
+
from argparse import Namespace
|
|
23
24
|
from glob import glob
|
|
25
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
24
26
|
|
|
25
27
|
import numpy as np
|
|
28
|
+
from numpy.typing import NDArray
|
|
26
29
|
|
|
27
30
|
import rapidtide.externaltools as tide_exttools
|
|
28
31
|
import rapidtide.io as tide_io
|
|
29
32
|
import rapidtide.workflows.parser_funcs as pf
|
|
30
33
|
|
|
31
34
|
|
|
32
|
-
def _get_parser():
|
|
35
|
+
def _get_parser() -> Any:
|
|
33
36
|
"""
|
|
34
|
-
Argument parser for atlastool
|
|
37
|
+
Argument parser for atlastool.
|
|
38
|
+
|
|
39
|
+
This function constructs and returns an `argparse.ArgumentParser` object configured
|
|
40
|
+
with all the necessary arguments for the `atlastool` utility. It supports parsing
|
|
41
|
+
of NIfTI atlas files, with options for transforming, splitting, masking, and
|
|
42
|
+
reformatting atlas data.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
argparse.ArgumentParser
|
|
47
|
+
Configured argument parser for atlastool.
|
|
48
|
+
|
|
49
|
+
Notes
|
|
50
|
+
-----
|
|
51
|
+
The parser includes both required and optional arguments for handling NIfTI files,
|
|
52
|
+
including support for 3D and 4D output formats, splitting regions along the midline,
|
|
53
|
+
applying masks, and debugging options.
|
|
54
|
+
|
|
55
|
+
Examples
|
|
56
|
+
--------
|
|
57
|
+
>>> parser = _get_parser()
|
|
58
|
+
>>> args = parser.parse_args()
|
|
35
59
|
"""
|
|
36
60
|
parser = argparse.ArgumentParser(
|
|
37
61
|
prog="atlastool",
|
|
@@ -156,7 +180,80 @@ def _get_parser():
|
|
|
156
180
|
return parser
|
|
157
181
|
|
|
158
182
|
|
|
159
|
-
def atlastool(args):
|
|
183
|
+
def atlastool(args: Any) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Process and convert atlas templates for neuroimaging analysis.
|
|
186
|
+
|
|
187
|
+
This function reads a template NIfTI file, reshapes it into a 4D array, and optionally
|
|
188
|
+
splits left-right regions, resamples to a target resolution, applies a mask, and saves
|
|
189
|
+
the processed data as a new NIfTI file. It supports both 3D and 4D input templates,
|
|
190
|
+
and can handle label files for region mapping.
|
|
191
|
+
|
|
192
|
+
Parameters
|
|
193
|
+
----------
|
|
194
|
+
args : Any
|
|
195
|
+
An object containing command-line arguments. Expected attributes include:
|
|
196
|
+
- inputtemplatename : str
|
|
197
|
+
Path to the input NIfTI template file.
|
|
198
|
+
- debug : bool
|
|
199
|
+
If True, print debug information.
|
|
200
|
+
- maxval : float, optional
|
|
201
|
+
Maximum value to truncate template data.
|
|
202
|
+
- labelfile : str, optional
|
|
203
|
+
Path to a text file containing region labels.
|
|
204
|
+
- dosplit : bool
|
|
205
|
+
If True, split regions into left and right hemispheres.
|
|
206
|
+
- LtoR : bool
|
|
207
|
+
If True, assign left hemisphere labels first.
|
|
208
|
+
- targetfile : str, optional
|
|
209
|
+
Path to a target NIfTI file for resampling.
|
|
210
|
+
- xfm : str, optional
|
|
211
|
+
Path to transformation file for resampling.
|
|
212
|
+
- maskfile : str, optional
|
|
213
|
+
Path to a mask NIfTI file.
|
|
214
|
+
- maskthresh : float
|
|
215
|
+
Threshold for generating mask from template if no maskfile is provided.
|
|
216
|
+
- removeemptyregions : bool
|
|
217
|
+
If True, remove regions with no voxels.
|
|
218
|
+
- volumeperregion : bool
|
|
219
|
+
If True, save each region as a separate volume; otherwise, save as a
|
|
220
|
+
single label map.
|
|
221
|
+
- outputtemplatename : str
|
|
222
|
+
Path for the output NIfTI file.
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
None
|
|
227
|
+
This function does not return a value but saves processed data to disk.
|
|
228
|
+
|
|
229
|
+
Notes
|
|
230
|
+
-----
|
|
231
|
+
- The function supports both 3D and 4D input templates.
|
|
232
|
+
- If `targetfile` is provided, the template is resampled using FSL or ANTs.
|
|
233
|
+
- If `maskfile` is not provided, a mask is generated from the template using
|
|
234
|
+
`maskthresh`.
|
|
235
|
+
- Labels from `labelfile` are used in the output if provided.
|
|
236
|
+
|
|
237
|
+
Examples
|
|
238
|
+
--------
|
|
239
|
+
>>> import argparse
|
|
240
|
+
>>> args = argparse.Namespace(
|
|
241
|
+
... inputtemplatename='template.nii.gz',
|
|
242
|
+
... debug=False,
|
|
243
|
+
... maxval=None,
|
|
244
|
+
... labelfile='labels.txt',
|
|
245
|
+
... dosplit=True,
|
|
246
|
+
... LtoR=True,
|
|
247
|
+
... targetfile='target.nii.gz',
|
|
248
|
+
... xfm='transform.mat',
|
|
249
|
+
... maskfile=None,
|
|
250
|
+
... maskthresh=0.5,
|
|
251
|
+
... removeemptyregions=True,
|
|
252
|
+
... volumeperregion=False,
|
|
253
|
+
... outputtemplatename='output.nii.gz'
|
|
254
|
+
... )
|
|
255
|
+
>>> atlastool(args)
|
|
256
|
+
"""
|
|
160
257
|
if args.debug:
|
|
161
258
|
print(args)
|
|
162
259
|
|