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.
- cloud/gmscalc-HCPYA +1 -1
- cloud/mount-and-run +2 -0
- cloud/rapidtide-HCPYA +3 -3
- rapidtide/Colortables.py +538 -38
- rapidtide/OrthoImageItem.py +1094 -51
- rapidtide/RapidtideDataset.py +1709 -114
- rapidtide/__init__.py +0 -8
- rapidtide/_version.py +4 -4
- rapidtide/calccoherence.py +242 -97
- rapidtide/calcnullsimfunc.py +240 -140
- rapidtide/calcsimfunc.py +314 -129
- rapidtide/correlate.py +1211 -389
- rapidtide/data/examples/src/testLD +56 -0
- rapidtide/data/examples/src/test_findmaxlag.py +2 -2
- rapidtide/data/examples/src/test_mlregressallt.py +32 -17
- rapidtide/data/examples/src/testalign +1 -1
- rapidtide/data/examples/src/testatlasaverage +35 -7
- rapidtide/data/examples/src/testboth +21 -0
- rapidtide/data/examples/src/testcifti +11 -0
- rapidtide/data/examples/src/testdelayvar +13 -0
- rapidtide/data/examples/src/testdlfilt +25 -0
- rapidtide/data/examples/src/testfft +35 -0
- rapidtide/data/examples/src/testfileorfloat +37 -0
- rapidtide/data/examples/src/testfmri +94 -27
- rapidtide/data/examples/src/testfuncs +3 -3
- rapidtide/data/examples/src/testglmfilt +8 -6
- rapidtide/data/examples/src/testhappy +84 -51
- rapidtide/data/examples/src/testinitdelay +19 -0
- rapidtide/data/examples/src/testmodels +33 -0
- rapidtide/data/examples/src/testnewrefine +26 -0
- rapidtide/data/examples/src/testnoiseamp +21 -0
- rapidtide/data/examples/src/testppgproc +17 -0
- rapidtide/data/examples/src/testrefineonly +22 -0
- rapidtide/data/examples/src/testretro +26 -13
- rapidtide/data/examples/src/testretrolagtcs +16 -0
- rapidtide/data/examples/src/testrolloff +11 -0
- rapidtide/data/examples/src/testsimdata +45 -28
- rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
- rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
- rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
- rapidtide/data/models/model_cnn_pytorch_fulldata/loss.png +0 -0
- rapidtide/data/models/model_cnn_pytorch_fulldata/loss.txt +1 -0
- rapidtide/data/models/model_cnn_pytorch_fulldata/model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch_fulldata/model_meta.json +80 -0
- rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.png +0 -0
- rapidtide/data/models/model_cnnbp_pytorch_fullldata/loss.txt +1 -0
- rapidtide/data/models/model_cnnbp_pytorch_fullldata/model.pth +0 -0
- rapidtide/data/models/model_cnnbp_pytorch_fullldata/model_meta.json +138 -0
- rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.png +0 -0
- rapidtide/data/models/model_cnnfft_pytorch_fulldata/loss.txt +1 -0
- rapidtide/data/models/model_cnnfft_pytorch_fulldata/model.pth +0 -0
- rapidtide/data/models/model_cnnfft_pytorch_fulldata/model_meta.json +128 -0
- rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.png +0 -0
- rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/loss.txt +1 -0
- rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model.pth +0 -0
- rapidtide/data/models/model_ppgattention_pytorch_w128_fulldata/model_meta.json +49 -0
- rapidtide/data/models/model_revised_tf2/model.keras +0 -0
- rapidtide/data/models/{model_serdar → model_revised_tf2}/model_meta.json +1 -1
- rapidtide/data/models/model_serdar2_tf2/model.keras +0 -0
- rapidtide/data/models/{model_serdar2 → model_serdar2_tf2}/model_meta.json +1 -1
- rapidtide/data/models/model_serdar_tf2/model.keras +0 -0
- rapidtide/data/models/{model_revised → model_serdar_tf2}/model_meta.json +1 -1
- rapidtide/data/reference/HCP1200v2_MTT_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_binmask_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_csf_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_gray_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_graylaghist.json +7 -0
- rapidtide/data/reference/HCP1200v2_graylaghist.tsv.gz +0 -0
- rapidtide/data/reference/HCP1200v2_laghist.json +7 -0
- rapidtide/data/reference/HCP1200v2_laghist.tsv.gz +0 -0
- rapidtide/data/reference/HCP1200v2_mask_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_maxcorr_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_maxtime_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_maxwidth_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_negmask_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_timepercentile_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_white_2mm.nii.gz +0 -0
- rapidtide/data/reference/HCP1200v2_whitelaghist.json +7 -0
- rapidtide/data/reference/HCP1200v2_whitelaghist.tsv.gz +0 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2.xml +131 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_regions.txt +60 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1-seg2_space-MNI152NLin6Asym_2mm.nii.gz +0 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm.nii.gz +0 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm_mask.nii.gz +0 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
- rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL2_space-MNI152NLin6Asym_2mm_mask.nii.gz +0 -0
- rapidtide/data/reference/MNI152_T1_1mm_Brain_FAST_seg.nii.gz +0 -0
- rapidtide/data/reference/MNI152_T1_1mm_Brain_Mask.nii.gz +0 -0
- rapidtide/data/reference/MNI152_T1_2mm_Brain_FAST_seg.nii.gz +0 -0
- rapidtide/data/reference/MNI152_T1_2mm_Brain_Mask.nii.gz +0 -0
- rapidtide/decorators.py +91 -0
- rapidtide/dlfilter.py +2553 -414
- rapidtide/dlfiltertorch.py +5201 -0
- rapidtide/externaltools.py +328 -13
- rapidtide/fMRIData_class.py +178 -0
- rapidtide/ffttools.py +168 -0
- rapidtide/filter.py +2704 -1462
- rapidtide/fit.py +2361 -579
- rapidtide/genericmultiproc.py +197 -0
- rapidtide/happy_supportfuncs.py +3255 -548
- rapidtide/helper_classes.py +590 -1181
- rapidtide/io.py +2569 -468
- rapidtide/linfitfiltpass.py +784 -0
- rapidtide/makelaggedtcs.py +267 -97
- rapidtide/maskutil.py +555 -25
- rapidtide/miscmath.py +867 -137
- rapidtide/multiproc.py +217 -44
- rapidtide/patchmatch.py +752 -0
- rapidtide/peakeval.py +32 -32
- rapidtide/ppgproc.py +2205 -0
- rapidtide/qualitycheck.py +353 -40
- rapidtide/refinedelay.py +854 -0
- rapidtide/refineregressor.py +939 -0
- rapidtide/resample.py +725 -204
- rapidtide/scripts/__init__.py +1 -0
- rapidtide/scripts/{adjustoffset → adjustoffset.py} +7 -2
- rapidtide/scripts/{aligntcs → aligntcs.py} +7 -2
- rapidtide/scripts/{applydlfilter → applydlfilter.py} +7 -2
- rapidtide/scripts/applyppgproc.py +28 -0
- rapidtide/scripts/{atlasaverage → atlasaverage.py} +7 -2
- rapidtide/scripts/{atlastool → atlastool.py} +7 -2
- rapidtide/scripts/{calcicc → calcicc.py} +7 -2
- rapidtide/scripts/{calctexticc → calctexticc.py} +7 -2
- rapidtide/scripts/{calcttest → calcttest.py} +7 -2
- rapidtide/scripts/{ccorrica → ccorrica.py} +7 -2
- rapidtide/scripts/delayvar.py +28 -0
- rapidtide/scripts/{diffrois → diffrois.py} +7 -2
- rapidtide/scripts/{endtidalproc → endtidalproc.py} +7 -2
- rapidtide/scripts/{fdica → fdica.py} +7 -2
- rapidtide/scripts/{filtnifti → filtnifti.py} +7 -2
- rapidtide/scripts/{filttc → filttc.py} +7 -2
- rapidtide/scripts/{fingerprint → fingerprint.py} +20 -16
- rapidtide/scripts/{fixtr → fixtr.py} +7 -2
- rapidtide/scripts/{gmscalc → gmscalc.py} +7 -2
- rapidtide/scripts/{happy → happy.py} +7 -2
- rapidtide/scripts/{happy2std → happy2std.py} +7 -2
- rapidtide/scripts/{happywarp → happywarp.py} +8 -4
- rapidtide/scripts/{histnifti → histnifti.py} +7 -2
- rapidtide/scripts/{histtc → histtc.py} +7 -2
- rapidtide/scripts/{glmfilt → linfitfilt.py} +7 -4
- rapidtide/scripts/{localflow → localflow.py} +7 -2
- rapidtide/scripts/{mergequality → mergequality.py} +7 -2
- rapidtide/scripts/{pairproc → pairproc.py} +7 -2
- rapidtide/scripts/{pairwisemergenifti → pairwisemergenifti.py} +7 -2
- rapidtide/scripts/{physiofreq → physiofreq.py} +7 -2
- rapidtide/scripts/{pixelcomp → pixelcomp.py} +7 -2
- rapidtide/scripts/{plethquality → plethquality.py} +7 -2
- rapidtide/scripts/{polyfitim → polyfitim.py} +7 -2
- rapidtide/scripts/{proj2flow → proj2flow.py} +7 -2
- rapidtide/scripts/{rankimage → rankimage.py} +7 -2
- rapidtide/scripts/{rapidtide → rapidtide.py} +7 -2
- rapidtide/scripts/{rapidtide2std → rapidtide2std.py} +7 -2
- rapidtide/scripts/{resamplenifti → resamplenifti.py} +7 -2
- rapidtide/scripts/{resampletc → resampletc.py} +7 -2
- rapidtide/scripts/retrolagtcs.py +28 -0
- rapidtide/scripts/retroregress.py +28 -0
- rapidtide/scripts/{roisummarize → roisummarize.py} +7 -2
- rapidtide/scripts/{runqualitycheck → runqualitycheck.py} +7 -2
- rapidtide/scripts/{showarbcorr → showarbcorr.py} +7 -2
- rapidtide/scripts/{showhist → showhist.py} +7 -2
- rapidtide/scripts/{showstxcorr → showstxcorr.py} +7 -2
- rapidtide/scripts/{showtc → showtc.py} +7 -2
- rapidtide/scripts/{showxcorr_legacy → showxcorr_legacy.py} +8 -8
- rapidtide/scripts/{showxcorrx → showxcorrx.py} +7 -2
- rapidtide/scripts/{showxy → showxy.py} +7 -2
- rapidtide/scripts/{simdata → simdata.py} +7 -2
- rapidtide/scripts/{spatialdecomp → spatialdecomp.py} +7 -2
- rapidtide/scripts/{spatialfit → spatialfit.py} +7 -2
- rapidtide/scripts/{spatialmi → spatialmi.py} +7 -2
- rapidtide/scripts/{spectrogram → spectrogram.py} +7 -2
- rapidtide/scripts/stupidramtricks.py +238 -0
- rapidtide/scripts/{synthASL → synthASL.py} +7 -2
- rapidtide/scripts/{tcfrom2col → tcfrom2col.py} +7 -2
- rapidtide/scripts/{tcfrom3col → tcfrom3col.py} +7 -2
- rapidtide/scripts/{temporaldecomp → temporaldecomp.py} +7 -2
- rapidtide/scripts/{testhrv → testhrv.py} +1 -1
- rapidtide/scripts/{threeD → threeD.py} +7 -2
- rapidtide/scripts/{tidepool → tidepool.py} +7 -2
- rapidtide/scripts/{variabilityizer → variabilityizer.py} +7 -2
- rapidtide/simFuncClasses.py +2113 -0
- rapidtide/simfuncfit.py +312 -108
- rapidtide/stats.py +579 -247
- rapidtide/tests/.coveragerc +27 -6
- rapidtide-2.9.5.data/scripts/fdica → rapidtide/tests/cleanposttest +4 -6
- rapidtide/tests/happycomp +9 -0
- rapidtide/tests/resethappytargets +1 -1
- rapidtide/tests/resetrapidtidetargets +1 -1
- rapidtide/tests/resettargets +1 -1
- rapidtide/tests/runlocaltest +3 -3
- rapidtide/tests/showkernels +1 -1
- rapidtide/tests/test_aliasedcorrelate.py +4 -4
- rapidtide/tests/test_aligntcs.py +1 -1
- rapidtide/tests/test_calcicc.py +1 -1
- rapidtide/tests/test_cleanregressor.py +184 -0
- rapidtide/tests/test_congrid.py +70 -81
- rapidtide/tests/test_correlate.py +1 -1
- rapidtide/tests/test_corrpass.py +4 -4
- rapidtide/tests/test_delayestimation.py +54 -59
- rapidtide/tests/test_dlfiltertorch.py +437 -0
- rapidtide/tests/test_doresample.py +2 -2
- rapidtide/tests/test_externaltools.py +69 -0
- rapidtide/tests/test_fastresampler.py +9 -5
- rapidtide/tests/test_filter.py +96 -57
- rapidtide/tests/test_findmaxlag.py +50 -19
- rapidtide/tests/test_fullrunhappy_v1.py +15 -10
- rapidtide/tests/test_fullrunhappy_v2.py +19 -13
- rapidtide/tests/test_fullrunhappy_v3.py +28 -13
- rapidtide/tests/test_fullrunhappy_v4.py +30 -11
- rapidtide/tests/test_fullrunhappy_v5.py +62 -0
- rapidtide/tests/test_fullrunrapidtide_v1.py +61 -7
- rapidtide/tests/test_fullrunrapidtide_v2.py +27 -15
- rapidtide/tests/test_fullrunrapidtide_v3.py +28 -8
- rapidtide/tests/test_fullrunrapidtide_v4.py +16 -8
- rapidtide/tests/test_fullrunrapidtide_v5.py +15 -6
- rapidtide/tests/test_fullrunrapidtide_v6.py +142 -0
- rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
- rapidtide/tests/test_fullrunrapidtide_v8.py +66 -0
- rapidtide/tests/test_getparsers.py +158 -0
- rapidtide/tests/test_io.py +59 -18
- rapidtide/tests/{test_glmpass.py → test_linfitfiltpass.py} +10 -10
- rapidtide/tests/test_mi.py +1 -1
- rapidtide/tests/test_miscmath.py +1 -1
- rapidtide/tests/test_motionregress.py +5 -5
- rapidtide/tests/test_nullcorr.py +6 -9
- rapidtide/tests/test_padvec.py +216 -0
- rapidtide/tests/test_parserfuncs.py +101 -0
- rapidtide/tests/test_phaseanalysis.py +1 -1
- rapidtide/tests/test_rapidtideparser.py +59 -53
- rapidtide/tests/test_refinedelay.py +296 -0
- rapidtide/tests/test_runmisc.py +5 -5
- rapidtide/tests/test_sharedmem.py +60 -0
- rapidtide/tests/test_simroundtrip.py +132 -0
- rapidtide/tests/test_simulate.py +1 -1
- rapidtide/tests/test_stcorrelate.py +4 -2
- rapidtide/tests/test_timeshift.py +2 -2
- rapidtide/tests/test_valtoindex.py +1 -1
- rapidtide/tests/test_zRapidtideDataset.py +5 -3
- rapidtide/tests/utils.py +10 -9
- rapidtide/tidepoolTemplate.py +88 -70
- rapidtide/tidepoolTemplate.ui +60 -46
- rapidtide/tidepoolTemplate_alt.py +88 -53
- rapidtide/tidepoolTemplate_alt.ui +62 -52
- rapidtide/tidepoolTemplate_alt_qt6.py +921 -0
- rapidtide/tidepoolTemplate_big.py +1125 -0
- rapidtide/tidepoolTemplate_big.ui +2386 -0
- rapidtide/tidepoolTemplate_big_qt6.py +1129 -0
- rapidtide/tidepoolTemplate_qt6.py +793 -0
- rapidtide/util.py +1389 -148
- rapidtide/voxelData.py +1048 -0
- rapidtide/wiener.py +138 -25
- rapidtide/wiener2.py +114 -8
- rapidtide/workflows/adjustoffset.py +107 -5
- rapidtide/workflows/aligntcs.py +86 -3
- rapidtide/workflows/applydlfilter.py +231 -89
- rapidtide/workflows/applyppgproc.py +540 -0
- rapidtide/workflows/atlasaverage.py +309 -48
- rapidtide/workflows/atlastool.py +130 -9
- rapidtide/workflows/calcSimFuncMap.py +490 -0
- rapidtide/workflows/calctexticc.py +202 -10
- rapidtide/workflows/ccorrica.py +123 -15
- rapidtide/workflows/cleanregressor.py +415 -0
- rapidtide/workflows/delayvar.py +1268 -0
- rapidtide/workflows/diffrois.py +84 -6
- rapidtide/workflows/endtidalproc.py +149 -9
- rapidtide/workflows/fdica.py +197 -17
- rapidtide/workflows/filtnifti.py +71 -4
- rapidtide/workflows/filttc.py +76 -5
- rapidtide/workflows/fitSimFuncMap.py +578 -0
- rapidtide/workflows/fixtr.py +74 -4
- rapidtide/workflows/gmscalc.py +116 -6
- rapidtide/workflows/happy.py +1242 -480
- rapidtide/workflows/happy2std.py +145 -13
- rapidtide/workflows/happy_parser.py +277 -59
- rapidtide/workflows/histnifti.py +120 -4
- rapidtide/workflows/histtc.py +85 -4
- rapidtide/workflows/{glmfilt.py → linfitfilt.py} +128 -14
- rapidtide/workflows/localflow.py +329 -29
- rapidtide/workflows/mergequality.py +80 -4
- rapidtide/workflows/niftidecomp.py +323 -19
- rapidtide/workflows/niftistats.py +178 -8
- rapidtide/workflows/pairproc.py +99 -5
- rapidtide/workflows/pairwisemergenifti.py +86 -3
- rapidtide/workflows/parser_funcs.py +1488 -56
- rapidtide/workflows/physiofreq.py +139 -12
- rapidtide/workflows/pixelcomp.py +211 -9
- rapidtide/workflows/plethquality.py +105 -23
- rapidtide/workflows/polyfitim.py +159 -19
- rapidtide/workflows/proj2flow.py +76 -3
- rapidtide/workflows/rankimage.py +115 -8
- rapidtide/workflows/rapidtide.py +1833 -1919
- rapidtide/workflows/rapidtide2std.py +101 -3
- rapidtide/workflows/rapidtide_parser.py +607 -372
- rapidtide/workflows/refineDelayMap.py +249 -0
- rapidtide/workflows/refineRegressor.py +1215 -0
- rapidtide/workflows/regressfrommaps.py +308 -0
- rapidtide/workflows/resamplenifti.py +86 -4
- rapidtide/workflows/resampletc.py +92 -4
- rapidtide/workflows/retrolagtcs.py +442 -0
- rapidtide/workflows/retroregress.py +1501 -0
- rapidtide/workflows/roisummarize.py +176 -7
- rapidtide/workflows/runqualitycheck.py +72 -7
- rapidtide/workflows/showarbcorr.py +172 -16
- rapidtide/workflows/showhist.py +87 -3
- rapidtide/workflows/showstxcorr.py +161 -4
- rapidtide/workflows/showtc.py +172 -10
- rapidtide/workflows/showxcorrx.py +250 -62
- rapidtide/workflows/showxy.py +186 -16
- rapidtide/workflows/simdata.py +418 -112
- rapidtide/workflows/spatialfit.py +83 -8
- rapidtide/workflows/spatialmi.py +252 -29
- rapidtide/workflows/spectrogram.py +306 -33
- rapidtide/workflows/synthASL.py +157 -6
- rapidtide/workflows/tcfrom2col.py +77 -3
- rapidtide/workflows/tcfrom3col.py +75 -3
- rapidtide/workflows/tidepool.py +3829 -666
- rapidtide/workflows/utils.py +45 -19
- rapidtide/workflows/utils_doc.py +293 -0
- rapidtide/workflows/variabilityizer.py +118 -5
- {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/METADATA +30 -223
- rapidtide-3.1.3.dist-info/RECORD +393 -0
- {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info}/WHEEL +1 -1
- rapidtide-3.1.3.dist-info/entry_points.txt +65 -0
- rapidtide-3.1.3.dist-info/top_level.txt +2 -0
- rapidtide/calcandfitcorrpairs.py +0 -262
- rapidtide/data/examples/src/testoutputsize +0 -45
- rapidtide/data/models/model_revised/model.h5 +0 -0
- rapidtide/data/models/model_serdar/model.h5 +0 -0
- rapidtide/data/models/model_serdar2/model.h5 +0 -0
- rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm.nii.gz +0 -0
- rapidtide/data/reference/ASPECTS_nlin_asym_09c_2mm_mask.nii.gz +0 -0
- rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm.nii.gz +0 -0
- rapidtide/data/reference/ATTbasedFlowTerritories_split_nlin_asym_09c_2mm_mask.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_binmask_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_lag_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_mask_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_negmask_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_sigma_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/data/reference/HCP1200_strength_2mm_2009c_asym.nii.gz +0 -0
- rapidtide/glmpass.py +0 -434
- rapidtide/refine_factored.py +0 -641
- rapidtide/scripts/retroglm +0 -23
- rapidtide/workflows/glmfrommaps.py +0 -202
- rapidtide/workflows/retroglm.py +0 -643
- rapidtide-2.9.5.data/scripts/adjustoffset +0 -23
- rapidtide-2.9.5.data/scripts/aligntcs +0 -23
- rapidtide-2.9.5.data/scripts/applydlfilter +0 -23
- rapidtide-2.9.5.data/scripts/atlasaverage +0 -23
- rapidtide-2.9.5.data/scripts/atlastool +0 -23
- rapidtide-2.9.5.data/scripts/calcicc +0 -22
- rapidtide-2.9.5.data/scripts/calctexticc +0 -23
- rapidtide-2.9.5.data/scripts/calcttest +0 -22
- rapidtide-2.9.5.data/scripts/ccorrica +0 -23
- rapidtide-2.9.5.data/scripts/diffrois +0 -23
- rapidtide-2.9.5.data/scripts/endtidalproc +0 -23
- rapidtide-2.9.5.data/scripts/filtnifti +0 -23
- rapidtide-2.9.5.data/scripts/filttc +0 -23
- rapidtide-2.9.5.data/scripts/fingerprint +0 -593
- rapidtide-2.9.5.data/scripts/fixtr +0 -23
- rapidtide-2.9.5.data/scripts/glmfilt +0 -24
- rapidtide-2.9.5.data/scripts/gmscalc +0 -22
- rapidtide-2.9.5.data/scripts/happy +0 -25
- rapidtide-2.9.5.data/scripts/happy2std +0 -23
- rapidtide-2.9.5.data/scripts/happywarp +0 -350
- rapidtide-2.9.5.data/scripts/histnifti +0 -23
- rapidtide-2.9.5.data/scripts/histtc +0 -23
- rapidtide-2.9.5.data/scripts/localflow +0 -23
- rapidtide-2.9.5.data/scripts/mergequality +0 -23
- rapidtide-2.9.5.data/scripts/pairproc +0 -23
- rapidtide-2.9.5.data/scripts/pairwisemergenifti +0 -23
- rapidtide-2.9.5.data/scripts/physiofreq +0 -23
- rapidtide-2.9.5.data/scripts/pixelcomp +0 -23
- rapidtide-2.9.5.data/scripts/plethquality +0 -23
- rapidtide-2.9.5.data/scripts/polyfitim +0 -23
- rapidtide-2.9.5.data/scripts/proj2flow +0 -23
- rapidtide-2.9.5.data/scripts/rankimage +0 -23
- rapidtide-2.9.5.data/scripts/rapidtide +0 -23
- rapidtide-2.9.5.data/scripts/rapidtide2std +0 -23
- rapidtide-2.9.5.data/scripts/resamplenifti +0 -23
- rapidtide-2.9.5.data/scripts/resampletc +0 -23
- rapidtide-2.9.5.data/scripts/retroglm +0 -23
- rapidtide-2.9.5.data/scripts/roisummarize +0 -23
- rapidtide-2.9.5.data/scripts/runqualitycheck +0 -23
- rapidtide-2.9.5.data/scripts/showarbcorr +0 -23
- rapidtide-2.9.5.data/scripts/showhist +0 -23
- rapidtide-2.9.5.data/scripts/showstxcorr +0 -23
- rapidtide-2.9.5.data/scripts/showtc +0 -23
- rapidtide-2.9.5.data/scripts/showxcorr_legacy +0 -536
- rapidtide-2.9.5.data/scripts/showxcorrx +0 -23
- rapidtide-2.9.5.data/scripts/showxy +0 -23
- rapidtide-2.9.5.data/scripts/simdata +0 -23
- rapidtide-2.9.5.data/scripts/spatialdecomp +0 -23
- rapidtide-2.9.5.data/scripts/spatialfit +0 -23
- rapidtide-2.9.5.data/scripts/spatialmi +0 -23
- rapidtide-2.9.5.data/scripts/spectrogram +0 -23
- rapidtide-2.9.5.data/scripts/synthASL +0 -23
- rapidtide-2.9.5.data/scripts/tcfrom2col +0 -23
- rapidtide-2.9.5.data/scripts/tcfrom3col +0 -23
- rapidtide-2.9.5.data/scripts/temporaldecomp +0 -23
- rapidtide-2.9.5.data/scripts/threeD +0 -236
- rapidtide-2.9.5.data/scripts/tidepool +0 -23
- rapidtide-2.9.5.data/scripts/variabilityizer +0 -23
- rapidtide-2.9.5.dist-info/RECORD +0 -357
- rapidtide-2.9.5.dist-info/top_level.txt +0 -86
- {rapidtide-2.9.5.dist-info → rapidtide-3.1.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2016-2025 Blaise Frederick
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
#
|
|
19
|
+
import gc
|
|
20
|
+
import logging
|
|
21
|
+
import sys
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
import numpy as np
|
|
25
|
+
import statsmodels as sm
|
|
26
|
+
from numpy.typing import NDArray
|
|
27
|
+
from scipy.stats import pearsonr
|
|
28
|
+
from sklearn.decomposition import PCA, FastICA
|
|
29
|
+
|
|
30
|
+
import rapidtide.fit as tide_fit
|
|
31
|
+
import rapidtide.genericmultiproc as tide_genericmultiproc
|
|
32
|
+
import rapidtide.io as tide_io
|
|
33
|
+
import rapidtide.miscmath as tide_math
|
|
34
|
+
import rapidtide.resample as tide_resample
|
|
35
|
+
import rapidtide.stats as tide_stats
|
|
36
|
+
|
|
37
|
+
LGR = logging.getLogger("GENERAL")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _procOneVoxelTimeShift(
|
|
41
|
+
vox: int,
|
|
42
|
+
voxelargs: tuple,
|
|
43
|
+
**kwargs: Any,
|
|
44
|
+
) -> tuple[int, NDArray, NDArray, NDArray, NDArray]:
|
|
45
|
+
options = {
|
|
46
|
+
"detrendorder": 1,
|
|
47
|
+
"offsettime": 0.0,
|
|
48
|
+
"debug": False,
|
|
49
|
+
}
|
|
50
|
+
options.update(kwargs)
|
|
51
|
+
detrendorder = int(options["detrendorder"])
|
|
52
|
+
offsettime = options["offsettime"]
|
|
53
|
+
debug = options["debug"]
|
|
54
|
+
if debug:
|
|
55
|
+
print(f"{detrendorder=} {offsettime=}")
|
|
56
|
+
(
|
|
57
|
+
fmritc,
|
|
58
|
+
lagtime,
|
|
59
|
+
padtrs,
|
|
60
|
+
fmritr,
|
|
61
|
+
) = voxelargs
|
|
62
|
+
if detrendorder > 0:
|
|
63
|
+
normtc = tide_fit.detrend(fmritc, order=detrendorder, demean=True)
|
|
64
|
+
else:
|
|
65
|
+
normtc = fmritc + 0.0
|
|
66
|
+
shifttr = -(-offsettime + lagtime) / fmritr # lagtime is in seconds
|
|
67
|
+
[shiftedtc, weights, paddedshiftedtc, paddedweights] = tide_resample.timeshift(
|
|
68
|
+
normtc, shifttr, padtrs
|
|
69
|
+
)
|
|
70
|
+
return vox, shiftedtc, weights, paddedshiftedtc, paddedweights
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _packvoxeldata(voxnum: int, voxelargs: tuple) -> list:
|
|
74
|
+
"""
|
|
75
|
+
Pack voxel data into a list structure.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
voxnum : int
|
|
80
|
+
The voxel index to extract data from.
|
|
81
|
+
voxelargs : tuple
|
|
82
|
+
A tuple containing voxel data with the following structure:
|
|
83
|
+
- voxelargs[0]: 2D array of shape (n_voxels, n_features) containing voxel features
|
|
84
|
+
- voxelargs[1]: 1D array of shape (n_voxels,) containing voxel labels or values
|
|
85
|
+
- voxelargs[2]: Additional voxel parameter (type depends on context)
|
|
86
|
+
- voxelargs[3]: Additional voxel parameter (type depends on context)
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
list
|
|
91
|
+
A list containing:
|
|
92
|
+
- [0]: 1D array of shape (n_features,) representing voxel features at voxnum
|
|
93
|
+
- [1]: scalar value representing voxel label or value at voxnum
|
|
94
|
+
- [2]: third element from voxelargs tuple
|
|
95
|
+
- [3]: fourth element from voxelargs tuple
|
|
96
|
+
|
|
97
|
+
Notes
|
|
98
|
+
-----
|
|
99
|
+
This function is typically used for extracting and packaging voxel data for further processing
|
|
100
|
+
in neuroimaging or 3D data analysis workflows.
|
|
101
|
+
|
|
102
|
+
Examples
|
|
103
|
+
--------
|
|
104
|
+
>>> voxel_features = np.array([[1, 2, 3], [4, 5, 6]])
|
|
105
|
+
>>> voxel_labels = np.array([10, 20])
|
|
106
|
+
>>> extra_param1 = "param1"
|
|
107
|
+
>>> extra_param2 = "param2"
|
|
108
|
+
>>> result = _packvoxeldata(0, (voxel_features, voxel_labels, extra_param1, extra_param2))
|
|
109
|
+
>>> print(result)
|
|
110
|
+
[[1, 2, 3], 10, 'param1', 'param2']
|
|
111
|
+
"""
|
|
112
|
+
return [(voxelargs[0])[voxnum, :], (voxelargs[1])[voxnum], voxelargs[2], voxelargs[3]]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _unpackvoxeldata(retvals: tuple, voxelproducts: list) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Unpack voxel data from retvals into voxelproducts arrays.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
retvals : tuple
|
|
122
|
+
Tuple containing voxel data to be unpacked. Expected to contain at least 5 elements
|
|
123
|
+
where retvals[0] is the index for assignment and retvals[1:5] are the data arrays.
|
|
124
|
+
voxelproducts : list
|
|
125
|
+
List of arrays where voxel data will be unpacked. Expected to contain exactly 4 arrays
|
|
126
|
+
that will be modified in-place.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
None
|
|
131
|
+
This function modifies the voxelproducts arrays in-place and does not return anything.
|
|
132
|
+
|
|
133
|
+
Notes
|
|
134
|
+
-----
|
|
135
|
+
This function performs in-place assignment of voxel data. The first element of retvals
|
|
136
|
+
is used as an index for row-wise assignment into each of the four arrays in voxelproducts.
|
|
137
|
+
All arrays in voxelproducts must have sufficient dimensions to accommodate the assignment.
|
|
138
|
+
|
|
139
|
+
Examples
|
|
140
|
+
--------
|
|
141
|
+
>>> import numpy as np
|
|
142
|
+
>>> voxel_data = [np.zeros((10, 5)), np.zeros((10, 5)), np.zeros((10, 5)), np.zeros((10, 5))]
|
|
143
|
+
>>> retvals = (2, np.array([1, 2, 3, 4, 5]), np.array([6, 7, 8, 9, 10]),
|
|
144
|
+
... np.array([11, 12, 13, 14, 15]), np.array([16, 17, 18, 19, 20]))
|
|
145
|
+
>>> _unpackvoxeldata(retvals, voxel_data)
|
|
146
|
+
>>> print(voxel_data[0][2, :]) # Should print [1 2 3 4 5]
|
|
147
|
+
"""
|
|
148
|
+
(voxelproducts[0])[retvals[0], :] = retvals[1]
|
|
149
|
+
(voxelproducts[1])[retvals[0], :] = retvals[2]
|
|
150
|
+
(voxelproducts[2])[retvals[0], :] = retvals[3]
|
|
151
|
+
(voxelproducts[3])[retvals[0], :] = retvals[4]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def findecho(
|
|
155
|
+
nlags: int,
|
|
156
|
+
shiftedtcs: NDArray,
|
|
157
|
+
sigmav: NDArray,
|
|
158
|
+
arcoefs: NDArray,
|
|
159
|
+
pacf: NDArray,
|
|
160
|
+
sigma: NDArray,
|
|
161
|
+
phi: NDArray,
|
|
162
|
+
) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Compute autoregressive parameters and related statistics for each voxel using Levinson-Durbin recursion.
|
|
165
|
+
|
|
166
|
+
This function applies the Levinson-Durbin algorithm to estimate autoregressive coefficients
|
|
167
|
+
and associated statistics for time series data from multiple voxels. The algorithm computes
|
|
168
|
+
the variance, autoregressive coefficients, partial autocorrelations, and other related
|
|
169
|
+
parameters for each voxel's time series.
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
nlags : int
|
|
174
|
+
Number of lags to compute for the autoregressive model.
|
|
175
|
+
shiftedtcs : NDArray
|
|
176
|
+
Input time series data with shape (n_voxels, n_timepoints), where each row represents
|
|
177
|
+
a voxel's time series.
|
|
178
|
+
sigmav : NDArray
|
|
179
|
+
Output array for variance estimates, shape (n_voxels,).
|
|
180
|
+
arcoefs : NDArray
|
|
181
|
+
Output array for autoregressive coefficients, shape (n_voxels, nlags).
|
|
182
|
+
pacf : NDArray
|
|
183
|
+
Output array for partial autocorrelations, shape (n_voxels, nlags).
|
|
184
|
+
sigma : NDArray
|
|
185
|
+
Output array for sigma values, shape (n_voxels, nlags).
|
|
186
|
+
phi : NDArray
|
|
187
|
+
Output array for phi values, shape (n_voxels, nlags).
|
|
188
|
+
|
|
189
|
+
Returns
|
|
190
|
+
-------
|
|
191
|
+
None
|
|
192
|
+
This function modifies the input arrays in-place and does not return any value.
|
|
193
|
+
|
|
194
|
+
Notes
|
|
195
|
+
-----
|
|
196
|
+
The function uses `statsmodels.tsa.stattools.levinson_durbin` to compute the autoregressive
|
|
197
|
+
parameters. This algorithm is efficient for computing autoregressive parameters and is
|
|
198
|
+
commonly used in time series analysis for estimating model parameters.
|
|
199
|
+
|
|
200
|
+
Examples
|
|
201
|
+
--------
|
|
202
|
+
>>> import numpy as np
|
|
203
|
+
>>> from statsmodels.tsa import stattools
|
|
204
|
+
>>> nlags = 5
|
|
205
|
+
>>> shiftedtcs = np.random.randn(100, 1000)
|
|
206
|
+
>>> sigmav = np.zeros(100)
|
|
207
|
+
>>> arcoefs = np.zeros((100, 5))
|
|
208
|
+
>>> pacf = np.zeros((100, 5))
|
|
209
|
+
>>> sigma = np.zeros((100, 5))
|
|
210
|
+
>>> phi = np.zeros((100, 5))
|
|
211
|
+
>>> findecho(nlags, shiftedtcs, sigmav, arcoefs, pacf, sigma, phi)
|
|
212
|
+
"""
|
|
213
|
+
inputshape = np.shape(shiftedtcs)
|
|
214
|
+
for voxel in range(inputshape[0]):
|
|
215
|
+
sigmav[voxel], arcoefs[voxel, :], pacf[voxel, :], sigma[voxel, :], phi[voxel, :] = (
|
|
216
|
+
sm.tsa.stattools.levinson_durbin(shiftedtcs[voxel, :], nlags=nlags, isacov=False)
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def alignvoxels(
|
|
221
|
+
fmridata: NDArray,
|
|
222
|
+
fmritr: float,
|
|
223
|
+
shiftedtcs: NDArray,
|
|
224
|
+
weights: NDArray,
|
|
225
|
+
paddedshiftedtcs: NDArray,
|
|
226
|
+
paddedweights: NDArray,
|
|
227
|
+
lagtimes: NDArray,
|
|
228
|
+
lagmask: NDArray,
|
|
229
|
+
detrendorder: int = 1,
|
|
230
|
+
offsettime: float = 0.0,
|
|
231
|
+
nprocs: int = 1,
|
|
232
|
+
alwaysmultiproc: bool = False,
|
|
233
|
+
showprogressbar: bool = True,
|
|
234
|
+
chunksize: int = 1000,
|
|
235
|
+
padtrs: int = 60,
|
|
236
|
+
debug: bool = False,
|
|
237
|
+
rt_floattype: np.dtype = np.float64,
|
|
238
|
+
) -> int:
|
|
239
|
+
"""
|
|
240
|
+
Apply temporal alignment (timeshift) to all voxels in fMRI data based on correlation peaks.
|
|
241
|
+
|
|
242
|
+
This routine applies a time shift to every voxel in the fMRI data based on the lag times
|
|
243
|
+
determined from cross-correlation with a reference signal. The function modifies the input
|
|
244
|
+
arrays in-place to store the aligned timecourses and associated weights.
|
|
245
|
+
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
fmridata : 4D NDArray
|
|
249
|
+
fMRI data, filtered to the passband, with shape (nx, ny, nz, nt)
|
|
250
|
+
fmritr : float
|
|
251
|
+
Data repetition time (TR), in seconds
|
|
252
|
+
shiftedtcs : 4D NDArray
|
|
253
|
+
Destination array for time-aligned voxel timecourses, shape (nx, ny, nz, nt)
|
|
254
|
+
weights : 4D NDArray
|
|
255
|
+
Weights for each timepoint in the final regressor, shape (nx, ny, nz, nt)
|
|
256
|
+
paddedshiftedtcs : 4D NDArray
|
|
257
|
+
Time-aligned voxel timecourses with padding, shape (nx, ny, nz, nt + 2*padtrs)
|
|
258
|
+
paddedweights : 4D NDArray
|
|
259
|
+
Weights for each timepoint in the padded regressor, shape (nx, ny, nz, nt + 2*padtrs)
|
|
260
|
+
lagtimes : 3D NDArray
|
|
261
|
+
Time delay of maximum crosscorrelation in seconds, shape (nx, ny, nz)
|
|
262
|
+
lagmask : 3D NDArray
|
|
263
|
+
Mask of voxels with successful correlation fits, shape (nx, ny, nz)
|
|
264
|
+
detrendorder : int, optional
|
|
265
|
+
Order of polynomial used to detrend the data (default is 1)
|
|
266
|
+
offsettime : float, optional
|
|
267
|
+
Global time shift to apply to all timecourses in seconds (default is 0.0)
|
|
268
|
+
nprocs : int, optional
|
|
269
|
+
Number of processes to use for multiprocessing (default is 1)
|
|
270
|
+
alwaysmultiproc : bool, optional
|
|
271
|
+
If True, always use multiprocessing even for small datasets (default is False)
|
|
272
|
+
showprogressbar : bool, optional
|
|
273
|
+
If True, show a progress bar during processing (default is True)
|
|
274
|
+
chunksize : int, optional
|
|
275
|
+
Number of voxels to process per chunk in multiprocessing (default is 1000)
|
|
276
|
+
padtrs : int, optional
|
|
277
|
+
Number of timepoints to pad on each end of the timecourses (default is 60)
|
|
278
|
+
debug : bool, optional
|
|
279
|
+
If True, enable additional debugging output (default is False)
|
|
280
|
+
rt_floattype : np.dtype, optional
|
|
281
|
+
Function to coerce variable types (default is np.float64)
|
|
282
|
+
|
|
283
|
+
Returns
|
|
284
|
+
-------
|
|
285
|
+
volumetotal : int
|
|
286
|
+
Total number of voxels processed
|
|
287
|
+
|
|
288
|
+
Notes
|
|
289
|
+
-----
|
|
290
|
+
This function modifies the input arrays `shiftedtcs`, `weights`, `paddedshiftedtcs`, and
|
|
291
|
+
`paddedweights` in-place. The `lagtimes` and `lagmask` arrays are used to determine the
|
|
292
|
+
appropriate time shifts for each voxel.
|
|
293
|
+
|
|
294
|
+
Examples
|
|
295
|
+
--------
|
|
296
|
+
>>> import numpy as np
|
|
297
|
+
>>> from rapidtide import alignvoxels
|
|
298
|
+
>>> fmridata = np.random.rand(64, 64, 32, 100)
|
|
299
|
+
>>> fmritr = 2.0
|
|
300
|
+
>>> shiftedtcs = np.zeros_like(fmridata)
|
|
301
|
+
>>> weights = np.ones_like(fmridata)
|
|
302
|
+
>>> paddedshiftedtcs = np.zeros((64, 64, 32, 100 + 2*60))
|
|
303
|
+
>>> paddedweights = np.ones((64, 64, 32, 100 + 2*60))
|
|
304
|
+
>>> lagtimes = np.random.rand(64, 64, 32)
|
|
305
|
+
>>> lagmask = np.ones((64, 64, 32))
|
|
306
|
+
>>> volumetotal = alignvoxels(
|
|
307
|
+
... fmridata, fmritr, shiftedtcs, weights, paddedshiftedtcs, paddedweights,
|
|
308
|
+
... lagtimes, lagmask, nprocs=4
|
|
309
|
+
... )
|
|
310
|
+
>>> print(f"Processed {volumetotal} voxels")
|
|
311
|
+
"""
|
|
312
|
+
inputshape = np.shape(fmridata)
|
|
313
|
+
voxelargs = [fmridata, lagtimes, padtrs, fmritr]
|
|
314
|
+
voxelfunc = _procOneVoxelTimeShift
|
|
315
|
+
packfunc = _packvoxeldata
|
|
316
|
+
unpackfunc = _unpackvoxeldata
|
|
317
|
+
voxeltargets = [
|
|
318
|
+
shiftedtcs,
|
|
319
|
+
weights,
|
|
320
|
+
paddedshiftedtcs,
|
|
321
|
+
paddedweights,
|
|
322
|
+
]
|
|
323
|
+
if debug:
|
|
324
|
+
print("alignvoxels: {inputshape}")
|
|
325
|
+
print("volumetotal: {volumetotal}")
|
|
326
|
+
|
|
327
|
+
# timeshift the valid voxels
|
|
328
|
+
# NOTE need to figure out how to use kwargs to pass extra arguments
|
|
329
|
+
volumetotal = tide_genericmultiproc.run_multiproc(
|
|
330
|
+
voxelfunc,
|
|
331
|
+
packfunc,
|
|
332
|
+
unpackfunc,
|
|
333
|
+
voxelargs,
|
|
334
|
+
voxeltargets,
|
|
335
|
+
inputshape,
|
|
336
|
+
lagmask,
|
|
337
|
+
LGR,
|
|
338
|
+
nprocs,
|
|
339
|
+
alwaysmultiproc,
|
|
340
|
+
showprogressbar,
|
|
341
|
+
chunksize,
|
|
342
|
+
detrendorder=detrendorder,
|
|
343
|
+
offsettime=offsettime,
|
|
344
|
+
debug=debug,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
LGR.info(
|
|
348
|
+
"Timeshift applied to " + str(int(volumetotal)) + " voxels",
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# garbage collect
|
|
352
|
+
uncollected = gc.collect()
|
|
353
|
+
if uncollected != 0:
|
|
354
|
+
LGR.info(f"garbage collected - unable to collect {uncollected} objects")
|
|
355
|
+
else:
|
|
356
|
+
LGR.info("garbage collected")
|
|
357
|
+
|
|
358
|
+
return volumetotal
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def makerefinemask(
|
|
362
|
+
lagstrengths: NDArray,
|
|
363
|
+
lagtimes: NDArray,
|
|
364
|
+
lagsigma: NDArray,
|
|
365
|
+
lagmask: NDArray,
|
|
366
|
+
offsettime: float = 0.0,
|
|
367
|
+
ampthresh: float = 0.3,
|
|
368
|
+
lagmaskside: str = "both",
|
|
369
|
+
lagminthresh: float = 0.5,
|
|
370
|
+
lagmaxthresh: float = 5.0,
|
|
371
|
+
sigmathresh: float = 100,
|
|
372
|
+
cleanrefined: bool = False,
|
|
373
|
+
bipolar: bool = False,
|
|
374
|
+
includemask: NDArray | None = None,
|
|
375
|
+
excludemask: NDArray | None = None,
|
|
376
|
+
fixdelay: bool = False,
|
|
377
|
+
debug: bool = False,
|
|
378
|
+
rt_floattype: np.dtype = np.float64,
|
|
379
|
+
) -> tuple[int, NDArray | None, int, int, int, int, int]:
|
|
380
|
+
"""
|
|
381
|
+
Determine which voxels should be used for regressor refinement based on correlation strength,
|
|
382
|
+
time delay, and peak width criteria.
|
|
383
|
+
|
|
384
|
+
This routine evaluates a set of voxels defined by their correlation properties and applies
|
|
385
|
+
various thresholds to determine which ones are suitable for refinement. It supports optional
|
|
386
|
+
masking, bipolar correlation handling, and debugging output.
|
|
387
|
+
|
|
388
|
+
Parameters
|
|
389
|
+
----------
|
|
390
|
+
lagstrengths : ndarray
|
|
391
|
+
3D numpy float array of maximum correlation coefficients in every voxel.
|
|
392
|
+
lagtimes : ndarray
|
|
393
|
+
3D numpy float array of time delays (in seconds) of maximum crosscorrelation.
|
|
394
|
+
lagsigma : ndarray
|
|
395
|
+
3D numpy float array of Gaussian widths (in seconds) of the crosscorrelation peaks.
|
|
396
|
+
lagmask : ndarray
|
|
397
|
+
3D numpy float array masking voxels with successful correlation fits.
|
|
398
|
+
offsettime : float, optional
|
|
399
|
+
Offset time in seconds to apply to all regressors. Default is 0.0.
|
|
400
|
+
ampthresh : float, optional
|
|
401
|
+
Lower limit of correlation values to consider for refine mask inclusion.
|
|
402
|
+
If negative, treated as percentile. Default is 0.3.
|
|
403
|
+
lagmaskside : str, optional
|
|
404
|
+
Which side of the lag values to consider: 'upper', 'lower', or 'both'.
|
|
405
|
+
Default is 'both'.
|
|
406
|
+
lagminthresh : float, optional
|
|
407
|
+
Lower limit of absolute lag values to consider for inclusion. Default is 0.5.
|
|
408
|
+
lagmaxthresh : float, optional
|
|
409
|
+
Upper limit of absolute lag values to consider for inclusion. Default is 5.0.
|
|
410
|
+
sigmathresh : float, optional
|
|
411
|
+
Upper limit of lag peak width (in seconds) for inclusion. Default is 100.
|
|
412
|
+
cleanrefined : bool, optional
|
|
413
|
+
If True, uses the full location mask for refinement; otherwise, uses the refined mask.
|
|
414
|
+
Default is False.
|
|
415
|
+
bipolar : bool, optional
|
|
416
|
+
If True, considers both positive and negative correlation peaks. Default is False.
|
|
417
|
+
includemask : ndarray, optional
|
|
418
|
+
3D array masking voxels to include in refinement. Default is None (all voxels).
|
|
419
|
+
excludemask : ndarray, optional
|
|
420
|
+
3D array masking voxels to exclude from refinement. Default is None (no voxels).
|
|
421
|
+
fixdelay : bool, optional
|
|
422
|
+
If True, uses the raw `lagmask` without applying delay thresholds. Default is False.
|
|
423
|
+
debug : bool, optional
|
|
424
|
+
Enable additional debugging output. Default is False.
|
|
425
|
+
rt_floattype : np.dtype, optional
|
|
426
|
+
Data type for internal arrays. Default is `np.float64`.
|
|
427
|
+
|
|
428
|
+
Returns
|
|
429
|
+
-------
|
|
430
|
+
volumetotal : int
|
|
431
|
+
Number of voxels processed for refinement.
|
|
432
|
+
maskarray : ndarray or None
|
|
433
|
+
3D mask of voxels used for refinement. Returns None if no voxels remain after filtering.
|
|
434
|
+
locationfails : int
|
|
435
|
+
Number of voxels eliminated due to include/exclude mask constraints.
|
|
436
|
+
ampfails : int
|
|
437
|
+
Number of voxels eliminated due to low correlation amplitude.
|
|
438
|
+
lagfails : int
|
|
439
|
+
Number of voxels eliminated due to lag value out of range.
|
|
440
|
+
sigmafails : int
|
|
441
|
+
Number of voxels eliminated due to wide correlation peak.
|
|
442
|
+
numinmask : int
|
|
443
|
+
Total number of voxels in the original `lagmask`.
|
|
444
|
+
|
|
445
|
+
Notes
|
|
446
|
+
-----
|
|
447
|
+
- The function applies multiple filtering steps: amplitude, lag time, and sigma (peak width).
|
|
448
|
+
- If `ampthresh` is negative, it is interpreted as a percentile threshold.
|
|
449
|
+
- The `lagmaskside` parameter controls which direction of the lag values to consider:
|
|
450
|
+
'upper' for positive lags, 'lower' for negative lags, 'both' for both.
|
|
451
|
+
- If no voxels remain after filtering, an error is printed and the function returns early.
|
|
452
|
+
|
|
453
|
+
Examples
|
|
454
|
+
--------
|
|
455
|
+
>>> import numpy as np
|
|
456
|
+
>>> lagstrengths = np.random.rand(10, 10, 10)
|
|
457
|
+
>>> lagtimes = np.random.rand(10, 10, 10) * 10
|
|
458
|
+
>>> lagsigma = np.random.rand(10, 10, 10) * 50
|
|
459
|
+
>>> lagmask = np.ones((10, 10, 10))
|
|
460
|
+
>>> volumetotal, maskarray, locfails, ampfails, lagfails, sigfails, numinmask = makerefinemask(
|
|
461
|
+
... lagstrengths, lagtimes, lagsigma, lagmask, ampthresh=0.4, lagminthresh=1.0
|
|
462
|
+
... )
|
|
463
|
+
"""
|
|
464
|
+
if ampthresh < 0.0:
|
|
465
|
+
if bipolar:
|
|
466
|
+
theampthresh = tide_stats.getfracval(np.fabs(lagstrengths), -ampthresh, nozero=True)
|
|
467
|
+
else:
|
|
468
|
+
theampthresh = tide_stats.getfracval(lagstrengths, -ampthresh, nozero=True)
|
|
469
|
+
LGR.info(f"setting ampthresh to the {-100.0 * ampthresh}th percentile ({theampthresh})")
|
|
470
|
+
else:
|
|
471
|
+
theampthresh = ampthresh
|
|
472
|
+
if debug:
|
|
473
|
+
print(f"makerefinemask: {theampthresh=}")
|
|
474
|
+
if bipolar:
|
|
475
|
+
ampmask = np.where(np.fabs(lagstrengths) >= theampthresh, np.int16(1), np.int16(0))
|
|
476
|
+
else:
|
|
477
|
+
ampmask = np.where(lagstrengths >= theampthresh, np.int16(1), np.int16(0))
|
|
478
|
+
if fixdelay:
|
|
479
|
+
delaymask = lagmask + 0
|
|
480
|
+
else:
|
|
481
|
+
if lagmaskside == "upper":
|
|
482
|
+
delaymask = np.where(
|
|
483
|
+
(lagtimes - offsettime) > lagminthresh,
|
|
484
|
+
np.int16(1),
|
|
485
|
+
np.int16(0),
|
|
486
|
+
) * np.where(
|
|
487
|
+
(lagtimes - offsettime) < lagmaxthresh,
|
|
488
|
+
np.int16(1),
|
|
489
|
+
np.int16(0),
|
|
490
|
+
)
|
|
491
|
+
elif lagmaskside == "lower":
|
|
492
|
+
delaymask = np.where(
|
|
493
|
+
(lagtimes - offsettime) < -lagminthresh,
|
|
494
|
+
np.int16(1),
|
|
495
|
+
np.int16(0),
|
|
496
|
+
) * np.where(
|
|
497
|
+
(lagtimes - offsettime) > -lagmaxthresh,
|
|
498
|
+
np.int16(1),
|
|
499
|
+
np.int16(0),
|
|
500
|
+
)
|
|
501
|
+
else:
|
|
502
|
+
abslag = abs(lagtimes - offsettime)
|
|
503
|
+
delaymask = np.where(abslag > lagminthresh, np.int16(1), np.int16(0)) * np.where(
|
|
504
|
+
abslag < lagmaxthresh, np.int16(1), np.int16(0)
|
|
505
|
+
)
|
|
506
|
+
if debug:
|
|
507
|
+
print(f"makerefinemask: {lagmaskside=}")
|
|
508
|
+
print(f"makerefinemask: {lagminthresh=}")
|
|
509
|
+
print(f"makerefinemask: {lagmaxthresh=}")
|
|
510
|
+
print(f"makerefinemask: {offsettime=}")
|
|
511
|
+
sigmamask = np.where(lagsigma < sigmathresh, np.int16(1), np.int16(0))
|
|
512
|
+
locationmask = lagmask + 0
|
|
513
|
+
if includemask is not None:
|
|
514
|
+
locationmask = locationmask * includemask
|
|
515
|
+
if excludemask is not None:
|
|
516
|
+
locationmask = locationmask * (1 - excludemask)
|
|
517
|
+
locationmask = locationmask.astype(np.int16)
|
|
518
|
+
LGR.info("location mask created")
|
|
519
|
+
|
|
520
|
+
# first generate the refine mask
|
|
521
|
+
locationfails = np.sum(1 - locationmask)
|
|
522
|
+
ampfails = np.sum(1 - ampmask * locationmask)
|
|
523
|
+
lagfails = np.sum(1 - delaymask * locationmask)
|
|
524
|
+
sigmafails = np.sum(1 - sigmamask * locationmask)
|
|
525
|
+
refinemask = locationmask * ampmask * delaymask * sigmamask
|
|
526
|
+
if tide_stats.getmasksize(refinemask) == 0:
|
|
527
|
+
print("ERROR: no voxels in the refine mask:")
|
|
528
|
+
print(
|
|
529
|
+
"\n ",
|
|
530
|
+
locationfails,
|
|
531
|
+
" locationfails",
|
|
532
|
+
"\n ",
|
|
533
|
+
ampfails,
|
|
534
|
+
" ampfails",
|
|
535
|
+
"\n ",
|
|
536
|
+
lagfails,
|
|
537
|
+
" lagfails",
|
|
538
|
+
"\n ",
|
|
539
|
+
sigmafails,
|
|
540
|
+
" sigmafails",
|
|
541
|
+
)
|
|
542
|
+
if (includemask is None) and (excludemask is None):
|
|
543
|
+
print("\nRelax ampthresh, delaythresh, or sigmathresh - exiting")
|
|
544
|
+
else:
|
|
545
|
+
print(
|
|
546
|
+
"\nChange include/exclude masks or relax ampthresh, delaythresh, or sigmathresh - exiting"
|
|
547
|
+
)
|
|
548
|
+
return 0, None, locationfails, ampfails, lagfails, sigmafails, 0
|
|
549
|
+
|
|
550
|
+
if cleanrefined:
|
|
551
|
+
shiftmask = locationmask
|
|
552
|
+
else:
|
|
553
|
+
shiftmask = refinemask
|
|
554
|
+
volumetotal = np.sum(shiftmask)
|
|
555
|
+
LGR.info(
|
|
556
|
+
f"{int(volumetotal)} voxels will be used for refinement:"
|
|
557
|
+
+ f"\n {locationfails} locationfails"
|
|
558
|
+
+ f"\n {ampfails} ampfails"
|
|
559
|
+
+ f"\n {lagfails} lagfails"
|
|
560
|
+
+ f"\n {sigmafails} sigmafails"
|
|
561
|
+
)
|
|
562
|
+
numinmask = np.sum(lagmask)
|
|
563
|
+
if numinmask is None:
|
|
564
|
+
numinmask = 0
|
|
565
|
+
|
|
566
|
+
return volumetotal, shiftmask, locationfails, ampfails, lagfails, sigmafails, numinmask
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
def prenorm(
|
|
570
|
+
shiftedtcs: NDArray,
|
|
571
|
+
refinemask: NDArray,
|
|
572
|
+
lagtimes: NDArray,
|
|
573
|
+
lagmaxthresh: float,
|
|
574
|
+
lagstrengths: NDArray,
|
|
575
|
+
R2vals: NDArray,
|
|
576
|
+
refineprenorm: str,
|
|
577
|
+
refineweighting: str,
|
|
578
|
+
debug: bool = False,
|
|
579
|
+
) -> None:
|
|
580
|
+
"""
|
|
581
|
+
Apply pre-normalization and weighting to shifted time correlation data.
|
|
582
|
+
|
|
583
|
+
This function performs normalization and weighting of time correlation data
|
|
584
|
+
based on specified criteria. It modifies the input `shiftedtcs` array in-place.
|
|
585
|
+
|
|
586
|
+
Parameters
|
|
587
|
+
----------
|
|
588
|
+
shiftedtcs : NDArray
|
|
589
|
+
Array of shifted time correlation data, shape (n_samples, n_timepoints).
|
|
590
|
+
refinemask : NDArray
|
|
591
|
+
Boolean mask for refining data, shape (n_samples,).
|
|
592
|
+
lagtimes : NDArray
|
|
593
|
+
Array of lag times, shape (n_samples,).
|
|
594
|
+
lagmaxthresh : float
|
|
595
|
+
Threshold for lag time normalization.
|
|
596
|
+
lagstrengths : NDArray
|
|
597
|
+
Array of lag strengths, shape (n_samples,).
|
|
598
|
+
R2vals : NDArray
|
|
599
|
+
Array of R-squared values, shape (n_samples,).
|
|
600
|
+
refineprenorm : str
|
|
601
|
+
Normalization method to use: 'mean', 'var', 'std', or 'invlag'.
|
|
602
|
+
If any other value is provided, unit normalization is applied.
|
|
603
|
+
refineweighting : str
|
|
604
|
+
Weighting method to use: 'R', 'R2', or other (default weighting based on lagstrengths).
|
|
605
|
+
debug : bool, optional
|
|
606
|
+
If True, print debug information about input shapes and intermediate values.
|
|
607
|
+
|
|
608
|
+
Returns
|
|
609
|
+
-------
|
|
610
|
+
None
|
|
611
|
+
The function modifies `shiftedtcs` in-place.
|
|
612
|
+
|
|
613
|
+
Notes
|
|
614
|
+
-----
|
|
615
|
+
The function applies normalization using a divisor computed according to the
|
|
616
|
+
`refineprenorm` parameter and then applies weights based on `refineweighting`.
|
|
617
|
+
The `shiftedtcs` array is updated in-place.
|
|
618
|
+
|
|
619
|
+
Examples
|
|
620
|
+
--------
|
|
621
|
+
>>> import numpy as np
|
|
622
|
+
>>> shiftedtcs = np.random.rand(10, 5)
|
|
623
|
+
>>> refinemask = np.ones(10, dtype=bool)
|
|
624
|
+
>>> lagtimes = np.arange(10)
|
|
625
|
+
>>> lagmaxthresh = 2.0
|
|
626
|
+
>>> lagstrengths = np.random.rand(10)
|
|
627
|
+
>>> R2vals = np.random.rand(10)
|
|
628
|
+
>>> prenorm(shiftedtcs, refinemask, lagtimes, lagmaxthresh, lagstrengths, R2vals, "mean", "R", debug=True)
|
|
629
|
+
"""
|
|
630
|
+
if debug:
|
|
631
|
+
print(f"{shiftedtcs.shape=}"),
|
|
632
|
+
print(f"{refinemask.shape=}"),
|
|
633
|
+
print(f"{lagtimes.shape=}"),
|
|
634
|
+
print(f"{lagmaxthresh=}"),
|
|
635
|
+
print(f"{lagstrengths.shape=}"),
|
|
636
|
+
print(f"{R2vals.shape=}"),
|
|
637
|
+
print(f"{refineprenorm=}"),
|
|
638
|
+
print(f"{refineweighting=}"),
|
|
639
|
+
if refineprenorm == "mean":
|
|
640
|
+
thedivisor = np.mean(shiftedtcs, axis=1)
|
|
641
|
+
elif refineprenorm == "var":
|
|
642
|
+
thedivisor = np.var(shiftedtcs, axis=1)
|
|
643
|
+
elif refineprenorm == "std":
|
|
644
|
+
thedivisor = np.std(shiftedtcs, axis=1)
|
|
645
|
+
elif refineprenorm == "invlag":
|
|
646
|
+
thedivisor = np.where(np.fabs(lagtimes) < lagmaxthresh, lagmaxthresh - lagtimes, 0.0)
|
|
647
|
+
else:
|
|
648
|
+
thedivisor = np.ones_like(shiftedtcs[:, 0])
|
|
649
|
+
|
|
650
|
+
normfac = np.where(thedivisor != 0.0, 1.0 / thedivisor, 0.0)
|
|
651
|
+
|
|
652
|
+
if refineweighting == "R":
|
|
653
|
+
thisweight = lagstrengths
|
|
654
|
+
elif refineweighting == "R2":
|
|
655
|
+
thisweight = R2vals
|
|
656
|
+
else:
|
|
657
|
+
thisweight = np.where(lagstrengths > 0.0, 1.0, -1.0)
|
|
658
|
+
thisweight *= refinemask
|
|
659
|
+
|
|
660
|
+
if debug:
|
|
661
|
+
print(f"{thedivisor.shape=}")
|
|
662
|
+
print(f"{normfac.shape=}")
|
|
663
|
+
print(f"{thisweight.shape=}")
|
|
664
|
+
|
|
665
|
+
shiftedtcs *= (normfac * thisweight)[:, None]
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def dorefine(
|
|
669
|
+
shiftedtcs: NDArray,
|
|
670
|
+
refinemask: NDArray,
|
|
671
|
+
weights: NDArray,
|
|
672
|
+
theprefilter: Any,
|
|
673
|
+
fmritr: float,
|
|
674
|
+
passnum: int,
|
|
675
|
+
lagstrengths: NDArray,
|
|
676
|
+
lagtimes: NDArray,
|
|
677
|
+
refinetype: str,
|
|
678
|
+
fmrifreq: float,
|
|
679
|
+
outputname: str,
|
|
680
|
+
detrendorder: int = 1,
|
|
681
|
+
pcacomponents: float | str = 0.8,
|
|
682
|
+
dodispersioncalc: bool = False,
|
|
683
|
+
dispersioncalc_lower: float = 0.0,
|
|
684
|
+
dispersioncalc_upper: float = 0.0,
|
|
685
|
+
dispersioncalc_step: float = 0.0,
|
|
686
|
+
windowfunc: str = "hamming",
|
|
687
|
+
cleanrefined: bool = False,
|
|
688
|
+
bipolar: bool = False,
|
|
689
|
+
debug: bool = False,
|
|
690
|
+
rt_floattype: np.dtype = np.float64,
|
|
691
|
+
) -> tuple[int, NDArray]:
|
|
692
|
+
"""
|
|
693
|
+
Refine timecourses using specified method (ICA, PCA, weighted average, or unweighted average).
|
|
694
|
+
|
|
695
|
+
This function applies a refinement process to a set of timecourses based on a mask and
|
|
696
|
+
weights. It supports multiple refinement techniques including ICA, PCA, and averaging,
|
|
697
|
+
and can optionally perform dispersion calculation and cleaning of refined data.
|
|
698
|
+
|
|
699
|
+
Parameters
|
|
700
|
+
----------
|
|
701
|
+
shiftedtcs : ndarray
|
|
702
|
+
Array of shape (n_voxels, n_timepoints) containing the shifted timecourses.
|
|
703
|
+
refinemask : ndarray
|
|
704
|
+
Boolean mask indicating which voxels to include in refinement.
|
|
705
|
+
weights : ndarray
|
|
706
|
+
Array of shape (n_voxels, n_timepoints) containing weights for each voxel.
|
|
707
|
+
theprefilter : Any
|
|
708
|
+
Pre-filter object with an `apply` method to filter the data.
|
|
709
|
+
fmritr : float
|
|
710
|
+
fMRI repetition time in seconds.
|
|
711
|
+
passnum : int
|
|
712
|
+
Pass number for output file naming.
|
|
713
|
+
lagstrengths : ndarray
|
|
714
|
+
Array of lag strengths for each voxel.
|
|
715
|
+
lagtimes : ndarray
|
|
716
|
+
Array of lag times for each voxel.
|
|
717
|
+
refinetype : str
|
|
718
|
+
Type of refinement to perform: 'ica', 'pca', 'weighted_average', or 'unweighted_average'.
|
|
719
|
+
fmrifreq : float
|
|
720
|
+
fMRI frequency in Hz.
|
|
721
|
+
outputname : str
|
|
722
|
+
Base name for output files.
|
|
723
|
+
detrendorder : int, optional
|
|
724
|
+
Order of detrending for correlation normalization (default is 1).
|
|
725
|
+
pcacomponents : float or str, optional
|
|
726
|
+
Number of PCA components to use. If < 1, treated as fraction of variance; if 'mle', uses MLE.
|
|
727
|
+
Default is 0.8.
|
|
728
|
+
dodispersioncalc : bool, optional
|
|
729
|
+
If True, compute dispersion calculation across lag ranges (default is False).
|
|
730
|
+
dispersioncalc_lower : float, optional
|
|
731
|
+
Lower bound for dispersion calculation lag range (default is 0.0).
|
|
732
|
+
dispersioncalc_upper : float, optional
|
|
733
|
+
Upper bound for dispersion calculation lag range (default is 0.0).
|
|
734
|
+
dispersioncalc_step : float, optional
|
|
735
|
+
Step size for dispersion calculation lag range (default is 0.0).
|
|
736
|
+
windowfunc : str, optional
|
|
737
|
+
Window function for correlation normalization (default is "hamming").
|
|
738
|
+
cleanrefined : bool, optional
|
|
739
|
+
If True, remove linearly fitted discard data from refined output (default is False).
|
|
740
|
+
bipolar : bool, optional
|
|
741
|
+
If True, flip sign of negative lag strengths (default is False).
|
|
742
|
+
debug : bool, optional
|
|
743
|
+
If True, print debug information (default is False).
|
|
744
|
+
rt_floattype : np.dtype, optional
|
|
745
|
+
Data type for floating-point numbers (default is np.float64).
|
|
746
|
+
|
|
747
|
+
Returns
|
|
748
|
+
-------
|
|
749
|
+
tuple[int, ndarray]
|
|
750
|
+
A tuple containing:
|
|
751
|
+
- `volumetotal`: int, total number of voxels included in refinement.
|
|
752
|
+
- `outputdata`: ndarray, refined timecourse of shape (n_timepoints,).
|
|
753
|
+
|
|
754
|
+
Notes
|
|
755
|
+
-----
|
|
756
|
+
- The function supports multiple refinement methods: ICA, PCA, weighted average, and
|
|
757
|
+
unweighted average.
|
|
758
|
+
- If `cleanrefined` is True, a linear regression is performed to remove discard data
|
|
759
|
+
from the refined output.
|
|
760
|
+
- If `dodispersioncalc` is True, dispersion calculation is performed across lag ranges
|
|
761
|
+
and outputs are saved to files with the prefix `outputname`.
|
|
762
|
+
|
|
763
|
+
Examples
|
|
764
|
+
--------
|
|
765
|
+
>>> import numpy as np
|
|
766
|
+
>>> shiftedtcs = np.random.rand(100, 200)
|
|
767
|
+
>>> refinemask = np.ones(100)
|
|
768
|
+
>>> weights = np.ones((100, 200))
|
|
769
|
+
>>> theprefilter = SomeFilter()
|
|
770
|
+
>>> fmritr = 2.0
|
|
771
|
+
>>> passnum = 1
|
|
772
|
+
>>> lagstrengths = np.random.rand(100)
|
|
773
|
+
>>> lagtimes = np.random.rand(100)
|
|
774
|
+
>>> refinetype = "pca"
|
|
775
|
+
>>> fmrifreq = 0.1
|
|
776
|
+
>>> outputname = "test_output"
|
|
777
|
+
>>> volumetotal, outputdata = dorefine(
|
|
778
|
+
... shiftedtcs, refinemask, weights, theprefilter, fmritr, passnum,
|
|
779
|
+
... lagstrengths, lagtimes, refinetype, fmrifreq, outputname
|
|
780
|
+
... )
|
|
781
|
+
"""
|
|
782
|
+
# now generate the refined timecourse(s)
|
|
783
|
+
inputshape = np.shape(shiftedtcs)
|
|
784
|
+
validlist = np.where(refinemask > 0)[0]
|
|
785
|
+
volumetotal = len(validlist)
|
|
786
|
+
refinevoxels = shiftedtcs[validlist, :]
|
|
787
|
+
if bipolar:
|
|
788
|
+
for thevoxel in range(len(validlist)):
|
|
789
|
+
if lagstrengths[validlist][thevoxel] < 0.0:
|
|
790
|
+
refinevoxels[thevoxel, :] *= -1.0
|
|
791
|
+
refineweights = weights[validlist]
|
|
792
|
+
weightsum = np.sum(refineweights, axis=0) / volumetotal
|
|
793
|
+
averagedata = np.sum(refinevoxels, axis=0) / volumetotal
|
|
794
|
+
if cleanrefined:
|
|
795
|
+
invalidlist = np.where((1 - refinemask) > 0)[0]
|
|
796
|
+
discardvoxels = shiftedtcs[invalidlist]
|
|
797
|
+
discardweights = weights[invalidlist]
|
|
798
|
+
discardweightsum = np.sum(discardweights, axis=0) / volumetotal
|
|
799
|
+
averagediscard = np.sum(discardvoxels, axis=0) / volumetotal
|
|
800
|
+
if dodispersioncalc:
|
|
801
|
+
LGR.info("splitting regressors by time lag for phase delay estimation")
|
|
802
|
+
laglist = np.arange(
|
|
803
|
+
dispersioncalc_lower,
|
|
804
|
+
dispersioncalc_upper,
|
|
805
|
+
dispersioncalc_step,
|
|
806
|
+
)
|
|
807
|
+
dispersioncalcout = np.zeros((np.shape(laglist)[0], inputshape[1]), dtype=rt_floattype)
|
|
808
|
+
fftlen = int(inputshape[1] // 2)
|
|
809
|
+
fftlen -= fftlen % 2
|
|
810
|
+
dispersioncalcspecmag = np.zeros((np.shape(laglist)[0], fftlen), dtype=rt_floattype)
|
|
811
|
+
dispersioncalcspecphase = np.zeros((np.shape(laglist)[0], fftlen), dtype=rt_floattype)
|
|
812
|
+
###### BBF dispersioncalc fails when the number of timepoints is odd (or even - not sure). Works the other way.
|
|
813
|
+
for lagnum in range(0, np.shape(laglist)[0]):
|
|
814
|
+
lower = laglist[lagnum] - dispersioncalc_step / 2.0
|
|
815
|
+
upper = laglist[lagnum] + dispersioncalc_step / 2.0
|
|
816
|
+
inlagrange = np.where(
|
|
817
|
+
refinemask
|
|
818
|
+
* np.where(lower < lagtimes, np.int16(1), np.int16(0))
|
|
819
|
+
* np.where(lagtimes < upper, np.int16(1), np.int16(0))
|
|
820
|
+
)[0]
|
|
821
|
+
LGR.info(
|
|
822
|
+
f"\tsumming {np.shape(inlagrange)[0]} regressors with lags from {lower} to {upper}"
|
|
823
|
+
)
|
|
824
|
+
if np.shape(inlagrange)[0] > 0:
|
|
825
|
+
dispersioncalcout[lagnum, :] = tide_math.corrnormalize(
|
|
826
|
+
np.mean(shiftedtcs[inlagrange], axis=0),
|
|
827
|
+
detrendorder=detrendorder,
|
|
828
|
+
windowfunc=windowfunc,
|
|
829
|
+
)
|
|
830
|
+
(
|
|
831
|
+
freqs,
|
|
832
|
+
dispersioncalcspecmag[lagnum, :],
|
|
833
|
+
dispersioncalcspecphase[lagnum, :],
|
|
834
|
+
) = tide_math.polarfft(dispersioncalcout[lagnum, :], 1.0 / fmritr)
|
|
835
|
+
inlagrange = None
|
|
836
|
+
tide_io.writenpvecs(
|
|
837
|
+
dispersioncalcout,
|
|
838
|
+
outputname + "_dispersioncalcvecs_pass" + str(passnum) + ".txt",
|
|
839
|
+
)
|
|
840
|
+
tide_io.writenpvecs(
|
|
841
|
+
dispersioncalcspecmag,
|
|
842
|
+
outputname + "_dispersioncalcspecmag_pass" + str(passnum) + ".txt",
|
|
843
|
+
)
|
|
844
|
+
tide_io.writenpvecs(
|
|
845
|
+
dispersioncalcspecphase,
|
|
846
|
+
outputname + "_dispersioncalcspecphase_pass" + str(passnum) + ".txt",
|
|
847
|
+
)
|
|
848
|
+
tide_io.writenpvecs(
|
|
849
|
+
freqs,
|
|
850
|
+
outputname + "_dispersioncalcfreqs_pass" + str(passnum) + ".txt",
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
if pcacomponents < 0.0:
|
|
854
|
+
pcacomponents = "mle"
|
|
855
|
+
elif pcacomponents >= 1.0:
|
|
856
|
+
pcacomponents = int(np.round(pcacomponents))
|
|
857
|
+
elif pcacomponents == 0.0:
|
|
858
|
+
print("0.0 is not an allowed value for pcacomponents")
|
|
859
|
+
sys.exit()
|
|
860
|
+
else:
|
|
861
|
+
pcacomponents = pcacomponents
|
|
862
|
+
icacomponents = 1
|
|
863
|
+
|
|
864
|
+
if refinetype == "ica":
|
|
865
|
+
LGR.info("performing ica refinement")
|
|
866
|
+
thefit = FastICA(n_components=icacomponents).fit(refinevoxels) # Reconstruct signals
|
|
867
|
+
LGR.info(f"Using first of {len(thefit.components_)} components")
|
|
868
|
+
icadata = thefit.components_[0]
|
|
869
|
+
filteredavg = tide_math.corrnormalize(
|
|
870
|
+
theprefilter.apply(fmrifreq, averagedata),
|
|
871
|
+
detrendorder=detrendorder,
|
|
872
|
+
)
|
|
873
|
+
filteredica = tide_math.corrnormalize(
|
|
874
|
+
theprefilter.apply(fmrifreq, icadata),
|
|
875
|
+
detrendorder=detrendorder,
|
|
876
|
+
)
|
|
877
|
+
thepxcorr = pearsonr(filteredavg, filteredica).statistic
|
|
878
|
+
LGR.info(f"ica/avg correlation = {thepxcorr}")
|
|
879
|
+
if thepxcorr > 0.0:
|
|
880
|
+
outputdata = 1.0 * icadata
|
|
881
|
+
else:
|
|
882
|
+
outputdata = -1.0 * icadata
|
|
883
|
+
elif refinetype == "pca":
|
|
884
|
+
# use the method of "A novel perspective to calibrate temporal delays in cerebrovascular reactivity
|
|
885
|
+
# using hypercapnic and hyperoxic respiratory challenges". NeuroImage 187, 154?165 (2019).
|
|
886
|
+
LGR.info(f"performing pca refinement with pcacomponents set to {pcacomponents}")
|
|
887
|
+
try:
|
|
888
|
+
thefit = PCA(n_components=pcacomponents).fit(refinevoxels)
|
|
889
|
+
except ValueError:
|
|
890
|
+
if pcacomponents == "mle":
|
|
891
|
+
LGR.info("mle estimation failed - falling back to pcacomponents=0.8")
|
|
892
|
+
thefit = PCA(n_components=0.8).fit(refinevoxels)
|
|
893
|
+
else:
|
|
894
|
+
print("unhandled math exception in PCA refinement - exiting")
|
|
895
|
+
sys.exit()
|
|
896
|
+
LGR.info(
|
|
897
|
+
f"Using {len(thefit.components_)} component(s), accounting for "
|
|
898
|
+
+ f"{100.0 * np.cumsum(thefit.explained_variance_ratio_)[len(thefit.components_) - 1]:.2f}% of the variance"
|
|
899
|
+
)
|
|
900
|
+
reduceddata = thefit.inverse_transform(thefit.transform(refinevoxels))
|
|
901
|
+
if debug:
|
|
902
|
+
print("complex processing: reduceddata.shape =", reduceddata.shape)
|
|
903
|
+
pcadata = np.mean(reduceddata, axis=0)
|
|
904
|
+
filteredavg = tide_math.corrnormalize(
|
|
905
|
+
theprefilter.apply(fmrifreq, averagedata),
|
|
906
|
+
detrendorder=detrendorder,
|
|
907
|
+
)
|
|
908
|
+
filteredpca = tide_math.corrnormalize(
|
|
909
|
+
theprefilter.apply(fmrifreq, pcadata),
|
|
910
|
+
detrendorder=detrendorder,
|
|
911
|
+
)
|
|
912
|
+
thepxcorr = pearsonr(filteredavg, filteredpca).statistic
|
|
913
|
+
LGR.info(f"pca/avg correlation = {thepxcorr}")
|
|
914
|
+
if thepxcorr > 0.0:
|
|
915
|
+
outputdata = 1.0 * pcadata
|
|
916
|
+
else:
|
|
917
|
+
outputdata = -1.0 * pcadata
|
|
918
|
+
elif refinetype == "weighted_average":
|
|
919
|
+
LGR.info("performing weighted averaging refinement")
|
|
920
|
+
outputdata = np.nan_to_num(averagedata / weightsum)
|
|
921
|
+
else:
|
|
922
|
+
LGR.info("performing unweighted averaging refinement")
|
|
923
|
+
outputdata = averagedata
|
|
924
|
+
|
|
925
|
+
if cleanrefined:
|
|
926
|
+
thefit, R2 = tide_fit.mlregress(averagediscard, averagedata)
|
|
927
|
+
|
|
928
|
+
fitcoff = thefit[0, 1]
|
|
929
|
+
datatoremove = (fitcoff * averagediscard).astype(rt_floattype)
|
|
930
|
+
outputdata -= datatoremove
|
|
931
|
+
|
|
932
|
+
# garbage collect
|
|
933
|
+
uncollected = gc.collect()
|
|
934
|
+
if uncollected != 0:
|
|
935
|
+
LGR.info(f"garbage collected - unable to collect {uncollected} objects")
|
|
936
|
+
else:
|
|
937
|
+
LGR.info("garbage collected")
|
|
938
|
+
|
|
939
|
+
return volumetotal, outputdata
|