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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
  #
4
- # Copyright 2016-2024 Blaise Frederick
4
+ # Copyright 2016-2025 Blaise Frederick
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -16,23 +16,18 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  #
19
- import bisect
20
- import copy
21
19
  import gc
22
20
  import logging
23
- import multiprocessing as mp
24
21
  import os
25
22
  import platform
26
23
  import sys
27
24
  import warnings
28
25
  from pathlib import Path
26
+ from typing import Any, Tuple
29
27
 
30
28
  import numpy as np
31
- from nilearn import masking
32
- from scipy import ndimage
29
+ from numpy.typing import NDArray
33
30
  from scipy.stats import rankdata
34
- from sklearn.decomposition import PCA
35
- from tqdm import tqdm
36
31
 
37
32
  import rapidtide.calccoherence as tide_calccoherence
38
33
  import rapidtide.calcnullsimfunc as tide_nullsimfunc
@@ -40,22 +35,25 @@ import rapidtide.calcsimfunc as tide_calcsimfunc
40
35
  import rapidtide.correlate as tide_corr
41
36
  import rapidtide.filter as tide_filt
42
37
  import rapidtide.fit as tide_fit
43
- import rapidtide.glmpass as tide_glmpass
44
38
  import rapidtide.helper_classes as tide_classes
45
39
  import rapidtide.io as tide_io
46
- import rapidtide.makelaggedtcs as tide_makelagged
40
+ import rapidtide.linfitfiltpass as tide_linfitfiltpass
47
41
  import rapidtide.maskutil as tide_mask
48
42
  import rapidtide.miscmath as tide_math
49
43
  import rapidtide.multiproc as tide_multiproc
50
- import rapidtide.peakeval as tide_peakeval
51
- import rapidtide.refine_factored as tide_refine
52
44
  import rapidtide.resample as tide_resample
53
- import rapidtide.simfuncfit as tide_simfuncfit
45
+ import rapidtide.simFuncClasses as tide_simFuncClasses
54
46
  import rapidtide.stats as tide_stats
55
47
  import rapidtide.util as tide_util
48
+ import rapidtide.voxelData as tide_voxelData
56
49
  import rapidtide.wiener as tide_wiener
57
- import rapidtide.workflows.glmfrommaps as tide_glmfrommaps
58
- from rapidtide.tests.utils import mse
50
+ import rapidtide.workflows.calcSimFuncMap as tide_calcSimFuncMap
51
+ import rapidtide.workflows.cleanregressor as tide_cleanregressor
52
+ import rapidtide.workflows.fitSimFuncMap as tide_fitSimFuncMap
53
+ import rapidtide.workflows.refineDelayMap as tide_refineDelayMap
54
+ import rapidtide.workflows.refineRegressor as tide_refineRegressor
55
+ import rapidtide.workflows.regressfrommaps as tide_regressfrommaps
56
+ from rapidtide.ffttools import showfftcache
59
57
 
60
58
  from .utils import setup_logger
61
59
 
@@ -66,110 +64,44 @@ try:
66
64
  except ImportError:
67
65
  mklexists = False
68
66
 
69
- try:
70
- from memory_profiler import profile
71
-
72
- memprofilerexists = True
73
- except ImportError:
74
- memprofilerexists = False
75
-
76
67
  LGR = logging.getLogger("GENERAL")
77
68
  ErrorLGR = logging.getLogger("ERROR")
78
69
  TimingLGR = logging.getLogger("TIMING")
79
70
 
80
-
81
- def conditionalprofile():
82
- def resdec(f):
83
- if memprofilerexists:
84
- return profile(f)
85
- return f
86
-
87
- return resdec
88
-
89
-
90
- @conditionalprofile()
91
- def memcheckpoint(message):
92
- LGR.info(message)
93
-
94
-
95
- def getglobalsignal(
96
- indata, optiondict, includemask=None, excludemask=None, pcacomponents=0.8, debug=False
97
- ):
98
- # Start with all voxels
99
- themask = indata[:, 0] * 0 + 1
100
-
101
- # modify the mask if needed
102
- if includemask is not None:
103
- themask = themask * includemask
104
- if excludemask is not None:
105
- themask = themask * (1 - excludemask)
106
-
107
- # combine all the voxels using one of the three methods
108
- global rt_floatset, rt_floattype
109
- globalmean = rt_floatset(indata[0, :])
110
- thesize = np.shape(themask)
111
- numvoxelsused = int(np.sum(np.where(themask > 0.0, 1, 0)))
112
- selectedvoxels = indata[np.where(themask > 0.0), :][0]
113
- if debug:
114
- print(f"getglobalsignal: {selectedvoxels.shape=}")
115
- LGR.info(f"constructing global mean signal using {optiondict['globalsignalmethod']}")
116
- if optiondict["globalsignalmethod"] == "sum":
117
- globalmean = np.mean(selectedvoxels, axis=0)
118
- globalmean -= np.mean(globalmean)
119
- elif optiondict["globalsignalmethod"] == "meanscale":
120
- themean = np.mean(indata, axis=1)
121
- for vox in range(0, thesize[0]):
122
- if themask[vox] > 0.0:
123
- if themean[vox] != 0.0:
124
- globalmean += indata[vox, :] / themean[vox] - 1.0
125
- elif optiondict["globalsignalmethod"] == "pca":
126
- themean = np.mean(indata, axis=1)
127
- thevar = np.var(indata, axis=1)
128
- scaledvoxels = selectedvoxels * 0.0
129
- for vox in range(0, selectedvoxels.shape[0]):
130
- scaledvoxels[vox, :] = selectedvoxels[vox, :] - themean[vox]
131
- if thevar[vox] > 0.0:
132
- scaledvoxels[vox, :] = selectedvoxels[vox, :] / thevar[vox]
133
- try:
134
- thefit = PCA(n_components=pcacomponents).fit(np.transpose(scaledvoxels))
135
- except ValueError:
136
- if pcacomponents == "mle":
137
- LGR.warning("mle estimation failed - falling back to pcacomponents=0.8")
138
- thefit = PCA(n_components=0.8).fit(np.transpose(scaledvoxels))
139
- else:
140
- raise ValueError("unhandled math exception in PCA refinement - exiting")
141
-
142
- varex = 100.0 * np.cumsum(thefit.explained_variance_ratio_)[len(thefit.components_) - 1]
143
- thetransform = thefit.transform(np.transpose(scaledvoxels))
144
- if debug:
145
- print(f"getglobalsignal: {thetransform.shape=}")
146
- globalmean = np.mean(thetransform, axis=0)
147
- globalmean -= np.mean(globalmean)
148
- if debug:
149
- print(f"getglobalsignal: {varex=}")
150
- LGR.info(
151
- f"Using {len(thefit.components_)} component(s), accounting for "
152
- f"{varex:.2f}% of the variance"
153
- )
154
- elif optiondict["globalsignalmethod"] == "random":
155
- globalmean = np.random.standard_normal(size=len(globalmean))
156
- else:
157
- raise ValueError(f"illegal globalsignalmethod: {optiondict['globalsignalmethod']}")
158
- LGR.info(f"used {numvoxelsused} voxels to calculate global mean signal")
159
- if debug:
160
- print(f"getglobalsignal: {globalmean=}")
161
- return tide_math.stdnormalize(globalmean), themask
162
-
163
-
164
- def addmemprofiling(thefunc, memprofile, themessage):
165
- if memprofile:
166
- return profile(thefunc, precision=2)
167
- else:
168
- tide_util.logmem(themessage)
169
- return thefunc
170
-
171
-
172
- def checkforzeromean(thedataset):
71
+ global rt_floattype
72
+ rt_floattype: np.dtype = np.float64
73
+
74
+
75
+ def checkforzeromean(thedataset: Any) -> bool:
76
+ """
77
+ Check if the mean of dataset is zero.
78
+
79
+ Parameters
80
+ ----------
81
+ thedataset : array-like
82
+ Input dataset to check for zero mean. Should be array-like structure
83
+ that can be processed by numpy mean and std functions.
84
+
85
+ Returns
86
+ -------
87
+ bool
88
+ True if the mean of standard deviations is greater than the mean of means,
89
+ False otherwise.
90
+
91
+ Notes
92
+ -----
93
+ This function calculates the mean and standard deviation along axis 1,
94
+ then compares the means of these two arrays. The function name suggests
95
+ checking for zero mean, but the implementation actually compares means
96
+ and standard deviations rather than directly checking if mean equals zero.
97
+
98
+ Examples
99
+ --------
100
+ >>> import numpy as np
101
+ >>> data = np.array([[1, 2, 3], [4, 5, 6]])
102
+ >>> checkforzeromean(data)
103
+ False
104
+ """
173
105
  themean = np.mean(thedataset, axis=1)
174
106
  thestd = np.std(thedataset, axis=1)
175
107
  if np.mean(thestd) > np.mean(themean):
@@ -178,7 +110,59 @@ def checkforzeromean(thedataset):
178
110
  return False
179
111
 
180
112
 
181
- def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints):
113
+ def echocancel(
114
+ thetimecourse: Any, echooffset: Any, thetimestep: Any, outputname: Any, padtimepoints: Any
115
+ ) -> Tuple[NDArray, NDArray, float]:
116
+ """
117
+ Perform echo cancellation on a timecourse using linear regression.
118
+
119
+ This function applies echo cancellation to a given timecourse by modeling the echo signal
120
+ and subtracting its contribution from the original signal. The echo is shifted in time
121
+ according to `echooffset` and then fitted using maximum likelihood regression. The
122
+ resulting filtered timecourse is saved along with the original and echo components.
123
+
124
+ Parameters
125
+ ----------
126
+ thetimecourse : array-like
127
+ The input timecourse data to be processed.
128
+ echooffset : float
129
+ The time offset (in seconds) of the echo signal relative to the input timecourse.
130
+ thetimestep : float
131
+ The time step (in seconds) of the input timecourse.
132
+ outputname : str
133
+ Base name for output files; used to construct filenames for saved results.
134
+ padtimepoints : int
135
+ Number of timepoints to pad during resampling of the echo signal.
136
+
137
+ Returns
138
+ -------
139
+ tuple
140
+ A tuple containing:
141
+ - `outputtimecourse`: The timecourse after echo cancellation.
142
+ - `echofit`: The regression coefficients from fitting the echo signal.
143
+ - `echoR2`: The R-squared value of the echo fit.
144
+
145
+ Notes
146
+ -----
147
+ - The function writes three separate TSV files:
148
+ 1. Original timecourse.
149
+ 2. Echo signal.
150
+ 3. Filtered (echo-cancelled) timecourse.
151
+ - The echo signal is shifted in time using `tide_resample.timeshift`.
152
+ - The echo is zeroed out at the beginning up to the computed shift.
153
+ - The function uses `tide_fit.mlregress` for linear regression fitting.
154
+
155
+ Examples
156
+ --------
157
+ >>> import numpy as np
158
+ >>> timecourse = np.random.rand(100)
159
+ >>> echo_offset = 2.0
160
+ >>> time_step = 1.0
161
+ >>> output_name = "test_output"
162
+ >>> pad_points = 10
163
+ >>> result = echocancel(timecourse, echo_offset, time_step, output_name, pad_points)
164
+ >>> filtered_tc, fit_coeffs, r2 = result
165
+ """
182
166
  tide_io.writebidstsv(
183
167
  f"{outputname}_desc-echocancellation_timeseries",
184
168
  thetimecourse,
@@ -192,7 +176,7 @@ def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints
192
176
  shifttr = echooffset / thetimestep # lagtime is in seconds
193
177
  echotc, dummy, dummy, dummy = tide_resample.timeshift(thetimecourse, shifttr, padtimepoints)
194
178
  echotc[0 : int(np.ceil(shifttr))] = 0.0
195
- echofit, echoR = tide_fit.mlregress(echotc, thetimecourse)
179
+ echofit, echoR2 = tide_fit.mlregress(echotc, thetimecourse)
196
180
  fitcoeff = echofit[0, 1]
197
181
  outputtimecourse = thetimecourse - fitcoeff * echotc
198
182
  tide_io.writebidstsv(
@@ -215,27 +199,88 @@ def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints
215
199
  },
216
200
  append=True,
217
201
  )
218
- return outputtimecourse, echofit, echoR
219
-
220
-
221
- def disablemkl(numprocs, debug=False):
222
- if mklexists:
223
- if numprocs > 1:
224
- if debug:
225
- print("disablemkl: setting threads to 1")
226
- mkl.set_num_threads(1)
227
-
228
-
229
- def enablemkl(numthreads, debug=False):
230
- if mklexists:
231
- if debug:
232
- print(f"enablemkl: setting threads to {numthreads}")
233
- mkl.set_num_threads(numthreads)
234
-
235
-
236
- def rapidtide_main(argparsingfunc):
237
- threaddebug = False
202
+ return outputtimecourse, echofit, echoR2
203
+
204
+
205
+ def setpassoptions(passdict: Any, optiondict: Any) -> None:
206
+ """
207
+ Copy key-value pairs from passdict to optiondict.
208
+
209
+ This function updates the optiondict with key-value pairs from passdict,
210
+ effectively passing options from one dictionary to another.
211
+
212
+ Parameters
213
+ ----------
214
+ passdict : Any
215
+ Dictionary containing options to be passed
216
+ optiondict : Any
217
+ Dictionary that will receive the options from passdict
218
+
219
+ Returns
220
+ -------
221
+ None
222
+ This function modifies optiondict in-place and returns None
223
+
224
+ Notes
225
+ -----
226
+ This function performs an in-place update of optiondict. Any existing keys
227
+ in optiondict that are also present in passdict will be overwritten with
228
+ the values from passdict.
229
+
230
+ Examples
231
+ --------
232
+ >>> options = {'verbose': True, 'timeout': 30}
233
+ >>> new_options = {'debug': False}
234
+ >>> setpassoptions(options, new_options)
235
+ >>> print(new_options)
236
+ {'debug': False, 'verbose': True, 'timeout': 30}
237
+ """
238
+ for key, value in passdict.items():
239
+ optiondict[key] = value
240
+
241
+
242
+ def rapidtide_main(argparsingfunc: Any) -> None:
243
+ """
244
+ Process fMRI data to perform spatially localized signal-to-noise ratio (sLFO) analysis.
245
+
246
+ This function performs a comprehensive analysis of fMRI data including correlation
247
+ analysis, signal filtering, and various statistical computations to identify and
248
+ remove spatially localized noise components.
249
+
250
+ Parameters
251
+ ----------
252
+ None
253
+
254
+ Returns
255
+ -------
256
+ None
257
+ The function performs in-place processing and saves results to files.
258
+
259
+ Notes
260
+ -----
261
+ This function is designed to be called as part of a larger pipeline for fMRI
262
+ preprocessing and analysis. It handles multiple stages including:
263
+
264
+ 1. Data initialization and validation
265
+ 2. Correlation analysis across spatial locations
266
+ 3. Signal filtering and noise removal
267
+ 4. Statistical computations and result saving
268
+ 5. Timing and logging management
269
+
270
+ Examples
271
+ --------
272
+ >>> process_fmri_data()
273
+ # Processes fMRI data and saves results to output files
274
+
275
+ See Also
276
+ --------
277
+ tide_regressfrommaps : Performs regression analysis on fMRI data
278
+ tide_io : Handles input/output operations for fMRI data
279
+ tide_util : Utility functions for processing fMRI data
280
+
281
+ """
238
282
  optiondict, theprefilter = argparsingfunc
283
+ optiondict["threaddebug"] = False
239
284
 
240
285
  optiondict["nodename"] = platform.node()
241
286
 
@@ -251,10 +296,16 @@ def rapidtide_main(argparsingfunc):
251
296
  optiondict["Description"] = (
252
297
  "A detailed dump of all internal variables in the program. Useful for debugging and data provenance."
253
298
  )
254
- fmrifilename = optiondict["in_file"]
299
+ inputdatafilename = optiondict["in_file"]
255
300
  outputname = optiondict["outputname"]
256
301
  regressorfilename = optiondict["regressorfile"]
257
302
 
303
+ # get the pid of the parent process
304
+ optiondict["pid"] = os.getpid()
305
+
306
+ # delete the old completion file, if present
307
+ Path(f"{outputname}_DONE.txt").unlink(missing_ok=True)
308
+
258
309
  # create the canary file
259
310
  Path(f"{outputname}_ISRUNNING.txt").touch()
260
311
 
@@ -265,16 +316,21 @@ def rapidtide_main(argparsingfunc):
265
316
  gc.enable()
266
317
  print("turning on garbage collection")
267
318
 
268
- # if we are running in a Docker container, make sure we enforce memory limits properly
269
- try:
270
- testval = os.environ["IS_DOCKER_8395080871"]
271
- except KeyError:
272
- optiondict["runningindocker"] = False
273
- else:
274
- optiondict["runningindocker"] = True
275
- optiondict["dockermemfree"], optiondict["dockermemswap"] = tide_util.findavailablemem()
276
- if optiondict["dockermemfix"]:
277
- tide_util.setmemlimit(optiondict["dockermemfree"])
319
+ # If running in Docker or Apptainer/Singularity, this is necessary to enforce memory limits properly
320
+ # otherwise likely to error out in gzip.py or at voxelnormalize step. But do nothing if running in CircleCI
321
+ # because it does NOT like you messing with the container.
322
+ optiondict["containertype"] = tide_util.checkifincontainer()
323
+ if optiondict["containertype"] is not None:
324
+ if optiondict["containertype"] != "CircleCI":
325
+ optiondict["containermemfree"], optiondict["containermemswap"] = (
326
+ tide_util.findavailablemem()
327
+ )
328
+ tide_util.setmemlimit(optiondict["containermemfree"])
329
+ else:
330
+ print("running in CircleCI environment - not messing with memory")
331
+
332
+ # load pyfftw wisdom
333
+ optiondict["pyfftw_wisdom"] = tide_util.configurepyfftw()
278
334
 
279
335
  # write out the current version of the run options
280
336
  optiondict["currentstage"] = "init"
@@ -285,7 +341,7 @@ def rapidtide_main(argparsingfunc):
285
341
  logger_filename=f"{outputname}_log.txt",
286
342
  timing_filename=f"{outputname}_runtimings.tsv",
287
343
  memory_filename=f"{outputname}_memusage.tsv",
288
- verbose=optiondict["verbose"],
344
+ isverbose=optiondict["verbose"],
289
345
  debug=optiondict["debug"],
290
346
  )
291
347
  TimingLGR.info("Start")
@@ -317,25 +373,21 @@ def rapidtide_main(argparsingfunc):
317
373
  tide_util.disablenumba()
318
374
 
319
375
  # set the internal precision
320
- global rt_floatset, rt_floattype
376
+ global rt_floattype
321
377
  if optiondict["internalprecision"] == "double":
322
378
  LGR.debug("setting internal precision to double")
323
- rt_floattype = "float64"
324
- rt_floatset = np.float64
379
+ rt_floattype = np.dtype(np.float64)
325
380
  else:
326
381
  LGR.debug("setting internal precision to single")
327
- rt_floattype = "float32"
328
- rt_floatset = np.float32
382
+ rt_floattype = np.dtype(np.float32)
329
383
 
330
384
  # set the output precision
331
385
  if optiondict["outputprecision"] == "double":
332
386
  LGR.debug("setting output precision to double")
333
- rt_outfloattype = "float64"
334
- rt_outfloatset = np.float64
387
+ rt_outfloattype = np.dtype(np.float64)
335
388
  else:
336
389
  LGR.debug("setting output precision to single")
337
- rt_outfloattype = "float32"
338
- rt_outfloatset = np.float32
390
+ rt_outfloattype = np.dtype(np.float32)
339
391
 
340
392
  # set the number of worker processes if multiprocessing
341
393
  if optiondict["nprocs"] < 1:
@@ -376,100 +428,43 @@ def rapidtide_main(argparsingfunc):
376
428
  else:
377
429
  optiondict["nprocs_makelaggedtcs"] = optiondict["nprocs"]
378
430
 
379
- if optiondict["singleproc_glm"]:
380
- optiondict["nprocs_glm"] = 1
431
+ if optiondict["singleproc_regressionfilt"]:
432
+ optiondict["nprocs_regressionfilt"] = 1
381
433
  else:
382
- optiondict["nprocs_glm"] = optiondict["nprocs"]
434
+ optiondict["nprocs_regressionfilt"] = optiondict["nprocs"]
383
435
 
384
436
  # set the number of MKL threads to use
385
437
  if mklexists:
386
438
  mklmaxthreads = mkl.get_max_threads()
387
439
  if not (1 <= optiondict["mklthreads"] <= mklmaxthreads):
388
440
  optiondict["mklthreads"] = mklmaxthreads
389
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
441
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
390
442
  LGR.info(f"using {optiondict['mklthreads']} MKL threads")
391
443
 
392
444
  # Generate MemoryLGR output file with column names
393
- if not optiondict["memprofile"]:
394
- tide_util.logmem()
445
+ tide_util.logmem()
395
446
 
396
447
  ####################################################
397
448
  # Read data
398
449
  ####################################################
399
- # open the fmri datafile
400
- tide_util.logmem("before reading in fmri data")
401
- if tide_io.checkiftext(fmrifilename):
402
- LGR.debug("input file is text - all I/O will be to text files")
403
- optiondict["textio"] = True
404
- if optiondict["gausssigma"] > 0.0:
405
- optiondict["gausssigma"] = 0.0
406
- LGR.info("gaussian spatial filter disabled for text input files")
407
- else:
408
- optiondict["textio"] = False
409
-
410
- if optiondict["textio"]:
411
- nim_data = tide_io.readvecs(fmrifilename)
412
- nim_hdr = None
413
- theshape = np.shape(nim_data)
414
- xsize = theshape[0]
415
- ysize = 1
416
- numslices = 1
417
- fileiscifti = False
418
- timepoints = theshape[1]
419
- thesizes = [0, int(xsize), 1, 1, int(timepoints)]
420
- numspatiallocs = int(xsize)
421
- nativespaceshape = xsize
422
- cifti_hdr = None
423
- else:
424
- fileiscifti = tide_io.checkifcifti(fmrifilename)
425
- if fileiscifti:
426
- LGR.debug("input file is CIFTI")
427
- (
428
- cifti,
429
- cifti_hdr,
430
- nim_data,
431
- nim_hdr,
432
- thedims,
433
- thesizes,
434
- dummy,
435
- ) = tide_io.readfromcifti(fmrifilename)
436
- optiondict["isgrayordinate"] = True
437
- timepoints = nim_data.shape[1]
438
- numspatiallocs = nim_data.shape[0]
439
- LGR.debug(f"cifti file has {timepoints} timepoints, {numspatiallocs} numspatiallocs")
440
- slicesize = numspatiallocs
441
- nativespaceshape = (1, 1, 1, 1, numspatiallocs)
442
- else:
443
- LGR.debug("input file is NIFTI")
444
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(fmrifilename)
445
- optiondict["isgrayordinate"] = False
446
- xsize, ysize, numslices, timepoints = tide_io.parseniftidims(thedims)
447
- numspatiallocs = int(xsize) * int(ysize) * int(numslices)
448
- cifti_hdr = None
449
- nativespaceshape = (xsize, ysize, numslices)
450
- xdim, ydim, slicethickness, tr = tide_io.parseniftisizes(thesizes)
451
-
452
- # correct some fields if necessary
453
- if fileiscifti:
454
- fmritr = 0.72 # this is wrong and is a hack until I can parse CIFTI XML
455
- else:
456
- if optiondict["textio"]:
457
- if optiondict["realtr"] <= 0.0:
458
- raise ValueError(
459
- "for text file data input, you must use the -t option to set the timestep"
460
- )
461
- else:
462
- if nim_hdr.get_xyzt_units()[1] == "msec":
463
- fmritr = thesizes[4] / 1000.0
464
- else:
465
- fmritr = thesizes[4]
466
- if optiondict["realtr"] > 0.0:
467
- fmritr = optiondict["realtr"]
450
+ # read the fmri datafile
451
+ tide_util.logmem("before reading in input data")
452
+ theinputdata = tide_voxelData.VoxelData(inputdatafilename, timestep=optiondict["realtr"])
453
+ if optiondict["debug"]:
454
+ theinputdata.summarize()
455
+ xsize, ysize, numslices, timepoints = theinputdata.getdims()
456
+ thesizes = theinputdata.thesizes
457
+ xdim, ydim, slicethickness, fmritr = theinputdata.getsizes()
458
+ numspatiallocs = theinputdata.numspatiallocs
459
+ nativespaceshape = theinputdata.nativespaceshape
460
+ fmritr = theinputdata.timestep
461
+ optiondict["filetype"] = theinputdata.filetype
468
462
 
469
463
  # check to see if we need to adjust the oversample factor
470
464
  if optiondict["oversampfactor"] < 0:
471
465
  optiondict["oversampfactor"] = int(np.max([np.ceil(fmritr / 0.5), 1]))
472
466
  LGR.debug(f"oversample factor set to {optiondict['oversampfactor']}")
467
+ # optiondict["prewhitenlags"] *= optiondict["oversampfactor"]
473
468
 
474
469
  oversamptr = fmritr / optiondict["oversampfactor"]
475
470
  LGR.verbose(f"fmri data: {timepoints} timepoints, tr = {fmritr}, oversamptr = {oversamptr}")
@@ -491,6 +486,8 @@ def rapidtide_main(argparsingfunc):
491
486
  raise ValueError(
492
487
  f"magnitude of lagmax exceeds {(validend - validstart + 1) * fmritr / 2.0} - invalid"
493
488
  )
489
+ # trim the fmri data to the limits
490
+ theinputdata.setvalidtimes(validstart, validend)
494
491
 
495
492
  # determine the valid timepoints
496
493
  validtimepoints = validend - validstart + 1
@@ -513,55 +510,21 @@ def rapidtide_main(argparsingfunc):
513
510
  optiondict["simcalcoffset"] = -validsimcalcstart * fmritr
514
511
 
515
512
  ####################################################
516
- # Prepare data
513
+ # Calculate initial stats
517
514
  ####################################################
518
- # do spatial filtering if requested
519
- if fileiscifti:
520
- optiondict["gausssigma"] = 0.0
521
- if optiondict["gausssigma"] < 0.0 and not optiondict["textio"]:
522
- # set gausssigma automatically
523
- optiondict["gausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
524
- if optiondict["gausssigma"] > 0.0:
525
- LGR.info(
526
- f"applying gaussian spatial filter to timepoints {validstart} "
527
- f"to {validend} with sigma={optiondict['gausssigma']}"
528
- )
529
- for i in tqdm(
530
- range(validstart, validend + 1),
531
- desc="Timepoint",
532
- unit="timepoints",
533
- disable=(not optiondict["showprogressbar"]),
534
- ):
535
- nim_data[:, :, :, i] = tide_filt.ssmooth(
536
- xdim,
537
- ydim,
538
- slicethickness,
539
- optiondict["gausssigma"],
540
- nim_data[:, :, :, i],
541
- )
542
- TimingLGR.info("End 3D smoothing")
543
-
544
- # reshape the data and trim to a time range, if specified. Check for special case of no trimming to save RAM
545
- fmri_data = nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1]
546
- if optiondict["numtozero"] > 0:
547
- themean = np.mean(fmri_data[:, optiondict["numtozero"] :], axis=1)
548
- fmri_data[:, 0 : optiondict["numtozero"]] = themean[:, None]
549
-
550
- # detect zero mean data
551
- optiondict["dataiszeromean"] = checkforzeromean(fmri_data)
552
- if optiondict["dataiszeromean"]:
553
- LGR.warning(
554
- "WARNING: dataset is zero mean - forcing variance masking and no refine prenormalization. "
555
- "Consider specifying a global mean and correlation mask."
556
- )
557
- optiondict["refineprenorm"] = "None"
558
- optiondict["globalmaskmethod"] = "variance"
515
+ init_min, init_max, init_mean, init_std, init_median, init_MAD, init_skew, init_kurtosis = (
516
+ tide_stats.fmristats(theinputdata.byvoxel())
517
+ )
559
518
 
519
+ ####################################################
520
+ # Prepare data
521
+ ####################################################
560
522
  # read in the anatomic masks
561
523
  anatomiclist = [
562
524
  ["brainmaskincludename", "brainmaskincludevals", "brainmask"],
563
525
  ["graymatterincludename", "graymatterincludevals", "graymattermask"],
564
526
  ["whitematterincludename", "whitematterincludevals", "whitemattermask"],
527
+ ["csfincludename", "csfincludevals", "csfmask"],
565
528
  ]
566
529
  anatomicmasks = []
567
530
  for thisanatomic in anatomiclist:
@@ -569,19 +532,59 @@ def rapidtide_main(argparsingfunc):
569
532
  anatomicmasks.append(
570
533
  tide_mask.readamask(
571
534
  optiondict[thisanatomic[0]],
572
- nim_hdr,
535
+ theinputdata.nim_hdr,
573
536
  xsize,
574
- istext=optiondict["textio"],
537
+ istext=(theinputdata.filetype == "text"),
575
538
  valslist=optiondict[thisanatomic[1]],
576
539
  maskname=thisanatomic[2],
577
540
  tolerance=optiondict["spatialtolerance"],
541
+ debug=optiondict["debug"],
578
542
  )
579
543
  )
580
544
  anatomicmasks[-1] = np.uint16(np.where(anatomicmasks[-1] > 0.1, 1, 0))
581
545
  else:
582
- anatomicmasks.append(None)
583
- # anatomicmasks[-1] = np.uint16(np.ones(nativespaceshape, dtype=np.uint16))
546
+ anatomicmasks.append(np.uint16(np.ones(nativespaceshape, dtype=np.uint16)))
547
+
584
548
  brainmask = anatomicmasks[0]
549
+ graymask = anatomicmasks[1]
550
+ whitemask = anatomicmasks[2]
551
+ csfmask = anatomicmasks[3]
552
+
553
+ # do spatial filtering if requested
554
+ if theinputdata.filetype == "nifti":
555
+ unfiltmeanvalue = np.mean(
556
+ theinputdata.byvoxel(),
557
+ axis=1,
558
+ )
559
+ optiondict["gausssigma"] = theinputdata.smooth(
560
+ optiondict["gausssigma"],
561
+ brainmask=brainmask,
562
+ graymask=graymask,
563
+ whitemask=whitemask,
564
+ premask=optiondict["premask"],
565
+ premasktissueonly=optiondict["premasktissueonly"],
566
+ showprogressbar=optiondict["showprogressbar"],
567
+ )
568
+ if optiondict["gausssigma"] > 0.0:
569
+ TimingLGR.info("End 3D smoothing")
570
+
571
+ # Reshape the data and trim to a time range, if specified. Check for special case of no trimming to save RAM
572
+ fmri_data = theinputdata.byvoxel()
573
+ print(f"{fmri_data.shape=}")
574
+
575
+ # detect zero mean data
576
+ if not optiondict["dataiszeromean"]:
577
+ # check anyway
578
+ optiondict["dataiszeromean"] = checkforzeromean(fmri_data)
579
+
580
+ if optiondict["dataiszeromean"]:
581
+ LGR.warning(
582
+ "WARNING: dataset is zero mean - forcing variance masking and no refine prenormalization. "
583
+ "Consider specifying a global mean and correlation mask."
584
+ )
585
+ optiondict["refineprenorm"] = "None"
586
+
587
+ # reformat the anatomic masks, if they exist
585
588
  if brainmask is None:
586
589
  invbrainmask = None
587
590
 
@@ -591,28 +594,29 @@ def rapidtide_main(argparsingfunc):
591
594
  invbrainmask = 1 - brainmask
592
595
  internalbrainmask = brainmask.reshape((numspatiallocs))
593
596
  internalinvbrainmask = invbrainmask.reshape((numspatiallocs))
594
- graymask = anatomicmasks[1]
595
- whitemask = anatomicmasks[2]
596
597
 
597
598
  # read in the optional masks
598
599
  tide_util.logmem("before setting masks")
599
600
 
600
- internalglobalmeanincludemask, internalglobalmeanexcludemask, dummy = tide_mask.getmaskset(
601
- "global mean",
602
- optiondict["globalmeanincludename"],
603
- optiondict["globalmeanincludevals"],
604
- optiondict["globalmeanexcludename"],
605
- optiondict["globalmeanexcludevals"],
606
- nim_hdr,
607
- numspatiallocs,
608
- istext=optiondict["textio"],
609
- tolerance=optiondict["spatialtolerance"],
601
+ internalinitregressorincludemask, internalinitregressorexcludemask, dummy = (
602
+ tide_mask.getmaskset(
603
+ "global mean",
604
+ optiondict["initregressorincludename"],
605
+ optiondict["initregressorincludevals"],
606
+ optiondict["initregressorexcludename"],
607
+ optiondict["initregressorexcludevals"],
608
+ theinputdata.nim_hdr,
609
+ numspatiallocs,
610
+ istext=(theinputdata.filetype == "text"),
611
+ tolerance=optiondict["spatialtolerance"],
612
+ debug=optiondict["debug"],
613
+ )
610
614
  )
611
615
  if internalinvbrainmask is not None:
612
- if internalglobalmeanexcludemask is not None:
613
- internalglobalmeanexcludemask *= internalinvbrainmask
616
+ if internalinitregressorexcludemask is not None:
617
+ internalinitregressorexcludemask *= internalinvbrainmask
614
618
  else:
615
- internalglobalmeanexcludemask = internalinvbrainmask
619
+ internalinitregressorexcludemask = internalinvbrainmask
616
620
 
617
621
  internalrefineincludemask, internalrefineexcludemask, dummy = tide_mask.getmaskset(
618
622
  "refine",
@@ -620,10 +624,11 @@ def rapidtide_main(argparsingfunc):
620
624
  optiondict["refineincludevals"],
621
625
  optiondict["refineexcludename"],
622
626
  optiondict["refineexcludevals"],
623
- nim_hdr,
627
+ theinputdata.nim_hdr,
624
628
  numspatiallocs,
625
- istext=optiondict["textio"],
629
+ istext=(theinputdata.filetype == "text"),
626
630
  tolerance=optiondict["spatialtolerance"],
631
+ debug=optiondict["debug"],
627
632
  )
628
633
  if internalinvbrainmask is not None:
629
634
  if internalrefineexcludemask is not None:
@@ -637,10 +642,11 @@ def rapidtide_main(argparsingfunc):
637
642
  optiondict["offsetincludevals"],
638
643
  optiondict["offsetexcludename"],
639
644
  optiondict["offsetexcludevals"],
640
- nim_hdr,
645
+ theinputdata.nim_hdr,
641
646
  numspatiallocs,
642
- istext=optiondict["textio"],
647
+ istext=(theinputdata.filetype == "text"),
643
648
  tolerance=optiondict["spatialtolerance"],
649
+ debug=optiondict["debug"],
644
650
  )
645
651
  if internalinvbrainmask is not None:
646
652
  if internaloffsetexcludemask is not None:
@@ -656,19 +662,20 @@ def rapidtide_main(argparsingfunc):
656
662
  if optiondict["corrmaskincludename"] is not None:
657
663
  thecorrmask = tide_mask.readamask(
658
664
  optiondict["corrmaskincludename"],
659
- nim_hdr,
665
+ theinputdata.nim_hdr,
660
666
  xsize,
661
- istext=optiondict["textio"],
667
+ istext=(theinputdata.filetype == "text"),
662
668
  valslist=optiondict["corrmaskincludevals"],
663
669
  maskname="correlation",
664
670
  tolerance=optiondict["spatialtolerance"],
671
+ debug=optiondict["debug"],
665
672
  )
666
673
 
667
674
  corrmask = np.uint16(np.where(thecorrmask > 0, 1, 0).reshape(numspatiallocs))
668
675
 
669
676
  # last line sanity check - if data is 0 over all time in a voxel, force corrmask to zero.
670
677
  datarange = np.max(fmri_data, axis=1) - np.min(fmri_data, axis=1)
671
- if optiondict["textio"]:
678
+ if theinputdata.filetype == "text":
672
679
  tide_io.writenpvecs(
673
680
  datarange.reshape((numspatiallocs)),
674
681
  f"{outputname}_motionr2.txt",
@@ -677,27 +684,29 @@ def rapidtide_main(argparsingfunc):
677
684
  savename = f"{outputname}_desc-datarange"
678
685
  tide_io.savetonifti(
679
686
  datarange.reshape((xsize, ysize, numslices)),
680
- nim_hdr,
687
+ theinputdata.nim_hdr,
681
688
  savename,
682
689
  )
683
690
  corrmask[np.where(datarange == 0)] = 0.0
684
691
  else:
685
692
  # check to see if the data has been demeaned
686
- meanim = np.mean(fmri_data, axis=1)
687
- stdim = np.std(fmri_data, axis=1)
688
- if fileiscifti:
689
- corrmask = np.uint(nim_data[:, 0] * 0 + 1)
693
+ if theinputdata.filetype != "nifti":
694
+ corrmask = np.ones_like(theinputdata.byvoxel()[:, 0], np.uint)
690
695
  else:
691
- if (np.mean(stdim) < np.mean(meanim)) and not optiondict["nirs"]:
696
+ if not optiondict["dataiszeromean"]:
692
697
  LGR.verbose("generating correlation mask from mean image")
693
- corrmask = np.uint16(tide_mask.makeepimask(nim).dataobj.reshape(numspatiallocs))
698
+ corrmask = np.uint16(
699
+ tide_mask.makeepimask(theinputdata.nim).dataobj.reshape(numspatiallocs)
700
+ )
694
701
  else:
695
702
  LGR.verbose("generating correlation mask from std image")
696
703
  corrmask = np.uint16(
697
- tide_stats.makemask(stdim, threshpct=optiondict["corrmaskthreshpct"])
704
+ tide_stats.makemask(
705
+ np.std(fmri_data, axis=1), threshpct=optiondict["corrmaskthreshpct"]
706
+ )
698
707
  )
699
- if internalbrainmask is not None:
700
- corrmask *= internalbrainmask
708
+ if internalbrainmask is not None:
709
+ corrmask = internalbrainmask
701
710
  if tide_stats.getmasksize(corrmask) == 0:
702
711
  raise ValueError("ERROR: there are no voxels in the correlation mask - exiting")
703
712
 
@@ -729,19 +738,20 @@ def rapidtide_main(argparsingfunc):
729
738
  corrmask *= 0
730
739
  corrmask += 1
731
740
  threshval = -10000000.0
732
- if not (fileiscifti or optiondict["textio"]):
733
- theheader = copy.deepcopy(nim_hdr)
734
- theheader["dim"][0] = 3
735
- theheader["dim"][4] = 1
736
- theheader["pixdim"][4] = 1.0
741
+ if theinputdata.filetype == "nifti":
742
+ theheader = theinputdata.copyheader(numtimepoints=1)
737
743
  savename = f"{outputname}_desc-processed_mask"
738
744
  tide_io.savetonifti(corrmask.reshape(xsize, ysize, numslices), theheader, savename)
739
745
 
740
- LGR.verbose(f"image threshval = {threshval}")
746
+ LGR.verbose(f"image threshval = {threshval:.2f}")
741
747
  validvoxels = np.where(corrmask > 0)[0]
748
+ if optiondict["debug"]:
749
+ print(f"{validvoxels.shape=}")
750
+ np.savetxt(f"{outputname}_validvoxels.txt", validvoxels)
742
751
  numvalidspatiallocs = np.shape(validvoxels)[0]
743
752
  LGR.debug(f"validvoxels shape = {numvalidspatiallocs}")
744
- fmri_data_valid = fmri_data[validvoxels, :] + 0.0
753
+ theinputdata.setvalidvoxels(validvoxels)
754
+ fmri_data_valid = theinputdata.validdata() + 0.0
745
755
  LGR.verbose(
746
756
  f"original size = {np.shape(fmri_data)}, trimmed size = {np.shape(fmri_data_valid)}"
747
757
  )
@@ -779,17 +789,15 @@ def rapidtide_main(argparsingfunc):
779
789
  )
780
790
  else:
781
791
  internaloffsetexcludemask_valid = None
782
-
783
792
  tide_util.logmem("after selecting valid voxels")
784
793
 
785
794
  # move fmri_data_valid into shared memory
786
795
  if optiondict["sharedmem"]:
787
796
  LGR.info("moving fmri data to shared memory")
788
797
  TimingLGR.verbose("Start moving fmri_data to shared memory")
789
- tide_util.numpy2shared_func = addmemprofiling(
790
- tide_util.numpy2shared, optiondict["memprofile"], "before fmri data move"
798
+ fmri_data_valid, fmri_data_valid_shm = tide_util.numpy2shared(
799
+ fmri_data_valid, rt_floattype, name=f"fmri_data_valid_{optiondict['pid']}"
791
800
  )
792
- fmri_data_valid = tide_util.numpy2shared_func(fmri_data_valid, rt_floatset)
793
801
  TimingLGR.verbose("End moving fmri_data to shared memory")
794
802
 
795
803
  # read in any motion and/or other confound regressors here
@@ -802,7 +810,7 @@ def rapidtide_main(argparsingfunc):
802
810
  ),
803
811
  labels=["xtrans", "ytrans", "ztrans", "xrot", "yrot", "zrot"],
804
812
  deriv=optiondict["mot_deriv"],
805
- order=1,
813
+ order=optiondict["mot_power"],
806
814
  )
807
815
  domotion = True
808
816
  else:
@@ -819,7 +827,7 @@ def rapidtide_main(argparsingfunc):
819
827
  else:
820
828
  doconfounds = False
821
829
 
822
- # now actually do the filtering
830
+ # now actually do the confound filtering
823
831
  if domotion or doconfounds:
824
832
  LGR.info("Doing confound filtering")
825
833
  TimingLGR.verbose("Confound filtering start")
@@ -845,13 +853,20 @@ def rapidtide_main(argparsingfunc):
845
853
  append=False,
846
854
  )
847
855
 
848
- disablemkl(optiondict["nprocs_confoundregress"], debug=threaddebug)
856
+ if optiondict["debug"]:
857
+ print(f"{mergedregressors.shape=}")
858
+ print(f"{mergedregressorlabels}")
859
+ print(f"{fmri_data_valid.shape=}")
860
+ print(f"{fmritr=}")
861
+ print(f"{validstart=}")
862
+ print(f"{validend=}")
863
+ tide_util.disablemkl(optiondict["nprocs_confoundregress"], debug=optiondict["threaddebug"])
849
864
  (
850
865
  mergedregressors,
851
866
  mergedregressorlabels,
852
867
  fmri_data_valid,
853
868
  confoundr2,
854
- ) = tide_glmpass.confoundregress(
869
+ ) = tide_linfitfiltpass.confoundregress(
855
870
  mergedregressors,
856
871
  mergedregressorlabels,
857
872
  fmri_data_valid,
@@ -862,7 +877,7 @@ def rapidtide_main(argparsingfunc):
862
877
  orthogonalize=optiondict["orthogonalize"],
863
878
  showprogressbar=optiondict["showprogressbar"],
864
879
  )
865
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
880
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
866
881
  if confoundr2 is None:
867
882
  print("There are no nonzero confound regressors - exiting")
868
883
  sys.exit()
@@ -875,8 +890,8 @@ def rapidtide_main(argparsingfunc):
875
890
  },
876
891
  )
877
892
  # save the confound filter R2 map
878
- if not optiondict["textio"]:
879
- if fileiscifti:
893
+ if theinputdata.filetype != "text":
894
+ if theinputdata.filetype == "cifti":
880
895
  timeindex = theheader["dim"][0] - 1
881
896
  spaceindex = theheader["dim"][0]
882
897
  theheader["dim"][timeindex] = 1
@@ -886,7 +901,7 @@ def rapidtide_main(argparsingfunc):
886
901
  theheader["dim"][4] = 1
887
902
  theheader["pixdim"][4] = 1.0
888
903
  maplist = [
889
- (confoundr2, "confoundfilterR2", "map", None, "R2 of the motion/confound regression")
904
+ (confoundr2, "confoundfilterR2", "map", None, "R2 of the motion/confound regression"),
890
905
  ]
891
906
  tide_io.savemaplist(
892
907
  outputname,
@@ -895,10 +910,9 @@ def rapidtide_main(argparsingfunc):
895
910
  nativespaceshape,
896
911
  theheader,
897
912
  bidsbasedict,
898
- textio=optiondict["textio"],
899
- fileiscifti=fileiscifti,
913
+ filetype=theinputdata.filetype,
900
914
  rt_floattype=rt_floattype,
901
- cifti_hdr=cifti_hdr,
915
+ cifti_hdr=theinputdata.cifti_hdr,
902
916
  )
903
917
  tide_stats.makeandsavehistogram(
904
918
  confoundr2,
@@ -921,29 +935,10 @@ def rapidtide_main(argparsingfunc):
921
935
  },
922
936
  append=False,
923
937
  )
924
- if optiondict["memprofile"]:
925
- memcheckpoint("...done")
926
- else:
927
- tide_util.logmem("after confound glm filter")
938
+ tide_util.logmem("after confound sLFO filter")
928
939
 
929
940
  if optiondict["saveconfoundfiltered"]:
930
- if not optiondict["textio"]:
931
- theheader = copy.deepcopy(nim_hdr)
932
- if fileiscifti:
933
- nativefmrishape = (1, 1, 1, validtimepoints, numspatiallocs)
934
- timeindex = theheader["dim"][0] - 1
935
- spaceindex = theheader["dim"][0]
936
- theheader["dim"][timeindex] = validtimepoints
937
- theheader["dim"][spaceindex] = numspatiallocs
938
- else:
939
- nativefmrishape = (xsize, ysize, numslices, validtimepoints)
940
- theheader["dim"][4] = validtimepoints
941
- theheader["pixdim"][4] = fmritr
942
- else:
943
- nativefmrishape = (xsize, validtimepoints)
944
- theheader = None
945
- cifti_hdr = None
946
-
941
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
947
942
  maplist = [
948
943
  (
949
944
  fmri_data_valid,
@@ -957,21 +952,26 @@ def rapidtide_main(argparsingfunc):
957
952
  outputname,
958
953
  maplist,
959
954
  validvoxels,
960
- nativefmrishape,
955
+ theinputdata.nativefmrishape,
961
956
  theheader,
962
957
  bidsbasedict,
963
- textio=optiondict["textio"],
964
- fileiscifti=fileiscifti,
958
+ filetype=theinputdata.filetype,
965
959
  rt_floattype=rt_floattype,
966
- cifti_hdr=cifti_hdr,
960
+ cifti_hdr=theinputdata.cifti_hdr,
967
961
  )
968
962
 
969
963
  # get rid of memory we aren't using
970
964
  tide_util.logmem("before purging full sized fmri data")
971
965
  meanvalue = np.mean(
972
- nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1],
966
+ theinputdata.byvoxel(),
967
+ axis=1,
968
+ )
969
+ stddevvalue = np.std(
970
+ theinputdata.byvoxel(),
973
971
  axis=1,
974
972
  )
973
+ covvalue = np.where(meanvalue > 0.0, stddevvalue / meanvalue, 0.0)
974
+ covvalue *= corrmask
975
975
 
976
976
  ####################################################
977
977
  # Get the moving regressor from somewhere
@@ -980,18 +980,88 @@ def rapidtide_main(argparsingfunc):
980
980
  meanfreq = 1.0 / fmritr
981
981
  meanperiod = 1.0 * fmritr
982
982
  meanstarttime = 0.0
983
- meanvec, meanmask = getglobalsignal(
983
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
984
+ "initial regressor",
985
+ "startregressormask",
984
986
  fmri_data,
985
- optiondict,
986
- includemask=internalglobalmeanincludemask,
987
- excludemask=internalglobalmeanexcludemask,
988
- pcacomponents=optiondict["globalpcacomponents"],
989
- debug=False,
987
+ internalinitregressorincludemask,
988
+ meanfreq,
989
+ outputname,
990
+ initfile=True,
991
+ signalgenmethod=optiondict["initregressorsignalmethod"],
992
+ pcacomponents=optiondict["initregressorpcacomponents"],
993
+ excludemask=internalinitregressorexcludemask,
994
+ filedesc="regionalprefilter",
995
+ suffix="",
996
+ debug=optiondict["debug"],
990
997
  )
991
998
 
999
+ if brainmask is not None:
1000
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
1001
+ "whole brain",
1002
+ "brain",
1003
+ fmri_data,
1004
+ internalbrainmask,
1005
+ meanfreq,
1006
+ outputname,
1007
+ filedesc="regionalprefilter",
1008
+ suffix="",
1009
+ debug=optiondict["debug"],
1010
+ )
1011
+
1012
+ if graymask is None:
1013
+ internalgraymask = None
1014
+ else:
1015
+ internalgraymask = graymask.reshape((numspatiallocs))
1016
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
1017
+ "gray matter",
1018
+ "GM",
1019
+ fmri_data,
1020
+ internalgraymask,
1021
+ meanfreq,
1022
+ outputname,
1023
+ excludemask=internalinvbrainmask,
1024
+ filedesc="regionalprefilter",
1025
+ suffix="",
1026
+ debug=optiondict["debug"],
1027
+ )
1028
+
1029
+ if whitemask is None:
1030
+ internalwhitemask = None
1031
+ else:
1032
+ internalwhitemask = whitemask.reshape((numspatiallocs))
1033
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
1034
+ "white matter",
1035
+ "WM",
1036
+ fmri_data,
1037
+ internalwhitemask,
1038
+ meanfreq,
1039
+ outputname,
1040
+ excludemask=internalinvbrainmask,
1041
+ filedesc="regionalprefilter",
1042
+ suffix="",
1043
+ debug=optiondict["debug"],
1044
+ )
1045
+
1046
+ if csfmask is None:
1047
+ internalcsfmask = None
1048
+ else:
1049
+ internalcsfmask = csfmask.reshape((numspatiallocs))
1050
+ csfvec, dummy = tide_mask.saveregionaltimeseries(
1051
+ "CSF",
1052
+ "CSF",
1053
+ fmri_data,
1054
+ internalcsfmask,
1055
+ meanfreq,
1056
+ outputname,
1057
+ excludemask=internalinvbrainmask,
1058
+ filedesc="regionalprefilter",
1059
+ suffix="",
1060
+ debug=optiondict["debug"],
1061
+ )
1062
+
992
1063
  # get rid of more memory we aren't using
993
- del fmri_data
994
- del nim_data
1064
+ theinputdata.unload()
995
1065
  uncollected = gc.collect()
996
1066
  if uncollected != 0:
997
1067
  print(f"garbage collected - unable to collect {uncollected} objects")
@@ -1004,31 +1074,23 @@ def rapidtide_main(argparsingfunc):
1004
1074
  TimingLGR.info("Start of reference prep")
1005
1075
  if regressorfilename is None:
1006
1076
  LGR.info("no regressor file specified - will use the global mean regressor")
1007
- optiondict["useglobalref"] = True
1077
+ optiondict["useinitregressorref"] = True
1008
1078
  else:
1009
- optiondict["useglobalref"] = False
1079
+ optiondict["useinitregressorref"] = False
1010
1080
 
1011
1081
  # now set the regressor that we'll use
1012
- if optiondict["useglobalref"]:
1082
+ if optiondict["useinitregressorref"]:
1013
1083
  LGR.verbose("using global mean as probe regressor")
1014
1084
  inputfreq = meanfreq
1015
1085
  inputperiod = meanperiod
1016
1086
  inputstarttime = meanstarttime
1017
1087
  inputvec = meanvec
1018
- theheader = copy.deepcopy(nim_hdr)
1019
1088
 
1020
1089
  # save the meanmask
1021
- if not optiondict["textio"]:
1022
- if fileiscifti:
1023
- timeindex = theheader["dim"][0] - 1
1024
- spaceindex = theheader["dim"][0]
1025
- theheader["dim"][timeindex] = 1
1026
- theheader["dim"][spaceindex] = numspatiallocs
1027
- else:
1028
- theheader["dim"][0] = 3
1029
- theheader["dim"][4] = 1
1030
- theheader["pixdim"][4] = 1.0
1031
- masklist = [(meanmask, "globalmean", "mask", None, "Voxels used to calculate global mean")]
1090
+ theheader = theinputdata.copyheader(numtimepoints=1)
1091
+ masklist = [
1092
+ (meanmask, "initregressor", "mask", None, "Voxels used to calculate initial regressor")
1093
+ ]
1032
1094
  tide_io.savemaplist(
1033
1095
  outputname,
1034
1096
  masklist,
@@ -1036,10 +1098,9 @@ def rapidtide_main(argparsingfunc):
1036
1098
  nativespaceshape,
1037
1099
  theheader,
1038
1100
  bidsbasedict,
1039
- textio=optiondict["textio"],
1040
- fileiscifti=fileiscifti,
1101
+ filetype=theinputdata.filetype,
1041
1102
  rt_floattype=rt_floattype,
1042
- cifti_hdr=cifti_hdr,
1103
+ cifti_hdr=theinputdata.cifti_hdr,
1043
1104
  )
1044
1105
  optiondict["preprocskip"] = 0
1045
1106
  else:
@@ -1077,10 +1138,10 @@ def rapidtide_main(argparsingfunc):
1077
1138
  )
1078
1139
  LGR.verbose("Input vector")
1079
1140
  LGR.verbose(f"length: {len(inputvec)}")
1080
- LGR.verbose(f"input freq: {inputfreq}")
1141
+ LGR.verbose(f"input freq: {inputfreq:.2f}")
1081
1142
  LGR.verbose(f"input start time: {inputstarttime:.3f}")
1082
1143
 
1083
- if not optiondict["useglobalref"]:
1144
+ if not optiondict["useinitregressorref"]:
1084
1145
  globalcorrx, globalcorry, dummy, dummy = tide_corr.arbcorr(
1085
1146
  meanvec, meanfreq, inputvec, inputfreq, start2=(inputstarttime)
1086
1147
  )
@@ -1104,59 +1165,6 @@ def rapidtide_main(argparsingfunc):
1104
1165
  LGR.verbose(f"the timepoint spacing is {1.0 / inputfreq}")
1105
1166
  LGR.verbose(f"the input timecourse start time is {inputstarttime}")
1106
1167
 
1107
- # if there is an externally specified noise regressor, read it in here
1108
- if optiondict["noisetimecoursespec"] is not None:
1109
- noisetimecoursespec = optiondict["noisetimecoursespec"]
1110
- LGR.info(f"using externally supplied noise regressor {noisetimecoursespec}")
1111
- (
1112
- filenoisefreq,
1113
- filenoisestarttime,
1114
- dummy,
1115
- noisevec,
1116
- dummy,
1117
- dummy,
1118
- ) = tide_io.readvectorsfromtextfile(optiondict["noisetimecoursespec"], onecol=True)
1119
- if optiondict["noiseinvert"]:
1120
- noisevec = noisevec * -1.0
1121
- noisefreq = optiondict["noisefreq"]
1122
- noisestarttime = optiondict["noisestarttime"]
1123
- if noisefreq is None:
1124
- if filenoisefreq is not None:
1125
- noisefreq = filenoisefreq
1126
- else:
1127
- noisefreq = 1.0 / fmritr
1128
- LGR.warning(f"no regressor frequency specified - defaulting to {noisefreq} (1/tr)")
1129
- if noisestarttime is None:
1130
- if filenoisestarttime is not None:
1131
- noisestarttime = filenoisestarttime
1132
- else:
1133
- LGR.warning("no regressor start time specified - defaulting to 0.0")
1134
- noisestarttime = 0.0
1135
- noiseperiod = 1.0 / noisefreq
1136
- numnoise = len(noisevec)
1137
- optiondict["noisefreq"] = noisefreq
1138
- optiondict["noisestarttime"] = noisestarttime
1139
- LGR.debug(
1140
- "Noise timecourse start time, end time, and step: {:.3f}, {:.3f}, {:.3f}".format(
1141
- -noisestarttime, noisestarttime + numnoise * noiseperiod, noiseperiod
1142
- )
1143
- )
1144
- noise_x = np.arange(0.0, numnoise) * noiseperiod - noisestarttime
1145
- noise_y = noisevec[0:numnoise] - np.mean(noisevec[0:numnoise])
1146
- # write out the noise regressor as read
1147
- tide_io.writebidstsv(
1148
- f"{outputname}_desc-initialnoiseregressor_timeseries",
1149
- noise_y,
1150
- noisefreq,
1151
- starttime=-noisestarttime,
1152
- columns=["prefilt"],
1153
- append=False,
1154
- )
1155
- LGR.verbose("noise vector")
1156
- LGR.verbose(f"length: {len(noisevec)}")
1157
- LGR.verbose(f"noise freq: {noisefreq}")
1158
- LGR.verbose(f"noise start time: {noisestarttime:.3f}")
1159
-
1160
1168
  # generate the time axes
1161
1169
  fmrifreq = 1.0 / fmritr
1162
1170
  optiondict["fmrifreq"] = fmrifreq
@@ -1233,8 +1241,6 @@ def rapidtide_main(argparsingfunc):
1233
1241
  reference_y = -np.gradient(reference_y_classfilter)
1234
1242
  else:
1235
1243
  reference_y = reference_y_classfilter
1236
- if optiondict["noisetimecoursespec"] is not None:
1237
- noise_y = theprefilter.apply(noisefreq, noise_y)
1238
1244
 
1239
1245
  # write out the reference regressor used
1240
1246
  tide_io.writebidstsv(
@@ -1260,27 +1266,7 @@ def rapidtide_main(argparsingfunc):
1260
1266
  padlen=int(inputfreq * optiondict["padseconds"]),
1261
1267
  debug=optiondict["debug"],
1262
1268
  )
1263
- reference_y = rt_floatset(reference_y_filt.real)
1264
- if optiondict["noisetimecoursespec"] is not None:
1265
- noise_y_filt = tide_filt.dolptrapfftfilt(
1266
- noisefreq,
1267
- 0.25 * fmrifreq,
1268
- 0.5 * fmrifreq,
1269
- noise_y,
1270
- padlen=int(noisefreq * optiondict["padseconds"]),
1271
- debug=optiondict["debug"],
1272
- )
1273
- noise_y = rt_floatset(noise_y_filt.real)
1274
-
1275
- # write out the noise regressor after filtering
1276
- tide_io.writebidstsv(
1277
- f"{outputname}_desc-initialnoiseregressor_timeseries",
1278
- noise_y,
1279
- noisefreq,
1280
- starttime=-noisestarttime,
1281
- columns=["postfilt"],
1282
- append=True,
1283
- )
1269
+ reference_y = (reference_y_filt.real).astype(rt_floattype)
1284
1270
 
1285
1271
  warnings.filterwarnings("ignore", "Casting*")
1286
1272
 
@@ -1314,35 +1300,6 @@ def rapidtide_main(argparsingfunc):
1314
1300
  order=optiondict["detrendorder"],
1315
1301
  demean=optiondict["dodemean"],
1316
1302
  )
1317
- if optiondict["noisetimecoursespec"] is not None:
1318
- if optiondict["detrendorder"] > 0:
1319
- resampnonosnoise_y = tide_fit.detrend(
1320
- tide_resample.doresample(
1321
- noise_x,
1322
- noise_y,
1323
- initial_fmri_x,
1324
- padlen=int((1.0 / fmritr) * optiondict["padseconds"]),
1325
- padtype="zero",
1326
- method=optiondict["interptype"],
1327
- debug=optiondict["debug"],
1328
- ),
1329
- order=optiondict["detrendorder"],
1330
- demean=optiondict["dodemean"],
1331
- )
1332
- resampnoise_y = tide_fit.detrend(
1333
- tide_resample.doresample(
1334
- noise_x,
1335
- noise_y,
1336
- os_fmri_x,
1337
- padlen=int(oversampfreq * optiondict["padseconds"]),
1338
- padtype="zero",
1339
- method=optiondict["interptype"],
1340
- debug=optiondict["debug"],
1341
- ),
1342
- order=optiondict["detrendorder"],
1343
- demean=optiondict["dodemean"],
1344
- )
1345
-
1346
1303
  else:
1347
1304
  resampnonosref_y = tide_resample.doresample(
1348
1305
  reference_x,
@@ -1358,23 +1315,6 @@ def rapidtide_main(argparsingfunc):
1358
1315
  padlen=int(oversampfreq * optiondict["padseconds"]),
1359
1316
  method=optiondict["interptype"],
1360
1317
  )
1361
- if optiondict["noisetimecoursespec"] is not None:
1362
- resampnonosnoise_y = tide_resample.doresample(
1363
- noise_x,
1364
- noise_y,
1365
- initial_fmri_x,
1366
- padlen=int((1.0 / fmritr) * optiondict["padseconds"]),
1367
- padtype="zero",
1368
- method=optiondict["interptype"],
1369
- )
1370
- resampnoise_y = tide_resample.doresample(
1371
- noise_x,
1372
- noise_y,
1373
- os_fmri_x,
1374
- padlen=int(oversampfreq * optiondict["padseconds"]),
1375
- padtype="zero",
1376
- method=optiondict["interptype"],
1377
- )
1378
1318
 
1379
1319
  LGR.debug(
1380
1320
  f"{len(os_fmri_x)} "
@@ -1387,11 +1327,33 @@ def rapidtide_main(argparsingfunc):
1387
1327
  # save the factor used to normalize the input regressor
1388
1328
  optiondict["initialmovingregressornormfac"] = np.std(resampnonosref_y)
1389
1329
 
1390
- # prepare the temporal mask
1391
- if optiondict["tmaskname"] is not None:
1392
- tmask_y = tide_mask.maketmask(
1393
- optiondict["tmaskname"], reference_x, rt_floatset(reference_y)
1330
+ # prepare the temporal masks
1331
+ if optiondict["tincludemaskname"] is not None:
1332
+ print("creating temporal include mask")
1333
+ includetmask_y = tide_mask.maketmask(
1334
+ optiondict["tincludemaskname"], reference_x, reference_y.astype(rt_floattype) + 0.0
1335
+ )
1336
+ else:
1337
+ includetmask_y = np.ones_like(reference_x)
1338
+ if optiondict["texcludemaskname"] is not None:
1339
+ print("creating temporal exclude mask")
1340
+ excludetmask_y = (
1341
+ -1.0
1342
+ * tide_mask.maketmask(
1343
+ optiondict["texcludemaskname"], reference_x, reference_y.astype(rt_floattype) + 0.0
1344
+ )
1345
+ + 1.0
1394
1346
  )
1347
+ else:
1348
+ excludetmask_y = np.ones_like(reference_x)
1349
+ tmask_y = includetmask_y * excludetmask_y
1350
+ tmask_y = np.where(tmask_y == 0.0, 0.0, 1.0)
1351
+ if optiondict["debug"]:
1352
+ print("after posterizing temporal mask")
1353
+ print(tmask_y)
1354
+ if (optiondict["tincludemaskname"] is not None) or (
1355
+ optiondict["texcludemaskname"] is not None
1356
+ ):
1395
1357
  tmaskos_y = tide_resample.doresample(
1396
1358
  reference_x, tmask_y, os_fmri_x, method=optiondict["interptype"]
1397
1359
  )
@@ -1406,27 +1368,16 @@ def rapidtide_main(argparsingfunc):
1406
1368
  append=False,
1407
1369
  )
1408
1370
  resampnonosref_y *= tmask_y
1409
- thefit, R = tide_fit.mlregress(tmask_y, resampnonosref_y)
1371
+ thefit, R2val = tide_fit.mlregress(tmask_y, resampnonosref_y)
1410
1372
  resampnonosref_y -= thefit[0, 1] * tmask_y
1411
1373
  resampref_y *= tmaskos_y
1412
- thefit, R = tide_fit.mlregress(tmaskos_y, resampref_y)
1374
+ thefit, R2val = tide_fit.mlregress(tmaskos_y, resampref_y)
1413
1375
  resampref_y -= thefit[0, 1] * tmaskos_y
1376
+ else:
1377
+ tmaskos_y = None
1414
1378
 
1415
- if optiondict["noisetimecoursespec"] is not None:
1416
- tide_io.writebidstsv(
1417
- f"{outputname}_desc-noiseregressor_timeseries",
1418
- tide_math.stdnormalize(resampnonosref_y),
1419
- 1.0 / fmritr,
1420
- columns=["resampled"],
1421
- append=False,
1422
- )
1423
- tide_io.writebidstsv(
1424
- f"{outputname}_desc-oversamplednoiseregressor_timeseries",
1425
- tide_math.stdnormalize(resampref_y),
1426
- oversampfreq,
1427
- columns=["oversampled"],
1428
- append=False,
1429
- )
1379
+ # construct refine temporal masks here
1380
+ optiondict["windowedrefinemasks"] = None
1430
1381
 
1431
1382
  (
1432
1383
  optiondict["kurtosis_reference_pass1"],
@@ -1467,16 +1418,21 @@ def rapidtide_main(argparsingfunc):
1467
1418
  # Set up for the delay finding/refinement passes
1468
1419
  ####################################################
1469
1420
  # initialize the Correlator
1470
- theCorrelator = tide_classes.Correlator(
1421
+ theCorrelator = tide_simFuncClasses.Correlator(
1471
1422
  Fs=oversampfreq,
1472
1423
  ncprefilter=theprefilter,
1473
1424
  negativegradient=optiondict["negativegradient"],
1474
1425
  detrendorder=optiondict["detrendorder"],
1426
+ filterinputdata=optiondict["filterinputdata"],
1475
1427
  windowfunc=optiondict["windowfunc"],
1476
1428
  corrweighting=optiondict["corrweighting"],
1477
1429
  corrpadding=optiondict["corrpadding"],
1478
1430
  debug=optiondict["debug"],
1479
1431
  )
1432
+ if optiondict["debug"]:
1433
+ print(
1434
+ f"calling setreftc during initialization with length {optiondict['oversampfactor'] * validtimepoints}"
1435
+ )
1480
1436
  theCorrelator.setreftc(
1481
1437
  np.zeros((optiondict["oversampfactor"] * validtimepoints), dtype=np.float64)
1482
1438
  )
@@ -1495,12 +1451,13 @@ def rapidtide_main(argparsingfunc):
1495
1451
  dummy, trimmedcorrscale, dummy = theCorrelator.getfunction()
1496
1452
 
1497
1453
  # initialize the MutualInformationator
1498
- theMutualInformationator = tide_classes.MutualInformationator(
1454
+ theMutualInformationator = tide_simFuncClasses.MutualInformationator(
1499
1455
  Fs=oversampfreq,
1500
1456
  smoothingtime=optiondict["smoothingtime"],
1501
1457
  ncprefilter=theprefilter,
1502
1458
  negativegradient=optiondict["negativegradient"],
1503
1459
  detrendorder=optiondict["detrendorder"],
1460
+ filterinputdata=optiondict["filterinputdata"],
1504
1461
  windowfunc=optiondict["windowfunc"],
1505
1462
  madnorm=False,
1506
1463
  lagmininpts=lagmininpts,
@@ -1531,6 +1488,7 @@ def rapidtide_main(argparsingfunc):
1531
1488
  1.0,
1532
1489
  starttime=0.0,
1533
1490
  columns=["corrtimes"],
1491
+ extraheaderinfo={"Description": "Trimmed correlation time axis"},
1534
1492
  append=False,
1535
1493
  )
1536
1494
  tide_io.writebidstsv(
@@ -1539,6 +1497,7 @@ def rapidtide_main(argparsingfunc):
1539
1497
  1.0,
1540
1498
  starttime=0.0,
1541
1499
  columns=["mitimes"],
1500
+ extraheaderinfo={"Description": "Trimmed cross mutual information time axis"},
1542
1501
  append=False,
1543
1502
  )
1544
1503
  tide_io.writebidstsv(
@@ -1547,6 +1506,7 @@ def rapidtide_main(argparsingfunc):
1547
1506
  1.0,
1548
1507
  starttime=0.0,
1549
1508
  columns=["corrtimes"],
1509
+ extraheaderinfo={"Description": "Correlation time axis"},
1550
1510
  append=False,
1551
1511
  )
1552
1512
  tide_io.writebidstsv(
@@ -1555,12 +1515,32 @@ def rapidtide_main(argparsingfunc):
1555
1515
  1.0,
1556
1516
  starttime=0.0,
1557
1517
  columns=["mitimes"],
1518
+ extraheaderinfo={"Description": "Cross mutual information time axis"},
1558
1519
  append=False,
1559
1520
  )
1560
- """
1561
- tide_io.writenpvecs(trimmedcorrscale, f"{outputname}_corrtimes.txt")
1562
- tide_io.writenpvecs(trimmedmiscale, f"{outputname}_mitimes.txt")
1563
- """
1521
+
1522
+ # prepare for fast resampling
1523
+ optiondict["fastresamplerpadtime"] = (
1524
+ max((-optiondict["lagmin"], optiondict["lagmax"]))
1525
+ + 30.0
1526
+ + np.abs(optiondict["offsettime"])
1527
+ )
1528
+ numpadtrs = int(optiondict["fastresamplerpadtime"] // fmritr)
1529
+ optiondict["fastresamplerpadtime"] = fmritr * numpadtrs
1530
+ LGR.info(f"setting up fast resampling with padtime = {optiondict['fastresamplerpadtime']}")
1531
+
1532
+ genlagtc = tide_resample.FastResampler(
1533
+ reference_x, reference_y, padtime=optiondict["fastresamplerpadtime"]
1534
+ )
1535
+ genlagtc.save(f"{outputname}_desc-lagtcgenerator_timeseries")
1536
+ if optiondict["debug"]:
1537
+ genlagtc.info()
1538
+ totalpadlen = validtimepoints + 2 * numpadtrs
1539
+ paddedinitial_fmri_x = (
1540
+ np.linspace(0.0, totalpadlen * fmritr, num=totalpadlen, endpoint=False)
1541
+ + skiptime
1542
+ - fmritr * numpadtrs
1543
+ )
1564
1544
 
1565
1545
  # allocate all the data arrays
1566
1546
  tide_util.logmem("before main array allocation")
@@ -1573,14 +1553,36 @@ def rapidtide_main(argparsingfunc):
1573
1553
  fitmask = np.zeros(internalvalidspaceshape, dtype="uint16")
1574
1554
  failreason = np.zeros(internalvalidspaceshape, dtype="uint32")
1575
1555
  R2 = np.zeros(internalvalidspaceshape, dtype=rt_floattype)
1576
- outmaparray = np.zeros(internalspaceshape, dtype=rt_floattype)
1556
+ outmaparray = np.zeros((internalspaceshape), dtype=rt_floattype)
1577
1557
  tide_util.logmem("after main array allocation")
1578
1558
 
1579
- corroutlen = np.shape(trimmedcorrscale)[0]
1580
- if optiondict["textio"]:
1559
+ if optiondict["similaritymetric"] == "riptide":
1560
+ riptideregressorset, riptidedelays = tide_calcSimFuncMap.makeRIPTiDeRegressors(
1561
+ initial_fmri_x,
1562
+ optiondict["lagmin"],
1563
+ optiondict["lagmax"],
1564
+ genlagtc,
1565
+ LGR,
1566
+ targetstep=optiondict["riptidestep"],
1567
+ edgepad=0,
1568
+ showprogressbar=optiondict["showprogressbar"],
1569
+ chunksize=optiondict["mp_chunksize"],
1570
+ nprocs=optiondict["nprocs"],
1571
+ alwaysmultiproc=optiondict["alwaysmultiproc"],
1572
+ rt_floattype=rt_floattype,
1573
+ debug=optiondict["debug"],
1574
+ )
1575
+ numriptideregressors = riptideregressorset.shape[0]
1576
+ corroutlen = numriptideregressors
1577
+ else:
1578
+ riptideregressorset = None
1579
+ riptidedelays = None
1580
+ corroutlen = np.shape(trimmedcorrscale)[0]
1581
+
1582
+ if theinputdata.filetype == "text":
1581
1583
  nativecorrshape = (xsize, corroutlen)
1582
1584
  else:
1583
- if fileiscifti:
1585
+ if theinputdata.filetype == "cifti":
1584
1586
  nativecorrshape = (1, 1, 1, corroutlen, numspatiallocs)
1585
1587
  else:
1586
1588
  nativecorrshape = (xsize, ysize, numslices, corroutlen)
@@ -1589,110 +1591,211 @@ def rapidtide_main(argparsingfunc):
1589
1591
  LGR.debug(
1590
1592
  f"allocating memory for correlation arrays {internalcorrshape} {internalvalidcorrshape}"
1591
1593
  )
1594
+
1595
+ corrout, corrout_shm = tide_util.allocarray(
1596
+ internalvalidcorrshape,
1597
+ rt_floattype,
1598
+ shared=optiondict["sharedmem"],
1599
+ name=f"corrout_{optiondict['pid']}",
1600
+ )
1601
+ gaussout, gaussout_shm = tide_util.allocarray(
1602
+ internalvalidcorrshape,
1603
+ rt_floattype,
1604
+ shared=optiondict["sharedmem"],
1605
+ name=f"gaussout_{optiondict['pid']}",
1606
+ )
1607
+ windowout, windowout_shm = tide_util.allocarray(
1608
+ internalvalidcorrshape,
1609
+ rt_floattype,
1610
+ shared=optiondict["sharedmem"],
1611
+ name=f"windowout_{optiondict['pid']}",
1612
+ )
1613
+ outcorrarray, outcorrarray_shm = tide_util.allocarray(
1614
+ internalcorrshape,
1615
+ rt_floattype,
1616
+ shared=optiondict["sharedmem"],
1617
+ name=f"outcorrarray_{optiondict['pid']}",
1618
+ )
1592
1619
  if optiondict["sharedmem"]:
1593
- corrout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1594
- gaussout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1595
- windowout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1596
- outcorrarray, dummy, dummy = tide_util.allocshared(internalcorrshape, rt_floatset)
1620
+ ramlocation = "in shared memory"
1597
1621
  else:
1598
- corrout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1599
- gaussout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1600
- windowout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1601
- outcorrarray = np.zeros(internalcorrshape, dtype=rt_floattype)
1602
- tide_util.logmem("after correlation array allocation")
1622
+ ramlocation = "locally"
1603
1623
 
1604
- # prepare for fast resampling
1605
- padtime = (
1606
- max((-optiondict["lagmin"], optiondict["lagmax"]))
1607
- + 30.0
1608
- + np.abs(optiondict["offsettime"])
1609
- )
1610
- LGR.info(f"setting up fast resampling with padtime = {padtime}")
1611
- numpadtrs = int(padtime // fmritr)
1612
- padtime = fmritr * numpadtrs
1613
- genlagtc = tide_resample.FastResampler(reference_x, reference_y, padtime=padtime)
1614
- totalpadlen = validtimepoints + 2 * numpadtrs
1615
- paddedinitial_fmri_x = (
1616
- np.linspace(0.0, totalpadlen * fmritr, num=totalpadlen, endpoint=False)
1617
- + skiptime
1618
- - fmritr * numpadtrs
1624
+ optiondict["totalcorrelationbytes"] = (
1625
+ corrout.nbytes + gaussout.nbytes + windowout.nbytes + outcorrarray.nbytes
1619
1626
  )
1627
+ thesize, theunit = tide_util.format_bytes(optiondict["totalcorrelationbytes"])
1628
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for correlation")
1629
+ tide_util.logmem("after correlation array allocation")
1620
1630
 
1621
- if optiondict["textio"]:
1631
+ # if there is an initial delay map, read it in
1632
+ if optiondict["initialdelayvalue"] is not None:
1633
+ try:
1634
+ theinitialdelay = float(optiondict["initialdelayvalue"])
1635
+ except ValueError:
1636
+ (
1637
+ initialdelay_input,
1638
+ initialdelay,
1639
+ initialdelay_header,
1640
+ initialdelay_dims,
1641
+ initialdelay_sizes,
1642
+ ) = tide_io.readfromnifti(optiondict["initialdelayvalue"])
1643
+ theheader = theinputdata.copyheader(numtimepoints=1)
1644
+ if not tide_io.checkspacematch(theheader, initialdelay_header):
1645
+ raise ValueError("fixed delay map dimensions do not match fmri dimensions")
1646
+ theinitialdelay = initialdelay.reshape(numspatiallocs)[validvoxels]
1647
+ else:
1648
+ theinitialdelay = None
1649
+
1650
+ if theinputdata.filetype == "text":
1622
1651
  nativefmrishape = (xsize, np.shape(initial_fmri_x)[0])
1623
- nativepaddedfmrishape = (xsize, 2 * numpadtrs + np.shape(initial_fmri_x)[0])
1652
+ elif theinputdata.filetype == "cifti":
1653
+ nativefmrishape = (1, 1, 1, np.shape(initial_fmri_x)[0], numspatiallocs)
1624
1654
  else:
1625
- if fileiscifti:
1626
- nativefmrishape = (1, 1, 1, np.shape(initial_fmri_x)[0], numspatiallocs)
1627
- nativepaddedfmrishape = (
1628
- 1,
1629
- 1,
1630
- 1,
1631
- 2 * numpadtrs + np.shape(initial_fmri_x)[0],
1632
- numspatiallocs,
1633
- )
1634
- else:
1635
- nativefmrishape = (xsize, ysize, numslices, np.shape(initial_fmri_x)[0])
1636
- nativepaddedfmrishape = (
1637
- xsize,
1638
- ysize,
1639
- numslices,
1640
- 2 * numpadtrs + np.shape(initial_fmri_x)[0],
1641
- )
1655
+ nativefmrishape = (xsize, ysize, numslices, np.shape(initial_fmri_x)[0])
1642
1656
 
1643
1657
  internalfmrishape = (numspatiallocs, np.shape(initial_fmri_x)[0])
1644
1658
  internalvalidfmrishape = (numvalidspatiallocs, np.shape(initial_fmri_x)[0])
1645
- internalpaddedfmrishape = (numspatiallocs, 2 * numpadtrs + np.shape(initial_fmri_x)[0])
1646
1659
  internalvalidpaddedfmrishape = (
1647
1660
  numvalidspatiallocs,
1648
1661
  2 * numpadtrs + np.shape(initial_fmri_x)[0],
1649
1662
  )
1650
1663
 
1664
+ # now do the arrays for delay refinement
1651
1665
  if (
1652
- optiondict["passes"] > 1
1653
- or optiondict["globalpreselect"]
1654
- or optiondict["convergencethresh"] is not None
1666
+ optiondict["dolinfitfilt"]
1667
+ or optiondict["docvrmap"]
1668
+ or optiondict["refinedelay"]
1669
+ or (optiondict["similaritymetric"] == "riptide")
1655
1670
  ):
1656
- if optiondict["sharedmem"]:
1657
- shiftedtcs, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
1658
- weights, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
1659
- paddedshiftedtcs, dummy, dummy = tide_util.allocshared(
1660
- internalvalidpaddedfmrishape, rt_floatset
1661
- )
1662
- paddedweights, dummy, dummy = tide_util.allocshared(
1663
- internalvalidpaddedfmrishape, rt_floatset
1664
- )
1671
+ if optiondict["refinedelay"]:
1672
+ derivaxissize = np.max([2, optiondict["regressderivs"] + 1])
1665
1673
  else:
1666
- shiftedtcs = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
1667
- weights = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
1668
- paddedshiftedtcs, dummy, dummy = tide_util.allocshared(
1669
- internalvalidpaddedfmrishape, rt_floatset
1670
- )
1671
- paddedweights, dummy, dummy = tide_util.allocshared(
1672
- internalvalidpaddedfmrishape, rt_floatset
1673
- )
1674
- tide_util.logmem("after refinement array allocation")
1675
- if optiondict["sharedmem"]:
1676
- outfmriarray, dummy, dummy = tide_util.allocshared(internalfmrishape, rt_floatset)
1677
- paddedoutfmriarray, dummy, dummy = tide_util.allocshared(
1678
- (internalpaddedfmrishape), rt_floatset
1674
+ derivaxissize = optiondict["regressderivs"] + 1
1675
+ internalvalidspaceshapederivs = (
1676
+ internalvalidspaceshape,
1677
+ derivaxissize,
1679
1678
  )
1680
- else:
1681
- outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
1682
- paddedoutfmriarray, dummy, dummy = tide_util.allocshared(
1683
- (internalpaddedfmrishape), rt_floatset
1679
+ sLFOfitmean, sLFOfitmean_shm = tide_util.allocarray(
1680
+ internalvalidspaceshape,
1681
+ rt_outfloattype,
1682
+ shared=optiondict["sharedmem"],
1683
+ name=f"sLFOfitmean_{optiondict['pid']}",
1684
1684
  )
1685
-
1686
- # cycle over all voxels
1687
- refine = True
1688
- LGR.verbose(f"refine is set to {refine}")
1685
+ rvalue, rvalue_shm = tide_util.allocarray(
1686
+ internalvalidspaceshape,
1687
+ rt_outfloattype,
1688
+ shared=optiondict["sharedmem"],
1689
+ name=f"rvalue_{optiondict['pid']}",
1690
+ )
1691
+ r2value, r2value_shm = tide_util.allocarray(
1692
+ internalvalidspaceshape,
1693
+ rt_outfloattype,
1694
+ shared=optiondict["sharedmem"],
1695
+ name=f"r2value_{optiondict['pid']}",
1696
+ )
1697
+ fitNorm, fitNorm_shm = tide_util.allocarray(
1698
+ internalvalidspaceshapederivs,
1699
+ rt_outfloattype,
1700
+ shared=optiondict["sharedmem"],
1701
+ name=f"fitNorm_{optiondict['pid']}",
1702
+ )
1703
+ fitcoeff, fitcoeff_shm = tide_util.allocarray(
1704
+ internalvalidspaceshapederivs,
1705
+ rt_outfloattype,
1706
+ shared=optiondict["sharedmem"],
1707
+ name=f"fitcoeff_{optiondict['pid']}",
1708
+ )
1709
+ lagtc, lagtc_shm = tide_util.allocarray(
1710
+ internalvalidfmrishape,
1711
+ rt_floattype,
1712
+ shared=optiondict["sharedmem"],
1713
+ name=f"lagtc_{optiondict['pid']}",
1714
+ )
1715
+ if optiondict["sharedmem"]:
1716
+ ramlocation = "in shared memory"
1717
+ else:
1718
+ ramlocation = "locally"
1719
+
1720
+ optiondict["totalRefineDelaybytes"] = (
1721
+ sLFOfitmean.nbytes
1722
+ + rvalue.nbytes
1723
+ + r2value.nbytes
1724
+ + fitNorm.nbytes
1725
+ + fitcoeff.nbytes
1726
+ + lagtc.nbytes
1727
+ )
1728
+ thesize, theunit = tide_util.format_bytes(optiondict["totalRefineDelaybytes"])
1729
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for delay refinement")
1730
+ tide_util.logmem("after derivative delay/sLFO filter array allocation")
1731
+ else:
1732
+ sLFOfitmean = None
1733
+ rvalue = None
1734
+ r2value = None
1735
+ fitNorm = None
1736
+ fitcoeff = None
1737
+ lagtc = None
1738
+
1739
+ # prepare for regressor refinement, if we're doing it
1740
+ if (
1741
+ optiondict["passes"] > 1
1742
+ or optiondict["initregressorpreselect"]
1743
+ or optiondict["dofinalrefine"]
1744
+ or optiondict["convergencethresh"] is not None
1745
+ ):
1746
+ # we will be doing regressor refinement, so configure the refiner
1747
+ theRegressorRefiner = tide_refineRegressor.RegressorRefiner(
1748
+ internalvalidfmrishape,
1749
+ internalvalidpaddedfmrishape,
1750
+ optiondict["pid"],
1751
+ optiondict["outputname"],
1752
+ initial_fmri_x,
1753
+ paddedinitial_fmri_x,
1754
+ os_fmri_x,
1755
+ sharedmem=optiondict["sharedmem"],
1756
+ offsettime=optiondict["offsettime"],
1757
+ ampthresh=optiondict["ampthresh"],
1758
+ lagminthresh=optiondict["lagminthresh"],
1759
+ lagmaxthresh=optiondict["lagmaxthresh"],
1760
+ sigmathresh=optiondict["sigmathresh"],
1761
+ cleanrefined=optiondict["cleanrefined"],
1762
+ bipolar=optiondict["bipolar"],
1763
+ fixdelay=optiondict["fixdelay"],
1764
+ LGR=LGR,
1765
+ nprocs=optiondict["nprocs_refine"],
1766
+ detrendorder=optiondict["detrendorder"],
1767
+ alwaysmultiproc=optiondict["alwaysmultiproc"],
1768
+ showprogressbar=optiondict["showprogressbar"],
1769
+ chunksize=optiondict["mp_chunksize"],
1770
+ padtrs=numpadtrs,
1771
+ refineprenorm=optiondict["refineprenorm"],
1772
+ refineweighting=optiondict["refineweighting"],
1773
+ refinetype=optiondict["refinetype"],
1774
+ pcacomponents=optiondict["pcacomponents"],
1775
+ windowfunc=optiondict["windowfunc"],
1776
+ passes=optiondict["passes"],
1777
+ maxpasses=optiondict["maxpasses"],
1778
+ convergencethresh=optiondict["convergencethresh"],
1779
+ interptype=optiondict["interptype"],
1780
+ usetmask=(optiondict["tincludemaskname"] is not None),
1781
+ tmask_y=tmask_y,
1782
+ tmaskos_y=tmaskos_y,
1783
+ fastresamplerpadtime=optiondict["fastresamplerpadtime"],
1784
+ prewhitenregressor=False,
1785
+ prewhitenlags=optiondict["prewhitenlags"],
1786
+ debug=optiondict["debug"],
1787
+ )
1788
+
1789
+ # cycle over all voxels
1790
+ refine = True
1791
+ LGR.verbose(f"refine is set to {refine}")
1689
1792
  optiondict["edgebufferfrac"] = max(
1690
1793
  [optiondict["edgebufferfrac"], 2.0 / np.shape(corrscale)[0]]
1691
1794
  )
1692
1795
  LGR.verbose(f"edgebufferfrac set to {optiondict['edgebufferfrac']}")
1693
1796
 
1694
- # intitialize the correlation fitter
1695
- thefitter = tide_classes.SimilarityFunctionFitter(
1797
+ # initialize the correlation fitter
1798
+ theFitter = tide_simFuncClasses.SimilarityFunctionFitter(
1696
1799
  lagmod=optiondict["lagmod"],
1697
1800
  lthreshval=optiondict["lthreshval"],
1698
1801
  uthreshval=optiondict["uthreshval"],
@@ -1713,11 +1816,6 @@ def rapidtide_main(argparsingfunc):
1713
1816
  if optiondict["echocancel"]:
1714
1817
  LGR.info("\n\nEcho cancellation")
1715
1818
  TimingLGR.info("Echo cancellation start")
1716
- calcsimilaritypass_func = addmemprofiling(
1717
- tide_calcsimfunc.correlationpass,
1718
- optiondict["memprofile"],
1719
- "before correlationpass",
1720
- )
1721
1819
 
1722
1820
  referencetc = tide_math.corrnormalize(
1723
1821
  resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
@@ -1725,12 +1823,12 @@ def rapidtide_main(argparsingfunc):
1725
1823
  windowfunc=optiondict["windowfunc"],
1726
1824
  )
1727
1825
 
1728
- disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
1826
+ tide_util.disablemkl(optiondict["nprocs_calcsimilarity"], debug=optiondict["threaddebug"])
1729
1827
  (
1730
1828
  voxelsprocessed_echo,
1731
1829
  theglobalmaxlist,
1732
1830
  trimmedcorrscale,
1733
- ) = calcsimilaritypass_func(
1831
+ ) = tide_calcsimfunc.correlationpass(
1734
1832
  fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1735
1833
  referencetc,
1736
1834
  theCorrelator,
@@ -1746,10 +1844,9 @@ def rapidtide_main(argparsingfunc):
1746
1844
  interptype=optiondict["interptype"],
1747
1845
  showprogressbar=optiondict["showprogressbar"],
1748
1846
  chunksize=optiondict["mp_chunksize"],
1749
- rt_floatset=rt_floatset,
1750
1847
  rt_floattype=rt_floattype,
1751
1848
  )
1752
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
1849
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
1753
1850
 
1754
1851
  for i in range(len(theglobalmaxlist)):
1755
1852
  theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
@@ -1770,13 +1867,13 @@ def rapidtide_main(argparsingfunc):
1770
1867
  # Now find and regress out the echo
1771
1868
  echooffset, echoratio = tide_stats.echoloc(np.asarray(theglobalmaxlist), len(corrscale))
1772
1869
  LGR.info(f"Echooffset, echoratio: {echooffset} {echoratio}")
1773
- echoremovedtc, echofit, echoR = echocancel(
1870
+ echoremovedtc, echofit, echoR2 = echocancel(
1774
1871
  resampref_y, echooffset, oversamptr, outputname, numpadtrs
1775
1872
  )
1776
1873
  optiondict["echooffset"] = echooffset
1777
1874
  optiondict["echoratio"] = echoratio
1778
1875
  optiondict["echofit"] = [echofit[0, 0], echofit[0, 1]]
1779
- optiondict["echofitR"] = echoR
1876
+ optiondict["echofitR2"] = echoR2
1780
1877
  resampref_y = echoremovedtc
1781
1878
  TimingLGR.info(
1782
1879
  "Echo cancellation calculation end",
@@ -1785,6 +1882,32 @@ def rapidtide_main(argparsingfunc):
1785
1882
  "message3": "voxels",
1786
1883
  },
1787
1884
  )
1885
+ tide_io.writebidstsv(
1886
+ f"{outputname}_desc-oversampledmovingregressor_timeseries",
1887
+ tide_math.stdnormalize(resampref_y),
1888
+ oversampfreq,
1889
+ columns=["pass1_echocancel"],
1890
+ extraheaderinfo={
1891
+ "Description": "The probe regressor used in each pass, at the time resolution used for calculating the similarity function"
1892
+ },
1893
+ append=True,
1894
+ )
1895
+
1896
+ # Preprocessing - prewhitening
1897
+ if optiondict["prewhitenregressor"]:
1898
+ resampref_y = tide_fit.prewhiten(
1899
+ resampref_y, optiondict["prewhitenlags"], debug=optiondict["debug"]
1900
+ )
1901
+ tide_io.writebidstsv(
1902
+ f"{outputname}_desc-oversampledmovingregressor_timeseries",
1903
+ tide_math.stdnormalize(resampref_y),
1904
+ oversampfreq,
1905
+ columns=["pass1_prewhiten"],
1906
+ extraheaderinfo={
1907
+ "Description": "The probe regressor used in each pass, at the time resolution used for calculating the similarity function"
1908
+ },
1909
+ append=True,
1910
+ )
1788
1911
 
1789
1912
  # --------------------- Main pass loop ---------------------
1790
1913
  # loop over all passes
@@ -1799,6 +1922,19 @@ def rapidtide_main(argparsingfunc):
1799
1922
  optiondict["currentstage"] = "preprocessingdone"
1800
1923
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
1801
1924
 
1925
+ # set up the pass options array
1926
+ optiondict["passoptions"] = []
1927
+ """optiondict["passoptions"].append(
1928
+ {
1929
+ "similaritymetric": "riptide"
1930
+ }
1931
+ )
1932
+ optiondict["passoptions"].append(
1933
+ {
1934
+ "similaritymetric": optiondict["similaritymetric"]
1935
+ }
1936
+ )"""
1937
+
1802
1938
  ####################################################
1803
1939
  # Start the iterative fit and refinement
1804
1940
  ####################################################
@@ -1811,6 +1947,10 @@ def rapidtide_main(argparsingfunc):
1811
1947
  LGR.info("\n\n*********************")
1812
1948
  LGR.info(f"Pass number {thepass}")
1813
1949
 
1950
+ # fetch the pass options
1951
+ if len(optiondict["passoptions"]) >= thepass:
1952
+ setpassoptions(optiondict["passoptions"][thepass - 1], optiondict)
1953
+
1814
1954
  referencetc = tide_math.corrnormalize(
1815
1955
  resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
1816
1956
  detrendorder=optiondict["detrendorder"],
@@ -1818,245 +1958,56 @@ def rapidtide_main(argparsingfunc):
1818
1958
  )
1819
1959
 
1820
1960
  # Step -1 - check the regressor for periodic components in the passband
1821
- dolagmod = True
1822
- doreferencenotch = True
1823
- if optiondict["respdelete"]:
1824
- resptracker = tide_classes.FrequencyTracker(nperseg=64)
1825
- thetimes, thefreqs = resptracker.track(resampref_y, 1.0 / oversamptr)
1826
- tide_io.writevec(thefreqs, f"{outputname}_peakfreaks_pass{thepass}.txt")
1827
- resampref_y = resptracker.clean(resampref_y, 1.0 / oversamptr, thetimes, thefreqs)
1828
- tide_io.writevec(resampref_y, f"{outputname}_respfilt_pass{thepass}.txt")
1829
- referencetc = tide_math.corrnormalize(
1830
- resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
1831
- detrendorder=optiondict["detrendorder"],
1832
- windowfunc=optiondict["windowfunc"],
1833
- )
1834
- if optiondict["noisetimecoursespec"] is not None:
1835
- # align the noise signal with referencetc
1836
- (
1837
- shiftednoise,
1838
- optiondict[f"noisedelay_pass{thepass}"],
1839
- optiondict[f"noisecorr_pass{thepass}"],
1840
- thisfailreason,
1841
- ) = tide_corr.aligntcwithref(
1842
- resampref_y,
1843
- resampnoise_y,
1844
- oversampfreq,
1845
- zerooutbadfit=False,
1846
- verbose=True,
1847
- )
1848
- LGR.info(
1849
- "Maximum correlation amplitude with noise regressor is "
1850
- + str(optiondict[f"noisecorr_pass{thepass}"])
1851
- + " at "
1852
- + str(optiondict[f"noisedelay_pass{thepass}"])
1853
- )
1854
-
1855
- # regress out
1856
- resampref_y, datatoremove, R, coffs = tide_fit.glmfilt(
1857
- resampref_y, shiftednoise, debug=True
1858
- )
1859
-
1860
- # save
1861
- tide_io.writebidstsv(
1862
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1863
- shiftednoise,
1864
- 1.0 / oversamptr,
1865
- starttime=0.0,
1866
- columns=[f"shiftednoise_pass{thepass}"],
1867
- append=(thepass > 1),
1868
- )
1869
- tide_io.writebidstsv(
1870
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1871
- datatoremove,
1872
- 1.0 / oversamptr,
1873
- starttime=0.0,
1874
- columns=[f"removed_pass{thepass}"],
1875
- append=True,
1876
- )
1877
- tide_io.writebidstsv(
1878
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1879
- resampref_y,
1880
- 1.0 / oversamptr,
1881
- starttime=0.0,
1882
- columns=[f"filtered_pass{thepass}"],
1883
- append=True,
1884
- )
1885
-
1886
- if optiondict["check_autocorrelation"]:
1887
- LGR.info("checking reference regressor autocorrelation properties")
1888
- optiondict["lagmod"] = 1000.0
1889
- lagindpad = corrorigin - 2 * np.max((lagmininpts, lagmaxinpts))
1890
- acmininpts = lagmininpts + lagindpad
1891
- acmaxinpts = lagmaxinpts + lagindpad
1892
- theCorrelator.setreftc(referencetc)
1893
- theCorrelator.setlimits(acmininpts, acmaxinpts)
1894
- thexcorr, accheckcorrscale, dummy = theCorrelator.run(
1895
- resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1]
1896
- )
1897
- thefitter.setcorrtimeaxis(accheckcorrscale)
1898
- (
1899
- maxindex,
1900
- maxlag,
1901
- maxval,
1902
- acwidth,
1903
- maskval,
1904
- peakstart,
1905
- peakend,
1906
- thisfailreason,
1907
- ) = tide_simfuncfit.onesimfuncfit(
1908
- thexcorr,
1909
- thefitter,
1910
- despeckle_thresh=optiondict["despeckle_thresh"],
1911
- lthreshval=optiondict["lthreshval"],
1912
- fixdelay=optiondict["fixdelay"],
1913
- rt_floatset=rt_floatset,
1914
- rt_floattype=rt_floattype,
1915
- )
1916
- outputarray = np.asarray([accheckcorrscale, thexcorr])
1917
- tide_io.writebidstsv(
1918
- f"{outputname}_desc-autocorr_timeseries",
1919
- thexcorr,
1920
- 1.0 / (accheckcorrscale[1] - accheckcorrscale[0]),
1921
- starttime=accheckcorrscale[0],
1922
- extraheaderinfo={
1923
- "Description": "Autocorrelation of the probe regressor for each pass"
1924
- },
1925
- columns=[f"pass{thepass}"],
1926
- append=(thepass > 1),
1927
- )
1928
- thelagthresh = np.max((abs(optiondict["lagmin"]), abs(optiondict["lagmax"])))
1929
- theampthresh = 0.1
1930
- LGR.info(
1931
- f"searching for sidelobes with amplitude > {theampthresh} "
1932
- f"with abs(lag) < {thelagthresh} s"
1933
- )
1934
- sidelobetime, sidelobeamp = tide_corr.check_autocorrelation(
1935
- accheckcorrscale,
1936
- thexcorr,
1937
- acampthresh=theampthresh,
1938
- aclagthresh=thelagthresh,
1939
- detrendorder=optiondict["detrendorder"],
1940
- )
1941
- optiondict["acwidth"] = acwidth + 0.0
1942
- optiondict["absmaxsigma"] = acwidth * 10.0
1943
- passsuffix = "_pass" + str(thepass)
1944
- if sidelobetime is not None:
1945
- optiondict["acsidelobelag" + passsuffix] = sidelobetime
1946
- optiondict["despeckle_thresh"] = np.max(
1947
- [optiondict["despeckle_thresh"], sidelobetime / 2.0]
1948
- )
1949
- optiondict["acsidelobeamp" + passsuffix] = sidelobeamp
1950
- LGR.warning(
1951
- f"\n\nWARNING: check_autocorrelation found bad sidelobe at {sidelobetime} "
1952
- f"seconds ({1.0 / sidelobetime} Hz)..."
1953
- )
1954
- # bidsify
1955
- """tide_io.writebidstsv(
1956
- f"{outputname}_desc-movingregressor_timeseries",
1957
- tide_math.stdnormalize(resampnonosref_y),
1958
- 1.0 / fmritr,
1959
- columns=["pass1"],
1960
- append=False,
1961
- )"""
1962
- tide_io.writenpvecs(
1963
- np.array([sidelobetime]),
1964
- f"{outputname}_autocorr_sidelobetime" + passsuffix + ".txt",
1965
- )
1966
- if optiondict["fix_autocorrelation"]:
1967
- LGR.info("Removing sidelobe")
1968
- if dolagmod:
1969
- LGR.info("subjecting lag times to modulus")
1970
- optiondict["lagmod"] = sidelobetime / 2.0
1971
- if doreferencenotch:
1972
- LGR.info("removing spectral component at sidelobe frequency")
1973
- acstopfreq = 1.0 / sidelobetime
1974
- acfixfilter = tide_filt.NoncausalFilter(
1975
- debug=optiondict["debug"],
1976
- )
1977
- acfixfilter.settype("arb_stop")
1978
- acfixfilter.setfreqs(
1979
- acstopfreq * 0.9,
1980
- acstopfreq * 0.95,
1981
- acstopfreq * 1.05,
1982
- acstopfreq * 1.1,
1983
- )
1984
- cleaned_resampref_y = tide_math.corrnormalize(
1985
- acfixfilter.apply(1.0 / oversamptr, resampref_y),
1986
- windowfunc="None",
1987
- detrendorder=optiondict["detrendorder"],
1988
- )
1989
- cleaned_referencetc = tide_math.corrnormalize(
1990
- cleaned_resampref_y,
1991
- detrendorder=optiondict["detrendorder"],
1992
- windowfunc=optiondict["windowfunc"],
1993
- )
1994
- cleaned_nonosreferencetc = tide_math.stdnormalize(
1995
- acfixfilter.apply(fmrifreq, resampnonosref_y)
1996
- )
1997
- tide_io.writebidstsv(
1998
- f"{outputname}_desc-cleanedreferencefmrires_info",
1999
- cleaned_nonosreferencetc,
2000
- fmrifreq,
2001
- columns=[f"pass{thepass}"],
2002
- append=(thepass > 1),
2003
- )
2004
- tide_io.writebidstsv(
2005
- f"{outputname}_desc-cleanedreference_info",
2006
- cleaned_referencetc,
2007
- 1.0 / oversamptr,
2008
- columns=[f"pass{thepass}"],
2009
- append=(thepass > 1),
2010
- )
2011
- tide_io.writebidstsv(
2012
- f"{outputname}_desc-cleanedresamprefy_info",
2013
- cleaned_resampref_y,
2014
- 1.0 / oversamptr,
2015
- columns=[f"pass{thepass}"],
2016
- append=(thepass > 1),
2017
- )
2018
- else:
2019
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
2020
- resampref_y,
2021
- windowfunc="None",
2022
- detrendorder=optiondict["detrendorder"],
2023
- )
2024
- cleaned_referencetc = 1.0 * referencetc
2025
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
2026
- else:
2027
- LGR.info("no sidelobes found in range")
2028
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
2029
- resampref_y,
2030
- windowfunc="None",
2031
- detrendorder=optiondict["detrendorder"],
2032
- )
2033
- cleaned_referencetc = 1.0 * referencetc
2034
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
2035
- else:
2036
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
2037
- resampref_y, windowfunc="None", detrendorder=optiondict["detrendorder"]
1961
+ passsuffix = "_pass" + str(thepass)
1962
+ (
1963
+ cleaned_resampref_y,
1964
+ cleaned_referencetc,
1965
+ cleaned_nonosreferencetc,
1966
+ optiondict["despeckle_thresh"],
1967
+ optiondict["acsidelobeamp" + passsuffix],
1968
+ optiondict["acsidelobelag" + passsuffix],
1969
+ optiondict["lagmod"],
1970
+ optiondict["acwidth"],
1971
+ optiondict["absmaxsigma"],
1972
+ ) = tide_cleanregressor.cleanregressor(
1973
+ outputname,
1974
+ thepass,
1975
+ referencetc,
1976
+ resampref_y,
1977
+ resampnonosref_y,
1978
+ fmrifreq,
1979
+ oversampfreq,
1980
+ osvalidsimcalcstart,
1981
+ osvalidsimcalcend,
1982
+ lagmininpts,
1983
+ lagmaxinpts,
1984
+ theFitter,
1985
+ theCorrelator,
1986
+ optiondict["lagmin"],
1987
+ optiondict["lagmax"],
1988
+ LGR=LGR,
1989
+ check_autocorrelation=optiondict["check_autocorrelation"],
1990
+ fix_autocorrelation=optiondict["fix_autocorrelation"],
1991
+ despeckle_thresh=optiondict["despeckle_thresh"],
1992
+ lthreshval=optiondict["lthreshval"],
1993
+ fixdelay=optiondict["fixdelay"],
1994
+ detrendorder=optiondict["detrendorder"],
1995
+ windowfunc=optiondict["windowfunc"],
1996
+ respdelete=optiondict["respdelete"],
1997
+ debug=optiondict["debug"],
1998
+ rt_floattype=rt_floattype,
1999
+ )
2000
+ if optiondict["debug"]:
2001
+ print(
2002
+ f"after cleanregressor: {len(referencetc)=}, {len(cleaned_referencetc)=}, {osvalidsimcalcstart=}, {osvalidsimcalcend=}, {lagmininpts=}, {lagmaxinpts=}"
2038
2003
  )
2039
- cleaned_referencetc = 1.0 * referencetc
2040
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
2041
2004
 
2042
2005
  # Step 0 - estimate significance
2043
2006
  if optiondict["numestreps"] > 0:
2044
2007
  TimingLGR.info(f"Significance estimation start, pass {thepass}")
2045
2008
  LGR.info(f"\n\nSignificance estimation, pass {thepass}")
2046
- getNullDistributionData_func = addmemprofiling(
2047
- tide_nullsimfunc.getNullDistributionDatax,
2048
- optiondict["memprofile"],
2049
- "before getnulldistristributiondata",
2050
- )
2051
2009
  if optiondict["checkpoint"]:
2052
2010
  # bidsify
2053
- """tide_io.writebidstsv(
2054
- f"{outputname}_desc-movingregressor_timeseries",
2055
- tide_math.stdnormalize(resampnonosref_y),
2056
- 1.0 / fmritr,
2057
- columns=["pass1"],
2058
- append=False,
2059
- )"""
2060
2011
  tide_io.writenpvecs(
2061
2012
  cleaned_referencetc,
2062
2013
  f"{outputname}_cleanedreference_pass" + str(thepass) + ".txt",
@@ -2070,34 +2021,36 @@ def rapidtide_main(argparsingfunc):
2070
2021
  f"{outputname}_options_pregetnull_pass" + str(thepass) + ".json",
2071
2022
  )
2072
2023
  theCorrelator.setlimits(lagmininpts, lagmaxinpts)
2024
+ if optiondict["debug"]:
2025
+ print(
2026
+ f"calling setreftc prior to significance estimation with length {len(cleaned_resampref_y)}"
2027
+ )
2073
2028
  theCorrelator.setreftc(cleaned_resampref_y)
2074
2029
  theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
2075
2030
  theMutualInformationator.setreftc(cleaned_resampref_y)
2076
2031
  dummy, trimmedcorrscale, dummy = theCorrelator.getfunction()
2077
- thefitter.setcorrtimeaxis(trimmedcorrscale)
2078
- # add parallel path for mutualinformationator BBF
2032
+ theFitter.setcorrtimeaxis(trimmedcorrscale)
2033
+
2034
+ # parallel path for mutual information
2079
2035
  if optiondict["similaritymetric"] == "mutualinfo":
2080
2036
  theSimFunc = theMutualInformationator
2081
2037
  else:
2082
2038
  theSimFunc = theCorrelator
2083
- disablemkl(optiondict["nprocs_getNullDist"], debug=threaddebug)
2084
- simdistdata = getNullDistributionData_func(
2085
- cleaned_resampref_y,
2039
+ tide_util.disablemkl(optiondict["nprocs_getNullDist"], debug=optiondict["threaddebug"])
2040
+ simdistdata = tide_nullsimfunc.getNullDistributionData(
2086
2041
  oversampfreq,
2087
2042
  theSimFunc,
2088
- thefitter,
2043
+ theFitter,
2044
+ LGR,
2089
2045
  numestreps=optiondict["numestreps"],
2090
2046
  nprocs=optiondict["nprocs_getNullDist"],
2091
2047
  alwaysmultiproc=optiondict["alwaysmultiproc"],
2092
2048
  showprogressbar=optiondict["showprogressbar"],
2093
2049
  chunksize=optiondict["mp_chunksize"],
2094
2050
  permutationmethod=optiondict["permutationmethod"],
2095
- fixdelay=optiondict["fixdelay"],
2096
- fixeddelayvalue=optiondict["fixeddelayvalue"],
2097
- rt_floatset=np.float64,
2098
- rt_floattype="float64",
2051
+ rt_floattype=np.float64,
2099
2052
  )
2100
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2053
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
2101
2054
 
2102
2055
  tide_io.writebidstsv(
2103
2056
  f"{outputname}_desc-simdistdata_info",
@@ -2136,22 +2089,22 @@ def rapidtide_main(argparsingfunc):
2136
2089
  similaritymetric=optiondict["similaritymetric"],
2137
2090
  twotail=optiondict["bipolar"],
2138
2091
  nozero=optiondict["nohistzero"],
2139
- dosighistfit=optiondict["dosighistfit"],
2140
2092
  )
2093
+ if sigfit is None:
2094
+ optiondict["ampthreshfromsig"] = False
2141
2095
  if pcts is not None:
2142
2096
  for i in range(len(thepvalnames)):
2143
2097
  optiondict[
2144
2098
  "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_thresh.txt"
2145
2099
  ] = pcts[i]
2146
- if optiondict["dosighistfit"]:
2147
- optiondict[
2148
- "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_fitthresh"
2149
- ] = pcts_fit[i]
2150
- optiondict["sigfit"] = sigfit
2100
+ optiondict[
2101
+ "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_fitthresh"
2102
+ ] = pcts_fit[i]
2103
+ optiondict["sigfit"] = sigfit
2151
2104
  if optiondict["ampthreshfromsig"]:
2152
2105
  if pcts is not None:
2153
2106
  LGR.info(
2154
- f"setting ampthresh to the p < {1.0 - thepercentiles[0]:.3f} threshhold"
2107
+ f"setting ampthresh to the p < {1.0 - thepercentiles[0]:.3f} threshold"
2155
2108
  )
2156
2109
  optiondict["ampthresh"] = pcts[0]
2157
2110
  tide_stats.printthresholds(
@@ -2159,25 +2112,24 @@ def rapidtide_main(argparsingfunc):
2159
2112
  thepercentiles,
2160
2113
  "Crosscorrelation significance thresholds from data:",
2161
2114
  )
2162
- if optiondict["dosighistfit"]:
2163
- tide_stats.printthresholds(
2164
- pcts_fit,
2165
- thepercentiles,
2166
- "Crosscorrelation significance thresholds from fit:",
2167
- )
2168
- namesuffix = "_desc-nullsimfunc_hist"
2169
- tide_stats.makeandsavehistogram(
2170
- simdistdata,
2171
- optiondict["sighistlen"],
2172
- 0,
2173
- outputname + namesuffix,
2174
- displaytitle="Null correlation histogram",
2175
- refine=False,
2176
- dictvarname="nullsimfunchist_pass" + str(thepass),
2177
- therange=(0.0, 1.0),
2178
- append=(thepass > 1),
2179
- thedict=optiondict,
2180
- )
2115
+ tide_stats.printthresholds(
2116
+ pcts_fit,
2117
+ thepercentiles,
2118
+ "Crosscorrelation significance thresholds from fit:",
2119
+ )
2120
+ namesuffix = "_desc-nullsimfunc_hist"
2121
+ tide_stats.makeandsavehistogram(
2122
+ simdistdata,
2123
+ optiondict["sighistlen"],
2124
+ 0,
2125
+ outputname + namesuffix,
2126
+ displaytitle="Null correlation histogram",
2127
+ refine=False,
2128
+ dictvarname="nullsimfunchist_pass" + str(thepass),
2129
+ therange=(0.0, 1.0),
2130
+ append=(thepass > 1),
2131
+ thedict=optiondict,
2132
+ )
2181
2133
  else:
2182
2134
  LGR.info("leaving ampthresh unchanged")
2183
2135
  else:
@@ -2191,347 +2143,207 @@ def rapidtide_main(argparsingfunc):
2191
2143
  "message3": "repetitions",
2192
2144
  },
2193
2145
  )
2194
-
2195
2146
  # write out the current version of the run options
2196
2147
  optiondict["currentstage"] = f"precorrelation_pass{thepass}"
2197
2148
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
2198
2149
 
2199
- # Step 1 - Correlation step
2200
- if optiondict["similaritymetric"] == "mutualinfo":
2201
- similaritytype = "Mutual information"
2202
- elif optiondict["similaritymetric"] == "correlation":
2203
- similaritytype = "Correlation"
2204
- else:
2205
- similaritytype = "MI enhanced correlation"
2206
- LGR.info(f"\n\n{similaritytype} calculation, pass {thepass}")
2207
- TimingLGR.info(f"{similaritytype} calculation start, pass {thepass}")
2208
- calcsimilaritypass_func = addmemprofiling(
2209
- tide_calcsimfunc.correlationpass,
2210
- optiondict["memprofile"],
2211
- "before correlationpass",
2150
+ # Step 1a - do the initial delay estimation
2151
+ similaritytype = tide_calcSimFuncMap.calcSimFunc(
2152
+ numvalidspatiallocs,
2153
+ fmri_data_valid,
2154
+ validsimcalcstart,
2155
+ validsimcalcend,
2156
+ osvalidsimcalcstart,
2157
+ osvalidsimcalcend,
2158
+ initial_fmri_x,
2159
+ os_fmri_x,
2160
+ theCorrelator,
2161
+ theMutualInformationator,
2162
+ cleaned_referencetc,
2163
+ corrout,
2164
+ riptideregressorset,
2165
+ riptidedelays,
2166
+ sLFOfitmean,
2167
+ r2value,
2168
+ fitcoeff,
2169
+ fitNorm,
2170
+ meanval,
2171
+ corrscale,
2172
+ outputname,
2173
+ outcorrarray,
2174
+ validvoxels,
2175
+ nativecorrshape,
2176
+ theinputdata,
2177
+ theheader,
2178
+ lagmininpts,
2179
+ lagmaxinpts,
2180
+ thepass,
2181
+ optiondict,
2182
+ LGR,
2183
+ TimingLGR,
2184
+ similaritymetric=optiondict["similaritymetric"],
2185
+ simcalcoffset=optiondict["simcalcoffset"],
2186
+ echocancel=optiondict["echocancel"],
2187
+ checkpoint=optiondict["checkpoint"],
2188
+ mklthreads=optiondict["mklthreads"],
2189
+ nprocs=optiondict["nprocs_calcsimilarity"],
2190
+ alwaysmultiproc=optiondict["alwaysmultiproc"],
2191
+ oversampfactor=optiondict["oversampfactor"],
2192
+ interptype=optiondict["interptype"],
2193
+ showprogressbar=optiondict["showprogressbar"],
2194
+ chunksize=optiondict["mp_chunksize"],
2195
+ rt_floattype=rt_floattype,
2196
+ threaddebug=optiondict["threaddebug"],
2197
+ debug=optiondict["debug"],
2212
2198
  )
2213
-
2214
- disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
2215
- if optiondict["similaritymetric"] == "mutualinfo":
2216
- theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
2217
- (
2218
- voxelsprocessed_cp,
2219
- theglobalmaxlist,
2220
- trimmedcorrscale,
2221
- ) = calcsimilaritypass_func(
2222
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2223
- cleaned_referencetc,
2224
- theMutualInformationator,
2225
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2226
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2227
- lagmininpts,
2228
- lagmaxinpts,
2229
- corrout,
2230
- meanval,
2231
- nprocs=optiondict["nprocs_calcsimilarity"],
2232
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2233
- oversampfactor=optiondict["oversampfactor"],
2234
- interptype=optiondict["interptype"],
2235
- showprogressbar=optiondict["showprogressbar"],
2236
- chunksize=optiondict["mp_chunksize"],
2237
- rt_floatset=rt_floatset,
2238
- rt_floattype=rt_floattype,
2239
- )
2199
+ if optiondict["similaritymetric"] == "riptide":
2200
+ optiondict["despeckle_passes"] = 0
2201
+ fitcorrscale = riptidedelays
2240
2202
  else:
2241
- (
2242
- voxelsprocessed_cp,
2243
- theglobalmaxlist,
2244
- trimmedcorrscale,
2245
- ) = calcsimilaritypass_func(
2246
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2247
- cleaned_referencetc,
2248
- theCorrelator,
2249
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2250
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2251
- lagmininpts,
2252
- lagmaxinpts,
2253
- corrout,
2254
- meanval,
2255
- nprocs=optiondict["nprocs_calcsimilarity"],
2256
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2257
- oversampfactor=optiondict["oversampfactor"],
2258
- interptype=optiondict["interptype"],
2259
- showprogressbar=optiondict["showprogressbar"],
2260
- chunksize=optiondict["mp_chunksize"],
2261
- rt_floatset=rt_floatset,
2262
- rt_floattype=rt_floattype,
2263
- )
2264
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2203
+ fitcorrscale = trimmedcorrscale
2265
2204
 
2266
- for i in range(len(theglobalmaxlist)):
2267
- theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
2268
- namesuffix = "_desc-globallag_hist"
2269
- tide_stats.makeandsavehistogram(
2270
- np.asarray(theglobalmaxlist),
2271
- len(corrscale),
2272
- 0,
2273
- outputname + namesuffix,
2274
- displaytitle="Histogram of lag times from global lag calculation",
2275
- therange=(corrscale[0], corrscale[-1]),
2276
- refine=False,
2277
- dictvarname="globallaghist_pass" + str(thepass),
2278
- append=(optiondict["echocancel"] or (thepass > 1)),
2279
- thedict=optiondict,
2280
- )
2281
-
2282
- if optiondict["checkpoint"]:
2283
- outcorrarray[:, :] = 0.0
2284
- outcorrarray[validvoxels, :] = corrout[:, :]
2285
- if optiondict["textio"]:
2286
- tide_io.writenpvecs(
2287
- outcorrarray.reshape(nativecorrshape),
2288
- f"{outputname}_corrout_prefit_pass" + str(thepass) + ".txt",
2289
- )
2290
- else:
2291
- savename = f"{outputname}_desc-corroutprefit_pass-" + str(thepass)
2292
- tide_io.savetonifti(outcorrarray.reshape(nativecorrshape), theheader, savename)
2293
-
2294
- TimingLGR.info(
2295
- f"{similaritytype} calculation end, pass {thepass}",
2296
- {
2297
- "message2": voxelsprocessed_cp,
2298
- "message3": "voxels",
2299
- },
2300
- )
2301
-
2302
- # Step 1b. Do a peak prefit
2303
- if optiondict["similaritymetric"] == "hybrid":
2304
- LGR.info(f"\n\nPeak prefit calculation, pass {thepass}")
2305
- TimingLGR.info(f"Peak prefit calculation start, pass {thepass}")
2306
- peakevalpass_func = addmemprofiling(
2307
- tide_peakeval.peakevalpass,
2308
- optiondict["memprofile"],
2309
- "before peakevalpass",
2310
- )
2311
-
2312
- disablemkl(optiondict["nprocs_peakeval"], debug=threaddebug)
2313
- voxelsprocessed_pe, thepeakdict = peakevalpass_func(
2314
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2315
- cleaned_referencetc,
2316
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2317
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2318
- theMutualInformationator,
2319
- trimmedcorrscale,
2320
- corrout,
2321
- nprocs=optiondict["nprocs_peakeval"],
2322
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2323
- bipolar=optiondict["bipolar"],
2324
- oversampfactor=optiondict["oversampfactor"],
2325
- interptype=optiondict["interptype"],
2326
- showprogressbar=optiondict["showprogressbar"],
2327
- chunksize=optiondict["mp_chunksize"],
2328
- rt_floatset=rt_floatset,
2205
+ if optiondict["saveintermediatemaps"]:
2206
+ theheader = theinputdata.copyheader(numtimepoints=1)
2207
+ bidspasssuffix = f"_intermediatedata-pass{thepass}"
2208
+ maplist = [
2209
+ (lagtimes, "maxtimecoarse", "map", "second", "Lag time in seconds"),
2210
+ (lagstrengths, "maxcorrcoarse", "map", None, "Maximum correlation strength"),
2211
+ ]
2212
+ tide_io.savemaplist(
2213
+ f"{outputname}{bidspasssuffix}",
2214
+ maplist,
2215
+ validvoxels,
2216
+ nativespaceshape,
2217
+ theheader,
2218
+ bidsbasedict,
2219
+ filetype=theinputdata.filetype,
2329
2220
  rt_floattype=rt_floattype,
2221
+ cifti_hdr=theinputdata.cifti_hdr,
2330
2222
  )
2331
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2332
-
2333
- TimingLGR.info(
2334
- f"Peak prefit end, pass {thepass}",
2335
- {
2336
- "message2": voxelsprocessed_pe,
2337
- "message3": "voxels",
2338
- },
2339
- )
2340
- mipeaks = lagtimes * 0.0
2341
- for i in range(numvalidspatiallocs):
2342
- if len(thepeakdict[str(i)]) > 0:
2343
- mipeaks[i] = thepeakdict[str(i)][0][0]
2344
- else:
2345
- thepeakdict = None
2346
2223
 
2347
- # Step 2 - similarity function fitting and time lag estimation
2348
- # write out the current version of the run options
2349
- optiondict["currentstage"] = f"presimfuncfit_pass{thepass}"
2350
- tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
2351
- LGR.info(f"\n\nTime lag estimation pass {thepass}")
2352
- TimingLGR.info(f"Time lag estimation start, pass {thepass}")
2353
- fitcorr_func = addmemprofiling(
2354
- tide_simfuncfit.fitcorr, optiondict["memprofile"], "before fitcorr"
2355
- )
2356
- thefitter.setfunctype(optiondict["similaritymetric"])
2357
- thefitter.setcorrtimeaxis(trimmedcorrscale)
2358
-
2359
- # use initial lags if this is a hybrid fit
2360
- if optiondict["similaritymetric"] == "hybrid" and thepeakdict is not None:
2361
- initlags = mipeaks
2362
- else:
2363
- initlags = None
2364
-
2365
- disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2366
- voxelsprocessed_fc = fitcorr_func(
2367
- trimmedcorrscale,
2368
- thefitter,
2224
+ # Step 2a - fit the delay function
2225
+ internaldespeckleincludemask = tide_fitSimFuncMap.fitSimFunc(
2226
+ fmri_data_valid,
2227
+ validsimcalcstart,
2228
+ validsimcalcend,
2229
+ osvalidsimcalcstart,
2230
+ osvalidsimcalcend,
2231
+ initial_fmri_x,
2232
+ os_fmri_x,
2233
+ theMutualInformationator,
2234
+ cleaned_referencetc,
2369
2235
  corrout,
2236
+ outputname,
2237
+ validvoxels,
2238
+ nativespaceshape,
2239
+ bidsbasedict,
2240
+ numspatiallocs,
2241
+ gaussout,
2242
+ theinitialdelay,
2243
+ windowout,
2244
+ R2,
2245
+ thesizes,
2246
+ internalspaceshape,
2247
+ numvalidspatiallocs,
2248
+ theinputdata,
2249
+ theheader,
2250
+ theFitter,
2370
2251
  fitmask,
2371
- failreason,
2372
2252
  lagtimes,
2373
2253
  lagstrengths,
2374
2254
  lagsigma,
2375
- gaussout,
2376
- windowout,
2377
- R2,
2378
- despeckling=False,
2379
- peakdict=thepeakdict,
2380
- nprocs=optiondict["nprocs_fitcorr"],
2381
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2382
- fixdelay=optiondict["fixdelay"],
2383
- showprogressbar=optiondict["showprogressbar"],
2384
- chunksize=optiondict["mp_chunksize"],
2385
- despeckle_thresh=optiondict["despeckle_thresh"],
2386
- initiallags=initlags,
2387
- rt_floatset=rt_floatset,
2388
- rt_floattype=rt_floattype,
2255
+ failreason,
2256
+ outmaparray,
2257
+ fitcorrscale,
2258
+ similaritytype,
2259
+ thepass,
2260
+ optiondict,
2261
+ LGR,
2262
+ TimingLGR,
2263
+ simplefit=(optiondict["similaritymetric"] == "riptide"),
2264
+ rt_floattype=np.float64,
2389
2265
  )
2390
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2391
2266
 
2392
- TimingLGR.info(
2393
- f"Time lag estimation end, pass {thepass}",
2394
- {
2395
- "message2": voxelsprocessed_fc,
2396
- "message3": "voxels",
2397
- },
2398
- )
2267
+ # Step 2b - refine delay (optional)
2268
+ if optiondict["refinedelayeachpass"]:
2269
+ if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
2270
+ # set gausssigma automatically
2271
+ optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
2399
2272
 
2400
- # Step 2b - Correlation time despeckle
2401
- if optiondict["despeckle_passes"] > 0:
2402
- LGR.info(f"\n\n{similaritytype} despeckling pass {thepass}")
2403
- LGR.info(f"\tUsing despeckle_thresh = {optiondict['despeckle_thresh']:.3f}")
2404
- TimingLGR.info(f"{similaritytype} despeckle start, pass {thepass}")
2405
-
2406
- # find lags that are very different from their neighbors, and refit starting at the median lag for the point
2407
- voxelsprocessed_fc_ds = 0
2408
- despecklingdone = False
2409
- for despecklepass in range(optiondict["despeckle_passes"]):
2410
- LGR.info(f"\n\n{similaritytype} despeckling subpass {despecklepass + 1}")
2411
- outmaparray *= 0.0
2412
- outmaparray[validvoxels] = eval("lagtimes")[:]
2413
- medianlags = ndimage.median_filter(
2414
- outmaparray.reshape(nativespaceshape), 3
2415
- ).reshape(numspatiallocs)
2416
- # voxels that we're happy with have initlags set to -1000000.0
2417
- initlags = np.where(
2418
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2419
- medianlags,
2420
- -1000000.0,
2421
- )[validvoxels]
2422
- if len(initlags) > 0:
2423
- if len(np.where(initlags != -1000000.0)[0]) > 0:
2424
- disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2425
- voxelsprocessed_thispass = fitcorr_func(
2426
- trimmedcorrscale,
2427
- thefitter,
2428
- corrout,
2429
- fitmask,
2430
- failreason,
2431
- lagtimes,
2432
- lagstrengths,
2433
- lagsigma,
2434
- gaussout,
2435
- windowout,
2436
- R2,
2437
- despeckling=True,
2438
- peakdict=thepeakdict,
2439
- nprocs=optiondict["nprocs_fitcorr"],
2440
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2441
- fixdelay=optiondict["fixdelay"],
2442
- showprogressbar=optiondict["showprogressbar"],
2443
- chunksize=optiondict["mp_chunksize"],
2444
- despeckle_thresh=optiondict["despeckle_thresh"],
2445
- initiallags=initlags,
2446
- rt_floatset=rt_floatset,
2447
- rt_floattype=rt_floattype,
2448
- )
2449
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2450
-
2451
- voxelsprocessed_fc_ds += voxelsprocessed_thispass
2452
- optiondict[
2453
- "despecklemasksize_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2454
- ] = voxelsprocessed_thispass
2455
- optiondict[
2456
- "despecklemaskpct_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2457
- ] = (100.0 * voxelsprocessed_thispass / optiondict["corrmasksize"])
2458
- else:
2459
- despecklingdone = True
2460
- else:
2461
- despecklingdone = True
2462
- if despecklingdone:
2463
- LGR.info("Nothing left to do! Terminating despeckling")
2464
- break
2465
-
2466
- internaldespeckleincludemask = np.where(
2467
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2468
- medianlags,
2469
- 0.0,
2273
+ if optiondict["sLFOfiltmask"]:
2274
+ sLFOfiltmask = fitmask + 0.0
2275
+ else:
2276
+ sLFOfiltmask = np.ones_like(fitmask)
2277
+
2278
+ optiondict["regressfiltthreshval"] = 0.0
2279
+
2280
+ (
2281
+ delayoffset,
2282
+ regressderivratios,
2283
+ medfiltregressderivratios,
2284
+ filteredregressderivratios,
2285
+ optiondict["delayoffsetMAD"],
2286
+ ) = tide_refineDelayMap.refineDelay(
2287
+ fmri_data_valid,
2288
+ initial_fmri_x,
2289
+ xdim,
2290
+ ydim,
2291
+ slicethickness,
2292
+ sLFOfiltmask,
2293
+ genlagtc,
2294
+ oversamptr,
2295
+ sLFOfitmean,
2296
+ rvalue,
2297
+ r2value,
2298
+ fitNorm,
2299
+ fitcoeff,
2300
+ lagtc,
2301
+ outputname,
2302
+ validvoxels,
2303
+ nativespaceshape,
2304
+ theinputdata,
2305
+ lagtimes,
2306
+ optiondict,
2307
+ LGR,
2308
+ TimingLGR,
2309
+ outputlevel=optiondict["outputlevel"],
2310
+ gausssigma=optiondict["delayoffsetgausssigma"],
2311
+ patchthresh=optiondict["delaypatchthresh"],
2312
+ mindelay=optiondict["mindelay"],
2313
+ maxdelay=optiondict["maxdelay"],
2314
+ numpoints=optiondict["numpoints"],
2315
+ histlen=optiondict["histlen"],
2316
+ rt_floattype=rt_floattype,
2317
+ debug=optiondict["debug"],
2470
2318
  )
2471
- if optiondict["savedespecklemasks"] and (optiondict["despeckle_passes"] > 0):
2472
- despecklesavemask = np.where(
2473
- internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2319
+ lagtimes[:] = lagtimes + delayoffset
2320
+
2321
+ if optiondict["saveintermediatemaps"]:
2322
+ theheader = theinputdata.copyheader(numtimepoints=1)
2323
+ bidspasssuffix = f"_intermediatedata-pass{thepass}"
2324
+ maplist = [
2325
+ (lagtimes, "maxtimerefined", "map", "second", "Lag time in seconds"),
2326
+ (lagstrengths, "maxcorrrefined", "map", None, "Maximum correlation strength"),
2327
+ ]
2328
+ tide_io.savemaplist(
2329
+ f"{outputname}{bidspasssuffix}",
2330
+ maplist,
2331
+ validvoxels,
2332
+ nativespaceshape,
2333
+ theheader,
2334
+ bidsbasedict,
2335
+ filetype=theinputdata.filetype,
2336
+ rt_floattype=rt_floattype,
2337
+ cifti_hdr=theinputdata.cifti_hdr,
2474
2338
  )
2475
- if thepass == optiondict["passes"]:
2476
- if not optiondict["textio"]:
2477
- if fileiscifti:
2478
- timeindex = theheader["dim"][0] - 1
2479
- spaceindex = theheader["dim"][0]
2480
- theheader["dim"][timeindex] = 1
2481
- theheader["dim"][spaceindex] = numspatiallocs
2482
- else:
2483
- theheader["dim"][0] = 3
2484
- theheader["dim"][4] = 1
2485
- theheader["pixdim"][4] = 1.0
2486
- masklist = [
2487
- (
2488
- despecklesavemask,
2489
- "despeckle",
2490
- "mask",
2491
- None,
2492
- "Voxels that underwent despeckling in the final pass",
2493
- )
2494
- ]
2495
- tide_io.savemaplist(
2496
- outputname,
2497
- masklist,
2498
- validvoxels,
2499
- nativespaceshape,
2500
- theheader,
2501
- bidsbasedict,
2502
- textio=optiondict["textio"],
2503
- fileiscifti=fileiscifti,
2504
- rt_floattype=rt_floattype,
2505
- cifti_hdr=cifti_hdr,
2506
- )
2507
- LGR.info(
2508
- f"\n\n{voxelsprocessed_fc_ds} voxels despeckled in "
2509
- f"{optiondict['despeckle_passes']} passes"
2510
- )
2511
- TimingLGR.info(
2512
- f"{similaritytype} despeckle end, pass {thepass}",
2513
- {
2514
- "message2": voxelsprocessed_fc_ds,
2515
- "message3": "voxels",
2516
- },
2517
- )
2339
+
2518
2340
  # Step 2c - make a rank order map
2519
2341
  timepercentile = (
2520
2342
  100.0 * (rankdata(lagtimes, method="dense") - 1) / (numvalidspatiallocs - 1)
2521
2343
  )
2522
2344
 
2523
2345
  if optiondict["saveintermediatemaps"]:
2524
- if not optiondict["textio"]:
2525
- theheader = copy.deepcopy(nim_hdr)
2526
- if fileiscifti:
2527
- timeindex = theheader["dim"][0] - 1
2528
- spaceindex = theheader["dim"][0]
2529
- theheader["dim"][timeindex] = 1
2530
- theheader["dim"][spaceindex] = numspatiallocs
2531
- else:
2532
- theheader["dim"][0] = 3
2533
- theheader["dim"][4] = 1
2534
- theheader["pixdim"][4] = 1.0
2346
+ theheader = theinputdata.copyheader(numtimepoints=1)
2535
2347
  bidspasssuffix = f"_intermediatedata-pass{thepass}"
2536
2348
  maplist = [
2537
2349
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
@@ -2552,10 +2364,9 @@ def rapidtide_main(argparsingfunc):
2552
2364
  nativespaceshape,
2553
2365
  theheader,
2554
2366
  bidsbasedict,
2555
- textio=optiondict["textio"],
2556
- fileiscifti=fileiscifti,
2367
+ filetype=theinputdata.filetype,
2557
2368
  rt_floattype=rt_floattype,
2558
- cifti_hdr=cifti_hdr,
2369
+ cifti_hdr=theinputdata.cifti_hdr,
2559
2370
  )
2560
2371
 
2561
2372
  # Step 3 - regressor refinement for next pass
@@ -2565,376 +2376,67 @@ def rapidtide_main(argparsingfunc):
2565
2376
  if (
2566
2377
  thepass < optiondict["passes"]
2567
2378
  or optiondict["convergencethresh"] is not None
2568
- or optiondict["globalpreselect"]
2379
+ or optiondict["initregressorpreselect"]
2380
+ or optiondict["dofinalrefine"]
2569
2381
  ):
2570
- LGR.info(f"\n\nRegressor refinement, pass {thepass}")
2571
- TimingLGR.info(f"Regressor refinement start, pass {thepass}")
2572
- if optiondict["refineoffset"]:
2573
- # check that we won't end up excluding all voxels from offset calculation before accepting mask
2574
- offsetmask = np.uint16(fitmask)
2575
- if internaloffsetincludemask_valid is not None:
2576
- offsetmask[np.where(internaloffsetincludemask_valid == 0)] = 0
2577
- if internaloffsetexcludemask_valid is not None:
2578
- offsetmask[np.where(internaloffsetexcludemask_valid != 0.0)] = 0
2579
- if tide_stats.getmasksize(offsetmask) == 0:
2580
- LGR.warning(
2581
- "NB: cannot exclude voxels from offset calculation mask - including for this pass"
2582
- )
2583
- offsetmask = fitmask
2584
-
2585
- peaklag, peakheight, peakwidth = tide_stats.gethistprops(
2586
- lagtimes[np.where(offsetmask > 0)],
2587
- optiondict["histlen"],
2588
- pickleft=optiondict["pickleft"],
2589
- peakthresh=optiondict["pickleftthresh"],
2590
- )
2591
- optiondict["offsettime"] = peaklag
2592
- optiondict["offsettime_total"] += peaklag
2593
- optiondict[f"offsettime_pass{thepass}"] = optiondict["offsettime"]
2594
- optiondict[f"offsettime_total_pass{thepass}"] = optiondict["offsettime_total"]
2595
- LGR.info(
2596
- f"offset time set to {optiondict['offsettime']:.3f}, "
2597
- f"total is {optiondict['offsettime_total']:.3f}"
2598
- )
2599
-
2600
- if optiondict["refinedespeckled"] or (optiondict["despeckle_passes"] == 0):
2601
- # if refinedespeckled is true, or there is no despeckling, masks are unaffected
2602
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2603
- else:
2604
- # if refinedespeckled is false and there is despeckling, need to make a proper mask
2605
- if internalrefineexcludemask_valid is None:
2606
- # if there is currently no exclude mask, set exclude mask = despeckle mask
2607
- thisinternalrefineexcludemask_valid = np.where(
2608
- internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2609
- )
2610
- else:
2611
- # if there is a current exclude mask, add any voxels that are being despeckled
2612
- thisinternalrefineexcludemask_valid = np.where(
2613
- internalrefineexcludemask_valid > 0, 1, 0
2614
- )
2615
- thisinternalrefineexcludemask_valid[
2616
- np.where(internaldespeckleincludemask[validvoxels] != 0.0)
2617
- ] = 1
2618
-
2619
- # now check that we won't end up excluding all voxels from refinement before accepting mask
2620
- overallmask = np.uint16(fitmask)
2621
- if internalrefineincludemask_valid is not None:
2622
- overallmask[np.where(internalrefineincludemask_valid == 0)] = 0
2623
- if thisinternalrefineexcludemask_valid is not None:
2624
- overallmask[np.where(thisinternalrefineexcludemask_valid != 0.0)] = 0
2625
- if tide_stats.getmasksize(overallmask) == 0:
2626
- LGR.warning(
2627
- "NB: cannot exclude despeckled voxels from refinement - including for this pass"
2628
- )
2629
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2630
-
2631
- # regenerate regressor for next pass
2632
- # create the refinement mask
2633
- LGR.info("making refine mask")
2634
- (
2635
- voxelsprocessed_rrm,
2636
- refinemask,
2637
- locationfails,
2638
- ampfails,
2639
- lagfails,
2640
- sigmafails,
2641
- numinmask,
2642
- ) = tide_refine.makerefinemask(
2643
- lagstrengths,
2644
- lagtimes,
2645
- lagsigma,
2646
- fitmask,
2647
- offsettime=optiondict["offsettime"],
2648
- ampthresh=optiondict["ampthresh"],
2649
- lagmaskside=optiondict["lagmaskside"],
2650
- lagminthresh=optiondict["lagminthresh"],
2651
- lagmaxthresh=optiondict["lagmaxthresh"],
2652
- sigmathresh=optiondict["sigmathresh"],
2653
- cleanrefined=optiondict["cleanrefined"],
2654
- bipolar=optiondict["bipolar"],
2655
- includemask=internalrefineincludemask_valid,
2656
- excludemask=thisinternalrefineexcludemask_valid,
2657
- )
2658
-
2659
- if numinmask == 0:
2660
- LGR.critical("No voxels in refine mask - adjust thresholds or external masks")
2661
- sys.exit()
2662
-
2663
- # align timecourses to prepare for refinement
2664
- alignvoxels_func = addmemprofiling(
2665
- tide_refine.alignvoxels,
2666
- optiondict["memprofile"],
2667
- "before aligning voxel timecourses",
2668
- )
2669
- LGR.info("aligning timecourses")
2670
- disablemkl(optiondict["nprocs_refine"], debug=threaddebug)
2671
- voxelsprocessed_rra = alignvoxels_func(
2672
- fmri_data_valid,
2673
- fmritr,
2674
- shiftedtcs,
2675
- weights,
2676
- paddedshiftedtcs,
2677
- paddedweights,
2678
- lagtimes,
2679
- refinemask,
2680
- nprocs=optiondict["nprocs_refine"],
2681
- detrendorder=optiondict["detrendorder"],
2682
- offsettime=optiondict["offsettime"],
2683
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2684
- showprogressbar=optiondict["showprogressbar"],
2685
- chunksize=optiondict["mp_chunksize"],
2686
- padtrs=numpadtrs,
2687
- rt_floatset=rt_floatset,
2688
- rt_floattype=rt_floattype,
2689
- )
2690
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2691
- LGR.info(f"align complete: {voxelsprocessed_rra=}")
2692
-
2693
- LGR.info("prenormalizing timecourses")
2694
- tide_refine.prenorm(
2695
- paddedshiftedtcs,
2696
- refinemask,
2697
- lagtimes,
2698
- optiondict["lagmaxthresh"],
2699
- lagstrengths,
2700
- R2,
2701
- optiondict["refineprenorm"],
2702
- optiondict["refineweighting"],
2703
- )
2704
-
2705
- (
2706
- voxelsprocessed_rr,
2707
- paddedoutputdata,
2708
- ) = tide_refine.dorefine(
2709
- paddedshiftedtcs,
2710
- refinemask,
2711
- weights,
2712
- theprefilter,
2713
- fmritr,
2714
- thepass,
2715
- lagstrengths,
2716
- lagtimes,
2717
- optiondict["refinetype"],
2718
- optiondict["fmrifreq"],
2719
- optiondict["outputname"],
2720
- detrendorder=optiondict["detrendorder"],
2721
- pcacomponents=optiondict["pcacomponents"],
2722
- dodispersioncalc=optiondict["dodispersioncalc"],
2723
- dispersioncalc_lower=optiondict["dispersioncalc_lower"],
2724
- dispersioncalc_upper=optiondict["dispersioncalc_upper"],
2725
- dispersioncalc_step=optiondict["dispersioncalc_step"],
2726
- windowfunc=optiondict["windowfunc"],
2727
- cleanrefined=optiondict["cleanrefined"],
2728
- bipolar=optiondict["bipolar"],
2729
- debug=optiondict["debug"],
2730
- rt_floatset=rt_floatset,
2731
- rt_floattype=rt_floattype,
2732
- )
2733
- optiondict["refinemasksize_pass" + str(thepass)] = voxelsprocessed_rr
2734
- optiondict["refinemaskpct_pass" + str(thepass)] = (
2735
- 100.0 * voxelsprocessed_rr / optiondict["corrmasksize"]
2736
- )
2737
- optiondict["refinelocationfails_pass" + str(thepass)] = locationfails
2738
- optiondict["refineampfails_pass" + str(thepass)] = ampfails
2739
- optiondict["refinelagfails_pass" + str(thepass)] = lagfails
2740
- optiondict["refinesigmafails_pass" + str(thepass)] = sigmafails
2741
- if voxelsprocessed_rr > 0:
2742
- paddednormoutputdata = tide_math.stdnormalize(
2743
- theprefilter.apply(fmrifreq, paddedoutputdata)
2744
- )
2745
- outputdata = paddedoutputdata[numpadtrs:-numpadtrs]
2746
- normoutputdata = tide_math.stdnormalize(theprefilter.apply(fmrifreq, outputdata))
2747
- normunfilteredoutputdata = tide_math.stdnormalize(outputdata)
2748
- tide_io.writebidstsv(
2749
- f"{outputname}_desc-refinedmovingregressor_timeseries",
2750
- normunfilteredoutputdata,
2751
- 1.0 / fmritr,
2752
- columns=["unfiltered_pass" + str(thepass)],
2753
- extraheaderinfo={
2754
- "Description": "The raw and filtered probe regressor produced by the refinement procedure, at the time resolution of the data"
2755
- },
2756
- append=(thepass > 1),
2757
- )
2758
- tide_io.writebidstsv(
2759
- f"{outputname}_desc-refinedmovingregressor_timeseries",
2760
- normoutputdata,
2761
- 1.0 / fmritr,
2762
- columns=["filtered_pass" + str(thepass)],
2763
- extraheaderinfo={
2764
- "Description": "The raw and filtered probe regressor produced by the refinement procedure, at the time resolution of the data"
2765
- },
2766
- append=True,
2767
- )
2768
-
2769
- # check for convergence
2770
- regressormse = mse(normoutputdata, previousnormoutputdata)
2771
- optiondict["regressormse_pass" + str(thepass).zfill(2)] = regressormse
2772
- LGR.info(f"regressor difference at end of pass {thepass:d} is {regressormse:.6f}")
2773
- if optiondict["convergencethresh"] is not None:
2774
- if thepass >= optiondict["maxpasses"]:
2775
- LGR.info("refinement ended (maxpasses reached)")
2776
- stoprefining = True
2777
- refinestopreason = "maxpassesreached"
2778
- elif regressormse < optiondict["convergencethresh"]:
2779
- LGR.info("refinement ended (refinement has converged")
2780
- stoprefining = True
2781
- refinestopreason = "convergence"
2782
- else:
2783
- stoprefining = False
2784
- elif thepass >= optiondict["passes"]:
2785
- stoprefining = True
2786
- refinestopreason = "passesreached"
2787
- else:
2788
- stoprefining = False
2789
-
2790
- if optiondict["detrendorder"] > 0:
2791
- resampnonosref_y = tide_fit.detrend(
2792
- tide_resample.doresample(
2793
- paddedinitial_fmri_x,
2794
- paddednormoutputdata,
2795
- initial_fmri_x,
2796
- method=optiondict["interptype"],
2797
- ),
2798
- order=optiondict["detrendorder"],
2799
- demean=optiondict["dodemean"],
2800
- )
2801
- resampref_y = tide_fit.detrend(
2802
- tide_resample.doresample(
2803
- paddedinitial_fmri_x,
2804
- paddednormoutputdata,
2805
- os_fmri_x,
2806
- method=optiondict["interptype"],
2807
- ),
2808
- order=optiondict["detrendorder"],
2809
- demean=optiondict["dodemean"],
2810
- )
2811
- else:
2812
- resampnonosref_y = tide_resample.doresample(
2813
- paddedinitial_fmri_x,
2814
- paddednormoutputdata,
2815
- initial_fmri_x,
2816
- method=optiondict["interptype"],
2817
- )
2818
- resampref_y = tide_resample.doresample(
2819
- paddedinitial_fmri_x,
2820
- paddednormoutputdata,
2821
- os_fmri_x,
2822
- method=optiondict["interptype"],
2823
- )
2824
- if optiondict["tmaskname"] is not None:
2825
- resampnonosref_y *= tmask_y
2826
- thefit, R = tide_fit.mlregress(tmask_y, resampnonosref_y)
2827
- resampnonosref_y -= thefit[0, 1] * tmask_y
2828
- resampref_y *= tmaskos_y
2829
- thefit, R = tide_fit.mlregress(tmaskos_y, resampref_y)
2830
- resampref_y -= thefit[0, 1] * tmaskos_y
2831
-
2832
- # reinitialize genlagtc for resampling
2833
- previousnormoutputdata = normoutputdata + 0.0
2834
- genlagtc = tide_resample.FastResampler(
2835
- paddedinitial_fmri_x, paddednormoutputdata, padtime=padtime
2836
- )
2837
- genlagtc.save(f"{outputname}_desc-lagtcgenerator_timeseries")
2838
- (
2839
- optiondict[f"kurtosis_reference_pass{thepass + 1}"],
2840
- optiondict[f"kurtosisz_reference_pass{thepass + 1}"],
2841
- optiondict[f"kurtosisp_reference_pass{thepass + 1}"],
2842
- ) = tide_stats.kurtosisstats(resampref_y)
2843
- (
2844
- optiondict[f"skewness_reference_pass{thepass + 1}"],
2845
- optiondict[f"skewnessz_reference_pass{thepass + 1}"],
2846
- optiondict[f"skewnessp_reference_pass{thepass + 1}"],
2847
- ) = tide_stats.skewnessstats(resampref_y)
2848
- if not stoprefining:
2849
- tide_io.writebidstsv(
2850
- f"{outputname}_desc-movingregressor_timeseries",
2851
- tide_math.stdnormalize(resampnonosref_y),
2852
- 1.0 / fmritr,
2853
- columns=["pass" + str(thepass + 1)],
2854
- extraheaderinfo={
2855
- "Description": "The probe regressor used in each pass, at the time resolution of the data"
2856
- },
2857
- append=True,
2858
- )
2859
- tide_io.writebidstsv(
2860
- f"{outputname}_desc-oversampledmovingregressor_timeseries",
2861
- tide_math.stdnormalize(resampref_y),
2862
- oversampfreq,
2863
- columns=["pass" + str(thepass + 1)],
2864
- extraheaderinfo={
2865
- "Description": "The probe regressor used in each pass, at the time resolution used for calculating the similarity function"
2866
- },
2867
- append=True,
2868
- )
2869
- else:
2870
- LGR.warning(f"refinement failed - terminating at end of pass {thepass}")
2871
- stoprefining = True
2872
- refinestopreason = "emptymask"
2873
-
2874
- TimingLGR.info(
2875
- f"Regressor refinement end, pass {thepass}",
2876
- {
2877
- "message2": voxelsprocessed_rr,
2878
- "message3": "voxels",
2879
- },
2880
- )
2881
- if optiondict["saveintermediatemaps"]:
2882
- if not optiondict["textio"]:
2883
- theheader = copy.deepcopy(nim_hdr)
2884
- if fileiscifti:
2885
- timeindex = theheader["dim"][0] - 1
2886
- spaceindex = theheader["dim"][0]
2887
- theheader["dim"][timeindex] = 1
2888
- theheader["dim"][spaceindex] = numspatiallocs
2889
- else:
2890
- theheader["dim"][0] = 3
2891
- theheader["dim"][4] = 1
2892
- theheader["pixdim"][4] = 1.0
2893
- bidspasssuffix = f"_intermediatedata-pass{thepass}"
2894
- maplist = [
2895
- (fitmask, "corrfit", "mask", None, "Voxels where correlation value was fit"),
2896
- (
2897
- failreason,
2898
- "corrfitfailreason",
2899
- "info",
2900
- None,
2901
- "Result codes for correlation fit",
2902
- ),
2903
- ]
2904
- if optiondict["savedespecklemasks"] and (optiondict["despeckle_passes"] > 0):
2905
- maplist.append(
2906
- (
2907
- despecklesavemask,
2908
- "despecklemask",
2909
- "map",
2910
- None,
2911
- "Voxels that underwent despeckling",
2912
- )
2913
- )
2914
- if thepass < optiondict["passes"]:
2915
- maplist.append(
2916
- (refinemask, "refinemask", "map", None, "Voxels used for regressor refinement")
2382
+ resampref_y, resampnonosref_y, stoprefining, refinestopreason, genlagtc = (
2383
+ tide_refineRegressor.refineRegressor(
2384
+ LGR,
2385
+ TimingLGR,
2386
+ thepass,
2387
+ optiondict,
2388
+ fitmask,
2389
+ internaloffsetincludemask_valid,
2390
+ internaloffsetexcludemask_valid,
2391
+ internalrefineincludemask_valid,
2392
+ internalrefineexcludemask_valid,
2393
+ internaldespeckleincludemask,
2394
+ validvoxels,
2395
+ theRegressorRefiner,
2396
+ lagtimes,
2397
+ lagstrengths,
2398
+ lagsigma,
2399
+ fmri_data_valid,
2400
+ fmritr,
2401
+ R2,
2402
+ theprefilter,
2403
+ previousnormoutputdata,
2404
+ theinputdata,
2405
+ numpadtrs,
2406
+ outputname,
2407
+ nativefmrishape,
2408
+ bidsbasedict,
2409
+ rt_floattype=np.float64,
2917
2410
  )
2918
- tide_io.savemaplist(
2919
- f"{outputname}{bidspasssuffix}",
2920
- maplist,
2921
- validvoxels,
2922
- nativespaceshape,
2923
- theheader,
2924
- bidsbasedict,
2925
- textio=optiondict["textio"],
2926
- fileiscifti=fileiscifti,
2927
- rt_floattype=rt_floattype,
2928
- cifti_hdr=cifti_hdr,
2929
2411
  )
2412
+ # End of main pass loop
2930
2413
 
2931
- # We are done with refinement.
2932
2414
  if optiondict["convergencethresh"] is None:
2933
2415
  optiondict["actual_passes"] = optiondict["passes"]
2934
2416
  else:
2935
2417
  optiondict["actual_passes"] = thepass - 1
2936
2418
  optiondict["refinestopreason"] = refinestopreason
2937
2419
 
2420
+ # calculate the sLFO growth
2421
+ (
2422
+ filtrms,
2423
+ filtrmslinfit,
2424
+ optiondict["sLFO_startamp"],
2425
+ optiondict["sLFO_endamp"],
2426
+ optiondict["sLFO_changepct"],
2427
+ optiondict["sLFO_changerate"],
2428
+ ) = tide_math.noiseamp(resampref_y, 1.0 / oversamptr, optiondict["sLFOnoiseampwindow"])
2429
+ tide_io.writebidstsv(
2430
+ f"{outputname}_desc-sLFOamplitude_timeseries",
2431
+ np.vstack((filtrms, filtrmslinfit)),
2432
+ oversampfreq,
2433
+ columns=["filteredRMS", "linearfit"],
2434
+ extraheaderinfo={
2435
+ "Description": "Filtered RMS amplitude of the probe regressor, and a linear fit"
2436
+ },
2437
+ append=False,
2438
+ )
2439
+
2938
2440
  # Post refinement step -1 - Coherence calculation
2939
2441
  if optiondict["calccoherence"]:
2940
2442
  TimingLGR.info("Coherence calculation start")
@@ -2958,42 +2460,47 @@ def rapidtide_main(argparsingfunc):
2958
2460
  coherencefreqstep,
2959
2461
  coherencefreqaxissize,
2960
2462
  ) = theCoherer.getaxisinfo()
2961
- if optiondict["textio"]:
2463
+ if theinputdata.filetype == "text":
2962
2464
  nativecoherenceshape = (xsize, coherencefreqaxissize)
2963
2465
  else:
2964
- if fileiscifti:
2466
+ if theinputdata.filetype == "cifti":
2965
2467
  nativecoherenceshape = (1, 1, 1, coherencefreqaxissize, numspatiallocs)
2966
2468
  else:
2967
2469
  nativecoherenceshape = (xsize, ysize, numslices, coherencefreqaxissize)
2968
2470
 
2969
2471
  internalvalidcoherenceshape = (numvalidspatiallocs, coherencefreqaxissize)
2970
- internalcoherenceshape = (numspatiallocs, coherencefreqaxissize)
2971
2472
 
2972
2473
  # now allocate the arrays needed for the coherence calculation
2474
+ coherencefunc, coherencefunc_shm = tide_util.allocarray(
2475
+ internalvalidcoherenceshape,
2476
+ rt_outfloattype,
2477
+ shared=optiondict["sharedmem"],
2478
+ name=f"coherencefunc_{optiondict['pid']}",
2479
+ )
2480
+ coherencepeakval, coherencepeakval_shm = tide_util.allocarray(
2481
+ numvalidspatiallocs,
2482
+ rt_outfloattype,
2483
+ shared=optiondict["sharedmem"],
2484
+ name=f"coherencepeakval_{optiondict['pid']}",
2485
+ )
2486
+ coherencepeakfreq, coherencepeakfreq_shm = tide_util.allocarray(
2487
+ numvalidspatiallocs,
2488
+ rt_outfloattype,
2489
+ shared=optiondict["sharedmem"],
2490
+ name=f"coherencepeakfreq_{optiondict['pid']}",
2491
+ )
2973
2492
  if optiondict["sharedmem"]:
2974
- coherencefunc, dummy, dummy = tide_util.allocshared(
2975
- internalvalidcoherenceshape, rt_outfloatset
2976
- )
2977
- coherencepeakval, dummy, dummy = tide_util.allocshared(
2978
- numvalidspatiallocs, rt_outfloatset
2979
- )
2980
- coherencepeakfreq, dummy, dummy = tide_util.allocshared(
2981
- numvalidspatiallocs, rt_outfloatset
2982
- )
2493
+ ramlocation = "in shared memory"
2983
2494
  else:
2984
- coherencefunc = np.zeros(internalvalidcoherenceshape, dtype=rt_outfloattype)
2985
- coherencepeakval, dummy, dummy = tide_util.allocshared(
2986
- numvalidspatiallocs, rt_outfloatset
2987
- )
2988
- coherencepeakfreq = np.zeros(numvalidspatiallocs, dtype=rt_outfloattype)
2989
-
2990
- coherencepass_func = addmemprofiling(
2991
- tide_calccoherence.coherencepass,
2992
- optiondict["memprofile"],
2993
- "before coherencepass",
2495
+ ramlocation = "locally"
2496
+ optiondict["totalcoherencebytes"] = (
2497
+ coherencefunc.nbytes + coherencepeakval.nbytes + coherencepeakfreq.nbytes
2994
2498
  )
2995
- disablemkl(1, debug=threaddebug)
2996
- voxelsprocessed_coherence = coherencepass_func(
2499
+ thesize, theunit = tide_util.format_bytes(optiondict["totalcoherencebytes"])
2500
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for coherence calculation")
2501
+
2502
+ tide_util.disablemkl(1, debug=optiondict["threaddebug"])
2503
+ voxelsprocessed_coherence = tide_calccoherence.coherencepass(
2997
2504
  fmri_data_valid,
2998
2505
  theCoherer,
2999
2506
  coherencefunc,
@@ -3002,27 +2509,17 @@ def rapidtide_main(argparsingfunc):
3002
2509
  alt=True,
3003
2510
  showprogressbar=optiondict["showprogressbar"],
3004
2511
  chunksize=optiondict["mp_chunksize"],
3005
- nprocs=1,
2512
+ nprocs=optiondict["nprocs"],
3006
2513
  alwaysmultiproc=optiondict["alwaysmultiproc"],
3007
- rt_floatset=rt_floatset,
3008
- rt_floattype=rt_floattype,
3009
2514
  )
3010
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2515
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
3011
2516
 
3012
2517
  # save the results of the calculations
3013
- if not optiondict["textio"]:
3014
- theheader = copy.deepcopy(nim_hdr)
3015
- theheader["toffset"] = coherencefreqstart
3016
- theheader["pixdim"][4] = coherencefreqstep
3017
- if fileiscifti:
3018
- timeindex = theheader["dim"][0] - 1
3019
- spaceindex = theheader["dim"][0]
3020
- theheader["dim"][timeindex] = coherencefreqaxissize
3021
- theheader["dim"][spaceindex] = numspatiallocs
3022
- else:
3023
- theheader["dim"][0] = 3
3024
- theheader["dim"][4] = coherencefreqaxissize
3025
- theheader["pixdim"][4] = 1.0
2518
+ theheader = theinputdata.copyheader(
2519
+ numtimepoints=coherencefreqaxissize,
2520
+ tr=coherencefreqstep,
2521
+ toffset=coherencefreqstart,
2522
+ )
3026
2523
  maplist = [(coherencefunc, "coherence", "info", None, "Coherence function")]
3027
2524
  tide_io.savemaplist(
3028
2525
  outputname,
@@ -3031,12 +2528,10 @@ def rapidtide_main(argparsingfunc):
3031
2528
  nativecoherenceshape,
3032
2529
  theheader,
3033
2530
  bidsbasedict,
3034
- textio=optiondict["textio"],
3035
- fileiscifti=fileiscifti,
2531
+ filetype=theinputdata.filetype,
3036
2532
  rt_floattype=rt_floattype,
3037
- cifti_hdr=cifti_hdr,
2533
+ cifti_hdr=theinputdata.cifti_hdr,
3038
2534
  )
3039
- del coherencefunc
3040
2535
 
3041
2536
  TimingLGR.info(
3042
2537
  "Coherence calculation end",
@@ -3052,29 +2547,35 @@ def rapidtide_main(argparsingfunc):
3052
2547
  LGR.info("\n\nWiener deconvolution")
3053
2548
 
3054
2549
  # now allocate the arrays needed for Wiener deconvolution
2550
+ wienerdeconv, wienerdeconv_shm = tide_util.allocarray(
2551
+ internalvalidspaceshape,
2552
+ rt_outfloattype,
2553
+ shared=optiondict["sharedmem"],
2554
+ name=f"wienerdeconv_{optiondict['pid']}",
2555
+ )
2556
+ wpeak, wpeak_shm = tide_util.allocarray(
2557
+ internalvalidspaceshape,
2558
+ rt_outfloattype,
2559
+ shared=optiondict["sharedmem"],
2560
+ name=f"wpeak_{optiondict['pid']}",
2561
+ )
3055
2562
  if optiondict["sharedmem"]:
3056
- wienerdeconv, dummy, dummy = tide_util.allocshared(
3057
- internalvalidspaceshape, rt_outfloatset
3058
- )
3059
- wpeak, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
2563
+ ramlocation = "in shared memory"
3060
2564
  else:
3061
- wienerdeconv = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3062
- wpeak = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2565
+ ramlocation = "locally"
2566
+ optiondict["totalwienerbytes"] = wienerdeconv.nbytes + wpeak.nbytes
2567
+ thesize, theunit = tide_util.format_bytes(optiondict["totalwienerbytes"])
2568
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for wiener deconvolution")
3063
2569
 
3064
- wienerpass_func = addmemprofiling(
3065
- tide_wiener.wienerpass,
3066
- optiondict["memprofile"],
3067
- "before wienerpass",
3068
- )
3069
- voxelsprocessed_wiener = wienerpass_func(
2570
+ voxelsprocessed_wiener = tide_wiener.wienerpass(
3070
2571
  numspatiallocs,
3071
2572
  fmri_data_valid,
3072
2573
  threshval,
2574
+ lagtc,
3073
2575
  optiondict,
3074
2576
  wienerdeconv,
3075
2577
  wpeak,
3076
2578
  resampref_y,
3077
- rt_floatset=rt_floatset,
3078
2579
  rt_floattype=rt_floattype,
3079
2580
  )
3080
2581
  TimingLGR.info(
@@ -3084,56 +2585,60 @@ def rapidtide_main(argparsingfunc):
3084
2585
  "message3": "voxels",
3085
2586
  },
3086
2587
  )
2588
+ del wienerdeconv
2589
+ del wpeak
2590
+ if optiondict["sharedmem"]:
2591
+ tide_util.cleanup_shm(wienerdeconv_shm)
2592
+ tide_util.cleanup_shm(wpeak_shm)
3087
2593
 
3088
2594
  ####################################################
3089
- # GLM filtering start
2595
+ # Linear regression filtering start
3090
2596
  ####################################################
3091
- # Post refinement step 1 - GLM fitting, either to remove moving signal, or to calculate delayed CVR
2597
+ # Post refinement step 1 - regression fitting, either to remove moving signal, or to calculate delayed CVR
3092
2598
  # write out the current version of the run options
3093
- optiondict["currentstage"] = "preglm"
2599
+ optiondict["currentstage"] = "presLFOfit"
3094
2600
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
3095
- if optiondict["doglmfilt"] or optiondict["docvrmap"]:
3096
- if optiondict["doglmfilt"]:
3097
- TimingLGR.info("GLM filtering start")
3098
- LGR.info("\n\nGLM filtering")
2601
+ if optiondict["dolinfitfilt"] or optiondict["docvrmap"] or optiondict["refinedelay"]:
2602
+ if optiondict["sLFOfiltmask"]:
2603
+ sLFOfiltmask = fitmask + 0.0
2604
+ else:
2605
+ sLFOfiltmask = np.ones_like(fitmask)
2606
+ if optiondict["dolinfitfilt"]:
2607
+ if optiondict["refinedelay"]:
2608
+ TimingLGR.info("Setting up for delay refinement and sLFO filtering")
2609
+ LGR.info("\n\nDelay refinement and sLFO filtering setup")
2610
+ else:
2611
+ TimingLGR.info("Setting up for sLFO filtering")
2612
+ LGR.info("\n\nsLFO filtering setup")
2613
+ elif optiondict["docvrmap"]:
2614
+ if optiondict["refinedelay"]:
2615
+ TimingLGR.info("Setting up for delay refinement and CVR map generation")
2616
+ LGR.info("\n\nDelay refinement and CVR mapping setup")
2617
+ else:
2618
+ TimingLGR.info("Setting up for CVR map generation")
2619
+ LGR.info("\n\nCVR mapping setup")
3099
2620
  else:
3100
- TimingLGR.info("CVR map generation start")
3101
- LGR.info("\n\nCVR mapping")
2621
+ TimingLGR.info("Setting up for delay refinement")
2622
+ LGR.info("\n\nDelay refinement setup")
3102
2623
  if (
3103
2624
  (optiondict["gausssigma"] > 0.0)
3104
- or (optiondict["glmsourcefile"] is not None)
2625
+ or (optiondict["denoisesourcefile"] is not None)
3105
2626
  or optiondict["docvrmap"]
3106
2627
  ):
3107
- if optiondict["glmsourcefile"] is not None:
3108
- LGR.info(f"reading in {optiondict['glmsourcefile']} for GLM filter, please wait")
3109
- sourcename = optiondict["glmsourcefile"]
3110
- else:
3111
- LGR.info(f"rereading {fmrifilename} for GLM filter, please wait")
3112
- sourcename = fmrifilename
3113
- if fileiscifti:
3114
- LGR.info("input file is CIFTI")
3115
- (
3116
- cifti,
3117
- cifti_hdr,
3118
- nim_data,
3119
- nim_hdr,
3120
- thedims,
3121
- thesizes,
3122
- dummy,
3123
- ) = tide_io.readfromcifti(sourcename)
3124
- else:
3125
- if optiondict["textio"]:
3126
- nim_data = tide_io.readvecs(sourcename)
3127
- else:
3128
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(sourcename)
2628
+ if optiondict["denoisesourcefile"] is not None:
2629
+ LGR.info(
2630
+ f"reading in {optiondict['denoisesourcefile']} for sLFO filter, please wait"
2631
+ )
2632
+ sourcename = optiondict["denoisesourcefile"]
2633
+ theinputdata = tide_voxelData.VoxelData(sourcename, timestep=optiondict["realtr"])
2634
+ theinputdata.setvalidtimes(validstart, validend)
2635
+ theinputdata.setvalidvoxels(validvoxels)
3129
2636
 
3130
- fmri_data_valid = (
3131
- nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1]
3132
- )[validvoxels, :] + 0.0
2637
+ fmri_data_valid = theinputdata.validdata() + 0.0
3133
2638
 
3134
2639
  if optiondict["docvrmap"]:
3135
2640
  # percent normalize the fmri data
3136
- LGR.info("normalzing data for CVR map")
2641
+ LGR.info("normalizing data for CVR map")
3137
2642
  themean = np.mean(fmri_data_valid, axis=1)
3138
2643
  fmri_data_valid /= themean[:, None]
3139
2644
 
@@ -3149,79 +2654,58 @@ def rapidtide_main(argparsingfunc):
3149
2654
 
3150
2655
  # move fmri_data_valid into shared memory
3151
2656
  if optiondict["sharedmem"]:
2657
+ tide_util.cleanup_shm(fmri_data_valid_shm)
3152
2658
  LGR.info("moving fmri data to shared memory")
3153
2659
  TimingLGR.info("Start moving fmri_data to shared memory")
3154
- numpy2shared_func = addmemprofiling(
3155
- tide_util.numpy2shared,
3156
- optiondict["memprofile"],
3157
- "before movetoshared (glm)",
2660
+ fmri_data_valid, fmri_data_valid_shm = tide_util.numpy2shared(
2661
+ fmri_data_valid,
2662
+ rt_floattype,
2663
+ name=f"fmri_data_valid_regressionfilt_{optiondict['pid']}",
3158
2664
  )
3159
- fmri_data_valid = numpy2shared_func(fmri_data_valid, rt_floatset)
3160
2665
  TimingLGR.info("End moving fmri_data to shared memory")
3161
- del nim_data
2666
+ theinputdata.unload()
3162
2667
 
3163
- # now allocate the arrays needed for GLM filtering
3164
- internalvalidspaceshapederivs = (
3165
- internalvalidspaceshape,
3166
- optiondict["glmderivs"] + 1,
2668
+ # allocate the arrays needed for sLFO filtering
2669
+ movingsignal, movingsignal_shm = tide_util.allocarray(
2670
+ internalvalidfmrishape,
2671
+ rt_outfloattype,
2672
+ shared=optiondict["sharedmem"],
2673
+ name=f"movingsignal_{optiondict['pid']}",
2674
+ )
2675
+ filtereddata, filtereddata_shm = tide_util.allocarray(
2676
+ internalvalidfmrishape,
2677
+ rt_outfloattype,
2678
+ shared=optiondict["sharedmem"],
2679
+ name=f"filtereddata_{optiondict['pid']}",
3167
2680
  )
3168
2681
  if optiondict["sharedmem"]:
3169
- glmmean, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3170
- rvalue, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3171
- r2value, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3172
- fitNorm, dummy, dummy = tide_util.allocshared(
3173
- internalvalidspaceshapederivs, rt_outfloatset
3174
- )
3175
- fitcoeff, dummy, dummy = tide_util.allocshared(
3176
- internalvalidspaceshapederivs, rt_outfloatset
3177
- )
3178
- movingsignal, dummy, dummy = tide_util.allocshared(
3179
- internalvalidfmrishape, rt_outfloatset
3180
- )
3181
- lagtc, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
3182
- filtereddata, dummy, dummy = tide_util.allocshared(
3183
- internalvalidfmrishape, rt_outfloatset
3184
- )
3185
- else:
3186
- glmmean = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3187
- rvalue = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3188
- r2value = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3189
- fitNorm = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
3190
- fitcoeff = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
3191
- movingsignal = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
3192
- lagtc = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
3193
- filtereddata = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
3194
-
3195
- if optiondict["memprofile"]:
3196
- if optiondict["doglmfilt"]:
3197
- memcheckpoint("about to start glm noise removal...")
3198
- else:
3199
- memcheckpoint("about to start CVR magnitude estimation...")
2682
+ ramlocation = "in shared memory"
3200
2683
  else:
3201
- tide_util.logmem("before glm")
2684
+ ramlocation = "locally"
3202
2685
 
3203
- if optiondict["doglmfilt"]:
2686
+ optiondict["totalsLFOfilterbytes"] = movingsignal.nbytes + filtereddata.nbytes
2687
+ thesize, theunit = tide_util.format_bytes(optiondict["totalsLFOfilterbytes"])
2688
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for sLFO filter")
2689
+ tide_util.logmem("before sLFO filter")
2690
+
2691
+ if optiondict["dolinfitfilt"]:
3204
2692
  mode = "glm"
3205
- optiondict["glmthreshval"] = threshval
2693
+ optiondict["regressfiltthreshval"] = threshval
3206
2694
  else:
3207
2695
  # set the threshval to zero
3208
2696
  mode = "cvrmap"
3209
- optiondict["glmthreshval"] = 0.0
3210
- if optiondict["focaldebug"]:
3211
- # dump the fmri input file going to glm
3212
- if not optiondict["textio"]:
3213
- theheader = copy.deepcopy(nim_hdr)
3214
- if fileiscifti:
3215
- timeindex = theheader["dim"][0] - 1
3216
- spaceindex = theheader["dim"][0]
3217
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
3218
- theheader["dim"][spaceindex] = numspatiallocs
3219
- else:
3220
- theheader["dim"][4] = np.shape(outfmriarray)[1]
3221
- theheader["pixdim"][4] = fmritr
2697
+ optiondict["regressfiltthreshval"] = 0.0
2698
+
2699
+ if optiondict["debug"]:
2700
+ # dump the fmri input file going to sLFO filter
2701
+ if theinputdata.filetype != "text":
2702
+ outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
2703
+ theheader = theinputdata.copyheader(
2704
+ numtimepoints=np.shape(outfmriarray)[1], tr=fmritr
2705
+ )
3222
2706
  else:
3223
2707
  theheader = None
3224
- cifti_hdr = None
2708
+ outfmriarray = None
3225
2709
 
3226
2710
  maplist = [
3227
2711
  (
@@ -3229,7 +2713,7 @@ def rapidtide_main(argparsingfunc):
3229
2713
  "datatofilter",
3230
2714
  "bold",
3231
2715
  None,
3232
- "fMRI data that will be subjected to GLM filtering",
2716
+ "fMRI data that will be subjected to sLFO filtering",
3233
2717
  ),
3234
2718
  ]
3235
2719
  tide_io.savemaplist(
@@ -3239,77 +2723,278 @@ def rapidtide_main(argparsingfunc):
3239
2723
  nativefmrishape,
3240
2724
  theheader,
3241
2725
  bidsbasedict,
3242
- textio=optiondict["textio"],
3243
- fileiscifti=fileiscifti,
2726
+ filetype=theinputdata.filetype,
3244
2727
  rt_floattype=rt_floattype,
3245
- cifti_hdr=cifti_hdr,
2728
+ cifti_hdr=theinputdata.cifti_hdr,
3246
2729
  )
2730
+ else:
2731
+ outfmriarray = None
3247
2732
 
3248
- # calculate the initial bandlimited mean normalized variance if we're going to filter the data
3249
- initialvariance = tide_math.imagevariance(fmri_data_valid, theprefilter, 1.0 / fmritr)
2733
+ # refine the delay value prior to calculating the sLFO filter
2734
+ if optiondict["refinedelay"]:
2735
+ TimingLGR.info("Delay refinement start")
2736
+ LGR.info("\n\nDelay refinement")
3250
2737
 
3251
- voxelsprocessed_glm, regressorset = tide_glmfrommaps.glmfrommaps(
3252
- fmri_data_valid,
3253
- validvoxels,
3254
- initial_fmri_x,
3255
- lagtimes,
3256
- fitmask,
3257
- genlagtc,
3258
- mode,
3259
- outputname,
3260
- oversamptr,
3261
- glmmean,
3262
- rvalue,
3263
- r2value,
3264
- fitNorm,
3265
- fitcoeff,
3266
- movingsignal,
3267
- lagtc,
3268
- filtereddata,
3269
- LGR,
3270
- TimingLGR,
3271
- optiondict["glmthreshval"],
3272
- optiondict["saveminimumglmfiles"],
3273
- nprocs_makelaggedtcs=optiondict["nprocs_makelaggedtcs"],
3274
- nprocs_glm=optiondict["nprocs_glm"],
3275
- glmderivs=optiondict["glmderivs"],
3276
- mp_chunksize=optiondict["mp_chunksize"],
3277
- showprogressbar=optiondict["showprogressbar"],
3278
- alwaysmultiproc=optiondict["alwaysmultiproc"],
3279
- memprofile=optiondict["memprofile"],
3280
- debug=optiondict["focaldebug"],
3281
- )
2738
+ if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
2739
+ # set gausssigma automatically
2740
+ optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
3282
2741
 
3283
- # calculate the final bandlimited mean normalized variance
3284
- finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
3285
- divlocs = np.where(finalvariance > 0.0)
3286
- varchange = initialvariance * 0.0
3287
- varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
3288
- del fmri_data_valid
2742
+ (
2743
+ delayoffset,
2744
+ regressderivratios,
2745
+ medfiltregressderivratios,
2746
+ filteredregressderivratios,
2747
+ optiondict["delayoffsetMAD"],
2748
+ ) = tide_refineDelayMap.refineDelay(
2749
+ fmri_data_valid,
2750
+ initial_fmri_x,
2751
+ xdim,
2752
+ ydim,
2753
+ slicethickness,
2754
+ sLFOfiltmask,
2755
+ genlagtc,
2756
+ oversamptr,
2757
+ sLFOfitmean,
2758
+ rvalue,
2759
+ r2value,
2760
+ fitNorm,
2761
+ fitcoeff,
2762
+ lagtc,
2763
+ outputname,
2764
+ validvoxels,
2765
+ nativespaceshape,
2766
+ theinputdata,
2767
+ lagtimes,
2768
+ optiondict,
2769
+ LGR,
2770
+ TimingLGR,
2771
+ outputlevel=optiondict["outputlevel"],
2772
+ gausssigma=optiondict["delayoffsetgausssigma"],
2773
+ patchthresh=optiondict["delaypatchthresh"],
2774
+ mindelay=optiondict["mindelay"],
2775
+ maxdelay=optiondict["maxdelay"],
2776
+ numpoints=optiondict["numpoints"],
2777
+ histlen=optiondict["histlen"],
2778
+ rt_floattype=rt_floattype,
2779
+ debug=optiondict["debug"],
2780
+ )
2781
+ lagtimesrefined = lagtimes + delayoffset
3289
2782
 
3290
- LGR.info("End filtering operation")
3291
- TimingLGR.info(
3292
- "GLM filtering end",
3293
- {
3294
- "message2": voxelsprocessed_glm,
3295
- "message3": "voxels",
3296
- },
3297
- )
3298
- if optiondict["memprofile"]:
3299
- memcheckpoint("...done")
3300
- else:
3301
- tide_util.logmem("after glm filter")
3302
- LGR.info("")
2783
+ if optiondict["windowedrefinemasks"] is not None:
2784
+ windoweddelayoffsets = []
2785
+ for thetimemask in optiondict["windowedrefinemasks"]:
2786
+ (
2787
+ windoweddelayoffset,
2788
+ dummy,
2789
+ dummy,
2790
+ dummy,
2791
+ dummy,
2792
+ ) = tide_refineDelayMap.refineDelay(
2793
+ fmri_data_valid,
2794
+ initial_fmri_x,
2795
+ xdim,
2796
+ ydim,
2797
+ slicethickness,
2798
+ sLFOfiltmask,
2799
+ genlagtc,
2800
+ oversamptr,
2801
+ sLFOfitmean,
2802
+ rvalue,
2803
+ r2value,
2804
+ fitNorm,
2805
+ fitcoeff,
2806
+ lagtc,
2807
+ outputname,
2808
+ validvoxels,
2809
+ nativespaceshape,
2810
+ theinputdata,
2811
+ lagtimes,
2812
+ optiondict,
2813
+ LGR,
2814
+ TimingLGR,
2815
+ outputlevel=optiondict["outputlevel"],
2816
+ gausssigma=optiondict["delayoffsetgausssigma"],
2817
+ patchthresh=optiondict["delaypatchthresh"],
2818
+ timemask=thetimemask,
2819
+ mindelay=optiondict["mindelay"],
2820
+ maxdelay=optiondict["maxdelay"],
2821
+ numpoints=optiondict["numpoints"],
2822
+ histlen=optiondict["histlen"],
2823
+ rt_floattype=rt_floattype,
2824
+ debug=optiondict["debug"],
2825
+ )
2826
+ windoweddelayoffsets.append(windoweddelayoffset)
2827
+
2828
+ ####################################################
2829
+ # Delay refinement end
2830
+ ####################################################
2831
+
2832
+ # now calculate the sLFO filter or CVR map
2833
+ if optiondict["dolinfitfilt"] or optiondict["docvrmap"]:
2834
+ if optiondict["dolinfitfilt"]:
2835
+ TimingLGR.info("sLFO filtering start")
2836
+ LGR.info("\n\nsLFO filtering")
2837
+ else:
2838
+ TimingLGR.info("CVR map generation")
2839
+ LGR.info("\n\nCVR mapping")
2840
+
2841
+ # calculate the initial raw and bandlimited mean normalized variance if we're going to filter the data
2842
+ # initialrawvariance = tide_math.imagevariance(fmri_data_valid, None, 1.0 / fmritr)
2843
+ initialvariance = tide_math.imagevariance(fmri_data_valid, theprefilter, 1.0 / fmritr)
2844
+
2845
+ # now calculate the sLFO filter
2846
+ if optiondict["refinedelay"] and optiondict["filterwithrefineddelay"]:
2847
+ lagstouse = lagtimesrefined
2848
+ else:
2849
+ lagstouse = lagtimes
2850
+ voxelsprocessed_regressionfilt, regressorset, evset = (
2851
+ tide_regressfrommaps.regressfrommaps(
2852
+ fmri_data_valid,
2853
+ validvoxels,
2854
+ initial_fmri_x,
2855
+ lagstouse,
2856
+ sLFOfiltmask,
2857
+ genlagtc,
2858
+ mode,
2859
+ outputname,
2860
+ oversamptr,
2861
+ sLFOfitmean,
2862
+ rvalue,
2863
+ r2value,
2864
+ fitNorm[:, : optiondict["regressderivs"] + 1],
2865
+ fitcoeff[:, : optiondict["regressderivs"] + 1],
2866
+ movingsignal,
2867
+ lagtc,
2868
+ filtereddata,
2869
+ LGR,
2870
+ TimingLGR,
2871
+ optiondict["regressfiltthreshval"],
2872
+ optiondict["saveminimumsLFOfiltfiles"],
2873
+ nprocs_makelaggedtcs=optiondict["nprocs_makelaggedtcs"],
2874
+ nprocs_regressionfilt=optiondict["nprocs_regressionfilt"],
2875
+ regressderivs=optiondict["regressderivs"],
2876
+ chunksize=optiondict["mp_chunksize"],
2877
+ showprogressbar=optiondict["showprogressbar"],
2878
+ alwaysmultiproc=optiondict["alwaysmultiproc"],
2879
+ debug=optiondict["debug"],
2880
+ )
2881
+ )
2882
+
2883
+ evcolnames = ["base"]
2884
+ if optiondict["regressderivs"] > 0:
2885
+ for i in range(1, optiondict["regressderivs"] + 1):
2886
+ evcolnames.append(f"deriv_{str(i)}")
2887
+
2888
+ tide_io.writebidstsv(
2889
+ f"{outputname}_desc-EV_timeseries",
2890
+ np.transpose(evset),
2891
+ 1.0 / fmritr,
2892
+ columns=evcolnames,
2893
+ extraheaderinfo={"Description": "sLFO filter regressor set"},
2894
+ append=False,
2895
+ )
2896
+
2897
+ # calculate the final raw and bandlimited mean normalized variance
2898
+ # finalrawvariance = tide_math.imagevariance(filtereddata, None, 1.0 / fmritr)
2899
+ finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
2900
+
2901
+ divlocs = np.where(finalvariance > 0.0)
2902
+ varchange = np.zeros_like(initialvariance)
2903
+ varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
2904
+
2905
+ # calculate the voxelwise mean of the filtered data
2906
+ lfofilteredmeanvalue = np.mean(
2907
+ filtereddata,
2908
+ axis=1,
2909
+ )
2910
+
2911
+ LGR.info("End filtering operation")
2912
+ TimingLGR.info(
2913
+ "sLFO filtering end",
2914
+ {
2915
+ "message2": voxelsprocessed_regressionfilt,
2916
+ "message3": "voxels",
2917
+ },
2918
+ )
2919
+ if internalinitregressorincludemask is not None:
2920
+ thisincludemask = internalinitregressorincludemask[validvoxels]
2921
+ else:
2922
+ thisincludemask = None
2923
+ if internalinitregressorexcludemask is not None:
2924
+ thisexcludemask = internalinitregressorexcludemask[validvoxels]
2925
+ else:
2926
+ thisexcludemask = None
2927
+
2928
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
2929
+ "initial regressor",
2930
+ "startregressormask",
2931
+ filtereddata,
2932
+ thisincludemask,
2933
+ meanfreq,
2934
+ outputname,
2935
+ initfile=True,
2936
+ excludemask=thisexcludemask,
2937
+ filedesc="regionalpostfilter",
2938
+ suffix="",
2939
+ debug=optiondict["debug"],
2940
+ )
2941
+ if brainmask is not None:
2942
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
2943
+ "whole brain",
2944
+ "brain",
2945
+ filtereddata,
2946
+ internalbrainmask[validvoxels],
2947
+ meanfreq,
2948
+ outputname,
2949
+ filedesc="regionalpostfilter",
2950
+ suffix="",
2951
+ debug=optiondict["debug"],
2952
+ )
2953
+ if graymask is not None:
2954
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
2955
+ "gray matter",
2956
+ "GM",
2957
+ filtereddata,
2958
+ internalgraymask[validvoxels],
2959
+ meanfreq,
2960
+ outputname,
2961
+ excludemask=internalinvbrainmask[validvoxels],
2962
+ filedesc="regionalpostfilter",
2963
+ suffix="",
2964
+ debug=optiondict["debug"],
2965
+ )
2966
+ if whitemask is not None:
2967
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
2968
+ "white matter",
2969
+ "WM",
2970
+ filtereddata,
2971
+ internalwhitemask[validvoxels],
2972
+ meanfreq,
2973
+ outputname,
2974
+ excludemask=internalinvbrainmask[validvoxels],
2975
+ filedesc="regionalpostfilter",
2976
+ suffix="",
2977
+ debug=optiondict["debug"],
2978
+ )
2979
+ if csfmask is not None:
2980
+ csfvec, dummy = tide_mask.saveregionaltimeseries(
2981
+ "CSF",
2982
+ "CSF",
2983
+ filtereddata,
2984
+ internalcsfmask[validvoxels],
2985
+ meanfreq,
2986
+ outputname,
2987
+ excludemask=internalinvbrainmask[validvoxels],
2988
+ filedesc="regionalpostfilter",
2989
+ suffix="",
2990
+ debug=optiondict["debug"],
2991
+ )
2992
+ tide_util.logmem("after sLFO filter")
2993
+ LGR.info("")
3303
2994
  else:
3304
- # get the original data to calculate the mean
3305
- pass
3306
- """LGR.info(f"rereading {fmrifilename} to calculate mean value, please wait")
3307
- if optiondict["textio"]:
3308
- nim_data = tide_io.readvecs(fmrifilename)
3309
- else:
3310
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(fmrifilename)"""
2995
+ outfmriarray = None
3311
2996
  ####################################################
3312
- # GLM filtering end
2997
+ # sLFO filtering end
3313
2998
  ####################################################
3314
2999
 
3315
3000
  # Post refinement step 2 - make and save interesting histograms
@@ -3347,24 +3032,24 @@ def rapidtide_main(argparsingfunc):
3347
3032
  thedict=optiondict,
3348
3033
  )
3349
3034
  namesuffix = "_desc-lfofilterR2_hist"
3350
- if optiondict["doglmfilt"]:
3035
+ if optiondict["dolinfitfilt"]:
3351
3036
  tide_stats.makeandsavehistogram(
3352
3037
  r2value[np.where(fitmask > 0)],
3353
3038
  optiondict["histlen"],
3354
3039
  1,
3355
3040
  outputname + namesuffix,
3356
- displaytitle="Histogram of GLM filter R2 values",
3041
+ displaytitle="Histogram of sLFO filter R2 values",
3357
3042
  dictvarname="R2hist",
3358
3043
  thedict=optiondict,
3359
3044
  )
3360
3045
  namesuffix = "_desc-lfofilterInbandVarianceChange_hist"
3361
- if optiondict["doglmfilt"]:
3046
+ if optiondict["dolinfitfilt"]:
3362
3047
  tide_stats.makeandsavehistogram(
3363
3048
  varchange[np.where(fitmask > 0)],
3364
3049
  optiondict["histlen"],
3365
3050
  1,
3366
3051
  outputname + namesuffix,
3367
- displaytitle="Histogram of percent of inband variance removed by GLM filter",
3052
+ displaytitle="Histogram of percent of inband variance removed by sLFO filter",
3368
3053
  dictvarname="varchangehist",
3369
3054
  thedict=optiondict,
3370
3055
  )
@@ -3378,6 +3063,10 @@ def rapidtide_main(argparsingfunc):
3378
3063
  lagstrengths[np.where(fitmask > 0)], histpcts, nozero=False
3379
3064
  )
3380
3065
  thesigmapcts = tide_stats.getfracvals(lagsigma[np.where(fitmask > 0)], histpcts, nozero=False)
3066
+ if optiondict["refinedelay"]:
3067
+ therefinedtimepcts = tide_stats.getfracvals(
3068
+ lagtimesrefined[np.where(fitmask > 0)], histpcts, nozero=False
3069
+ )
3381
3070
  for i in range(len(histpcts)):
3382
3071
  optiondict[f"lagtimes_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3383
3072
  thetimepcts[i]
@@ -3388,6 +3077,10 @@ def rapidtide_main(argparsingfunc):
3388
3077
  optiondict[f"lagsigma_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3389
3078
  thesigmapcts[i]
3390
3079
  )
3080
+ if optiondict["refinedelay"]:
3081
+ optiondict[
3082
+ f"lagtimesrefined_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"
3083
+ ] = therefinedtimepcts[i]
3391
3084
  optiondict["fitmasksize"] = np.sum(fitmask)
3392
3085
  optiondict["fitmaskpct"] = 100.0 * optiondict["fitmasksize"] / optiondict["corrmasksize"]
3393
3086
 
@@ -3397,21 +3090,7 @@ def rapidtide_main(argparsingfunc):
3397
3090
 
3398
3091
  # write the 3D maps that need to be remapped
3399
3092
  TimingLGR.info("Start saving maps")
3400
- if not optiondict["textio"]:
3401
- theheader = copy.deepcopy(nim_hdr)
3402
- if fileiscifti:
3403
- timeindex = theheader["dim"][0] - 1
3404
- spaceindex = theheader["dim"][0]
3405
- theheader["dim"][timeindex] = 1
3406
- theheader["dim"][spaceindex] = numspatiallocs
3407
- else:
3408
- theheader["dim"][0] = 3
3409
- theheader["dim"][4] = 1
3410
- theheader["pixdim"][4] = 1.0
3411
- else:
3412
- theheader = None
3413
- cifti_hdr = None
3414
-
3093
+ theheader = theinputdata.copyheader(numtimepoints=1)
3415
3094
  savelist = [
3416
3095
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
3417
3096
  (
@@ -3433,10 +3112,51 @@ def rapidtide_main(argparsingfunc):
3433
3112
  (fitmask, "corrfit", "mask", None, "Voxels where correlation value was fit"),
3434
3113
  (failreason, "corrfitfailreason", "info", None, "Result codes for correlation fit"),
3435
3114
  ]
3436
- MTT = np.square(lagsigma) - (optiondict["acwidth"] * optiondict["acwidth"])
3115
+ MTT = np.square(lagsigma) - 0.5 * (optiondict["acwidth"] * optiondict["acwidth"])
3437
3116
  MTT = np.where(MTT > 0.0, MTT, 0.0)
3438
3117
  MTT = np.sqrt(MTT)
3439
3118
  savelist += [(MTT, "MTT", "map", "second", "Mean transit time (estimated)")]
3119
+ if optiondict["refinedelay"]:
3120
+ savelist += [
3121
+ (
3122
+ delayoffset,
3123
+ "delayoffset",
3124
+ "map",
3125
+ "second",
3126
+ "Delay offset correction from delay refinement",
3127
+ ),
3128
+ (
3129
+ lagtimesrefined,
3130
+ "maxtimerefined",
3131
+ "map",
3132
+ "second",
3133
+ "Lag time in seconds, refined",
3134
+ ),
3135
+ ]
3136
+ if (optiondict["outputlevel"] != "min") and (optiondict["outputlevel"] != "less"):
3137
+ savelist += [
3138
+ (
3139
+ regressderivratios,
3140
+ "regressderivratios",
3141
+ "map",
3142
+ None,
3143
+ "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
3144
+ ),
3145
+ (
3146
+ medfiltregressderivratios,
3147
+ "medfiltregressderivratios",
3148
+ "map",
3149
+ None,
3150
+ "Median filtered version of the regressderivratios map",
3151
+ ),
3152
+ (
3153
+ filteredregressderivratios,
3154
+ "filteredregressderivratios",
3155
+ "map",
3156
+ None,
3157
+ "regressderivratios, with outliers patched using median filtered data",
3158
+ ),
3159
+ ]
3440
3160
  if optiondict["calccoherence"]:
3441
3161
  savelist += [
3442
3162
  (coherencepeakval, "coherencepeakval", "map", None, "Coherence peak value"),
@@ -3449,10 +3169,9 @@ def rapidtide_main(argparsingfunc):
3449
3169
  nativespaceshape,
3450
3170
  theheader,
3451
3171
  bidsbasedict,
3452
- textio=optiondict["textio"],
3453
- fileiscifti=fileiscifti,
3172
+ filetype=theinputdata.filetype,
3454
3173
  rt_floattype=rt_floattype,
3455
- cifti_hdr=cifti_hdr,
3174
+ cifti_hdr=theinputdata.cifti_hdr,
3456
3175
  )
3457
3176
  namesuffix = "_desc-MTT_hist"
3458
3177
  tide_stats.makeandsavehistogram(
@@ -3464,10 +3183,18 @@ def rapidtide_main(argparsingfunc):
3464
3183
  dictvarname="MTThist",
3465
3184
  thedict=optiondict,
3466
3185
  )
3186
+ if optiondict["calccoherence"]:
3187
+ del coherencefunc
3188
+ del coherencepeakval
3189
+ del coherencepeakfreq
3190
+ if optiondict["sharedmem"]:
3191
+ tide_util.cleanup_shm(coherencefunc_shm)
3192
+ tide_util.cleanup_shm(coherencepeakval_shm)
3193
+ tide_util.cleanup_shm(coherencepeakfreq_shm)
3467
3194
 
3468
3195
  # write the optional 3D maps that need to be remapped
3469
- if optiondict["doglmfilt"] or optiondict["docvrmap"]:
3470
- if optiondict["doglmfilt"]:
3196
+ if optiondict["dolinfitfilt"] or optiondict["docvrmap"]:
3197
+ if optiondict["dolinfitfilt"]:
3471
3198
  maplist = [
3472
3199
  (
3473
3200
  initialvariance,
@@ -3490,34 +3217,41 @@ def rapidtide_main(argparsingfunc):
3490
3217
  "percent",
3491
3218
  "Change in inband variance after filtering, in percent",
3492
3219
  ),
3220
+ # (
3221
+ # lfofilteredmeanvalue,
3222
+ # "lfofilterMean",
3223
+ # "map",
3224
+ # None,
3225
+ # "Voxelwise mean of the sLFO filtered data",
3226
+ # ),
3493
3227
  ]
3494
- if optiondict["saveminimumglmfiles"]:
3228
+ if optiondict["saveminimumsLFOfiltfiles"]:
3495
3229
  maplist += [
3496
3230
  (
3497
3231
  r2value,
3498
3232
  "lfofilterR2",
3499
3233
  "map",
3500
3234
  None,
3501
- "Squared R value of the GLM fit (proportion of variance explained)",
3235
+ "Squared R value of the sLFO fit (proportion of variance explained)",
3502
3236
  ),
3503
3237
  ]
3504
- if optiondict["savenormalglmfiles"]:
3238
+ if optiondict["savenormalsLFOfiltfiles"]:
3505
3239
  maplist += [
3506
- (rvalue, "lfofilterR", "map", None, "R value of the GLM fit"),
3507
- (glmmean, "lfofilterMean", "map", None, "Intercept from GLM fit"),
3240
+ (rvalue, "lfofilterR", "map", None, "R value of the sLFO fit"),
3241
+ (sLFOfitmean, "lfofilterMean", "map", None, "Intercept from sLFO fit"),
3508
3242
  ]
3509
- if optiondict["glmderivs"] > 0:
3243
+ if optiondict["regressderivs"] > 0:
3510
3244
  maplist += [
3511
- (fitcoeff[:, 0], f"lfofilterCoeff", "map", None, "Fit coefficient"),
3245
+ (fitcoeff[:, 0], "lfofilterCoeff", "map", None, "Fit coefficient"),
3512
3246
  (
3513
3247
  fitNorm[:, 0],
3514
- f"lfofilterNorm",
3248
+ "lfofilterNorm",
3515
3249
  "map",
3516
3250
  None,
3517
3251
  "Normalized fit coefficient",
3518
3252
  ),
3519
3253
  ]
3520
- for thederiv in range(1, optiondict["glmderivs"] + 1):
3254
+ for thederiv in range(1, optiondict["regressderivs"] + 1):
3521
3255
  maplist += [
3522
3256
  (
3523
3257
  fitcoeff[:, thederiv],
@@ -3536,9 +3270,74 @@ def rapidtide_main(argparsingfunc):
3536
3270
  ]
3537
3271
  else:
3538
3272
  maplist += [
3539
- (fitcoeff, "lfofilterCoeff", "map", None, "Fit coefficient"),
3540
- (fitNorm, "lfofilterNorm", "map", None, "Normalized fit coefficient"),
3273
+ (
3274
+ fitcoeff[:, : optiondict["regressderivs"] + 1],
3275
+ "lfofilterCoeff",
3276
+ "map",
3277
+ None,
3278
+ "Fit coefficient",
3279
+ ),
3280
+ (
3281
+ fitNorm[:, : optiondict["regressderivs"] + 1],
3282
+ "lfofilterNorm",
3283
+ "map",
3284
+ None,
3285
+ "Normalized fit coefficient",
3286
+ ),
3541
3287
  ]
3288
+ init_std_valid = init_std[validvoxels] + 0.0
3289
+ init_skew_valid = init_skew[validvoxels] + 0.0
3290
+ init_kurtosis_valid = init_kurtosis[validvoxels] + 0.0
3291
+ maplist += [
3292
+ (init_std_valid, "initialStd", "map", None, "Std of the raw input data"),
3293
+ (
3294
+ init_skew_valid,
3295
+ "initialSkewness",
3296
+ "map",
3297
+ None,
3298
+ "Skewness of the raw input data",
3299
+ ),
3300
+ (
3301
+ init_kurtosis_valid,
3302
+ "initialKurtosis",
3303
+ "map",
3304
+ None,
3305
+ "Kurtosis of the raw input data",
3306
+ ),
3307
+ ]
3308
+ (
3309
+ final_min_valid,
3310
+ final_max_valid,
3311
+ final_mean_valid,
3312
+ final_std_valid,
3313
+ final_median_valid,
3314
+ final_MAD_valid,
3315
+ final_skew_valid,
3316
+ final_kurtosis_valid,
3317
+ ) = tide_stats.fmristats(filtereddata)
3318
+ maplist += [
3319
+ (
3320
+ final_std_valid,
3321
+ "lfofilterCleanedStd",
3322
+ "map",
3323
+ None,
3324
+ "Std of the sLFO cleaned data",
3325
+ ),
3326
+ (
3327
+ final_skew_valid,
3328
+ "lfofilterCleanedSkewness",
3329
+ "map",
3330
+ None,
3331
+ "Skewness of the sLFO cleaned data",
3332
+ ),
3333
+ (
3334
+ final_kurtosis_valid,
3335
+ "lfofilterCleanedKurtosis",
3336
+ "map",
3337
+ None,
3338
+ "Kurtosis of the sLFO cleaned data",
3339
+ ),
3340
+ ]
3542
3341
  else:
3543
3342
  maplist = [
3544
3343
  (
@@ -3562,25 +3361,22 @@ def rapidtide_main(argparsingfunc):
3562
3361
  None,
3563
3362
  "Percentage of inband variance attributable to CVR regressor",
3564
3363
  ),
3364
+ (rvalue, "CVRR", "map", None, "R value of the sLFO fit"),
3365
+ (
3366
+ r2value,
3367
+ "CVRR2",
3368
+ "map",
3369
+ None,
3370
+ "Squared R value of the sLFO fit (proportion of variance explained)",
3371
+ ),
3372
+ (
3373
+ fitcoeff[:, 0],
3374
+ "CVR",
3375
+ "map",
3376
+ "percent",
3377
+ "Percent signal change due to the CVR regressor",
3378
+ ),
3565
3379
  ]
3566
- if optiondict["savenormalglmfiles"]:
3567
- maplist = [
3568
- (rvalue, "CVRR", "map", None, "R value of the GLM fit"),
3569
- (
3570
- r2value,
3571
- "CVRR2",
3572
- "map",
3573
- None,
3574
- "Squared R value of the GLM fit (proportion of variance explained)",
3575
- ),
3576
- (
3577
- fitcoeff,
3578
- "CVR",
3579
- "map",
3580
- "percent",
3581
- "Percent signal change due to the CVR regressor",
3582
- ),
3583
- ]
3584
3380
 
3585
3381
  tide_io.savemaplist(
3586
3382
  outputname,
@@ -3589,11 +3385,78 @@ def rapidtide_main(argparsingfunc):
3589
3385
  nativespaceshape,
3590
3386
  theheader,
3591
3387
  bidsbasedict,
3592
- textio=optiondict["textio"],
3593
- fileiscifti=fileiscifti,
3388
+ filetype=theinputdata.filetype,
3594
3389
  rt_floattype=rt_floattype,
3595
- cifti_hdr=cifti_hdr,
3390
+ cifti_hdr=theinputdata.cifti_hdr,
3596
3391
  )
3392
+
3393
+ if optiondict["refinedelay"]:
3394
+ # filter the fmri data to the lfo band
3395
+ print("filtering fmri_data to sLFO band")
3396
+ for i in range(fmri_data_valid.shape[0]):
3397
+ fmri_data_valid[i, :] = theprefilter.apply(
3398
+ optiondict["fmrifreq"], fmri_data_valid[i, :]
3399
+ )
3400
+
3401
+ print("rerunning sLFO fit to get filtered R value")
3402
+ dummy, dummy, dummy = tide_regressfrommaps.regressfrommaps(
3403
+ fmri_data_valid,
3404
+ validvoxels,
3405
+ initial_fmri_x,
3406
+ lagstouse,
3407
+ sLFOfiltmask,
3408
+ genlagtc,
3409
+ mode,
3410
+ outputname,
3411
+ oversamptr,
3412
+ sLFOfitmean,
3413
+ rvalue,
3414
+ r2value,
3415
+ fitNorm[:, : optiondict["regressderivs"] + 1],
3416
+ fitcoeff[:, : optiondict["regressderivs"] + 1],
3417
+ movingsignal,
3418
+ lagtc,
3419
+ filtereddata,
3420
+ LGR,
3421
+ TimingLGR,
3422
+ optiondict["regressfiltthreshval"],
3423
+ optiondict["saveminimumsLFOfiltfiles"],
3424
+ nprocs_makelaggedtcs=optiondict["nprocs_makelaggedtcs"],
3425
+ nprocs_regressionfilt=optiondict["nprocs_regressionfilt"],
3426
+ regressderivs=optiondict["regressderivs"],
3427
+ chunksize=optiondict["mp_chunksize"],
3428
+ showprogressbar=optiondict["showprogressbar"],
3429
+ alwaysmultiproc=optiondict["alwaysmultiproc"],
3430
+ debug=optiondict["debug"],
3431
+ )
3432
+
3433
+ maplist = [
3434
+ (
3435
+ rvalue,
3436
+ "maxcorrrefined",
3437
+ "map",
3438
+ None,
3439
+ "R value of the inband sLFO fit, with sign",
3440
+ ),
3441
+ ]
3442
+
3443
+ tide_io.savemaplist(
3444
+ outputname,
3445
+ maplist,
3446
+ validvoxels,
3447
+ nativespaceshape,
3448
+ theheader,
3449
+ bidsbasedict,
3450
+ filetype=theinputdata.filetype,
3451
+ rt_floattype=rt_floattype,
3452
+ cifti_hdr=theinputdata.cifti_hdr,
3453
+ )
3454
+
3455
+ del fmri_data_valid
3456
+ if optiondict["sharedmem"]:
3457
+ tide_util.cleanup_shm(fmri_data_valid_shm)
3458
+
3459
+ del sLFOfitmean
3597
3460
  del rvalue
3598
3461
  del r2value
3599
3462
  del fitcoeff
@@ -3601,10 +3464,27 @@ def rapidtide_main(argparsingfunc):
3601
3464
  del initialvariance
3602
3465
  del finalvariance
3603
3466
  del varchange
3467
+ if optiondict["sharedmem"]:
3468
+ tide_util.cleanup_shm(sLFOfitmean_shm)
3469
+ tide_util.cleanup_shm(rvalue_shm)
3470
+ tide_util.cleanup_shm(r2value_shm)
3471
+ tide_util.cleanup_shm(fitcoeff_shm)
3472
+ tide_util.cleanup_shm(fitNorm_shm)
3604
3473
 
3605
3474
  # write the 3D maps that don't need to be remapped
3475
+ if theinputdata.filetype != "nifti":
3476
+ unfiltmeanvalue = meanvalue
3606
3477
  maplist = [
3478
+ (
3479
+ unfiltmeanvalue,
3480
+ "unfiltmean",
3481
+ "map",
3482
+ None,
3483
+ "Voxelwise mean of fmri data before smoothing",
3484
+ ),
3607
3485
  (meanvalue, "mean", "map", None, "Voxelwise mean of fmri data"),
3486
+ (stddevvalue, "std", "map", None, "Voxelwise standard deviation of fmri data"),
3487
+ (covvalue, "CoV", "map", None, "Voxelwise coefficient of variation of fmri data"),
3608
3488
  ]
3609
3489
  if brainmask is not None:
3610
3490
  maplist.append((brainmask, "brainmask", "mask", None, "Brain mask"))
@@ -3612,6 +3492,8 @@ def rapidtide_main(argparsingfunc):
3612
3492
  maplist.append((graymask, "GM", "mask", None, "Gray matter mask"))
3613
3493
  if whitemask is not None:
3614
3494
  maplist.append((whitemask, "WM", "mask", None, "White matter mask"))
3495
+ if csfmask is not None:
3496
+ maplist.append((csfmask, "CSF", "mask", None, "CSF mask"))
3615
3497
  tide_io.savemaplist(
3616
3498
  outputname,
3617
3499
  maplist,
@@ -3619,29 +3501,38 @@ def rapidtide_main(argparsingfunc):
3619
3501
  nativespaceshape,
3620
3502
  theheader,
3621
3503
  bidsbasedict,
3622
- textio=optiondict["textio"],
3623
- fileiscifti=fileiscifti,
3504
+ filetype=theinputdata.filetype,
3624
3505
  rt_floattype=rt_floattype,
3625
- cifti_hdr=cifti_hdr,
3506
+ cifti_hdr=theinputdata.cifti_hdr,
3626
3507
  )
3627
3508
  del meanvalue
3509
+ del unfiltmeanvalue
3628
3510
 
3629
3511
  if optiondict["numestreps"] > 0:
3630
3512
  masklist = []
3631
- for i in range(0, len(thepercentiles)):
3632
- if optiondict["dosighistfit"]:
3633
- pmask = np.where(np.abs(lagstrengths) > pcts_fit[i], fitmask, 0 * fitmask)
3634
- else:
3635
- pmask = np.where(np.abs(lagstrengths) > pcts[i], fitmask, 0 * fitmask)
3636
- masklist += [
3637
- (
3638
- pmask.copy(),
3639
- f"plt{thepvalnames[i]}",
3640
- "mask",
3641
- None,
3642
- f"Voxels where the maxcorr value exceeds the p < {1.0 - thepercentiles[i]:.3f} significance level",
3643
- )
3644
- ]
3513
+
3514
+ # we can only calculate this map if we have enough data for a good fit, and the fit succeeded
3515
+ if optiondict["numestreps"] >= 1000:
3516
+ if sigfit is not None:
3517
+ neglogpmax = np.log10(optiondict["numestreps"])
3518
+ # generate a neglogp map
3519
+ neglog10pmap = np.zeros_like(lagstrengths)
3520
+ for voxel in range(neglog10pmap.shape[0]):
3521
+ neglog10pmap[voxel] = tide_stats.neglog10pfromr(
3522
+ lagstrengths[voxel],
3523
+ sigfit,
3524
+ neglogpmax=neglogpmax,
3525
+ debug=optiondict["debug"],
3526
+ )
3527
+ masklist += [
3528
+ (
3529
+ neglog10pmap.copy(),
3530
+ "neglog10p",
3531
+ "map",
3532
+ None,
3533
+ f"Negative log(10) of the p value of the r at each voxel",
3534
+ )
3535
+ ]
3645
3536
 
3646
3537
  tide_io.savemaplist(
3647
3538
  outputname,
@@ -3650,21 +3541,21 @@ def rapidtide_main(argparsingfunc):
3650
3541
  nativespaceshape,
3651
3542
  theheader,
3652
3543
  bidsbasedict,
3653
- textio=optiondict["textio"],
3654
- fileiscifti=fileiscifti,
3544
+ filetype=theinputdata.filetype,
3655
3545
  rt_floattype=rt_floattype,
3656
- cifti_hdr=cifti_hdr,
3546
+ cifti_hdr=theinputdata.cifti_hdr,
3657
3547
  )
3658
3548
  del masklist
3659
3549
 
3660
- if (optiondict["passes"] > 1 or optiondict["globalpreselect"]) and optiondict[
3550
+ if (optiondict["passes"] > 1 or optiondict["initregressorpreselect"]) and optiondict[
3661
3551
  "refinestopreason"
3662
3552
  ] != "emptymask":
3663
- if optiondict["globalpreselect"]:
3553
+ refinemask = theRegressorRefiner.getrefinemask()
3554
+ if optiondict["initregressorpreselect"]:
3664
3555
  masklist = [
3665
3556
  (
3666
3557
  refinemask,
3667
- "globalmeanpreselect",
3558
+ "initregressorpreselect",
3668
3559
  "mask",
3669
3560
  None,
3670
3561
  "I really don't know what this file is for",
@@ -3679,10 +3570,9 @@ def rapidtide_main(argparsingfunc):
3679
3570
  nativespaceshape,
3680
3571
  theheader,
3681
3572
  bidsbasedict,
3682
- textio=optiondict["textio"],
3683
- fileiscifti=fileiscifti,
3573
+ filetype=theinputdata.filetype,
3684
3574
  rt_floattype=rt_floattype,
3685
- cifti_hdr=cifti_hdr,
3575
+ cifti_hdr=theinputdata.cifti_hdr,
3686
3576
  )
3687
3577
  del refinemask
3688
3578
 
@@ -3694,20 +3584,18 @@ def rapidtide_main(argparsingfunc):
3694
3584
  del fitmask
3695
3585
 
3696
3586
  # now do the 4D maps of the similarity function and friends
3697
- if not optiondict["textio"]:
3698
- theheader = copy.deepcopy(nim_hdr)
3699
- theheader["toffset"] = corrscale[corrorigin - lagmininpts]
3700
- if fileiscifti:
3701
- timeindex = theheader["dim"][0] - 1
3702
- spaceindex = theheader["dim"][0]
3703
- theheader["dim"][timeindex] = np.shape(outcorrarray)[1]
3704
- theheader["dim"][spaceindex] = numspatiallocs
3705
- else:
3706
- theheader["dim"][4] = np.shape(outcorrarray)[1]
3707
- theheader["pixdim"][4] = corrtr
3587
+ if optiondict["similaritymetric"] == "riptide":
3588
+ theheader = theinputdata.copyheader(
3589
+ numtimepoints=np.shape(outcorrarray)[1],
3590
+ tr=riptidedelays[1] - riptidedelays[0],
3591
+ toffset=(riptidedelays[0]),
3592
+ )
3708
3593
  else:
3709
- theheader = None
3710
- cifti_hdr = None
3594
+ theheader = theinputdata.copyheader(
3595
+ numtimepoints=np.shape(outcorrarray)[1],
3596
+ tr=corrtr,
3597
+ toffset=(corrscale[corrorigin - lagmininpts]),
3598
+ )
3711
3599
 
3712
3600
  if (
3713
3601
  optiondict["savecorrout"]
@@ -3735,33 +3623,29 @@ def rapidtide_main(argparsingfunc):
3735
3623
  nativecorrshape,
3736
3624
  theheader,
3737
3625
  bidsbasedict,
3738
- textio=optiondict["textio"],
3739
- fileiscifti=fileiscifti,
3626
+ filetype=theinputdata.filetype,
3740
3627
  rt_floattype=rt_floattype,
3741
- cifti_hdr=cifti_hdr,
3628
+ cifti_hdr=theinputdata.cifti_hdr,
3742
3629
  )
3743
3630
  del windowout
3744
3631
  del gaussout
3745
3632
  del corrout
3633
+ del outcorrarray
3634
+ if optiondict["sharedmem"]:
3635
+ tide_util.cleanup_shm(windowout_shm)
3636
+ tide_util.cleanup_shm(gaussout_shm)
3637
+ tide_util.cleanup_shm(corrout_shm)
3638
+ tide_util.cleanup_shm(outcorrarray_shm)
3746
3639
 
3747
3640
  # now save all the files that are of the same length as the input data file and masked
3748
- if not optiondict["textio"]:
3749
- theheader = copy.deepcopy(nim_hdr)
3750
- if fileiscifti:
3751
- timeindex = theheader["dim"][0] - 1
3752
- spaceindex = theheader["dim"][0]
3753
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
3754
- theheader["dim"][spaceindex] = numspatiallocs
3755
- else:
3756
- theheader["dim"][4] = np.shape(outfmriarray)[1]
3757
- theheader["pixdim"][4] = fmritr
3758
- else:
3759
- theheader = None
3760
- cifti_hdr = None
3761
-
3641
+ if outfmriarray is None:
3642
+ outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
3643
+ theheader = theinputdata.copyheader(numtimepoints=np.shape(outfmriarray)[1], tr=fmritr)
3762
3644
  maplist = []
3763
- if optiondict["saveallglmfiles"] and (optiondict["doglmfilt"] or optiondict["docvrmap"]):
3764
- if optiondict["glmderivs"] > 0:
3645
+ if optiondict["saveallsLFOfiltfiles"] and (
3646
+ optiondict["dolinfitfilt"] or optiondict["docvrmap"]
3647
+ ):
3648
+ if optiondict["regressderivs"] > 0:
3765
3649
  maplist += [
3766
3650
  (
3767
3651
  regressorset[:, :, 0],
@@ -3771,7 +3655,7 @@ def rapidtide_main(argparsingfunc):
3771
3655
  "Shifted sLFO regressor to filter",
3772
3656
  ),
3773
3657
  ]
3774
- for thederiv in range(1, optiondict["glmderivs"] + 1):
3658
+ for thederiv in range(1, optiondict["regressderivs"] + 1):
3775
3659
  maplist += [
3776
3660
  (
3777
3661
  regressorset[:, :, thederiv],
@@ -3786,11 +3670,11 @@ def rapidtide_main(argparsingfunc):
3786
3670
  (regressorset, "lfofilterEV", "bold", None, "Shifted sLFO regressor to filter"),
3787
3671
  ]
3788
3672
 
3789
- if optiondict["passes"] > 1:
3673
+ if (optiondict["passes"] > 1) or optiondict["dofinalrefine"]:
3790
3674
  if optiondict["savelagregressors"]:
3791
3675
  maplist += [
3792
3676
  (
3793
- paddedshiftedtcs[:, numpadtrs:-numpadtrs],
3677
+ (theRegressorRefiner.getpaddedshiftedtcs())[:, numpadtrs:-numpadtrs],
3794
3678
  "shiftedtcs",
3795
3679
  "bold",
3796
3680
  None,
@@ -3798,8 +3682,8 @@ def rapidtide_main(argparsingfunc):
3798
3682
  ),
3799
3683
  ]
3800
3684
 
3801
- if optiondict["doglmfilt"]:
3802
- if optiondict["saveminimumglmfiles"]:
3685
+ if optiondict["dolinfitfilt"]:
3686
+ if optiondict["saveminimumsLFOfiltfiles"]:
3803
3687
  maplist += [
3804
3688
  (
3805
3689
  filtereddata,
@@ -3820,6 +3704,27 @@ def rapidtide_main(argparsingfunc):
3820
3704
  ),
3821
3705
  ]
3822
3706
 
3707
+ # save a pseudofile if we're going to
3708
+ if optiondict["makepseudofile"]:
3709
+ print("reading mean image")
3710
+ meanfile = f"{outputname}_desc-mean_map.nii.gz"
3711
+ (
3712
+ mean_input,
3713
+ mean,
3714
+ mean_header,
3715
+ mean_dims,
3716
+ mean_sizes,
3717
+ ) = tide_io.readfromnifti(meanfile)
3718
+ if not tide_io.checkspacematch(theheader, mean_header):
3719
+ raise ValueError("mean dimensions do not match fmri dimensions")
3720
+ if optiondict["debug"]:
3721
+ print(f"{mean.shape=}")
3722
+ mean_spacebytime = mean.reshape((numspatiallocs))
3723
+ if optiondict["debug"]:
3724
+ print(f"{mean_spacebytime.shape=}")
3725
+ pseudofile = mean_spacebytime[validvoxels, None] + movingsignal[:, :]
3726
+ maplist.append((pseudofile, "pseudofile", "bold", None, None))
3727
+
3823
3728
  # save maps in the current output list
3824
3729
  if len(maplist) > 0:
3825
3730
  tide_io.savemaplist(
@@ -3829,20 +3734,22 @@ def rapidtide_main(argparsingfunc):
3829
3734
  nativefmrishape,
3830
3735
  theheader,
3831
3736
  bidsbasedict,
3832
- textio=optiondict["textio"],
3833
- fileiscifti=fileiscifti,
3737
+ filetype=theinputdata.filetype,
3834
3738
  rt_floattype=rt_floattype,
3835
- cifti_hdr=cifti_hdr,
3739
+ cifti_hdr=theinputdata.cifti_hdr,
3836
3740
  )
3837
3741
 
3838
3742
  # clean up
3839
3743
  if optiondict["passes"] > 1:
3840
- del paddedshiftedtcs
3841
- del shiftedtcs
3842
- if optiondict["doglmfilt"]:
3744
+ theRegressorRefiner.cleanup()
3745
+ if optiondict["dolinfitfilt"]:
3843
3746
  del lagtc
3844
3747
  del filtereddata
3845
3748
  del movingsignal
3749
+ if optiondict["sharedmem"]:
3750
+ tide_util.cleanup_shm(lagtc_shm)
3751
+ tide_util.cleanup_shm(filtereddata_shm)
3752
+ tide_util.cleanup_shm(movingsignal_shm)
3846
3753
 
3847
3754
  TimingLGR.info("Finished saving maps")
3848
3755
  LGR.info("done")
@@ -3877,6 +3784,13 @@ def rapidtide_main(argparsingfunc):
3877
3784
  )
3878
3785
  Path(f"{outputname}_runtimings.tsv").unlink(missing_ok=True)
3879
3786
 
3787
+ # save pyfftw wisdom
3788
+ tide_util.savewisdom(optiondict["pyfftw_wisdom"])
3789
+
3790
+ # show fft cache information
3791
+ if optiondict["focaldebug"]:
3792
+ showfftcache()
3793
+
3880
3794
  # do a final save of the options file
3881
3795
  optiondict["currentstage"] = "done"
3882
3796
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
@@ -3891,5 +3805,5 @@ def rapidtide_main(argparsingfunc):
3891
3805
  # delete the canary file
3892
3806
  Path(f"{outputname}_ISRUNNING.txt").unlink()
3893
3807
 
3894
- # created the finished file
3808
+ # create the finished file
3895
3809
  Path(f"{outputname}_DONE.txt").touch()