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
rapidtide/voxelData.py
ADDED
|
@@ -0,0 +1,1048 @@
|
|
|
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 copy
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
from numpy.typing import NDArray
|
|
24
|
+
from tqdm import tqdm
|
|
25
|
+
|
|
26
|
+
import rapidtide.filter as tide_filt
|
|
27
|
+
import rapidtide.io as tide_io
|
|
28
|
+
import rapidtide.util as tide_util
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class dataVolume:
|
|
32
|
+
xsize = None
|
|
33
|
+
ysize = None
|
|
34
|
+
numslices = None
|
|
35
|
+
numspatiallocs = None
|
|
36
|
+
timepoints = None
|
|
37
|
+
dtype = None
|
|
38
|
+
dimensions = None
|
|
39
|
+
data = None
|
|
40
|
+
data_shm = None
|
|
41
|
+
thepid = None
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
shape: tuple,
|
|
46
|
+
shared: bool = False,
|
|
47
|
+
dtype: type = np.float64,
|
|
48
|
+
thepid: int = 0,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Initialize a data container with specified shape and properties.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
shape : tuple
|
|
56
|
+
The shape of the data array. Must be either 3D (x, y, z) or 4D (x, y, z, t).
|
|
57
|
+
shared : bool, optional
|
|
58
|
+
Whether to create a shared memory array, by default False
|
|
59
|
+
dtype : type, optional
|
|
60
|
+
Data type of the array, by default np.float64
|
|
61
|
+
thepid : int, optional
|
|
62
|
+
Process ID for naming shared memory, by default 0
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
None
|
|
67
|
+
This method initializes the object in-place and does not return a value.
|
|
68
|
+
|
|
69
|
+
Notes
|
|
70
|
+
-----
|
|
71
|
+
The function automatically determines the number of dimensions based on the shape tuple length.
|
|
72
|
+
For 3D shapes, timepoints is set to 1. For 4D shapes, timepoints is set to the fourth dimension.
|
|
73
|
+
Invalid shapes will trigger a print statement with the error message.
|
|
74
|
+
|
|
75
|
+
Examples
|
|
76
|
+
--------
|
|
77
|
+
>>> data_container = DataContainer((64, 64, 32))
|
|
78
|
+
>>> data_container = DataContainer((64, 64, 32, 10), shared=True, dtype=np.float32)
|
|
79
|
+
"""
|
|
80
|
+
if len(shape) == 3:
|
|
81
|
+
self.xsize = int(shape[0])
|
|
82
|
+
self.ysize = int(shape[1])
|
|
83
|
+
self.numslices = int(shape[2])
|
|
84
|
+
self.timepoints = 1
|
|
85
|
+
self.dimensions = 3
|
|
86
|
+
elif len(shape) == 4:
|
|
87
|
+
self.xsize = int(shape[0])
|
|
88
|
+
self.ysize = int(shape[1])
|
|
89
|
+
self.numslices = int(shape[2])
|
|
90
|
+
self.timepoints = int(shape[3])
|
|
91
|
+
self.dimensions = 4
|
|
92
|
+
else:
|
|
93
|
+
print(f"illegal shape: {shape}")
|
|
94
|
+
self.numspatiallocs = self.xsize * self.ysize * self.numslices
|
|
95
|
+
self.dtype = dtype
|
|
96
|
+
self.data, self.data_shm = tide_util.allocarray(
|
|
97
|
+
shape, self.dtype, shared=shared, name=f"filtereddata_{thepid}"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def byvol(self) -> NDArray:
|
|
101
|
+
"""
|
|
102
|
+
Return the data array.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
NDArray
|
|
107
|
+
The underlying data array stored in the object.
|
|
108
|
+
|
|
109
|
+
Notes
|
|
110
|
+
-----
|
|
111
|
+
This method provides direct access to the internal data array.
|
|
112
|
+
The returned array is a view of the original data and modifications
|
|
113
|
+
to it will affect the original object.
|
|
114
|
+
|
|
115
|
+
Examples
|
|
116
|
+
--------
|
|
117
|
+
>>> obj = MyClass()
|
|
118
|
+
>>> data = obj.byvol()
|
|
119
|
+
>>> print(data.shape)
|
|
120
|
+
(100, 50)
|
|
121
|
+
"""
|
|
122
|
+
return self.data
|
|
123
|
+
|
|
124
|
+
def byslice(self) -> NDArray:
|
|
125
|
+
"""
|
|
126
|
+
Reshape data by slices for 2D processing.
|
|
127
|
+
|
|
128
|
+
Reshapes the internal data array to facilitate 2D processing operations
|
|
129
|
+
by combining the x and y dimensions while preserving slice information.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
self : object
|
|
134
|
+
The instance containing the data to be reshaped. Expected to have
|
|
135
|
+
attributes: dimensions (int), data (array-like), xsize (int),
|
|
136
|
+
ysize (int), and numslices (int).
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
NDArray
|
|
141
|
+
Reshaped array with dimensions (xsize * ysize, -1). For 3D data,
|
|
142
|
+
the shape becomes (xsize * ysize, -1). For 4D data, the shape becomes
|
|
143
|
+
(xsize * ysize, numslices, -1).
|
|
144
|
+
|
|
145
|
+
Notes
|
|
146
|
+
-----
|
|
147
|
+
This function is useful for preparing data for 2D processing operations
|
|
148
|
+
where the spatial dimensions need to be flattened while maintaining
|
|
149
|
+
temporal or spectral slice information.
|
|
150
|
+
|
|
151
|
+
Examples
|
|
152
|
+
--------
|
|
153
|
+
>>> # For 3D data with shape (100, 100, 50)
|
|
154
|
+
>>> result = obj.byslice()
|
|
155
|
+
>>> # Result shape: (10000, 50)
|
|
156
|
+
>>>
|
|
157
|
+
>>> # For 4D data with shape (50, 50, 10, 20)
|
|
158
|
+
>>> result = obj.byslice()
|
|
159
|
+
>>> # Result shape: (2500, 10, 20)
|
|
160
|
+
"""
|
|
161
|
+
if self.dimensions == 3:
|
|
162
|
+
return self.data.reshape(self.xsize * self.ysize, -1)
|
|
163
|
+
else:
|
|
164
|
+
return self.data.reshape(self.xsize * self.ysize, self.numslices, -1)
|
|
165
|
+
|
|
166
|
+
def byvoxel(self) -> NDArray:
|
|
167
|
+
"""
|
|
168
|
+
Reshape data to voxel format based on dimensions.
|
|
169
|
+
|
|
170
|
+
Returns
|
|
171
|
+
-------
|
|
172
|
+
NDArray
|
|
173
|
+
Reshaped array where each row represents a voxel. For 3D data, returns
|
|
174
|
+
a 1D array of shape (numspatiallocs,). For non-3D data, returns a 2D array
|
|
175
|
+
of shape (numspatiallocs, -1).
|
|
176
|
+
|
|
177
|
+
Notes
|
|
178
|
+
-----
|
|
179
|
+
This method reshapes the internal ``data`` attribute to a voxel-based
|
|
180
|
+
structure. The ``numspatiallocs`` attribute determines the first dimension
|
|
181
|
+
of the output array, while the second dimension is determined by the
|
|
182
|
+
remaining data dimensions.
|
|
183
|
+
|
|
184
|
+
Examples
|
|
185
|
+
--------
|
|
186
|
+
>>> # For 3D data
|
|
187
|
+
>>> result = obj.byvoxel()
|
|
188
|
+
>>> print(result.shape)
|
|
189
|
+
(1000,) # where 1000 = numspatiallocs
|
|
190
|
+
|
|
191
|
+
>>> # For 2D data
|
|
192
|
+
>>> result = obj.byvoxel()
|
|
193
|
+
>>> print(result.shape)
|
|
194
|
+
(1000, 5) # where 1000 = numspatiallocs, 5 = remaining dimensions
|
|
195
|
+
"""
|
|
196
|
+
if self.dimensions == 3:
|
|
197
|
+
return self.data.reshape(self.numspatiallocs)
|
|
198
|
+
else:
|
|
199
|
+
return self.data.reshape(self.numspatiallocs, -1)
|
|
200
|
+
|
|
201
|
+
def destroy(self) -> None:
|
|
202
|
+
"""
|
|
203
|
+
Clean up and destroy the object's resources.
|
|
204
|
+
|
|
205
|
+
This method releases the internal data storage and performs cleanup of
|
|
206
|
+
shared memory resources if they exist.
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
None
|
|
211
|
+
This method does not return any value.
|
|
212
|
+
|
|
213
|
+
Notes
|
|
214
|
+
-----
|
|
215
|
+
The method first deletes the internal `data` attribute, then checks if
|
|
216
|
+
`data_shm` (shared memory) exists and performs cleanup if it does.
|
|
217
|
+
|
|
218
|
+
Examples
|
|
219
|
+
--------
|
|
220
|
+
>>> obj = MyClass()
|
|
221
|
+
>>> obj.destroy()
|
|
222
|
+
>>> # Object resources have been cleaned up
|
|
223
|
+
"""
|
|
224
|
+
del self.data
|
|
225
|
+
if self.data_shm is not None:
|
|
226
|
+
tide_util.cleanup_shm(self.data_shm)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class VoxelData:
|
|
230
|
+
nim = None
|
|
231
|
+
nim_data = None
|
|
232
|
+
nim_hdr = None
|
|
233
|
+
nim_affine = None
|
|
234
|
+
theshape = None
|
|
235
|
+
xsize = None
|
|
236
|
+
ysize = None
|
|
237
|
+
numslices = None
|
|
238
|
+
timepoints = None
|
|
239
|
+
dimensions = None
|
|
240
|
+
realtimepoints = None
|
|
241
|
+
xdim = None
|
|
242
|
+
ydim = None
|
|
243
|
+
slicethickness = None
|
|
244
|
+
timestep = None
|
|
245
|
+
thesizes = None
|
|
246
|
+
thedims = None
|
|
247
|
+
numslicelocs = None
|
|
248
|
+
numspatiallocs = None
|
|
249
|
+
nativespaceshape = None
|
|
250
|
+
nativefmrishape = None
|
|
251
|
+
validvoxels = None
|
|
252
|
+
cifti_hdr = None
|
|
253
|
+
filetype = None
|
|
254
|
+
resident = False
|
|
255
|
+
|
|
256
|
+
def __init__(
|
|
257
|
+
self,
|
|
258
|
+
filename: str,
|
|
259
|
+
timestep: float = 0.0,
|
|
260
|
+
validstart: int | None = None,
|
|
261
|
+
validend: int | None = None,
|
|
262
|
+
) -> None:
|
|
263
|
+
"""
|
|
264
|
+
Initialize the object with filename and optional data reading parameters.
|
|
265
|
+
|
|
266
|
+
Parameters
|
|
267
|
+
----------
|
|
268
|
+
filename : str
|
|
269
|
+
Path to the data file to be read.
|
|
270
|
+
timestep : float, optional
|
|
271
|
+
Time step for data processing, default is 0.0.
|
|
272
|
+
validstart : int, optional
|
|
273
|
+
Starting index for valid data range, default is None (all data).
|
|
274
|
+
validend : int, optional
|
|
275
|
+
Ending index for valid data range, default is None (all data).
|
|
276
|
+
|
|
277
|
+
Returns
|
|
278
|
+
-------
|
|
279
|
+
None
|
|
280
|
+
This method initializes the object and reads data but does not return any value.
|
|
281
|
+
|
|
282
|
+
Notes
|
|
283
|
+
-----
|
|
284
|
+
This method calls `readdata()` internally with the provided parameters to load
|
|
285
|
+
and process the data from the specified file.
|
|
286
|
+
|
|
287
|
+
Examples
|
|
288
|
+
--------
|
|
289
|
+
>>> obj = MyClass("data.txt")
|
|
290
|
+
>>> obj = MyClass("data.txt", timestep=0.1, validstart=10, validend=100)
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
self.filename = filename
|
|
294
|
+
self.readdata(timestep, validstart, validend)
|
|
295
|
+
|
|
296
|
+
def readdata(self, timestep: float, validstart: int | None, validend: int | None) -> None:
|
|
297
|
+
"""
|
|
298
|
+
Load and process data from a file based on its type (NIfTI, CIFTI, or text).
|
|
299
|
+
|
|
300
|
+
This function loads data using `self.load()` and determines the file type
|
|
301
|
+
(NIfTI, CIFTI, or text) to set appropriate attributes such as dimensions,
|
|
302
|
+
timepoints, and spatial locations. It also handles time-related parameters
|
|
303
|
+
like `timestep` and `toffset`, and sets valid time ranges.
|
|
304
|
+
|
|
305
|
+
Parameters
|
|
306
|
+
----------
|
|
307
|
+
timestep : float
|
|
308
|
+
The time step size (in seconds) for the data. If <= 0.0, the function
|
|
309
|
+
will attempt to infer it from the file metadata (except for text files,
|
|
310
|
+
which require this to be explicitly set).
|
|
311
|
+
validstart : int, optional
|
|
312
|
+
The starting index of the valid time range. If None, defaults to the
|
|
313
|
+
beginning of the data.
|
|
314
|
+
validend : int, optional
|
|
315
|
+
The ending index of the valid time range. If None, defaults to the end
|
|
316
|
+
of the data.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
None
|
|
321
|
+
This function does not return a value but updates the instance attributes
|
|
322
|
+
of `self` based on the loaded data and parameters.
|
|
323
|
+
|
|
324
|
+
Notes
|
|
325
|
+
-----
|
|
326
|
+
- For text files, `timestep` must be provided explicitly; otherwise, a
|
|
327
|
+
`ValueError` is raised.
|
|
328
|
+
- For CIFTI files, the `timestep` is hardcoded to 0.72 seconds as a temporary
|
|
329
|
+
workaround until full XML parsing is implemented.
|
|
330
|
+
- The function sets various internal attributes such as `xsize`, `ysize`,
|
|
331
|
+
`numslices`, `timepoints`, `numspatiallocs`, and `nativespaceshape`
|
|
332
|
+
depending on the file type.
|
|
333
|
+
|
|
334
|
+
Examples
|
|
335
|
+
--------
|
|
336
|
+
>>> readdata(timestep=1.0, validstart=0, validend=100)
|
|
337
|
+
# Loads data with a 1-second timestep and valid time range from 0 to 100.
|
|
338
|
+
|
|
339
|
+
>>> readdata(timestep=0.0, validstart=None, validend=None)
|
|
340
|
+
# Loads data and infers timestep from file metadata (if not text).
|
|
341
|
+
"""
|
|
342
|
+
# load the data
|
|
343
|
+
self.load()
|
|
344
|
+
|
|
345
|
+
if tide_io.checkiftext(self.filename):
|
|
346
|
+
self.filetype = "text"
|
|
347
|
+
self.nim_hdr = None
|
|
348
|
+
self.nim_affine = None
|
|
349
|
+
self.theshape = np.shape(self.nim_data)
|
|
350
|
+
self.xsize = self.theshape[0]
|
|
351
|
+
self.ysize = 1
|
|
352
|
+
self.numslices = 1
|
|
353
|
+
self.numslicelocs = None
|
|
354
|
+
self.timepoints = int(self.theshape[1])
|
|
355
|
+
self.thesizes = [0, int(self.xsize), 1, 1, int(self.timepoints)]
|
|
356
|
+
self.toffset = 0.0
|
|
357
|
+
self.numspatiallocs = int(self.xsize)
|
|
358
|
+
self.nativespaceshape = self.xsize
|
|
359
|
+
self.cifti_hdr = None
|
|
360
|
+
else:
|
|
361
|
+
if tide_io.checkifcifti(self.filename):
|
|
362
|
+
self.filetype = "cifti"
|
|
363
|
+
self.nim_affine = None
|
|
364
|
+
self.numslicelocs = None
|
|
365
|
+
self.timepoints = int(self.nim_data.shape[1])
|
|
366
|
+
self.numspatiallocs = self.nim_data.shape[0]
|
|
367
|
+
self.nativespaceshape = (1, 1, 1, 1, self.numspatiallocs)
|
|
368
|
+
else:
|
|
369
|
+
self.filetype = "nifti"
|
|
370
|
+
self.nim_affine = self.nim.affine
|
|
371
|
+
self.xsize, self.ysize, self.numslices, self.timepoints = tide_io.parseniftidims(
|
|
372
|
+
self.thedims
|
|
373
|
+
)
|
|
374
|
+
if self.timepoints == 1:
|
|
375
|
+
self.dimensions = 3
|
|
376
|
+
else:
|
|
377
|
+
self.dimensions = 4
|
|
378
|
+
self.numslicelocs = int(self.xsize) * int(self.ysize)
|
|
379
|
+
self.numspatiallocs = int(self.xsize) * int(self.ysize) * int(self.numslices)
|
|
380
|
+
self.cifti_hdr = None
|
|
381
|
+
self.nativespaceshape = (self.xsize, self.ysize, self.numslices)
|
|
382
|
+
self.xdim, self.ydim, self.slicethickness, dummy = tide_io.parseniftisizes(
|
|
383
|
+
self.thesizes
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
# correct some fields if necessary
|
|
387
|
+
if self.filetype == "cifti":
|
|
388
|
+
self.timestep = 0.72 # this is wrong and is a hack until I can parse CIFTI XML
|
|
389
|
+
self.toffset = 0.0
|
|
390
|
+
else:
|
|
391
|
+
if self.filetype == "text":
|
|
392
|
+
if timestep <= 0.0:
|
|
393
|
+
raise ValueError(
|
|
394
|
+
"for text file data input, you must use the -t option to set the timestep"
|
|
395
|
+
)
|
|
396
|
+
else:
|
|
397
|
+
if self.nim_hdr.get_xyzt_units()[1] == "msec":
|
|
398
|
+
self.timestep = self.thesizes[4] / 1000.0
|
|
399
|
+
self.toffset = self.nim_hdr["toffset"] / 1000.0
|
|
400
|
+
else:
|
|
401
|
+
self.timestep = self.thesizes[4]
|
|
402
|
+
self.toffset = self.nim_hdr["toffset"]
|
|
403
|
+
if timestep > 0.0:
|
|
404
|
+
self.timestep = timestep
|
|
405
|
+
|
|
406
|
+
self.setvalidtimes(validstart, validend)
|
|
407
|
+
self.resident = True
|
|
408
|
+
|
|
409
|
+
def copyheader(
|
|
410
|
+
self,
|
|
411
|
+
numtimepoints: int | None = None,
|
|
412
|
+
tr: float | None = None,
|
|
413
|
+
toffset: float | None = None,
|
|
414
|
+
) -> Any | None:
|
|
415
|
+
"""
|
|
416
|
+
Copy and modify header information for neuroimaging files.
|
|
417
|
+
|
|
418
|
+
This method creates a deep copy of the current header and modifies specific
|
|
419
|
+
dimensions and parameters based on the file type (CIFTI or other formats).
|
|
420
|
+
For text files, returns None immediately. For CIFTI files, modifies time and
|
|
421
|
+
space dimensions. For other file types, updates time dimensions and related
|
|
422
|
+
parameters.
|
|
423
|
+
|
|
424
|
+
Parameters
|
|
425
|
+
----------
|
|
426
|
+
numtimepoints : int, optional
|
|
427
|
+
Number of time points to set in the header. If None, time dimension
|
|
428
|
+
remains unchanged for non-CIFTI files.
|
|
429
|
+
tr : float, optional
|
|
430
|
+
Repetition time (TR) to set in the header. If None, TR remains unchanged.
|
|
431
|
+
toffset : float, optional
|
|
432
|
+
Time offset to set in the header. If None, time offset remains unchanged.
|
|
433
|
+
|
|
434
|
+
Returns
|
|
435
|
+
-------
|
|
436
|
+
dict or None
|
|
437
|
+
Modified header dictionary for non-text files, or None for text files.
|
|
438
|
+
Returns None if the file type is "text".
|
|
439
|
+
|
|
440
|
+
Notes
|
|
441
|
+
-----
|
|
442
|
+
For CIFTI files:
|
|
443
|
+
- Time dimension is updated to numtimepoints
|
|
444
|
+
- Space dimension is set to self.numspatiallocs
|
|
445
|
+
For other file types:
|
|
446
|
+
- Time dimension is updated to numtimepoints (index 4)
|
|
447
|
+
- Dimension index 0 is updated based on numtimepoints (4 for >1, 3 for 1)
|
|
448
|
+
- TR is set in pixdim[4] if provided
|
|
449
|
+
- Time offset is set in toffset if provided
|
|
450
|
+
|
|
451
|
+
Examples
|
|
452
|
+
--------
|
|
453
|
+
>>> header = obj.copyheader(numtimepoints=100, tr=2.0)
|
|
454
|
+
>>> header = obj.copyheader(toffset=-5.0)
|
|
455
|
+
>>> header = obj.copyheader()
|
|
456
|
+
"""
|
|
457
|
+
if self.filetype == "text":
|
|
458
|
+
return None
|
|
459
|
+
else:
|
|
460
|
+
thisheader = copy.deepcopy(self.nim_hdr)
|
|
461
|
+
if self.filetype == "cifti":
|
|
462
|
+
timeindex = thisheader["dim"][0] - 1
|
|
463
|
+
spaceindex = thisheader["dim"][0]
|
|
464
|
+
thisheader["dim"][timeindex] = numtimepoints
|
|
465
|
+
thisheader["dim"][spaceindex] = self.numspatiallocs
|
|
466
|
+
else:
|
|
467
|
+
if numtimepoints is not None:
|
|
468
|
+
thisheader["dim"][4] = numtimepoints
|
|
469
|
+
if numtimepoints > 1:
|
|
470
|
+
thisheader["dim"][0] = 4
|
|
471
|
+
else:
|
|
472
|
+
thisheader["dim"][0] = 3
|
|
473
|
+
thisheader["pixdim"][4] = 1.0
|
|
474
|
+
if toffset is not None:
|
|
475
|
+
thisheader["toffset"] = toffset
|
|
476
|
+
if tr is not None:
|
|
477
|
+
thisheader["pixdim"][4] = tr
|
|
478
|
+
return thisheader
|
|
479
|
+
|
|
480
|
+
def getsizes(self) -> tuple[float, float, float, float]:
|
|
481
|
+
"""
|
|
482
|
+
Return the dimensions and spacing parameters of the data structure.
|
|
483
|
+
|
|
484
|
+
Returns
|
|
485
|
+
-------
|
|
486
|
+
tuple[float, float, float, float]
|
|
487
|
+
A tuple containing four float values in order:
|
|
488
|
+
- xdim: x-dimension size
|
|
489
|
+
- ydim: y-dimension size
|
|
490
|
+
- slicethickness: thickness of each slice
|
|
491
|
+
- timestep: time step between measurements
|
|
492
|
+
|
|
493
|
+
Notes
|
|
494
|
+
-----
|
|
495
|
+
This method provides access to the fundamental spatial and temporal
|
|
496
|
+
parameters of the data structure. The returned values represent the
|
|
497
|
+
physical dimensions and spacing characteristics that define the
|
|
498
|
+
coordinate system of the data.
|
|
499
|
+
|
|
500
|
+
Examples
|
|
501
|
+
--------
|
|
502
|
+
>>> sizes = obj.getsizes()
|
|
503
|
+
>>> print(sizes)
|
|
504
|
+
(100.0, 100.0, 1.0, 0.1)
|
|
505
|
+
>>> x_size, y_size, slice_thick, time_step = obj.getsizes()
|
|
506
|
+
"""
|
|
507
|
+
return self.xdim, self.ydim, self.slicethickness, self.timestep
|
|
508
|
+
|
|
509
|
+
def getdims(self) -> tuple[int, int, int, int]:
|
|
510
|
+
"""
|
|
511
|
+
Return the dimensions of the data structure.
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
tuple[int, int, int, int]
|
|
516
|
+
A tuple containing four integers representing:
|
|
517
|
+
- xsize: width dimension
|
|
518
|
+
- ysize: height dimension
|
|
519
|
+
- numslices: number of slices
|
|
520
|
+
- timepoints: number of time points
|
|
521
|
+
|
|
522
|
+
Notes
|
|
523
|
+
-----
|
|
524
|
+
This method provides access to the fundamental spatial and temporal dimensions
|
|
525
|
+
of the data structure. The returned tuple follows the order (x, y, slices, time).
|
|
526
|
+
|
|
527
|
+
Examples
|
|
528
|
+
--------
|
|
529
|
+
>>> dims = obj.getdims()
|
|
530
|
+
>>> print(dims)
|
|
531
|
+
(640, 480, 32, 100)
|
|
532
|
+
>>> x, y, slices, time = obj.getdims()
|
|
533
|
+
>>> print(f"Data shape: {x} x {y} x {slices} x {time}")
|
|
534
|
+
Data shape: 640 x 480 x 32 x 100
|
|
535
|
+
"""
|
|
536
|
+
return self.xsize, self.ysize, self.numslices, self.timepoints
|
|
537
|
+
|
|
538
|
+
def unload(self) -> None:
|
|
539
|
+
"""
|
|
540
|
+
Unload Nim data and clean up resources.
|
|
541
|
+
|
|
542
|
+
This method removes the Nim data and Nim object references from the instance
|
|
543
|
+
and marks the instance as not resident in memory.
|
|
544
|
+
|
|
545
|
+
Notes
|
|
546
|
+
-----
|
|
547
|
+
This method should be called to properly clean up resources when the Nim
|
|
548
|
+
data is no longer needed. The method deletes the internal references to
|
|
549
|
+
``nim_data`` and ``nim`` objects and sets the ``resident`` flag to ``False``.
|
|
550
|
+
|
|
551
|
+
Examples
|
|
552
|
+
--------
|
|
553
|
+
>>> instance = MyClass()
|
|
554
|
+
>>> instance.load() # Load some data
|
|
555
|
+
>>> instance.unload() # Clean up resources
|
|
556
|
+
>>> instance.resident
|
|
557
|
+
False
|
|
558
|
+
"""
|
|
559
|
+
del self.nim_data
|
|
560
|
+
del self.nim
|
|
561
|
+
self.resident = False
|
|
562
|
+
|
|
563
|
+
def load(self) -> None:
|
|
564
|
+
"""
|
|
565
|
+
Load data from file based on file type detection.
|
|
566
|
+
|
|
567
|
+
This method loads data from the specified filename, automatically detecting
|
|
568
|
+
whether the file is text, CIFTI, or NIFTI format. The loaded data is stored
|
|
569
|
+
in instance variables for subsequent processing.
|
|
570
|
+
|
|
571
|
+
Parameters
|
|
572
|
+
----------
|
|
573
|
+
self : object
|
|
574
|
+
The instance of the class containing this method. Expected to have
|
|
575
|
+
attributes: filename (str), filetype (str or None), and various data
|
|
576
|
+
storage attributes (nim_data, nim, cifti_hdr, nim_hdr, thedims, thesizes).
|
|
577
|
+
|
|
578
|
+
Returns
|
|
579
|
+
-------
|
|
580
|
+
None
|
|
581
|
+
This method does not return any value but updates instance attributes
|
|
582
|
+
with loaded data.
|
|
583
|
+
|
|
584
|
+
Notes
|
|
585
|
+
-----
|
|
586
|
+
- If filetype is not None, the method prints "reloading non-resident data"
|
|
587
|
+
- For text files, data is read using tide_io.readvecs()
|
|
588
|
+
- For CIFTI files, data is read using tide_io.readfromcifti() and stored
|
|
589
|
+
in multiple attributes including cifti_hdr and nim_hdr
|
|
590
|
+
- For NIFTI files, data is read using tide_io.readfromnifti() and stored
|
|
591
|
+
in nim, nim_data, nim_hdr, thedims, and thesizes attributes
|
|
592
|
+
- The method sets self.resident = True upon successful completion
|
|
593
|
+
|
|
594
|
+
Examples
|
|
595
|
+
--------
|
|
596
|
+
>>> loader = DataContainer()
|
|
597
|
+
>>> loader.filename = "data.nii.gz"
|
|
598
|
+
>>> loader.load()
|
|
599
|
+
loading data from data.nii.gz
|
|
600
|
+
"""
|
|
601
|
+
if self.filetype is not None:
|
|
602
|
+
print("reloading non-resident data")
|
|
603
|
+
else:
|
|
604
|
+
print(f"loading data from {self.filename}")
|
|
605
|
+
if tide_io.checkiftext(self.filename):
|
|
606
|
+
self.nim_data = tide_io.readvecs(self.filename)
|
|
607
|
+
self.nim = None
|
|
608
|
+
else:
|
|
609
|
+
if tide_io.checkifcifti(self.filename):
|
|
610
|
+
self.filetype = "cifti"
|
|
611
|
+
(
|
|
612
|
+
dummy,
|
|
613
|
+
self.cifti_hdr,
|
|
614
|
+
self.nim_data,
|
|
615
|
+
self.nim_hdr,
|
|
616
|
+
self.thedims,
|
|
617
|
+
self.thesizes,
|
|
618
|
+
dummy,
|
|
619
|
+
) = tide_io.readfromcifti(self.filename)
|
|
620
|
+
self.nim = None
|
|
621
|
+
else:
|
|
622
|
+
self.nim, self.nim_data, self.nim_hdr, self.thedims, self.thesizes = (
|
|
623
|
+
tide_io.readfromnifti(self.filename)
|
|
624
|
+
)
|
|
625
|
+
self.resident = True
|
|
626
|
+
|
|
627
|
+
def setvalidtimes(self, validstart: int | None, validend: int | None) -> None:
|
|
628
|
+
"""
|
|
629
|
+
Set valid time points for the object based on start and end indices.
|
|
630
|
+
|
|
631
|
+
This method configures the valid time range for the object by setting
|
|
632
|
+
`validstart` and `validend` attributes. It also calculates the number of
|
|
633
|
+
real time points and updates the native fMRI shape based on the file type.
|
|
634
|
+
|
|
635
|
+
Parameters
|
|
636
|
+
----------
|
|
637
|
+
validstart : int, optional
|
|
638
|
+
The starting index of valid time points. If None, defaults to 0.
|
|
639
|
+
validend : int, optional
|
|
640
|
+
The ending index of valid time points. If None, defaults to
|
|
641
|
+
`self.timepoints - 1`.
|
|
642
|
+
|
|
643
|
+
Returns
|
|
644
|
+
-------
|
|
645
|
+
None
|
|
646
|
+
This method modifies the object's attributes in-place and does not return anything.
|
|
647
|
+
|
|
648
|
+
Notes
|
|
649
|
+
-----
|
|
650
|
+
The method calculates `realtimepoints` as `validend - validstart + 1`.
|
|
651
|
+
The `nativefmrishape` is updated based on the `filetype` attribute:
|
|
652
|
+
- "nifti": (xsize, ysize, numslices, realtimepoints)
|
|
653
|
+
- "cifti": (1, 1, 1, realtimepoints, numspatiallocs)
|
|
654
|
+
- else: (xsize, realtimepoints)
|
|
655
|
+
|
|
656
|
+
Examples
|
|
657
|
+
--------
|
|
658
|
+
>>> obj.setvalidtimes(5, 15)
|
|
659
|
+
>>> obj.setvalidtimes(None, 10)
|
|
660
|
+
>>> obj.setvalidtimes(0, None)
|
|
661
|
+
"""
|
|
662
|
+
if validstart is None:
|
|
663
|
+
self.validstart = 0
|
|
664
|
+
else:
|
|
665
|
+
self.validstart = validstart
|
|
666
|
+
if validend is None:
|
|
667
|
+
self.validend = self.timepoints - 1
|
|
668
|
+
else:
|
|
669
|
+
self.validend = validend
|
|
670
|
+
self.realtimepoints = self.validend - self.validstart + 1
|
|
671
|
+
if self.filetype == "nifti":
|
|
672
|
+
self.nativefmrishape = (self.xsize, self.ysize, self.numslices, self.realtimepoints)
|
|
673
|
+
elif self.filetype == "cifti":
|
|
674
|
+
self.nativefmrishape = (1, 1, 1, self.realtimepoints, self.numspatiallocs)
|
|
675
|
+
else:
|
|
676
|
+
self.nativefmrishape = (self.xsize, self.realtimepoints)
|
|
677
|
+
|
|
678
|
+
def setvalidvoxels(self, validvoxels: NDArray) -> None:
|
|
679
|
+
"""
|
|
680
|
+
Set the valid voxels for the object.
|
|
681
|
+
|
|
682
|
+
Parameters
|
|
683
|
+
----------
|
|
684
|
+
validvoxels : NDArray
|
|
685
|
+
Array containing the valid voxel coordinates. The first dimension
|
|
686
|
+
represents the number of valid spatial locations.
|
|
687
|
+
|
|
688
|
+
Returns
|
|
689
|
+
-------
|
|
690
|
+
None
|
|
691
|
+
This method does not return any value.
|
|
692
|
+
|
|
693
|
+
Notes
|
|
694
|
+
-----
|
|
695
|
+
This method updates two attributes:
|
|
696
|
+
- `self.validvoxels`: Stores the provided valid voxel array
|
|
697
|
+
- `self.numvalidspatiallocs`: Stores the number of valid spatial locations
|
|
698
|
+
(derived from the shape of the validvoxels array)
|
|
699
|
+
|
|
700
|
+
Examples
|
|
701
|
+
--------
|
|
702
|
+
>>> obj = MyClass()
|
|
703
|
+
>>> voxels = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]])
|
|
704
|
+
>>> obj.setvalidvoxels(voxels)
|
|
705
|
+
>>> print(obj.numvalidspatiallocs)
|
|
706
|
+
3
|
|
707
|
+
"""
|
|
708
|
+
self.validvoxels = validvoxels
|
|
709
|
+
self.numvalidspatiallocs = np.shape(self.validvoxels)[0]
|
|
710
|
+
|
|
711
|
+
def byvol(self) -> NDArray:
|
|
712
|
+
"""
|
|
713
|
+
Return the nim_data array from the object.
|
|
714
|
+
|
|
715
|
+
If the object is not resident, it will be loaded first.
|
|
716
|
+
|
|
717
|
+
Returns
|
|
718
|
+
-------
|
|
719
|
+
NDArray
|
|
720
|
+
The nim_data array stored in the object.
|
|
721
|
+
|
|
722
|
+
Notes
|
|
723
|
+
-----
|
|
724
|
+
This method checks if the object is resident and loads it if necessary
|
|
725
|
+
before returning the nim_data array.
|
|
726
|
+
|
|
727
|
+
Examples
|
|
728
|
+
--------
|
|
729
|
+
>>> obj = MyClass()
|
|
730
|
+
>>> data = obj.byvol()
|
|
731
|
+
>>> print(data.shape)
|
|
732
|
+
(100, 100)
|
|
733
|
+
"""
|
|
734
|
+
if not self.resident:
|
|
735
|
+
self.load()
|
|
736
|
+
return self.nim_data
|
|
737
|
+
|
|
738
|
+
def byvoltrimmed(self) -> NDArray:
|
|
739
|
+
"""
|
|
740
|
+
Return data with volume trimming applied based on valid time range.
|
|
741
|
+
|
|
742
|
+
This method returns the neuroimaging data with temporal dimensions trimmed
|
|
743
|
+
according to the valid start and end indices. The behavior varies depending
|
|
744
|
+
on the file type and dimensions of the data.
|
|
745
|
+
|
|
746
|
+
Returns
|
|
747
|
+
-------
|
|
748
|
+
NDArray
|
|
749
|
+
Trimmed neuroimaging data array. For NIfTI files with 4D data or
|
|
750
|
+
CIFTI/text files, returns data with shape (X, Y, Z, T) where T is
|
|
751
|
+
the trimmed temporal dimension. For other file types, returns data
|
|
752
|
+
with shape (X, Y, Z) or (X, T) depending on the data structure.
|
|
753
|
+
|
|
754
|
+
Notes
|
|
755
|
+
-----
|
|
756
|
+
- If the data is not resident in memory, it will be loaded automatically
|
|
757
|
+
- For NIfTI files with 4D data, CIFTI files, or text files, the temporal
|
|
758
|
+
dimension is trimmed using self.validstart and self.validend
|
|
759
|
+
- For other file types, only the temporal dimension is trimmed
|
|
760
|
+
- The validend index is inclusive in the returned data
|
|
761
|
+
|
|
762
|
+
Examples
|
|
763
|
+
--------
|
|
764
|
+
>>> data = obj.byvoltrimmed()
|
|
765
|
+
>>> print(data.shape)
|
|
766
|
+
(64, 64, 32, 100) # For 4D NIfTI data with 100 valid time points
|
|
767
|
+
"""
|
|
768
|
+
if not self.resident:
|
|
769
|
+
self.load()
|
|
770
|
+
if self.filetype == "nifti":
|
|
771
|
+
if self.dimensions == 4 or self.filetype == "cifti" or self.filetype == "text":
|
|
772
|
+
return self.nim_data[:, :, :, self.validstart : self.validend + 1]
|
|
773
|
+
else:
|
|
774
|
+
return self.nim_data[:, :, :]
|
|
775
|
+
else:
|
|
776
|
+
return self.nim_data[:, self.validstart : self.validend + 1]
|
|
777
|
+
|
|
778
|
+
def byvoxel(self) -> NDArray:
|
|
779
|
+
"""
|
|
780
|
+
Reshape data by voxel across spatial locations.
|
|
781
|
+
|
|
782
|
+
This method reshapes the trimmed volume data to organize it by voxel
|
|
783
|
+
across all spatial locations. The output format depends on the
|
|
784
|
+
file type and dimensions of the data.
|
|
785
|
+
|
|
786
|
+
Returns
|
|
787
|
+
-------
|
|
788
|
+
NDArray
|
|
789
|
+
Reshaped array where each row represents a voxel and columns
|
|
790
|
+
represent time points or other dimensions. For 4D data or
|
|
791
|
+
CIFTI/text files, the shape is (numspatiallocs, -1), otherwise
|
|
792
|
+
(numspatiallocs,).
|
|
793
|
+
|
|
794
|
+
Notes
|
|
795
|
+
-----
|
|
796
|
+
- For 4D data, CIFTI files, or text files, the result is reshaped to
|
|
797
|
+
have an additional dimension for time points or other temporal
|
|
798
|
+
dimensions
|
|
799
|
+
- For other file types, the result is reshaped to a 2D array with
|
|
800
|
+
shape (numspatiallocs,)
|
|
801
|
+
|
|
802
|
+
Examples
|
|
803
|
+
--------
|
|
804
|
+
>>> data = MyDataClass()
|
|
805
|
+
>>> voxel_data = data.byvoxel()
|
|
806
|
+
>>> print(voxel_data.shape)
|
|
807
|
+
(numspatiallocs, num_timepoints)
|
|
808
|
+
"""
|
|
809
|
+
if self.dimensions == 4 or self.filetype == "cifti" or self.filetype == "text":
|
|
810
|
+
return self.byvoltrimmed().reshape(self.numspatiallocs, -1)
|
|
811
|
+
else:
|
|
812
|
+
return self.byvoltrimmed().reshape(self.numspatiallocs)
|
|
813
|
+
|
|
814
|
+
def byslice(self) -> NDArray:
|
|
815
|
+
"""
|
|
816
|
+
Reshape data by slice dimensions.
|
|
817
|
+
|
|
818
|
+
Reshapes the data returned by `byvoltrimmed()` to organize data by slice
|
|
819
|
+
locations and slices. The output format depends on the file type and
|
|
820
|
+
dimensions of the data.
|
|
821
|
+
|
|
822
|
+
Returns
|
|
823
|
+
-------
|
|
824
|
+
NDArray
|
|
825
|
+
Reshaped array with dimensions (numslicelocs, numslices, -1) for
|
|
826
|
+
CIFTI or text files, or (numslicelocs, numslices) for other file types.
|
|
827
|
+
|
|
828
|
+
Notes
|
|
829
|
+
-----
|
|
830
|
+
This method is particularly useful for organizing volumetric data by
|
|
831
|
+
slice locations and slices. For CIFTI and text file types, the last
|
|
832
|
+
dimension is automatically expanded to accommodate additional data
|
|
833
|
+
dimensions.
|
|
834
|
+
|
|
835
|
+
Examples
|
|
836
|
+
--------
|
|
837
|
+
>>> data = MyClass()
|
|
838
|
+
>>> result = data.byslice()
|
|
839
|
+
>>> print(result.shape)
|
|
840
|
+
(10, 20, 100) # for CIFTI/text files
|
|
841
|
+
>>> print(result.shape)
|
|
842
|
+
(10, 20) # for other file types
|
|
843
|
+
"""
|
|
844
|
+
if self.dimensions == 4 or self.filetype == "cifti" or self.filetype == "text":
|
|
845
|
+
return self.byvoltrimmed().reshape(self.numslicelocs, self.numslices, -1)
|
|
846
|
+
else:
|
|
847
|
+
return self.byvoltrimmed().reshape(self.numslicelocs, self.numslices)
|
|
848
|
+
|
|
849
|
+
def validdata(self) -> NDArray:
|
|
850
|
+
"""
|
|
851
|
+
Return valid voxel data based on validvoxels mask.
|
|
852
|
+
|
|
853
|
+
If validvoxels is None, returns all voxel data. Otherwise, returns
|
|
854
|
+
only the subset of voxel data indicated by the validvoxels mask.
|
|
855
|
+
|
|
856
|
+
Returns
|
|
857
|
+
-------
|
|
858
|
+
NDArray
|
|
859
|
+
Array containing voxel data. If validvoxels is None, returns
|
|
860
|
+
all voxel data from byvoxel() method. If validvoxels is not None,
|
|
861
|
+
returns subset of voxel data filtered by validvoxels mask.
|
|
862
|
+
|
|
863
|
+
Notes
|
|
864
|
+
-----
|
|
865
|
+
This method relies on the byvoxel() method to generate the base
|
|
866
|
+
voxel data array and applies filtering based on the validvoxels
|
|
867
|
+
attribute if it exists.
|
|
868
|
+
|
|
869
|
+
Examples
|
|
870
|
+
--------
|
|
871
|
+
>>> # Get all voxel data
|
|
872
|
+
>>> data = obj.validdata()
|
|
873
|
+
>>>
|
|
874
|
+
>>> # Get filtered voxel data
|
|
875
|
+
>>> obj.validvoxels = [0, 1, 2, 5, 10]
|
|
876
|
+
>>> data = obj.validdata()
|
|
877
|
+
"""
|
|
878
|
+
if self.validvoxels is None:
|
|
879
|
+
return self.byvoxel()
|
|
880
|
+
else:
|
|
881
|
+
return self.byvoxel()[self.validvoxels, :]
|
|
882
|
+
|
|
883
|
+
# def validdatabyslice(self):
|
|
884
|
+
# if self.validvoxels is None:
|
|
885
|
+
# return self.byslice()
|
|
886
|
+
# else:
|
|
887
|
+
# return self.byvoxel()[self.validvoxels, :].reshape(self.numslicelocs, self.numslices, -1)
|
|
888
|
+
|
|
889
|
+
def smooth(
|
|
890
|
+
self,
|
|
891
|
+
gausssigma: float,
|
|
892
|
+
brainmask: NDArray | None = None,
|
|
893
|
+
graymask: NDArray | None = None,
|
|
894
|
+
whitemask: NDArray | None = None,
|
|
895
|
+
premask: bool = False,
|
|
896
|
+
premasktissueonly: bool = False,
|
|
897
|
+
showprogressbar: bool = False,
|
|
898
|
+
) -> float:
|
|
899
|
+
"""
|
|
900
|
+
Apply Gaussian spatial smoothing to the data.
|
|
901
|
+
|
|
902
|
+
This function applies a Gaussian spatial filter to the data, with optional
|
|
903
|
+
pre-masking of brain or tissue regions. For CIFTI and text file types, the
|
|
904
|
+
smoothing is skipped by setting `gausssigma` to 0.0. If `gausssigma` is less
|
|
905
|
+
than 0.0, it is automatically set to the mean of the image dimensions divided
|
|
906
|
+
by 2.0.
|
|
907
|
+
|
|
908
|
+
Parameters
|
|
909
|
+
----------
|
|
910
|
+
gausssigma : float
|
|
911
|
+
Standard deviation for the Gaussian kernel. If less than 0.0, it is
|
|
912
|
+
automatically calculated as the mean of image dimensions divided by 2.0.
|
|
913
|
+
brainmask : NDArray | None, optional
|
|
914
|
+
Binary mask for the brain region. Required if `premask` is True and
|
|
915
|
+
`premasktissueonly` is False.
|
|
916
|
+
graymask : NDArray | None, optional
|
|
917
|
+
Binary mask for gray matter. Required if `premask` is True and
|
|
918
|
+
`premasktissueonly` is True.
|
|
919
|
+
whitemask : NDArray | None, optional
|
|
920
|
+
Binary mask for white matter. Required if `premask` is True and
|
|
921
|
+
`premasktissueonly` is True.
|
|
922
|
+
premask : bool, optional
|
|
923
|
+
If True, applies the mask before smoothing. Default is False.
|
|
924
|
+
premasktissueonly : bool, optional
|
|
925
|
+
If True, applies the mask only to gray and white matter. Requires
|
|
926
|
+
`graymask` and `whitemask` to be provided. Default is False.
|
|
927
|
+
showprogressbar : bool, optional
|
|
928
|
+
If True, displays a progress bar during processing. Default is False.
|
|
929
|
+
|
|
930
|
+
Returns
|
|
931
|
+
-------
|
|
932
|
+
float
|
|
933
|
+
The actual `gausssigma` value used for smoothing.
|
|
934
|
+
|
|
935
|
+
Notes
|
|
936
|
+
-----
|
|
937
|
+
- For CIFTI and text file types, smoothing is skipped.
|
|
938
|
+
- The function modifies `self.nim_data` in-place.
|
|
939
|
+
- If `premask` is True, the mask is applied to the timepoints specified by
|
|
940
|
+
`self.validstart` to `self.validend`.
|
|
941
|
+
|
|
942
|
+
Examples
|
|
943
|
+
--------
|
|
944
|
+
>>> # Apply smoothing with automatic sigma
|
|
945
|
+
>>> smooth(-1.0)
|
|
946
|
+
1.5
|
|
947
|
+
|
|
948
|
+
>>> # Apply smoothing with a custom sigma and pre-mask
|
|
949
|
+
>>> smooth(2.0, brainmask=mask, premask=True)
|
|
950
|
+
2.0
|
|
951
|
+
"""
|
|
952
|
+
# do spatial filtering if requested
|
|
953
|
+
if self.filetype == "cifti" or self.filetype == "text":
|
|
954
|
+
gausssigma = 0.0
|
|
955
|
+
if gausssigma < 0.0:
|
|
956
|
+
# set gausssigma automatically
|
|
957
|
+
gausssigma = np.mean([self.xdim, self.ydim, self.slicethickness]) / 2.0
|
|
958
|
+
if gausssigma > 0.0:
|
|
959
|
+
# premask data if requested
|
|
960
|
+
if premask:
|
|
961
|
+
if premasktissueonly:
|
|
962
|
+
if (graymask is not None) and (whitemask is not None):
|
|
963
|
+
multmask = graymask + whitemask
|
|
964
|
+
else:
|
|
965
|
+
raise ValueError(
|
|
966
|
+
"ERROR: graymask and whitemask must be defined to use premasktissueonly - exiting"
|
|
967
|
+
)
|
|
968
|
+
else:
|
|
969
|
+
if brainmask is not None:
|
|
970
|
+
multmask = brainmask
|
|
971
|
+
else:
|
|
972
|
+
raise ValueError(
|
|
973
|
+
"ERROR: brainmask must be defined to use premask - exiting"
|
|
974
|
+
)
|
|
975
|
+
print(f"premasking timepoints {self.validstart} to {self.validend}")
|
|
976
|
+
for i in tqdm(
|
|
977
|
+
range(self.validstart, self.validend + 1),
|
|
978
|
+
desc="Timepoint",
|
|
979
|
+
unit="timepoints",
|
|
980
|
+
disable=(not showprogressbar),
|
|
981
|
+
):
|
|
982
|
+
self.nim_data[:, :, :, i] *= multmask
|
|
983
|
+
|
|
984
|
+
# now apply the filter
|
|
985
|
+
print(
|
|
986
|
+
f"applying gaussian spatial filter to timepoints {self.validstart} "
|
|
987
|
+
f"to {self.validend} with sigma={gausssigma}"
|
|
988
|
+
)
|
|
989
|
+
sourcedata = self.byvol()
|
|
990
|
+
for i in tqdm(
|
|
991
|
+
range(self.validstart, self.validend + 1),
|
|
992
|
+
desc="Timepoint",
|
|
993
|
+
unit="timepoints",
|
|
994
|
+
disable=(not showprogressbar),
|
|
995
|
+
):
|
|
996
|
+
self.nim_data[:, :, :, i] = tide_filt.ssmooth(
|
|
997
|
+
self.xdim,
|
|
998
|
+
self.ydim,
|
|
999
|
+
self.slicethickness,
|
|
1000
|
+
gausssigma,
|
|
1001
|
+
sourcedata[:, :, :, i],
|
|
1002
|
+
)
|
|
1003
|
+
return gausssigma
|
|
1004
|
+
|
|
1005
|
+
def summarize(self) -> None:
|
|
1006
|
+
"""
|
|
1007
|
+
Print a comprehensive summary of voxel data properties.
|
|
1008
|
+
|
|
1009
|
+
This method outputs detailed information about the voxel data structure,
|
|
1010
|
+
including image dimensions, spatial properties, temporal characteristics,
|
|
1011
|
+
and file metadata. The summary includes both geometric and temporal
|
|
1012
|
+
parameters that define the voxel space and data organization.
|
|
1013
|
+
|
|
1014
|
+
Notes
|
|
1015
|
+
-----
|
|
1016
|
+
The method prints to standard output and does not return any value.
|
|
1017
|
+
All attributes are accessed from the instance and displayed in a
|
|
1018
|
+
formatted manner for easy inspection of the data structure.
|
|
1019
|
+
|
|
1020
|
+
Examples
|
|
1021
|
+
--------
|
|
1022
|
+
>>> obj.summarize()
|
|
1023
|
+
Voxel data summary:
|
|
1024
|
+
self.nim=...
|
|
1025
|
+
self.nim_data.shape=...
|
|
1026
|
+
self.nim_hdr=...
|
|
1027
|
+
self.nim_affine=...
|
|
1028
|
+
...
|
|
1029
|
+
"""
|
|
1030
|
+
print("Voxel data summary:")
|
|
1031
|
+
print(f"\t{self.nim=}")
|
|
1032
|
+
print(f"\t{self.nim_data.shape=}")
|
|
1033
|
+
print(f"\t{self.nim_hdr=}")
|
|
1034
|
+
print(f"\t{self.nim_affine=}")
|
|
1035
|
+
print(f"\t{self.theshape=}")
|
|
1036
|
+
print(f"\t{self.xsize=}")
|
|
1037
|
+
print(f"\t{self.ysize=}")
|
|
1038
|
+
print(f"\t{self.numslices=}")
|
|
1039
|
+
print(f"\t{self.timepoints=}")
|
|
1040
|
+
print(f"\t{self.timestep=}")
|
|
1041
|
+
print(f"\t{self.thesizes=}")
|
|
1042
|
+
print(f"\t{self.thedims=}")
|
|
1043
|
+
print(f"\t{self.numslicelocs=}")
|
|
1044
|
+
print(f"\t{self.numspatiallocs=}")
|
|
1045
|
+
print(f"\t{self.nativespaceshape=}")
|
|
1046
|
+
print(f"\t{self.cifti_hdr=}")
|
|
1047
|
+
print(f"\t{self.filetype=}")
|
|
1048
|
+
print(f"\t{self.resident=}")
|