rapidtide 2.9.6__py3-none-any.whl → 3.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +92 -42
- 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 +2 -2
- 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 +108 -92
- 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 +587 -1116
- rapidtide/io.py +2569 -468
- rapidtide/linfitfiltpass.py +784 -0
- rapidtide/makelaggedtcs.py +267 -97
- rapidtide/maskutil.py +555 -25
- rapidtide/miscmath.py +835 -144
- 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.6.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 +26 -14
- 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 +1785 -1858
- rapidtide/workflows/rapidtide2std.py +101 -3
- rapidtide/workflows/rapidtide_parser.py +590 -389
- 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.6.dist-info → rapidtide-3.1.3.dist-info}/METADATA +30 -223
- rapidtide-3.1.3.dist-info/RECORD +393 -0
- {rapidtide-2.9.6.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.6.data/scripts/adjustoffset +0 -23
- rapidtide-2.9.6.data/scripts/aligntcs +0 -23
- rapidtide-2.9.6.data/scripts/applydlfilter +0 -23
- rapidtide-2.9.6.data/scripts/atlasaverage +0 -23
- rapidtide-2.9.6.data/scripts/atlastool +0 -23
- rapidtide-2.9.6.data/scripts/calcicc +0 -22
- rapidtide-2.9.6.data/scripts/calctexticc +0 -23
- rapidtide-2.9.6.data/scripts/calcttest +0 -22
- rapidtide-2.9.6.data/scripts/ccorrica +0 -23
- rapidtide-2.9.6.data/scripts/diffrois +0 -23
- rapidtide-2.9.6.data/scripts/endtidalproc +0 -23
- rapidtide-2.9.6.data/scripts/filtnifti +0 -23
- rapidtide-2.9.6.data/scripts/filttc +0 -23
- rapidtide-2.9.6.data/scripts/fingerprint +0 -593
- rapidtide-2.9.6.data/scripts/fixtr +0 -23
- rapidtide-2.9.6.data/scripts/glmfilt +0 -24
- rapidtide-2.9.6.data/scripts/gmscalc +0 -22
- rapidtide-2.9.6.data/scripts/happy +0 -25
- rapidtide-2.9.6.data/scripts/happy2std +0 -23
- rapidtide-2.9.6.data/scripts/happywarp +0 -350
- rapidtide-2.9.6.data/scripts/histnifti +0 -23
- rapidtide-2.9.6.data/scripts/histtc +0 -23
- rapidtide-2.9.6.data/scripts/localflow +0 -23
- rapidtide-2.9.6.data/scripts/mergequality +0 -23
- rapidtide-2.9.6.data/scripts/pairproc +0 -23
- rapidtide-2.9.6.data/scripts/pairwisemergenifti +0 -23
- rapidtide-2.9.6.data/scripts/physiofreq +0 -23
- rapidtide-2.9.6.data/scripts/pixelcomp +0 -23
- rapidtide-2.9.6.data/scripts/plethquality +0 -23
- rapidtide-2.9.6.data/scripts/polyfitim +0 -23
- rapidtide-2.9.6.data/scripts/proj2flow +0 -23
- rapidtide-2.9.6.data/scripts/rankimage +0 -23
- rapidtide-2.9.6.data/scripts/rapidtide +0 -23
- rapidtide-2.9.6.data/scripts/rapidtide2std +0 -23
- rapidtide-2.9.6.data/scripts/resamplenifti +0 -23
- rapidtide-2.9.6.data/scripts/resampletc +0 -23
- rapidtide-2.9.6.data/scripts/retroglm +0 -23
- rapidtide-2.9.6.data/scripts/roisummarize +0 -23
- rapidtide-2.9.6.data/scripts/runqualitycheck +0 -23
- rapidtide-2.9.6.data/scripts/showarbcorr +0 -23
- rapidtide-2.9.6.data/scripts/showhist +0 -23
- rapidtide-2.9.6.data/scripts/showstxcorr +0 -23
- rapidtide-2.9.6.data/scripts/showtc +0 -23
- rapidtide-2.9.6.data/scripts/showxcorr_legacy +0 -536
- rapidtide-2.9.6.data/scripts/showxcorrx +0 -23
- rapidtide-2.9.6.data/scripts/showxy +0 -23
- rapidtide-2.9.6.data/scripts/simdata +0 -23
- rapidtide-2.9.6.data/scripts/spatialdecomp +0 -23
- rapidtide-2.9.6.data/scripts/spatialfit +0 -23
- rapidtide-2.9.6.data/scripts/spatialmi +0 -23
- rapidtide-2.9.6.data/scripts/spectrogram +0 -23
- rapidtide-2.9.6.data/scripts/synthASL +0 -23
- rapidtide-2.9.6.data/scripts/tcfrom2col +0 -23
- rapidtide-2.9.6.data/scripts/tcfrom3col +0 -23
- rapidtide-2.9.6.data/scripts/temporaldecomp +0 -23
- rapidtide-2.9.6.data/scripts/threeD +0 -236
- rapidtide-2.9.6.data/scripts/tidepool +0 -23
- rapidtide-2.9.6.data/scripts/variabilityizer +0 -23
- rapidtide-2.9.6.dist-info/RECORD +0 -359
- rapidtide-2.9.6.dist-info/top_level.txt +0 -86
- {rapidtide-2.9.6.dist-info → rapidtide-3.1.3.dist-info/licenses}/LICENSE +0 -0
rapidtide/workflows/utils.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
#
|
|
4
|
-
# Copyright 2021-
|
|
4
|
+
# Copyright 2021-2025 Blaise Frederick
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -19,16 +19,19 @@
|
|
|
19
19
|
"""Utility functions for rapidtide workflows."""
|
|
20
20
|
import logging
|
|
21
21
|
import os
|
|
22
|
+
from typing import Any, Optional
|
|
22
23
|
|
|
23
24
|
LGR = logging.getLogger("GENERAL")
|
|
24
25
|
TimingLGR = logging.getLogger("TIMING")
|
|
25
26
|
MemoryLGR = logging.getLogger("MEMORY")
|
|
27
|
+
ErrorLGR = logging.getLogger("ERROR")
|
|
26
28
|
|
|
27
29
|
starttime = None
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
class ContextFilter(logging.Filter):
|
|
31
|
-
"""
|
|
33
|
+
"""
|
|
34
|
+
A filter to allow specific logging handlers to ignore specific loggers.
|
|
32
35
|
|
|
33
36
|
We use this to prevent our secondary loggers from printing to the general log file or to
|
|
34
37
|
stdout.
|
|
@@ -36,18 +39,20 @@ class ContextFilter(logging.Filter):
|
|
|
36
39
|
|
|
37
40
|
NAMES = {"TIMING", "MEMORY"}
|
|
38
41
|
|
|
39
|
-
def filter(self, record):
|
|
42
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
40
43
|
if not any([n in record.name for n in self.NAMES]):
|
|
41
44
|
return True
|
|
45
|
+
return False
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
class TimingFormatter(logging.Formatter):
|
|
45
|
-
"""
|
|
49
|
+
"""
|
|
50
|
+
A formatter to allow optional extra fields (message2 and message3) in a logger.
|
|
46
51
|
|
|
47
52
|
The fields must be passed as a dictionary, without a keyword.
|
|
48
53
|
"""
|
|
49
54
|
|
|
50
|
-
def format(self, record):
|
|
55
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
51
56
|
if isinstance(record.args, dict):
|
|
52
57
|
record.message2 = record.args.get("message2", None)
|
|
53
58
|
record.message3 = record.args.get("message3", None)
|
|
@@ -57,8 +62,16 @@ class TimingFormatter(logging.Formatter):
|
|
|
57
62
|
return super().format(record)
|
|
58
63
|
|
|
59
64
|
|
|
60
|
-
def setup_logger(
|
|
61
|
-
|
|
65
|
+
def setup_logger(
|
|
66
|
+
logger_filename: str,
|
|
67
|
+
timing_filename: str,
|
|
68
|
+
memory_filename: Optional[str] = None,
|
|
69
|
+
error_filename: Optional[str] = None,
|
|
70
|
+
isverbose: bool = False,
|
|
71
|
+
debug: bool = False,
|
|
72
|
+
) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Set up a set of loggers.
|
|
62
75
|
|
|
63
76
|
Parameters
|
|
64
77
|
----------
|
|
@@ -68,6 +81,8 @@ def setup_logger(logger_filename, timing_filename, memory_filename, verbose=Fals
|
|
|
68
81
|
Output file for timing-related information.
|
|
69
82
|
memory_filename : str
|
|
70
83
|
Output file for memory usage-related information.
|
|
84
|
+
error_filename : str
|
|
85
|
+
Output file for error-related information.
|
|
71
86
|
verbose : bool, optional
|
|
72
87
|
Sets the target logging level to VERBOSE (a custom level between INFO and DEBUG).
|
|
73
88
|
Is overridden by ``debug``, if ``debug = True``.
|
|
@@ -76,16 +91,17 @@ def setup_logger(logger_filename, timing_filename, memory_filename, verbose=Fals
|
|
|
76
91
|
Sets the target logging level to DEBUG. Default is False.
|
|
77
92
|
"""
|
|
78
93
|
# Clean up existing files from previous runs
|
|
79
|
-
for fname in [logger_filename, timing_filename, memory_filename]:
|
|
80
|
-
if
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
for fname in [logger_filename, timing_filename, memory_filename, error_filename]:
|
|
95
|
+
if fname is not None:
|
|
96
|
+
if os.path.isfile(fname):
|
|
97
|
+
LGR.info(f"Removing existing file: {fname}")
|
|
98
|
+
os.remove(fname)
|
|
83
99
|
|
|
84
100
|
# Create a new "verbose" logging level
|
|
85
101
|
VERBOSE_LEVEL = 15 # between info and debug
|
|
86
102
|
logging.addLevelName(VERBOSE_LEVEL, "VERBOSE")
|
|
87
103
|
|
|
88
|
-
def verbose(self, message, *args, **kwargs):
|
|
104
|
+
def verbose(self: logging.Logger, message: str, *args: Any, **kwargs: Any) -> None:
|
|
89
105
|
if self.isEnabledFor(VERBOSE_LEVEL):
|
|
90
106
|
self._log(VERBOSE_LEVEL, message, args, **kwargs)
|
|
91
107
|
|
|
@@ -94,7 +110,7 @@ def setup_logger(logger_filename, timing_filename, memory_filename, verbose=Fals
|
|
|
94
110
|
# Set logging level for main logger
|
|
95
111
|
if debug:
|
|
96
112
|
logging.root.setLevel(logging.DEBUG)
|
|
97
|
-
elif
|
|
113
|
+
elif isverbose:
|
|
98
114
|
logging.root.setLevel(VERBOSE_LEVEL)
|
|
99
115
|
else:
|
|
100
116
|
logging.root.setLevel(logging.INFO)
|
|
@@ -129,9 +145,19 @@ def setup_logger(logger_filename, timing_filename, memory_filename, verbose=Fals
|
|
|
129
145
|
TimingLGR.propagate = False # do not print to console
|
|
130
146
|
|
|
131
147
|
# A memory logger
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
148
|
+
if memory_filename is not None:
|
|
149
|
+
memory_formatter = logging.Formatter("%(message)s")
|
|
150
|
+
memory_handler = logging.FileHandler(memory_filename)
|
|
151
|
+
memory_handler.setFormatter(memory_formatter)
|
|
152
|
+
MemoryLGR.setLevel(logging.INFO)
|
|
153
|
+
MemoryLGR.addHandler(memory_handler)
|
|
154
|
+
MemoryLGR.propagate = False # do not print to console
|
|
155
|
+
|
|
156
|
+
# An error logger
|
|
157
|
+
if error_filename is not None:
|
|
158
|
+
error_formatter = logging.Formatter("%(message)s")
|
|
159
|
+
error_handler = logging.FileHandler(error_filename)
|
|
160
|
+
error_handler.setFormatter(error_formatter)
|
|
161
|
+
ErrorLGR.setLevel(logging.INFO)
|
|
162
|
+
ErrorLGR.addHandler(error_handler)
|
|
163
|
+
ErrorLGR.propagate = False # do not print to console
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2021-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
|
+
"""Utility functions for rapidtide workflows."""
|
|
20
|
+
import logging
|
|
21
|
+
import os
|
|
22
|
+
from typing import Any, Optional
|
|
23
|
+
|
|
24
|
+
LGR = logging.getLogger("GENERAL")
|
|
25
|
+
TimingLGR = logging.getLogger("TIMING")
|
|
26
|
+
MemoryLGR = logging.getLogger("MEMORY")
|
|
27
|
+
ErrorLGR = logging.getLogger("ERROR")
|
|
28
|
+
|
|
29
|
+
starttime = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ContextFilter(logging.Filter):
|
|
33
|
+
"""
|
|
34
|
+
A filter to allow specific logging handlers to ignore specific loggers.
|
|
35
|
+
|
|
36
|
+
We use this to prevent our secondary loggers from printing to the general log file or to
|
|
37
|
+
stdout.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
NAMES = {"TIMING", "MEMORY"}
|
|
41
|
+
|
|
42
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
43
|
+
if not any([n in record.name for n in self.NAMES]):
|
|
44
|
+
return True
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TimingFormatter(logging.Formatter):
|
|
49
|
+
"""
|
|
50
|
+
Determine whether to filter a log record based on its name.
|
|
51
|
+
|
|
52
|
+
This filter checks if any of the names in `self.NAMES` are contained
|
|
53
|
+
within the log record's name. If none of the names are found, the record
|
|
54
|
+
is allowed through (returns True). If any name is found, the record is
|
|
55
|
+
filtered out (returns False).
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
record : logging.LogRecord
|
|
60
|
+
The log record to be filtered.
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
bool
|
|
65
|
+
True if the record should be allowed through (not filtered),
|
|
66
|
+
False if the record should be filtered out.
|
|
67
|
+
|
|
68
|
+
Notes
|
|
69
|
+
-----
|
|
70
|
+
The filtering is performed using substring matching. If `self.NAMES` is
|
|
71
|
+
empty, all records will be allowed through.
|
|
72
|
+
|
|
73
|
+
Examples
|
|
74
|
+
--------
|
|
75
|
+
>>> class MyFilter:
|
|
76
|
+
... NAMES = ['DEBUG', 'INFO']
|
|
77
|
+
... def filter(self, record):
|
|
78
|
+
... if not any([n in record.name for n in self.NAMES]):
|
|
79
|
+
... return True
|
|
80
|
+
... return False
|
|
81
|
+
...
|
|
82
|
+
>>> filter_instance = MyFilter()
|
|
83
|
+
>>> record = logging.LogRecord('DEBUG', 10, 'file.py', 1, 'message', None, None)
|
|
84
|
+
>>> filter_instance.filter(record)
|
|
85
|
+
False
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
89
|
+
"""
|
|
90
|
+
Format a log record, extracting message2 and message3 from record.args.
|
|
91
|
+
|
|
92
|
+
This method extends the standard logging formatter by checking if the log record's
|
|
93
|
+
args attribute is a dictionary. If so, it extracts "message2" and "message3"
|
|
94
|
+
values from the dictionary and assigns them as attributes to the record for
|
|
95
|
+
use in log formatting.
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
record : logging.LogRecord
|
|
100
|
+
The log record to be formatted. The record's args attribute is checked
|
|
101
|
+
to determine if message2 and message3 should be extracted.
|
|
102
|
+
|
|
103
|
+
Returns
|
|
104
|
+
-------
|
|
105
|
+
str
|
|
106
|
+
The formatted log message string.
|
|
107
|
+
|
|
108
|
+
Notes
|
|
109
|
+
-----
|
|
110
|
+
This method modifies the record in-place by adding message2 and message3
|
|
111
|
+
attributes when record.args is a dictionary. If record.args is not a
|
|
112
|
+
dictionary, these attributes are set to None.
|
|
113
|
+
|
|
114
|
+
Examples
|
|
115
|
+
--------
|
|
116
|
+
>>> import logging
|
|
117
|
+
>>> formatter = MyFormatter()
|
|
118
|
+
>>> record = logging.LogRecord('name', 1, 'file', 1, 'message', {'message2': 'extra', 'message3': 'info'}, None)
|
|
119
|
+
>>> formatted = formatter.format(record)
|
|
120
|
+
>>> print(formatted)
|
|
121
|
+
'message'
|
|
122
|
+
"""
|
|
123
|
+
if isinstance(record.args, dict):
|
|
124
|
+
record.message2 = record.args.get("message2", None)
|
|
125
|
+
record.message3 = record.args.get("message3", None)
|
|
126
|
+
else:
|
|
127
|
+
record.message2 = None
|
|
128
|
+
record.message3 = None
|
|
129
|
+
return super().format(record)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def setup_logger(
|
|
133
|
+
logger_filename: str,
|
|
134
|
+
timing_filename: str,
|
|
135
|
+
memory_filename: Optional[str] = None,
|
|
136
|
+
error_filename: Optional[str] = None,
|
|
137
|
+
isverbose: bool = False,
|
|
138
|
+
debug: bool = False,
|
|
139
|
+
) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Set up a set of loggers for handling generic, timing, memory, and error logging.
|
|
142
|
+
|
|
143
|
+
This function configures multiple loggers with custom handlers and formatters,
|
|
144
|
+
writing output to specified files. It also sets up a custom "VERBOSE" logging level
|
|
145
|
+
and supports optional console output filtering.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
logger_filename : str
|
|
150
|
+
Output file for generic logging information.
|
|
151
|
+
timing_filename : str
|
|
152
|
+
Output file for timing-related information.
|
|
153
|
+
memory_filename : str, optional
|
|
154
|
+
Output file for memory usage-related information. If not provided, memory logging is disabled.
|
|
155
|
+
error_filename : str, optional
|
|
156
|
+
Output file for error-related information. If not provided, error logging is disabled.
|
|
157
|
+
isverbose : bool, optional
|
|
158
|
+
Sets the target logging level to VERBOSE (a custom level between INFO and DEBUG).
|
|
159
|
+
Is overridden by ``debug``, if ``debug = True``. Default is False.
|
|
160
|
+
debug : bool, optional
|
|
161
|
+
Sets the target logging level to DEBUG. Default is False.
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
None
|
|
166
|
+
This function does not return any value.
|
|
167
|
+
|
|
168
|
+
Notes
|
|
169
|
+
-----
|
|
170
|
+
- Existing log files from previous runs are automatically removed.
|
|
171
|
+
- A custom logging level "VERBOSE" (level 15) is added, placed between INFO and DEBUG.
|
|
172
|
+
- Console output is filtered using a `ContextFilter` to avoid duplicate messages.
|
|
173
|
+
- Loggers for timing, memory, and error are configured only if their respective filenames are provided.
|
|
174
|
+
|
|
175
|
+
Examples
|
|
176
|
+
--------
|
|
177
|
+
>>> setup_logger(
|
|
178
|
+
... logger_filename="app.log",
|
|
179
|
+
... timing_filename="timing.log",
|
|
180
|
+
... memory_filename="memory.log",
|
|
181
|
+
... error_filename="error.log",
|
|
182
|
+
... isverbose=True,
|
|
183
|
+
... debug=False
|
|
184
|
+
... )
|
|
185
|
+
"""
|
|
186
|
+
# Clean up existing files from previous runs
|
|
187
|
+
for fname in [logger_filename, timing_filename, memory_filename, error_filename]:
|
|
188
|
+
if fname is not None:
|
|
189
|
+
if os.path.isfile(fname):
|
|
190
|
+
LGR.info(f"Removing existing file: {fname}")
|
|
191
|
+
os.remove(fname)
|
|
192
|
+
|
|
193
|
+
# Create a new "verbose" logging level
|
|
194
|
+
VERBOSE_LEVEL = 15 # between info and debug
|
|
195
|
+
logging.addLevelName(VERBOSE_LEVEL, "VERBOSE")
|
|
196
|
+
|
|
197
|
+
def verbose(self: logging.Logger, message: str, *args: Any, **kwargs: Any) -> None:
|
|
198
|
+
"""
|
|
199
|
+
Log a message with VERBOSE_LEVEL if it is enabled.
|
|
200
|
+
|
|
201
|
+
This method provides a verbose logging capability that only executes
|
|
202
|
+
when the logger's verbosity level is set to include VERBOSE_LEVEL.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
self : logging.Logger
|
|
207
|
+
The logger instance calling this method.
|
|
208
|
+
message : str
|
|
209
|
+
The message to be logged. This message may contain placeholders
|
|
210
|
+
for additional arguments.
|
|
211
|
+
*args : Any
|
|
212
|
+
Additional arguments to be formatted into the message.
|
|
213
|
+
**kwargs : Any
|
|
214
|
+
Additional keyword arguments to be passed to the logging system.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
None
|
|
219
|
+
This method does not return any value.
|
|
220
|
+
|
|
221
|
+
Notes
|
|
222
|
+
-----
|
|
223
|
+
This method is a convenience wrapper around the standard logging system
|
|
224
|
+
that only executes when VERBOSE_LEVEL is enabled. It allows for
|
|
225
|
+
conditional verbose logging without requiring explicit checks in the
|
|
226
|
+
calling code.
|
|
227
|
+
|
|
228
|
+
Examples
|
|
229
|
+
--------
|
|
230
|
+
>>> import logging
|
|
231
|
+
>>> logger = logging.getLogger(__name__)
|
|
232
|
+
>>> logger.setLevel(logging.DEBUG)
|
|
233
|
+
>>> logger.verbose("Processing item %s", item_name)
|
|
234
|
+
"""
|
|
235
|
+
if self.isEnabledFor(VERBOSE_LEVEL):
|
|
236
|
+
self._log(VERBOSE_LEVEL, message, args, **kwargs)
|
|
237
|
+
|
|
238
|
+
logging.Logger.verbose = verbose
|
|
239
|
+
|
|
240
|
+
# Set logging level for main logger
|
|
241
|
+
if debug:
|
|
242
|
+
logging.root.setLevel(logging.DEBUG)
|
|
243
|
+
elif isverbose:
|
|
244
|
+
logging.root.setLevel(VERBOSE_LEVEL)
|
|
245
|
+
else:
|
|
246
|
+
logging.root.setLevel(logging.INFO)
|
|
247
|
+
|
|
248
|
+
# Set up handler for main logger's output file
|
|
249
|
+
log_formatter = logging.Formatter("%(message)s")
|
|
250
|
+
log_handler = logging.FileHandler(logger_filename)
|
|
251
|
+
log_handler.setFormatter(log_formatter)
|
|
252
|
+
|
|
253
|
+
# A handler for the console
|
|
254
|
+
stream_handler = logging.StreamHandler()
|
|
255
|
+
stream_handler.setFormatter(log_formatter)
|
|
256
|
+
|
|
257
|
+
# Removing handlers after basicConfig doesn't work, so we use filters
|
|
258
|
+
# for the relevant handlers themselves.
|
|
259
|
+
log_handler.addFilter(ContextFilter())
|
|
260
|
+
stream_handler.addFilter(ContextFilter())
|
|
261
|
+
|
|
262
|
+
LGR.addHandler(log_handler)
|
|
263
|
+
LGR.addHandler(stream_handler)
|
|
264
|
+
LGR.propagate = False # do not print to console, except for messages for StreamHandler
|
|
265
|
+
|
|
266
|
+
# A timing logger
|
|
267
|
+
timing_formatter = TimingFormatter(
|
|
268
|
+
"%(asctime)s.%(msecs)03d\t%(message)s\t%(message2)s\t%(message3)s",
|
|
269
|
+
datefmt="%Y%m%dT%H%M%S",
|
|
270
|
+
)
|
|
271
|
+
timing_handler = logging.FileHandler(timing_filename)
|
|
272
|
+
timing_handler.setFormatter(timing_formatter)
|
|
273
|
+
TimingLGR.setLevel(logging.INFO)
|
|
274
|
+
TimingLGR.addHandler(timing_handler)
|
|
275
|
+
TimingLGR.propagate = False # do not print to console
|
|
276
|
+
|
|
277
|
+
# A memory logger
|
|
278
|
+
if memory_filename is not None:
|
|
279
|
+
memory_formatter = logging.Formatter("%(message)s")
|
|
280
|
+
memory_handler = logging.FileHandler(memory_filename)
|
|
281
|
+
memory_handler.setFormatter(memory_formatter)
|
|
282
|
+
MemoryLGR.setLevel(logging.INFO)
|
|
283
|
+
MemoryLGR.addHandler(memory_handler)
|
|
284
|
+
MemoryLGR.propagate = False # do not print to console
|
|
285
|
+
|
|
286
|
+
# An error logger
|
|
287
|
+
if error_filename is not None:
|
|
288
|
+
error_formatter = logging.Formatter("%(message)s")
|
|
289
|
+
error_handler = logging.FileHandler(error_filename)
|
|
290
|
+
error_handler.setFormatter(error_formatter)
|
|
291
|
+
ErrorLGR.setLevel(logging.INFO)
|
|
292
|
+
ErrorLGR.addHandler(error_handler)
|
|
293
|
+
ErrorLGR.propagate = False # do not print to console
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
#
|
|
4
|
-
# Copyright 2016-
|
|
4
|
+
# Copyright 2016-2025 Blaise Frederick
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -17,14 +17,46 @@
|
|
|
17
17
|
#
|
|
18
18
|
#
|
|
19
19
|
import argparse
|
|
20
|
+
from argparse import Namespace
|
|
21
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
20
22
|
|
|
21
23
|
import numpy as np
|
|
24
|
+
from numpy.typing import NDArray
|
|
22
25
|
|
|
23
26
|
import rapidtide.filter as tide_filt
|
|
24
27
|
import rapidtide.io as tide_io
|
|
25
28
|
|
|
26
29
|
|
|
27
|
-
def _get_parser():
|
|
30
|
+
def _get_parser() -> Any:
|
|
31
|
+
"""
|
|
32
|
+
Transform a nifti fmri file into a temporal variability file.
|
|
33
|
+
|
|
34
|
+
This function creates and configures an argument parser for the variabilityizer tool
|
|
35
|
+
that processes fMRI data to generate temporal variability maps.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
argparse.ArgumentParser
|
|
40
|
+
Configured argument parser with the following arguments:
|
|
41
|
+
- inputfilename : str
|
|
42
|
+
The name of the input nifti file
|
|
43
|
+
- outputfilename : str
|
|
44
|
+
The name of the output nifti file
|
|
45
|
+
- windowlength : float
|
|
46
|
+
The size of the temporal window in seconds
|
|
47
|
+
|
|
48
|
+
Notes
|
|
49
|
+
-----
|
|
50
|
+
The parser is configured with:
|
|
51
|
+
- Program name: "variabilityizer"
|
|
52
|
+
- Description: "Transform a nifti fmri file into a temporal variability file."
|
|
53
|
+
- allow_abbrev: False
|
|
54
|
+
|
|
55
|
+
Examples
|
|
56
|
+
--------
|
|
57
|
+
>>> parser = _get_parser()
|
|
58
|
+
>>> args = parser.parse_args(['input.nii', 'output.nii', '10.0'])
|
|
59
|
+
"""
|
|
28
60
|
# get the command line parameters
|
|
29
61
|
parser = argparse.ArgumentParser(
|
|
30
62
|
prog="variabilityizer",
|
|
@@ -41,10 +73,49 @@ def _get_parser():
|
|
|
41
73
|
return parser
|
|
42
74
|
|
|
43
75
|
|
|
44
|
-
def cvttovariability(windowhalfwidth, data):
|
|
76
|
+
def cvttovariability(windowhalfwidth: Any, data: Any) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Convert data to variability by computing rolling standard deviations with symmetric windows.
|
|
79
|
+
|
|
80
|
+
This function calculates the variability of input data by computing rolling standard
|
|
81
|
+
deviations using symmetric windows around each data point. The window size is determined
|
|
82
|
+
by the windowhalfwidth parameter, and the function handles edge cases by computing
|
|
83
|
+
standard deviations from the beginning and end of the array to the window boundary.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
windowhalfwidth : Any
|
|
88
|
+
Half the width of the sliding window used for computing standard deviations.
|
|
89
|
+
Should be a positive integer representing the number of elements on each side
|
|
90
|
+
of the current element to include in the standard deviation calculation.
|
|
91
|
+
data : Any
|
|
92
|
+
Input data array for which variability is to be computed. Should be a numeric array-like object.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
None
|
|
97
|
+
The function currently returns None but appears to be intended to return the computed
|
|
98
|
+
variability values (thestd + themean) as shown in the implementation.
|
|
99
|
+
|
|
100
|
+
Notes
|
|
101
|
+
-----
|
|
102
|
+
- The function only processes data when the mean is greater than zero
|
|
103
|
+
- For data with zero or negative mean, the original data is returned unchanged
|
|
104
|
+
- Edge cases are handled by computing standard deviations from the beginning and end
|
|
105
|
+
of the array to the window boundary
|
|
106
|
+
- The function uses symmetric windowing around each data point for consistency
|
|
107
|
+
|
|
108
|
+
Examples
|
|
109
|
+
--------
|
|
110
|
+
>>> import numpy as np
|
|
111
|
+
>>> data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
112
|
+
>>> result = cvttovariability(2, data)
|
|
113
|
+
>>> print(result)
|
|
114
|
+
[2.58253175 2.58253175 3.53553391 3.53553391 3.53553391 3.53553391 3.53553391 2.58253175 2.58253175]
|
|
115
|
+
"""
|
|
45
116
|
themean = np.mean(data)
|
|
46
117
|
if themean > 0.0:
|
|
47
|
-
thestd = data
|
|
118
|
+
thestd = np.zeros_like(data)
|
|
48
119
|
for i in range(windowhalfwidth):
|
|
49
120
|
thestd[i] = np.std(data[: i + windowhalfwidth + 1])
|
|
50
121
|
thestd[-(i + 1)] = np.std(data[-(i + 1) - windowhalfwidth :])
|
|
@@ -55,7 +126,49 @@ def cvttovariability(windowhalfwidth, data):
|
|
|
55
126
|
return data
|
|
56
127
|
|
|
57
128
|
|
|
58
|
-
def variabilityizer(args):
|
|
129
|
+
def variabilityizer(args: Any) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Compute temporal variability maps from fMRI data using a sliding window approach.
|
|
132
|
+
|
|
133
|
+
This function calculates the coefficient of variation (CV) for each voxel's time series
|
|
134
|
+
within a specified window size, producing a variability map for the entire 3D volume.
|
|
135
|
+
The result is saved as a NIfTI file.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
args : argparse.Namespace
|
|
140
|
+
An object containing the following attributes:
|
|
141
|
+
- inputfilename : str
|
|
142
|
+
Path to the input NIfTI file containing fMRI data.
|
|
143
|
+
- outputfilename : str
|
|
144
|
+
Path to the output NIfTI file where variability maps will be saved.
|
|
145
|
+
- windowlength : float
|
|
146
|
+
Length of the sliding window in seconds.
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
None
|
|
151
|
+
The function does not return any value but saves the computed variability maps
|
|
152
|
+
to the specified output NIfTI file.
|
|
153
|
+
|
|
154
|
+
Notes
|
|
155
|
+
-----
|
|
156
|
+
- The function assumes the input data is in NIfTI format and contains time series
|
|
157
|
+
data in the fourth dimension.
|
|
158
|
+
- The window size is rounded to the nearest odd number of TRs to ensure symmetry.
|
|
159
|
+
- The coefficient of variation is computed using the `cvttovariability` helper function.
|
|
160
|
+
- Time points are processed slice-by-slice for memory efficiency.
|
|
161
|
+
|
|
162
|
+
Examples
|
|
163
|
+
--------
|
|
164
|
+
>>> import argparse
|
|
165
|
+
>>> args = argparse.Namespace(
|
|
166
|
+
... inputfilename='fmri_data.nii',
|
|
167
|
+
... outputfilename='variability_map.nii',
|
|
168
|
+
... windowlength=10.0
|
|
169
|
+
... )
|
|
170
|
+
>>> variabilityizer(args)
|
|
171
|
+
"""
|
|
59
172
|
# get the input TR
|
|
60
173
|
inputtr_fromfile, numinputtrs = tide_io.fmritimeinfo(args.inputfilename)
|
|
61
174
|
print("input data: ", numinputtrs, " timepoints, tr = ", inputtr_fromfile)
|