rapidtide 2.9.5__py3-none-any.whl → 3.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. cloud/gmscalc-HCPYA +1 -1
  2. cloud/mount-and-run +2 -0
  3. cloud/rapidtide-HCPYA +3 -3
  4. rapidtide/Colortables.py +538 -38
  5. rapidtide/OrthoImageItem.py +1094 -51
  6. rapidtide/RapidtideDataset.py +1709 -114
  7. rapidtide/__init__.py +0 -8
  8. rapidtide/_version.py +4 -4
  9. rapidtide/calccoherence.py +242 -97
  10. rapidtide/calcnullsimfunc.py +240 -140
  11. rapidtide/calcsimfunc.py +314 -129
  12. rapidtide/correlate.py +1211 -389
  13. rapidtide/data/examples/src/testLD +56 -0
  14. rapidtide/data/examples/src/test_findmaxlag.py +2 -2
  15. rapidtide/data/examples/src/test_mlregressallt.py +32 -17
  16. rapidtide/data/examples/src/testalign +1 -1
  17. rapidtide/data/examples/src/testatlasaverage +35 -7
  18. rapidtide/data/examples/src/testboth +21 -0
  19. rapidtide/data/examples/src/testcifti +11 -0
  20. rapidtide/data/examples/src/testdelayvar +13 -0
  21. rapidtide/data/examples/src/testdlfilt +25 -0
  22. rapidtide/data/examples/src/testfft +35 -0
  23. rapidtide/data/examples/src/testfileorfloat +37 -0
  24. rapidtide/data/examples/src/testfmri +94 -27
  25. rapidtide/data/examples/src/testfuncs +3 -3
  26. rapidtide/data/examples/src/testglmfilt +8 -6
  27. rapidtide/data/examples/src/testhappy +84 -51
  28. rapidtide/data/examples/src/testinitdelay +19 -0
  29. rapidtide/data/examples/src/testmodels +33 -0
  30. rapidtide/data/examples/src/testnewrefine +26 -0
  31. rapidtide/data/examples/src/testnoiseamp +21 -0
  32. rapidtide/data/examples/src/testppgproc +17 -0
  33. rapidtide/data/examples/src/testrefineonly +22 -0
  34. rapidtide/data/examples/src/testretro +26 -13
  35. rapidtide/data/examples/src/testretrolagtcs +16 -0
  36. rapidtide/data/examples/src/testrolloff +11 -0
  37. rapidtide/data/examples/src/testsimdata +45 -28
  38. rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
  39. rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
  40. rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
  41. rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
  42. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.png +0 -0
  43. rapidtide/data/models/model_cnn_pytorch_fulldata/loss.txt +1 -0
  44. rapidtide/data/models/model_cnn_pytorch_fulldata/model.pth +0 -0
  45. rapidtide/data/models/model_cnn_pytorch_fulldata/model_meta.json +80 -0
  46. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.png +0 -0
  47. rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.txt +1 -0
  48. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model.pth +0 -0
  49. rapidtide/data/models/model_cnnbp_pytorch_fullldata/model_meta.json +138 -0
  50. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.png +0 -0
  51. rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.txt +1 -0
  52. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model.pth +0 -0
  53. rapidtide/data/models/model_cnnfft_pytorch_fulldata/model_meta.json +128 -0
  54. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.png +0 -0
  55. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.txt +1 -0
  56. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model.pth +0 -0
  57. rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model_meta.json +49 -0
  58. rapidtide/data/models/model_revised_tf2/model.keras +0 -0
  59. rapidtide/data/models/{model_serdar → model_revised_tf2}/model_meta.json +1 -1
  60. rapidtide/data/models/model_serdar2_tf2/model.keras +0 -0
  61. rapidtide/data/models/{model_serdar2 → model_serdar2_tf2}/model_meta.json +1 -1
  62. rapidtide/data/models/model_serdar_tf2/model.keras +0 -0
  63. rapidtide/data/models/{model_revised → model_serdar_tf2}/model_meta.json +1 -1
  64. rapidtide/data/reference/HCP1200v2_MTT_2mm.nii.gz +0 -0
  65. rapidtide/data/reference/HCP1200v2_binmask_2mm.nii.gz +0 -0
  66. rapidtide/data/reference/HCP1200v2_csf_2mm.nii.gz +0 -0
  67. rapidtide/data/reference/HCP1200v2_gray_2mm.nii.gz +0 -0
  68. rapidtide/data/reference/HCP1200v2_graylaghist.json +7 -0
  69. rapidtide/data/reference/HCP1200v2_graylaghist.tsv.gz +0 -0
  70. rapidtide/data/reference/HCP1200v2_laghist.json +7 -0
  71. rapidtide/data/reference/HCP1200v2_laghist.tsv.gz +0 -0
  72. rapidtide/data/reference/HCP1200v2_mask_2mm.nii.gz +0 -0
  73. rapidtide/data/reference/HCP1200v2_maxcorr_2mm.nii.gz +0 -0
  74. rapidtide/data/reference/HCP1200v2_maxtime_2mm.nii.gz +0 -0
  75. rapidtide/data/reference/HCP1200v2_maxwidth_2mm.nii.gz +0 -0
  76. rapidtide/data/reference/HCP1200v2_negmask_2mm.nii.gz +0 -0
  77. rapidtide/data/reference/HCP1200v2_timepercentile_2mm.nii.gz +0 -0
  78. rapidtide/data/reference/HCP1200v2_white_2mm.nii.gz +0 -0
  79. rapidtide/data/reference/HCP1200v2_whitelaghist.json +7 -0
  80. rapidtide/data/reference/HCP1200v2_whitelaghist.tsv.gz +0 -0
  81. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2.xml +131 -0
  82. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_regions.txt +60 -0
  83. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_space-MNI152NLin6Asym_2mm.nii.gz +0 -0
  84. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm.nii.gz +0 -0
  85. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm_mask.nii.gz +0 -0
  86. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  87. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL2_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
  88. rapidtide/data/reference/MNI152_T1_1mm_Brain_FAST_seg.nii.gz +0 -0
  89. rapidtide/data/reference/MNI152_T1_1mm_Brain_Mask.nii.gz +0 -0
  90. rapidtide/data/reference/MNI152_T1_2mm_Brain_FAST_seg.nii.gz +0 -0
  91. rapidtide/data/reference/MNI152_T1_2mm_Brain_Mask.nii.gz +0 -0
  92. rapidtide/decorators.py +91 -0
  93. rapidtide/dlfilter.py +2553 -414
  94. rapidtide/dlfiltertorch.py +5201 -0
  95. rapidtide/externaltools.py +328 -13
  96. rapidtide/fMRIData_class.py +178 -0
  97. rapidtide/ffttools.py +168 -0
  98. rapidtide/filter.py +2704 -1462
  99. rapidtide/fit.py +2361 -579
  100. rapidtide/genericmultiproc.py +197 -0
  101. rapidtide/happy_supportfuncs.py +3255 -548
  102. rapidtide/helper_classes.py +590 -1181
  103. rapidtide/io.py +2569 -468
  104. rapidtide/linfitfiltpass.py +784 -0
  105. rapidtide/makelaggedtcs.py +267 -97
  106. rapidtide/maskutil.py +555 -25
  107. rapidtide/miscmath.py +867 -137
  108. rapidtide/multiproc.py +217 -44
  109. rapidtide/patchmatch.py +752 -0
  110. rapidtide/peakeval.py +32 -32
  111. rapidtide/ppgproc.py +2205 -0
  112. rapidtide/qualitycheck.py +353 -40
  113. rapidtide/refinedelay.py +854 -0
  114. rapidtide/refineregressor.py +939 -0
  115. rapidtide/resample.py +725 -204
  116. rapidtide/scripts/__init__.py +1 -0
  117. rapidtide/scripts/{adjustoffset → adjustoffset.py} +7 -2
  118. rapidtide/scripts/{aligntcs → aligntcs.py} +7 -2
  119. rapidtide/scripts/{applydlfilter → applydlfilter.py} +7 -2
  120. rapidtide/scripts/applyppgproc.py +28 -0
  121. rapidtide/scripts/{atlasaverage → atlasaverage.py} +7 -2
  122. rapidtide/scripts/{atlastool → atlastool.py} +7 -2
  123. rapidtide/scripts/{calcicc → calcicc.py} +7 -2
  124. rapidtide/scripts/{calctexticc → calctexticc.py} +7 -2
  125. rapidtide/scripts/{calcttest → calcttest.py} +7 -2
  126. rapidtide/scripts/{ccorrica → ccorrica.py} +7 -2
  127. rapidtide/scripts/delayvar.py +28 -0
  128. rapidtide/scripts/{diffrois → diffrois.py} +7 -2
  129. rapidtide/scripts/{endtidalproc → endtidalproc.py} +7 -2
  130. rapidtide/scripts/{fdica → fdica.py} +7 -2
  131. rapidtide/scripts/{filtnifti → filtnifti.py} +7 -2
  132. rapidtide/scripts/{filttc → filttc.py} +7 -2
  133. rapidtide/scripts/{fingerprint → fingerprint.py} +20 -16
  134. rapidtide/scripts/{fixtr → fixtr.py} +7 -2
  135. rapidtide/scripts/{gmscalc → gmscalc.py} +7 -2
  136. rapidtide/scripts/{happy → happy.py} +7 -2
  137. rapidtide/scripts/{happy2std → happy2std.py} +7 -2
  138. rapidtide/scripts/{happywarp → happywarp.py} +8 -4
  139. rapidtide/scripts/{histnifti → histnifti.py} +7 -2
  140. rapidtide/scripts/{histtc → histtc.py} +7 -2
  141. rapidtide/scripts/{glmfilt → linfitfilt.py} +7 -4
  142. rapidtide/scripts/{localflow → localflow.py} +7 -2
  143. rapidtide/scripts/{mergequality → mergequality.py} +7 -2
  144. rapidtide/scripts/{pairproc → pairproc.py} +7 -2
  145. rapidtide/scripts/{pairwisemergenifti → pairwisemergenifti.py} +7 -2
  146. rapidtide/scripts/{physiofreq → physiofreq.py} +7 -2
  147. rapidtide/scripts/{pixelcomp → pixelcomp.py} +7 -2
  148. rapidtide/scripts/{plethquality → plethquality.py} +7 -2
  149. rapidtide/scripts/{polyfitim → polyfitim.py} +7 -2
  150. rapidtide/scripts/{proj2flow → proj2flow.py} +7 -2
  151. rapidtide/scripts/{rankimage → rankimage.py} +7 -2
  152. rapidtide/scripts/{rapidtide → rapidtide.py} +7 -2
  153. rapidtide/scripts/{rapidtide2std → rapidtide2std.py} +7 -2
  154. rapidtide/scripts/{resamplenifti → resamplenifti.py} +7 -2
  155. rapidtide/scripts/{resampletc → resampletc.py} +7 -2
  156. rapidtide/scripts/retrolagtcs.py +28 -0
  157. rapidtide/scripts/retroregress.py +28 -0
  158. rapidtide/scripts/{roisummarize → roisummarize.py} +7 -2
  159. rapidtide/scripts/{runqualitycheck → runqualitycheck.py} +7 -2
  160. rapidtide/scripts/{showarbcorr → showarbcorr.py} +7 -2
  161. rapidtide/scripts/{showhist → showhist.py} +7 -2
  162. rapidtide/scripts/{showstxcorr → showstxcorr.py} +7 -2
  163. rapidtide/scripts/{showtc → showtc.py} +7 -2
  164. rapidtide/scripts/{showxcorr_legacy → showxcorr_legacy.py} +8 -8
  165. rapidtide/scripts/{showxcorrx → showxcorrx.py} +7 -2
  166. rapidtide/scripts/{showxy → showxy.py} +7 -2
  167. rapidtide/scripts/{simdata → simdata.py} +7 -2
  168. rapidtide/scripts/{spatialdecomp → spatialdecomp.py} +7 -2
  169. rapidtide/scripts/{spatialfit → spatialfit.py} +7 -2
  170. rapidtide/scripts/{spatialmi → spatialmi.py} +7 -2
  171. rapidtide/scripts/{spectrogram → spectrogram.py} +7 -2
  172. rapidtide/scripts/stupidramtricks.py +238 -0
  173. rapidtide/scripts/{synthASL → synthASL.py} +7 -2
  174. rapidtide/scripts/{tcfrom2col → tcfrom2col.py} +7 -2
  175. rapidtide/scripts/{tcfrom3col → tcfrom3col.py} +7 -2
  176. rapidtide/scripts/{temporaldecomp → temporaldecomp.py} +7 -2
  177. rapidtide/scripts/{testhrv → testhrv.py} +1 -1
  178. rapidtide/scripts/{threeD → threeD.py} +7 -2
  179. rapidtide/scripts/{tidepool → tidepool.py} +7 -2
  180. rapidtide/scripts/{variabilityizer → variabilityizer.py} +7 -2
  181. rapidtide/simFuncClasses.py +2113 -0
  182. rapidtide/simfuncfit.py +312 -108
  183. rapidtide/stats.py +579 -247
  184. rapidtide/tests/.coveragerc +27 -6
  185. rapidtide-2.9.5.data/scripts/fdica → rapidtide/tests/cleanposttest +4 -6
  186. rapidtide/tests/happycomp +9 -0
  187. rapidtide/tests/resethappytargets +1 -1
  188. rapidtide/tests/resetrapidtidetargets +1 -1
  189. rapidtide/tests/resettargets +1 -1
  190. rapidtide/tests/runlocaltest +3 -3
  191. rapidtide/tests/showkernels +1 -1
  192. rapidtide/tests/test_aliasedcorrelate.py +4 -4
  193. rapidtide/tests/test_aligntcs.py +1 -1
  194. rapidtide/tests/test_calcicc.py +1 -1
  195. rapidtide/tests/test_cleanregressor.py +184 -0
  196. rapidtide/tests/test_congrid.py +70 -81
  197. rapidtide/tests/test_correlate.py +1 -1
  198. rapidtide/tests/test_corrpass.py +4 -4
  199. rapidtide/tests/test_delayestimation.py +54 -59
  200. rapidtide/tests/test_dlfiltertorch.py +437 -0
  201. rapidtide/tests/test_doresample.py +2 -2
  202. rapidtide/tests/test_externaltools.py +69 -0
  203. rapidtide/tests/test_fastresampler.py +9 -5
  204. rapidtide/tests/test_filter.py +96 -57
  205. rapidtide/tests/test_findmaxlag.py +50 -19
  206. rapidtide/tests/test_fullrunhappy_v1.py +15 -10
  207. rapidtide/tests/test_fullrunhappy_v2.py +19 -13
  208. rapidtide/tests/test_fullrunhappy_v3.py +28 -13
  209. rapidtide/tests/test_fullrunhappy_v4.py +30 -11
  210. rapidtide/tests/test_fullrunhappy_v5.py +62 -0
  211. rapidtide/tests/test_fullrunrapidtide_v1.py +61 -7
  212. rapidtide/tests/test_fullrunrapidtide_v2.py +27 -15
  213. rapidtide/tests/test_fullrunrapidtide_v3.py +28 -8
  214. rapidtide/tests/test_fullrunrapidtide_v4.py +16 -8
  215. rapidtide/tests/test_fullrunrapidtide_v5.py +15 -6
  216. rapidtide/tests/test_fullrunrapidtide_v6.py +142 -0
  217. rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
  218. rapidtide/tests/test_fullrunrapidtide_v8.py +66 -0
  219. rapidtide/tests/test_getparsers.py +158 -0
  220. rapidtide/tests/test_io.py +59 -18
  221. rapidtide/tests/{test_glmpass.py → test_linfitfiltpass.py} +10 -10
  222. rapidtide/tests/test_mi.py +1 -1
  223. rapidtide/tests/test_miscmath.py +1 -1
  224. rapidtide/tests/test_motionregress.py +5 -5
  225. rapidtide/tests/test_nullcorr.py +6 -9
  226. rapidtide/tests/test_padvec.py +216 -0
  227. rapidtide/tests/test_parserfuncs.py +101 -0
  228. rapidtide/tests/test_phaseanalysis.py +1 -1
  229. rapidtide/tests/test_rapidtideparser.py +59 -53
  230. rapidtide/tests/test_refinedelay.py +296 -0
  231. rapidtide/tests/test_runmisc.py +5 -5
  232. rapidtide/tests/test_sharedmem.py +60 -0
  233. rapidtide/tests/test_simroundtrip.py +132 -0
  234. rapidtide/tests/test_simulate.py +1 -1
  235. rapidtide/tests/test_stcorrelate.py +4 -2
  236. rapidtide/tests/test_timeshift.py +2 -2
  237. rapidtide/tests/test_valtoindex.py +1 -1
  238. rapidtide/tests/test_zRapidtideDataset.py +5 -3
  239. rapidtide/tests/utils.py +10 -9
  240. rapidtide/tidepoolTemplate.py +88 -70
  241. rapidtide/tidepoolTemplate.ui +60 -46
  242. rapidtide/tidepoolTemplate_alt.py +88 -53
  243. rapidtide/tidepoolTemplate_alt.ui +62 -52
  244. rapidtide/tidepoolTemplate_alt_qt6.py +921 -0
  245. rapidtide/tidepoolTemplate_big.py +1125 -0
  246. rapidtide/tidepoolTemplate_big.ui +2386 -0
  247. rapidtide/tidepoolTemplate_big_qt6.py +1129 -0
  248. rapidtide/tidepoolTemplate_qt6.py +793 -0
  249. rapidtide/util.py +1389 -148
  250. rapidtide/voxelData.py +1048 -0
  251. rapidtide/wiener.py +138 -25
  252. rapidtide/wiener2.py +114 -8
  253. rapidtide/workflows/adjustoffset.py +107 -5
  254. rapidtide/workflows/aligntcs.py +86 -3
  255. rapidtide/workflows/applydlfilter.py +231 -89
  256. rapidtide/workflows/applyppgproc.py +540 -0
  257. rapidtide/workflows/atlasaverage.py +309 -48
  258. rapidtide/workflows/atlastool.py +130 -9
  259. rapidtide/workflows/calcSimFuncMap.py +490 -0
  260. rapidtide/workflows/calctexticc.py +202 -10
  261. rapidtide/workflows/ccorrica.py +123 -15
  262. rapidtide/workflows/cleanregressor.py +415 -0
  263. rapidtide/workflows/delayvar.py +1268 -0
  264. rapidtide/workflows/diffrois.py +84 -6
  265. rapidtide/workflows/endtidalproc.py +149 -9
  266. rapidtide/workflows/fdica.py +197 -17
  267. rapidtide/workflows/filtnifti.py +71 -4
  268. rapidtide/workflows/filttc.py +76 -5
  269. rapidtide/workflows/fitSimFuncMap.py +578 -0
  270. rapidtide/workflows/fixtr.py +74 -4
  271. rapidtide/workflows/gmscalc.py +116 -6
  272. rapidtide/workflows/happy.py +1242 -480
  273. rapidtide/workflows/happy2std.py +145 -13
  274. rapidtide/workflows/happy_parser.py +277 -59
  275. rapidtide/workflows/histnifti.py +120 -4
  276. rapidtide/workflows/histtc.py +85 -4
  277. rapidtide/workflows/{glmfilt.py → linfitfilt.py} +128 -14
  278. rapidtide/workflows/localflow.py +329 -29
  279. rapidtide/workflows/mergequality.py +80 -4
  280. rapidtide/workflows/niftidecomp.py +323 -19
  281. rapidtide/workflows/niftistats.py +178 -8
  282. rapidtide/workflows/pairproc.py +99 -5
  283. rapidtide/workflows/pairwisemergenifti.py +86 -3
  284. rapidtide/workflows/parser_funcs.py +1488 -56
  285. rapidtide/workflows/physiofreq.py +139 -12
  286. rapidtide/workflows/pixelcomp.py +211 -9
  287. rapidtide/workflows/plethquality.py +105 -23
  288. rapidtide/workflows/polyfitim.py +159 -19
  289. rapidtide/workflows/proj2flow.py +76 -3
  290. rapidtide/workflows/rankimage.py +115 -8
  291. rapidtide/workflows/rapidtide.py +1833 -1919
  292. rapidtide/workflows/rapidtide2std.py +101 -3
  293. rapidtide/workflows/rapidtide_parser.py +607 -372
  294. rapidtide/workflows/refineDelayMap.py +249 -0
  295. rapidtide/workflows/refineRegressor.py +1215 -0
  296. rapidtide/workflows/regressfrommaps.py +308 -0
  297. rapidtide/workflows/resamplenifti.py +86 -4
  298. rapidtide/workflows/resampletc.py +92 -4
  299. rapidtide/workflows/retrolagtcs.py +442 -0
  300. rapidtide/workflows/retroregress.py +1501 -0
  301. rapidtide/workflows/roisummarize.py +176 -7
  302. rapidtide/workflows/runqualitycheck.py +72 -7
  303. rapidtide/workflows/showarbcorr.py +172 -16
  304. rapidtide/workflows/showhist.py +87 -3
  305. rapidtide/workflows/showstxcorr.py +161 -4
  306. rapidtide/workflows/showtc.py +172 -10
  307. rapidtide/workflows/showxcorrx.py +250 -62
  308. rapidtide/workflows/showxy.py +186 -16
  309. rapidtide/workflows/simdata.py +418 -112
  310. rapidtide/workflows/spatialfit.py +83 -8
  311. rapidtide/workflows/spatialmi.py +252 -29
  312. rapidtide/workflows/spectrogram.py +306 -33
  313. rapidtide/workflows/synthASL.py +157 -6
  314. rapidtide/workflows/tcfrom2col.py +77 -3
  315. rapidtide/workflows/tcfrom3col.py +75 -3
  316. rapidtide/workflows/tidepool.py +3829 -666
  317. rapidtide/workflows/utils.py +45 -19
  318. rapidtide/workflows/utils_doc.py +293 -0
  319. rapidtide/workflows/variabilityizer.py +118 -5
  320. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/METADATA +30 -223
  321. rapidtide-3.1.3.dist-info/RECORD +393 -0
  322. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/WHEEL +1 -1
  323. rapidtide-3.1.3.dist-info/entry_points.txt +65 -0
  324. rapidtide-3.1.3.dist-info/top_level.txt +2 -0
  325. rapidtide/calcandfitcorrpairs.py +0 -262
  326. rapidtide/data/examples/src/testoutputsize +0 -45
  327. rapidtide/data/models/model_revised/model.h5 +0 -0
  328. rapidtide/data/models/model_serdar/model.h5 +0 -0
  329. rapidtide/data/models/model_serdar2/model.h5 +0 -0
  330. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm.nii.gz +0 -0
  331. rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  332. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm.nii.gz +0 -0
  333. rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm_mask.nii.gz +0 -0
  334. rapidtide/data/reference/HCP1200_binmask_2mm_2009c_asym.nii.gz +0 -0
  335. rapidtide/data/reference/HCP1200_lag_2mm_2009c_asym.nii.gz +0 -0
  336. rapidtide/data/reference/HCP1200_mask_2mm_2009c_asym.nii.gz +0 -0
  337. rapidtide/data/reference/HCP1200_negmask_2mm_2009c_asym.nii.gz +0 -0
  338. rapidtide/data/reference/HCP1200_sigma_2mm_2009c_asym.nii.gz +0 -0
  339. rapidtide/data/reference/HCP1200_strength_2mm_2009c_asym.nii.gz +0 -0
  340. rapidtide/glmpass.py +0 -434
  341. rapidtide/refine_factored.py +0 -641
  342. rapidtide/scripts/retroglm +0 -23
  343. rapidtide/workflows/glmfrommaps.py +0 -202
  344. rapidtide/workflows/retroglm.py +0 -643
  345. rapidtide-2.9.5.data/scripts/adjustoffset +0 -23
  346. rapidtide-2.9.5.data/scripts/aligntcs +0 -23
  347. rapidtide-2.9.5.data/scripts/applydlfilter +0 -23
  348. rapidtide-2.9.5.data/scripts/atlasaverage +0 -23
  349. rapidtide-2.9.5.data/scripts/atlastool +0 -23
  350. rapidtide-2.9.5.data/scripts/calcicc +0 -22
  351. rapidtide-2.9.5.data/scripts/calctexticc +0 -23
  352. rapidtide-2.9.5.data/scripts/calcttest +0 -22
  353. rapidtide-2.9.5.data/scripts/ccorrica +0 -23
  354. rapidtide-2.9.5.data/scripts/diffrois +0 -23
  355. rapidtide-2.9.5.data/scripts/endtidalproc +0 -23
  356. rapidtide-2.9.5.data/scripts/filtnifti +0 -23
  357. rapidtide-2.9.5.data/scripts/filttc +0 -23
  358. rapidtide-2.9.5.data/scripts/fingerprint +0 -593
  359. rapidtide-2.9.5.data/scripts/fixtr +0 -23
  360. rapidtide-2.9.5.data/scripts/glmfilt +0 -24
  361. rapidtide-2.9.5.data/scripts/gmscalc +0 -22
  362. rapidtide-2.9.5.data/scripts/happy +0 -25
  363. rapidtide-2.9.5.data/scripts/happy2std +0 -23
  364. rapidtide-2.9.5.data/scripts/happywarp +0 -350
  365. rapidtide-2.9.5.data/scripts/histnifti +0 -23
  366. rapidtide-2.9.5.data/scripts/histtc +0 -23
  367. rapidtide-2.9.5.data/scripts/localflow +0 -23
  368. rapidtide-2.9.5.data/scripts/mergequality +0 -23
  369. rapidtide-2.9.5.data/scripts/pairproc +0 -23
  370. rapidtide-2.9.5.data/scripts/pairwisemergenifti +0 -23
  371. rapidtide-2.9.5.data/scripts/physiofreq +0 -23
  372. rapidtide-2.9.5.data/scripts/pixelcomp +0 -23
  373. rapidtide-2.9.5.data/scripts/plethquality +0 -23
  374. rapidtide-2.9.5.data/scripts/polyfitim +0 -23
  375. rapidtide-2.9.5.data/scripts/proj2flow +0 -23
  376. rapidtide-2.9.5.data/scripts/rankimage +0 -23
  377. rapidtide-2.9.5.data/scripts/rapidtide +0 -23
  378. rapidtide-2.9.5.data/scripts/rapidtide2std +0 -23
  379. rapidtide-2.9.5.data/scripts/resamplenifti +0 -23
  380. rapidtide-2.9.5.data/scripts/resampletc +0 -23
  381. rapidtide-2.9.5.data/scripts/retroglm +0 -23
  382. rapidtide-2.9.5.data/scripts/roisummarize +0 -23
  383. rapidtide-2.9.5.data/scripts/runqualitycheck +0 -23
  384. rapidtide-2.9.5.data/scripts/showarbcorr +0 -23
  385. rapidtide-2.9.5.data/scripts/showhist +0 -23
  386. rapidtide-2.9.5.data/scripts/showstxcorr +0 -23
  387. rapidtide-2.9.5.data/scripts/showtc +0 -23
  388. rapidtide-2.9.5.data/scripts/showxcorr_legacy +0 -536
  389. rapidtide-2.9.5.data/scripts/showxcorrx +0 -23
  390. rapidtide-2.9.5.data/scripts/showxy +0 -23
  391. rapidtide-2.9.5.data/scripts/simdata +0 -23
  392. rapidtide-2.9.5.data/scripts/spatialdecomp +0 -23
  393. rapidtide-2.9.5.data/scripts/spatialfit +0 -23
  394. rapidtide-2.9.5.data/scripts/spatialmi +0 -23
  395. rapidtide-2.9.5.data/scripts/spectrogram +0 -23
  396. rapidtide-2.9.5.data/scripts/synthASL +0 -23
  397. rapidtide-2.9.5.data/scripts/tcfrom2col +0 -23
  398. rapidtide-2.9.5.data/scripts/tcfrom3col +0 -23
  399. rapidtide-2.9.5.data/scripts/temporaldecomp +0 -23
  400. rapidtide-2.9.5.data/scripts/threeD +0 -236
  401. rapidtide-2.9.5.data/scripts/tidepool +0 -23
  402. rapidtide-2.9.5.data/scripts/variabilityizer +0 -23
  403. rapidtide-2.9.5.dist-info/RECORD +0 -357
  404. rapidtide-2.9.5.dist-info/top_level.txt +0 -86
  405. {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info/licenses}/LICENSE +0 -0
rapidtide/resample.py CHANGED
@@ -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.
@@ -31,14 +31,18 @@ with warnings.catch_warnings():
31
31
  else:
32
32
  pyfftwpresent = True
33
33
 
34
- import pylab as pl
34
+ from typing import Any, Callable, Optional, Tuple, Union
35
+
36
+ import matplotlib.pyplot as plt
35
37
  import scipy as sp
38
+ from numpy.typing import ArrayLike, NDArray
36
39
  from scipy import fftpack, signal
37
40
 
38
41
  import rapidtide.filter as tide_filt
39
42
  import rapidtide.fit as tide_fit
40
43
  import rapidtide.io as tide_io
41
44
  import rapidtide.util as tide_util
45
+ from rapidtide.decorators import conditionaljit, conditionaljit2
42
46
 
43
47
  if pyfftwpresent:
44
48
  fftpack = pyfftw.interfaces.scipy_fftpack
@@ -50,124 +54,86 @@ import warnings
50
54
 
51
55
  warnings.simplefilter(action="ignore", category=RuntimeWarning)
52
56
 
53
- # ---------------------------------------- Global constants -------------------------------------------
54
- donotbeaggressive = True
55
-
56
- # ----------------------------------------- Conditional imports ---------------------------------------
57
- try:
58
- from numba import jit
59
- except ImportError:
60
- donotusenumba = True
61
- else:
62
- donotusenumba = False
63
-
64
-
65
- def conditionaljit():
66
- def resdec(f):
67
- if donotusenumba:
68
- return f
69
- return jit(f, nopython=True)
70
-
71
- return resdec
72
-
73
-
74
- def conditionaljit2():
75
- def resdec(f):
76
- if donotusenumba or donotbeaggressive:
77
- return f
78
- return jit(f, nopython=True)
79
-
80
- return resdec
81
-
82
-
83
- def disablenumba():
84
- global donotusenumba
85
- donotusenumba = True
86
-
87
-
88
57
  # --------------------------- Resampling and time shifting functions -------------------------------------------
89
- """
90
- class ConvolutionGridder:
91
- def __init__(self, timeaxis, width, method='gauss', circular=True, upsampleratio=100, doplot=False, debug=False):
92
- self.upsampleratio = upsampleratio
93
- self.initstep = timeaxis[1] - timeaxis[0]
94
- self.initstart = timeaxis[0]
95
- self.initend = timeaxis[-1]
96
- self.hiresstep = self.initstep / np.float64(self.upsampleratio)
97
- if method == 'gauss':
98
- fullwidth = 2.355 * width
99
- fullwidthpts = int(np.round(fullwidth / self.hiresstep, 0))
100
- fullwidthpts += ((fullwidthpts % 2) - 1)
101
- self.hires_x = np.linspace(-fullwidth / 2.0, fullwidth / 2.0, numpts = fullwidthpts, endpoint=True)
102
- if method == 'gauss':
103
- self.hires_y = tide_fit.gauss_eval(self.hires_x, np.array([1.0, 0.0, width])
104
- if debug:
105
- print(self.hires_x)
106
- if doplot:
107
- fig = pl.figure()
108
- ax = fig.add_subplot(111)
109
- ax.set_title('congrid convolution function')
110
- pl.plot(self.hires_x, self.hires_y)
111
- pl.legend(('input', 'hires'))
112
- pl.show()
113
-
114
- def gridded(xvals, yvals):
115
- if len(xvals) != len(yvals):
116
- print('x and y vectors do not match - aborting')
117
- return None
118
- for i in range(len(xvals)):
119
- outindices = ((newtimeaxis - self.hiresstart) // self.hiresstep).astype(int)
120
- """
121
-
122
- congridyvals = {}
58
+ congridyvals: dict = {}
123
59
  congridyvals["kernel"] = "kaiser"
124
60
  congridyvals["width"] = 3.0
125
61
 
126
62
 
127
- def congrid(xaxis, loc, val, width, kernel="kaiser", cyclic=True, debug=False):
63
+ def congrid(
64
+ xaxis: NDArray[np.floating[Any]],
65
+ loc: float,
66
+ val: float,
67
+ width: float,
68
+ kernel: str = "kaiser",
69
+ cache: bool = True,
70
+ cyclic: bool = True,
71
+ debug: bool = False,
72
+ onlykeynotices: bool = True,
73
+ ) -> Tuple[NDArray[np.floating[Any]], NDArray[np.floating[Any]], NDArray[np.floating[Any]]]:
128
74
  """
129
- Perform a convolution gridding operation with a Kaiser-Bessel or Gaussian kernel of width 'width'. Grid
130
- parameters are cached for performance.
75
+ Perform a convolution gridding operation with a Kaiser-Bessel or Gaussian kernel.
76
+
77
+ This function convolves a given value with a specified gridding kernel and projects
78
+ the result onto a target axis. It supports both cyclic and non-cyclic boundary
79
+ conditions and caches kernel values for performance optimization.
131
80
 
132
81
  Parameters
133
82
  ----------
134
- xaxis: array-like
135
- The target axis for resampling
136
- loc: float
137
- The location, in x-axis units, of the sample to be gridded
138
- val: float
139
- The value to be gridded
140
- width: float
141
- The width of the gridding kernel in target bins
142
- kernel: {'old', 'gauss', 'kaiser'}, optional
143
- The type of convolution gridding kernel. Default is 'kaiser'.
144
- cyclic: bool, optional
145
- When True, gridding wraps around the endpoints of xaxis. Default is True.
146
- debug: bool, optional
147
- When True, output additional information about the gridding process
83
+ xaxis : NDArray[np.floating[Any]]
84
+ The target axis for resampling. Should be a 1D array of evenly spaced points.
85
+ loc : float
86
+ The location, in x-axis units, of the sample to be gridded.
87
+ val : float
88
+ The value to be gridded.
89
+ width : float
90
+ The width of the gridding kernel in target bins. Must be a half-integral value
91
+ between 1.5 and 5.0 inclusive.
92
+ kernel : {'old', 'gauss', 'kaiser'}, optional
93
+ The type of convolution gridding kernel. Default is 'kaiser'.
94
+ - 'old': Uses a Gaussian kernel with fixed width.
95
+ - 'gauss': Uses a Gaussian kernel with optimized sigma.
96
+ - 'kaiser': Uses a Kaiser-Bessel kernel with optimized beta.
97
+ cache : bool, optional
98
+ If True, caches kernel values for performance. Default is True.
99
+ cyclic : bool, optional
100
+ When True, gridding wraps around the endpoints of xaxis. Default is True.
101
+ debug : bool, optional
102
+ When True, outputs additional information about the gridding process.
103
+ Default is False.
104
+ onlykeynotices : bool, optional
105
+ When True, suppresses certain debug messages. Default is True.
148
106
 
149
107
  Returns
150
108
  -------
151
- vals: array-like
152
- The input value, convolved with the gridding kernel, projected on to x axis points
153
- weights: array-like
154
- The values of convolution kernel, projected on to x axis points (used for normalization)
155
- indices: array-like
156
- The indices along the x axis where the vals and weights fall.
109
+ vals : NDArray[np.floating[Any]]
110
+ The input value, convolved with the gridding kernel, projected onto x-axis points.
111
+ weights : NDArray[np.floating[Any]]
112
+ The values of the convolution kernel, projected onto x-axis points (used for normalization).
113
+ indices : NDArray[int[Any]]
114
+ The indices along the x-axis where the vals and weights fall.
157
115
 
158
116
  Notes
159
117
  -----
160
- See IEEE TRANSACTIONS ON MEDICAL IMAGING. VOL. IO.NO. 3, SEPTEMBER 1991
161
-
118
+ This implementation is based on the method described in:
119
+ IEEE TRANSACTIONS ON MEDICAL IMAGING. VOL. 10, NO. 3, SEPTEMBER 1991
120
+
121
+ Examples
122
+ --------
123
+ >>> import numpy as np
124
+ >>> xaxis = np.linspace(0, 10, 100)
125
+ >>> vals, weights, indices = congrid(xaxis, 5.5, 1.0, 2.0)
126
+ >>> print(vals.shape)
127
+ (100,)
162
128
  """
163
129
  global congridyvals
164
130
 
165
131
  if (congridyvals["kernel"] != kernel) or (congridyvals["width"] != width):
166
132
  if congridyvals["kernel"] != kernel:
167
- if debug:
133
+ if debug and not onlykeynotices:
168
134
  print(congridyvals["kernel"], "!=", kernel)
169
135
  if congridyvals["width"] != width:
170
- if debug:
136
+ if debug and not onlykeynotices:
171
137
  print(congridyvals["width"], "!=", width)
172
138
  if debug:
173
139
  print("(re)initializing congridyvals")
@@ -191,7 +157,7 @@ def congrid(xaxis, loc, val, width, kernel="kaiser", cyclic=True, debug=False):
191
157
 
192
158
  # find the closest grid point to the target location, calculate relative offsets from this point
193
159
  center = tide_util.valtoindex(xaxis, loc)
194
- offset = np.fmod(np.round((loc - xaxis[center]) / xstep, 3), 1.0) # will vary from -0.5 to 0.5
160
+ offset = np.fmod(np.round((loc - xaxis[center]) / xstep, 4), 1.0) # will vary from -0.5 to 0.5
195
161
  if cyclic:
196
162
  if center == len(xaxis) - 1 and offset > 0.5:
197
163
  center = 0
@@ -224,19 +190,20 @@ def congrid(xaxis, loc, val, width, kernel="kaiser", cyclic=True, debug=False):
224
190
  )
225
191
  + offset
226
192
  )
227
- congridyvals[offsetkey] = tide_fit.gauss_eval(xvals, np.array([1.0, 0.0, width]))
228
- yvals = congridyvals[offsetkey]
193
+ yvals = tide_fit.gauss_eval(xvals, np.array([1.0, 0.0, width]))
194
+ if cache:
195
+ congridyvals[offsetkey] = 1.0 * yvals
229
196
  startpt = int(center - widthinpts // 2)
230
197
  indices = range(startpt, startpt + widthinpts)
231
198
  indices = np.remainder(indices, len(xaxis))
232
- if debug:
199
+ if debug and not onlykeynotices:
233
200
  print("center, offset, indices, yvals", center, offset, indices, yvals)
234
201
  return val * yvals, yvals, indices
235
202
  else:
236
203
  offsetinpts = center + offset
237
204
  startpt = int(np.ceil(offsetinpts - width / 2.0))
238
205
  endpt = int(np.floor(offsetinpts + width / 2.0))
239
- indices = np.remainder(range(startpt, endpt + 1), len(xaxis))
206
+ indices = np.remainder(np.array(list(range(startpt, endpt + 1))), len(xaxis))
240
207
  try:
241
208
  yvals = congridyvals[offsetkey]
242
209
  except KeyError:
@@ -245,19 +212,18 @@ def congrid(xaxis, loc, val, width, kernel="kaiser", cyclic=True, debug=False):
245
212
  xvals = indices - center + offset
246
213
  if kernel == "gauss":
247
214
  sigma = optsigma[kernelindex]
248
- congridyvals[offsetkey] = tide_fit.gauss_eval(xvals, np.array([1.0, 0.0, sigma]))
215
+ yvals = tide_fit.gauss_eval(xvals, np.array([1.0, 0.0, sigma]))
249
216
  elif kernel == "kaiser":
250
217
  beta = optbeta[kernelindex]
251
- congridyvals[offsetkey] = tide_fit.kaiserbessel_eval(
252
- xvals, np.array([beta, width / 2.0])
253
- )
218
+ yvals = tide_fit.kaiserbessel_eval(xvals, np.array([beta, width / 2.0]))
254
219
  else:
255
220
  print("illegal kernel value in congrid - exiting")
256
221
  sys.exit()
257
- yvals = congridyvals[offsetkey]
258
- if debug:
222
+ if cache:
223
+ congridyvals[offsetkey] = 1.0 * yvals
224
+ if debug and not onlykeynotices:
259
225
  print("xvals, yvals", xvals, yvals)
260
- if debug:
226
+ if debug and not onlykeynotices:
261
227
  print("center, offset, indices, yvals", center, offset, indices, yvals)
262
228
  return val * yvals, yvals, indices
263
229
 
@@ -273,6 +239,53 @@ class FastResampler:
273
239
  debug=False,
274
240
  method="univariate",
275
241
  ):
242
+ """
243
+ Initialize the FastResampler with given time axis and time course data.
244
+
245
+ This constructor prepares high-resolution time series data by resampling the input
246
+ time course using one of several methods, with optional padding and plotting.
247
+
248
+ Parameters
249
+ ----------
250
+ timeaxis : array-like
251
+ The time axis of the input data. Should be a 1D array of time points.
252
+ timecourse : array-like
253
+ The time course data corresponding to `timeaxis`. Should be a 1D array of values.
254
+ padtime : float, optional
255
+ Padding time in seconds to extend the resampled time axis on both ends.
256
+ Default is 30.0.
257
+ upsampleratio : int, optional
258
+ The upsampling ratio used for resampling. Default is 100.
259
+ doplot : bool, optional
260
+ If True, plot the original and high-resolution time courses. Default is False.
261
+ debug : bool, optional
262
+ If True, print debug information during initialization. Default is False.
263
+ method : str, optional
264
+ Resampling method to use. Options are:
265
+ - "univariate": Uses custom resampling logic.
266
+ - "poly": Uses `scipy.signal.resample_poly`.
267
+ - "fourier": Uses `scipy.signal.resample`.
268
+ Default is "univariate".
269
+
270
+ Returns
271
+ -------
272
+ None
273
+ This method initializes instance attributes and does not return a value.
274
+
275
+ Notes
276
+ -----
277
+ The resampled time axis (`hires_x`) is generated by extending the original time axis
278
+ by `padtime` on each side, using a step size that is `1 / upsampleratio` of the
279
+ original step size. The `hires_y` array contains the resampled time course values.
280
+
281
+ Examples
282
+ --------
283
+ >>> import numpy as np
284
+ >>> from scipy import signal
285
+ >>> timeaxis = np.linspace(0, 10, 100)
286
+ >>> timecourse = np.sin(timeaxis)
287
+ >>> resampler = FastResampler(timeaxis, timecourse, padtime=5.0, method="poly")
288
+ """
276
289
  self.timeaxis = timeaxis
277
290
  self.timecourse = timecourse
278
291
  self.upsampleratio = upsampleratio
@@ -288,13 +301,14 @@ class FastResampler:
288
301
  )
289
302
  self.hiresstart = self.hires_x[0]
290
303
  self.hiresend = self.hires_x[-1]
291
- if method == "poly":
304
+ self.method = method
305
+ if self.method == "poly":
292
306
  self.hires_y = 0.0 * self.hires_x
293
307
  self.hires_y[
294
308
  int(self.padtime // self.hiresstep)
295
309
  + 1 : -(int(self.padtime // self.hiresstep) + 1)
296
310
  ] = signal.resample_poly(timecourse, int(self.upsampleratio * 10), 10)
297
- elif method == "fourier":
311
+ elif self.method == "fourier":
298
312
  self.hires_y = 0.0 * self.hires_x
299
313
  self.hires_y[
300
314
  int(self.padtime // self.hiresstep)
@@ -320,14 +334,144 @@ class FastResampler:
320
334
  if doplot:
321
335
  import matplolib.pyplot as pl
322
336
 
323
- fig = pl.figure()
337
+ fig = plt.figure()
324
338
  ax = fig.add_subplot(111)
325
339
  ax.set_title("FastResampler initial timecourses")
326
- pl.plot(timeaxis, timecourse, self.hires_x, self.hires_y)
327
- pl.legend(("input", "hires"))
328
- pl.show()
340
+ plt.plot(timeaxis, timecourse, self.hires_x, self.hires_y)
341
+ plt.legend(("input", "hires"))
342
+ plt.show()
343
+
344
+ def getdata(self):
345
+ """
346
+ Retrieve time series data and related parameters.
347
+
348
+ Returns
349
+ -------
350
+ tuple
351
+ A tuple containing:
352
+ - timeaxis : array_like
353
+ Time axis values
354
+ - timecourse : array_like
355
+ Time course data values
356
+ - hires_x : array_like
357
+ High resolution x-axis data
358
+ - hires_y : array_like
359
+ High resolution y-axis data
360
+ - inverse_initstep : float
361
+ Reciprocal of the initial step size (1.0 / self.initstep)
362
+
363
+ Notes
364
+ -----
365
+ This function provides access to all time series data and associated
366
+ high resolution parameters stored in the object instance. The returned
367
+ inverse_initstep value is commonly used for normalization or scaling
368
+ operations in time series analysis.
369
+
370
+ Examples
371
+ --------
372
+ >>> data = obj.getdata()
373
+ >>> time_axis, time_course, hires_x, hires_y, inv_step = data
374
+ >>> print(f"Time course shape: {time_course.shape}")
375
+ """
376
+ return self.timeaxis, self.timecourse, self.hires_x, self.hires_y, 1.0 / self.initstep
377
+
378
+ def info(self, prefix=""):
379
+ """
380
+ Print information about the object's time and sampling parameters.
381
+
382
+ This method displays various time-related attributes and sampling parameters
383
+ of the object, with optional prefix for better formatting in output.
384
+
385
+ Parameters
386
+ ----------
387
+ prefix : str, optional
388
+ String to prepend to each printed line, useful for indentation or
389
+ grouping related output. Default is empty string.
390
+
391
+ Returns
392
+ -------
393
+ None
394
+ This method prints information to stdout and does not return any value.
395
+
396
+ Notes
397
+ -----
398
+ The method prints the following attributes:
399
+ - timeaxis: Time axis values
400
+ - timecourse: Time course data
401
+ - upsampleratio: Upsampling ratio
402
+ - padtime: Padding time
403
+ - initstep: Initial step size
404
+ - initstart: Initial start time
405
+ - initend: Initial end time
406
+ - hiresstep: High-resolution step size
407
+ - hires_x[0]: First value of high-resolution x-axis
408
+ - hires_x[-1]: Last value of high-resolution x-axis
409
+ - hiresstart: High-resolution start time
410
+ - hiresend: High-resolution end time
411
+ - method: Interpolation/processing method used
412
+ - hires_y[0]: First value of high-resolution y-axis
413
+ - hires_y[-1]: Last value of high-resolution y-axis
414
+
415
+ Examples
416
+ --------
417
+ >>> obj.info()
418
+ timeaxis=100
419
+ timecourse=200
420
+ upsampleratio=4
421
+ ...
422
+
423
+ >>> obj.info(prefix=" ")
424
+ timeaxis=100
425
+ timecourse=200
426
+ upsampleratio=4
427
+ ...
428
+ """
429
+ print(f"{prefix}{self.timeaxis=}")
430
+ print(f"{prefix}{self.timecourse=}")
431
+ print(f"{prefix}{self.upsampleratio=}")
432
+ print(f"{prefix}{self.padtime=}")
433
+ print(f"{prefix}{self.initstep=}")
434
+ print(f"{prefix}{self.initstart=}")
435
+ print(f"{prefix}{self.initend=}")
436
+ print(f"{prefix}{self.hiresstep=}")
437
+ print(f"{prefix}{self.hires_x[0]=}")
438
+ print(f"{prefix}{self.hires_x[-1]=}")
439
+ print(f"{prefix}{self.hiresstart=}")
440
+ print(f"{prefix}{self.hiresend=}")
441
+ print(f"{prefix}{self.method=}")
442
+ print(f"{prefix}{self.hires_y[0]=}")
443
+ print(f"{prefix}{self.hires_y[-1]=}")
329
444
 
330
445
  def save(self, outputname):
446
+ """
447
+ Save the timecourse data to a TSV file.
448
+
449
+ This method writes the internal timecourse data to a tab-separated values file
450
+ with additional metadata in the header. The output includes the timecourse data
451
+ along with timing information derived from the object's initialization parameters.
452
+
453
+ Parameters
454
+ ----------
455
+ outputname : str
456
+ The path and filename where the TSV output will be saved.
457
+
458
+ Returns
459
+ -------
460
+ None
461
+ This method does not return any value.
462
+
463
+ Notes
464
+ -----
465
+ The method uses the `tide_io.writebidstsv` function to perform the actual file writing.
466
+ The time step is calculated as 1.0 divided by `self.initstep`, and the start time
467
+ is taken from `self.initstart`. The output file includes a header with description
468
+ metadata indicating this is a lagged timecourse generator.
469
+
470
+ Examples
471
+ --------
472
+ >>> obj.save("output_timecourse.tsv")
473
+ >>> # Creates a TSV file with the timecourse data and metadata
474
+ """
331
475
  tide_io.writebidstsv(
332
476
  outputname,
333
477
  self.timecourse,
@@ -339,6 +483,41 @@ class FastResampler:
339
483
  )
340
484
 
341
485
  def yfromx(self, newtimeaxis, doplot=False, debug=False):
486
+ """
487
+ Resample y-values from a high-resolution time axis to a new time axis.
488
+
489
+ This method maps values from a high-resolution y-array (`self.hires_y`) to a
490
+ new time axis (`newtimeaxis`) by linear interpolation based on the step size
491
+ and start of the high-resolution axis.
492
+
493
+ Parameters
494
+ ----------
495
+ newtimeaxis : array-like
496
+ The new time axis to which the y-values will be resampled.
497
+ doplot : bool, optional
498
+ If True, plot the original high-resolution y-values and the resampled
499
+ values for comparison. Default is False.
500
+ debug : bool, optional
501
+ If True, print debug information including internal parameters and
502
+ bounds checking. Default is False.
503
+
504
+ Returns
505
+ -------
506
+ out_y : ndarray
507
+ The resampled y-values corresponding to `newtimeaxis`.
508
+
509
+ Notes
510
+ -----
511
+ This function assumes that `self.hires_y` has been precomputed and that
512
+ the internal parameters (`self.hiresstart`, `self.hiresstep`) are valid.
513
+ An IndexError is raised if any index in `outindices` is out of bounds.
514
+
515
+ Examples
516
+ --------
517
+ >>> resampler = FastResampler()
518
+ >>> new_times = np.linspace(0, 10, 100)
519
+ >>> y_vals = resampler.yfromx(new_times, doplot=True)
520
+ """
342
521
  if debug:
343
522
  print("FastResampler: yfromx called with following parameters")
344
523
  print(" padtime:, ", self.padtime)
@@ -361,16 +540,59 @@ class FastResampler:
361
540
  print(" requested axis limits:", newtimeaxis[0], newtimeaxis[-1])
362
541
  sys.exit()
363
542
  if doplot:
364
- fig = pl.figure()
543
+ fig = plt.figure()
365
544
  ax = fig.add_subplot(111)
366
545
  ax.set_title("FastResampler timecourses")
367
- pl.plot(self.hires_x, self.hires_y, newtimeaxis, out_y)
368
- pl.legend(("hires", "output"))
369
- pl.show()
546
+ plt.plot(self.hires_x, self.hires_y, newtimeaxis, out_y)
547
+ plt.legend(("hires", "output"))
548
+ plt.show()
370
549
  return out_y
371
550
 
372
551
 
373
- def FastResamplerFromFile(inputname, colspec=None, debug=False, **kwargs):
552
+ def FastResamplerFromFile(
553
+ inputname: str, colspec: Optional[str] = None, debug: bool = False, **kwargs
554
+ ) -> FastResampler:
555
+ """
556
+ Create a FastResampler from a BIDS TSV file.
557
+
558
+ This function reads data from a BIDS TSV file and creates a FastResampler object
559
+ for efficient time series resampling operations. The input file must contain
560
+ exactly one column of data.
561
+
562
+ Parameters
563
+ ----------
564
+ inputname : str
565
+ Path to the input BIDS TSV file containing the time series data
566
+ colspec : str, optional
567
+ Column specification for selecting specific columns from the TSV file.
568
+ If None, all columns are read (default: None)
569
+ debug : bool, optional
570
+ Enable debug output printing (default: False)
571
+ **kwargs
572
+ Additional keyword arguments passed to the FastResampler constructor
573
+
574
+ Returns
575
+ -------
576
+ FastResampler
577
+ A FastResampler object initialized with the time axis and data from the input file
578
+
579
+ Raises
580
+ ------
581
+ ValueError
582
+ If the input file contains multiple columns of data
583
+
584
+ Notes
585
+ -----
586
+ The function internally calls `tide_io.readbidstsv` to read the input file and
587
+ constructs a time axis using `np.linspace` based on the sampling rate and
588
+ start time from the input file.
589
+
590
+ Examples
591
+ --------
592
+ >>> resampler = FastResamplerFromFile('data.tsv')
593
+ >>> resampler = FastResamplerFromFile('data.tsv', colspec='column1')
594
+ >>> resampler = FastResamplerFromFile('data.tsv', debug=True)
595
+ """
374
596
  (
375
597
  insamplerate,
376
598
  instarttime,
@@ -378,9 +600,13 @@ def FastResamplerFromFile(inputname, colspec=None, debug=False, **kwargs):
378
600
  indata,
379
601
  incompressed,
380
602
  incolsource,
603
+ inextrainfo,
381
604
  ) = tide_io.readbidstsv(inputname, colspec=colspec, debug=debug)
382
- if len(incolumns) > 1:
383
- raise ValueError("Multiple columns in input file")
605
+ if incolumns is not None:
606
+ if len(incolumns) > 1:
607
+ raise ValueError("Multiple columns in input file")
608
+ else:
609
+ raise ValueError("No column names in file")
384
610
  intimecourse = indata[0, :]
385
611
  intimeaxis = np.linspace(
386
612
  instarttime,
@@ -394,29 +620,65 @@ def FastResamplerFromFile(inputname, colspec=None, debug=False, **kwargs):
394
620
 
395
621
 
396
622
  def doresample(
397
- orig_x,
398
- orig_y,
399
- new_x,
400
- method="cubic",
401
- padlen=0,
402
- padtype="reflect",
403
- antialias=False,
404
- debug=False,
405
- ):
623
+ orig_x: NDArray,
624
+ orig_y: NDArray,
625
+ new_x: NDArray,
626
+ method: str = "cubic",
627
+ padlen: int = 0,
628
+ padtype: str = "reflect",
629
+ antialias: bool = False,
630
+ debug: bool = False,
631
+ ) -> NDArray:
406
632
  """
407
- Resample data from one spacing to another. By default, does not apply any antialiasing filter.
633
+ Resample data from one spacing to another.
634
+
635
+ By default, does not apply any antialiasing filter.
408
636
 
409
637
  Parameters
410
638
  ----------
411
- orig_x
412
- orig_y
413
- new_x
414
- method
415
- padlen
639
+ orig_x : NDArray
640
+ Original x-coordinates of the data to be resampled.
641
+ orig_y : NDArray
642
+ Original y-values corresponding to `orig_x`.
643
+ new_x : NDArray
644
+ New x-coordinates at which to evaluate the resampled data.
645
+ method : str, optional
646
+ Interpolation method to use. Options are:
647
+ - "cubic": cubic spline interpolation (default)
648
+ - "quadratic": quadratic spline interpolation
649
+ - "univariate": univariate spline interpolation using `scipy.interpolate.UnivariateSpline`
650
+ padlen : int, optional
651
+ Number of elements to pad the input data at both ends. Default is 0.
652
+ padtype : str, optional
653
+ Type of padding to use when `padlen > 0`. Default is "reflect".
654
+ Passed to `tide_filt.padvec`.
655
+ antialias : bool, optional
656
+ If True, apply an antialiasing filter before resampling if the original
657
+ sampling frequency is higher than the target frequency. Default is False.
658
+ debug : bool, optional
659
+ If True, print debug information and display a plot of the original and
660
+ padded data. Default is False.
416
661
 
417
662
  Returns
418
663
  -------
664
+ ndarray
665
+ Resampled y-values at coordinates specified by `new_x`. If an invalid
666
+ interpolation method is specified, returns None.
419
667
 
668
+ Notes
669
+ -----
670
+ - The function uses padding to handle edge effects during interpolation.
671
+ - When `antialias=True`, a non-causal filter is applied to reduce aliasing
672
+ artifacts when downsampling.
673
+ - The `tide_filt` module is used for padding and filtering operations.
674
+
675
+ Examples
676
+ --------
677
+ >>> import numpy as np
678
+ >>> x = np.linspace(0, 10, 100)
679
+ >>> y = np.sin(x)
680
+ >>> new_x = np.linspace(0, 10, 200)
681
+ >>> y_resampled = doresample(x, y, new_x, method="cubic")
420
682
  """
421
683
  tstep = orig_x[1] - orig_x[0]
422
684
  if padlen > 0:
@@ -435,11 +697,11 @@ def doresample(
435
697
  print("lens:", len(pad_x), len(pad_y))
436
698
  print(pad_x)
437
699
  print(pad_y)
438
- fig = pl.figure()
700
+ fig = plt.figure()
439
701
  ax = fig.add_subplot(111)
440
702
  ax.set_title("Original and padded vector")
441
- pl.plot(orig_x, orig_y + 1.0, pad_x, pad_y)
442
- pl.show()
703
+ plt.plot(orig_x, orig_y + 1.0, pad_x, pad_y)
704
+ plt.show()
443
705
 
444
706
  # antialias and ringstop filter
445
707
  init_freq = len(pad_x) / (pad_x[-1] - pad_x[0])
@@ -463,38 +725,82 @@ def doresample(
463
725
  elif method == "univariate":
464
726
  interpolator = sp.interpolate.UnivariateSpline(pad_x, pad_y, k=3, s=0) # s=0 interpolates
465
727
  # return tide_filt.unpadvec(np.float64(interpolator(new_x)), padlen=padlen)
466
- return np.float64(interpolator(new_x))
728
+ return (interpolator(new_x)).astype(np.float64)
467
729
  else:
468
730
  print("invalid interpolation method")
469
731
  return None
470
732
 
471
733
 
472
734
  def arbresample(
473
- inputdata,
474
- init_freq,
475
- final_freq,
476
- intermed_freq=0.0,
477
- method="univariate",
478
- antialias=True,
479
- decimate=False,
480
- debug=False,
481
- ):
735
+ inputdata: NDArray,
736
+ init_freq: float,
737
+ final_freq: float,
738
+ intermed_freq: float = 0.0,
739
+ method: str = "univariate",
740
+ antialias: bool = True,
741
+ decimate: bool = False,
742
+ debug: bool = False,
743
+ ) -> NDArray:
482
744
  """
745
+ Resample input data from an initial frequency to a final frequency using either
746
+ direct resampling or a two-step process with intermediate frequency.
747
+
748
+ This function supports both upsampling and downsampling, with optional anti-aliasing
749
+ and decimation. It can operate in debug mode to print intermediate steps and
750
+ statistics.
483
751
 
484
752
  Parameters
485
753
  ----------
486
- inputdata
487
- init_freq
488
- final_freq
489
- intermed_freq
490
- method
491
- antialias
492
- decimate
493
- debug
754
+ inputdata : NDArray
755
+ Input signal or data to be resampled. Should be a 1-D array-like object.
756
+ init_freq : float
757
+ Initial sampling frequency of the input data in Hz.
758
+ final_freq : float
759
+ Target sampling frequency of the output data in Hz.
760
+ intermed_freq : float, optional
761
+ Intermediate sampling frequency used in the two-step resampling process.
762
+ If not specified (default: 0.0), it is automatically set to the maximum of
763
+ 2 * init_freq and 2 * final_freq.
764
+ method : str, optional
765
+ Interpolation method to use for resampling. Default is "univariate".
766
+ Other options may be supported depending on the underlying implementation.
767
+ antialias : bool, optional
768
+ If True (default), apply anti-aliasing filter during downsampling using
769
+ `scipy.signal.decimate`. If False, use simple interpolation for downsampling.
770
+ decimate : bool, optional
771
+ If True, perform upsampling followed by decimation for downsampling.
772
+ If False, use a two-step resampling approach with `dotwostepresample`.
773
+ Default is False.
774
+ debug : bool, optional
775
+ If True, print debug information including number of points before and after
776
+ resampling, and intermediate steps. Default is False.
494
777
 
495
778
  Returns
496
779
  -------
780
+ NDArray
781
+ Resampled data as a NumPy array with length adjusted according to `final_freq`.
497
782
 
783
+ Notes
784
+ -----
785
+ - When `decimate=True`, the function uses integer decimation for efficient downsampling.
786
+ - For downsampling, if `antialias=False`, the function uses linear interpolation
787
+ instead of filtering to reduce computational cost.
788
+ - The `intermed_freq` is automatically calculated when `decimate=True` and
789
+ `final_freq < init_freq`.
790
+
791
+ Examples
792
+ --------
793
+ >>> import numpy as np
794
+ >>> data = np.random.rand(100)
795
+ >>> resampled = arbresample(data, init_freq=100, final_freq=50, decimate=True)
796
+ >>> print(len(resampled))
797
+ 50
798
+
799
+ See Also
800
+ --------
801
+ upsample : Function used for upsampling when `decimate=True`.
802
+ dotwostepresample : Function used for two-step resampling when `decimate=False`.
803
+ scipy.signal.decimate : Anti-aliasing filter used when `antialias=True`.
498
804
  """
499
805
  if debug:
500
806
  print("arbresample - initial points:", len(inputdata))
@@ -566,7 +872,62 @@ def arbresample(
566
872
  return resampled
567
873
 
568
874
 
569
- def upsample(inputdata, Fs_init, Fs_higher, method="univariate", intfac=False, debug=False):
875
+ def upsample(
876
+ inputdata: NDArray,
877
+ Fs_init: float,
878
+ Fs_higher: float,
879
+ method: str = "univariate",
880
+ intfac: bool = False,
881
+ dofilt: bool = True,
882
+ debug: bool = False,
883
+ ) -> NDArray:
884
+ """
885
+ Upsample input data to a higher sampling frequency.
886
+
887
+ This function increases the sampling rate of the input data using interpolation
888
+ and optional filtering. It supports different interpolation methods and allows
889
+ for control over the resampling factor and filtering behavior.
890
+
891
+ Parameters
892
+ ----------
893
+ inputdata : NDArray
894
+ Input time series data to be upsampled.
895
+ Fs_init : float
896
+ Initial sampling frequency of the input data (Hz).
897
+ Fs_higher : float
898
+ Target sampling frequency to upsample to (Hz). Must be greater than `Fs_init`.
899
+ method : str, optional
900
+ Interpolation method to use. Default is "univariate". Other options depend
901
+ on the implementation of `doresample`.
902
+ intfac : bool, optional
903
+ If True, use integer resampling factor based on `Fs_higher // Fs_init`.
904
+ If False, compute resampled points based on time duration. Default is False.
905
+ dofilt : bool, optional
906
+ If True, apply a non-causal filter to prevent aliasing. Default is True.
907
+ debug : bool, optional
908
+ If True, print timing information. Default is False.
909
+
910
+ Returns
911
+ -------
912
+ NDArray
913
+ Upsampled time series data with the new sampling frequency.
914
+
915
+ Notes
916
+ -----
917
+ - The function uses linear interpolation by default, but the actual method
918
+ depends on the `doresample` function implementation.
919
+ - If `dofilt` is True, a trapezoidal non-causal filter is applied with a
920
+ stop frequency set to the minimum of 1.1 * Fs_init / 2.0 and Fs_higher / 2.0.
921
+ - The function will terminate if `Fs_higher` is not greater than `Fs_init`.
922
+
923
+ Examples
924
+ --------
925
+ >>> import numpy as np
926
+ >>> data = np.sin(np.linspace(0, 4*np.pi, 100))
927
+ >>> upsampled = upsample(data, Fs_init=10.0, Fs_higher=20.0)
928
+ >>> print(len(upsampled))
929
+ 200
930
+ """
570
931
  starttime = time.time()
571
932
  if Fs_higher <= Fs_init:
572
933
  print("upsample: target frequency must be higher than initial frequency")
@@ -576,48 +937,79 @@ def upsample(inputdata, Fs_init, Fs_higher, method="univariate", intfac=False, d
576
937
  orig_x = np.linspace(0.0, (1.0 / Fs_init) * len(inputdata), num=len(inputdata), endpoint=False)
577
938
  endpoint = orig_x[-1] - orig_x[0]
578
939
  ts_higher = 1.0 / Fs_higher
579
- numresamppts = int(endpoint // ts_higher + 1)
580
940
  if intfac:
581
941
  numresamppts = int(Fs_higher // Fs_init) * len(inputdata)
582
942
  else:
583
943
  numresamppts = int(endpoint // ts_higher + 1)
584
944
  upsampled_x = np.arange(0.0, ts_higher * numresamppts, ts_higher)
585
945
  upsampled_y = doresample(orig_x, inputdata, upsampled_x, method=method)
586
- initfilter = tide_filt.NoncausalFilter(
587
- filtertype="arb", transferfunc="trapezoidal", debug=debug
588
- )
589
- stopfreq = np.min([1.1 * Fs_init / 2.0, Fs_higher / 2.0])
590
- initfilter.setfreqs(0.0, 0.0, Fs_init / 2.0, stopfreq)
591
- upsampled_y = initfilter.apply(Fs_higher, upsampled_y)
946
+ if dofilt:
947
+ initfilter = tide_filt.NoncausalFilter(
948
+ filtertype="arb", transferfunc="trapezoidal", debug=debug
949
+ )
950
+ stopfreq = np.min([1.1 * Fs_init / 2.0, Fs_higher / 2.0])
951
+ initfilter.setfreqs(0.0, 0.0, Fs_init / 2.0, stopfreq)
952
+ upsampled_y = initfilter.apply(Fs_higher, upsampled_y)
592
953
  if debug:
593
954
  print("upsampling took", time.time() - starttime, "seconds")
594
955
  return upsampled_y
595
956
 
596
957
 
597
958
  def dotwostepresample(
598
- orig_x,
599
- orig_y,
600
- intermed_freq,
601
- final_freq,
602
- method="univariate",
603
- antialias=True,
604
- debug=False,
605
- ):
959
+ orig_x: NDArray,
960
+ orig_y: NDArray,
961
+ intermed_freq: float,
962
+ final_freq: float,
963
+ method: str = "univariate",
964
+ antialias: bool = True,
965
+ debug: bool = False,
966
+ ) -> NDArray:
606
967
  """
968
+ Resample a signal from original frequency to final frequency using a two-step process:
969
+ first upsampling to an intermediate frequency, then downsampling to the final frequency.
970
+
971
+ This function performs resampling by first interpolating the input signal to an
972
+ intermediate frequency that is higher than the final desired frequency, followed by
973
+ downsampling to the target frequency. Optional antialiasing filtering is applied
974
+ during the upsampling step.
607
975
 
608
976
  Parameters
609
977
  ----------
610
- orig_x
611
- orig_y
612
- intermed_freq
613
- final_freq
614
- method
615
- debug
978
+ orig_x : NDArray
979
+ Original time axis values (must be monotonically increasing).
980
+ orig_y : NDArray
981
+ Original signal values corresponding to `orig_x`.
982
+ intermed_freq : float
983
+ Intermediate frequency to which the signal is upsampled.
984
+ Must be greater than `final_freq`.
985
+ final_freq : float
986
+ Target frequency to which the signal is downsampled.
987
+ method : str, optional
988
+ Interpolation method used for resampling. Default is "univariate".
989
+ Should be compatible with the `doresample` function.
990
+ antialias : bool, optional
991
+ If True, apply an antialiasing filter during upsampling. Default is True.
992
+ debug : bool, optional
993
+ If True, print timing and intermediate information. Default is False.
616
994
 
617
995
  Returns
618
996
  -------
619
- resampled_y
997
+ ndarray
998
+ Resampled signal values at the final frequency.
620
999
 
1000
+ Notes
1001
+ -----
1002
+ - The intermediate frequency must be strictly greater than the final frequency.
1003
+ - The function uses `doresample` for interpolation and `tide_filt.NoncausalFilter`
1004
+ for antialiasing if enabled.
1005
+ - Timing information is printed when `debug=True`.
1006
+
1007
+ Examples
1008
+ --------
1009
+ >>> import numpy as np
1010
+ >>> x = np.linspace(0, 10, 100)
1011
+ >>> y = np.sin(x)
1012
+ >>> resampled = dotwostepresample(x, y, intermed_freq=50.0, final_freq=10.0)
621
1013
  """
622
1014
  if intermed_freq <= final_freq:
623
1015
  print("intermediate frequency must be higher than final frequency")
@@ -667,20 +1059,56 @@ def dotwostepresample(
667
1059
  return resampled_y
668
1060
 
669
1061
 
670
- def calcsliceoffset(sotype, slicenum, numslices, tr, multiband=1):
1062
+ def calcsliceoffset(
1063
+ sotype: int, slicenum: int, numslices: int, tr: float, multiband: int = 1
1064
+ ) -> float:
671
1065
  """
1066
+ Calculate slice timing offset for slice timing correction.
1067
+
1068
+ This function computes the timing offset (in seconds) for a given slice
1069
+ based on the slice timing correction method specified by `sotype`. The
1070
+ offset is used to align slice acquisition times for functional MRI data
1071
+ preprocessing.
672
1072
 
673
1073
  Parameters
674
1074
  ----------
675
- sotype
676
- slicenum
677
- numslices
678
- tr
679
- multiband
1075
+ sotype : int
1076
+ Slice timing correction method:
1077
+ - 0: None
1078
+ - 1: Regular up (0, 1, 2, 3, ...)
1079
+ - 2: Regular down
1080
+ - 3: Use slice order file (not supported)
1081
+ - 4: Use slice timings file (not supported)
1082
+ - 5: Standard interleaved (0, 2, 4, ..., 1, 3, 5, ...)
1083
+ - 6: Siemens interleaved
1084
+ - 7: Siemens multiband interleaved
1085
+ slicenum : int
1086
+ The index of the slice for which to compute the timing offset.
1087
+ numslices : int
1088
+ Total number of slices in the volume.
1089
+ tr : float
1090
+ Repetition time (TR) in seconds.
1091
+ multiband : int, optional
1092
+ Multiband factor (default is 1). Used only for sotype 7 (Siemens
1093
+ multiband interleaved).
680
1094
 
681
1095
  Returns
682
1096
  -------
1097
+ float
1098
+ Slice timing offset in seconds.
1099
+
1100
+ Notes
1101
+ -----
1102
+ For sotypes 3 and 4, the function returns 0.0 as these methods are not
1103
+ implemented.
1104
+
1105
+ Examples
1106
+ --------
1107
+ >>> calcsliceoffset(1, 5, 32, 2.0)
1108
+ 0.3125
683
1109
 
1110
+ >>> calcsliceoffset(5, 3, 16, 1.5)
1111
+ 0.28125
684
1112
  """
685
1113
  # Slice timing correction
686
1114
  # 0 : None
@@ -771,19 +1199,61 @@ def calcsliceoffset(sotype, slicenum, numslices, tr, multiband=1):
771
1199
 
772
1200
  # NB: a positive value of shifttrs delays the signal, a negative value advances it
773
1201
  # timeshift using fourier phase multiplication
774
- def timeshift(inputtc, shifttrs, padtrs, doplot=False, debug=False):
1202
+ def timeshift(
1203
+ inputtc: ArrayLike, shifttrs: float, padtrs: int, doplot: bool = False, debug: bool = False
1204
+ ) -> Tuple[NDArray, NDArray, NDArray, NDArray]:
775
1205
  """
1206
+ Apply a time shift to a signal using FFT-based modulation and padding.
1207
+
1208
+ This function performs a time shift on an input time course by applying
1209
+ phase modulation in the frequency domain, followed by inverse FFT. It uses
1210
+ padding and reflection to avoid edge discontinuities. The function also
1211
+ returns the corresponding shifted weights and the full padded results.
776
1212
 
777
1213
  Parameters
778
1214
  ----------
779
- inputtc
780
- shifttrs
781
- padtrs
782
- doplot
1215
+ inputtc : array-like
1216
+ Input time course to be shifted. Should be a 1D array of real values.
1217
+ shifttrs : float
1218
+ Time shift in units of samples. Positive values shift the signal forward,
1219
+ negative values shift it backward.
1220
+ padtrs : int
1221
+ Number of samples to pad the input signal on each side before shifting.
1222
+ This helps reduce edge effects.
1223
+ doplot : bool, optional
1224
+ If True, plots the original and shifted signals. Default is False.
1225
+ debug : bool, optional
1226
+ If True, prints debug information during execution. Default is False.
783
1227
 
784
1228
  Returns
785
1229
  -------
1230
+ tuple of ndarray
1231
+ A tuple containing:
1232
+ - shifted_y : ndarray
1233
+ The time-shifted signal, cropped to the original length.
1234
+ - shifted_weights : ndarray
1235
+ The corresponding shifted weights, cropped to the original length.
1236
+ - shifted_y_full : ndarray
1237
+ The full time-shifted signal including padding.
1238
+ - shifted_weights_full : ndarray
1239
+ The full shifted weights including padding.
786
1240
 
1241
+ Notes
1242
+ -----
1243
+ The function uses reflection padding to minimize edge artifacts. The phase
1244
+ modulation is applied in the frequency domain using FFT and inverse FFT.
1245
+ The shift is implemented as a complex exponential modulation.
1246
+
1247
+ Examples
1248
+ --------
1249
+ >>> import numpy as np
1250
+ >>> from scipy import fftpack
1251
+ >>> input_signal = np.sin(np.linspace(0, 4*np.pi, 100))
1252
+ >>> shifted_sig, weights, full_shifted, full_weights = timeshift(
1253
+ ... input_signal, shifttrs=5.0, padtrs=10, doplot=False
1254
+ ... )
1255
+ >>> print(shifted_sig.shape)
1256
+ (100,)
787
1257
  """
788
1258
  # set up useful parameters
789
1259
  thelen = np.shape(inputtc)[0]
@@ -830,36 +1300,87 @@ def timeshift(inputtc, shifttrs, padtrs, doplot=False, debug=False):
830
1300
  print("thelen:", thelen)
831
1301
  print("thepaddedlen:", thepaddedlen)
832
1302
 
833
- fig = pl.figure()
1303
+ fig = plt.figure()
834
1304
  ax = fig.add_subplot(111)
835
1305
  ax.set_title("Initial vector")
836
- pl.plot(xvec, preshifted_y)
1306
+ plt.plot(xvec, preshifted_y)
837
1307
 
838
- fig = pl.figure()
1308
+ fig = plt.figure()
839
1309
  ax = fig.add_subplot(111)
840
1310
  ax.set_title("Initial and shifted vector")
841
- pl.plot(xvec, preshifted_y, xvec, shifted_y)
1311
+ plt.plot(xvec, preshifted_y, xvec, shifted_y)
842
1312
 
843
- pl.show()
1313
+ plt.show()
844
1314
 
845
- return [
1315
+ return (
846
1316
  shifted_y[padtrs : padtrs + thelen],
847
1317
  shifted_weights[padtrs : padtrs + thelen],
848
1318
  shifted_y,
849
1319
  shifted_weights,
850
- ]
1320
+ )
1321
+
851
1322
 
1323
+ def timewarp(
1324
+ orig_x: NDArray,
1325
+ orig_y: NDArray,
1326
+ timeoffset: NDArray,
1327
+ demean: bool = True,
1328
+ method: str = "univariate",
1329
+ debug: bool = False,
1330
+ ) -> NDArray:
1331
+ """
1332
+ Apply time warping to align time series data based on time offsets.
1333
+
1334
+ This function performs time warping by resampling input data according to
1335
+ provided time offsets. It can optionally remove the mean of the time offsets
1336
+ before resampling to center the data around zero.
1337
+
1338
+ Parameters
1339
+ ----------
1340
+ orig_x : NDArray
1341
+ Original time axis values (x-coordinates) for the data to be warped.
1342
+ orig_y : NDArray
1343
+ Original signal values (y-coordinates) corresponding to orig_x.
1344
+ timeoffset : NDArray
1345
+ Time offsets to be applied to each point in the time axis. Positive values
1346
+ shift data forward in time, negative values shift backward.
1347
+ demean : bool, optional
1348
+ If True, remove the mean of timeoffset before resampling. Default is True.
1349
+ method : str, optional
1350
+ Resampling method to use. Options are 'univariate' or other methods
1351
+ supported by the underlying doresample function. Default is 'univariate'.
1352
+ debug : bool, optional
1353
+ If True, print debugging information about the warping process.
1354
+ Default is False.
852
1355
 
853
- def timewarp(orig_x, orig_y, timeoffset, demean=True, method="univariate", debug=False):
1356
+ Returns
1357
+ -------
1358
+ NDArray
1359
+ Warped time series data after applying the time offsets and resampling.
1360
+
1361
+ Notes
1362
+ -----
1363
+ The function calculates the maximum deviation in samples and uses half the
1364
+ length of the input data (or 30 seconds worth of samples, whichever is smaller)
1365
+ as padding length for the resampling operation.
1366
+
1367
+ Examples
1368
+ --------
1369
+ >>> import numpy as np
1370
+ >>> x = np.linspace(0, 10, 100)
1371
+ >>> y = np.sin(x)
1372
+ >>> offsets = np.random.normal(0, 0.1, 100)
1373
+ >>> warped_y = timewarp(x, y, offsets)
1374
+ """
854
1375
  if demean:
855
1376
  demeanedoffset = timeoffset - np.mean(timeoffset)
856
1377
  if debug:
857
1378
  print("mean delay of ", np.mean(timeoffset), "seconds removed prior to resampling")
858
1379
  else:
859
1380
  demeanedoffset = timeoffset
860
- sampletime = orig_x[1] - orig_x[0]
861
- maxdevs = (np.min(demeanedoffset), np.max(demeanedoffset))
862
- maxsamps = maxdevs / sampletime
1381
+ sampletime = float(orig_x[1] - orig_x[0])
1382
+ maxdevs = (float(np.min(demeanedoffset)), float(np.max(demeanedoffset)))
1383
+ maxsamps = (maxdevs[0] / sampletime, maxdevs[1] / sampletime)
863
1384
  padlen = np.min([int(len(orig_x) // 2), int(30.0 / sampletime)])
864
1385
  if debug:
865
1386
  print("maximum deviation in samples:", maxsamps)