rapidtide 2.9.6__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 +92 -42
  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 +2 -2
  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 +108 -92
  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 +587 -1116
  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 +835 -144
  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.6.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 +26 -14
  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 +1785 -1858
  292. rapidtide/workflows/rapidtide2std.py +101 -3
  293. rapidtide/workflows/rapidtide_parser.py +590 -389
  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.6.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.6.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.6.data/scripts/adjustoffset +0 -23
  346. rapidtide-2.9.6.data/scripts/aligntcs +0 -23
  347. rapidtide-2.9.6.data/scripts/applydlfilter +0 -23
  348. rapidtide-2.9.6.data/scripts/atlasaverage +0 -23
  349. rapidtide-2.9.6.data/scripts/atlastool +0 -23
  350. rapidtide-2.9.6.data/scripts/calcicc +0 -22
  351. rapidtide-2.9.6.data/scripts/calctexticc +0 -23
  352. rapidtide-2.9.6.data/scripts/calcttest +0 -22
  353. rapidtide-2.9.6.data/scripts/ccorrica +0 -23
  354. rapidtide-2.9.6.data/scripts/diffrois +0 -23
  355. rapidtide-2.9.6.data/scripts/endtidalproc +0 -23
  356. rapidtide-2.9.6.data/scripts/filtnifti +0 -23
  357. rapidtide-2.9.6.data/scripts/filttc +0 -23
  358. rapidtide-2.9.6.data/scripts/fingerprint +0 -593
  359. rapidtide-2.9.6.data/scripts/fixtr +0 -23
  360. rapidtide-2.9.6.data/scripts/glmfilt +0 -24
  361. rapidtide-2.9.6.data/scripts/gmscalc +0 -22
  362. rapidtide-2.9.6.data/scripts/happy +0 -25
  363. rapidtide-2.9.6.data/scripts/happy2std +0 -23
  364. rapidtide-2.9.6.data/scripts/happywarp +0 -350
  365. rapidtide-2.9.6.data/scripts/histnifti +0 -23
  366. rapidtide-2.9.6.data/scripts/histtc +0 -23
  367. rapidtide-2.9.6.data/scripts/localflow +0 -23
  368. rapidtide-2.9.6.data/scripts/mergequality +0 -23
  369. rapidtide-2.9.6.data/scripts/pairproc +0 -23
  370. rapidtide-2.9.6.data/scripts/pairwisemergenifti +0 -23
  371. rapidtide-2.9.6.data/scripts/physiofreq +0 -23
  372. rapidtide-2.9.6.data/scripts/pixelcomp +0 -23
  373. rapidtide-2.9.6.data/scripts/plethquality +0 -23
  374. rapidtide-2.9.6.data/scripts/polyfitim +0 -23
  375. rapidtide-2.9.6.data/scripts/proj2flow +0 -23
  376. rapidtide-2.9.6.data/scripts/rankimage +0 -23
  377. rapidtide-2.9.6.data/scripts/rapidtide +0 -23
  378. rapidtide-2.9.6.data/scripts/rapidtide2std +0 -23
  379. rapidtide-2.9.6.data/scripts/resamplenifti +0 -23
  380. rapidtide-2.9.6.data/scripts/resampletc +0 -23
  381. rapidtide-2.9.6.data/scripts/retroglm +0 -23
  382. rapidtide-2.9.6.data/scripts/roisummarize +0 -23
  383. rapidtide-2.9.6.data/scripts/runqualitycheck +0 -23
  384. rapidtide-2.9.6.data/scripts/showarbcorr +0 -23
  385. rapidtide-2.9.6.data/scripts/showhist +0 -23
  386. rapidtide-2.9.6.data/scripts/showstxcorr +0 -23
  387. rapidtide-2.9.6.data/scripts/showtc +0 -23
  388. rapidtide-2.9.6.data/scripts/showxcorr_legacy +0 -536
  389. rapidtide-2.9.6.data/scripts/showxcorrx +0 -23
  390. rapidtide-2.9.6.data/scripts/showxy +0 -23
  391. rapidtide-2.9.6.data/scripts/simdata +0 -23
  392. rapidtide-2.9.6.data/scripts/spatialdecomp +0 -23
  393. rapidtide-2.9.6.data/scripts/spatialfit +0 -23
  394. rapidtide-2.9.6.data/scripts/spatialmi +0 -23
  395. rapidtide-2.9.6.data/scripts/spectrogram +0 -23
  396. rapidtide-2.9.6.data/scripts/synthASL +0 -23
  397. rapidtide-2.9.6.data/scripts/tcfrom2col +0 -23
  398. rapidtide-2.9.6.data/scripts/tcfrom3col +0 -23
  399. rapidtide-2.9.6.data/scripts/temporaldecomp +0 -23
  400. rapidtide-2.9.6.data/scripts/threeD +0 -236
  401. rapidtide-2.9.6.data/scripts/tidepool +0 -23
  402. rapidtide-2.9.6.data/scripts/variabilityizer +0 -23
  403. rapidtide-2.9.6.dist-info/RECORD +0 -359
  404. rapidtide-2.9.6.dist-info/top_level.txt +0 -86
  405. {rapidtide-2.9.6.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,7 +16,6 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  #
19
- import copy
20
19
  import gc
21
20
  import logging
22
21
  import os
@@ -24,12 +23,11 @@ import platform
24
23
  import sys
25
24
  import warnings
26
25
  from pathlib import Path
26
+ from typing import Any, Tuple
27
27
 
28
28
  import numpy as np
29
- from scipy import ndimage
29
+ from numpy.typing import NDArray
30
30
  from scipy.stats import rankdata
31
- from sklearn.decomposition import PCA
32
- from tqdm import tqdm
33
31
 
34
32
  import rapidtide.calccoherence as tide_calccoherence
35
33
  import rapidtide.calcnullsimfunc as tide_nullsimfunc
@@ -37,21 +35,25 @@ import rapidtide.calcsimfunc as tide_calcsimfunc
37
35
  import rapidtide.correlate as tide_corr
38
36
  import rapidtide.filter as tide_filt
39
37
  import rapidtide.fit as tide_fit
40
- import rapidtide.glmpass as tide_glmpass
41
38
  import rapidtide.helper_classes as tide_classes
42
39
  import rapidtide.io as tide_io
40
+ import rapidtide.linfitfiltpass as tide_linfitfiltpass
43
41
  import rapidtide.maskutil as tide_mask
44
42
  import rapidtide.miscmath as tide_math
45
43
  import rapidtide.multiproc as tide_multiproc
46
- import rapidtide.peakeval as tide_peakeval
47
- import rapidtide.refine_factored as tide_refine
48
44
  import rapidtide.resample as tide_resample
49
- import rapidtide.simfuncfit as tide_simfuncfit
45
+ import rapidtide.simFuncClasses as tide_simFuncClasses
50
46
  import rapidtide.stats as tide_stats
51
47
  import rapidtide.util as tide_util
48
+ import rapidtide.voxelData as tide_voxelData
52
49
  import rapidtide.wiener as tide_wiener
53
- import rapidtide.workflows.glmfrommaps as tide_glmfrommaps
54
- 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
55
57
 
56
58
  from .utils import setup_logger
57
59
 
@@ -62,110 +64,44 @@ try:
62
64
  except ImportError:
63
65
  mklexists = False
64
66
 
65
- try:
66
- from memory_profiler import profile
67
-
68
- memprofilerexists = True
69
- except ImportError:
70
- memprofilerexists = False
71
-
72
67
  LGR = logging.getLogger("GENERAL")
73
68
  ErrorLGR = logging.getLogger("ERROR")
74
69
  TimingLGR = logging.getLogger("TIMING")
75
70
 
76
-
77
- def conditionalprofile():
78
- def resdec(f):
79
- if memprofilerexists:
80
- return profile(f)
81
- return f
82
-
83
- return resdec
84
-
85
-
86
- @conditionalprofile()
87
- def memcheckpoint(message):
88
- LGR.info(message)
89
-
90
-
91
- def getglobalsignal(
92
- indata, optiondict, includemask=None, excludemask=None, pcacomponents=0.8, debug=False
93
- ):
94
- # Start with all voxels
95
- themask = indata[:, 0] * 0 + 1
96
-
97
- # modify the mask if needed
98
- if includemask is not None:
99
- themask = themask * includemask
100
- if excludemask is not None:
101
- themask = themask * (1 - excludemask)
102
-
103
- # combine all the voxels using one of the three methods
104
- global rt_floatset, rt_floattype
105
- globalmean = rt_floatset(indata[0, :])
106
- thesize = np.shape(themask)
107
- numvoxelsused = int(np.sum(np.where(themask > 0.0, 1, 0)))
108
- selectedvoxels = indata[np.where(themask > 0.0), :][0]
109
- if debug:
110
- print(f"getglobalsignal: {selectedvoxels.shape=}")
111
- LGR.info(f"constructing global mean signal using {optiondict['globalsignalmethod']}")
112
- if optiondict["globalsignalmethod"] == "sum":
113
- globalmean = np.mean(selectedvoxels, axis=0)
114
- globalmean -= np.mean(globalmean)
115
- elif optiondict["globalsignalmethod"] == "meanscale":
116
- themean = np.mean(indata, axis=1)
117
- for vox in range(0, thesize[0]):
118
- if themask[vox] > 0.0:
119
- if themean[vox] != 0.0:
120
- globalmean += indata[vox, :] / themean[vox] - 1.0
121
- elif optiondict["globalsignalmethod"] == "pca":
122
- themean = np.mean(indata, axis=1)
123
- thevar = np.var(indata, axis=1)
124
- scaledvoxels = selectedvoxels * 0.0
125
- for vox in range(0, selectedvoxels.shape[0]):
126
- scaledvoxels[vox, :] = selectedvoxels[vox, :] - themean[vox]
127
- if thevar[vox] > 0.0:
128
- scaledvoxels[vox, :] = selectedvoxels[vox, :] / thevar[vox]
129
- try:
130
- thefit = PCA(n_components=pcacomponents).fit(np.transpose(scaledvoxels))
131
- except ValueError:
132
- if pcacomponents == "mle":
133
- LGR.warning("mle estimation failed - falling back to pcacomponents=0.8")
134
- thefit = PCA(n_components=0.8).fit(np.transpose(scaledvoxels))
135
- else:
136
- raise ValueError("unhandled math exception in PCA refinement - exiting")
137
-
138
- varex = 100.0 * np.cumsum(thefit.explained_variance_ratio_)[len(thefit.components_) - 1]
139
- thetransform = thefit.transform(np.transpose(scaledvoxels))
140
- if debug:
141
- print(f"getglobalsignal: {thetransform.shape=}")
142
- globalmean = np.mean(thetransform, axis=0)
143
- globalmean -= np.mean(globalmean)
144
- if debug:
145
- print(f"getglobalsignal: {varex=}")
146
- LGR.info(
147
- f"Using {len(thefit.components_)} component(s), accounting for "
148
- f"{varex:.2f}% of the variance"
149
- )
150
- elif optiondict["globalsignalmethod"] == "random":
151
- globalmean = np.random.standard_normal(size=len(globalmean))
152
- else:
153
- raise ValueError(f"illegal globalsignalmethod: {optiondict['globalsignalmethod']}")
154
- LGR.info(f"used {numvoxelsused} voxels to calculate global mean signal")
155
- if debug:
156
- print(f"getglobalsignal: {globalmean=}")
157
- return tide_math.stdnormalize(globalmean), themask
158
-
159
-
160
- def addmemprofiling(thefunc, memprofile, themessage):
161
- tide_util.logmem(themessage)
162
- if memprofile:
163
- return profile(thefunc, precision=2)
164
- else:
165
- return thefunc
166
-
167
-
168
- 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
+ """
169
105
  themean = np.mean(thedataset, axis=1)
170
106
  thestd = np.std(thedataset, axis=1)
171
107
  if np.mean(thestd) > np.mean(themean):
@@ -174,7 +110,59 @@ def checkforzeromean(thedataset):
174
110
  return False
175
111
 
176
112
 
177
- 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
+ """
178
166
  tide_io.writebidstsv(
179
167
  f"{outputname}_desc-echocancellation_timeseries",
180
168
  thetimecourse,
@@ -188,7 +176,7 @@ def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints
188
176
  shifttr = echooffset / thetimestep # lagtime is in seconds
189
177
  echotc, dummy, dummy, dummy = tide_resample.timeshift(thetimecourse, shifttr, padtimepoints)
190
178
  echotc[0 : int(np.ceil(shifttr))] = 0.0
191
- echofit, echoR = tide_fit.mlregress(echotc, thetimecourse)
179
+ echofit, echoR2 = tide_fit.mlregress(echotc, thetimecourse)
192
180
  fitcoeff = echofit[0, 1]
193
181
  outputtimecourse = thetimecourse - fitcoeff * echotc
194
182
  tide_io.writebidstsv(
@@ -211,27 +199,88 @@ def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints
211
199
  },
212
200
  append=True,
213
201
  )
214
- return outputtimecourse, echofit, echoR
215
-
216
-
217
- def disablemkl(numprocs, debug=False):
218
- if mklexists:
219
- if numprocs > 1:
220
- if debug:
221
- print("disablemkl: setting threads to 1")
222
- mkl.set_num_threads(1)
223
-
224
-
225
- def enablemkl(numthreads, debug=False):
226
- if mklexists:
227
- if debug:
228
- print(f"enablemkl: setting threads to {numthreads}")
229
- mkl.set_num_threads(numthreads)
230
-
231
-
232
- def rapidtide_main(argparsingfunc):
233
- 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
+ """
234
282
  optiondict, theprefilter = argparsingfunc
283
+ optiondict["threaddebug"] = False
235
284
 
236
285
  optiondict["nodename"] = platform.node()
237
286
 
@@ -247,10 +296,16 @@ def rapidtide_main(argparsingfunc):
247
296
  optiondict["Description"] = (
248
297
  "A detailed dump of all internal variables in the program. Useful for debugging and data provenance."
249
298
  )
250
- fmrifilename = optiondict["in_file"]
299
+ inputdatafilename = optiondict["in_file"]
251
300
  outputname = optiondict["outputname"]
252
301
  regressorfilename = optiondict["regressorfile"]
253
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
+
254
309
  # create the canary file
255
310
  Path(f"{outputname}_ISRUNNING.txt").touch()
256
311
 
@@ -261,14 +316,21 @@ def rapidtide_main(argparsingfunc):
261
316
  gc.enable()
262
317
  print("turning on garbage collection")
263
318
 
264
- # if we are running in a Docker container, make sure we enforce memory limits properly
265
- if "IS_DOCKER_8395080871" in os.environ:
266
- optiondict["runningindocker"] = True
267
- optiondict["dockermemfree"], optiondict["dockermemswap"] = tide_util.findavailablemem()
268
- if optiondict["dockermemfix"]:
269
- tide_util.setmemlimit(optiondict["dockermemfree"])
270
- else:
271
- optiondict["runningindocker"] = False
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()
272
334
 
273
335
  # write out the current version of the run options
274
336
  optiondict["currentstage"] = "init"
@@ -279,7 +341,7 @@ def rapidtide_main(argparsingfunc):
279
341
  logger_filename=f"{outputname}_log.txt",
280
342
  timing_filename=f"{outputname}_runtimings.tsv",
281
343
  memory_filename=f"{outputname}_memusage.tsv",
282
- verbose=optiondict["verbose"],
344
+ isverbose=optiondict["verbose"],
283
345
  debug=optiondict["debug"],
284
346
  )
285
347
  TimingLGR.info("Start")
@@ -311,25 +373,21 @@ def rapidtide_main(argparsingfunc):
311
373
  tide_util.disablenumba()
312
374
 
313
375
  # set the internal precision
314
- global rt_floatset, rt_floattype
376
+ global rt_floattype
315
377
  if optiondict["internalprecision"] == "double":
316
378
  LGR.debug("setting internal precision to double")
317
- rt_floattype = "float64"
318
- rt_floatset = np.float64
379
+ rt_floattype = np.dtype(np.float64)
319
380
  else:
320
381
  LGR.debug("setting internal precision to single")
321
- rt_floattype = "float32"
322
- rt_floatset = np.float32
382
+ rt_floattype = np.dtype(np.float32)
323
383
 
324
384
  # set the output precision
325
385
  if optiondict["outputprecision"] == "double":
326
386
  LGR.debug("setting output precision to double")
327
- rt_outfloattype = "float64"
328
- rt_outfloatset = np.float64
387
+ rt_outfloattype = np.dtype(np.float64)
329
388
  else:
330
389
  LGR.debug("setting output precision to single")
331
- rt_outfloattype = "float32"
332
- rt_outfloatset = np.float32
390
+ rt_outfloattype = np.dtype(np.float32)
333
391
 
334
392
  # set the number of worker processes if multiprocessing
335
393
  if optiondict["nprocs"] < 1:
@@ -370,17 +428,17 @@ def rapidtide_main(argparsingfunc):
370
428
  else:
371
429
  optiondict["nprocs_makelaggedtcs"] = optiondict["nprocs"]
372
430
 
373
- if optiondict["singleproc_glm"]:
374
- optiondict["nprocs_glm"] = 1
431
+ if optiondict["singleproc_regressionfilt"]:
432
+ optiondict["nprocs_regressionfilt"] = 1
375
433
  else:
376
- optiondict["nprocs_glm"] = optiondict["nprocs"]
434
+ optiondict["nprocs_regressionfilt"] = optiondict["nprocs"]
377
435
 
378
436
  # set the number of MKL threads to use
379
437
  if mklexists:
380
438
  mklmaxthreads = mkl.get_max_threads()
381
439
  if not (1 <= optiondict["mklthreads"] <= mklmaxthreads):
382
440
  optiondict["mklthreads"] = mklmaxthreads
383
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
441
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
384
442
  LGR.info(f"using {optiondict['mklthreads']} MKL threads")
385
443
 
386
444
  # Generate MemoryLGR output file with column names
@@ -389,79 +447,24 @@ def rapidtide_main(argparsingfunc):
389
447
  ####################################################
390
448
  # Read data
391
449
  ####################################################
392
- # open the fmri datafile
393
- tide_util.logmem("before reading in fmri data")
394
- if tide_io.checkiftext(fmrifilename):
395
- LGR.debug("input file is text - all I/O will be to text files")
396
- optiondict["textio"] = True
397
- if optiondict["gausssigma"] > 0.0:
398
- optiondict["gausssigma"] = 0.0
399
- LGR.info("gaussian spatial filter disabled for text input files")
400
- else:
401
- optiondict["textio"] = False
402
-
403
- if optiondict["textio"]:
404
- nim_data = tide_io.readvecs(fmrifilename)
405
- nim_hdr = None
406
- theshape = np.shape(nim_data)
407
- xsize = theshape[0]
408
- ysize = 1
409
- numslices = 1
410
- fileiscifti = False
411
- timepoints = theshape[1]
412
- thesizes = [0, int(xsize), 1, 1, int(timepoints)]
413
- numspatiallocs = int(xsize)
414
- nativespaceshape = xsize
415
- cifti_hdr = None
416
- else:
417
- fileiscifti = tide_io.checkifcifti(fmrifilename)
418
- if fileiscifti:
419
- LGR.debug("input file is CIFTI")
420
- (
421
- dummy,
422
- cifti_hdr,
423
- nim_data,
424
- nim_hdr,
425
- thedims,
426
- thesizes,
427
- dummy,
428
- ) = tide_io.readfromcifti(fmrifilename)
429
- optiondict["isgrayordinate"] = True
430
- timepoints = nim_data.shape[1]
431
- numspatiallocs = nim_data.shape[0]
432
- LGR.debug(f"cifti file has {timepoints} timepoints, {numspatiallocs} numspatiallocs")
433
- nativespaceshape = (1, 1, 1, 1, numspatiallocs)
434
- else:
435
- LGR.debug("input file is NIFTI")
436
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(fmrifilename)
437
- optiondict["isgrayordinate"] = False
438
- xsize, ysize, numslices, timepoints = tide_io.parseniftidims(thedims)
439
- numspatiallocs = int(xsize) * int(ysize) * int(numslices)
440
- cifti_hdr = None
441
- nativespaceshape = (xsize, ysize, numslices)
442
- xdim, ydim, slicethickness, dummy = tide_io.parseniftisizes(thesizes)
443
-
444
- # correct some fields if necessary
445
- if fileiscifti:
446
- fmritr = 0.72 # this is wrong and is a hack until I can parse CIFTI XML
447
- else:
448
- if optiondict["textio"]:
449
- if optiondict["realtr"] <= 0.0:
450
- raise ValueError(
451
- "for text file data input, you must use the -t option to set the timestep"
452
- )
453
- else:
454
- if nim_hdr.get_xyzt_units()[1] == "msec":
455
- fmritr = thesizes[4] / 1000.0
456
- else:
457
- fmritr = thesizes[4]
458
- if optiondict["realtr"] > 0.0:
459
- 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
460
462
 
461
463
  # check to see if we need to adjust the oversample factor
462
464
  if optiondict["oversampfactor"] < 0:
463
465
  optiondict["oversampfactor"] = int(np.max([np.ceil(fmritr / 0.5), 1]))
464
466
  LGR.debug(f"oversample factor set to {optiondict['oversampfactor']}")
467
+ # optiondict["prewhitenlags"] *= optiondict["oversampfactor"]
465
468
 
466
469
  oversamptr = fmritr / optiondict["oversampfactor"]
467
470
  LGR.verbose(f"fmri data: {timepoints} timepoints, tr = {fmritr}, oversamptr = {oversamptr}")
@@ -483,6 +486,8 @@ def rapidtide_main(argparsingfunc):
483
486
  raise ValueError(
484
487
  f"magnitude of lagmax exceeds {(validend - validstart + 1) * fmritr / 2.0} - invalid"
485
488
  )
489
+ # trim the fmri data to the limits
490
+ theinputdata.setvalidtimes(validstart, validend)
486
491
 
487
492
  # determine the valid timepoints
488
493
  validtimepoints = validend - validstart + 1
@@ -505,55 +510,21 @@ def rapidtide_main(argparsingfunc):
505
510
  optiondict["simcalcoffset"] = -validsimcalcstart * fmritr
506
511
 
507
512
  ####################################################
508
- # Prepare data
513
+ # Calculate initial stats
509
514
  ####################################################
510
- # do spatial filtering if requested
511
- if fileiscifti:
512
- optiondict["gausssigma"] = 0.0
513
- if optiondict["gausssigma"] < 0.0 and not optiondict["textio"]:
514
- # set gausssigma automatically
515
- optiondict["gausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
516
- if optiondict["gausssigma"] > 0.0:
517
- LGR.info(
518
- f"applying gaussian spatial filter to timepoints {validstart} "
519
- f"to {validend} with sigma={optiondict['gausssigma']}"
520
- )
521
- for i in tqdm(
522
- range(validstart, validend + 1),
523
- desc="Timepoint",
524
- unit="timepoints",
525
- disable=(not optiondict["showprogressbar"]),
526
- ):
527
- nim_data[:, :, :, i] = tide_filt.ssmooth(
528
- xdim,
529
- ydim,
530
- slicethickness,
531
- optiondict["gausssigma"],
532
- nim_data[:, :, :, i],
533
- )
534
- TimingLGR.info("End 3D smoothing")
535
-
536
- # reshape the data and trim to a time range, if specified. Check for special case of no trimming to save RAM
537
- fmri_data = nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1]
538
- if optiondict["numtozero"] > 0:
539
- themean = np.mean(fmri_data[:, optiondict["numtozero"] :], axis=1)
540
- fmri_data[:, 0 : optiondict["numtozero"]] = themean[:, None]
541
-
542
- # detect zero mean data
543
- optiondict["dataiszeromean"] = checkforzeromean(fmri_data)
544
- if optiondict["dataiszeromean"]:
545
- LGR.warning(
546
- "WARNING: dataset is zero mean - forcing variance masking and no refine prenormalization. "
547
- "Consider specifying a global mean and correlation mask."
548
- )
549
- optiondict["refineprenorm"] = "None"
550
- 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
+ )
551
518
 
519
+ ####################################################
520
+ # Prepare data
521
+ ####################################################
552
522
  # read in the anatomic masks
553
523
  anatomiclist = [
554
524
  ["brainmaskincludename", "brainmaskincludevals", "brainmask"],
555
525
  ["graymatterincludename", "graymatterincludevals", "graymattermask"],
556
526
  ["whitematterincludename", "whitematterincludevals", "whitemattermask"],
527
+ ["csfincludename", "csfincludevals", "csfmask"],
557
528
  ]
558
529
  anatomicmasks = []
559
530
  for thisanatomic in anatomiclist:
@@ -561,19 +532,59 @@ def rapidtide_main(argparsingfunc):
561
532
  anatomicmasks.append(
562
533
  tide_mask.readamask(
563
534
  optiondict[thisanatomic[0]],
564
- nim_hdr,
535
+ theinputdata.nim_hdr,
565
536
  xsize,
566
- istext=optiondict["textio"],
537
+ istext=(theinputdata.filetype == "text"),
567
538
  valslist=optiondict[thisanatomic[1]],
568
539
  maskname=thisanatomic[2],
569
540
  tolerance=optiondict["spatialtolerance"],
541
+ debug=optiondict["debug"],
570
542
  )
571
543
  )
572
544
  anatomicmasks[-1] = np.uint16(np.where(anatomicmasks[-1] > 0.1, 1, 0))
573
545
  else:
574
- anatomicmasks.append(None)
575
- # anatomicmasks[-1] = np.uint16(np.ones(nativespaceshape, dtype=np.uint16))
546
+ anatomicmasks.append(np.uint16(np.ones(nativespaceshape, dtype=np.uint16)))
547
+
576
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
577
588
  if brainmask is None:
578
589
  invbrainmask = None
579
590
 
@@ -583,28 +594,29 @@ def rapidtide_main(argparsingfunc):
583
594
  invbrainmask = 1 - brainmask
584
595
  internalbrainmask = brainmask.reshape((numspatiallocs))
585
596
  internalinvbrainmask = invbrainmask.reshape((numspatiallocs))
586
- graymask = anatomicmasks[1]
587
- whitemask = anatomicmasks[2]
588
597
 
589
598
  # read in the optional masks
590
599
  tide_util.logmem("before setting masks")
591
600
 
592
- internalglobalmeanincludemask, internalglobalmeanexcludemask, dummy = tide_mask.getmaskset(
593
- "global mean",
594
- optiondict["globalmeanincludename"],
595
- optiondict["globalmeanincludevals"],
596
- optiondict["globalmeanexcludename"],
597
- optiondict["globalmeanexcludevals"],
598
- nim_hdr,
599
- numspatiallocs,
600
- istext=optiondict["textio"],
601
- 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
+ )
602
614
  )
603
615
  if internalinvbrainmask is not None:
604
- if internalglobalmeanexcludemask is not None:
605
- internalglobalmeanexcludemask *= internalinvbrainmask
616
+ if internalinitregressorexcludemask is not None:
617
+ internalinitregressorexcludemask *= internalinvbrainmask
606
618
  else:
607
- internalglobalmeanexcludemask = internalinvbrainmask
619
+ internalinitregressorexcludemask = internalinvbrainmask
608
620
 
609
621
  internalrefineincludemask, internalrefineexcludemask, dummy = tide_mask.getmaskset(
610
622
  "refine",
@@ -612,10 +624,11 @@ def rapidtide_main(argparsingfunc):
612
624
  optiondict["refineincludevals"],
613
625
  optiondict["refineexcludename"],
614
626
  optiondict["refineexcludevals"],
615
- nim_hdr,
627
+ theinputdata.nim_hdr,
616
628
  numspatiallocs,
617
- istext=optiondict["textio"],
629
+ istext=(theinputdata.filetype == "text"),
618
630
  tolerance=optiondict["spatialtolerance"],
631
+ debug=optiondict["debug"],
619
632
  )
620
633
  if internalinvbrainmask is not None:
621
634
  if internalrefineexcludemask is not None:
@@ -629,10 +642,11 @@ def rapidtide_main(argparsingfunc):
629
642
  optiondict["offsetincludevals"],
630
643
  optiondict["offsetexcludename"],
631
644
  optiondict["offsetexcludevals"],
632
- nim_hdr,
645
+ theinputdata.nim_hdr,
633
646
  numspatiallocs,
634
- istext=optiondict["textio"],
647
+ istext=(theinputdata.filetype == "text"),
635
648
  tolerance=optiondict["spatialtolerance"],
649
+ debug=optiondict["debug"],
636
650
  )
637
651
  if internalinvbrainmask is not None:
638
652
  if internaloffsetexcludemask is not None:
@@ -648,19 +662,20 @@ def rapidtide_main(argparsingfunc):
648
662
  if optiondict["corrmaskincludename"] is not None:
649
663
  thecorrmask = tide_mask.readamask(
650
664
  optiondict["corrmaskincludename"],
651
- nim_hdr,
665
+ theinputdata.nim_hdr,
652
666
  xsize,
653
- istext=optiondict["textio"],
667
+ istext=(theinputdata.filetype == "text"),
654
668
  valslist=optiondict["corrmaskincludevals"],
655
669
  maskname="correlation",
656
670
  tolerance=optiondict["spatialtolerance"],
671
+ debug=optiondict["debug"],
657
672
  )
658
673
 
659
674
  corrmask = np.uint16(np.where(thecorrmask > 0, 1, 0).reshape(numspatiallocs))
660
675
 
661
676
  # last line sanity check - if data is 0 over all time in a voxel, force corrmask to zero.
662
677
  datarange = np.max(fmri_data, axis=1) - np.min(fmri_data, axis=1)
663
- if optiondict["textio"]:
678
+ if theinputdata.filetype == "text":
664
679
  tide_io.writenpvecs(
665
680
  datarange.reshape((numspatiallocs)),
666
681
  f"{outputname}_motionr2.txt",
@@ -669,27 +684,29 @@ def rapidtide_main(argparsingfunc):
669
684
  savename = f"{outputname}_desc-datarange"
670
685
  tide_io.savetonifti(
671
686
  datarange.reshape((xsize, ysize, numslices)),
672
- nim_hdr,
687
+ theinputdata.nim_hdr,
673
688
  savename,
674
689
  )
675
690
  corrmask[np.where(datarange == 0)] = 0.0
676
691
  else:
677
692
  # check to see if the data has been demeaned
678
- meanim = np.mean(fmri_data, axis=1)
679
- stdim = np.std(fmri_data, axis=1)
680
- if fileiscifti:
681
- corrmask = np.uint(nim_data[:, 0] * 0 + 1)
693
+ if theinputdata.filetype != "nifti":
694
+ corrmask = np.ones_like(theinputdata.byvoxel()[:, 0], np.uint)
682
695
  else:
683
- if (np.mean(stdim) < np.mean(meanim)) and not optiondict["nirs"]:
696
+ if not optiondict["dataiszeromean"]:
684
697
  LGR.verbose("generating correlation mask from mean image")
685
- corrmask = np.uint16(tide_mask.makeepimask(nim).dataobj.reshape(numspatiallocs))
698
+ corrmask = np.uint16(
699
+ tide_mask.makeepimask(theinputdata.nim).dataobj.reshape(numspatiallocs)
700
+ )
686
701
  else:
687
702
  LGR.verbose("generating correlation mask from std image")
688
703
  corrmask = np.uint16(
689
- tide_stats.makemask(stdim, threshpct=optiondict["corrmaskthreshpct"])
704
+ tide_stats.makemask(
705
+ np.std(fmri_data, axis=1), threshpct=optiondict["corrmaskthreshpct"]
706
+ )
690
707
  )
691
- if internalbrainmask is not None:
692
- corrmask *= internalbrainmask
708
+ if internalbrainmask is not None:
709
+ corrmask = internalbrainmask
693
710
  if tide_stats.getmasksize(corrmask) == 0:
694
711
  raise ValueError("ERROR: there are no voxels in the correlation mask - exiting")
695
712
 
@@ -721,19 +738,20 @@ def rapidtide_main(argparsingfunc):
721
738
  corrmask *= 0
722
739
  corrmask += 1
723
740
  threshval = -10000000.0
724
- if not (fileiscifti or optiondict["textio"]):
725
- theheader = copy.deepcopy(nim_hdr)
726
- theheader["dim"][0] = 3
727
- theheader["dim"][4] = 1
728
- theheader["pixdim"][4] = 1.0
741
+ if theinputdata.filetype == "nifti":
742
+ theheader = theinputdata.copyheader(numtimepoints=1)
729
743
  savename = f"{outputname}_desc-processed_mask"
730
744
  tide_io.savetonifti(corrmask.reshape(xsize, ysize, numslices), theheader, savename)
731
745
 
732
- LGR.verbose(f"image threshval = {threshval}")
746
+ LGR.verbose(f"image threshval = {threshval:.2f}")
733
747
  validvoxels = np.where(corrmask > 0)[0]
748
+ if optiondict["debug"]:
749
+ print(f"{validvoxels.shape=}")
750
+ np.savetxt(f"{outputname}_validvoxels.txt", validvoxels)
734
751
  numvalidspatiallocs = np.shape(validvoxels)[0]
735
752
  LGR.debug(f"validvoxels shape = {numvalidspatiallocs}")
736
- fmri_data_valid = fmri_data[validvoxels, :] + 0.0
753
+ theinputdata.setvalidvoxels(validvoxels)
754
+ fmri_data_valid = theinputdata.validdata() + 0.0
737
755
  LGR.verbose(
738
756
  f"original size = {np.shape(fmri_data)}, trimmed size = {np.shape(fmri_data_valid)}"
739
757
  )
@@ -771,17 +789,15 @@ def rapidtide_main(argparsingfunc):
771
789
  )
772
790
  else:
773
791
  internaloffsetexcludemask_valid = None
774
-
775
792
  tide_util.logmem("after selecting valid voxels")
776
793
 
777
794
  # move fmri_data_valid into shared memory
778
795
  if optiondict["sharedmem"]:
779
796
  LGR.info("moving fmri data to shared memory")
780
797
  TimingLGR.verbose("Start moving fmri_data to shared memory")
781
- tide_util.numpy2shared_func = addmemprofiling(
782
- 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']}"
783
800
  )
784
- fmri_data_valid = tide_util.numpy2shared_func(fmri_data_valid, rt_floatset)
785
801
  TimingLGR.verbose("End moving fmri_data to shared memory")
786
802
 
787
803
  # read in any motion and/or other confound regressors here
@@ -794,7 +810,7 @@ def rapidtide_main(argparsingfunc):
794
810
  ),
795
811
  labels=["xtrans", "ytrans", "ztrans", "xrot", "yrot", "zrot"],
796
812
  deriv=optiondict["mot_deriv"],
797
- order=1,
813
+ order=optiondict["mot_power"],
798
814
  )
799
815
  domotion = True
800
816
  else:
@@ -811,7 +827,7 @@ def rapidtide_main(argparsingfunc):
811
827
  else:
812
828
  doconfounds = False
813
829
 
814
- # now actually do the filtering
830
+ # now actually do the confound filtering
815
831
  if domotion or doconfounds:
816
832
  LGR.info("Doing confound filtering")
817
833
  TimingLGR.verbose("Confound filtering start")
@@ -837,13 +853,20 @@ def rapidtide_main(argparsingfunc):
837
853
  append=False,
838
854
  )
839
855
 
840
- 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"])
841
864
  (
842
865
  mergedregressors,
843
866
  mergedregressorlabels,
844
867
  fmri_data_valid,
845
868
  confoundr2,
846
- ) = tide_glmpass.confoundregress(
869
+ ) = tide_linfitfiltpass.confoundregress(
847
870
  mergedregressors,
848
871
  mergedregressorlabels,
849
872
  fmri_data_valid,
@@ -854,7 +877,7 @@ def rapidtide_main(argparsingfunc):
854
877
  orthogonalize=optiondict["orthogonalize"],
855
878
  showprogressbar=optiondict["showprogressbar"],
856
879
  )
857
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
880
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
858
881
  if confoundr2 is None:
859
882
  print("There are no nonzero confound regressors - exiting")
860
883
  sys.exit()
@@ -867,8 +890,8 @@ def rapidtide_main(argparsingfunc):
867
890
  },
868
891
  )
869
892
  # save the confound filter R2 map
870
- if not optiondict["textio"]:
871
- if fileiscifti:
893
+ if theinputdata.filetype != "text":
894
+ if theinputdata.filetype == "cifti":
872
895
  timeindex = theheader["dim"][0] - 1
873
896
  spaceindex = theheader["dim"][0]
874
897
  theheader["dim"][timeindex] = 1
@@ -878,7 +901,7 @@ def rapidtide_main(argparsingfunc):
878
901
  theheader["dim"][4] = 1
879
902
  theheader["pixdim"][4] = 1.0
880
903
  maplist = [
881
- (confoundr2, "confoundfilterR2", "map", None, "R2 of the motion/confound regression")
904
+ (confoundr2, "confoundfilterR2", "map", None, "R2 of the motion/confound regression"),
882
905
  ]
883
906
  tide_io.savemaplist(
884
907
  outputname,
@@ -887,10 +910,9 @@ def rapidtide_main(argparsingfunc):
887
910
  nativespaceshape,
888
911
  theheader,
889
912
  bidsbasedict,
890
- textio=optiondict["textio"],
891
- fileiscifti=fileiscifti,
913
+ filetype=theinputdata.filetype,
892
914
  rt_floattype=rt_floattype,
893
- cifti_hdr=cifti_hdr,
915
+ cifti_hdr=theinputdata.cifti_hdr,
894
916
  )
895
917
  tide_stats.makeandsavehistogram(
896
918
  confoundr2,
@@ -913,28 +935,10 @@ def rapidtide_main(argparsingfunc):
913
935
  },
914
936
  append=False,
915
937
  )
916
- if optiondict["memprofile"]:
917
- memcheckpoint("...done")
918
- tide_util.logmem("after confound glm filter")
938
+ tide_util.logmem("after confound sLFO filter")
919
939
 
920
940
  if optiondict["saveconfoundfiltered"]:
921
- if not optiondict["textio"]:
922
- theheader = copy.deepcopy(nim_hdr)
923
- if fileiscifti:
924
- nativefmrishape = (1, 1, 1, validtimepoints, numspatiallocs)
925
- timeindex = theheader["dim"][0] - 1
926
- spaceindex = theheader["dim"][0]
927
- theheader["dim"][timeindex] = validtimepoints
928
- theheader["dim"][spaceindex] = numspatiallocs
929
- else:
930
- nativefmrishape = (xsize, ysize, numslices, validtimepoints)
931
- theheader["dim"][4] = validtimepoints
932
- theheader["pixdim"][4] = fmritr
933
- else:
934
- nativefmrishape = (xsize, validtimepoints)
935
- theheader = None
936
- cifti_hdr = None
937
-
941
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
938
942
  maplist = [
939
943
  (
940
944
  fmri_data_valid,
@@ -948,21 +952,26 @@ def rapidtide_main(argparsingfunc):
948
952
  outputname,
949
953
  maplist,
950
954
  validvoxels,
951
- nativefmrishape,
955
+ theinputdata.nativefmrishape,
952
956
  theheader,
953
957
  bidsbasedict,
954
- textio=optiondict["textio"],
955
- fileiscifti=fileiscifti,
958
+ filetype=theinputdata.filetype,
956
959
  rt_floattype=rt_floattype,
957
- cifti_hdr=cifti_hdr,
960
+ cifti_hdr=theinputdata.cifti_hdr,
958
961
  )
959
962
 
960
963
  # get rid of memory we aren't using
961
964
  tide_util.logmem("before purging full sized fmri data")
962
965
  meanvalue = np.mean(
963
- nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1],
966
+ theinputdata.byvoxel(),
964
967
  axis=1,
965
968
  )
969
+ stddevvalue = np.std(
970
+ theinputdata.byvoxel(),
971
+ axis=1,
972
+ )
973
+ covvalue = np.where(meanvalue > 0.0, stddevvalue / meanvalue, 0.0)
974
+ covvalue *= corrmask
966
975
 
967
976
  ####################################################
968
977
  # Get the moving regressor from somewhere
@@ -971,18 +980,88 @@ def rapidtide_main(argparsingfunc):
971
980
  meanfreq = 1.0 / fmritr
972
981
  meanperiod = 1.0 * fmritr
973
982
  meanstarttime = 0.0
974
- meanvec, meanmask = getglobalsignal(
983
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
984
+ "initial regressor",
985
+ "startregressormask",
975
986
  fmri_data,
976
- optiondict,
977
- includemask=internalglobalmeanincludemask,
978
- excludemask=internalglobalmeanexcludemask,
979
- pcacomponents=optiondict["globalpcacomponents"],
980
- 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"],
981
997
  )
982
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
+
983
1063
  # get rid of more memory we aren't using
984
- del fmri_data
985
- del nim_data
1064
+ theinputdata.unload()
986
1065
  uncollected = gc.collect()
987
1066
  if uncollected != 0:
988
1067
  print(f"garbage collected - unable to collect {uncollected} objects")
@@ -995,31 +1074,23 @@ def rapidtide_main(argparsingfunc):
995
1074
  TimingLGR.info("Start of reference prep")
996
1075
  if regressorfilename is None:
997
1076
  LGR.info("no regressor file specified - will use the global mean regressor")
998
- optiondict["useglobalref"] = True
1077
+ optiondict["useinitregressorref"] = True
999
1078
  else:
1000
- optiondict["useglobalref"] = False
1079
+ optiondict["useinitregressorref"] = False
1001
1080
 
1002
1081
  # now set the regressor that we'll use
1003
- if optiondict["useglobalref"]:
1082
+ if optiondict["useinitregressorref"]:
1004
1083
  LGR.verbose("using global mean as probe regressor")
1005
1084
  inputfreq = meanfreq
1006
1085
  inputperiod = meanperiod
1007
1086
  inputstarttime = meanstarttime
1008
1087
  inputvec = meanvec
1009
- theheader = copy.deepcopy(nim_hdr)
1010
1088
 
1011
1089
  # save the meanmask
1012
- if not optiondict["textio"]:
1013
- if fileiscifti:
1014
- timeindex = theheader["dim"][0] - 1
1015
- spaceindex = theheader["dim"][0]
1016
- theheader["dim"][timeindex] = 1
1017
- theheader["dim"][spaceindex] = numspatiallocs
1018
- else:
1019
- theheader["dim"][0] = 3
1020
- theheader["dim"][4] = 1
1021
- theheader["pixdim"][4] = 1.0
1022
- 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
+ ]
1023
1094
  tide_io.savemaplist(
1024
1095
  outputname,
1025
1096
  masklist,
@@ -1027,10 +1098,9 @@ def rapidtide_main(argparsingfunc):
1027
1098
  nativespaceshape,
1028
1099
  theheader,
1029
1100
  bidsbasedict,
1030
- textio=optiondict["textio"],
1031
- fileiscifti=fileiscifti,
1101
+ filetype=theinputdata.filetype,
1032
1102
  rt_floattype=rt_floattype,
1033
- cifti_hdr=cifti_hdr,
1103
+ cifti_hdr=theinputdata.cifti_hdr,
1034
1104
  )
1035
1105
  optiondict["preprocskip"] = 0
1036
1106
  else:
@@ -1068,10 +1138,10 @@ def rapidtide_main(argparsingfunc):
1068
1138
  )
1069
1139
  LGR.verbose("Input vector")
1070
1140
  LGR.verbose(f"length: {len(inputvec)}")
1071
- LGR.verbose(f"input freq: {inputfreq}")
1141
+ LGR.verbose(f"input freq: {inputfreq:.2f}")
1072
1142
  LGR.verbose(f"input start time: {inputstarttime:.3f}")
1073
1143
 
1074
- if not optiondict["useglobalref"]:
1144
+ if not optiondict["useinitregressorref"]:
1075
1145
  globalcorrx, globalcorry, dummy, dummy = tide_corr.arbcorr(
1076
1146
  meanvec, meanfreq, inputvec, inputfreq, start2=(inputstarttime)
1077
1147
  )
@@ -1095,59 +1165,6 @@ def rapidtide_main(argparsingfunc):
1095
1165
  LGR.verbose(f"the timepoint spacing is {1.0 / inputfreq}")
1096
1166
  LGR.verbose(f"the input timecourse start time is {inputstarttime}")
1097
1167
 
1098
- # if there is an externally specified noise regressor, read it in here
1099
- if optiondict["noisetimecoursespec"] is not None:
1100
- noisetimecoursespec = optiondict["noisetimecoursespec"]
1101
- LGR.info(f"using externally supplied noise regressor {noisetimecoursespec}")
1102
- (
1103
- filenoisefreq,
1104
- filenoisestarttime,
1105
- dummy,
1106
- noisevec,
1107
- dummy,
1108
- dummy,
1109
- ) = tide_io.readvectorsfromtextfile(optiondict["noisetimecoursespec"], onecol=True)
1110
- if optiondict["noiseinvert"]:
1111
- noisevec = noisevec * -1.0
1112
- noisefreq = optiondict["noisefreq"]
1113
- noisestarttime = optiondict["noisestarttime"]
1114
- if noisefreq is None:
1115
- if filenoisefreq is not None:
1116
- noisefreq = filenoisefreq
1117
- else:
1118
- noisefreq = 1.0 / fmritr
1119
- LGR.warning(f"no regressor frequency specified - defaulting to {noisefreq} (1/tr)")
1120
- if noisestarttime is None:
1121
- if filenoisestarttime is not None:
1122
- noisestarttime = filenoisestarttime
1123
- else:
1124
- LGR.warning("no regressor start time specified - defaulting to 0.0")
1125
- noisestarttime = 0.0
1126
- noiseperiod = 1.0 / noisefreq
1127
- numnoise = len(noisevec)
1128
- optiondict["noisefreq"] = noisefreq
1129
- optiondict["noisestarttime"] = noisestarttime
1130
- LGR.debug(
1131
- "Noise timecourse start time, end time, and step: {:.3f}, {:.3f}, {:.3f}".format(
1132
- -noisestarttime, noisestarttime + numnoise * noiseperiod, noiseperiod
1133
- )
1134
- )
1135
- noise_x = np.arange(0.0, numnoise) * noiseperiod - noisestarttime
1136
- noise_y = noisevec[0:numnoise] - np.mean(noisevec[0:numnoise])
1137
- # write out the noise regressor as read
1138
- tide_io.writebidstsv(
1139
- f"{outputname}_desc-initialnoiseregressor_timeseries",
1140
- noise_y,
1141
- noisefreq,
1142
- starttime=-noisestarttime,
1143
- columns=["prefilt"],
1144
- append=False,
1145
- )
1146
- LGR.verbose("noise vector")
1147
- LGR.verbose(f"length: {len(noisevec)}")
1148
- LGR.verbose(f"noise freq: {noisefreq}")
1149
- LGR.verbose(f"noise start time: {noisestarttime:.3f}")
1150
-
1151
1168
  # generate the time axes
1152
1169
  fmrifreq = 1.0 / fmritr
1153
1170
  optiondict["fmrifreq"] = fmrifreq
@@ -1224,8 +1241,6 @@ def rapidtide_main(argparsingfunc):
1224
1241
  reference_y = -np.gradient(reference_y_classfilter)
1225
1242
  else:
1226
1243
  reference_y = reference_y_classfilter
1227
- if optiondict["noisetimecoursespec"] is not None:
1228
- noise_y = theprefilter.apply(noisefreq, noise_y)
1229
1244
 
1230
1245
  # write out the reference regressor used
1231
1246
  tide_io.writebidstsv(
@@ -1251,27 +1266,7 @@ def rapidtide_main(argparsingfunc):
1251
1266
  padlen=int(inputfreq * optiondict["padseconds"]),
1252
1267
  debug=optiondict["debug"],
1253
1268
  )
1254
- reference_y = rt_floatset(reference_y_filt.real)
1255
- if optiondict["noisetimecoursespec"] is not None:
1256
- noise_y_filt = tide_filt.dolptrapfftfilt(
1257
- noisefreq,
1258
- 0.25 * fmrifreq,
1259
- 0.5 * fmrifreq,
1260
- noise_y,
1261
- padlen=int(noisefreq * optiondict["padseconds"]),
1262
- debug=optiondict["debug"],
1263
- )
1264
- noise_y = rt_floatset(noise_y_filt.real)
1265
-
1266
- # write out the noise regressor after filtering
1267
- tide_io.writebidstsv(
1268
- f"{outputname}_desc-initialnoiseregressor_timeseries",
1269
- noise_y,
1270
- noisefreq,
1271
- starttime=-noisestarttime,
1272
- columns=["postfilt"],
1273
- append=True,
1274
- )
1269
+ reference_y = (reference_y_filt.real).astype(rt_floattype)
1275
1270
 
1276
1271
  warnings.filterwarnings("ignore", "Casting*")
1277
1272
 
@@ -1305,22 +1300,6 @@ def rapidtide_main(argparsingfunc):
1305
1300
  order=optiondict["detrendorder"],
1306
1301
  demean=optiondict["dodemean"],
1307
1302
  )
1308
- if optiondict["noisetimecoursespec"] is not None:
1309
- if optiondict["detrendorder"] > 0:
1310
- resampnoise_y = tide_fit.detrend(
1311
- tide_resample.doresample(
1312
- noise_x,
1313
- noise_y,
1314
- os_fmri_x,
1315
- padlen=int(oversampfreq * optiondict["padseconds"]),
1316
- padtype="zero",
1317
- method=optiondict["interptype"],
1318
- debug=optiondict["debug"],
1319
- ),
1320
- order=optiondict["detrendorder"],
1321
- demean=optiondict["dodemean"],
1322
- )
1323
-
1324
1303
  else:
1325
1304
  resampnonosref_y = tide_resample.doresample(
1326
1305
  reference_x,
@@ -1336,15 +1315,6 @@ def rapidtide_main(argparsingfunc):
1336
1315
  padlen=int(oversampfreq * optiondict["padseconds"]),
1337
1316
  method=optiondict["interptype"],
1338
1317
  )
1339
- if optiondict["noisetimecoursespec"] is not None:
1340
- resampnoise_y = tide_resample.doresample(
1341
- noise_x,
1342
- noise_y,
1343
- os_fmri_x,
1344
- padlen=int(oversampfreq * optiondict["padseconds"]),
1345
- padtype="zero",
1346
- method=optiondict["interptype"],
1347
- )
1348
1318
 
1349
1319
  LGR.debug(
1350
1320
  f"{len(os_fmri_x)} "
@@ -1357,28 +1327,28 @@ def rapidtide_main(argparsingfunc):
1357
1327
  # save the factor used to normalize the input regressor
1358
1328
  optiondict["initialmovingregressornormfac"] = np.std(resampnonosref_y)
1359
1329
 
1360
- # prepare the temporal mask
1330
+ # prepare the temporal masks
1361
1331
  if optiondict["tincludemaskname"] is not None:
1362
1332
  print("creating temporal include mask")
1363
1333
  includetmask_y = tide_mask.maketmask(
1364
- optiondict["tincludemaskname"], reference_x, rt_floatset(reference_y) + 0.0
1334
+ optiondict["tincludemaskname"], reference_x, reference_y.astype(rt_floattype) + 0.0
1365
1335
  )
1366
1336
  else:
1367
- includetmask_y = (reference_x * 0.0) + 1.0
1337
+ includetmask_y = np.ones_like(reference_x)
1368
1338
  if optiondict["texcludemaskname"] is not None:
1369
1339
  print("creating temporal exclude mask")
1370
1340
  excludetmask_y = (
1371
1341
  -1.0
1372
1342
  * tide_mask.maketmask(
1373
- optiondict["texcludemaskname"], reference_x, rt_floatset(reference_y) + 0.0
1343
+ optiondict["texcludemaskname"], reference_x, reference_y.astype(rt_floattype) + 0.0
1374
1344
  )
1375
1345
  + 1.0
1376
1346
  )
1377
1347
  else:
1378
- excludetmask_y = (reference_x * 0.0) + 1.0
1348
+ excludetmask_y = np.ones_like(reference_x)
1379
1349
  tmask_y = includetmask_y * excludetmask_y
1380
1350
  tmask_y = np.where(tmask_y == 0.0, 0.0, 1.0)
1381
- if optiondict["focaldebug"]:
1351
+ if optiondict["debug"]:
1382
1352
  print("after posterizing temporal mask")
1383
1353
  print(tmask_y)
1384
1354
  if (optiondict["tincludemaskname"] is not None) or (
@@ -1398,27 +1368,16 @@ def rapidtide_main(argparsingfunc):
1398
1368
  append=False,
1399
1369
  )
1400
1370
  resampnonosref_y *= tmask_y
1401
- thefit, R = tide_fit.mlregress(tmask_y, resampnonosref_y)
1371
+ thefit, R2val = tide_fit.mlregress(tmask_y, resampnonosref_y)
1402
1372
  resampnonosref_y -= thefit[0, 1] * tmask_y
1403
1373
  resampref_y *= tmaskos_y
1404
- thefit, R = tide_fit.mlregress(tmaskos_y, resampref_y)
1374
+ thefit, R2val = tide_fit.mlregress(tmaskos_y, resampref_y)
1405
1375
  resampref_y -= thefit[0, 1] * tmaskos_y
1376
+ else:
1377
+ tmaskos_y = None
1406
1378
 
1407
- if optiondict["noisetimecoursespec"] is not None:
1408
- tide_io.writebidstsv(
1409
- f"{outputname}_desc-noiseregressor_timeseries",
1410
- tide_math.stdnormalize(resampnonosref_y),
1411
- 1.0 / fmritr,
1412
- columns=["resampled"],
1413
- append=False,
1414
- )
1415
- tide_io.writebidstsv(
1416
- f"{outputname}_desc-oversamplednoiseregressor_timeseries",
1417
- tide_math.stdnormalize(resampref_y),
1418
- oversampfreq,
1419
- columns=["oversampled"],
1420
- append=False,
1421
- )
1379
+ # construct refine temporal masks here
1380
+ optiondict["windowedrefinemasks"] = None
1422
1381
 
1423
1382
  (
1424
1383
  optiondict["kurtosis_reference_pass1"],
@@ -1459,16 +1418,21 @@ def rapidtide_main(argparsingfunc):
1459
1418
  # Set up for the delay finding/refinement passes
1460
1419
  ####################################################
1461
1420
  # initialize the Correlator
1462
- theCorrelator = tide_classes.Correlator(
1421
+ theCorrelator = tide_simFuncClasses.Correlator(
1463
1422
  Fs=oversampfreq,
1464
1423
  ncprefilter=theprefilter,
1465
1424
  negativegradient=optiondict["negativegradient"],
1466
1425
  detrendorder=optiondict["detrendorder"],
1426
+ filterinputdata=optiondict["filterinputdata"],
1467
1427
  windowfunc=optiondict["windowfunc"],
1468
1428
  corrweighting=optiondict["corrweighting"],
1469
1429
  corrpadding=optiondict["corrpadding"],
1470
1430
  debug=optiondict["debug"],
1471
1431
  )
1432
+ if optiondict["debug"]:
1433
+ print(
1434
+ f"calling setreftc during initialization with length {optiondict['oversampfactor'] * validtimepoints}"
1435
+ )
1472
1436
  theCorrelator.setreftc(
1473
1437
  np.zeros((optiondict["oversampfactor"] * validtimepoints), dtype=np.float64)
1474
1438
  )
@@ -1487,12 +1451,13 @@ def rapidtide_main(argparsingfunc):
1487
1451
  dummy, trimmedcorrscale, dummy = theCorrelator.getfunction()
1488
1452
 
1489
1453
  # initialize the MutualInformationator
1490
- theMutualInformationator = tide_classes.MutualInformationator(
1454
+ theMutualInformationator = tide_simFuncClasses.MutualInformationator(
1491
1455
  Fs=oversampfreq,
1492
1456
  smoothingtime=optiondict["smoothingtime"],
1493
1457
  ncprefilter=theprefilter,
1494
1458
  negativegradient=optiondict["negativegradient"],
1495
1459
  detrendorder=optiondict["detrendorder"],
1460
+ filterinputdata=optiondict["filterinputdata"],
1496
1461
  windowfunc=optiondict["windowfunc"],
1497
1462
  madnorm=False,
1498
1463
  lagmininpts=lagmininpts,
@@ -1523,6 +1488,7 @@ def rapidtide_main(argparsingfunc):
1523
1488
  1.0,
1524
1489
  starttime=0.0,
1525
1490
  columns=["corrtimes"],
1491
+ extraheaderinfo={"Description": "Trimmed correlation time axis"},
1526
1492
  append=False,
1527
1493
  )
1528
1494
  tide_io.writebidstsv(
@@ -1531,6 +1497,7 @@ def rapidtide_main(argparsingfunc):
1531
1497
  1.0,
1532
1498
  starttime=0.0,
1533
1499
  columns=["mitimes"],
1500
+ extraheaderinfo={"Description": "Trimmed cross mutual information time axis"},
1534
1501
  append=False,
1535
1502
  )
1536
1503
  tide_io.writebidstsv(
@@ -1539,6 +1506,7 @@ def rapidtide_main(argparsingfunc):
1539
1506
  1.0,
1540
1507
  starttime=0.0,
1541
1508
  columns=["corrtimes"],
1509
+ extraheaderinfo={"Description": "Correlation time axis"},
1542
1510
  append=False,
1543
1511
  )
1544
1512
  tide_io.writebidstsv(
@@ -1547,12 +1515,32 @@ def rapidtide_main(argparsingfunc):
1547
1515
  1.0,
1548
1516
  starttime=0.0,
1549
1517
  columns=["mitimes"],
1518
+ extraheaderinfo={"Description": "Cross mutual information time axis"},
1550
1519
  append=False,
1551
1520
  )
1552
- """
1553
- tide_io.writenpvecs(trimmedcorrscale, f"{outputname}_corrtimes.txt")
1554
- tide_io.writenpvecs(trimmedmiscale, f"{outputname}_mitimes.txt")
1555
- """
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
+ )
1556
1544
 
1557
1545
  # allocate all the data arrays
1558
1546
  tide_util.logmem("before main array allocation")
@@ -1565,14 +1553,36 @@ def rapidtide_main(argparsingfunc):
1565
1553
  fitmask = np.zeros(internalvalidspaceshape, dtype="uint16")
1566
1554
  failreason = np.zeros(internalvalidspaceshape, dtype="uint32")
1567
1555
  R2 = np.zeros(internalvalidspaceshape, dtype=rt_floattype)
1568
- outmaparray = np.zeros(internalspaceshape, dtype=rt_floattype)
1556
+ outmaparray = np.zeros((internalspaceshape), dtype=rt_floattype)
1569
1557
  tide_util.logmem("after main array allocation")
1570
1558
 
1571
- corroutlen = np.shape(trimmedcorrscale)[0]
1572
- 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":
1573
1583
  nativecorrshape = (xsize, corroutlen)
1574
1584
  else:
1575
- if fileiscifti:
1585
+ if theinputdata.filetype == "cifti":
1576
1586
  nativecorrshape = (1, 1, 1, corroutlen, numspatiallocs)
1577
1587
  else:
1578
1588
  nativecorrshape = (xsize, ysize, numslices, corroutlen)
@@ -1581,38 +1591,65 @@ def rapidtide_main(argparsingfunc):
1581
1591
  LGR.debug(
1582
1592
  f"allocating memory for correlation arrays {internalcorrshape} {internalvalidcorrshape}"
1583
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
+ )
1584
1619
  if optiondict["sharedmem"]:
1585
- corrout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1586
- gaussout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1587
- windowout, dummy, dummy = tide_util.allocshared(internalvalidcorrshape, rt_floatset)
1588
- outcorrarray, dummy, dummy = tide_util.allocshared(internalcorrshape, rt_floatset)
1620
+ ramlocation = "in shared memory"
1589
1621
  else:
1590
- corrout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1591
- gaussout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1592
- windowout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1593
- outcorrarray = np.zeros(internalcorrshape, dtype=rt_floattype)
1594
- tide_util.logmem("after correlation array allocation")
1622
+ ramlocation = "locally"
1595
1623
 
1596
- # prepare for fast resampling
1597
- padtime = (
1598
- max((-optiondict["lagmin"], optiondict["lagmax"]))
1599
- + 30.0
1600
- + np.abs(optiondict["offsettime"])
1601
- )
1602
- LGR.info(f"setting up fast resampling with padtime = {padtime}")
1603
- numpadtrs = int(padtime // fmritr)
1604
- padtime = fmritr * numpadtrs
1605
- genlagtc = tide_resample.FastResampler(reference_x, reference_y, padtime=padtime)
1606
- totalpadlen = validtimepoints + 2 * numpadtrs
1607
- paddedinitial_fmri_x = (
1608
- np.linspace(0.0, totalpadlen * fmritr, num=totalpadlen, endpoint=False)
1609
- + skiptime
1610
- - fmritr * numpadtrs
1624
+ optiondict["totalcorrelationbytes"] = (
1625
+ corrout.nbytes + gaussout.nbytes + windowout.nbytes + outcorrarray.nbytes
1611
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")
1630
+
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
1612
1649
 
1613
- if optiondict["textio"]:
1650
+ if theinputdata.filetype == "text":
1614
1651
  nativefmrishape = (xsize, np.shape(initial_fmri_x)[0])
1615
- elif fileiscifti:
1652
+ elif theinputdata.filetype == "cifti":
1616
1653
  nativefmrishape = (1, 1, 1, np.shape(initial_fmri_x)[0], numspatiallocs)
1617
1654
  else:
1618
1655
  nativefmrishape = (xsize, ysize, numslices, np.shape(initial_fmri_x)[0])
@@ -1624,37 +1661,132 @@ def rapidtide_main(argparsingfunc):
1624
1661
  2 * numpadtrs + np.shape(initial_fmri_x)[0],
1625
1662
  )
1626
1663
 
1664
+ # now do the arrays for delay refinement
1627
1665
  if (
1628
- optiondict["passes"] > 1
1629
- or optiondict["globalpreselect"]
1630
- or optiondict["convergencethresh"] is not None
1666
+ optiondict["dolinfitfilt"]
1667
+ or optiondict["docvrmap"]
1668
+ or optiondict["refinedelay"]
1669
+ or (optiondict["similaritymetric"] == "riptide")
1631
1670
  ):
1671
+ if optiondict["refinedelay"]:
1672
+ derivaxissize = np.max([2, optiondict["regressderivs"] + 1])
1673
+ else:
1674
+ derivaxissize = optiondict["regressderivs"] + 1
1675
+ internalvalidspaceshapederivs = (
1676
+ internalvalidspaceshape,
1677
+ derivaxissize,
1678
+ )
1679
+ sLFOfitmean, sLFOfitmean_shm = tide_util.allocarray(
1680
+ internalvalidspaceshape,
1681
+ rt_outfloattype,
1682
+ shared=optiondict["sharedmem"],
1683
+ name=f"sLFOfitmean_{optiondict['pid']}",
1684
+ )
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
+ )
1632
1715
  if optiondict["sharedmem"]:
1633
- shiftedtcs, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
1634
- weights, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
1635
- paddedshiftedtcs, dummy, dummy = tide_util.allocshared(
1636
- internalvalidpaddedfmrishape, rt_floatset
1637
- )
1638
- paddedweights, dummy, dummy = tide_util.allocshared(
1639
- internalvalidpaddedfmrishape, rt_floatset
1640
- )
1716
+ ramlocation = "in shared memory"
1641
1717
  else:
1642
- shiftedtcs = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
1643
- weights = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
1644
- paddedshiftedtcs, dummy, dummy = tide_util.allocshared(
1645
- internalvalidpaddedfmrishape, rt_floatset
1646
- )
1647
- paddedweights, dummy, dummy = tide_util.allocshared(
1648
- internalvalidpaddedfmrishape, rt_floatset
1649
- )
1650
- tide_util.logmem("after refinement array allocation")
1651
-
1652
- if optiondict["sharedmem"]:
1653
- outfmriarray, dummy, dummy = tide_util.allocshared(internalfmrishape, rt_floatset)
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")
1654
1731
  else:
1655
- outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
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
+ )
1656
1788
 
1657
- # cycle over all voxels
1789
+ # cycle over all voxels
1658
1790
  refine = True
1659
1791
  LGR.verbose(f"refine is set to {refine}")
1660
1792
  optiondict["edgebufferfrac"] = max(
@@ -1662,8 +1794,8 @@ def rapidtide_main(argparsingfunc):
1662
1794
  )
1663
1795
  LGR.verbose(f"edgebufferfrac set to {optiondict['edgebufferfrac']}")
1664
1796
 
1665
- # intitialize the correlation fitter
1666
- thefitter = tide_classes.SimilarityFunctionFitter(
1797
+ # initialize the correlation fitter
1798
+ theFitter = tide_simFuncClasses.SimilarityFunctionFitter(
1667
1799
  lagmod=optiondict["lagmod"],
1668
1800
  lthreshval=optiondict["lthreshval"],
1669
1801
  uthreshval=optiondict["uthreshval"],
@@ -1684,11 +1816,6 @@ def rapidtide_main(argparsingfunc):
1684
1816
  if optiondict["echocancel"]:
1685
1817
  LGR.info("\n\nEcho cancellation")
1686
1818
  TimingLGR.info("Echo cancellation start")
1687
- calcsimilaritypass_func = addmemprofiling(
1688
- tide_calcsimfunc.correlationpass,
1689
- optiondict["memprofile"],
1690
- "before correlationpass",
1691
- )
1692
1819
 
1693
1820
  referencetc = tide_math.corrnormalize(
1694
1821
  resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
@@ -1696,12 +1823,12 @@ def rapidtide_main(argparsingfunc):
1696
1823
  windowfunc=optiondict["windowfunc"],
1697
1824
  )
1698
1825
 
1699
- disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
1826
+ tide_util.disablemkl(optiondict["nprocs_calcsimilarity"], debug=optiondict["threaddebug"])
1700
1827
  (
1701
1828
  voxelsprocessed_echo,
1702
1829
  theglobalmaxlist,
1703
1830
  trimmedcorrscale,
1704
- ) = calcsimilaritypass_func(
1831
+ ) = tide_calcsimfunc.correlationpass(
1705
1832
  fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1706
1833
  referencetc,
1707
1834
  theCorrelator,
@@ -1717,10 +1844,9 @@ def rapidtide_main(argparsingfunc):
1717
1844
  interptype=optiondict["interptype"],
1718
1845
  showprogressbar=optiondict["showprogressbar"],
1719
1846
  chunksize=optiondict["mp_chunksize"],
1720
- rt_floatset=rt_floatset,
1721
1847
  rt_floattype=rt_floattype,
1722
1848
  )
1723
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
1849
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
1724
1850
 
1725
1851
  for i in range(len(theglobalmaxlist)):
1726
1852
  theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
@@ -1741,13 +1867,13 @@ def rapidtide_main(argparsingfunc):
1741
1867
  # Now find and regress out the echo
1742
1868
  echooffset, echoratio = tide_stats.echoloc(np.asarray(theglobalmaxlist), len(corrscale))
1743
1869
  LGR.info(f"Echooffset, echoratio: {echooffset} {echoratio}")
1744
- echoremovedtc, echofit, echoR = echocancel(
1870
+ echoremovedtc, echofit, echoR2 = echocancel(
1745
1871
  resampref_y, echooffset, oversamptr, outputname, numpadtrs
1746
1872
  )
1747
1873
  optiondict["echooffset"] = echooffset
1748
1874
  optiondict["echoratio"] = echoratio
1749
1875
  optiondict["echofit"] = [echofit[0, 0], echofit[0, 1]]
1750
- optiondict["echofitR"] = echoR
1876
+ optiondict["echofitR2"] = echoR2
1751
1877
  resampref_y = echoremovedtc
1752
1878
  TimingLGR.info(
1753
1879
  "Echo cancellation calculation end",
@@ -1756,6 +1882,32 @@ def rapidtide_main(argparsingfunc):
1756
1882
  "message3": "voxels",
1757
1883
  },
1758
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
+ )
1759
1911
 
1760
1912
  # --------------------- Main pass loop ---------------------
1761
1913
  # loop over all passes
@@ -1770,6 +1922,19 @@ def rapidtide_main(argparsingfunc):
1770
1922
  optiondict["currentstage"] = "preprocessingdone"
1771
1923
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
1772
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
+
1773
1938
  ####################################################
1774
1939
  # Start the iterative fit and refinement
1775
1940
  ####################################################
@@ -1782,6 +1947,10 @@ def rapidtide_main(argparsingfunc):
1782
1947
  LGR.info("\n\n*********************")
1783
1948
  LGR.info(f"Pass number {thepass}")
1784
1949
 
1950
+ # fetch the pass options
1951
+ if len(optiondict["passoptions"]) >= thepass:
1952
+ setpassoptions(optiondict["passoptions"][thepass - 1], optiondict)
1953
+
1785
1954
  referencetc = tide_math.corrnormalize(
1786
1955
  resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
1787
1956
  detrendorder=optiondict["detrendorder"],
@@ -1789,244 +1958,56 @@ def rapidtide_main(argparsingfunc):
1789
1958
  )
1790
1959
 
1791
1960
  # Step -1 - check the regressor for periodic components in the passband
1792
- dolagmod = True
1793
- doreferencenotch = True
1794
- if optiondict["respdelete"]:
1795
- resptracker = tide_classes.FrequencyTracker(nperseg=64)
1796
- thetimes, thefreqs = resptracker.track(resampref_y, 1.0 / oversamptr)
1797
- tide_io.writevec(thefreqs, f"{outputname}_peakfreaks_pass{thepass}.txt")
1798
- resampref_y = resptracker.clean(resampref_y, 1.0 / oversamptr, thetimes, thefreqs)
1799
- tide_io.writevec(resampref_y, f"{outputname}_respfilt_pass{thepass}.txt")
1800
- referencetc = tide_math.corrnormalize(
1801
- resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1],
1802
- detrendorder=optiondict["detrendorder"],
1803
- windowfunc=optiondict["windowfunc"],
1804
- )
1805
- if optiondict["noisetimecoursespec"] is not None:
1806
- # align the noise signal with referencetc
1807
- (
1808
- shiftednoise,
1809
- optiondict[f"noisedelay_pass{thepass}"],
1810
- optiondict[f"noisecorr_pass{thepass}"],
1811
- dummy,
1812
- ) = tide_corr.aligntcwithref(
1813
- resampref_y,
1814
- resampnoise_y,
1815
- oversampfreq,
1816
- zerooutbadfit=False,
1817
- verbose=True,
1818
- )
1819
- LGR.info(
1820
- "Maximum correlation amplitude with noise regressor is "
1821
- + str(optiondict[f"noisecorr_pass{thepass}"])
1822
- + " at "
1823
- + str(optiondict[f"noisedelay_pass{thepass}"])
1824
- )
1825
-
1826
- # regress out
1827
- resampref_y, datatoremove, R, dummy = tide_fit.glmfilt(
1828
- resampref_y, shiftednoise, debug=True
1829
- )
1830
-
1831
- # save
1832
- tide_io.writebidstsv(
1833
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1834
- shiftednoise,
1835
- 1.0 / oversamptr,
1836
- starttime=0.0,
1837
- columns=[f"shiftednoise_pass{thepass}"],
1838
- append=(thepass > 1),
1839
- )
1840
- tide_io.writebidstsv(
1841
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1842
- datatoremove,
1843
- 1.0 / oversamptr,
1844
- starttime=0.0,
1845
- columns=[f"removed_pass{thepass}"],
1846
- append=True,
1847
- )
1848
- tide_io.writebidstsv(
1849
- f"{outputname}_desc-regressornoiseremoval_timeseries",
1850
- resampref_y,
1851
- 1.0 / oversamptr,
1852
- starttime=0.0,
1853
- columns=[f"filtered_pass{thepass}"],
1854
- append=True,
1855
- )
1856
-
1857
- if optiondict["check_autocorrelation"]:
1858
- LGR.info("checking reference regressor autocorrelation properties")
1859
- optiondict["lagmod"] = 1000.0
1860
- lagindpad = corrorigin - 2 * np.max((lagmininpts, lagmaxinpts))
1861
- acmininpts = lagmininpts + lagindpad
1862
- acmaxinpts = lagmaxinpts + lagindpad
1863
- theCorrelator.setreftc(referencetc)
1864
- theCorrelator.setlimits(acmininpts, acmaxinpts)
1865
- thexcorr, accheckcorrscale, dummy = theCorrelator.run(
1866
- resampref_y[osvalidsimcalcstart : osvalidsimcalcend + 1]
1867
- )
1868
- thefitter.setcorrtimeaxis(accheckcorrscale)
1869
- (
1870
- dummy,
1871
- dummy,
1872
- dummy,
1873
- acwidth,
1874
- dummy,
1875
- dummy,
1876
- dummy,
1877
- dummy,
1878
- ) = tide_simfuncfit.onesimfuncfit(
1879
- thexcorr,
1880
- thefitter,
1881
- despeckle_thresh=optiondict["despeckle_thresh"],
1882
- lthreshval=optiondict["lthreshval"],
1883
- fixdelay=optiondict["fixdelay"],
1884
- rt_floatset=rt_floatset,
1885
- rt_floattype=rt_floattype,
1886
- )
1887
- tide_io.writebidstsv(
1888
- f"{outputname}_desc-autocorr_timeseries",
1889
- thexcorr,
1890
- 1.0 / (accheckcorrscale[1] - accheckcorrscale[0]),
1891
- starttime=accheckcorrscale[0],
1892
- extraheaderinfo={
1893
- "Description": "Autocorrelation of the probe regressor for each pass"
1894
- },
1895
- columns=[f"pass{thepass}"],
1896
- append=(thepass > 1),
1897
- )
1898
- thelagthresh = np.max((abs(optiondict["lagmin"]), abs(optiondict["lagmax"])))
1899
- theampthresh = 0.1
1900
- LGR.info(
1901
- f"searching for sidelobes with amplitude > {theampthresh} "
1902
- f"with abs(lag) < {thelagthresh} s"
1903
- )
1904
- sidelobetime, sidelobeamp = tide_corr.check_autocorrelation(
1905
- accheckcorrscale,
1906
- thexcorr,
1907
- acampthresh=theampthresh,
1908
- aclagthresh=thelagthresh,
1909
- detrendorder=optiondict["detrendorder"],
1910
- )
1911
- optiondict["acwidth"] = acwidth + 0.0
1912
- optiondict["absmaxsigma"] = acwidth * 10.0
1913
- passsuffix = "_pass" + str(thepass)
1914
- if sidelobetime is not None:
1915
- optiondict["acsidelobelag" + passsuffix] = sidelobetime
1916
- optiondict["despeckle_thresh"] = np.max(
1917
- [optiondict["despeckle_thresh"], sidelobetime / 2.0]
1918
- )
1919
- optiondict["acsidelobeamp" + passsuffix] = sidelobeamp
1920
- LGR.warning(
1921
- f"\n\nWARNING: check_autocorrelation found bad sidelobe at {sidelobetime} "
1922
- f"seconds ({1.0 / sidelobetime} Hz)..."
1923
- )
1924
- # bidsify
1925
- """tide_io.writebidstsv(
1926
- f"{outputname}_desc-movingregressor_timeseries",
1927
- tide_math.stdnormalize(resampnonosref_y),
1928
- 1.0 / fmritr,
1929
- columns=["pass1"],
1930
- append=False,
1931
- )"""
1932
- tide_io.writenpvecs(
1933
- np.array([sidelobetime]),
1934
- f"{outputname}_autocorr_sidelobetime" + passsuffix + ".txt",
1935
- )
1936
- if optiondict["fix_autocorrelation"]:
1937
- LGR.info("Removing sidelobe")
1938
- if dolagmod:
1939
- LGR.info("subjecting lag times to modulus")
1940
- optiondict["lagmod"] = sidelobetime / 2.0
1941
- if doreferencenotch:
1942
- LGR.info("removing spectral component at sidelobe frequency")
1943
- acstopfreq = 1.0 / sidelobetime
1944
- acfixfilter = tide_filt.NoncausalFilter(
1945
- debug=optiondict["debug"],
1946
- )
1947
- acfixfilter.settype("arb_stop")
1948
- acfixfilter.setfreqs(
1949
- acstopfreq * 0.9,
1950
- acstopfreq * 0.95,
1951
- acstopfreq * 1.05,
1952
- acstopfreq * 1.1,
1953
- )
1954
- cleaned_resampref_y = tide_math.corrnormalize(
1955
- acfixfilter.apply(1.0 / oversamptr, resampref_y),
1956
- windowfunc="None",
1957
- detrendorder=optiondict["detrendorder"],
1958
- )
1959
- cleaned_referencetc = tide_math.corrnormalize(
1960
- cleaned_resampref_y,
1961
- detrendorder=optiondict["detrendorder"],
1962
- windowfunc=optiondict["windowfunc"],
1963
- )
1964
- cleaned_nonosreferencetc = tide_math.stdnormalize(
1965
- acfixfilter.apply(fmrifreq, resampnonosref_y)
1966
- )
1967
- tide_io.writebidstsv(
1968
- f"{outputname}_desc-cleanedreferencefmrires_info",
1969
- cleaned_nonosreferencetc,
1970
- fmrifreq,
1971
- columns=[f"pass{thepass}"],
1972
- append=(thepass > 1),
1973
- )
1974
- tide_io.writebidstsv(
1975
- f"{outputname}_desc-cleanedreference_info",
1976
- cleaned_referencetc,
1977
- 1.0 / oversamptr,
1978
- columns=[f"pass{thepass}"],
1979
- append=(thepass > 1),
1980
- )
1981
- tide_io.writebidstsv(
1982
- f"{outputname}_desc-cleanedresamprefy_info",
1983
- cleaned_resampref_y,
1984
- 1.0 / oversamptr,
1985
- columns=[f"pass{thepass}"],
1986
- append=(thepass > 1),
1987
- )
1988
- else:
1989
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
1990
- resampref_y,
1991
- windowfunc="None",
1992
- detrendorder=optiondict["detrendorder"],
1993
- )
1994
- cleaned_referencetc = 1.0 * referencetc
1995
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
1996
- else:
1997
- LGR.info("no sidelobes found in range")
1998
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
1999
- resampref_y,
2000
- windowfunc="None",
2001
- detrendorder=optiondict["detrendorder"],
2002
- )
2003
- cleaned_referencetc = 1.0 * referencetc
2004
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
2005
- else:
2006
- cleaned_resampref_y = 1.0 * tide_math.corrnormalize(
2007
- 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=}"
2008
2003
  )
2009
- cleaned_referencetc = 1.0 * referencetc
2010
- cleaned_nonosreferencetc = 1.0 * resampnonosref_y
2011
2004
 
2012
2005
  # Step 0 - estimate significance
2013
2006
  if optiondict["numestreps"] > 0:
2014
2007
  TimingLGR.info(f"Significance estimation start, pass {thepass}")
2015
2008
  LGR.info(f"\n\nSignificance estimation, pass {thepass}")
2016
- getNullDistributionData_func = addmemprofiling(
2017
- tide_nullsimfunc.getNullDistributionDatax,
2018
- optiondict["memprofile"],
2019
- "before getnulldistristributiondata",
2020
- )
2021
2009
  if optiondict["checkpoint"]:
2022
2010
  # bidsify
2023
- """tide_io.writebidstsv(
2024
- f"{outputname}_desc-movingregressor_timeseries",
2025
- tide_math.stdnormalize(resampnonosref_y),
2026
- 1.0 / fmritr,
2027
- columns=["pass1"],
2028
- append=False,
2029
- )"""
2030
2011
  tide_io.writenpvecs(
2031
2012
  cleaned_referencetc,
2032
2013
  f"{outputname}_cleanedreference_pass" + str(thepass) + ".txt",
@@ -2040,34 +2021,36 @@ def rapidtide_main(argparsingfunc):
2040
2021
  f"{outputname}_options_pregetnull_pass" + str(thepass) + ".json",
2041
2022
  )
2042
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
+ )
2043
2028
  theCorrelator.setreftc(cleaned_resampref_y)
2044
2029
  theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
2045
2030
  theMutualInformationator.setreftc(cleaned_resampref_y)
2046
2031
  dummy, trimmedcorrscale, dummy = theCorrelator.getfunction()
2047
- thefitter.setcorrtimeaxis(trimmedcorrscale)
2048
- # add parallel path for mutualinformationator BBF
2032
+ theFitter.setcorrtimeaxis(trimmedcorrscale)
2033
+
2034
+ # parallel path for mutual information
2049
2035
  if optiondict["similaritymetric"] == "mutualinfo":
2050
2036
  theSimFunc = theMutualInformationator
2051
2037
  else:
2052
2038
  theSimFunc = theCorrelator
2053
- disablemkl(optiondict["nprocs_getNullDist"], debug=threaddebug)
2054
- simdistdata = getNullDistributionData_func(
2055
- cleaned_resampref_y,
2039
+ tide_util.disablemkl(optiondict["nprocs_getNullDist"], debug=optiondict["threaddebug"])
2040
+ simdistdata = tide_nullsimfunc.getNullDistributionData(
2056
2041
  oversampfreq,
2057
2042
  theSimFunc,
2058
- thefitter,
2043
+ theFitter,
2044
+ LGR,
2059
2045
  numestreps=optiondict["numestreps"],
2060
2046
  nprocs=optiondict["nprocs_getNullDist"],
2061
2047
  alwaysmultiproc=optiondict["alwaysmultiproc"],
2062
2048
  showprogressbar=optiondict["showprogressbar"],
2063
2049
  chunksize=optiondict["mp_chunksize"],
2064
2050
  permutationmethod=optiondict["permutationmethod"],
2065
- fixdelay=optiondict["fixdelay"],
2066
- fixeddelayvalue=optiondict["fixeddelayvalue"],
2067
- rt_floatset=np.float64,
2068
- rt_floattype="float64",
2051
+ rt_floattype=np.float64,
2069
2052
  )
2070
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2053
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
2071
2054
 
2072
2055
  tide_io.writebidstsv(
2073
2056
  f"{outputname}_desc-simdistdata_info",
@@ -2106,22 +2089,22 @@ def rapidtide_main(argparsingfunc):
2106
2089
  similaritymetric=optiondict["similaritymetric"],
2107
2090
  twotail=optiondict["bipolar"],
2108
2091
  nozero=optiondict["nohistzero"],
2109
- dosighistfit=optiondict["dosighistfit"],
2110
2092
  )
2093
+ if sigfit is None:
2094
+ optiondict["ampthreshfromsig"] = False
2111
2095
  if pcts is not None:
2112
2096
  for i in range(len(thepvalnames)):
2113
2097
  optiondict[
2114
2098
  "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_thresh.txt"
2115
2099
  ] = pcts[i]
2116
- if optiondict["dosighistfit"]:
2117
- optiondict[
2118
- "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_fitthresh"
2119
- ] = pcts_fit[i]
2120
- optiondict["sigfit"] = sigfit
2100
+ optiondict[
2101
+ "p_lt_" + thepvalnames[i] + "_pass" + str(thepass) + "_fitthresh"
2102
+ ] = pcts_fit[i]
2103
+ optiondict["sigfit"] = sigfit
2121
2104
  if optiondict["ampthreshfromsig"]:
2122
2105
  if pcts is not None:
2123
2106
  LGR.info(
2124
- 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"
2125
2108
  )
2126
2109
  optiondict["ampthresh"] = pcts[0]
2127
2110
  tide_stats.printthresholds(
@@ -2129,25 +2112,24 @@ def rapidtide_main(argparsingfunc):
2129
2112
  thepercentiles,
2130
2113
  "Crosscorrelation significance thresholds from data:",
2131
2114
  )
2132
- if optiondict["dosighistfit"]:
2133
- tide_stats.printthresholds(
2134
- pcts_fit,
2135
- thepercentiles,
2136
- "Crosscorrelation significance thresholds from fit:",
2137
- )
2138
- namesuffix = "_desc-nullsimfunc_hist"
2139
- tide_stats.makeandsavehistogram(
2140
- simdistdata,
2141
- optiondict["sighistlen"],
2142
- 0,
2143
- outputname + namesuffix,
2144
- displaytitle="Null correlation histogram",
2145
- refine=False,
2146
- dictvarname="nullsimfunchist_pass" + str(thepass),
2147
- therange=(0.0, 1.0),
2148
- append=(thepass > 1),
2149
- thedict=optiondict,
2150
- )
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
+ )
2151
2133
  else:
2152
2134
  LGR.info("leaving ampthresh unchanged")
2153
2135
  else:
@@ -2161,347 +2143,207 @@ def rapidtide_main(argparsingfunc):
2161
2143
  "message3": "repetitions",
2162
2144
  },
2163
2145
  )
2164
-
2165
2146
  # write out the current version of the run options
2166
2147
  optiondict["currentstage"] = f"precorrelation_pass{thepass}"
2167
2148
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
2168
2149
 
2169
- # Step 1 - Correlation step
2170
- if optiondict["similaritymetric"] == "mutualinfo":
2171
- similaritytype = "Mutual information"
2172
- elif optiondict["similaritymetric"] == "correlation":
2173
- similaritytype = "Correlation"
2174
- else:
2175
- similaritytype = "MI enhanced correlation"
2176
- LGR.info(f"\n\n{similaritytype} calculation, pass {thepass}")
2177
- TimingLGR.info(f"{similaritytype} calculation start, pass {thepass}")
2178
- calcsimilaritypass_func = addmemprofiling(
2179
- tide_calcsimfunc.correlationpass,
2180
- optiondict["memprofile"],
2181
- "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"],
2182
2198
  )
2183
-
2184
- disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
2185
- if optiondict["similaritymetric"] == "mutualinfo":
2186
- theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
2187
- (
2188
- voxelsprocessed_cp,
2189
- theglobalmaxlist,
2190
- trimmedcorrscale,
2191
- ) = calcsimilaritypass_func(
2192
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2193
- cleaned_referencetc,
2194
- theMutualInformationator,
2195
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2196
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2197
- lagmininpts,
2198
- lagmaxinpts,
2199
- corrout,
2200
- meanval,
2201
- nprocs=optiondict["nprocs_calcsimilarity"],
2202
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2203
- oversampfactor=optiondict["oversampfactor"],
2204
- interptype=optiondict["interptype"],
2205
- showprogressbar=optiondict["showprogressbar"],
2206
- chunksize=optiondict["mp_chunksize"],
2207
- rt_floatset=rt_floatset,
2208
- rt_floattype=rt_floattype,
2209
- )
2199
+ if optiondict["similaritymetric"] == "riptide":
2200
+ optiondict["despeckle_passes"] = 0
2201
+ fitcorrscale = riptidedelays
2210
2202
  else:
2211
- (
2212
- voxelsprocessed_cp,
2213
- theglobalmaxlist,
2214
- trimmedcorrscale,
2215
- ) = calcsimilaritypass_func(
2216
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2217
- cleaned_referencetc,
2218
- theCorrelator,
2219
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2220
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2221
- lagmininpts,
2222
- lagmaxinpts,
2223
- corrout,
2224
- meanval,
2225
- nprocs=optiondict["nprocs_calcsimilarity"],
2226
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2227
- oversampfactor=optiondict["oversampfactor"],
2228
- interptype=optiondict["interptype"],
2229
- showprogressbar=optiondict["showprogressbar"],
2230
- chunksize=optiondict["mp_chunksize"],
2231
- rt_floatset=rt_floatset,
2232
- rt_floattype=rt_floattype,
2233
- )
2234
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2203
+ fitcorrscale = trimmedcorrscale
2235
2204
 
2236
- for i in range(len(theglobalmaxlist)):
2237
- theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
2238
- namesuffix = "_desc-globallag_hist"
2239
- tide_stats.makeandsavehistogram(
2240
- np.asarray(theglobalmaxlist),
2241
- len(corrscale),
2242
- 0,
2243
- outputname + namesuffix,
2244
- displaytitle="Histogram of lag times from global lag calculation",
2245
- therange=(corrscale[0], corrscale[-1]),
2246
- refine=False,
2247
- dictvarname="globallaghist_pass" + str(thepass),
2248
- append=(optiondict["echocancel"] or (thepass > 1)),
2249
- thedict=optiondict,
2250
- )
2251
-
2252
- if optiondict["checkpoint"]:
2253
- outcorrarray[:, :] = 0.0
2254
- outcorrarray[validvoxels, :] = corrout[:, :]
2255
- if optiondict["textio"]:
2256
- tide_io.writenpvecs(
2257
- outcorrarray.reshape(nativecorrshape),
2258
- f"{outputname}_corrout_prefit_pass" + str(thepass) + ".txt",
2259
- )
2260
- else:
2261
- savename = f"{outputname}_desc-corroutprefit_pass-" + str(thepass)
2262
- tide_io.savetonifti(outcorrarray.reshape(nativecorrshape), theheader, savename)
2263
-
2264
- TimingLGR.info(
2265
- f"{similaritytype} calculation end, pass {thepass}",
2266
- {
2267
- "message2": voxelsprocessed_cp,
2268
- "message3": "voxels",
2269
- },
2270
- )
2271
-
2272
- # Step 1b. Do a peak prefit
2273
- if optiondict["similaritymetric"] == "hybrid":
2274
- LGR.info(f"\n\nPeak prefit calculation, pass {thepass}")
2275
- TimingLGR.info(f"Peak prefit calculation start, pass {thepass}")
2276
- peakevalpass_func = addmemprofiling(
2277
- tide_peakeval.peakevalpass,
2278
- optiondict["memprofile"],
2279
- "before peakevalpass",
2280
- )
2281
-
2282
- disablemkl(optiondict["nprocs_peakeval"], debug=threaddebug)
2283
- voxelsprocessed_pe, thepeakdict = peakevalpass_func(
2284
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
2285
- cleaned_referencetc,
2286
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
2287
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
2288
- theMutualInformationator,
2289
- trimmedcorrscale,
2290
- corrout,
2291
- nprocs=optiondict["nprocs_peakeval"],
2292
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2293
- bipolar=optiondict["bipolar"],
2294
- oversampfactor=optiondict["oversampfactor"],
2295
- interptype=optiondict["interptype"],
2296
- showprogressbar=optiondict["showprogressbar"],
2297
- chunksize=optiondict["mp_chunksize"],
2298
- 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,
2299
2220
  rt_floattype=rt_floattype,
2221
+ cifti_hdr=theinputdata.cifti_hdr,
2300
2222
  )
2301
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2302
2223
 
2303
- TimingLGR.info(
2304
- f"Peak prefit end, pass {thepass}",
2305
- {
2306
- "message2": voxelsprocessed_pe,
2307
- "message3": "voxels",
2308
- },
2309
- )
2310
- mipeaks = lagtimes * 0.0
2311
- for i in range(numvalidspatiallocs):
2312
- if len(thepeakdict[str(i)]) > 0:
2313
- mipeaks[i] = thepeakdict[str(i)][0][0]
2314
- else:
2315
- thepeakdict = None
2316
-
2317
- # Step 2 - similarity function fitting and time lag estimation
2318
- # write out the current version of the run options
2319
- optiondict["currentstage"] = f"presimfuncfit_pass{thepass}"
2320
- tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
2321
- LGR.info(f"\n\nTime lag estimation pass {thepass}")
2322
- TimingLGR.info(f"Time lag estimation start, pass {thepass}")
2323
- fitcorr_func = addmemprofiling(
2324
- tide_simfuncfit.fitcorr, optiondict["memprofile"], "before fitcorr"
2325
- )
2326
- thefitter.setfunctype(optiondict["similaritymetric"])
2327
- thefitter.setcorrtimeaxis(trimmedcorrscale)
2328
-
2329
- # use initial lags if this is a hybrid fit
2330
- if optiondict["similaritymetric"] == "hybrid" and thepeakdict is not None:
2331
- initlags = mipeaks
2332
- else:
2333
- initlags = None
2334
-
2335
- disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2336
- voxelsprocessed_fc = fitcorr_func(
2337
- trimmedcorrscale,
2338
- 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,
2339
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,
2340
2251
  fitmask,
2341
- failreason,
2342
2252
  lagtimes,
2343
2253
  lagstrengths,
2344
2254
  lagsigma,
2345
- gaussout,
2346
- windowout,
2347
- R2,
2348
- despeckling=False,
2349
- peakdict=thepeakdict,
2350
- nprocs=optiondict["nprocs_fitcorr"],
2351
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2352
- fixdelay=optiondict["fixdelay"],
2353
- showprogressbar=optiondict["showprogressbar"],
2354
- chunksize=optiondict["mp_chunksize"],
2355
- despeckle_thresh=optiondict["despeckle_thresh"],
2356
- initiallags=initlags,
2357
- rt_floatset=rt_floatset,
2358
- 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,
2359
2265
  )
2360
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2361
2266
 
2362
- TimingLGR.info(
2363
- f"Time lag estimation end, pass {thepass}",
2364
- {
2365
- "message2": voxelsprocessed_fc,
2366
- "message3": "voxels",
2367
- },
2368
- )
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
2369
2272
 
2370
- # Step 2b - Correlation time despeckle
2371
- if optiondict["despeckle_passes"] > 0:
2372
- LGR.info(f"\n\n{similaritytype} despeckling pass {thepass}")
2373
- LGR.info(f"\tUsing despeckle_thresh = {optiondict['despeckle_thresh']:.3f}")
2374
- TimingLGR.info(f"{similaritytype} despeckle start, pass {thepass}")
2375
-
2376
- # find lags that are very different from their neighbors, and refit starting at the median lag for the point
2377
- voxelsprocessed_fc_ds = 0
2378
- despecklingdone = False
2379
- for despecklepass in range(optiondict["despeckle_passes"]):
2380
- LGR.info(f"\n\n{similaritytype} despeckling subpass {despecklepass + 1}")
2381
- outmaparray *= 0.0
2382
- outmaparray[validvoxels] = eval("lagtimes")[:]
2383
- medianlags = ndimage.median_filter(
2384
- outmaparray.reshape(nativespaceshape), 3
2385
- ).reshape(numspatiallocs)
2386
- # voxels that we're happy with have initlags set to -1000000.0
2387
- initlags = np.where(
2388
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2389
- medianlags,
2390
- -1000000.0,
2391
- )[validvoxels]
2392
- if len(initlags) > 0:
2393
- if len(np.where(initlags != -1000000.0)[0]) > 0:
2394
- disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2395
- voxelsprocessed_thispass = fitcorr_func(
2396
- trimmedcorrscale,
2397
- thefitter,
2398
- corrout,
2399
- fitmask,
2400
- failreason,
2401
- lagtimes,
2402
- lagstrengths,
2403
- lagsigma,
2404
- gaussout,
2405
- windowout,
2406
- R2,
2407
- despeckling=True,
2408
- peakdict=thepeakdict,
2409
- nprocs=optiondict["nprocs_fitcorr"],
2410
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2411
- fixdelay=optiondict["fixdelay"],
2412
- showprogressbar=optiondict["showprogressbar"],
2413
- chunksize=optiondict["mp_chunksize"],
2414
- despeckle_thresh=optiondict["despeckle_thresh"],
2415
- initiallags=initlags,
2416
- rt_floatset=rt_floatset,
2417
- rt_floattype=rt_floattype,
2418
- )
2419
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2420
-
2421
- voxelsprocessed_fc_ds += voxelsprocessed_thispass
2422
- optiondict[
2423
- "despecklemasksize_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2424
- ] = voxelsprocessed_thispass
2425
- optiondict[
2426
- "despecklemaskpct_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2427
- ] = (100.0 * voxelsprocessed_thispass / optiondict["corrmasksize"])
2428
- else:
2429
- despecklingdone = True
2430
- else:
2431
- despecklingdone = True
2432
- if despecklingdone:
2433
- LGR.info("Nothing left to do! Terminating despeckling")
2434
- break
2435
-
2436
- internaldespeckleincludemask = np.where(
2437
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2438
- medianlags,
2439
- 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"],
2440
2318
  )
2441
- if optiondict["savedespecklemasks"] and (optiondict["despeckle_passes"] > 0):
2442
- despecklesavemask = np.where(
2443
- 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,
2444
2338
  )
2445
- if thepass == optiondict["passes"]:
2446
- if not optiondict["textio"]:
2447
- if fileiscifti:
2448
- timeindex = theheader["dim"][0] - 1
2449
- spaceindex = theheader["dim"][0]
2450
- theheader["dim"][timeindex] = 1
2451
- theheader["dim"][spaceindex] = numspatiallocs
2452
- else:
2453
- theheader["dim"][0] = 3
2454
- theheader["dim"][4] = 1
2455
- theheader["pixdim"][4] = 1.0
2456
- masklist = [
2457
- (
2458
- despecklesavemask,
2459
- "despeckle",
2460
- "mask",
2461
- None,
2462
- "Voxels that underwent despeckling in the final pass",
2463
- )
2464
- ]
2465
- tide_io.savemaplist(
2466
- outputname,
2467
- masklist,
2468
- validvoxels,
2469
- nativespaceshape,
2470
- theheader,
2471
- bidsbasedict,
2472
- textio=optiondict["textio"],
2473
- fileiscifti=fileiscifti,
2474
- rt_floattype=rt_floattype,
2475
- cifti_hdr=cifti_hdr,
2476
- )
2477
- LGR.info(
2478
- f"\n\n{voxelsprocessed_fc_ds} voxels despeckled in "
2479
- f"{optiondict['despeckle_passes']} passes"
2480
- )
2481
- TimingLGR.info(
2482
- f"{similaritytype} despeckle end, pass {thepass}",
2483
- {
2484
- "message2": voxelsprocessed_fc_ds,
2485
- "message3": "voxels",
2486
- },
2487
- )
2339
+
2488
2340
  # Step 2c - make a rank order map
2489
2341
  timepercentile = (
2490
2342
  100.0 * (rankdata(lagtimes, method="dense") - 1) / (numvalidspatiallocs - 1)
2491
2343
  )
2492
2344
 
2493
2345
  if optiondict["saveintermediatemaps"]:
2494
- if not optiondict["textio"]:
2495
- theheader = copy.deepcopy(nim_hdr)
2496
- if fileiscifti:
2497
- timeindex = theheader["dim"][0] - 1
2498
- spaceindex = theheader["dim"][0]
2499
- theheader["dim"][timeindex] = 1
2500
- theheader["dim"][spaceindex] = numspatiallocs
2501
- else:
2502
- theheader["dim"][0] = 3
2503
- theheader["dim"][4] = 1
2504
- theheader["pixdim"][4] = 1.0
2346
+ theheader = theinputdata.copyheader(numtimepoints=1)
2505
2347
  bidspasssuffix = f"_intermediatedata-pass{thepass}"
2506
2348
  maplist = [
2507
2349
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
@@ -2522,10 +2364,9 @@ def rapidtide_main(argparsingfunc):
2522
2364
  nativespaceshape,
2523
2365
  theheader,
2524
2366
  bidsbasedict,
2525
- textio=optiondict["textio"],
2526
- fileiscifti=fileiscifti,
2367
+ filetype=theinputdata.filetype,
2527
2368
  rt_floattype=rt_floattype,
2528
- cifti_hdr=cifti_hdr,
2369
+ cifti_hdr=theinputdata.cifti_hdr,
2529
2370
  )
2530
2371
 
2531
2372
  # Step 3 - regressor refinement for next pass
@@ -2535,370 +2376,41 @@ def rapidtide_main(argparsingfunc):
2535
2376
  if (
2536
2377
  thepass < optiondict["passes"]
2537
2378
  or optiondict["convergencethresh"] is not None
2538
- or optiondict["globalpreselect"]
2379
+ or optiondict["initregressorpreselect"]
2380
+ or optiondict["dofinalrefine"]
2539
2381
  ):
2540
- LGR.info(f"\n\nRegressor refinement, pass {thepass}")
2541
- TimingLGR.info(f"Regressor refinement start, pass {thepass}")
2542
- if optiondict["refineoffset"]:
2543
- # check that we won't end up excluding all voxels from offset calculation before accepting mask
2544
- offsetmask = np.uint16(fitmask)
2545
- if internaloffsetincludemask_valid is not None:
2546
- offsetmask[np.where(internaloffsetincludemask_valid == 0)] = 0
2547
- if internaloffsetexcludemask_valid is not None:
2548
- offsetmask[np.where(internaloffsetexcludemask_valid != 0.0)] = 0
2549
- if tide_stats.getmasksize(offsetmask) == 0:
2550
- LGR.warning(
2551
- "NB: cannot exclude voxels from offset calculation mask - including for this pass"
2552
- )
2553
- offsetmask = fitmask
2554
-
2555
- peaklag, dummy, dummy = tide_stats.gethistprops(
2556
- lagtimes[np.where(offsetmask > 0)],
2557
- optiondict["histlen"],
2558
- pickleft=optiondict["pickleft"],
2559
- peakthresh=optiondict["pickleftthresh"],
2560
- )
2561
- optiondict["offsettime"] = peaklag
2562
- optiondict["offsettime_total"] += peaklag
2563
- optiondict[f"offsettime_pass{thepass}"] = optiondict["offsettime"]
2564
- optiondict[f"offsettime_total_pass{thepass}"] = optiondict["offsettime_total"]
2565
- LGR.info(
2566
- f"offset time set to {optiondict['offsettime']:.3f}, "
2567
- f"total is {optiondict['offsettime_total']:.3f}"
2568
- )
2569
-
2570
- if optiondict["refinedespeckled"] or (optiondict["despeckle_passes"] == 0):
2571
- # if refinedespeckled is true, or there is no despeckling, masks are unaffected
2572
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2573
- else:
2574
- # if refinedespeckled is false and there is despeckling, need to make a proper mask
2575
- if internalrefineexcludemask_valid is None:
2576
- # if there is currently no exclude mask, set exclude mask = despeckle mask
2577
- thisinternalrefineexcludemask_valid = np.where(
2578
- internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2579
- )
2580
- else:
2581
- # if there is a current exclude mask, add any voxels that are being despeckled
2582
- thisinternalrefineexcludemask_valid = np.where(
2583
- internalrefineexcludemask_valid > 0, 1, 0
2584
- )
2585
- thisinternalrefineexcludemask_valid[
2586
- np.where(internaldespeckleincludemask[validvoxels] != 0.0)
2587
- ] = 1
2588
-
2589
- # now check that we won't end up excluding all voxels from refinement before accepting mask
2590
- overallmask = np.uint16(fitmask)
2591
- if internalrefineincludemask_valid is not None:
2592
- overallmask[np.where(internalrefineincludemask_valid == 0)] = 0
2593
- if thisinternalrefineexcludemask_valid is not None:
2594
- overallmask[np.where(thisinternalrefineexcludemask_valid != 0.0)] = 0
2595
- if tide_stats.getmasksize(overallmask) == 0:
2596
- LGR.warning(
2597
- "NB: cannot exclude despeckled voxels from refinement - including for this pass"
2598
- )
2599
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2600
-
2601
- # regenerate regressor for next pass
2602
- # create the refinement mask
2603
- LGR.info("making refine mask")
2604
- (
2605
- dummy,
2606
- refinemask,
2607
- locationfails,
2608
- ampfails,
2609
- lagfails,
2610
- sigmafails,
2611
- numinmask,
2612
- ) = tide_refine.makerefinemask(
2613
- lagstrengths,
2614
- lagtimes,
2615
- lagsigma,
2616
- fitmask,
2617
- offsettime=optiondict["offsettime"],
2618
- ampthresh=optiondict["ampthresh"],
2619
- lagmaskside=optiondict["lagmaskside"],
2620
- lagminthresh=optiondict["lagminthresh"],
2621
- lagmaxthresh=optiondict["lagmaxthresh"],
2622
- sigmathresh=optiondict["sigmathresh"],
2623
- cleanrefined=optiondict["cleanrefined"],
2624
- bipolar=optiondict["bipolar"],
2625
- includemask=internalrefineincludemask_valid,
2626
- excludemask=thisinternalrefineexcludemask_valid,
2627
- )
2628
-
2629
- if numinmask == 0:
2630
- LGR.critical("No voxels in refine mask - adjust thresholds or external masks")
2631
- sys.exit()
2632
-
2633
- # align timecourses to prepare for refinement
2634
- alignvoxels_func = addmemprofiling(
2635
- tide_refine.alignvoxels,
2636
- optiondict["memprofile"],
2637
- "before aligning voxel timecourses",
2638
- )
2639
- LGR.info("aligning timecourses")
2640
- disablemkl(optiondict["nprocs_refine"], debug=threaddebug)
2641
- voxelsprocessed_rra = alignvoxels_func(
2642
- fmri_data_valid,
2643
- fmritr,
2644
- shiftedtcs,
2645
- weights,
2646
- paddedshiftedtcs,
2647
- paddedweights,
2648
- lagtimes,
2649
- refinemask,
2650
- nprocs=optiondict["nprocs_refine"],
2651
- detrendorder=optiondict["detrendorder"],
2652
- offsettime=optiondict["offsettime"],
2653
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2654
- showprogressbar=optiondict["showprogressbar"],
2655
- chunksize=optiondict["mp_chunksize"],
2656
- padtrs=numpadtrs,
2657
- rt_floatset=rt_floatset,
2658
- rt_floattype=rt_floattype,
2659
- )
2660
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2661
- LGR.info(f"align complete: {voxelsprocessed_rra=}")
2662
-
2663
- LGR.info("prenormalizing timecourses")
2664
- tide_refine.prenorm(
2665
- paddedshiftedtcs,
2666
- refinemask,
2667
- lagtimes,
2668
- optiondict["lagmaxthresh"],
2669
- lagstrengths,
2670
- R2,
2671
- optiondict["refineprenorm"],
2672
- optiondict["refineweighting"],
2673
- )
2674
-
2675
- (
2676
- voxelsprocessed_rr,
2677
- paddedoutputdata,
2678
- ) = tide_refine.dorefine(
2679
- paddedshiftedtcs,
2680
- refinemask,
2681
- weights,
2682
- theprefilter,
2683
- fmritr,
2684
- thepass,
2685
- lagstrengths,
2686
- lagtimes,
2687
- optiondict["refinetype"],
2688
- optiondict["fmrifreq"],
2689
- optiondict["outputname"],
2690
- detrendorder=optiondict["detrendorder"],
2691
- pcacomponents=optiondict["pcacomponents"],
2692
- dodispersioncalc=optiondict["dodispersioncalc"],
2693
- dispersioncalc_lower=optiondict["dispersioncalc_lower"],
2694
- dispersioncalc_upper=optiondict["dispersioncalc_upper"],
2695
- dispersioncalc_step=optiondict["dispersioncalc_step"],
2696
- windowfunc=optiondict["windowfunc"],
2697
- cleanrefined=optiondict["cleanrefined"],
2698
- bipolar=optiondict["bipolar"],
2699
- debug=optiondict["debug"],
2700
- rt_floatset=rt_floatset,
2701
- rt_floattype=rt_floattype,
2702
- )
2703
- optiondict["refinemasksize_pass" + str(thepass)] = voxelsprocessed_rr
2704
- optiondict["refinemaskpct_pass" + str(thepass)] = (
2705
- 100.0 * voxelsprocessed_rr / optiondict["corrmasksize"]
2706
- )
2707
- optiondict["refinelocationfails_pass" + str(thepass)] = locationfails
2708
- optiondict["refineampfails_pass" + str(thepass)] = ampfails
2709
- optiondict["refinelagfails_pass" + str(thepass)] = lagfails
2710
- optiondict["refinesigmafails_pass" + str(thepass)] = sigmafails
2711
- if voxelsprocessed_rr > 0:
2712
- paddednormoutputdata = tide_math.stdnormalize(
2713
- theprefilter.apply(fmrifreq, paddedoutputdata)
2714
- )
2715
- outputdata = paddedoutputdata[numpadtrs:-numpadtrs]
2716
- normoutputdata = tide_math.stdnormalize(theprefilter.apply(fmrifreq, outputdata))
2717
- normunfilteredoutputdata = tide_math.stdnormalize(outputdata)
2718
- tide_io.writebidstsv(
2719
- f"{outputname}_desc-refinedmovingregressor_timeseries",
2720
- normunfilteredoutputdata,
2721
- 1.0 / fmritr,
2722
- columns=["unfiltered_pass" + str(thepass)],
2723
- extraheaderinfo={
2724
- "Description": "The raw and filtered probe regressor produced by the refinement procedure, at the time resolution of the data"
2725
- },
2726
- append=(thepass > 1),
2727
- )
2728
- tide_io.writebidstsv(
2729
- f"{outputname}_desc-refinedmovingregressor_timeseries",
2730
- normoutputdata,
2731
- 1.0 / fmritr,
2732
- columns=["filtered_pass" + str(thepass)],
2733
- extraheaderinfo={
2734
- "Description": "The raw and filtered probe regressor produced by the refinement procedure, at the time resolution of the data"
2735
- },
2736
- append=True,
2737
- )
2738
-
2739
- # check for convergence
2740
- regressormse = mse(normoutputdata, previousnormoutputdata)
2741
- optiondict["regressormse_pass" + str(thepass).zfill(2)] = regressormse
2742
- LGR.info(f"regressor difference at end of pass {thepass:d} is {regressormse:.6f}")
2743
- if optiondict["convergencethresh"] is not None:
2744
- if thepass >= optiondict["maxpasses"]:
2745
- LGR.info("refinement ended (maxpasses reached)")
2746
- stoprefining = True
2747
- refinestopreason = "maxpassesreached"
2748
- elif regressormse < optiondict["convergencethresh"]:
2749
- LGR.info("refinement ended (refinement has converged")
2750
- stoprefining = True
2751
- refinestopreason = "convergence"
2752
- else:
2753
- stoprefining = False
2754
- elif thepass >= optiondict["passes"]:
2755
- stoprefining = True
2756
- refinestopreason = "passesreached"
2757
- else:
2758
- stoprefining = False
2759
-
2760
- if optiondict["detrendorder"] > 0:
2761
- resampnonosref_y = tide_fit.detrend(
2762
- tide_resample.doresample(
2763
- paddedinitial_fmri_x,
2764
- paddednormoutputdata,
2765
- initial_fmri_x,
2766
- method=optiondict["interptype"],
2767
- ),
2768
- order=optiondict["detrendorder"],
2769
- demean=optiondict["dodemean"],
2770
- )
2771
- resampref_y = tide_fit.detrend(
2772
- tide_resample.doresample(
2773
- paddedinitial_fmri_x,
2774
- paddednormoutputdata,
2775
- os_fmri_x,
2776
- method=optiondict["interptype"],
2777
- ),
2778
- order=optiondict["detrendorder"],
2779
- demean=optiondict["dodemean"],
2780
- )
2781
- else:
2782
- resampnonosref_y = tide_resample.doresample(
2783
- paddedinitial_fmri_x,
2784
- paddednormoutputdata,
2785
- initial_fmri_x,
2786
- method=optiondict["interptype"],
2787
- )
2788
- resampref_y = tide_resample.doresample(
2789
- paddedinitial_fmri_x,
2790
- paddednormoutputdata,
2791
- os_fmri_x,
2792
- method=optiondict["interptype"],
2793
- )
2794
- if optiondict["tincludemaskname"] is not None:
2795
- resampnonosref_y *= tmask_y
2796
- thefit, R = tide_fit.mlregress(tmask_y, resampnonosref_y)
2797
- resampnonosref_y -= thefit[0, 1] * tmask_y
2798
- resampref_y *= tmaskos_y
2799
- thefit, R = tide_fit.mlregress(tmaskos_y, resampref_y)
2800
- resampref_y -= thefit[0, 1] * tmaskos_y
2801
-
2802
- # reinitialize genlagtc for resampling
2803
- previousnormoutputdata = normoutputdata + 0.0
2804
- genlagtc = tide_resample.FastResampler(
2805
- paddedinitial_fmri_x, paddednormoutputdata, padtime=padtime
2806
- )
2807
- genlagtc.save(f"{outputname}_desc-lagtcgenerator_timeseries")
2808
- (
2809
- optiondict[f"kurtosis_reference_pass{thepass + 1}"],
2810
- optiondict[f"kurtosisz_reference_pass{thepass + 1}"],
2811
- optiondict[f"kurtosisp_reference_pass{thepass + 1}"],
2812
- ) = tide_stats.kurtosisstats(resampref_y)
2813
- (
2814
- optiondict[f"skewness_reference_pass{thepass + 1}"],
2815
- optiondict[f"skewnessz_reference_pass{thepass + 1}"],
2816
- optiondict[f"skewnessp_reference_pass{thepass + 1}"],
2817
- ) = tide_stats.skewnessstats(resampref_y)
2818
- if not stoprefining:
2819
- tide_io.writebidstsv(
2820
- f"{outputname}_desc-movingregressor_timeseries",
2821
- tide_math.stdnormalize(resampnonosref_y),
2822
- 1.0 / fmritr,
2823
- columns=["pass" + str(thepass + 1)],
2824
- extraheaderinfo={
2825
- "Description": "The probe regressor used in each pass, at the time resolution of the data"
2826
- },
2827
- append=True,
2828
- )
2829
- tide_io.writebidstsv(
2830
- f"{outputname}_desc-oversampledmovingregressor_timeseries",
2831
- tide_math.stdnormalize(resampref_y),
2832
- oversampfreq,
2833
- columns=["pass" + str(thepass + 1)],
2834
- extraheaderinfo={
2835
- "Description": "The probe regressor used in each pass, at the time resolution used for calculating the similarity function"
2836
- },
2837
- append=True,
2838
- )
2839
- else:
2840
- LGR.warning(f"refinement failed - terminating at end of pass {thepass}")
2841
- stoprefining = True
2842
- refinestopreason = "emptymask"
2843
-
2844
- TimingLGR.info(
2845
- f"Regressor refinement end, pass {thepass}",
2846
- {
2847
- "message2": voxelsprocessed_rr,
2848
- "message3": "voxels",
2849
- },
2850
- )
2851
- if optiondict["saveintermediatemaps"]:
2852
- if not optiondict["textio"]:
2853
- theheader = copy.deepcopy(nim_hdr)
2854
- if fileiscifti:
2855
- timeindex = theheader["dim"][0] - 1
2856
- spaceindex = theheader["dim"][0]
2857
- theheader["dim"][timeindex] = 1
2858
- theheader["dim"][spaceindex] = numspatiallocs
2859
- else:
2860
- theheader["dim"][0] = 3
2861
- theheader["dim"][4] = 1
2862
- theheader["pixdim"][4] = 1.0
2863
- bidspasssuffix = f"_intermediatedata-pass{thepass}"
2864
- maplist = [
2865
- (fitmask, "corrfit", "mask", None, "Voxels where correlation value was fit"),
2866
- (
2867
- failreason,
2868
- "corrfitfailreason",
2869
- "info",
2870
- None,
2871
- "Result codes for correlation fit",
2872
- ),
2873
- ]
2874
- if optiondict["savedespecklemasks"] and (optiondict["despeckle_passes"] > 0):
2875
- maplist.append(
2876
- (
2877
- despecklesavemask,
2878
- "despecklemask",
2879
- "map",
2880
- None,
2881
- "Voxels that underwent despeckling",
2882
- )
2883
- )
2884
- if thepass < optiondict["passes"]:
2885
- maplist.append(
2886
- (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,
2887
2410
  )
2888
- tide_io.savemaplist(
2889
- f"{outputname}{bidspasssuffix}",
2890
- maplist,
2891
- validvoxels,
2892
- nativespaceshape,
2893
- theheader,
2894
- bidsbasedict,
2895
- textio=optiondict["textio"],
2896
- fileiscifti=fileiscifti,
2897
- rt_floattype=rt_floattype,
2898
- cifti_hdr=cifti_hdr,
2899
2411
  )
2412
+ # End of main pass loop
2900
2413
 
2901
- # We are done with refinement.
2902
2414
  if optiondict["convergencethresh"] is None:
2903
2415
  optiondict["actual_passes"] = optiondict["passes"]
2904
2416
  else:
@@ -2948,10 +2460,10 @@ def rapidtide_main(argparsingfunc):
2948
2460
  coherencefreqstep,
2949
2461
  coherencefreqaxissize,
2950
2462
  ) = theCoherer.getaxisinfo()
2951
- if optiondict["textio"]:
2463
+ if theinputdata.filetype == "text":
2952
2464
  nativecoherenceshape = (xsize, coherencefreqaxissize)
2953
2465
  else:
2954
- if fileiscifti:
2466
+ if theinputdata.filetype == "cifti":
2955
2467
  nativecoherenceshape = (1, 1, 1, coherencefreqaxissize, numspatiallocs)
2956
2468
  else:
2957
2469
  nativecoherenceshape = (xsize, ysize, numslices, coherencefreqaxissize)
@@ -2959,30 +2471,36 @@ def rapidtide_main(argparsingfunc):
2959
2471
  internalvalidcoherenceshape = (numvalidspatiallocs, coherencefreqaxissize)
2960
2472
 
2961
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
+ )
2962
2492
  if optiondict["sharedmem"]:
2963
- coherencefunc, dummy, dummy = tide_util.allocshared(
2964
- internalvalidcoherenceshape, rt_outfloatset
2965
- )
2966
- coherencepeakval, dummy, dummy = tide_util.allocshared(
2967
- numvalidspatiallocs, rt_outfloatset
2968
- )
2969
- coherencepeakfreq, dummy, dummy = tide_util.allocshared(
2970
- numvalidspatiallocs, rt_outfloatset
2971
- )
2493
+ ramlocation = "in shared memory"
2972
2494
  else:
2973
- coherencefunc = np.zeros(internalvalidcoherenceshape, dtype=rt_outfloattype)
2974
- coherencepeakval, dummy, dummy = tide_util.allocshared(
2975
- numvalidspatiallocs, rt_outfloatset
2976
- )
2977
- coherencepeakfreq = np.zeros(numvalidspatiallocs, dtype=rt_outfloattype)
2978
-
2979
- coherencepass_func = addmemprofiling(
2980
- tide_calccoherence.coherencepass,
2981
- optiondict["memprofile"],
2982
- "before coherencepass",
2495
+ ramlocation = "locally"
2496
+ optiondict["totalcoherencebytes"] = (
2497
+ coherencefunc.nbytes + coherencepeakval.nbytes + coherencepeakfreq.nbytes
2983
2498
  )
2984
- disablemkl(1, debug=threaddebug)
2985
- 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(
2986
2504
  fmri_data_valid,
2987
2505
  theCoherer,
2988
2506
  coherencefunc,
@@ -2991,27 +2509,17 @@ def rapidtide_main(argparsingfunc):
2991
2509
  alt=True,
2992
2510
  showprogressbar=optiondict["showprogressbar"],
2993
2511
  chunksize=optiondict["mp_chunksize"],
2994
- nprocs=1,
2512
+ nprocs=optiondict["nprocs"],
2995
2513
  alwaysmultiproc=optiondict["alwaysmultiproc"],
2996
- rt_floatset=rt_floatset,
2997
- rt_floattype=rt_floattype,
2998
2514
  )
2999
- enablemkl(optiondict["mklthreads"], debug=threaddebug)
2515
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
3000
2516
 
3001
2517
  # save the results of the calculations
3002
- if not optiondict["textio"]:
3003
- theheader = copy.deepcopy(nim_hdr)
3004
- theheader["toffset"] = coherencefreqstart
3005
- theheader["pixdim"][4] = coherencefreqstep
3006
- if fileiscifti:
3007
- timeindex = theheader["dim"][0] - 1
3008
- spaceindex = theheader["dim"][0]
3009
- theheader["dim"][timeindex] = coherencefreqaxissize
3010
- theheader["dim"][spaceindex] = numspatiallocs
3011
- else:
3012
- theheader["dim"][0] = 3
3013
- theheader["dim"][4] = coherencefreqaxissize
3014
- theheader["pixdim"][4] = 1.0
2518
+ theheader = theinputdata.copyheader(
2519
+ numtimepoints=coherencefreqaxissize,
2520
+ tr=coherencefreqstep,
2521
+ toffset=coherencefreqstart,
2522
+ )
3015
2523
  maplist = [(coherencefunc, "coherence", "info", None, "Coherence function")]
3016
2524
  tide_io.savemaplist(
3017
2525
  outputname,
@@ -3020,12 +2528,10 @@ def rapidtide_main(argparsingfunc):
3020
2528
  nativecoherenceshape,
3021
2529
  theheader,
3022
2530
  bidsbasedict,
3023
- textio=optiondict["textio"],
3024
- fileiscifti=fileiscifti,
2531
+ filetype=theinputdata.filetype,
3025
2532
  rt_floattype=rt_floattype,
3026
- cifti_hdr=cifti_hdr,
2533
+ cifti_hdr=theinputdata.cifti_hdr,
3027
2534
  )
3028
- del coherencefunc
3029
2535
 
3030
2536
  TimingLGR.info(
3031
2537
  "Coherence calculation end",
@@ -3041,29 +2547,35 @@ def rapidtide_main(argparsingfunc):
3041
2547
  LGR.info("\n\nWiener deconvolution")
3042
2548
 
3043
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
+ )
3044
2562
  if optiondict["sharedmem"]:
3045
- wienerdeconv, dummy, dummy = tide_util.allocshared(
3046
- internalvalidspaceshape, rt_outfloatset
3047
- )
3048
- wpeak, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
2563
+ ramlocation = "in shared memory"
3049
2564
  else:
3050
- wienerdeconv = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3051
- 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")
3052
2569
 
3053
- wienerpass_func = addmemprofiling(
3054
- tide_wiener.wienerpass,
3055
- optiondict["memprofile"],
3056
- "before wienerpass",
3057
- )
3058
- voxelsprocessed_wiener = wienerpass_func(
2570
+ voxelsprocessed_wiener = tide_wiener.wienerpass(
3059
2571
  numspatiallocs,
3060
2572
  fmri_data_valid,
3061
2573
  threshval,
2574
+ lagtc,
3062
2575
  optiondict,
3063
2576
  wienerdeconv,
3064
2577
  wpeak,
3065
2578
  resampref_y,
3066
- rt_floatset=rt_floatset,
3067
2579
  rt_floattype=rt_floattype,
3068
2580
  )
3069
2581
  TimingLGR.info(
@@ -3073,56 +2585,60 @@ def rapidtide_main(argparsingfunc):
3073
2585
  "message3": "voxels",
3074
2586
  },
3075
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)
3076
2593
 
3077
2594
  ####################################################
3078
- # GLM filtering start
2595
+ # Linear regression filtering start
3079
2596
  ####################################################
3080
- # 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
3081
2598
  # write out the current version of the run options
3082
- optiondict["currentstage"] = "preglm"
2599
+ optiondict["currentstage"] = "presLFOfit"
3083
2600
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
3084
- if optiondict["doglmfilt"] or optiondict["docvrmap"]:
3085
- if optiondict["doglmfilt"]:
3086
- TimingLGR.info("GLM filtering start")
3087
- 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")
3088
2620
  else:
3089
- TimingLGR.info("CVR map generation start")
3090
- LGR.info("\n\nCVR mapping")
2621
+ TimingLGR.info("Setting up for delay refinement")
2622
+ LGR.info("\n\nDelay refinement setup")
3091
2623
  if (
3092
2624
  (optiondict["gausssigma"] > 0.0)
3093
- or (optiondict["glmsourcefile"] is not None)
2625
+ or (optiondict["denoisesourcefile"] is not None)
3094
2626
  or optiondict["docvrmap"]
3095
2627
  ):
3096
- if optiondict["glmsourcefile"] is not None:
3097
- LGR.info(f"reading in {optiondict['glmsourcefile']} for GLM filter, please wait")
3098
- sourcename = optiondict["glmsourcefile"]
3099
- else:
3100
- LGR.info(f"rereading {fmrifilename} for GLM filter, please wait")
3101
- sourcename = fmrifilename
3102
- if fileiscifti:
3103
- LGR.info("input file is CIFTI")
3104
- (
3105
- dummy,
3106
- cifti_hdr,
3107
- nim_data,
3108
- nim_hdr,
3109
- thedims,
3110
- thesizes,
3111
- dummy,
3112
- ) = tide_io.readfromcifti(sourcename)
3113
- else:
3114
- if optiondict["textio"]:
3115
- nim_data = tide_io.readvecs(sourcename)
3116
- else:
3117
- 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)
3118
2636
 
3119
- fmri_data_valid = (
3120
- nim_data.reshape((numspatiallocs, timepoints))[:, validstart : validend + 1]
3121
- )[validvoxels, :] + 0.0
2637
+ fmri_data_valid = theinputdata.validdata() + 0.0
3122
2638
 
3123
2639
  if optiondict["docvrmap"]:
3124
2640
  # percent normalize the fmri data
3125
- LGR.info("normalzing data for CVR map")
2641
+ LGR.info("normalizing data for CVR map")
3126
2642
  themean = np.mean(fmri_data_valid, axis=1)
3127
2643
  fmri_data_valid /= themean[:, None]
3128
2644
 
@@ -3138,78 +2654,58 @@ def rapidtide_main(argparsingfunc):
3138
2654
 
3139
2655
  # move fmri_data_valid into shared memory
3140
2656
  if optiondict["sharedmem"]:
2657
+ tide_util.cleanup_shm(fmri_data_valid_shm)
3141
2658
  LGR.info("moving fmri data to shared memory")
3142
2659
  TimingLGR.info("Start moving fmri_data to shared memory")
3143
- numpy2shared_func = addmemprofiling(
3144
- tide_util.numpy2shared,
3145
- optiondict["memprofile"],
3146
- "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']}",
3147
2664
  )
3148
- fmri_data_valid = numpy2shared_func(fmri_data_valid, rt_floatset)
3149
2665
  TimingLGR.info("End moving fmri_data to shared memory")
3150
- del nim_data
2666
+ theinputdata.unload()
3151
2667
 
3152
- # now allocate the arrays needed for GLM filtering
3153
- internalvalidspaceshapederivs = (
3154
- internalvalidspaceshape,
3155
- 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']}",
3156
2680
  )
3157
2681
  if optiondict["sharedmem"]:
3158
- glmmean, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3159
- rvalue, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3160
- r2value, dummy, dummy = tide_util.allocshared(internalvalidspaceshape, rt_outfloatset)
3161
- fitNorm, dummy, dummy = tide_util.allocshared(
3162
- internalvalidspaceshapederivs, rt_outfloatset
3163
- )
3164
- fitcoeff, dummy, dummy = tide_util.allocshared(
3165
- internalvalidspaceshapederivs, rt_outfloatset
3166
- )
3167
- movingsignal, dummy, dummy = tide_util.allocshared(
3168
- internalvalidfmrishape, rt_outfloatset
3169
- )
3170
- lagtc, dummy, dummy = tide_util.allocshared(internalvalidfmrishape, rt_floatset)
3171
- filtereddata, dummy, dummy = tide_util.allocshared(
3172
- internalvalidfmrishape, rt_outfloatset
3173
- )
2682
+ ramlocation = "in shared memory"
3174
2683
  else:
3175
- glmmean = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3176
- rvalue = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3177
- r2value = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
3178
- fitNorm = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
3179
- fitcoeff = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
3180
- movingsignal = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
3181
- lagtc = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
3182
- filtereddata = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
3183
-
3184
- if optiondict["memprofile"]:
3185
- if optiondict["doglmfilt"]:
3186
- memcheckpoint("about to start glm noise removal...")
3187
- else:
3188
- memcheckpoint("about to start CVR magnitude estimation...")
3189
- tide_util.logmem("before glm")
2684
+ ramlocation = "locally"
2685
+
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")
3190
2690
 
3191
- if optiondict["doglmfilt"]:
2691
+ if optiondict["dolinfitfilt"]:
3192
2692
  mode = "glm"
3193
- optiondict["glmthreshval"] = threshval
2693
+ optiondict["regressfiltthreshval"] = threshval
3194
2694
  else:
3195
2695
  # set the threshval to zero
3196
2696
  mode = "cvrmap"
3197
- optiondict["glmthreshval"] = 0.0
3198
- if optiondict["focaldebug"]:
3199
- # dump the fmri input file going to glm
3200
- if not optiondict["textio"]:
3201
- theheader = copy.deepcopy(nim_hdr)
3202
- if fileiscifti:
3203
- timeindex = theheader["dim"][0] - 1
3204
- spaceindex = theheader["dim"][0]
3205
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
3206
- theheader["dim"][spaceindex] = numspatiallocs
3207
- else:
3208
- theheader["dim"][4] = np.shape(outfmriarray)[1]
3209
- 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
+ )
3210
2706
  else:
3211
2707
  theheader = None
3212
- cifti_hdr = None
2708
+ outfmriarray = None
3213
2709
 
3214
2710
  maplist = [
3215
2711
  (
@@ -3217,7 +2713,7 @@ def rapidtide_main(argparsingfunc):
3217
2713
  "datatofilter",
3218
2714
  "bold",
3219
2715
  None,
3220
- "fMRI data that will be subjected to GLM filtering",
2716
+ "fMRI data that will be subjected to sLFO filtering",
3221
2717
  ),
3222
2718
  ]
3223
2719
  tide_io.savemaplist(
@@ -3227,76 +2723,278 @@ def rapidtide_main(argparsingfunc):
3227
2723
  nativefmrishape,
3228
2724
  theheader,
3229
2725
  bidsbasedict,
3230
- textio=optiondict["textio"],
3231
- fileiscifti=fileiscifti,
2726
+ filetype=theinputdata.filetype,
3232
2727
  rt_floattype=rt_floattype,
3233
- cifti_hdr=cifti_hdr,
2728
+ cifti_hdr=theinputdata.cifti_hdr,
3234
2729
  )
2730
+ else:
2731
+ outfmriarray = None
3235
2732
 
3236
- # calculate the initial bandlimited mean normalized variance if we're going to filter the data
3237
- 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")
3238
2737
 
3239
- voxelsprocessed_glm, regressorset = tide_glmfrommaps.glmfrommaps(
3240
- fmri_data_valid,
3241
- validvoxels,
3242
- initial_fmri_x,
3243
- lagtimes,
3244
- fitmask,
3245
- genlagtc,
3246
- mode,
3247
- outputname,
3248
- oversamptr,
3249
- glmmean,
3250
- rvalue,
3251
- r2value,
3252
- fitNorm,
3253
- fitcoeff,
3254
- movingsignal,
3255
- lagtc,
3256
- filtereddata,
3257
- LGR,
3258
- TimingLGR,
3259
- optiondict["glmthreshval"],
3260
- optiondict["saveminimumglmfiles"],
3261
- nprocs_makelaggedtcs=optiondict["nprocs_makelaggedtcs"],
3262
- nprocs_glm=optiondict["nprocs_glm"],
3263
- glmderivs=optiondict["glmderivs"],
3264
- mp_chunksize=optiondict["mp_chunksize"],
3265
- showprogressbar=optiondict["showprogressbar"],
3266
- alwaysmultiproc=optiondict["alwaysmultiproc"],
3267
- memprofile=optiondict["memprofile"],
3268
- debug=optiondict["focaldebug"],
3269
- )
2738
+ if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
2739
+ # set gausssigma automatically
2740
+ optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
3270
2741
 
3271
- # calculate the final bandlimited mean normalized variance
3272
- finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
3273
- divlocs = np.where(finalvariance > 0.0)
3274
- varchange = initialvariance * 0.0
3275
- varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
3276
- 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
3277
2782
 
3278
- LGR.info("End filtering operation")
3279
- TimingLGR.info(
3280
- "GLM filtering end",
3281
- {
3282
- "message2": voxelsprocessed_glm,
3283
- "message3": "voxels",
3284
- },
3285
- )
3286
- if optiondict["memprofile"]:
3287
- memcheckpoint("...done")
3288
- tide_util.logmem("after glm filter")
3289
- 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("")
3290
2994
  else:
3291
- # get the original data to calculate the mean
3292
- pass
3293
- """LGR.info(f"rereading {fmrifilename} to calculate mean value, please wait")
3294
- if optiondict["textio"]:
3295
- nim_data = tide_io.readvecs(fmrifilename)
3296
- else:
3297
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(fmrifilename)"""
2995
+ outfmriarray = None
3298
2996
  ####################################################
3299
- # GLM filtering end
2997
+ # sLFO filtering end
3300
2998
  ####################################################
3301
2999
 
3302
3000
  # Post refinement step 2 - make and save interesting histograms
@@ -3334,24 +3032,24 @@ def rapidtide_main(argparsingfunc):
3334
3032
  thedict=optiondict,
3335
3033
  )
3336
3034
  namesuffix = "_desc-lfofilterR2_hist"
3337
- if optiondict["doglmfilt"]:
3035
+ if optiondict["dolinfitfilt"]:
3338
3036
  tide_stats.makeandsavehistogram(
3339
3037
  r2value[np.where(fitmask > 0)],
3340
3038
  optiondict["histlen"],
3341
3039
  1,
3342
3040
  outputname + namesuffix,
3343
- displaytitle="Histogram of GLM filter R2 values",
3041
+ displaytitle="Histogram of sLFO filter R2 values",
3344
3042
  dictvarname="R2hist",
3345
3043
  thedict=optiondict,
3346
3044
  )
3347
3045
  namesuffix = "_desc-lfofilterInbandVarianceChange_hist"
3348
- if optiondict["doglmfilt"]:
3046
+ if optiondict["dolinfitfilt"]:
3349
3047
  tide_stats.makeandsavehistogram(
3350
3048
  varchange[np.where(fitmask > 0)],
3351
3049
  optiondict["histlen"],
3352
3050
  1,
3353
3051
  outputname + namesuffix,
3354
- displaytitle="Histogram of percent of inband variance removed by GLM filter",
3052
+ displaytitle="Histogram of percent of inband variance removed by sLFO filter",
3355
3053
  dictvarname="varchangehist",
3356
3054
  thedict=optiondict,
3357
3055
  )
@@ -3365,6 +3063,10 @@ def rapidtide_main(argparsingfunc):
3365
3063
  lagstrengths[np.where(fitmask > 0)], histpcts, nozero=False
3366
3064
  )
3367
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
+ )
3368
3070
  for i in range(len(histpcts)):
3369
3071
  optiondict[f"lagtimes_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3370
3072
  thetimepcts[i]
@@ -3375,6 +3077,10 @@ def rapidtide_main(argparsingfunc):
3375
3077
  optiondict[f"lagsigma_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3376
3078
  thesigmapcts[i]
3377
3079
  )
3080
+ if optiondict["refinedelay"]:
3081
+ optiondict[
3082
+ f"lagtimesrefined_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"
3083
+ ] = therefinedtimepcts[i]
3378
3084
  optiondict["fitmasksize"] = np.sum(fitmask)
3379
3085
  optiondict["fitmaskpct"] = 100.0 * optiondict["fitmasksize"] / optiondict["corrmasksize"]
3380
3086
 
@@ -3384,21 +3090,7 @@ def rapidtide_main(argparsingfunc):
3384
3090
 
3385
3091
  # write the 3D maps that need to be remapped
3386
3092
  TimingLGR.info("Start saving maps")
3387
- if not optiondict["textio"]:
3388
- theheader = copy.deepcopy(nim_hdr)
3389
- if fileiscifti:
3390
- timeindex = theheader["dim"][0] - 1
3391
- spaceindex = theheader["dim"][0]
3392
- theheader["dim"][timeindex] = 1
3393
- theheader["dim"][spaceindex] = numspatiallocs
3394
- else:
3395
- theheader["dim"][0] = 3
3396
- theheader["dim"][4] = 1
3397
- theheader["pixdim"][4] = 1.0
3398
- else:
3399
- theheader = None
3400
- cifti_hdr = None
3401
-
3093
+ theheader = theinputdata.copyheader(numtimepoints=1)
3402
3094
  savelist = [
3403
3095
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
3404
3096
  (
@@ -3420,10 +3112,51 @@ def rapidtide_main(argparsingfunc):
3420
3112
  (fitmask, "corrfit", "mask", None, "Voxels where correlation value was fit"),
3421
3113
  (failreason, "corrfitfailreason", "info", None, "Result codes for correlation fit"),
3422
3114
  ]
3423
- MTT = np.square(lagsigma) - (optiondict["acwidth"] * optiondict["acwidth"])
3115
+ MTT = np.square(lagsigma) - 0.5 * (optiondict["acwidth"] * optiondict["acwidth"])
3424
3116
  MTT = np.where(MTT > 0.0, MTT, 0.0)
3425
3117
  MTT = np.sqrt(MTT)
3426
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
+ ]
3427
3160
  if optiondict["calccoherence"]:
3428
3161
  savelist += [
3429
3162
  (coherencepeakval, "coherencepeakval", "map", None, "Coherence peak value"),
@@ -3436,10 +3169,9 @@ def rapidtide_main(argparsingfunc):
3436
3169
  nativespaceshape,
3437
3170
  theheader,
3438
3171
  bidsbasedict,
3439
- textio=optiondict["textio"],
3440
- fileiscifti=fileiscifti,
3172
+ filetype=theinputdata.filetype,
3441
3173
  rt_floattype=rt_floattype,
3442
- cifti_hdr=cifti_hdr,
3174
+ cifti_hdr=theinputdata.cifti_hdr,
3443
3175
  )
3444
3176
  namesuffix = "_desc-MTT_hist"
3445
3177
  tide_stats.makeandsavehistogram(
@@ -3451,10 +3183,18 @@ def rapidtide_main(argparsingfunc):
3451
3183
  dictvarname="MTThist",
3452
3184
  thedict=optiondict,
3453
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)
3454
3194
 
3455
3195
  # write the optional 3D maps that need to be remapped
3456
- if optiondict["doglmfilt"] or optiondict["docvrmap"]:
3457
- if optiondict["doglmfilt"]:
3196
+ if optiondict["dolinfitfilt"] or optiondict["docvrmap"]:
3197
+ if optiondict["dolinfitfilt"]:
3458
3198
  maplist = [
3459
3199
  (
3460
3200
  initialvariance,
@@ -3477,23 +3217,30 @@ def rapidtide_main(argparsingfunc):
3477
3217
  "percent",
3478
3218
  "Change in inband variance after filtering, in percent",
3479
3219
  ),
3220
+ # (
3221
+ # lfofilteredmeanvalue,
3222
+ # "lfofilterMean",
3223
+ # "map",
3224
+ # None,
3225
+ # "Voxelwise mean of the sLFO filtered data",
3226
+ # ),
3480
3227
  ]
3481
- if optiondict["saveminimumglmfiles"]:
3228
+ if optiondict["saveminimumsLFOfiltfiles"]:
3482
3229
  maplist += [
3483
3230
  (
3484
3231
  r2value,
3485
3232
  "lfofilterR2",
3486
3233
  "map",
3487
3234
  None,
3488
- "Squared R value of the GLM fit (proportion of variance explained)",
3235
+ "Squared R value of the sLFO fit (proportion of variance explained)",
3489
3236
  ),
3490
3237
  ]
3491
- if optiondict["savenormalglmfiles"]:
3238
+ if optiondict["savenormalsLFOfiltfiles"]:
3492
3239
  maplist += [
3493
- (rvalue, "lfofilterR", "map", None, "R value of the GLM fit"),
3494
- (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"),
3495
3242
  ]
3496
- if optiondict["glmderivs"] > 0:
3243
+ if optiondict["regressderivs"] > 0:
3497
3244
  maplist += [
3498
3245
  (fitcoeff[:, 0], "lfofilterCoeff", "map", None, "Fit coefficient"),
3499
3246
  (
@@ -3504,7 +3251,7 @@ def rapidtide_main(argparsingfunc):
3504
3251
  "Normalized fit coefficient",
3505
3252
  ),
3506
3253
  ]
3507
- for thederiv in range(1, optiondict["glmderivs"] + 1):
3254
+ for thederiv in range(1, optiondict["regressderivs"] + 1):
3508
3255
  maplist += [
3509
3256
  (
3510
3257
  fitcoeff[:, thederiv],
@@ -3523,9 +3270,74 @@ def rapidtide_main(argparsingfunc):
3523
3270
  ]
3524
3271
  else:
3525
3272
  maplist += [
3526
- (fitcoeff, "lfofilterCoeff", "map", None, "Fit coefficient"),
3527
- (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
+ ),
3528
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
+ ]
3529
3341
  else:
3530
3342
  maplist = [
3531
3343
  (
@@ -3549,25 +3361,22 @@ def rapidtide_main(argparsingfunc):
3549
3361
  None,
3550
3362
  "Percentage of inband variance attributable to CVR regressor",
3551
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
+ ),
3552
3379
  ]
3553
- if optiondict["savenormalglmfiles"]:
3554
- maplist = [
3555
- (rvalue, "CVRR", "map", None, "R value of the GLM fit"),
3556
- (
3557
- r2value,
3558
- "CVRR2",
3559
- "map",
3560
- None,
3561
- "Squared R value of the GLM fit (proportion of variance explained)",
3562
- ),
3563
- (
3564
- fitcoeff,
3565
- "CVR",
3566
- "map",
3567
- "percent",
3568
- "Percent signal change due to the CVR regressor",
3569
- ),
3570
- ]
3571
3380
 
3572
3381
  tide_io.savemaplist(
3573
3382
  outputname,
@@ -3576,11 +3385,78 @@ def rapidtide_main(argparsingfunc):
3576
3385
  nativespaceshape,
3577
3386
  theheader,
3578
3387
  bidsbasedict,
3579
- textio=optiondict["textio"],
3580
- fileiscifti=fileiscifti,
3388
+ filetype=theinputdata.filetype,
3581
3389
  rt_floattype=rt_floattype,
3582
- cifti_hdr=cifti_hdr,
3390
+ cifti_hdr=theinputdata.cifti_hdr,
3583
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
3584
3460
  del rvalue
3585
3461
  del r2value
3586
3462
  del fitcoeff
@@ -3588,10 +3464,27 @@ def rapidtide_main(argparsingfunc):
3588
3464
  del initialvariance
3589
3465
  del finalvariance
3590
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)
3591
3473
 
3592
3474
  # write the 3D maps that don't need to be remapped
3475
+ if theinputdata.filetype != "nifti":
3476
+ unfiltmeanvalue = meanvalue
3593
3477
  maplist = [
3478
+ (
3479
+ unfiltmeanvalue,
3480
+ "unfiltmean",
3481
+ "map",
3482
+ None,
3483
+ "Voxelwise mean of fmri data before smoothing",
3484
+ ),
3594
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"),
3595
3488
  ]
3596
3489
  if brainmask is not None:
3597
3490
  maplist.append((brainmask, "brainmask", "mask", None, "Brain mask"))
@@ -3599,6 +3492,8 @@ def rapidtide_main(argparsingfunc):
3599
3492
  maplist.append((graymask, "GM", "mask", None, "Gray matter mask"))
3600
3493
  if whitemask is not None:
3601
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"))
3602
3497
  tide_io.savemaplist(
3603
3498
  outputname,
3604
3499
  maplist,
@@ -3606,29 +3501,38 @@ def rapidtide_main(argparsingfunc):
3606
3501
  nativespaceshape,
3607
3502
  theheader,
3608
3503
  bidsbasedict,
3609
- textio=optiondict["textio"],
3610
- fileiscifti=fileiscifti,
3504
+ filetype=theinputdata.filetype,
3611
3505
  rt_floattype=rt_floattype,
3612
- cifti_hdr=cifti_hdr,
3506
+ cifti_hdr=theinputdata.cifti_hdr,
3613
3507
  )
3614
3508
  del meanvalue
3509
+ del unfiltmeanvalue
3615
3510
 
3616
3511
  if optiondict["numestreps"] > 0:
3617
3512
  masklist = []
3618
- for i in range(0, len(thepercentiles)):
3619
- if optiondict["dosighistfit"]:
3620
- pmask = np.where(np.abs(lagstrengths) > pcts_fit[i], fitmask, 0 * fitmask)
3621
- else:
3622
- pmask = np.where(np.abs(lagstrengths) > pcts[i], fitmask, 0 * fitmask)
3623
- masklist += [
3624
- (
3625
- pmask.copy(),
3626
- f"plt{thepvalnames[i]}",
3627
- "mask",
3628
- None,
3629
- f"Voxels where the maxcorr value exceeds the p < {1.0 - thepercentiles[i]:.3f} significance level",
3630
- )
3631
- ]
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
+ ]
3632
3536
 
3633
3537
  tide_io.savemaplist(
3634
3538
  outputname,
@@ -3637,21 +3541,21 @@ def rapidtide_main(argparsingfunc):
3637
3541
  nativespaceshape,
3638
3542
  theheader,
3639
3543
  bidsbasedict,
3640
- textio=optiondict["textio"],
3641
- fileiscifti=fileiscifti,
3544
+ filetype=theinputdata.filetype,
3642
3545
  rt_floattype=rt_floattype,
3643
- cifti_hdr=cifti_hdr,
3546
+ cifti_hdr=theinputdata.cifti_hdr,
3644
3547
  )
3645
3548
  del masklist
3646
3549
 
3647
- if (optiondict["passes"] > 1 or optiondict["globalpreselect"]) and optiondict[
3550
+ if (optiondict["passes"] > 1 or optiondict["initregressorpreselect"]) and optiondict[
3648
3551
  "refinestopreason"
3649
3552
  ] != "emptymask":
3650
- if optiondict["globalpreselect"]:
3553
+ refinemask = theRegressorRefiner.getrefinemask()
3554
+ if optiondict["initregressorpreselect"]:
3651
3555
  masklist = [
3652
3556
  (
3653
3557
  refinemask,
3654
- "globalmeanpreselect",
3558
+ "initregressorpreselect",
3655
3559
  "mask",
3656
3560
  None,
3657
3561
  "I really don't know what this file is for",
@@ -3666,10 +3570,9 @@ def rapidtide_main(argparsingfunc):
3666
3570
  nativespaceshape,
3667
3571
  theheader,
3668
3572
  bidsbasedict,
3669
- textio=optiondict["textio"],
3670
- fileiscifti=fileiscifti,
3573
+ filetype=theinputdata.filetype,
3671
3574
  rt_floattype=rt_floattype,
3672
- cifti_hdr=cifti_hdr,
3575
+ cifti_hdr=theinputdata.cifti_hdr,
3673
3576
  )
3674
3577
  del refinemask
3675
3578
 
@@ -3681,20 +3584,18 @@ def rapidtide_main(argparsingfunc):
3681
3584
  del fitmask
3682
3585
 
3683
3586
  # now do the 4D maps of the similarity function and friends
3684
- if not optiondict["textio"]:
3685
- theheader = copy.deepcopy(nim_hdr)
3686
- theheader["toffset"] = corrscale[corrorigin - lagmininpts]
3687
- if fileiscifti:
3688
- timeindex = theheader["dim"][0] - 1
3689
- spaceindex = theheader["dim"][0]
3690
- theheader["dim"][timeindex] = np.shape(outcorrarray)[1]
3691
- theheader["dim"][spaceindex] = numspatiallocs
3692
- else:
3693
- theheader["dim"][4] = np.shape(outcorrarray)[1]
3694
- 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
+ )
3695
3593
  else:
3696
- theheader = None
3697
- cifti_hdr = None
3594
+ theheader = theinputdata.copyheader(
3595
+ numtimepoints=np.shape(outcorrarray)[1],
3596
+ tr=corrtr,
3597
+ toffset=(corrscale[corrorigin - lagmininpts]),
3598
+ )
3698
3599
 
3699
3600
  if (
3700
3601
  optiondict["savecorrout"]
@@ -3722,33 +3623,29 @@ def rapidtide_main(argparsingfunc):
3722
3623
  nativecorrshape,
3723
3624
  theheader,
3724
3625
  bidsbasedict,
3725
- textio=optiondict["textio"],
3726
- fileiscifti=fileiscifti,
3626
+ filetype=theinputdata.filetype,
3727
3627
  rt_floattype=rt_floattype,
3728
- cifti_hdr=cifti_hdr,
3628
+ cifti_hdr=theinputdata.cifti_hdr,
3729
3629
  )
3730
3630
  del windowout
3731
3631
  del gaussout
3732
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)
3733
3639
 
3734
3640
  # now save all the files that are of the same length as the input data file and masked
3735
- if not optiondict["textio"]:
3736
- theheader = copy.deepcopy(nim_hdr)
3737
- if fileiscifti:
3738
- timeindex = theheader["dim"][0] - 1
3739
- spaceindex = theheader["dim"][0]
3740
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
3741
- theheader["dim"][spaceindex] = numspatiallocs
3742
- else:
3743
- theheader["dim"][4] = np.shape(outfmriarray)[1]
3744
- theheader["pixdim"][4] = fmritr
3745
- else:
3746
- theheader = None
3747
- cifti_hdr = None
3748
-
3641
+ if outfmriarray is None:
3642
+ outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
3643
+ theheader = theinputdata.copyheader(numtimepoints=np.shape(outfmriarray)[1], tr=fmritr)
3749
3644
  maplist = []
3750
- if optiondict["saveallglmfiles"] and (optiondict["doglmfilt"] or optiondict["docvrmap"]):
3751
- if optiondict["glmderivs"] > 0:
3645
+ if optiondict["saveallsLFOfiltfiles"] and (
3646
+ optiondict["dolinfitfilt"] or optiondict["docvrmap"]
3647
+ ):
3648
+ if optiondict["regressderivs"] > 0:
3752
3649
  maplist += [
3753
3650
  (
3754
3651
  regressorset[:, :, 0],
@@ -3758,7 +3655,7 @@ def rapidtide_main(argparsingfunc):
3758
3655
  "Shifted sLFO regressor to filter",
3759
3656
  ),
3760
3657
  ]
3761
- for thederiv in range(1, optiondict["glmderivs"] + 1):
3658
+ for thederiv in range(1, optiondict["regressderivs"] + 1):
3762
3659
  maplist += [
3763
3660
  (
3764
3661
  regressorset[:, :, thederiv],
@@ -3773,11 +3670,11 @@ def rapidtide_main(argparsingfunc):
3773
3670
  (regressorset, "lfofilterEV", "bold", None, "Shifted sLFO regressor to filter"),
3774
3671
  ]
3775
3672
 
3776
- if optiondict["passes"] > 1:
3673
+ if (optiondict["passes"] > 1) or optiondict["dofinalrefine"]:
3777
3674
  if optiondict["savelagregressors"]:
3778
3675
  maplist += [
3779
3676
  (
3780
- paddedshiftedtcs[:, numpadtrs:-numpadtrs],
3677
+ (theRegressorRefiner.getpaddedshiftedtcs())[:, numpadtrs:-numpadtrs],
3781
3678
  "shiftedtcs",
3782
3679
  "bold",
3783
3680
  None,
@@ -3785,8 +3682,8 @@ def rapidtide_main(argparsingfunc):
3785
3682
  ),
3786
3683
  ]
3787
3684
 
3788
- if optiondict["doglmfilt"]:
3789
- if optiondict["saveminimumglmfiles"]:
3685
+ if optiondict["dolinfitfilt"]:
3686
+ if optiondict["saveminimumsLFOfiltfiles"]:
3790
3687
  maplist += [
3791
3688
  (
3792
3689
  filtereddata,
@@ -3807,6 +3704,27 @@ def rapidtide_main(argparsingfunc):
3807
3704
  ),
3808
3705
  ]
3809
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
+
3810
3728
  # save maps in the current output list
3811
3729
  if len(maplist) > 0:
3812
3730
  tide_io.savemaplist(
@@ -3816,20 +3734,22 @@ def rapidtide_main(argparsingfunc):
3816
3734
  nativefmrishape,
3817
3735
  theheader,
3818
3736
  bidsbasedict,
3819
- textio=optiondict["textio"],
3820
- fileiscifti=fileiscifti,
3737
+ filetype=theinputdata.filetype,
3821
3738
  rt_floattype=rt_floattype,
3822
- cifti_hdr=cifti_hdr,
3739
+ cifti_hdr=theinputdata.cifti_hdr,
3823
3740
  )
3824
3741
 
3825
3742
  # clean up
3826
3743
  if optiondict["passes"] > 1:
3827
- del paddedshiftedtcs
3828
- del shiftedtcs
3829
- if optiondict["doglmfilt"]:
3744
+ theRegressorRefiner.cleanup()
3745
+ if optiondict["dolinfitfilt"]:
3830
3746
  del lagtc
3831
3747
  del filtereddata
3832
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)
3833
3753
 
3834
3754
  TimingLGR.info("Finished saving maps")
3835
3755
  LGR.info("done")
@@ -3864,6 +3784,13 @@ def rapidtide_main(argparsingfunc):
3864
3784
  )
3865
3785
  Path(f"{outputname}_runtimings.tsv").unlink(missing_ok=True)
3866
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
+
3867
3794
  # do a final save of the options file
3868
3795
  optiondict["currentstage"] = "done"
3869
3796
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
@@ -3878,5 +3805,5 @@ def rapidtide_main(argparsingfunc):
3878
3805
  # delete the canary file
3879
3806
  Path(f"{outputname}_ISRUNNING.txt").unlink()
3880
3807
 
3881
- # created the finished file
3808
+ # create the finished file
3882
3809
  Path(f"{outputname}_DONE.txt").touch()