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.
Files changed (144) hide show
  1. rapidtide/Colortables.py +492 -27
  2. rapidtide/OrthoImageItem.py +1049 -46
  3. rapidtide/RapidtideDataset.py +1533 -86
  4. rapidtide/_version.py +3 -3
  5. rapidtide/calccoherence.py +196 -29
  6. rapidtide/calcnullsimfunc.py +188 -40
  7. rapidtide/calcsimfunc.py +242 -42
  8. rapidtide/correlate.py +1203 -383
  9. rapidtide/data/examples/src/testLD +56 -0
  10. rapidtide/data/examples/src/testalign +1 -1
  11. rapidtide/data/examples/src/testdelayvar +0 -1
  12. rapidtide/data/examples/src/testfmri +53 -3
  13. rapidtide/data/examples/src/testglmfilt +5 -5
  14. rapidtide/data/examples/src/testhappy +29 -7
  15. rapidtide/data/examples/src/testppgproc +17 -0
  16. rapidtide/data/examples/src/testrolloff +11 -0
  17. rapidtide/data/models/model_cnn_pytorch/best_model.pth +0 -0
  18. rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
  19. rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
  20. rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
  21. rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
  22. rapidtide/decorators.py +91 -0
  23. rapidtide/dlfilter.py +2226 -110
  24. rapidtide/dlfiltertorch.py +4842 -0
  25. rapidtide/externaltools.py +327 -12
  26. rapidtide/fMRIData_class.py +79 -40
  27. rapidtide/filter.py +1899 -810
  28. rapidtide/fit.py +2011 -581
  29. rapidtide/genericmultiproc.py +93 -18
  30. rapidtide/happy_supportfuncs.py +2047 -172
  31. rapidtide/helper_classes.py +584 -43
  32. rapidtide/io.py +2370 -372
  33. rapidtide/linfitfiltpass.py +346 -99
  34. rapidtide/makelaggedtcs.py +210 -24
  35. rapidtide/maskutil.py +448 -62
  36. rapidtide/miscmath.py +827 -121
  37. rapidtide/multiproc.py +210 -22
  38. rapidtide/patchmatch.py +242 -42
  39. rapidtide/peakeval.py +31 -31
  40. rapidtide/ppgproc.py +2203 -0
  41. rapidtide/qualitycheck.py +352 -39
  42. rapidtide/refinedelay.py +431 -57
  43. rapidtide/refineregressor.py +494 -189
  44. rapidtide/resample.py +671 -185
  45. rapidtide/scripts/applyppgproc.py +28 -0
  46. rapidtide/scripts/showxcorr_legacy.py +7 -7
  47. rapidtide/scripts/stupidramtricks.py +15 -17
  48. rapidtide/simFuncClasses.py +1052 -77
  49. rapidtide/simfuncfit.py +269 -69
  50. rapidtide/stats.py +540 -238
  51. rapidtide/tests/happycomp +9 -0
  52. rapidtide/tests/test_cleanregressor.py +1 -2
  53. rapidtide/tests/test_dlfiltertorch.py +627 -0
  54. rapidtide/tests/test_findmaxlag.py +24 -8
  55. rapidtide/tests/test_fullrunhappy_v1.py +0 -2
  56. rapidtide/tests/test_fullrunhappy_v2.py +0 -2
  57. rapidtide/tests/test_fullrunhappy_v3.py +11 -4
  58. rapidtide/tests/test_fullrunhappy_v4.py +10 -2
  59. rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
  60. rapidtide/tests/test_getparsers.py +11 -3
  61. rapidtide/tests/test_refinedelay.py +0 -1
  62. rapidtide/tests/test_simroundtrip.py +16 -8
  63. rapidtide/tests/test_stcorrelate.py +3 -1
  64. rapidtide/tests/utils.py +9 -8
  65. rapidtide/tidepoolTemplate.py +142 -38
  66. rapidtide/tidepoolTemplate_alt.py +165 -44
  67. rapidtide/tidepoolTemplate_big.py +189 -52
  68. rapidtide/util.py +1217 -118
  69. rapidtide/voxelData.py +684 -37
  70. rapidtide/wiener.py +136 -23
  71. rapidtide/wiener2.py +113 -7
  72. rapidtide/workflows/adjustoffset.py +105 -3
  73. rapidtide/workflows/aligntcs.py +85 -2
  74. rapidtide/workflows/applydlfilter.py +87 -10
  75. rapidtide/workflows/applyppgproc.py +540 -0
  76. rapidtide/workflows/atlasaverage.py +210 -47
  77. rapidtide/workflows/atlastool.py +100 -3
  78. rapidtide/workflows/calcSimFuncMap.py +288 -69
  79. rapidtide/workflows/calctexticc.py +201 -9
  80. rapidtide/workflows/ccorrica.py +101 -6
  81. rapidtide/workflows/cleanregressor.py +165 -31
  82. rapidtide/workflows/delayvar.py +171 -23
  83. rapidtide/workflows/diffrois.py +81 -3
  84. rapidtide/workflows/endtidalproc.py +144 -4
  85. rapidtide/workflows/fdica.py +195 -15
  86. rapidtide/workflows/filtnifti.py +70 -3
  87. rapidtide/workflows/filttc.py +74 -3
  88. rapidtide/workflows/fitSimFuncMap.py +202 -51
  89. rapidtide/workflows/fixtr.py +73 -3
  90. rapidtide/workflows/gmscalc.py +113 -3
  91. rapidtide/workflows/happy.py +801 -199
  92. rapidtide/workflows/happy2std.py +144 -12
  93. rapidtide/workflows/happy_parser.py +163 -23
  94. rapidtide/workflows/histnifti.py +118 -2
  95. rapidtide/workflows/histtc.py +84 -3
  96. rapidtide/workflows/linfitfilt.py +117 -4
  97. rapidtide/workflows/localflow.py +328 -28
  98. rapidtide/workflows/mergequality.py +79 -3
  99. rapidtide/workflows/niftidecomp.py +322 -18
  100. rapidtide/workflows/niftistats.py +174 -4
  101. rapidtide/workflows/pairproc.py +98 -4
  102. rapidtide/workflows/pairwisemergenifti.py +85 -2
  103. rapidtide/workflows/parser_funcs.py +1421 -40
  104. rapidtide/workflows/physiofreq.py +137 -11
  105. rapidtide/workflows/pixelcomp.py +207 -5
  106. rapidtide/workflows/plethquality.py +103 -21
  107. rapidtide/workflows/polyfitim.py +151 -11
  108. rapidtide/workflows/proj2flow.py +75 -2
  109. rapidtide/workflows/rankimage.py +111 -4
  110. rapidtide/workflows/rapidtide.py +368 -76
  111. rapidtide/workflows/rapidtide2std.py +98 -2
  112. rapidtide/workflows/rapidtide_parser.py +109 -9
  113. rapidtide/workflows/refineDelayMap.py +144 -33
  114. rapidtide/workflows/refineRegressor.py +675 -96
  115. rapidtide/workflows/regressfrommaps.py +161 -37
  116. rapidtide/workflows/resamplenifti.py +85 -3
  117. rapidtide/workflows/resampletc.py +91 -3
  118. rapidtide/workflows/retrolagtcs.py +99 -9
  119. rapidtide/workflows/retroregress.py +176 -26
  120. rapidtide/workflows/roisummarize.py +174 -5
  121. rapidtide/workflows/runqualitycheck.py +71 -3
  122. rapidtide/workflows/showarbcorr.py +149 -6
  123. rapidtide/workflows/showhist.py +86 -2
  124. rapidtide/workflows/showstxcorr.py +160 -3
  125. rapidtide/workflows/showtc.py +159 -3
  126. rapidtide/workflows/showxcorrx.py +190 -10
  127. rapidtide/workflows/showxy.py +185 -15
  128. rapidtide/workflows/simdata.py +264 -38
  129. rapidtide/workflows/spatialfit.py +77 -2
  130. rapidtide/workflows/spatialmi.py +250 -27
  131. rapidtide/workflows/spectrogram.py +305 -32
  132. rapidtide/workflows/synthASL.py +154 -3
  133. rapidtide/workflows/tcfrom2col.py +76 -2
  134. rapidtide/workflows/tcfrom3col.py +74 -2
  135. rapidtide/workflows/tidepool.py +2971 -130
  136. rapidtide/workflows/utils.py +19 -14
  137. rapidtide/workflows/utils_doc.py +293 -0
  138. rapidtide/workflows/variabilityizer.py +116 -3
  139. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/METADATA +10 -8
  140. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/RECORD +144 -128
  141. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/entry_points.txt +1 -0
  142. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/WHEEL +0 -0
  143. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/licenses/LICENSE +0 -0
  144. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/top_level.txt +0 -0
@@ -21,11 +21,39 @@ import glob
21
21
  import os
22
22
  import subprocess
23
23
  import sys
24
+ from argparse import Namespace
25
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
24
26
 
25
27
  import rapidtide.externaltools as tide_extern
26
28
 
27
29
 
28
- def _get_parser():
30
+ def _get_parser() -> Any:
31
+ """
32
+ Create and configure an argument parser for the rapidtide2std command-line tool.
33
+
34
+ This function sets up an `argparse.ArgumentParser` with specific arguments
35
+ required for registering happy output maps to standard space. It defines
36
+ positional and optional arguments for input file roots, output directories,
37
+ and various transformation options.
38
+
39
+ Returns
40
+ -------
41
+ argparse.ArgumentParser
42
+ Configured argument parser object with defined arguments for
43
+ the rapidtide2std tool.
44
+
45
+ Notes
46
+ -----
47
+ The parser is configured with a program name, description, and usage string
48
+ specific to the rapidtide2std tool. It expects three positional arguments:
49
+ inputfileroot, outputdir, and featdirectory, followed by several optional
50
+ flags that control the registration process.
51
+
52
+ Examples
53
+ --------
54
+ >>> parser = _get_parser()
55
+ >>> args = parser.parse_args()
56
+ """
29
57
  # get the command line parameters
30
58
  parser = argparse.ArgumentParser(
31
59
  prog="rapidtide2std",
@@ -84,16 +112,74 @@ def _get_parser():
84
112
 
85
113
 
86
114
  def transformmaps(
87
- thepath,
88
- theoutputdir,
89
- subjroot,
90
- reftarget,
91
- xformfuncmat,
92
- warpfuncfile,
93
- thefmrimaps=None,
94
- theanatmaps=None,
95
- preponly=False,
96
- ):
115
+ thepath: Any,
116
+ theoutputdir: Any,
117
+ subjroot: Any,
118
+ reftarget: Any,
119
+ xformfuncmat: Any,
120
+ warpfuncfile: Any,
121
+ thefmrimaps: Optional[Any] = None,
122
+ theanatmaps: Optional[Any] = None,
123
+ preponly: bool = False,
124
+ ) -> None:
125
+ """
126
+ Apply spatial transformations to fMRI and anatomical maps from a happy dataset using FLIRT and/or
127
+ copy commands.
128
+
129
+ This function applies rigid-body and non-linear transformations to a set of fMRI and/or
130
+ anatomical maps, based on provided transformation matrices and warp fields. It supports
131
+ both functional and anatomical image processing pipelines.
132
+
133
+ Parameters
134
+ ----------
135
+ thepath : Any
136
+ Path to the directory containing input fMRI maps.
137
+ theoutputdir : Any
138
+ Directory where transformed maps will be saved.
139
+ subjroot : Any
140
+ Subject identifier used to construct input and output file names.
141
+ reftarget : Any
142
+ Reference image to which maps are transformed.
143
+ xformfuncmat : Any
144
+ Transformation matrix for functional-to-standard space alignment.
145
+ warpfuncfile : Any
146
+ Warp field file for non-linear functional-to-standard space transformation.
147
+ thefmrimaps : Optional[Any], default=None
148
+ List of fMRI map names to transform. If None, no fMRI maps are processed.
149
+ theanatmaps : Optional[Any], default=None
150
+ List of anatomical map names to transform. If None, no anatomical maps are processed.
151
+ preponly : bool, default=False
152
+ If True, only print the commands without executing them.
153
+
154
+ Returns
155
+ -------
156
+ None
157
+ This function does not return any value; it performs file I/O operations.
158
+
159
+ Notes
160
+ -----
161
+ - For fMRI maps, the function uses `tide_extern.makeflirtcmd` to generate and execute
162
+ FLIRT commands for transformation.
163
+ - For anatomical maps, it either copies the file or applies a transformation using
164
+ `tide_extern.makeflirtcmd`, depending on the `aligntohires` flag.
165
+ - If `preponly` is True, the commands are printed but not executed.
166
+ - The function assumes that input files exist and are named according to the
167
+ pattern: ``{subjroot}_{mapname}.nii.gz``.
168
+
169
+ Examples
170
+ --------
171
+ >>> transformmaps(
172
+ ... thepath="/data/subj1",
173
+ ... theoutputdir="/data/subj1/transformed",
174
+ ... subjroot="subj1",
175
+ ... reftarget="/data/templates/MNI152_T1_2mm.nii.gz",
176
+ ... xformfuncmat="/data/subj1/reg/func2standard.mat",
177
+ ... warpfuncfile="/data/subj1/reg/warpfield.nii.gz",
178
+ ... thefmrimaps=["bold", "mask"],
179
+ ... theanatmaps=["brain"],
180
+ ... preponly=False
181
+ ... )
182
+ """
97
183
  print("entering transformmaps with:")
98
184
  print(thepath)
99
185
  print(subjroot)
@@ -151,7 +237,53 @@ def transformmaps(
151
237
  print("no hires anatomic found - skipping")
152
238
 
153
239
 
154
- def happy2std(args):
240
+ def happy2std(args: Any) -> None:
241
+ """
242
+ Apply FSL-based spatial transformation to fMRI data and anatomical maps.
243
+
244
+ This function performs spatial normalization of fMRI data to either high-resolution
245
+ or standard MNI152 space, using FSL transformation matrices and warp fields. It supports
246
+ both linear and nonlinear transformations, and can process either a single file or
247
+ a set of files based on input arguments.
248
+
249
+ Parameters
250
+ ----------
251
+ args : Any
252
+ An object containing command-line arguments. Expected attributes include:
253
+ - featdirectory : str
254
+ Path to the FEAT directory containing registration files.
255
+ - aligntohires : bool
256
+ If True, align to high-resolution anatomical space; otherwise to standard MNI152.
257
+ - forcelinear : bool
258
+ If True, forces use of a linear transformation even if warp files are present.
259
+ - onefilename : str or None
260
+ If provided, process only this single file.
261
+ - preponly : bool
262
+ If True, print the FSL command without executing it.
263
+ - inputfileroot : str
264
+ Root path to input files for batch processing.
265
+ - outputdir : str
266
+ Output directory for transformed files.
267
+ - all : bool
268
+ If True, include additional fMRI maps in processing.
269
+
270
+ Returns
271
+ -------
272
+ None
273
+ This function does not return a value but may exit the program on error.
274
+
275
+ Notes
276
+ -----
277
+ This function requires the FSL environment variable ``FSLDIR`` to be set.
278
+ It relies on FSL tools like `applywarp` and `flirt` for transformations.
279
+ The function supports processing of both single files and batches of files
280
+ using glob patterns.
281
+
282
+ Examples
283
+ --------
284
+ >>> args = parse_args() # Assume args is parsed from command line
285
+ >>> happy2std(args)
286
+ """
155
287
  # make sure the appropriate transformation matrix and targets exist
156
288
  fsldir = os.environ.get("FSLDIR")
157
289
  if fsldir is None:
@@ -17,6 +17,7 @@
17
17
  #
18
18
  #
19
19
  import argparse
20
+ from typing import Any, Optional
20
21
 
21
22
  import numpy as np
22
23
 
@@ -24,19 +25,59 @@ import rapidtide.io as tide_io
24
25
  import rapidtide.multiproc as tide_multiproc
25
26
  import rapidtide.workflows.parser_funcs as pf
26
27
 
28
+ try:
29
+ import tensorflow as tf
30
+ tensorflowpresent = True
31
+ except ImportError:
32
+ tensorflowpresent = False
33
+
27
34
  DEFAULT_ALIASEDCORRELATIONWIDTH = 5.0
28
- DEFAULT_DL_MODEL = "model_revised_tf2"
35
+ DEFAULT_PULSATILITYSIGMA = 6.0
36
+ DEFAULT_PULSATILITYTHRESHOLD = 0.5
37
+ DEFAULT_TF_DL_MODEL = "model_revised_tf2"
38
+ DEFAULT_PT_DL_MODEL = "model_cnn_pytorch"
29
39
 
30
40
 
31
- def _get_parser():
41
+ def _get_parser() -> Any:
32
42
  """
33
- Argument parser for happy
43
+ Create and configure an argument parser for the happy command-line tool.
44
+
45
+ This function sets up an `argparse.ArgumentParser` with numerous options for
46
+ configuring the hypersampling by analytic phase projection (HAPPY) pipeline.
47
+ It includes arguments for input files, processing steps, performance tuning,
48
+ preprocessing, cardiac and respiration estimation, output handling, and debugging.
49
+
50
+ Returns
51
+ -------
52
+ argparse.ArgumentParser
53
+ Configured argument parser with all supported command-line options.
54
+
55
+ Notes
56
+ -----
57
+ The parser includes multiple argument groups for different functional areas:
58
+ - Processing steps
59
+ - Performance
60
+ - Preprocessing
61
+ - Cardiac estimation tuning
62
+ - External cardiac waveform options
63
+ - External respiration waveform options
64
+ - Output processing
65
+ - Output options
66
+ - Phase projection tuning
67
+ - Miscellaneous options
68
+ - Debugging options
69
+
70
+ Examples
71
+ --------
72
+ >>> parser = _get_parser()
73
+ >>> args = parser.parse_args()
34
74
  """
35
75
  parser = argparse.ArgumentParser(
36
76
  prog="happy",
37
77
  description="Hypersampling by Analytic Phase Projection - Yay!.",
38
78
  allow_abbrev=False,
39
79
  )
80
+
40
81
 
41
82
  # Required arguments
42
83
  parser.add_argument(
@@ -73,18 +114,19 @@ def _get_parser():
73
114
  help="Disable deep learning cardiac waveform filter. ",
74
115
  default=True,
75
116
  )
76
- processing_steps.add_argument(
77
- "--usesuperdangerousworkaround",
78
- dest="mpfix",
79
- action="store_true",
80
- help=(
81
- "Some versions of tensorflow seem to have some weird conflict with MKL which"
82
- "I don't seem to be able to fix. If the dl filter bombs complaining about "
83
- "multiple openmp libraries, try rerunning with the secret and inadvisable "
84
- "'--usesuperdangerousworkaround' flag. Good luck! "
85
- ),
86
- default=False,
87
- )
117
+ if tensorflowpresent:
118
+ processing_steps.add_argument(
119
+ "--usesuperdangerousworkaround",
120
+ dest="mpfix",
121
+ action="store_true",
122
+ help=(
123
+ "Some versions of tensorflow seem to have some weird conflict with MKL which"
124
+ "I don't seem to be able to fix. If the dl filter bombs complaining about "
125
+ "multiple openmp libraries, try rerunning with the secret and inadvisable "
126
+ "'--usesuperdangerousworkaround' flag. Good luck! "
127
+ ),
128
+ default=False,
129
+ )
88
130
  processing_steps.add_argument(
89
131
  "--slicetimesareinseconds",
90
132
  action="store_true",
@@ -101,10 +143,10 @@ def _get_parser():
101
143
  dest="modelname",
102
144
  metavar="MODELNAME",
103
145
  help=(
104
- f"Use model MODELNAME for dl filter (default is {DEFAULT_DL_MODEL} - "
146
+ f"Use model MODELNAME for dl filter (default is {DEFAULT_PT_DL_MODEL} - "
105
147
  "from the revised NeuroImage paper.) "
106
148
  ),
107
- default=DEFAULT_DL_MODEL,
149
+ default=None,
108
150
  )
109
151
 
110
152
  # Performance
@@ -550,6 +592,31 @@ def _get_parser():
550
592
  help="Restrict cardiac waveform estimation to putative arteries only.",
551
593
  default=False,
552
594
  )
595
+ phase_proj_tuning.add_argument(
596
+ "--pulsatilitysigma",
597
+ dest="pulsatilitysigma",
598
+ action="store",
599
+ metavar="SIGMAINMM",
600
+ type=lambda x: pf.is_float(parser, x),
601
+ help=(
602
+ "Split pulsatility map spatial frequencies with a gaussian filter with sigma=SIGMAINMM. "
603
+ f"Default is {DEFAULT_PULSATILITYSIGMA}mm. "
604
+ ),
605
+ default=DEFAULT_PULSATILITYSIGMA,
606
+ )
607
+ phase_proj_tuning.add_argument(
608
+ "--pulsatilitythreshold",
609
+ dest="pulsatilitythreshold",
610
+ action="store",
611
+ metavar="THRESHPCT",
612
+ type=lambda x: pf.is_float(parser, x),
613
+ help=(
614
+ "Consider voxels with a high spatial frequency pulsatility above THRESHPCT percent "
615
+ "to be vessels. "
616
+ f"Default is {DEFAULT_PULSATILITYTHRESHOLD}mm. "
617
+ ),
618
+ default=DEFAULT_PULSATILITYSIGMA,
619
+ )
553
620
 
554
621
  # Add version options
555
622
  pf.addversionopts(parser)
@@ -563,7 +630,7 @@ def _get_parser():
563
630
  metavar="MASKNAME",
564
631
  help=(
565
632
  "Instead of dynamically generating a processing mask from the data, use "
566
- "the mask specified in the file MASKNAME. "
633
+ "the mask specified in the file MASKNAME. "
567
634
  "The mask must be a 3D NIFTI file with x, y, z dimensions matching the fMRI data. "
568
635
  ),
569
636
  default=None,
@@ -613,6 +680,13 @@ def _get_parser():
613
680
  help="Number of iterations for calculating Wright map. Set to 0 to disable.",
614
681
  default=0,
615
682
  )
683
+ misc_opts.add_argument(
684
+ "--usenewvesselmethod",
685
+ dest="useoriginalvesselmethod",
686
+ action="store_false",
687
+ help="Will use the new pulsatility method to find blood vessels. ",
688
+ default=True,
689
+ )
616
690
  pf.addtagopts(
617
691
  misc_opts,
618
692
  helptext="Additional key, value pairs to add to the info json file (useful for tracking analyses).",
@@ -635,6 +709,13 @@ def _get_parser():
635
709
  help="Disable data detrending. ",
636
710
  default=3,
637
711
  )
712
+ debug_opts.add_argument(
713
+ "--normvesselmap",
714
+ dest="unnormvesselmap",
715
+ action="store_false",
716
+ help="Find vessels using normalized phase projection. ",
717
+ default=True,
718
+ )
638
719
  debug_opts.add_argument(
639
720
  "--noorthog",
640
721
  dest="orthogonalize",
@@ -740,19 +821,64 @@ def _get_parser():
740
821
  help="Disable the congrid value cache completely.",
741
822
  default=True,
742
823
  )
824
+ if tensorflowpresent:
825
+ debug_opts.add_argument(
826
+ "--usetensorflow",
827
+ dest="usepytorch",
828
+ action="store_false",
829
+ help=("Switch to the old style tensorflow deep learning filter"),
830
+ default=True,
831
+ )
832
+ debug_opts.add_argument(
833
+ "--focaldebug",
834
+ dest="focaldebug",
835
+ action="store_true",
836
+ help=("Enable targeted additional debugging output (used during development)."),
837
+ default=False,
838
+ )
743
839
 
744
840
  return parser
745
841
 
746
842
 
747
- def process_args(inputargs=None):
843
+ def process_args(inputargs: Optional[Any] = None) -> Any:
748
844
  """
749
- Compile arguments for rapidtide workflow.
845
+ Compile arguments for happy workflow.
846
+
847
+ This function processes input arguments for the happy workflow, handling
848
+ argument parsing, command line formatting, default model selection, and post-processing
849
+ of various parameters. It also manages motion file specifications, multiprocessing
850
+ settings, and output level calculations.
851
+
852
+ Parameters
853
+ ----------
854
+ inputargs : optional
855
+ Input arguments to be processed. If None, arguments are parsed from the command line.
856
+ Default is None.
857
+
858
+ Returns
859
+ -------
860
+ args : argparse.Namespace
861
+ Processed arguments namespace containing all parsed and defaulted values.
862
+
863
+ Notes
864
+ -----
865
+ - If no model is specified, the function sets a default based on whether PyTorch or TensorFlow
866
+ is being used.
867
+ - The function writes formatted command line arguments to files for logging purposes.
868
+ - Multiprocessing is currently disabled due to instability.
869
+ - The output level is adjusted based on user-provided increments and decrements.
870
+
871
+ Examples
872
+ --------
873
+ >>> args = process_args()
874
+ >>> print(args.outputroot)
875
+ >>> print(args.modelname)
750
876
  """
751
877
  args, argstowrite = pf.setargs(_get_parser, inputargs=inputargs)
752
878
 
753
879
  # save the raw and formatted command lines
754
880
  args.commandline = " ".join(argstowrite)
755
- tide_io.writevec([args.commandline], args.outputroot + "_commandline.txt")
881
+ tide_io.writevec(np.array([args.commandline]), args.outputroot + "_commandline.txt")
756
882
  formattedcommandline = []
757
883
  for thetoken in argstowrite[0:3]:
758
884
  formattedcommandline.append(thetoken)
@@ -771,7 +897,19 @@ def process_args(inputargs=None):
771
897
  else:
772
898
  suffix = ""
773
899
  formattedcommandline[i] = prefix + formattedcommandline[i] + suffix
774
- tide_io.writevec(formattedcommandline, args.outputroot + "_formattedcommandline.txt")
900
+ tide_io.writevec(np.array(formattedcommandline), args.outputroot + "_formattedcommandline.txt")
901
+
902
+ if not tensorflowpresent:
903
+ args.usepytorch = True
904
+ args.mpfix = False
905
+
906
+ # if user did not specify a model, set the default, depending on DL library
907
+ if args.modelname is None:
908
+ if args.usepytorch:
909
+ args.modelname = DEFAULT_PT_DL_MODEL
910
+ else:
911
+ args.modelname = DEFAULT_TF_DL_MODEL
912
+ print(f"No model specified. {args.usepytorch=}, so using {args.modelname}")
775
913
 
776
914
  if args.debug:
777
915
  print()
@@ -788,12 +926,12 @@ def process_args(inputargs=None):
788
926
  args.upsamplefac = 100
789
927
  args.centric = True
790
928
  args.pulsereconstepsize = 0.01
791
- args.unnormvesselmap = True
792
929
  args.histlen = 100
793
930
  args.softvesselfrac = 0.4
794
931
  args.savecardiacnoise = True
795
932
  args.colnum = None
796
933
  args.colname = None
934
+ args.notchrolloff = 0.5
797
935
 
798
936
  # Additional argument parsing not handled by argparse
799
937
  # deal with notch filter logic
@@ -807,6 +945,8 @@ def process_args(inputargs=None):
807
945
  args.motionfilename = None
808
946
 
809
947
  # set the number of worker processes if multiprocessing
948
+ # Multiprocessing is very broken atm. Hard disable it.
949
+ # args.nprocs = 1
810
950
  if args.nprocs < 1:
811
951
  args.nprocs = tide_multiproc.maxcpus()
812
952
 
@@ -19,8 +19,11 @@
19
19
  import argparse
20
20
  import copy
21
21
  import sys
22
+ from argparse import Namespace
23
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
22
24
 
23
25
  import numpy as np
26
+ from numpy.typing import NDArray
24
27
  from tqdm import tqdm
25
28
 
26
29
  import rapidtide.io as tide_io
@@ -29,7 +32,47 @@ import rapidtide.util as tide_util
29
32
  import rapidtide.workflows.parser_funcs as pf
30
33
 
31
34
 
32
- def _get_parser():
35
+ def _get_parser() -> Any:
36
+ """
37
+ Generate and return an argument parser for the histnifti command-line tool.
38
+
39
+ This function constructs an `argparse.ArgumentParser` object configured with
40
+ all necessary arguments for processing NIFTI files and generating histograms
41
+ of their voxel values. It supports various options for controlling binning,
42
+ masking, normalization, and display behavior.
43
+
44
+ Returns
45
+ -------
46
+ argparse.ArgumentParser
47
+ Configured argument parser object ready to parse command-line arguments.
48
+
49
+ Notes
50
+ -----
51
+ The parser includes the following positional and optional arguments:
52
+
53
+ - Positional arguments:
54
+ - inputfile: Path to the input NIFTI file.
55
+ - outputroot: Root name for output files.
56
+
57
+ - Optional arguments:
58
+ - --histlen: Set histogram length to LEN (default: auto).
59
+ - --minval: Minimum bin value in histogram.
60
+ - --maxval: Maximum bin value in histogram.
61
+ - --robustrange: Use robust range (2nd to 98th percentile) for histogram limits.
62
+ - --transform: Replace data values with their percentile scores.
63
+ - --nozero: Exclude zero values from histogram.
64
+ - --nozerothresh: Threshold for considering values as zero (default: 0.01).
65
+ - --normhist: Return probability density instead of raw counts.
66
+ - --maskfile: Only process voxels within a 3D mask.
67
+ - --nodisplay: Do not display histogram.
68
+
69
+ Examples
70
+ --------
71
+ >>> parser = _get_parser()
72
+ >>> args = parser.parse_args(['input.nii', 'output_root'])
73
+ >>> print(args.inputfile)
74
+ 'input.nii'
75
+ """
33
76
  # get the command line parameters
34
77
  parser = argparse.ArgumentParser(
35
78
  prog="histnifti",
@@ -119,7 +162,80 @@ def _get_parser():
119
162
  return parser
120
163
 
121
164
 
122
- def histnifti(args):
165
+ def histnifti(args: Any) -> None:
166
+ """
167
+ Compute and save histograms, sorted data, and percentiles from NIfTI image data.
168
+
169
+ This function reads input NIfTI data and optionally a mask, computes histograms
170
+ for each voxel (or across all voxels if 3D), and saves sorted data, percentiles,
171
+ and histogram results as NIfTI files. It supports both 3D and 4D data processing.
172
+
173
+ Parameters
174
+ ----------
175
+ args : argparse.Namespace
176
+ Command-line arguments containing:
177
+ - inputfile : str
178
+ Path to the input NIfTI file.
179
+ - maskfile : str, optional
180
+ Path to the mask NIfTI file. If None, a full mask is generated.
181
+ - outputroot : str
182
+ Root name for output files.
183
+ - robustrange : bool
184
+ If True, use 2nd and 98th percentiles for histogram range.
185
+ - minval : float, optional
186
+ Minimum value for histogram range.
187
+ - maxval : float, optional
188
+ Maximum value for histogram range.
189
+ - histlen : int, optional
190
+ Number of histogram bins. If None, computed based on data size.
191
+ - nozero : bool
192
+ If True, exclude zero values from histogram calculation.
193
+ - nozerothresh : float
194
+ Threshold for excluding zero-like values when `nozero` is True.
195
+ - transform : bool
196
+ If True, apply a transformation to the data.
197
+ - display : bool
198
+ If True, display histogram plots.
199
+ - normhist : bool
200
+ If True, normalize histogram values.
201
+
202
+ Returns
203
+ -------
204
+ None
205
+ This function does not return a value but saves multiple NIfTI files:
206
+ - `<outputroot>_sorted.nii.gz`: Sorted time series data.
207
+ - `<outputroot>_pcts.nii.gz`: Percentile values.
208
+ - `<outputroot>_hists.nii.gz`: Histogram data per voxel.
209
+ - `<outputroot>_transformed.nii.gz`: Transformed data (if `transform` is True).
210
+ - `<outputroot>_hist.txt`: Histogram plot (if `display` is True).
211
+
212
+ Notes
213
+ -----
214
+ - For 4D data, the function computes histograms, sorted arrays, and percentiles
215
+ for each voxel.
216
+ - For 3D data, the function can compute a global histogram or apply a transformation.
217
+ - The function uses `tide_io` for reading/writing NIfTI files and `tide_stats` for
218
+ statistical operations.
219
+
220
+ Examples
221
+ --------
222
+ >>> import argparse
223
+ >>> args = argparse.Namespace(
224
+ ... inputfile='data.nii.gz',
225
+ ... maskfile=None,
226
+ ... outputroot='output',
227
+ ... robustrange=False,
228
+ ... minval=None,
229
+ ... maxval=None,
230
+ ... histlen=None,
231
+ ... nozero=False,
232
+ ... nozerothresh=0.0,
233
+ ... transform=False,
234
+ ... display=False,
235
+ ... normhist=False
236
+ ... )
237
+ >>> histnifti(args)
238
+ """
123
239
  # set default variable values
124
240
  thepercentiles = [0.2, 0.25, 0.5, 0.75, 0.98]
125
241
  thepvalnames = []