rapidtide 2.9.5__py3-none-any.whl → 3.1.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.
Files changed (405) hide show
  1. cloud/gmscalc-HCPYA +1 -1
  2. cloud/mount-and-run +2 -0
  3. cloud/rapidtide-HCPYA +3 -3
  4. rapidtide/Colortables.py +538 -38
  5. rapidtide/OrthoImageItem.py +1094 -51
  6. rapidtide/RapidtideDataset.py +1709 -114
  7. rapidtide/__init__.py +0 -8
  8. rapidtide/_version.py +4 -4
  9. rapidtide/calccoherence.py +242 -97
  10. rapidtide/calcnullsimfunc.py +240 -140
  11. rapidtide/calcsimfunc.py +314 -129
  12. rapidtide/correlate.py +1211 -389
  13. rapidtide/data/examples/src/testLD +56 -0
  14. rapidtide/data/examples/src/test_findmaxlag.py +2 -2
  15. rapidtide/data/examples/src/test_mlregressallt.py +32 -17
  16. rapidtide/data/examples/src/testalign +1 -1
  17. rapidtide/data/examples/src/testatlasaverage +35 -7
  18. rapidtide/data/examples/src/testboth +21 -0
  19. rapidtide/data/examples/src/testcifti +11 -0
  20. rapidtide/data/examples/src/testdelayvar +13 -0
  21. rapidtide/data/examples/src/testdlfilt +25 -0
  22. rapidtide/data/examples/src/testfft +35 -0
  23. rapidtide/data/examples/src/testfileorfloat +37 -0
  24. rapidtide/data/examples/src/testfmri +94 -27
  25. rapidtide/data/examples/src/testfuncs +3 -3
  26. rapidtide/data/examples/src/testglmfilt +8 -6
  27. rapidtide/data/examples/src/testhappy +84 -51
  28. rapidtide/data/examples/src/testinitdelay +19 -0
  29. rapidtide/data/examples/src/testmodels +33 -0
  30. rapidtide/data/examples/src/testnewrefine +26 -0
  31. rapidtide/data/examples/src/testnoiseamp +21 -0
  32. rapidtide/data/examples/src/testppgproc +17 -0
  33. rapidtide/data/examples/src/testrefineonly +22 -0
  34. rapidtide/data/examples/src/testretro +26 -13
  35. rapidtide/data/examples/src/testretrolagtcs +16 -0
  36. rapidtide/data/examples/src/testrolloff +11 -0
  37. rapidtide/data/examples/src/testsimdata +45 -28
  38. rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
  39. rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
  40. rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
  41. rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
  42. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.png +0 -0
  43. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.txt +1 -0
  44. rapidtide/data/models/model_cnn_pytorch_fulldata/model.pth +0 -0
  45. rapidtide/data/models/model_cnn_pytorch_fulldata/model_meta.json +80 -0
  46. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.png +0 -0
  47. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.txt +1 -0
  48. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model.pth +0 -0
  49. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model_meta.json +138 -0
  50. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.png +0 -0
  51. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.txt +1 -0
  52. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model.pth +0 -0
  53. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model_meta.json +128 -0
  54. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.png +0 -0
  55. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.txt +1 -0
  56. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model.pth +0 -0
  57. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model_meta.json +49 -0
  58. rapidtide/data/models/model_revised_tf2/model.keras +0 -0
  59. rapidtide/data/models/{model_serdar → model_revised_tf2}/model_meta.json +1 -1
  60. rapidtide/data/models/model_serdar2_tf2/model.keras +0 -0
  61. rapidtide/data/models/{model_serdar2 → model_serdar2_tf2}/model_meta.json +1 -1
  62. rapidtide/data/models/model_serdar_tf2/model.keras +0 -0
  63. rapidtide/data/models/{model_revised → model_serdar_tf2}/model_meta.json +1 -1
  64. rapidtide/data/reference/HCP1200v2_MTT_2mm.nii.gz +0 -0
  65. rapidtide/data/reference/HCP1200v2_binmask_2mm.nii.gz +0 -0
  66. rapidtide/data/reference/HCP1200v2_csf_2mm.nii.gz +0 -0
  67. rapidtide/data/reference/HCP1200v2_gray_2mm.nii.gz +0 -0
  68. rapidtide/data/reference/HCP1200v2_graylaghist.json +7 -0
  69. rapidtide/data/reference/HCP1200v2_graylaghist.tsv.gz +0 -0
  70. rapidtide/data/reference/HCP1200v2_laghist.json +7 -0
  71. rapidtide/data/reference/HCP1200v2_laghist.tsv.gz +0 -0
  72. rapidtide/data/reference/HCP1200v2_mask_2mm.nii.gz +0 -0
  73. rapidtide/data/reference/HCP1200v2_maxcorr_2mm.nii.gz +0 -0
  74. rapidtide/data/reference/HCP1200v2_maxtime_2mm.nii.gz +0 -0
  75. rapidtide/data/reference/HCP1200v2_maxwidth_2mm.nii.gz +0 -0
  76. rapidtide/data/reference/HCP1200v2_negmask_2mm.nii.gz +0 -0
  77. rapidtide/data/reference/HCP1200v2_timepercentile_2mm.nii.gz +0 -0
  78. rapidtide/data/reference/HCP1200v2_white_2mm.nii.gz +0 -0
  79. rapidtide/data/reference/HCP1200v2_whitelaghist.json +7 -0
  80. rapidtide/data/reference/HCP1200v2_whitelaghist.tsv.gz +0 -0
  81. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2.xml +131 -0
  82. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_regions.txt +60 -0
  83. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_space-MNI152NLin6Asym_2mm.nii.gz +0 -0
  84. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm.nii.gz +0 -0
  85. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm_mask.nii.gz +0 -0
  86. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  87. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL2_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  88. rapidtide/data/reference/MNI152_T1_1mm_Brain_FAST_seg.nii.gz +0 -0
  89. rapidtide/data/reference/MNI152_T1_1mm_Brain_Mask.nii.gz +0 -0
  90. rapidtide/data/reference/MNI152_T1_2mm_Brain_FAST_seg.nii.gz +0 -0
  91. rapidtide/data/reference/MNI152_T1_2mm_Brain_Mask.nii.gz +0 -0
  92. rapidtide/decorators.py +91 -0
  93. rapidtide/dlfilter.py +2553 -414
  94. rapidtide/dlfiltertorch.py +5201 -0
  95. rapidtide/externaltools.py +328 -13
  96. rapidtide/fMRIData_class.py +178 -0
  97. rapidtide/ffttools.py +168 -0
  98. rapidtide/filter.py +2704 -1462
  99. rapidtide/fit.py +2361 -579
  100. rapidtide/genericmultiproc.py +197 -0
  101. rapidtide/happy_supportfuncs.py +3255 -548
  102. rapidtide/helper_classes.py +590 -1181
  103. rapidtide/io.py +2569 -468
  104. rapidtide/linfitfiltpass.py +784 -0
  105. rapidtide/makelaggedtcs.py +267 -97
  106. rapidtide/maskutil.py +555 -25
  107. rapidtide/miscmath.py +867 -137
  108. rapidtide/multiproc.py +217 -44
  109. rapidtide/patchmatch.py +752 -0
  110. rapidtide/peakeval.py +32 -32
  111. rapidtide/ppgproc.py +2205 -0
  112. rapidtide/qualitycheck.py +353 -40
  113. rapidtide/refinedelay.py +854 -0
  114. rapidtide/refineregressor.py +939 -0
  115. rapidtide/resample.py +725 -204
  116. rapidtide/scripts/__init__.py +1 -0
  117. rapidtide/scripts/{adjustoffset → adjustoffset.py} +7 -2
  118. rapidtide/scripts/{aligntcs → aligntcs.py} +7 -2
  119. rapidtide/scripts/{applydlfilter → applydlfilter.py} +7 -2
  120. rapidtide/scripts/applyppgproc.py +28 -0
  121. rapidtide/scripts/{atlasaverage → atlasaverage.py} +7 -2
  122. rapidtide/scripts/{atlastool → atlastool.py} +7 -2
  123. rapidtide/scripts/{calcicc → calcicc.py} +7 -2
  124. rapidtide/scripts/{calctexticc → calctexticc.py} +7 -2
  125. rapidtide/scripts/{calcttest → calcttest.py} +7 -2
  126. rapidtide/scripts/{ccorrica → ccorrica.py} +7 -2
  127. rapidtide/scripts/delayvar.py +28 -0
  128. rapidtide/scripts/{diffrois → diffrois.py} +7 -2
  129. rapidtide/scripts/{endtidalproc → endtidalproc.py} +7 -2
  130. rapidtide/scripts/{fdica → fdica.py} +7 -2
  131. rapidtide/scripts/{filtnifti → filtnifti.py} +7 -2
  132. rapidtide/scripts/{filttc → filttc.py} +7 -2
  133. rapidtide/scripts/{fingerprint → fingerprint.py} +20 -16
  134. rapidtide/scripts/{fixtr → fixtr.py} +7 -2
  135. rapidtide/scripts/{gmscalc → gmscalc.py} +7 -2
  136. rapidtide/scripts/{happy → happy.py} +7 -2
  137. rapidtide/scripts/{happy2std → happy2std.py} +7 -2
  138. rapidtide/scripts/{happywarp → happywarp.py} +8 -4
  139. rapidtide/scripts/{histnifti → histnifti.py} +7 -2
  140. rapidtide/scripts/{histtc → histtc.py} +7 -2
  141. rapidtide/scripts/{glmfilt → linfitfilt.py} +7 -4
  142. rapidtide/scripts/{localflow → localflow.py} +7 -2
  143. rapidtide/scripts/{mergequality → mergequality.py} +7 -2
  144. rapidtide/scripts/{pairproc → pairproc.py} +7 -2
  145. rapidtide/scripts/{pairwisemergenifti → pairwisemergenifti.py} +7 -2
  146. rapidtide/scripts/{physiofreq → physiofreq.py} +7 -2
  147. rapidtide/scripts/{pixelcomp → pixelcomp.py} +7 -2
  148. rapidtide/scripts/{plethquality → plethquality.py} +7 -2
  149. rapidtide/scripts/{polyfitim → polyfitim.py} +7 -2
  150. rapidtide/scripts/{proj2flow → proj2flow.py} +7 -2
  151. rapidtide/scripts/{rankimage → rankimage.py} +7 -2
  152. rapidtide/scripts/{rapidtide → rapidtide.py} +7 -2
  153. rapidtide/scripts/{rapidtide2std → rapidtide2std.py} +7 -2
  154. rapidtide/scripts/{resamplenifti → resamplenifti.py} +7 -2
  155. rapidtide/scripts/{resampletc → resampletc.py} +7 -2
  156. rapidtide/scripts/retrolagtcs.py +28 -0
  157. rapidtide/scripts/retroregress.py +28 -0
  158. rapidtide/scripts/{roisummarize → roisummarize.py} +7 -2
  159. rapidtide/scripts/{runqualitycheck → runqualitycheck.py} +7 -2
  160. rapidtide/scripts/{showarbcorr → showarbcorr.py} +7 -2
  161. rapidtide/scripts/{showhist → showhist.py} +7 -2
  162. rapidtide/scripts/{showstxcorr → showstxcorr.py} +7 -2
  163. rapidtide/scripts/{showtc → showtc.py} +7 -2
  164. rapidtide/scripts/{showxcorr_legacy → showxcorr_legacy.py} +8 -8
  165. rapidtide/scripts/{showxcorrx → showxcorrx.py} +7 -2
  166. rapidtide/scripts/{showxy → showxy.py} +7 -2
  167. rapidtide/scripts/{simdata → simdata.py} +7 -2
  168. rapidtide/scripts/{spatialdecomp → spatialdecomp.py} +7 -2
  169. rapidtide/scripts/{spatialfit → spatialfit.py} +7 -2
  170. rapidtide/scripts/{spatialmi → spatialmi.py} +7 -2
  171. rapidtide/scripts/{spectrogram → spectrogram.py} +7 -2
  172. rapidtide/scripts/stupidramtricks.py +238 -0
  173. rapidtide/scripts/{synthASL → synthASL.py} +7 -2
  174. rapidtide/scripts/{tcfrom2col → tcfrom2col.py} +7 -2
  175. rapidtide/scripts/{tcfrom3col → tcfrom3col.py} +7 -2
  176. rapidtide/scripts/{temporaldecomp → temporaldecomp.py} +7 -2
  177. rapidtide/scripts/{testhrv → testhrv.py} +1 -1
  178. rapidtide/scripts/{threeD → threeD.py} +7 -2
  179. rapidtide/scripts/{tidepool → tidepool.py} +7 -2
  180. rapidtide/scripts/{variabilityizer → variabilityizer.py} +7 -2
  181. rapidtide/simFuncClasses.py +2113 -0
  182. rapidtide/simfuncfit.py +312 -108
  183. rapidtide/stats.py +579 -247
  184. rapidtide/tests/.coveragerc +27 -6
  185. rapidtide-2.9.5.data/scripts/fdica → rapidtide/tests/cleanposttest +4 -6
  186. rapidtide/tests/happycomp +9 -0
  187. rapidtide/tests/resethappytargets +1 -1
  188. rapidtide/tests/resetrapidtidetargets +1 -1
  189. rapidtide/tests/resettargets +1 -1
  190. rapidtide/tests/runlocaltest +3 -3
  191. rapidtide/tests/showkernels +1 -1
  192. rapidtide/tests/test_aliasedcorrelate.py +4 -4
  193. rapidtide/tests/test_aligntcs.py +1 -1
  194. rapidtide/tests/test_calcicc.py +1 -1
  195. rapidtide/tests/test_cleanregressor.py +184 -0
  196. rapidtide/tests/test_congrid.py +70 -81
  197. rapidtide/tests/test_correlate.py +1 -1
  198. rapidtide/tests/test_corrpass.py +4 -4
  199. rapidtide/tests/test_delayestimation.py +54 -59
  200. rapidtide/tests/test_dlfiltertorch.py +437 -0
  201. rapidtide/tests/test_doresample.py +2 -2
  202. rapidtide/tests/test_externaltools.py +69 -0
  203. rapidtide/tests/test_fastresampler.py +9 -5
  204. rapidtide/tests/test_filter.py +96 -57
  205. rapidtide/tests/test_findmaxlag.py +50 -19
  206. rapidtide/tests/test_fullrunhappy_v1.py +15 -10
  207. rapidtide/tests/test_fullrunhappy_v2.py +19 -13
  208. rapidtide/tests/test_fullrunhappy_v3.py +28 -13
  209. rapidtide/tests/test_fullrunhappy_v4.py +30 -11
  210. rapidtide/tests/test_fullrunhappy_v5.py +62 -0
  211. rapidtide/tests/test_fullrunrapidtide_v1.py +61 -7
  212. rapidtide/tests/test_fullrunrapidtide_v2.py +27 -15
  213. rapidtide/tests/test_fullrunrapidtide_v3.py +28 -8
  214. rapidtide/tests/test_fullrunrapidtide_v4.py +16 -8
  215. rapidtide/tests/test_fullrunrapidtide_v5.py +15 -6
  216. rapidtide/tests/test_fullrunrapidtide_v6.py +142 -0
  217. rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
  218. rapidtide/tests/test_fullrunrapidtide_v8.py +66 -0
  219. rapidtide/tests/test_getparsers.py +158 -0
  220. rapidtide/tests/test_io.py +59 -18
  221. rapidtide/tests/{test_glmpass.py → test_linfitfiltpass.py} +10 -10
  222. rapidtide/tests/test_mi.py +1 -1
  223. rapidtide/tests/test_miscmath.py +1 -1
  224. rapidtide/tests/test_motionregress.py +5 -5
  225. rapidtide/tests/test_nullcorr.py +6 -9
  226. rapidtide/tests/test_padvec.py +216 -0
  227. rapidtide/tests/test_parserfuncs.py +101 -0
  228. rapidtide/tests/test_phaseanalysis.py +1 -1
  229. rapidtide/tests/test_rapidtideparser.py +59 -53
  230. rapidtide/tests/test_refinedelay.py +296 -0
  231. rapidtide/tests/test_runmisc.py +5 -5
  232. rapidtide/tests/test_sharedmem.py +60 -0
  233. rapidtide/tests/test_simroundtrip.py +132 -0
  234. rapidtide/tests/test_simulate.py +1 -1
  235. rapidtide/tests/test_stcorrelate.py +4 -2
  236. rapidtide/tests/test_timeshift.py +2 -2
  237. rapidtide/tests/test_valtoindex.py +1 -1
  238. rapidtide/tests/test_zRapidtideDataset.py +5 -3
  239. rapidtide/tests/utils.py +10 -9
  240. rapidtide/tidepoolTemplate.py +88 -70
  241. rapidtide/tidepoolTemplate.ui +60 -46
  242. rapidtide/tidepoolTemplate_alt.py +88 -53
  243. rapidtide/tidepoolTemplate_alt.ui +62 -52
  244. rapidtide/tidepoolTemplate_alt_qt6.py +921 -0
  245. rapidtide/tidepoolTemplate_big.py +1125 -0
  246. rapidtide/tidepoolTemplate_big.ui +2386 -0
  247. rapidtide/tidepoolTemplate_big_qt6.py +1129 -0
  248. rapidtide/tidepoolTemplate_qt6.py +793 -0
  249. rapidtide/util.py +1389 -148
  250. rapidtide/voxelData.py +1048 -0
  251. rapidtide/wiener.py +138 -25
  252. rapidtide/wiener2.py +114 -8
  253. rapidtide/workflows/adjustoffset.py +107 -5
  254. rapidtide/workflows/aligntcs.py +86 -3
  255. rapidtide/workflows/applydlfilter.py +231 -89
  256. rapidtide/workflows/applyppgproc.py +540 -0
  257. rapidtide/workflows/atlasaverage.py +309 -48
  258. rapidtide/workflows/atlastool.py +130 -9
  259. rapidtide/workflows/calcSimFuncMap.py +490 -0
  260. rapidtide/workflows/calctexticc.py +202 -10
  261. rapidtide/workflows/ccorrica.py +123 -15
  262. rapidtide/workflows/cleanregressor.py +415 -0
  263. rapidtide/workflows/delayvar.py +1268 -0
  264. rapidtide/workflows/diffrois.py +84 -6
  265. rapidtide/workflows/endtidalproc.py +149 -9
  266. rapidtide/workflows/fdica.py +197 -17
  267. rapidtide/workflows/filtnifti.py +71 -4
  268. rapidtide/workflows/filttc.py +76 -5
  269. rapidtide/workflows/fitSimFuncMap.py +578 -0
  270. rapidtide/workflows/fixtr.py +74 -4
  271. rapidtide/workflows/gmscalc.py +116 -6
  272. rapidtide/workflows/happy.py +1242 -480
  273. rapidtide/workflows/happy2std.py +145 -13
  274. rapidtide/workflows/happy_parser.py +277 -59
  275. rapidtide/workflows/histnifti.py +120 -4
  276. rapidtide/workflows/histtc.py +85 -4
  277. rapidtide/workflows/{glmfilt.py → linfitfilt.py} +128 -14
  278. rapidtide/workflows/localflow.py +329 -29
  279. rapidtide/workflows/mergequality.py +80 -4
  280. rapidtide/workflows/niftidecomp.py +323 -19
  281. rapidtide/workflows/niftistats.py +178 -8
  282. rapidtide/workflows/pairproc.py +99 -5
  283. rapidtide/workflows/pairwisemergenifti.py +86 -3
  284. rapidtide/workflows/parser_funcs.py +1488 -56
  285. rapidtide/workflows/physiofreq.py +139 -12
  286. rapidtide/workflows/pixelcomp.py +211 -9
  287. rapidtide/workflows/plethquality.py +105 -23
  288. rapidtide/workflows/polyfitim.py +159 -19
  289. rapidtide/workflows/proj2flow.py +76 -3
  290. rapidtide/workflows/rankimage.py +115 -8
  291. rapidtide/workflows/rapidtide.py +1833 -1919
  292. rapidtide/workflows/rapidtide2std.py +101 -3
  293. rapidtide/workflows/rapidtide_parser.py +607 -372
  294. rapidtide/workflows/refineDelayMap.py +249 -0
  295. rapidtide/workflows/refineRegressor.py +1215 -0
  296. rapidtide/workflows/regressfrommaps.py +308 -0
  297. rapidtide/workflows/resamplenifti.py +86 -4
  298. rapidtide/workflows/resampletc.py +92 -4
  299. rapidtide/workflows/retrolagtcs.py +442 -0
  300. rapidtide/workflows/retroregress.py +1501 -0
  301. rapidtide/workflows/roisummarize.py +176 -7
  302. rapidtide/workflows/runqualitycheck.py +72 -7
  303. rapidtide/workflows/showarbcorr.py +172 -16
  304. rapidtide/workflows/showhist.py +87 -3
  305. rapidtide/workflows/showstxcorr.py +161 -4
  306. rapidtide/workflows/showtc.py +172 -10
  307. rapidtide/workflows/showxcorrx.py +250 -62
  308. rapidtide/workflows/showxy.py +186 -16
  309. rapidtide/workflows/simdata.py +418 -112
  310. rapidtide/workflows/spatialfit.py +83 -8
  311. rapidtide/workflows/spatialmi.py +252 -29
  312. rapidtide/workflows/spectrogram.py +306 -33
  313. rapidtide/workflows/synthASL.py +157 -6
  314. rapidtide/workflows/tcfrom2col.py +77 -3
  315. rapidtide/workflows/tcfrom3col.py +75 -3
  316. rapidtide/workflows/tidepool.py +3829 -666
  317. rapidtide/workflows/utils.py +45 -19
  318. rapidtide/workflows/utils_doc.py +293 -0
  319. rapidtide/workflows/variabilityizer.py +118 -5
  320. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/METADATA +30 -223
  321. rapidtide-3.1.3.dist-info/RECORD +393 -0
  322. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/WHEEL +1 -1
  323. rapidtide-3.1.3.dist-info/entry_points.txt +65 -0
  324. rapidtide-3.1.3.dist-info/top_level.txt +2 -0
  325. rapidtide/calcandfitcorrpairs.py +0 -262
  326. rapidtide/data/examples/src/testoutputsize +0 -45
  327. rapidtide/data/models/model_revised/model.h5 +0 -0
  328. rapidtide/data/models/model_serdar/model.h5 +0 -0
  329. rapidtide/data/models/model_serdar2/model.h5 +0 -0
  330. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm.nii.gz +0 -0
  331. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  332. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm.nii.gz +0 -0
  333. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  334. rapidtide/data/reference/HCP1200_binmask_2mm_2009c_asym.nii.gz +0 -0
  335. rapidtide/data/reference/HCP1200_lag_2mm_2009c_asym.nii.gz +0 -0
  336. rapidtide/data/reference/HCP1200_mask_2mm_2009c_asym.nii.gz +0 -0
  337. rapidtide/data/reference/HCP1200_negmask_2mm_2009c_asym.nii.gz +0 -0
  338. rapidtide/data/reference/HCP1200_sigma_2mm_2009c_asym.nii.gz +0 -0
  339. rapidtide/data/reference/HCP1200_strength_2mm_2009c_asym.nii.gz +0 -0
  340. rapidtide/glmpass.py +0 -434
  341. rapidtide/refine_factored.py +0 -641
  342. rapidtide/scripts/retroglm +0 -23
  343. rapidtide/workflows/glmfrommaps.py +0 -202
  344. rapidtide/workflows/retroglm.py +0 -643
  345. rapidtide-2.9.5.data/scripts/adjustoffset +0 -23
  346. rapidtide-2.9.5.data/scripts/aligntcs +0 -23
  347. rapidtide-2.9.5.data/scripts/applydlfilter +0 -23
  348. rapidtide-2.9.5.data/scripts/atlasaverage +0 -23
  349. rapidtide-2.9.5.data/scripts/atlastool +0 -23
  350. rapidtide-2.9.5.data/scripts/calcicc +0 -22
  351. rapidtide-2.9.5.data/scripts/calctexticc +0 -23
  352. rapidtide-2.9.5.data/scripts/calcttest +0 -22
  353. rapidtide-2.9.5.data/scripts/ccorrica +0 -23
  354. rapidtide-2.9.5.data/scripts/diffrois +0 -23
  355. rapidtide-2.9.5.data/scripts/endtidalproc +0 -23
  356. rapidtide-2.9.5.data/scripts/filtnifti +0 -23
  357. rapidtide-2.9.5.data/scripts/filttc +0 -23
  358. rapidtide-2.9.5.data/scripts/fingerprint +0 -593
  359. rapidtide-2.9.5.data/scripts/fixtr +0 -23
  360. rapidtide-2.9.5.data/scripts/glmfilt +0 -24
  361. rapidtide-2.9.5.data/scripts/gmscalc +0 -22
  362. rapidtide-2.9.5.data/scripts/happy +0 -25
  363. rapidtide-2.9.5.data/scripts/happy2std +0 -23
  364. rapidtide-2.9.5.data/scripts/happywarp +0 -350
  365. rapidtide-2.9.5.data/scripts/histnifti +0 -23
  366. rapidtide-2.9.5.data/scripts/histtc +0 -23
  367. rapidtide-2.9.5.data/scripts/localflow +0 -23
  368. rapidtide-2.9.5.data/scripts/mergequality +0 -23
  369. rapidtide-2.9.5.data/scripts/pairproc +0 -23
  370. rapidtide-2.9.5.data/scripts/pairwisemergenifti +0 -23
  371. rapidtide-2.9.5.data/scripts/physiofreq +0 -23
  372. rapidtide-2.9.5.data/scripts/pixelcomp +0 -23
  373. rapidtide-2.9.5.data/scripts/plethquality +0 -23
  374. rapidtide-2.9.5.data/scripts/polyfitim +0 -23
  375. rapidtide-2.9.5.data/scripts/proj2flow +0 -23
  376. rapidtide-2.9.5.data/scripts/rankimage +0 -23
  377. rapidtide-2.9.5.data/scripts/rapidtide +0 -23
  378. rapidtide-2.9.5.data/scripts/rapidtide2std +0 -23
  379. rapidtide-2.9.5.data/scripts/resamplenifti +0 -23
  380. rapidtide-2.9.5.data/scripts/resampletc +0 -23
  381. rapidtide-2.9.5.data/scripts/retroglm +0 -23
  382. rapidtide-2.9.5.data/scripts/roisummarize +0 -23
  383. rapidtide-2.9.5.data/scripts/runqualitycheck +0 -23
  384. rapidtide-2.9.5.data/scripts/showarbcorr +0 -23
  385. rapidtide-2.9.5.data/scripts/showhist +0 -23
  386. rapidtide-2.9.5.data/scripts/showstxcorr +0 -23
  387. rapidtide-2.9.5.data/scripts/showtc +0 -23
  388. rapidtide-2.9.5.data/scripts/showxcorr_legacy +0 -536
  389. rapidtide-2.9.5.data/scripts/showxcorrx +0 -23
  390. rapidtide-2.9.5.data/scripts/showxy +0 -23
  391. rapidtide-2.9.5.data/scripts/simdata +0 -23
  392. rapidtide-2.9.5.data/scripts/spatialdecomp +0 -23
  393. rapidtide-2.9.5.data/scripts/spatialfit +0 -23
  394. rapidtide-2.9.5.data/scripts/spatialmi +0 -23
  395. rapidtide-2.9.5.data/scripts/spectrogram +0 -23
  396. rapidtide-2.9.5.data/scripts/synthASL +0 -23
  397. rapidtide-2.9.5.data/scripts/tcfrom2col +0 -23
  398. rapidtide-2.9.5.data/scripts/tcfrom3col +0 -23
  399. rapidtide-2.9.5.data/scripts/temporaldecomp +0 -23
  400. rapidtide-2.9.5.data/scripts/threeD +0 -236
  401. rapidtide-2.9.5.data/scripts/tidepool +0 -23
  402. rapidtide-2.9.5.data/scripts/variabilityizer +0 -23
  403. rapidtide-2.9.5.dist-info/RECORD +0 -357
  404. rapidtide-2.9.5.dist-info/top_level.txt +0 -86
  405. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,1501 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright 2024-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 argparse
20
+ import copy
21
+ import logging
22
+ import os
23
+ import platform
24
+ import sys
25
+ import time
26
+ from argparse import Namespace
27
+ from pathlib import Path
28
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
29
+
30
+ import numpy as np
31
+ from numpy.typing import NDArray
32
+
33
+ import rapidtide.filter as tide_filt
34
+ import rapidtide.io as tide_io
35
+ import rapidtide.maskutil as tide_mask
36
+ import rapidtide.miscmath as tide_math
37
+ import rapidtide.multiproc as tide_multiproc
38
+ import rapidtide.resample as tide_resample
39
+ import rapidtide.stats as tide_stats
40
+ import rapidtide.util as tide_util
41
+ import rapidtide.voxelData as tide_voxelData
42
+ import rapidtide.workflows.parser_funcs as pf
43
+ import rapidtide.workflows.refineDelayMap as tide_refineDelayMap
44
+ import rapidtide.workflows.regressfrommaps as tide_regressfrommaps
45
+
46
+ from .rapidtide_parser import DEFAULT_REGRESSIONFILTDERIVS
47
+ from .utils import setup_logger
48
+
49
+
50
+ # Create a sentinel.
51
+ # from https://stackoverflow.com/questions/58594956/find-out-which-arguments-were-passed-explicitly-in-argparse
52
+ class _Sentinel:
53
+ pass
54
+
55
+
56
+ sentinel = _Sentinel()
57
+ LGR = logging.getLogger(__name__)
58
+ ErrorLGR = logging.getLogger("ERROR")
59
+ TimingLGR = logging.getLogger("TIMING")
60
+
61
+ DEFAULT_REGRESSIONFILTDERIVS = 0
62
+ DEFAULT_PATCHTHRESH = 3.0
63
+ DEFAULT_REFINEDELAYMINDELAY = -5.0
64
+ DEFAULT_REFINEDELAYMAXDELAY = 5.0
65
+ DEFAULT_REFINEDELAYNUMPOINTS = 501
66
+ DEFAULT_DELAYOFFSETSPATIALFILT = -1
67
+
68
+
69
+ def _get_parser() -> Any:
70
+ """
71
+ Argument parser for glmfilt.
72
+
73
+ This function constructs and returns an `argparse.ArgumentParser` object configured
74
+ for the `glmfilt` command-line tool, which performs sLFO (spatially localized
75
+ filter) filtering using maps generated from a previous rapidtide analysis.
76
+
77
+ Returns
78
+ -------
79
+ argparse.ArgumentParser
80
+ Configured argument parser for the glmfilt command-line interface.
81
+
82
+ Notes
83
+ -----
84
+ The parser includes both standard and experimental options. Experimental options
85
+ are not fully tested and may not work as expected.
86
+
87
+ Examples
88
+ --------
89
+ >>> parser = _get_parser()
90
+ >>> args = parser.parse_args(['fmri.nii', 'dataset_root'])
91
+ >>> print(args.fmrifile)
92
+ 'fmri.nii'
93
+ """
94
+ parser = argparse.ArgumentParser(
95
+ prog="retroregress",
96
+ description="Do the rapidtide sLFO filtering using the maps generated from a previous analysis.",
97
+ allow_abbrev=False,
98
+ )
99
+
100
+ # Required arguments
101
+ parser.add_argument(
102
+ "fmrifile",
103
+ type=lambda x: pf.is_valid_file(parser, x),
104
+ help="The name of 4D nifti fmri file to filter.",
105
+ )
106
+ parser.add_argument(
107
+ "datafileroot",
108
+ type=str,
109
+ help="The root name of the previously run rapidtide dataset (everything up to but not including the underscore.)",
110
+ )
111
+ parser.add_argument(
112
+ "--alternateoutput",
113
+ dest="alternateoutput",
114
+ type=str,
115
+ help="Alternate output root (if not specified, will use the same root as the previous dataset).",
116
+ default=None,
117
+ )
118
+ parser.add_argument(
119
+ "--regressderivs",
120
+ dest="regressderivs",
121
+ action="store",
122
+ type=lambda x: pf.is_int(parser, x, minval=0),
123
+ metavar="NDERIVS",
124
+ help=(
125
+ f"When doing final GLM, include derivatives up to NDERIVS order. Default is {DEFAULT_REGRESSIONFILTDERIVS}"
126
+ ),
127
+ default=DEFAULT_REGRESSIONFILTDERIVS,
128
+ )
129
+ parser.add_argument(
130
+ "--nprocs",
131
+ dest="nprocs",
132
+ action="store",
133
+ type=int,
134
+ metavar="NPROCS",
135
+ help=(
136
+ "Use NPROCS worker processes for multiprocessing. "
137
+ "Setting NPROCS to less than 1 sets the number of "
138
+ "worker processes to n_cpus."
139
+ ),
140
+ default=1,
141
+ )
142
+ parser.add_argument(
143
+ "--numskip",
144
+ dest="numskip",
145
+ action="store",
146
+ type=lambda x: pf.is_int(parser, x, minval=0),
147
+ metavar="NUMSKIP",
148
+ help=("Skip NUMSKIP points at the beginning of the fmri file."),
149
+ default=0,
150
+ )
151
+ parser.add_argument(
152
+ "--outputlevel",
153
+ dest="outputlevel",
154
+ action="store",
155
+ type=str,
156
+ choices=["min", "less", "normal", "more", "max", "onlyregressors"],
157
+ help=(
158
+ "The level of file output produced. 'min' produces only absolutely essential files, 'less' adds in "
159
+ "the sLFO filtered data (rather than just filter efficacy metrics), 'normal' saves what you "
160
+ "would typically want around for interactive data exploration, "
161
+ "'more' adds files that are sometimes useful, and 'max' outputs anything you might possibly want. "
162
+ "Selecting 'max' will produce ~3x your input datafile size as output. 'onlyregressors' will ONLY generate the "
163
+ "voxelwise timecourses to filter and save them without actually running the filter. "
164
+ f'Default is "normal".'
165
+ ),
166
+ default="normal",
167
+ )
168
+ parser.add_argument(
169
+ "--noprogressbar",
170
+ dest="showprogressbar",
171
+ action="store_false",
172
+ help=("Will disable showing progress bars (helpful if stdout is going to a file)."),
173
+ default=True,
174
+ )
175
+ parser.add_argument(
176
+ "--makepseudofile",
177
+ dest="makepseudofile",
178
+ action="store_true",
179
+ help=("Make a simulated input file from the mean and the movingsignal."),
180
+ default=False,
181
+ )
182
+ parser.add_argument(
183
+ "--norefinedelay",
184
+ dest="refinedelay",
185
+ action="store_false",
186
+ help=("Do not calculate a refined delay map using GLM information."),
187
+ default=True,
188
+ )
189
+ parser.add_argument(
190
+ "--norefinecorr",
191
+ dest="refinecorr",
192
+ action="store_false",
193
+ help=(
194
+ "Don't recalculate the maxcorr map using GLM coefficient of determination from bandpassed data."
195
+ ),
196
+ default=True,
197
+ )
198
+ parser.add_argument(
199
+ "--nofilterwithrefineddelay",
200
+ dest="filterwithrefineddelay",
201
+ action="store_false",
202
+ help=("Do not use the refined delay in sLFO filter."),
203
+ default=True,
204
+ )
205
+ parser.add_argument(
206
+ "--delaypatchthresh",
207
+ dest="delaypatchthresh",
208
+ action="store",
209
+ type=float,
210
+ metavar="NUMMADs",
211
+ help=(
212
+ "Maximum number of robust standard deviations to permit in the offset delay refine map. "
213
+ f"Default is {DEFAULT_PATCHTHRESH}"
214
+ ),
215
+ default=DEFAULT_PATCHTHRESH,
216
+ )
217
+ parser.add_argument(
218
+ "--delayoffsetspatialfilt",
219
+ dest="delayoffsetgausssigma",
220
+ action="store",
221
+ type=float,
222
+ metavar="GAUSSSIGMA",
223
+ help=(
224
+ "Spatially filter fMRI data prior to calculating delay offsets "
225
+ "using GAUSSSIGMA in mm. Set GAUSSSIGMA negative "
226
+ "to have rapidtide set it to half the mean voxel "
227
+ "dimension (a rule of thumb for a good value)."
228
+ ),
229
+ default=DEFAULT_DELAYOFFSETSPATIALFILT,
230
+ )
231
+ parser.add_argument(
232
+ "--debug",
233
+ dest="debug",
234
+ action="store_true",
235
+ help=("Output lots of helpful information."),
236
+ default=False,
237
+ )
238
+ parser.add_argument(
239
+ "--focaldebug",
240
+ dest="focaldebug",
241
+ action="store_true",
242
+ help=("Output lots of helpful information on a limited subset of operations."),
243
+ default=False,
244
+ )
245
+ parser.add_argument(
246
+ "--sLFOfiltmask",
247
+ dest="sLFOfiltmask",
248
+ action="store_true",
249
+ help=("Limit sLFO filter to fit voxels."),
250
+ default=False,
251
+ )
252
+ experimental = parser.add_argument_group(
253
+ "Experimental options (not fully tested, or not tested at all, may not work). Beware!"
254
+ )
255
+
256
+ return parser
257
+
258
+
259
+ def retroregress(args: Any) -> None:
260
+ """
261
+ Perform retrospective regression analysis on fMRI data to filter out slow
262
+ physiological noise (sLFO).
263
+
264
+ This function applies a retrospective regression approach to remove slow
265
+ physiological noise from fMRI data. It uses a delayed sLFO regressor to
266
+ model and remove the noise, optionally refining the delay using temporal
267
+ derivatives of the regressor.
268
+
269
+ Parameters
270
+ ----------
271
+ args : argparse.Namespace
272
+ Command-line arguments parsed by argparse. Expected attributes include:
273
+ - data_root : str
274
+ Root path for input data files
275
+ - output_prefix : str
276
+ Prefix for output files
277
+ - filter_type : str
278
+ Type of filtering to apply (e.g., 'bandpass')
279
+ - filter_low : float
280
+ Low cutoff frequency for filtering
281
+ - filter_high : float
282
+ High cutoff frequency for filtering
283
+ - regress_derivs : int
284
+ Number of temporal derivatives to include in the regressor
285
+ - refinedelay : bool
286
+ Whether to refine the delay using temporal derivatives
287
+ - refinecorr : bool
288
+ Whether to compute correlation refinement
289
+ - savemovingsignal : bool
290
+ Whether to save the filtered signal
291
+ - savenormalsLFOfiltfiles : bool
292
+ Whether to save standard output files
293
+ - saveminimumsLFOfiltfiles : bool
294
+ Whether to save minimum output files
295
+ - saveallsLFOfiltfiles : bool
296
+ Whether to save all output files
297
+ - makepseudofile : bool
298
+ Whether to create a pseudo-file
299
+ - nprocs : int
300
+ Number of processes to use
301
+ - debug : bool
302
+ Enable debug mode
303
+ - focaldebug : bool
304
+ Enable focal debug mode
305
+
306
+ Returns
307
+ -------
308
+ None
309
+ This function does not return a value but writes output files to disk.
310
+
311
+ Notes
312
+ -----
313
+ The function performs the following steps:
314
+ 1. Reads input data files including mean image, correlation mask, and processed mask
315
+ 2. Applies temporal filtering to the input data
316
+ 3. Performs GLM regression using delayed sLFO regressors
317
+ 4. Refines delay if requested using temporal derivatives
318
+ 5. Saves output files including filtered data, regressors, and timing information
319
+
320
+ Examples
321
+ --------
322
+ >>> import argparse
323
+ >>> args = argparse.Namespace(
324
+ ... data_root='path/to/data',
325
+ ... output_prefix='output',
326
+ ... filter_type='bandpass',
327
+ ... filter_low=0.01,
328
+ ... filter_high=0.1,
329
+ ... regress_derivs=2,
330
+ ... refinedelay=True,
331
+ ... refinecorr=False,
332
+ ... savemovingsignal=True,
333
+ ... savenormalsLFOfiltfiles=True,
334
+ ... saveminimumsLFOfiltfiles=True,
335
+ ... saveallsLFOfiltfiles=False,
336
+ ... makepseudofile=False,
337
+ ... nprocs=4,
338
+ ... debug=False,
339
+ ... focaldebug=False
340
+ ... )
341
+ >>> retroregress(args)
342
+ """
343
+ # get the pid of the parent process
344
+ args.pid = os.getpid()
345
+
346
+ # specify the output name
347
+ if args.alternateoutput is None:
348
+ outputname = args.datafileroot
349
+ else:
350
+ outputname = args.alternateoutput
351
+
352
+ # start the loggers low that we know the output name
353
+ sh = logging.StreamHandler()
354
+ if args.debug:
355
+ logging.basicConfig(level=logging.DEBUG, handlers=[sh])
356
+ else:
357
+ logging.basicConfig(level=logging.INFO, handlers=[sh])
358
+ # Set up loggers for workflow
359
+ setup_logger(
360
+ logger_filename=f"{outputname}_retrolog.txt",
361
+ timing_filename=f"{outputname}_retroruntimings.tsv",
362
+ error_filename=f"{outputname}_retroerrorlog.txt",
363
+ isverbose=False,
364
+ debug=args.debug,
365
+ )
366
+ TimingLGR.info("Start")
367
+ LGR.info(f"starting retroregress")
368
+
369
+ # set some global values
370
+ args.mindelay = DEFAULT_REFINEDELAYMINDELAY
371
+ args.maxdelay = DEFAULT_REFINEDELAYMAXDELAY
372
+ args.numpoints = DEFAULT_REFINEDELAYNUMPOINTS
373
+
374
+ if args.outputlevel == "min":
375
+ args.saveminimumsLFOfiltfiles = False
376
+ args.savenormalsLFOfiltfiles = False
377
+ args.savemovingsignal = False
378
+ args.saveallsLFOfiltfiles = False
379
+ args.saveEVsandquit = False
380
+ elif args.outputlevel == "less":
381
+ args.saveminimumsLFOfiltfiles = True
382
+ args.savenormalsLFOfiltfiles = False
383
+ args.savemovingsignal = False
384
+ args.saveallsLFOfiltfiles = False
385
+ args.saveEVsandquit = False
386
+ elif args.outputlevel == "normal":
387
+ args.saveminimumsLFOfiltfiles = True
388
+ args.savenormalsLFOfiltfiles = True
389
+ args.savemovingsignal = False
390
+ args.saveallsLFOfiltfiles = False
391
+ args.saveEVsandquit = False
392
+ elif args.outputlevel == "more":
393
+ args.saveminimumsLFOfiltfiles = True
394
+ args.savenormalsLFOfiltfiles = True
395
+ args.savemovingsignal = True
396
+ args.saveallsLFOfiltfiles = False
397
+ args.saveEVsandquit = False
398
+ elif args.outputlevel == "max":
399
+ args.saveminimumsLFOfiltfiles = True
400
+ args.savenormalsLFOfiltfiles = True
401
+ args.savemovingsignal = True
402
+ args.saveallsLFOfiltfiles = True
403
+ args.saveEVsandquit = False
404
+ elif args.outputlevel == "onlyregressors":
405
+ args.saveminimumsLFOfiltfiles = False
406
+ args.savenormalsLFOfiltfiles = False
407
+ args.savemovingsignal = False
408
+ args.saveallsLFOfiltfiles = False
409
+ args.saveEVsandquit = True
410
+ else:
411
+ print(f"illegal output level {args.outputlevel}")
412
+ sys.exit()
413
+
414
+ # save the raw and formatted command lines
415
+ argstowrite = sys.argv
416
+ thecommandline = " ".join(sys.argv[1:])
417
+ tide_io.writevec(np.asarray([thecommandline]), f"{outputname}_retrocommandline.txt")
418
+ formattedcommandline = []
419
+ for thetoken in argstowrite[0:3]:
420
+ formattedcommandline.append(thetoken)
421
+ for thetoken in argstowrite[3:]:
422
+ if thetoken[0:2] == "--":
423
+ formattedcommandline.append(thetoken)
424
+ else:
425
+ formattedcommandline[-1] += " " + thetoken
426
+ for i in range(len(formattedcommandline)):
427
+ if i > 0:
428
+ prefix = " "
429
+ else:
430
+ prefix = ""
431
+ if i < len(formattedcommandline) - 1:
432
+ suffix = " \\"
433
+ else:
434
+ suffix = ""
435
+ formattedcommandline[i] = prefix + formattedcommandline[i] + suffix
436
+ tide_io.writevec(
437
+ np.asarray(formattedcommandline), f"{outputname}_retroformattedcommandline.txt"
438
+ )
439
+
440
+ if args.nprocs < 1:
441
+ args.nprocs = tide_multiproc.maxcpus()
442
+ # don't use shared memory if there is only one process
443
+ if args.nprocs == 1:
444
+ usesharedmem = False
445
+ else:
446
+ usesharedmem = True
447
+
448
+ # read the runoptions file, update if necessary
449
+ print("reading runoptions")
450
+ runoptionsfile = f"{args.datafileroot}_desc-runoptions_info"
451
+ therunoptions = tide_io.readoptionsfile(runoptionsfile)
452
+ sublist = (
453
+ ("retroglmcompatible", "retroregresscompatible"),
454
+ ("glmthreshval", "regressfiltthreshval"),
455
+ )
456
+ therunoptions["singleproc_regressionfilt"] = False
457
+ therunoptions["nprocs_regressionfilt"] = args.nprocs
458
+ for subpair in sublist:
459
+ try:
460
+ therunoptions[subpair[1]] = therunoptions[subpair[0]]
461
+ print(f"substituting {subpair[1]} for {subpair[0]} in runoptions")
462
+ except KeyError:
463
+ pass
464
+
465
+ try:
466
+ candoretroregress = therunoptions["retroregresscompatible"]
467
+ except KeyError:
468
+ print(
469
+ f"based on {runoptionsfile}, this rapidtide dataset does not support retrospective GLM calculation"
470
+ )
471
+ sys.exit()
472
+
473
+ if therunoptions["internalprecision"] == "double":
474
+ rt_floattype = np.dtype(np.float64)
475
+ else:
476
+ rt_floattype = np.dtype(np.float32)
477
+
478
+ # set the output precision
479
+ if therunoptions["outputprecision"] == "double":
480
+ rt_outfloattype = np.dtype(np.float64)
481
+ else:
482
+ rt_outfloattype = np.dtype(np.float32)
483
+ therunoptions["saveminimumsLFOfiltfiles"] = args.saveminimumsLFOfiltfiles
484
+
485
+ # read the fmri input files
486
+ print("reading fmrifile")
487
+ theinputdata = tide_voxelData.VoxelData(args.fmrifile)
488
+ xsize, ysize, numslices, timepoints = theinputdata.getdims()
489
+ xdim, ydim, slicethickness, fmritr = theinputdata.getsizes()
490
+ fmri_header = theinputdata.copyheader()
491
+ fmri_data = theinputdata.byvol()
492
+ numspatiallocs = theinputdata.numspatiallocs
493
+
494
+ # create the canary file
495
+ Path(f"{outputname}_RETROISRUNNING.txt").touch()
496
+
497
+ if args.debug:
498
+ print(f"{fmri_data.shape=}")
499
+ fmri_data_spacebytime = theinputdata.byvoxel()
500
+ if args.debug:
501
+ print(f"{fmri_data_spacebytime.shape=}")
502
+
503
+ # read the processed mask
504
+ print("reading procfit maskfile")
505
+ procmaskfile = f"{args.datafileroot}_desc-processed_mask.nii.gz"
506
+ (
507
+ procmask_input,
508
+ procmask,
509
+ procmask_header,
510
+ procmask_dims,
511
+ procmask_sizes,
512
+ ) = tide_io.readfromnifti(procmaskfile)
513
+ if not tide_io.checkspacematch(fmri_header, procmask_header):
514
+ raise ValueError("procmask dimensions do not match fmri dimensions")
515
+ procmask_spacebytime = procmask.reshape((numspatiallocs))
516
+ if args.debug:
517
+ print(f"{procmask_spacebytime.shape=}")
518
+ print(f"{tide_stats.getmasksize(procmask_spacebytime)=}")
519
+
520
+ # read the corrfit mask
521
+ print("reading corrfit maskfile")
522
+ corrmaskfile = f"{args.datafileroot}_desc-corrfit_mask.nii.gz"
523
+ (
524
+ corrmask_input,
525
+ corrmask,
526
+ corrmask_header,
527
+ corrmask_dims,
528
+ corrmask_sizes,
529
+ ) = tide_io.readfromnifti(corrmaskfile)
530
+ if not tide_io.checkspacematch(fmri_header, corrmask_header):
531
+ raise ValueError("corrmask dimensions do not match fmri dimensions")
532
+ corrmask_spacebytime = corrmask.reshape((numspatiallocs))
533
+ if args.debug:
534
+ print(f"{corrmask_spacebytime.shape=}")
535
+ print(f"{tide_stats.getmasksize(corrmask_spacebytime)=}")
536
+
537
+ print("reading lagtimes")
538
+ lagtimesfile = f"{args.datafileroot}_desc-maxtime_map.nii.gz"
539
+ (
540
+ lagtimes_input,
541
+ lagtimes,
542
+ lagtimes_header,
543
+ lagtimes_dims,
544
+ lagtimes_sizes,
545
+ ) = tide_io.readfromnifti(lagtimesfile)
546
+ if not tide_io.checkspacematch(fmri_header, lagtimes_header):
547
+ raise ValueError("lagtimes dimensions do not match fmri dimensions")
548
+ if args.debug:
549
+ print(f"{lagtimes.shape=}")
550
+ lagtimes_spacebytime = lagtimes.reshape((numspatiallocs))
551
+ if args.debug:
552
+ print(f"{lagtimes_spacebytime.shape=}")
553
+
554
+ startpt = args.numskip
555
+ endpt = timepoints - 1
556
+ validtimepoints = endpt - startpt + 1
557
+ skiptime = startpt * fmritr
558
+ initial_fmri_x = (
559
+ np.linspace(0.0, validtimepoints * fmritr, num=validtimepoints, endpoint=False) + skiptime
560
+ )
561
+
562
+ if therunoptions["arbvec"] is not None:
563
+ # NOTE - this vector is LOWERPASS, UPPERPASS, LOWERSTOP, UPPERSTOP
564
+ # setfreqs expects LOWERSTOP, LOWERPASS, UPPERPASS, UPPERSTOP
565
+ theprefilter = tide_filt.NoncausalFilter(
566
+ "arb",
567
+ transferfunc=therunoptions["filtertype"],
568
+ )
569
+ theprefilter.setfreqs(
570
+ therunoptions["arbvec"][2],
571
+ therunoptions["arbvec"][0],
572
+ therunoptions["arbvec"][1],
573
+ therunoptions["arbvec"][3],
574
+ )
575
+ else:
576
+ theprefilter = tide_filt.NoncausalFilter(
577
+ therunoptions["filterband"],
578
+ transferfunc=therunoptions["filtertype"],
579
+ padtime=therunoptions["padseconds"],
580
+ )
581
+
582
+ # read the lagtc generator file
583
+ print("reading lagtc generator")
584
+ lagtcgeneratorfile = f"{args.datafileroot}_desc-lagtcgenerator_timeseries"
585
+ try:
586
+ thepadtime = therunoptions["fastresamplerpadtime"]
587
+ except KeyError:
588
+ thepadtime = therunoptions["padseconds"]
589
+ genlagtc = tide_resample.FastResamplerFromFile(lagtcgeneratorfile, padtime=thepadtime)
590
+
591
+ # select the voxels in the mask
592
+ print("figuring out valid voxels")
593
+ validvoxels = np.where(procmask_spacebytime > 0)[0]
594
+ numvalidspatiallocs = np.shape(validvoxels)[0]
595
+ if args.debug:
596
+ print(f"{numvalidspatiallocs=}")
597
+ internalvalidspaceshape = numvalidspatiallocs
598
+ if args.refinedelay:
599
+ derivaxissize = np.max([2, args.regressderivs + 1])
600
+ else:
601
+ derivaxissize = args.regressderivs + 1
602
+ internalvalidspaceshapederivs = (
603
+ internalvalidspaceshape,
604
+ derivaxissize,
605
+ )
606
+ internalvalidfmrishape = (numvalidspatiallocs, np.shape(initial_fmri_x)[0])
607
+ if args.debug:
608
+ print(f"validvoxels shape = {numvalidspatiallocs}")
609
+ print(f"internalvalidfmrishape shape = {internalvalidfmrishape}")
610
+
611
+ # slicing to valid voxels
612
+ print("selecting valid voxels")
613
+ fmri_data_valid = fmri_data_spacebytime[validvoxels, :]
614
+ lagtimes_valid = lagtimes_spacebytime[validvoxels]
615
+ corrmask_valid = corrmask_spacebytime[validvoxels]
616
+ procmask_valid = procmask_spacebytime[validvoxels]
617
+ if args.sLFOfiltmask:
618
+ sLFOfiltmask_valid = corrmask_spacebytime[validvoxels] + 0.0
619
+ else:
620
+ sLFOfiltmask_valid = np.ones_like(corrmask_spacebytime[validvoxels])
621
+ if args.debug:
622
+ print(f"{fmri_data_valid.shape=}")
623
+
624
+ sLFOfitmean, sLFOfitmean_shm = tide_util.allocarray(
625
+ internalvalidspaceshape, rt_outfloattype, shared=usesharedmem
626
+ )
627
+ rvalue, rvalue_shm = tide_util.allocarray(
628
+ internalvalidspaceshape, rt_outfloattype, shared=usesharedmem
629
+ )
630
+ r2value, r2value_shm = tide_util.allocarray(
631
+ internalvalidspaceshape, rt_outfloattype, shared=usesharedmem
632
+ )
633
+ fitNorm, fitNorm_shm = tide_util.allocarray(
634
+ internalvalidspaceshapederivs, rt_outfloattype, shared=usesharedmem
635
+ )
636
+ fitcoeff, fitcoeff_shm = tide_util.allocarray(
637
+ internalvalidspaceshapederivs, rt_outfloattype, shared=usesharedmem
638
+ )
639
+ movingsignal, movingsignal_shm = tide_util.allocarray(
640
+ internalvalidfmrishape, rt_outfloattype, shared=usesharedmem
641
+ )
642
+ lagtc, lagtc_shm = tide_util.allocarray(
643
+ internalvalidfmrishape, rt_floattype, shared=usesharedmem
644
+ )
645
+ filtereddata, filtereddata_shm = tide_util.allocarray(
646
+ internalvalidfmrishape, rt_outfloattype, shared=usesharedmem
647
+ )
648
+ if usesharedmem:
649
+ if args.debug:
650
+ print("allocating shared memory")
651
+ ramlocation = "in shared memory"
652
+ else:
653
+ if args.debug:
654
+ print("allocating memory")
655
+ ramlocation = "locally"
656
+
657
+ totalbytes = (
658
+ sLFOfitmean.nbytes
659
+ + rvalue.nbytes
660
+ + r2value.nbytes
661
+ + fitNorm.nbytes
662
+ + fitcoeff.nbytes
663
+ + movingsignal.nbytes
664
+ + lagtc.nbytes
665
+ + filtereddata.nbytes
666
+ )
667
+ thesize, theunit = tide_util.format_bytes(totalbytes)
668
+ ramstring = f"allocated {thesize:.3f} {theunit} {ramlocation}"
669
+ print(ramstring)
670
+ therunoptions["totalretrobytes"] = totalbytes
671
+
672
+ oversampfactor = int(therunoptions["oversampfactor"])
673
+ if args.debug:
674
+ print(f"{outputname=}")
675
+ oversamptr = fmritr / oversampfactor
676
+ try:
677
+ threshval = therunoptions["regressfiltthreshval"]
678
+ except KeyError:
679
+ threshval = 0.0
680
+ therunoptions["regressfiltthreshval"] = threshval
681
+ mode = "glm"
682
+
683
+ if args.debug:
684
+ print(f"{validvoxels.shape=}")
685
+ np.savetxt(f"{outputname}_validvoxels.txt", validvoxels)
686
+
687
+ outputpath = os.path.dirname(outputname)
688
+ rawsources = [
689
+ os.path.relpath(args.fmrifile, start=outputpath),
690
+ os.path.relpath(lagtimesfile, start=outputpath),
691
+ os.path.relpath(corrmaskfile, start=outputpath),
692
+ os.path.relpath(procmaskfile, start=outputpath),
693
+ os.path.relpath(runoptionsfile, start=outputpath),
694
+ os.path.relpath(lagtcgeneratorfile, start=outputpath),
695
+ ]
696
+
697
+ bidsbasedict = {
698
+ "RawSources": rawsources,
699
+ "Units": "arbitrary",
700
+ "CommandLineArgs": thecommandline,
701
+ }
702
+
703
+ if args.debug:
704
+ # dump the fmri input file going to glm
705
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
706
+
707
+ maplist = [
708
+ (
709
+ fmri_data_valid,
710
+ "inputdata",
711
+ "bold",
712
+ None,
713
+ "fMRI data that will be subjected to sLFO filtering",
714
+ ),
715
+ ]
716
+ tide_io.savemaplist(
717
+ outputname,
718
+ maplist,
719
+ validvoxels,
720
+ (xsize, ysize, numslices, validtimepoints),
721
+ theheader,
722
+ bidsbasedict,
723
+ filetype=theinputdata.filetype,
724
+ rt_floattype=rt_floattype,
725
+ cifti_hdr=None,
726
+ )
727
+
728
+ # refine the delay value prior to calculating the GLM
729
+ if args.refinedelay:
730
+ print("\n\nDelay refinement")
731
+ TimingLGR.info("Delay refinement start")
732
+ LGR.info("\n\nDelay refinement")
733
+
734
+ if args.delayoffsetgausssigma < 0.0:
735
+ # set gausssigma automatically
736
+ args.delayoffsetgausssigma = np.mean([xdim, ydim, slicethickness]) / 2.0
737
+
738
+ (
739
+ delayoffset,
740
+ regressderivratios,
741
+ medfiltregressderivratios,
742
+ filteredregressderivratios,
743
+ delayoffsetMAD,
744
+ ) = tide_refineDelayMap.refineDelay(
745
+ fmri_data_valid,
746
+ initial_fmri_x,
747
+ xdim,
748
+ ydim,
749
+ slicethickness,
750
+ sLFOfiltmask_valid,
751
+ genlagtc,
752
+ oversamptr,
753
+ sLFOfitmean,
754
+ rvalue,
755
+ r2value,
756
+ fitNorm,
757
+ fitcoeff,
758
+ lagtc,
759
+ outputname,
760
+ validvoxels,
761
+ theinputdata.nativespaceshape,
762
+ theinputdata,
763
+ lagtimes_valid,
764
+ therunoptions,
765
+ LGR,
766
+ TimingLGR,
767
+ outputlevel=args.outputlevel,
768
+ gausssigma=args.delayoffsetgausssigma,
769
+ patchthresh=args.delaypatchthresh,
770
+ mindelay=args.mindelay,
771
+ maxdelay=args.maxdelay,
772
+ numpoints=args.numpoints,
773
+ histlen=therunoptions["histlen"],
774
+ rt_floattype=rt_floattype,
775
+ debug=args.debug,
776
+ )
777
+
778
+ refinedvoxelstoreport = filteredregressderivratios.shape[0]
779
+
780
+ lagtimesrefined_valid = lagtimes_valid + delayoffset
781
+
782
+ TimingLGR.info(
783
+ "Delay offset calculation done",
784
+ {
785
+ "message2": refinedvoxelstoreport,
786
+ "message3": "voxels",
787
+ },
788
+ )
789
+ ####################################################
790
+ # Delay refinement end
791
+ ####################################################
792
+
793
+ initialvariance = tide_math.imagevariance(fmri_data_valid, theprefilter, 1.0 / fmritr)
794
+
795
+ print("calling regressfrommaps")
796
+ TimingLGR.info("Starting sLFO filtering")
797
+ if args.refinedelay and args.filterwithrefineddelay:
798
+ lagstouse_valid = lagtimesrefined_valid
799
+ else:
800
+ lagstouse_valid = lagtimes_valid
801
+ voxelsprocessed_regressionfilt, regressorset, evset = tide_regressfrommaps.regressfrommaps(
802
+ fmri_data_valid,
803
+ validvoxels,
804
+ initial_fmri_x,
805
+ lagstouse_valid,
806
+ sLFOfiltmask_valid,
807
+ genlagtc,
808
+ mode,
809
+ outputname,
810
+ oversamptr,
811
+ sLFOfitmean,
812
+ rvalue,
813
+ r2value,
814
+ fitNorm[:, : args.regressderivs + 1],
815
+ fitcoeff[:, : args.regressderivs + 1],
816
+ movingsignal,
817
+ lagtc,
818
+ filtereddata,
819
+ LGR,
820
+ TimingLGR,
821
+ threshval,
822
+ args.saveminimumsLFOfiltfiles,
823
+ nprocs_makelaggedtcs=args.nprocs,
824
+ nprocs_regressionfilt=args.nprocs,
825
+ regressderivs=args.regressderivs,
826
+ showprogressbar=args.showprogressbar,
827
+ saveEVsandquit=args.saveEVsandquit,
828
+ debug=args.debug,
829
+ )
830
+
831
+ if not args.saveEVsandquit:
832
+ print(f"filtered {voxelsprocessed_regressionfilt} voxels")
833
+ TimingLGR.info(
834
+ "sLFO filtering done",
835
+ {
836
+ "message2": voxelsprocessed_regressionfilt,
837
+ "message3": "voxels",
838
+ },
839
+ )
840
+ finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
841
+
842
+ divlocs = np.where(finalvariance > 0.0)
843
+ varchange = np.zeros_like(initialvariance)
844
+ varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
845
+
846
+ # calculate the voxelwise mean of the filtered data
847
+ lfofilteredmeanvalue = np.mean(
848
+ filtereddata,
849
+ axis=1,
850
+ )
851
+
852
+ # save regional timecourses if masks are defined
853
+ # read in the anatomic masks
854
+ anatomiclist = [
855
+ ["brainmaskincludename", "brainmaskincludevals", "brainmask"],
856
+ ["graymatterincludename", "graymatterincludevals", "graymattermask"],
857
+ ["whitematterincludename", "whitematterincludevals", "whitemattermask"],
858
+ ["csfincludename", "csfincludevals", "csfmask"],
859
+ ]
860
+ anatomicmasks = []
861
+ for thisanatomic in anatomiclist:
862
+ try:
863
+ thename = therunoptions[thisanatomic[0]]
864
+ except KeyError:
865
+ therunoptions[thisanatomic[0]] = None
866
+ if therunoptions[thisanatomic[0]] is not None:
867
+ anatomicmasks.append(
868
+ tide_mask.readamask(
869
+ therunoptions[thisanatomic[0]],
870
+ theinputdata.nim_hdr,
871
+ xsize,
872
+ istext=(theinputdata.filetype == "text"),
873
+ valslist=therunoptions[thisanatomic[1]],
874
+ maskname=thisanatomic[2],
875
+ tolerance=therunoptions["spatialtolerance"],
876
+ debug=args.focaldebug,
877
+ )
878
+ )
879
+ anatomicmasks[-1] = np.uint16(np.where(anatomicmasks[-1] > 0.1, 1, 0))
880
+ else:
881
+ anatomicmasks.append(None)
882
+ brainmask = anatomicmasks[0]
883
+ graymask = anatomicmasks[1]
884
+ whitemask = anatomicmasks[2]
885
+ csfmask = anatomicmasks[3]
886
+
887
+ """if internalinitregressorincludemask is not None:
888
+ thisincludemask = internalinitregressorincludemask[validvoxels]
889
+ else:
890
+ thisincludemask = None
891
+ if internalinitregressorexcludemask is not None:
892
+ thisexcludemask = internalinitregressorexcludemask[validvoxels]
893
+ else:
894
+ thisexcludemask = None
895
+
896
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
897
+ "initial regressor",
898
+ "startregressormask",
899
+ filtereddata,
900
+ thisincludemask,
901
+ 1.0 / fmritr,
902
+ outputname,
903
+ initfile=True,
904
+ excludemask=thisexcludemask,
905
+ filedesc="regionalpostfilter",
906
+ suffix="",
907
+ debug=args.debug,
908
+ )"""
909
+ # reformat the anatomic masks, if they exist
910
+ if brainmask is None:
911
+ invbrainmask = None
912
+
913
+ internalbrainmask = None
914
+ internalinvbrainmask = None
915
+ else:
916
+ invbrainmask = 1 - brainmask
917
+ internalbrainmask = brainmask.reshape((numspatiallocs))
918
+ internalinvbrainmask = invbrainmask.reshape((numspatiallocs))
919
+ if graymask is None:
920
+ internalgraymask = None
921
+ else:
922
+ internalgraymask = graymask.reshape((numspatiallocs))
923
+ if whitemask is None:
924
+ internalwhitemask = None
925
+ else:
926
+ internalwhitemask = whitemask.reshape((numspatiallocs))
927
+ if csfmask is None:
928
+ internalcsfmask = None
929
+ else:
930
+ internalcsfmask = csfmask.reshape((numspatiallocs))
931
+ if brainmask is not None:
932
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
933
+ "whole brain",
934
+ "brain",
935
+ filtereddata,
936
+ internalbrainmask[validvoxels],
937
+ 1.0 / fmritr,
938
+ outputname,
939
+ filedesc="regionalpostfilter",
940
+ suffix="",
941
+ debug=args.debug,
942
+ )
943
+ if graymask is not None:
944
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
945
+ "gray matter",
946
+ "GM",
947
+ filtereddata,
948
+ internalgraymask[validvoxels],
949
+ 1.0 / fmritr,
950
+ outputname,
951
+ excludemask=internalinvbrainmask[validvoxels],
952
+ filedesc="regionalpostfilter",
953
+ suffix="",
954
+ debug=args.debug,
955
+ )
956
+ if whitemask is not None:
957
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
958
+ "white matter",
959
+ "WM",
960
+ filtereddata,
961
+ internalwhitemask[validvoxels],
962
+ 1.0 / fmritr,
963
+ outputname,
964
+ excludemask=internalinvbrainmask[validvoxels],
965
+ filedesc="regionalpostfilter",
966
+ suffix="",
967
+ debug=args.debug,
968
+ )
969
+ if csfmask is not None:
970
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
971
+ "CSF",
972
+ "CSF",
973
+ filtereddata,
974
+ internalcsfmask[validvoxels],
975
+ 1.0 / fmritr,
976
+ outputname,
977
+ excludemask=internalinvbrainmask[validvoxels],
978
+ filedesc="regionalpostfilter",
979
+ suffix="",
980
+ debug=args.debug,
981
+ )
982
+
983
+ # save outputs
984
+ TimingLGR.info("Starting output save")
985
+ theheader = copy.deepcopy(lagtimes_header)
986
+ if mode == "glm":
987
+ maplist = [
988
+ (
989
+ initialvariance,
990
+ "lfofilterInbandVarianceBefore",
991
+ "map",
992
+ None,
993
+ "Inband variance prior to filtering",
994
+ ),
995
+ (
996
+ finalvariance,
997
+ "lfofilterInbandVarianceAfter",
998
+ "map",
999
+ None,
1000
+ "Inband variance after filtering",
1001
+ ),
1002
+ (
1003
+ varchange,
1004
+ "lfofilterInbandVarianceChange",
1005
+ "map",
1006
+ "percent",
1007
+ "Change in inband variance after filtering, in percent",
1008
+ ),
1009
+ # (
1010
+ # lfofilteredmeanvalue,
1011
+ # "lfofilterMean",
1012
+ # "map",
1013
+ # None,
1014
+ # "Voxelwise mean of the sLFO filtered data",
1015
+ # )
1016
+ # (
1017
+ # initialrawvariance,
1018
+ # "lfofilterTotalVarianceBefore",
1019
+ # "map",
1020
+ # None,
1021
+ # "Total variance prior to filtering",
1022
+ # ),
1023
+ # (
1024
+ # finalrawvariance,
1025
+ # "lfofilterTotalVarianceAfter",
1026
+ # "map",
1027
+ # None,
1028
+ # "Total variance after filtering",
1029
+ # ),
1030
+ # (
1031
+ # rawvarchange,
1032
+ # "lfofilterTotalVarianceChange",
1033
+ # "map",
1034
+ # "percent",
1035
+ # "Change in total variance after filtering, in percent",
1036
+ # ),
1037
+ ]
1038
+ if args.saveminimumsLFOfiltfiles:
1039
+ maplist += [
1040
+ (
1041
+ r2value,
1042
+ "lfofilterR2",
1043
+ "map",
1044
+ None,
1045
+ "Squared R value of the GLM fit (proportion of variance explained)",
1046
+ ),
1047
+ ]
1048
+ if args.savenormalsLFOfiltfiles:
1049
+ maplist += [
1050
+ (rvalue, "lfofilterR", "map", None, "R value of the GLM fit"),
1051
+ (sLFOfitmean, "lfofilterMean", "map", None, "Intercept from GLM fit"),
1052
+ ]
1053
+ else:
1054
+ maplist = [
1055
+ (initialvariance, "lfofilterInbandVarianceBefore", "map", None),
1056
+ (finalvariance, "lfofilterInbandVarianceAfter", "map", None),
1057
+ (varchange, "CVRVariance", "map", None),
1058
+ (rvalue, "CVRR", "map", None),
1059
+ (r2value, "CVRR2", "map", None),
1060
+ (fitcoeff[:, 0], "CVR", "map", "percent"),
1061
+ ]
1062
+ bidsdict = bidsbasedict.copy()
1063
+
1064
+ if args.debug or args.focaldebug:
1065
+ maplist += [
1066
+ (
1067
+ lagtimes_valid,
1068
+ "maxtimeREAD",
1069
+ "map",
1070
+ "second",
1071
+ "Lag time in seconds used for calculation",
1072
+ ),
1073
+ (
1074
+ corrmask_valid,
1075
+ "corrfitREAD",
1076
+ "mask",
1077
+ None,
1078
+ "Correlation mask read for calculation",
1079
+ ),
1080
+ (
1081
+ sLFOfiltmask_valid,
1082
+ "corrfitUSED",
1083
+ "mask",
1084
+ None,
1085
+ "Correlation mask used for calculation",
1086
+ ),
1087
+ (
1088
+ procmask_valid,
1089
+ "processedREAD",
1090
+ "mask",
1091
+ None,
1092
+ "Processed mask used for calculation",
1093
+ ),
1094
+ ]
1095
+ if args.savenormalsLFOfiltfiles:
1096
+ if args.regressderivs > 0 or args.refinedelay:
1097
+ maplist += [
1098
+ (fitcoeff[:, 0], "lfofilterCoeff", "map", None, "Fit coefficient"),
1099
+ (fitNorm[:, 0], "lfofilterNorm", "map", None, "Normalized fit coefficient"),
1100
+ ]
1101
+ for thederiv in range(1, args.regressderivs + 1):
1102
+ maplist += [
1103
+ (
1104
+ fitcoeff[:, thederiv],
1105
+ f"lfofilterCoeffDeriv{thederiv}",
1106
+ "map",
1107
+ None,
1108
+ f"Fit coefficient for temporal derivative {thederiv}",
1109
+ ),
1110
+ (
1111
+ fitNorm[:, thederiv],
1112
+ f"lfofilterNormDeriv{thederiv}",
1113
+ "map",
1114
+ None,
1115
+ f"Normalized fit coefficient for temporal derivative {thederiv}",
1116
+ ),
1117
+ ]
1118
+ else:
1119
+ maplist += [
1120
+ (fitcoeff, "lfofilterCoeff", "map", None, "Fit coefficient"),
1121
+ (fitNorm, "lfofilterNorm", "map", None, "Normalized fit coefficient"),
1122
+ ]
1123
+
1124
+ if args.refinedelay:
1125
+ maplist += [
1126
+ (
1127
+ regressderivratios,
1128
+ "regressderivratios",
1129
+ "map",
1130
+ None,
1131
+ "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
1132
+ ),
1133
+ (
1134
+ medfiltregressderivratios,
1135
+ "medfiltregressderivratios",
1136
+ "map",
1137
+ None,
1138
+ "Median filtered version of the regressderivratios map",
1139
+ ),
1140
+ (
1141
+ filteredregressderivratios,
1142
+ "filteredregressderivratios",
1143
+ "map",
1144
+ None,
1145
+ "regressderivratios, with outliers patched using median filtered data",
1146
+ ),
1147
+ (
1148
+ delayoffset,
1149
+ "delayoffset",
1150
+ "map",
1151
+ "second",
1152
+ "Delay offset correction from delay refinement",
1153
+ ),
1154
+ (
1155
+ lagtimesrefined_valid,
1156
+ "maxtimerefined",
1157
+ "map",
1158
+ "second",
1159
+ "Lag time in seconds, refined",
1160
+ ),
1161
+ ]
1162
+
1163
+ # write the 3D maps
1164
+ tide_io.savemaplist(
1165
+ outputname,
1166
+ maplist,
1167
+ validvoxels,
1168
+ (xsize, ysize, numslices),
1169
+ theheader,
1170
+ bidsdict,
1171
+ debug=args.debug,
1172
+ )
1173
+
1174
+ # write the 4D maps
1175
+ theheader = theinputdata.copyheader()
1176
+ maplist = []
1177
+ if args.saveminimumsLFOfiltfiles:
1178
+ maplist = [
1179
+ (
1180
+ filtereddata,
1181
+ "lfofilterCleaned",
1182
+ "bold",
1183
+ None,
1184
+ "fMRI data with sLFO signal filtered out",
1185
+ ),
1186
+ ]
1187
+ if args.savemovingsignal:
1188
+ maplist += [
1189
+ (
1190
+ movingsignal,
1191
+ "lfofilterRemoved",
1192
+ "bold",
1193
+ None,
1194
+ "sLFO signal filtered out of this voxel",
1195
+ )
1196
+ ]
1197
+
1198
+ if args.saveallsLFOfiltfiles:
1199
+ if args.regressderivs > 0:
1200
+ if args.debug:
1201
+ print("going down the multiple EV path")
1202
+ print(f"{regressorset[:, :, 0].shape=}")
1203
+ maplist += [
1204
+ (
1205
+ regressorset[:, :, 0],
1206
+ "lfofilterEV",
1207
+ "bold",
1208
+ None,
1209
+ "Shifted sLFO regressor to filter",
1210
+ ),
1211
+ ]
1212
+ for thederiv in range(1, args.regressderivs + 1):
1213
+ if args.debug:
1214
+ print(f"{regressorset[:, :, thederiv].shape=}")
1215
+ maplist += [
1216
+ (
1217
+ regressorset[:, :, thederiv],
1218
+ f"lfofilterEVDeriv{thederiv}",
1219
+ "bold",
1220
+ None,
1221
+ f"Time derivative {thederiv} of shifted sLFO regressor",
1222
+ ),
1223
+ ]
1224
+ else:
1225
+ if args.debug:
1226
+ print("going down the single EV path")
1227
+ maplist += [
1228
+ (
1229
+ regressorset,
1230
+ "lfofilterEV",
1231
+ "bold",
1232
+ None,
1233
+ "Shifted sLFO regressor to filter",
1234
+ ),
1235
+ ]
1236
+ if args.makepseudofile:
1237
+ print("reading mean image")
1238
+ meanfile = f"{args.datafileroot}_desc-mean_map.nii.gz"
1239
+ (
1240
+ mean_input,
1241
+ mean,
1242
+ mean_header,
1243
+ mean_dims,
1244
+ mean_sizes,
1245
+ ) = tide_io.readfromnifti(meanfile)
1246
+ if not tide_io.checkspacematch(fmri_header, mean_header):
1247
+ raise ValueError("mean dimensions do not match fmri dimensions")
1248
+ if args.debug:
1249
+ print(f"{mean.shape=}")
1250
+ mean_spacebytime = mean.reshape((numspatiallocs))
1251
+ if args.debug:
1252
+ print(f"{mean_spacebytime.shape=}")
1253
+ pseudofile = mean_spacebytime[validvoxels, None] + movingsignal[:, :]
1254
+ maplist.append((pseudofile, "pseudofile", "bold", None, None))
1255
+ tide_io.savemaplist(
1256
+ outputname,
1257
+ maplist,
1258
+ validvoxels,
1259
+ (xsize, ysize, numslices, validtimepoints),
1260
+ theheader,
1261
+ bidsdict,
1262
+ debug=args.debug,
1263
+ )
1264
+ TimingLGR.info("Finishing output save")
1265
+
1266
+ if args.refinecorr:
1267
+ TimingLGR.info("Filtering for maxcorrrefined calculation start")
1268
+ for thevoxel in range(fmri_data_valid.shape[0]):
1269
+ fmri_data_valid[thevoxel, :] = theprefilter.apply(
1270
+ 1.0 / fmritr, fmri_data_valid[thevoxel, :]
1271
+ )
1272
+ TimingLGR.info("Filtering for maxcorrrefined calculation complete")
1273
+ TimingLGR.info("GLM for maxcorrrefined calculation start")
1274
+ voxelsprocessed_regressionfilt, regressorset, evset = (
1275
+ tide_regressfrommaps.regressfrommaps(
1276
+ fmri_data_valid,
1277
+ validvoxels,
1278
+ initial_fmri_x,
1279
+ lagstouse_valid,
1280
+ sLFOfiltmask_valid,
1281
+ genlagtc,
1282
+ mode,
1283
+ outputname,
1284
+ oversamptr,
1285
+ sLFOfitmean,
1286
+ rvalue,
1287
+ r2value,
1288
+ fitNorm[:, : args.regressderivs + 1],
1289
+ fitcoeff[:, : args.regressderivs + 1],
1290
+ movingsignal,
1291
+ lagtc,
1292
+ filtereddata,
1293
+ LGR,
1294
+ TimingLGR,
1295
+ threshval,
1296
+ args.saveminimumsLFOfiltfiles,
1297
+ nprocs_makelaggedtcs=args.nprocs,
1298
+ nprocs_regressionfilt=args.nprocs,
1299
+ regressderivs=args.regressderivs,
1300
+ showprogressbar=args.showprogressbar,
1301
+ debug=args.debug,
1302
+ )
1303
+ )
1304
+ TimingLGR.info(
1305
+ "GLM for maxcorrrefined calculation done",
1306
+ {
1307
+ "message2": voxelsprocessed_regressionfilt,
1308
+ "message3": "voxels",
1309
+ },
1310
+ )
1311
+
1312
+ maplist = [
1313
+ (
1314
+ rvalue,
1315
+ "maxcorrrefined",
1316
+ "map",
1317
+ None,
1318
+ "R value for the lfo component of the delayed regressor, with sign",
1319
+ ),
1320
+ ]
1321
+ theheader = copy.deepcopy(lagtimes_header)
1322
+ tide_io.savemaplist(
1323
+ outputname,
1324
+ maplist,
1325
+ validvoxels,
1326
+ (xsize, ysize, numslices),
1327
+ theheader,
1328
+ bidsdict,
1329
+ debug=args.debug,
1330
+ )
1331
+ if args.debug:
1332
+ # dump the fmri input file going to glm
1333
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
1334
+
1335
+ maplist = [
1336
+ (
1337
+ fmri_data_valid,
1338
+ "prefilteredinputdata",
1339
+ "bold",
1340
+ None,
1341
+ "fMRI data after temporal filtering",
1342
+ ),
1343
+ ]
1344
+ tide_io.savemaplist(
1345
+ outputname,
1346
+ maplist,
1347
+ validvoxels,
1348
+ (xsize, ysize, numslices, validtimepoints),
1349
+ theheader,
1350
+ bidsbasedict,
1351
+ filetype=theinputdata.filetype,
1352
+ rt_floattype=rt_floattype,
1353
+ cifti_hdr=None,
1354
+ )
1355
+ else:
1356
+ # We are terminating early because we only want the regressors
1357
+ # write the EVs
1358
+ theheader = theinputdata.copyheader()
1359
+ maplist = []
1360
+ if args.regressderivs > 0:
1361
+ if args.debug:
1362
+ print("going down the multiple EV path")
1363
+ print(f"{regressorset[:, :, 0].shape=}")
1364
+ maplist += [
1365
+ (
1366
+ regressorset[:, :, 0],
1367
+ "lfofilterEV",
1368
+ "bold",
1369
+ None,
1370
+ "Shifted sLFO regressor to filter",
1371
+ ),
1372
+ ]
1373
+ for thederiv in range(1, args.regressderivs + 1):
1374
+ if args.debug:
1375
+ print(f"{regressorset[:, :, thederiv].shape=}")
1376
+ maplist += [
1377
+ (
1378
+ regressorset[:, :, thederiv],
1379
+ f"lfofilterEVDeriv{thederiv}",
1380
+ "bold",
1381
+ None,
1382
+ f"Time derivative {thederiv} of shifted sLFO regressor",
1383
+ ),
1384
+ ]
1385
+ else:
1386
+ if args.debug:
1387
+ print("going down the single EV path")
1388
+ maplist += [
1389
+ (
1390
+ regressorset,
1391
+ "lfofilterEV",
1392
+ "bold",
1393
+ None,
1394
+ "Shifted sLFO regressor to filter",
1395
+ ),
1396
+ ]
1397
+ bidsdict = bidsbasedict.copy()
1398
+ tide_io.savemaplist(
1399
+ outputname,
1400
+ maplist,
1401
+ validvoxels,
1402
+ (xsize, ysize, numslices, validtimepoints),
1403
+ theheader,
1404
+ bidsdict,
1405
+ debug=args.debug,
1406
+ )
1407
+
1408
+ # write the runoptions file
1409
+ print("writing runoptions")
1410
+ if args.refinedelay:
1411
+ therunoptions["retroregress_delayoffsetMAD"] = delayoffsetMAD
1412
+ therunoptions["retroregress_runtime"] = time.strftime(
1413
+ "%a, %d %b %Y %H:%M:%S %Z", time.localtime(time.time())
1414
+ )
1415
+ (
1416
+ therunoptions["retroregress_release_version"],
1417
+ therunoptions["retroregress_git_sha"],
1418
+ therunoptions["retroregress_git_date"],
1419
+ therunoptions["retroregress_git_isdirty"],
1420
+ ) = tide_util.version()
1421
+ therunoptions["retroregress_python_version"] = str(sys.version_info)
1422
+ therunoptions["retroregress_nodename"] = platform.node()
1423
+
1424
+ # clean up shared memory
1425
+ if usesharedmem:
1426
+ TimingLGR.info("Shared memory cleanup start")
1427
+ tide_util.cleanup_shm(sLFOfitmean_shm)
1428
+ tide_util.cleanup_shm(rvalue_shm)
1429
+ tide_util.cleanup_shm(r2value_shm)
1430
+ tide_util.cleanup_shm(fitNorm_shm)
1431
+ tide_util.cleanup_shm(fitcoeff_shm)
1432
+ tide_util.cleanup_shm(movingsignal_shm)
1433
+ tide_util.cleanup_shm(lagtc_shm)
1434
+ tide_util.cleanup_shm(filtereddata_shm)
1435
+ TimingLGR.info("Shared memory cleanup complete")
1436
+
1437
+ # shut down logging
1438
+ TimingLGR.info("Done")
1439
+ logging.shutdown()
1440
+
1441
+ # reformat timing information and delete the unformatted version
1442
+ timingdata, therunoptions["totalretroruntime"] = tide_util.proctiminglogfile(
1443
+ f"{outputname}_retroruntimings.tsv"
1444
+ )
1445
+ tide_io.writevec(
1446
+ np.asarray(timingdata),
1447
+ f"{outputname}_desc-formattedretroruntimings_info.tsv",
1448
+ )
1449
+ Path(f"{outputname}_retroruntimings.tsv").unlink(missing_ok=True)
1450
+
1451
+ # save the modified runoptions file
1452
+ tide_io.writedicttojson(therunoptions, f"{outputname}_desc-runoptions_info.json")
1453
+
1454
+ # shut down the loggers
1455
+ for thelogger in [LGR, ErrorLGR, TimingLGR]:
1456
+ handlers = thelogger.handlers[:]
1457
+ for handler in handlers:
1458
+ thelogger.removeHandler(handler)
1459
+ handler.close()
1460
+
1461
+ # delete the canary file
1462
+ Path(f"{outputname}_RETROISRUNNING.txt").unlink()
1463
+
1464
+ # create the finished file
1465
+ Path(f"{outputname}_RETRODONE.txt").touch()
1466
+
1467
+
1468
+ def process_args(inputargs: Optional[Any] = None) -> argparse.Namespace:
1469
+ """
1470
+ Compile arguments for retroregress workflow.
1471
+
1472
+ This function processes input arguments for the retroregress workflow by parsing
1473
+ command line arguments or provided input arguments using a predefined parser.
1474
+
1475
+ Parameters
1476
+ ----------
1477
+ inputargs : Any, optional
1478
+ Input arguments to be processed. Can be None (default), a list of strings,
1479
+ or other argument formats supported by the underlying parser. Default is None.
1480
+
1481
+ Returns
1482
+ -------
1483
+ argparse.Namespace
1484
+ Parsed arguments namespace containing all processed arguments for the workflow.
1485
+
1486
+ Notes
1487
+ -----
1488
+ The function relies on `pf.setargs` and `_get_parser` which should be defined
1489
+ in the module's scope. The returned arguments can be used directly in the
1490
+ retroregress workflow pipeline.
1491
+
1492
+ Examples
1493
+ --------
1494
+ >>> # Using default arguments
1495
+ >>> args = process_args()
1496
+
1497
+ >>> # Using custom input arguments
1498
+ >>> args = process_args(['--input', 'data.csv', '--output', 'results.txt'])
1499
+ """
1500
+ args, argstowrite = pf.setargs(_get_parser, inputargs=inputargs)
1501
+ return args