rapidtide 3.0.1__py3-none-any.whl → 3.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. rapidtide/DerivativeDelay.py +0 -4
  2. rapidtide/calcsimfunc.py +3 -0
  3. rapidtide/correlate.py +18 -1
  4. rapidtide/data/examples/src/testfmri +7 -4
  5. rapidtide/data/examples/src/testretro +15 -13
  6. rapidtide/happy_supportfuncs.py +70 -234
  7. rapidtide/helper_classes.py +4 -4
  8. rapidtide/io.py +21 -23
  9. rapidtide/maskutil.py +144 -0
  10. rapidtide/refinedelay.py +4 -7
  11. rapidtide/tests/cleanposttest +0 -1
  12. rapidtide/tests/test_cleanregressor.py +185 -0
  13. rapidtide/tests/test_fullrunrapidtide_v1.py +4 -0
  14. rapidtide/tests/test_fullrunrapidtide_v3.py +10 -0
  15. rapidtide/tests/test_fullrunrapidtide_v6.py +0 -1
  16. rapidtide/tests/test_fullrunrapidtide_v7.py +114 -0
  17. rapidtide/tests/test_io.py +58 -13
  18. rapidtide/tests/test_refinedelay.py +0 -3
  19. rapidtide/voxelData.py +126 -14
  20. rapidtide/workflows/cleanregressor.py +43 -6
  21. rapidtide/workflows/delayestimation.py +8 -13
  22. rapidtide/workflows/delayvar.py +11 -13
  23. rapidtide/workflows/happy.py +72 -179
  24. rapidtide/workflows/rapidtide.py +335 -329
  25. rapidtide/workflows/rapidtide_parser.py +115 -66
  26. rapidtide/workflows/regressfrommaps.py +12 -7
  27. rapidtide/workflows/retroregress.py +533 -337
  28. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/METADATA +1 -1
  29. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/RECORD +33 -31
  30. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/WHEEL +1 -1
  31. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/entry_points.txt +0 -0
  32. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/licenses/LICENSE +0 -0
  33. {rapidtide-3.0.1.dist-info → rapidtide-3.0.3.dist-info}/top_level.txt +0 -0
@@ -28,12 +28,14 @@ import numpy as np
28
28
 
29
29
  import rapidtide.filter as tide_filt
30
30
  import rapidtide.io as tide_io
31
+ import rapidtide.maskutil as tide_mask
31
32
  import rapidtide.miscmath as tide_math
32
33
  import rapidtide.multiproc as tide_multiproc
33
34
  import rapidtide.refinedelay as tide_refinedelay
34
35
  import rapidtide.resample as tide_resample
35
36
  import rapidtide.stats as tide_stats
36
37
  import rapidtide.util as tide_util
38
+ import rapidtide.voxelData as tide_voxelData
37
39
  import rapidtide.workflows.parser_funcs as pf
38
40
  import rapidtide.workflows.regressfrommaps as tide_regressfrommaps
39
41
 
@@ -127,13 +129,14 @@ def _get_parser():
127
129
  dest="outputlevel",
128
130
  action="store",
129
131
  type=str,
130
- choices=["min", "less", "normal", "more", "max"],
132
+ choices=["min", "less", "normal", "more", "max", "onlyregressors"],
131
133
  help=(
132
134
  "The level of file output produced. 'min' produces only absolutely essential files, 'less' adds in "
133
135
  "the sLFO filtered data (rather than just filter efficacy metrics), 'normal' saves what you "
134
136
  "would typically want around for interactive data exploration, "
135
137
  "'more' adds files that are sometimes useful, and 'max' outputs anything you might possibly want. "
136
- "Selecting 'max' will produce ~3x your input datafile size as output. "
138
+ "Selecting 'max' will produce ~3x your input datafile size as output. 'onlyregressors' will ONLY generate the "
139
+ "voxelwise timecourses to filter and save them without actually running the filter. "
137
140
  f'Default is "normal".'
138
141
  ),
139
142
  default="normal",
@@ -271,28 +274,39 @@ def retroregress(args):
271
274
  args.savenormalsLFOfiltfiles = False
272
275
  args.savemovingsignal = False
273
276
  args.saveallsLFOfiltfiles = False
277
+ args.saveEVsandquit = False
274
278
  elif args.outputlevel == "less":
275
279
  args.saveminimumsLFOfiltfiles = True
276
280
  args.savenormalsLFOfiltfiles = False
277
281
  args.savemovingsignal = False
278
282
  args.saveallsLFOfiltfiles = False
283
+ args.saveEVsandquit = False
279
284
  elif args.outputlevel == "normal":
280
285
  args.saveminimumsLFOfiltfiles = True
281
286
  args.savenormalsLFOfiltfiles = True
282
287
  args.savemovingsignal = False
283
288
  args.saveallsLFOfiltfiles = False
289
+ args.saveEVsandquit = False
284
290
  elif args.outputlevel == "more":
285
291
  args.saveminimumsLFOfiltfiles = True
286
292
  args.savenormalsLFOfiltfiles = True
287
293
  args.savemovingsignal = True
288
294
  args.saveallsLFOfiltfiles = False
295
+ args.saveEVsandquit = False
289
296
  elif args.outputlevel == "max":
290
297
  args.saveminimumsLFOfiltfiles = True
291
298
  args.savenormalsLFOfiltfiles = True
292
299
  args.savemovingsignal = True
293
300
  args.saveallsLFOfiltfiles = True
301
+ args.saveEVsandquit = False
302
+ elif args.outputlevel == "onlyregressors":
303
+ args.saveminimumsLFOfiltfiles = False
304
+ args.savenormalsLFOfiltfiles = False
305
+ args.savemovingsignal = False
306
+ args.saveallsLFOfiltfiles = False
307
+ args.saveEVsandquit = True
294
308
  else:
295
- print(f"illegal output level {args['outputlevel']}")
309
+ print(f"illegal output level {args.outputlevel}")
296
310
  sys.exit()
297
311
 
298
312
  # save the raw and formatted command lines
@@ -370,19 +384,19 @@ def retroregress(args):
370
384
 
371
385
  # read the fmri input files
372
386
  print("reading fmrifile")
373
- fmri_input, fmri_data, fmri_header, fmri_dims, fmri_sizes = tide_io.readfromnifti(
374
- args.fmrifile
375
- )
387
+ theinputdata = tide_voxelData.VoxelData(args.fmrifile)
388
+ xsize, ysize, numslices, timepoints = theinputdata.getdims()
389
+ xdim, ydim, slicethickness, fmritr = theinputdata.getsizes()
390
+ fmri_header = theinputdata.copyheader()
391
+ fmri_data = theinputdata.byvol()
392
+ numspatiallocs = theinputdata.numspatiallocs
376
393
 
377
394
  # create the canary file
378
395
  Path(f"{outputname}_RETROISRUNNING.txt").touch()
379
396
 
380
397
  if args.debug:
381
398
  print(f"{fmri_data.shape=}")
382
- xdim, ydim, slicedim, fmritr = tide_io.parseniftisizes(fmri_sizes)
383
- xsize, ysize, numslices, timepoints = tide_io.parseniftidims(fmri_dims)
384
- numspatiallocs = int(xsize) * int(ysize) * int(numslices)
385
- fmri_data_spacebytime = fmri_data.reshape((numspatiallocs, timepoints))
399
+ fmri_data_spacebytime = theinputdata.byvoxel()
386
400
  if args.debug:
387
401
  print(f"{fmri_data_spacebytime.shape=}")
388
402
 
@@ -584,9 +598,7 @@ def retroregress(args):
584
598
 
585
599
  if args.debug:
586
600
  # dump the fmri input file going to glm
587
- theheader = copy.deepcopy(fmri_header)
588
- theheader["dim"][4] = validtimepoints
589
- theheader["pixdim"][4] = fmritr
601
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
590
602
 
591
603
  maplist = [
592
604
  (
@@ -604,8 +616,7 @@ def retroregress(args):
604
616
  (xsize, ysize, numslices, validtimepoints),
605
617
  theheader,
606
618
  bidsbasedict,
607
- textio=therunoptions["textio"],
608
- fileiscifti=False,
619
+ filetype=theinputdata.filetype,
609
620
  rt_floattype=rt_floattype,
610
621
  cifti_hdr=None,
611
622
  )
@@ -618,7 +629,7 @@ def retroregress(args):
618
629
 
619
630
  if args.delayoffsetgausssigma < 0.0:
620
631
  # set gausssigma automatically
621
- args.delayoffsetgausssigma = np.mean([xdim, ydim, slicedim]) / 2.0
632
+ args.delayoffsetgausssigma = np.mean([xdim, ydim, slicethickness]) / 2.0
622
633
 
623
634
  TimingLGR.info("Refinement calibration start")
624
635
  regressderivratios, regressrvalues = tide_refinedelay.getderivratios(
@@ -652,11 +663,9 @@ def retroregress(args):
652
663
  regressderivratios,
653
664
  (xsize, ysize, numslices),
654
665
  validvoxels,
655
- (xdim, ydim, slicedim),
666
+ (xdim, ydim, slicethickness),
656
667
  gausssigma=args.delayoffsetgausssigma,
657
668
  patchthresh=args.delaypatchthresh,
658
- fileiscifti=False,
659
- textio=False,
660
669
  rt_floattype=rt_floattype,
661
670
  debug=args.debug,
662
671
  )
@@ -704,11 +713,9 @@ def retroregress(args):
704
713
  regressderivratios[i, :],
705
714
  (xsize, ysize, numslices),
706
715
  validvoxels,
707
- (xdim, ydim, slicedim),
716
+ (xdim, ydim, slicethickness),
708
717
  gausssigma=args.delayoffsetgausssigma,
709
718
  patchthresh=args.delaypatchthresh,
710
- fileiscifti=False,
711
- textio=False,
712
719
  rt_floattype=rt_floattype,
713
720
  debug=args.debug,
714
721
  )
@@ -725,16 +732,17 @@ def retroregress(args):
725
732
  )
726
733
  refinedvoxelstoreport = filteredregressderivratios.shape[1]
727
734
 
728
- namesuffix = "_desc-delayoffset_hist"
729
- tide_stats.makeandsavehistogram(
730
- delayoffset,
731
- therunoptions["histlen"],
732
- 1,
733
- outputname + namesuffix,
734
- displaytitle="Histogram of delay offsets calculated from GLM",
735
- dictvarname="delayoffsethist",
736
- thedict=None,
737
- )
735
+ if not args.saveEVsandquit:
736
+ namesuffix = "_desc-delayoffset_hist"
737
+ tide_stats.makeandsavehistogram(
738
+ delayoffset,
739
+ therunoptions["histlen"],
740
+ 1,
741
+ outputname + namesuffix,
742
+ displaytitle="Histogram of delay offsets calculated from GLM",
743
+ dictvarname="delayoffsethist",
744
+ thedict=None,
745
+ )
738
746
  lagtimesrefined_valid = lagtimes_valid + delayoffset
739
747
 
740
748
  TimingLGR.info(
@@ -782,248 +790,546 @@ def retroregress(args):
782
790
  nprocs_regressionfilt=args.nprocs,
783
791
  regressderivs=args.regressderivs,
784
792
  showprogressbar=args.showprogressbar,
793
+ saveEVsandquit=args.saveEVsandquit,
785
794
  debug=args.debug,
786
795
  )
787
- print(f"filtered {voxelsprocessed_regressionfilt} voxels")
788
- TimingLGR.info(
789
- "sLFO filtering done",
790
- {
791
- "message2": voxelsprocessed_regressionfilt,
792
- "message3": "voxels",
793
- },
794
- )
795
- # finalrawvariance = tide_math.imagevariance(filtereddata, None, 1.0 / fmritr)
796
- finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
797
796
 
798
- divlocs = np.where(finalvariance > 0.0)
799
- varchange = initialvariance * 0.0
800
- varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
797
+ if not args.saveEVsandquit:
798
+ print(f"filtered {voxelsprocessed_regressionfilt} voxels")
799
+ TimingLGR.info(
800
+ "sLFO filtering done",
801
+ {
802
+ "message2": voxelsprocessed_regressionfilt,
803
+ "message3": "voxels",
804
+ },
805
+ )
806
+ finalvariance = tide_math.imagevariance(filtereddata, theprefilter, 1.0 / fmritr)
807
+
808
+ divlocs = np.where(finalvariance > 0.0)
809
+ varchange = initialvariance * 0.0
810
+ varchange[divlocs] = 100.0 * (finalvariance[divlocs] / initialvariance[divlocs] - 1.0)
811
+
812
+ # save regional timecourses if masks are defined
813
+ # read in the anatomic masks
814
+ anatomiclist = [
815
+ ["brainmaskincludename", "brainmaskincludevals", "brainmask"],
816
+ ["graymatterincludename", "graymatterincludevals", "graymattermask"],
817
+ ["whitematterincludename", "whitematterincludevals", "whitemattermask"],
818
+ ["csfincludename", "csfincludevals", "csfmask"],
819
+ ]
820
+ anatomicmasks = []
821
+ for thisanatomic in anatomiclist:
822
+ if therunoptions[thisanatomic[0]] is not None:
823
+ anatomicmasks.append(
824
+ tide_mask.readamask(
825
+ therunoptions[thisanatomic[0]],
826
+ theinputdata.nim_hdr,
827
+ xsize,
828
+ istext=(theinputdata.filetype == "text"),
829
+ valslist=therunoptions[thisanatomic[1]],
830
+ maskname=thisanatomic[2],
831
+ tolerance=therunoptions["spatialtolerance"],
832
+ debug=args.focaldebug,
833
+ )
834
+ )
835
+ anatomicmasks[-1] = np.uint16(np.where(anatomicmasks[-1] > 0.1, 1, 0))
836
+ else:
837
+ anatomicmasks.append(None)
838
+ brainmask = anatomicmasks[0]
839
+ graymask = anatomicmasks[1]
840
+ whitemask = anatomicmasks[2]
841
+ csfmask = anatomicmasks[3]
842
+
843
+ """if internalinitregressorincludemask is not None:
844
+ thisincludemask = internalinitregressorincludemask[validvoxels]
845
+ else:
846
+ thisincludemask = None
847
+ if internalinitregressorexcludemask is not None:
848
+ thisexcludemask = internalinitregressorexcludemask[validvoxels]
849
+ else:
850
+ thisexcludemask = None
801
851
 
802
- """divlocs = np.where(finalrawvariance > 0.0)
803
- rawvarchange = initialrawvariance * 0.0
804
- rawvarchange[divlocs] = 100.0 * (finalrawvariance[divlocs] / initialrawvariance[divlocs] - 1.0)"""
852
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
853
+ "initial regressor",
854
+ "startregressormask",
855
+ filtereddata,
856
+ thisincludemask,
857
+ 1.0 / fmritr,
858
+ outputname,
859
+ initfile=True,
860
+ excludemask=thisexcludemask,
861
+ filedesc="regionalpostfilter",
862
+ suffix="",
863
+ debug=args.debug,
864
+ )"""
865
+ # reformat the anatomic masks, if they exist
866
+ if brainmask is None:
867
+ invbrainmask = None
805
868
 
806
- # save outputs
807
- TimingLGR.info("Starting output save")
808
- theheader = copy.deepcopy(lagtimes_header)
809
- if mode == "glm":
810
- maplist = [
811
- (
812
- initialvariance,
813
- "lfofilterInbandVarianceBefore",
814
- "map",
815
- None,
816
- "Inband variance prior to filtering",
817
- ),
818
- (
819
- finalvariance,
820
- "lfofilterInbandVarianceAfter",
821
- "map",
822
- None,
823
- "Inband variance after filtering",
824
- ),
825
- (
826
- varchange,
827
- "lfofilterInbandVarianceChange",
828
- "map",
829
- "percent",
830
- "Change in inband variance after filtering, in percent",
831
- ),
832
- # (
833
- # initialrawvariance,
834
- # "lfofilterTotalVarianceBefore",
835
- # "map",
836
- # None,
837
- # "Total variance prior to filtering",
838
- # ),
839
- # (
840
- # finalrawvariance,
841
- # "lfofilterTotalVarianceAfter",
842
- # "map",
843
- # None,
844
- # "Total variance after filtering",
845
- # ),
846
- # (
847
- # rawvarchange,
848
- # "lfofilterTotalVarianceChange",
849
- # "map",
850
- # "percent",
851
- # "Change in total variance after filtering, in percent",
852
- # ),
853
- ]
854
- if args.saveminimumsLFOfiltfiles:
855
- maplist += [
869
+ internalbrainmask = None
870
+ internalinvbrainmask = None
871
+ else:
872
+ invbrainmask = 1 - brainmask
873
+ internalbrainmask = brainmask.reshape((numspatiallocs))
874
+ internalinvbrainmask = invbrainmask.reshape((numspatiallocs))
875
+ if graymask is None:
876
+ internalgraymask = None
877
+ else:
878
+ internalgraymask = graymask.reshape((numspatiallocs))
879
+ if whitemask is None:
880
+ internalwhitemask = None
881
+ else:
882
+ internalwhitemask = whitemask.reshape((numspatiallocs))
883
+ if csfmask is None:
884
+ internalcsfmask = None
885
+ else:
886
+ internalcsfmask = csfmask.reshape((numspatiallocs))
887
+ if brainmask is not None:
888
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
889
+ "whole brain",
890
+ "brain",
891
+ filtereddata,
892
+ internalbrainmask[validvoxels],
893
+ 1.0 / fmritr,
894
+ outputname,
895
+ filedesc="regionalpostfilter",
896
+ suffix="",
897
+ debug=args.debug,
898
+ )
899
+ if graymask is not None:
900
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
901
+ "gray matter",
902
+ "GM",
903
+ filtereddata,
904
+ internalgraymask[validvoxels],
905
+ 1.0 / fmritr,
906
+ outputname,
907
+ excludemask=internalinvbrainmask[validvoxels],
908
+ filedesc="regionalpostfilter",
909
+ suffix="",
910
+ debug=args.debug,
911
+ )
912
+ if whitemask is not None:
913
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
914
+ "white matter",
915
+ "WM",
916
+ filtereddata,
917
+ internalwhitemask[validvoxels],
918
+ 1.0 / fmritr,
919
+ outputname,
920
+ excludemask=internalinvbrainmask[validvoxels],
921
+ filedesc="regionalpostfilter",
922
+ suffix="",
923
+ debug=args.debug,
924
+ )
925
+ if csfmask is not None:
926
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
927
+ "CSF",
928
+ "CSF",
929
+ filtereddata,
930
+ internalcsfmask[validvoxels],
931
+ 1.0 / fmritr,
932
+ outputname,
933
+ excludemask=internalinvbrainmask[validvoxels],
934
+ filedesc="regionalpostfilter",
935
+ suffix="",
936
+ debug=args.debug,
937
+ )
938
+
939
+ # save outputs
940
+ TimingLGR.info("Starting output save")
941
+ theheader = copy.deepcopy(lagtimes_header)
942
+ if mode == "glm":
943
+ maplist = [
856
944
  (
857
- r2value,
858
- "lfofilterR2",
945
+ initialvariance,
946
+ "lfofilterInbandVarianceBefore",
859
947
  "map",
860
948
  None,
861
- "Squared R value of the GLM fit (proportion of variance explained)",
949
+ "Inband variance prior to filtering",
862
950
  ),
951
+ (
952
+ finalvariance,
953
+ "lfofilterInbandVarianceAfter",
954
+ "map",
955
+ None,
956
+ "Inband variance after filtering",
957
+ ),
958
+ (
959
+ varchange,
960
+ "lfofilterInbandVarianceChange",
961
+ "map",
962
+ "percent",
963
+ "Change in inband variance after filtering, in percent",
964
+ ),
965
+ # (
966
+ # initialrawvariance,
967
+ # "lfofilterTotalVarianceBefore",
968
+ # "map",
969
+ # None,
970
+ # "Total variance prior to filtering",
971
+ # ),
972
+ # (
973
+ # finalrawvariance,
974
+ # "lfofilterTotalVarianceAfter",
975
+ # "map",
976
+ # None,
977
+ # "Total variance after filtering",
978
+ # ),
979
+ # (
980
+ # rawvarchange,
981
+ # "lfofilterTotalVarianceChange",
982
+ # "map",
983
+ # "percent",
984
+ # "Change in total variance after filtering, in percent",
985
+ # ),
863
986
  ]
864
- if args.savenormalsLFOfiltfiles:
865
- maplist += [
866
- (rvalue, "lfofilterR", "map", None, "R value of the GLM fit"),
867
- (sLFOfitmean, "lfofilterMean", "map", None, "Intercept from GLM fit"),
868
- ]
869
- else:
870
- maplist = [
871
- (initialvariance, "lfofilterInbandVarianceBefore", "map", None),
872
- (finalvariance, "lfofilterInbandVarianceAfter", "map", None),
873
- (varchange, "CVRVariance", "map", None),
874
- ]
875
- if args.savenormalsLFOfiltfiles:
876
- maplist += [
877
- (rvalue, "CVRR", "map", None),
878
- (r2value, "CVRR2", "map", None),
879
- (fitcoeff, "CVR", "map", "percent"),
880
- ]
881
- bidsdict = bidsbasedict.copy()
882
-
883
- if args.debug or args.focaldebug:
884
- maplist += [
885
- (
886
- lagtimes_valid,
887
- "maxtimeREAD",
888
- "map",
889
- "second",
890
- "Lag time in seconds used for calculation",
891
- ),
892
- (corrmask_valid, "corrfitREAD", "mask", None, "Correlation mask used for calculation"),
893
- (procmask_valid, "processedREAD", "mask", None, "Processed mask used for calculation"),
894
- ]
895
- if args.savenormalsLFOfiltfiles:
896
- if args.regressderivs > 0 or args.refinedelay:
897
- maplist += [
898
- (fitcoeff[:, 0], "lfofilterCoeff", "map", None, "Fit coefficient"),
899
- (fitNorm[:, 0], "lfofilterNorm", "map", None, "Normalized fit coefficient"),
900
- ]
901
- for thederiv in range(1, args.regressderivs + 1):
987
+ if args.saveminimumsLFOfiltfiles:
902
988
  maplist += [
903
989
  (
904
- fitcoeff[:, thederiv],
905
- f"lfofilterCoeffDeriv{thederiv}",
990
+ r2value,
991
+ "lfofilterR2",
906
992
  "map",
907
993
  None,
908
- f"Fit coefficient for temporal derivative {thederiv}",
909
- ),
910
- (
911
- fitNorm[:, thederiv],
912
- f"lfofilterNormDeriv{thederiv}",
913
- "map",
914
- None,
915
- f"Normalized fit coefficient for temporal derivative {thederiv}",
994
+ "Squared R value of the GLM fit (proportion of variance explained)",
916
995
  ),
917
996
  ]
997
+ if args.savenormalsLFOfiltfiles:
998
+ maplist += [
999
+ (rvalue, "lfofilterR", "map", None, "R value of the GLM fit"),
1000
+ (sLFOfitmean, "lfofilterMean", "map", None, "Intercept from GLM fit"),
1001
+ ]
918
1002
  else:
1003
+ maplist = [
1004
+ (initialvariance, "lfofilterInbandVarianceBefore", "map", None),
1005
+ (finalvariance, "lfofilterInbandVarianceAfter", "map", None),
1006
+ (varchange, "CVRVariance", "map", None),
1007
+ ]
1008
+ if args.savenormalsLFOfiltfiles:
1009
+ maplist += [
1010
+ (rvalue, "CVRR", "map", None),
1011
+ (r2value, "CVRR2", "map", None),
1012
+ (fitcoeff, "CVR", "map", "percent"),
1013
+ ]
1014
+ bidsdict = bidsbasedict.copy()
1015
+
1016
+ if args.debug or args.focaldebug:
919
1017
  maplist += [
920
- (fitcoeff, "lfofilterCoeff", "map", None, "Fit coefficient"),
921
- (fitNorm, "lfofilterNorm", "map", None, "Normalized fit coefficient"),
1018
+ (
1019
+ lagtimes_valid,
1020
+ "maxtimeREAD",
1021
+ "map",
1022
+ "second",
1023
+ "Lag time in seconds used for calculation",
1024
+ ),
1025
+ (
1026
+ corrmask_valid,
1027
+ "corrfitREAD",
1028
+ "mask",
1029
+ None,
1030
+ "Correlation mask used for calculation",
1031
+ ),
1032
+ (
1033
+ procmask_valid,
1034
+ "processedREAD",
1035
+ "mask",
1036
+ None,
1037
+ "Processed mask used for calculation",
1038
+ ),
922
1039
  ]
1040
+ if args.savenormalsLFOfiltfiles:
1041
+ if args.regressderivs > 0 or args.refinedelay:
1042
+ maplist += [
1043
+ (fitcoeff[:, 0], "lfofilterCoeff", "map", None, "Fit coefficient"),
1044
+ (fitNorm[:, 0], "lfofilterNorm", "map", None, "Normalized fit coefficient"),
1045
+ ]
1046
+ for thederiv in range(1, args.regressderivs + 1):
1047
+ maplist += [
1048
+ (
1049
+ fitcoeff[:, thederiv],
1050
+ f"lfofilterCoeffDeriv{thederiv}",
1051
+ "map",
1052
+ None,
1053
+ f"Fit coefficient for temporal derivative {thederiv}",
1054
+ ),
1055
+ (
1056
+ fitNorm[:, thederiv],
1057
+ f"lfofilterNormDeriv{thederiv}",
1058
+ "map",
1059
+ None,
1060
+ f"Normalized fit coefficient for temporal derivative {thederiv}",
1061
+ ),
1062
+ ]
1063
+ else:
1064
+ maplist += [
1065
+ (fitcoeff, "lfofilterCoeff", "map", None, "Fit coefficient"),
1066
+ (fitNorm, "lfofilterNorm", "map", None, "Normalized fit coefficient"),
1067
+ ]
923
1068
 
924
- if args.refinedelay:
925
- if args.refineregressderivs > 1:
926
- for i in range(args.refineregressderivs):
1069
+ if args.refinedelay:
1070
+ if args.refineregressderivs > 1:
1071
+ for i in range(args.refineregressderivs):
1072
+ maplist += [
1073
+ (
1074
+ regressderivratios[i, :],
1075
+ f"regressderivratios_{i}",
1076
+ "map",
1077
+ None,
1078
+ f"Ratio of derivative {i+1} of delayed sLFO to the delayed sLFO",
1079
+ ),
1080
+ (
1081
+ medfiltregressderivratios[i, :],
1082
+ f"medfiltregressderivratios_{i}",
1083
+ "map",
1084
+ None,
1085
+ f"Median filtered version of the regressderivratios_{i} map",
1086
+ ),
1087
+ (
1088
+ filteredregressderivratios[i, :],
1089
+ f"filteredregressderivratios_{i}",
1090
+ "map",
1091
+ None,
1092
+ f"regressderivratios_{i}, with outliers patched using median filtered data",
1093
+ ),
1094
+ ]
1095
+ else:
927
1096
  maplist += [
928
1097
  (
929
- regressderivratios[i, :],
930
- f"regressderivratios_{i}",
1098
+ regressderivratios,
1099
+ "regressderivratios",
931
1100
  "map",
932
1101
  None,
933
- f"Ratio of derivative {i+1} of delayed sLFO to the delayed sLFO",
1102
+ "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
934
1103
  ),
935
1104
  (
936
- medfiltregressderivratios[i, :],
937
- f"medfiltregressderivratios_{i}",
1105
+ medfiltregressderivratios,
1106
+ "medfiltregressderivratios",
938
1107
  "map",
939
1108
  None,
940
- f"Median filtered version of the regressderivratios_{i} map",
1109
+ "Median filtered version of the regressderivratios map",
941
1110
  ),
942
1111
  (
943
- filteredregressderivratios[i, :],
944
- f"filteredregressderivratios_{i}",
1112
+ filteredregressderivratios,
1113
+ "filteredregressderivratios",
945
1114
  "map",
946
1115
  None,
947
- f"regressderivratios_{i}, with outliers patched using median filtered data",
1116
+ "regressderivratios, with outliers patched using median filtered data",
948
1117
  ),
949
1118
  ]
950
- else:
951
1119
  maplist += [
952
1120
  (
953
- regressderivratios,
954
- "regressderivratios",
1121
+ delayoffset,
1122
+ "delayoffset",
955
1123
  "map",
956
- None,
957
- "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
1124
+ "second",
1125
+ "Delay offset correction from delay refinement",
958
1126
  ),
959
1127
  (
960
- medfiltregressderivratios,
961
- "medfiltregressderivratios",
1128
+ lagtimesrefined_valid,
1129
+ "maxtimerefined",
962
1130
  "map",
963
- None,
964
- "Median filtered version of the regressderivratios map",
1131
+ "second",
1132
+ "Lag time in seconds, refined",
965
1133
  ),
1134
+ ]
1135
+
1136
+ # write the 3D maps
1137
+ tide_io.savemaplist(
1138
+ outputname,
1139
+ maplist,
1140
+ validvoxels,
1141
+ (xsize, ysize, numslices),
1142
+ theheader,
1143
+ bidsdict,
1144
+ debug=args.debug,
1145
+ )
1146
+
1147
+ # write the 4D maps
1148
+ theheader = theinputdata.copyheader()
1149
+ maplist = []
1150
+ if args.saveminimumsLFOfiltfiles:
1151
+ maplist = [
966
1152
  (
967
- filteredregressderivratios,
968
- "filteredregressderivratios",
969
- "map",
1153
+ filtereddata,
1154
+ "lfofilterCleaned",
1155
+ "bold",
970
1156
  None,
971
- "regressderivratios, with outliers patched using median filtered data",
1157
+ "fMRI data with sLFO signal filtered out",
972
1158
  ),
973
1159
  ]
974
- maplist += [
975
- (
976
- delayoffset,
977
- "delayoffset",
978
- "map",
979
- "second",
980
- "Delay offset correction from delay refinement",
981
- ),
1160
+ if args.savemovingsignal:
1161
+ maplist += [
1162
+ (
1163
+ movingsignal,
1164
+ "lfofilterRemoved",
1165
+ "bold",
1166
+ None,
1167
+ "sLFO signal filtered out of this voxel",
1168
+ )
1169
+ ]
1170
+
1171
+ if args.saveallsLFOfiltfiles:
1172
+ if args.regressderivs > 0:
1173
+ if args.debug:
1174
+ print("going down the multiple EV path")
1175
+ print(f"{regressorset[:, :, 0].shape=}")
1176
+ maplist += [
1177
+ (
1178
+ regressorset[:, :, 0],
1179
+ "lfofilterEV",
1180
+ "bold",
1181
+ None,
1182
+ "Shifted sLFO regressor to filter",
1183
+ ),
1184
+ ]
1185
+ for thederiv in range(1, args.regressderivs + 1):
1186
+ if args.debug:
1187
+ print(f"{regressorset[:, :, thederiv].shape=}")
1188
+ maplist += [
1189
+ (
1190
+ regressorset[:, :, thederiv],
1191
+ f"lfofilterEVDeriv{thederiv}",
1192
+ "bold",
1193
+ None,
1194
+ f"Time derivative {thederiv} of shifted sLFO regressor",
1195
+ ),
1196
+ ]
1197
+ else:
1198
+ if args.debug:
1199
+ print("going down the single EV path")
1200
+ maplist += [
1201
+ (
1202
+ regressorset,
1203
+ "lfofilterEV",
1204
+ "bold",
1205
+ None,
1206
+ "Shifted sLFO regressor to filter",
1207
+ ),
1208
+ ]
1209
+ if args.makepseudofile:
1210
+ print("reading mean image")
1211
+ meanfile = f"{args.datafileroot}_desc-mean_map.nii.gz"
982
1212
  (
983
- lagtimesrefined_valid,
984
- "maxtimerefined",
985
- "map",
986
- "second",
987
- "Lag time in seconds, refined",
988
- ),
989
- ]
1213
+ mean_input,
1214
+ mean,
1215
+ mean_header,
1216
+ mean_dims,
1217
+ mean_sizes,
1218
+ ) = tide_io.readfromnifti(meanfile)
1219
+ if not tide_io.checkspacematch(fmri_header, mean_header):
1220
+ raise ValueError("mean dimensions do not match fmri dimensions")
1221
+ if args.debug:
1222
+ print(f"{mean.shape=}")
1223
+ mean_spacebytime = mean.reshape((numspatiallocs))
1224
+ if args.debug:
1225
+ print(f"{mean_spacebytime.shape=}")
1226
+ pseudofile = mean_spacebytime[validvoxels, None] + movingsignal[:, :]
1227
+ maplist.append((pseudofile, "pseudofile", "bold", None, None))
1228
+ tide_io.savemaplist(
1229
+ outputname,
1230
+ maplist,
1231
+ validvoxels,
1232
+ (xsize, ysize, numslices, validtimepoints),
1233
+ theheader,
1234
+ bidsdict,
1235
+ debug=args.debug,
1236
+ )
1237
+ TimingLGR.info("Finishing output save")
990
1238
 
991
- # write the 3D maps
992
- tide_io.savemaplist(
993
- outputname,
994
- maplist,
995
- validvoxels,
996
- (xsize, ysize, numslices),
997
- theheader,
998
- bidsdict,
999
- debug=args.debug,
1000
- )
1239
+ if args.refinecorr:
1240
+ TimingLGR.info("Filtering for maxcorralt calculation start")
1241
+ for thevoxel in range(fmri_data_valid.shape[0]):
1242
+ fmri_data_valid[thevoxel, :] = theprefilter.apply(
1243
+ 1.0 / fmritr, fmri_data_valid[thevoxel, :]
1244
+ )
1245
+ TimingLGR.info("Filtering for maxcorralt calculation complete")
1246
+ TimingLGR.info("GLM for maxcorralt calculation start")
1247
+ voxelsprocessed_regressionfilt, regressorset, evset = (
1248
+ tide_regressfrommaps.regressfrommaps(
1249
+ fmri_data_valid,
1250
+ validvoxels,
1251
+ initial_fmri_x,
1252
+ lagstouse_valid,
1253
+ corrmask_valid,
1254
+ genlagtc,
1255
+ mode,
1256
+ outputname,
1257
+ oversamptr,
1258
+ sLFOfitmean,
1259
+ rvalue,
1260
+ r2value,
1261
+ fitNorm[:, : args.regressderivs + 1],
1262
+ fitcoeff[:, : args.regressderivs + 1],
1263
+ movingsignal,
1264
+ lagtc,
1265
+ filtereddata,
1266
+ LGR,
1267
+ TimingLGR,
1268
+ threshval,
1269
+ args.saveminimumsLFOfiltfiles,
1270
+ nprocs_makelaggedtcs=args.nprocs,
1271
+ nprocs_regressionfilt=args.nprocs,
1272
+ regressderivs=args.regressderivs,
1273
+ showprogressbar=args.showprogressbar,
1274
+ debug=args.debug,
1275
+ )
1276
+ )
1277
+ TimingLGR.info(
1278
+ "GLM for maxcorralt calculation done",
1279
+ {
1280
+ "message2": voxelsprocessed_regressionfilt,
1281
+ "message3": "voxels",
1282
+ },
1283
+ )
1001
1284
 
1002
- # write the 4D maps
1003
- theheader = copy.deepcopy(fmri_header)
1004
- maplist = []
1005
- if args.saveminimumsLFOfiltfiles:
1006
- maplist = [
1007
- (
1008
- filtereddata,
1009
- "lfofilterCleaned",
1010
- "bold",
1011
- None,
1012
- "fMRI data with sLFO signal filtered out",
1013
- ),
1014
- ]
1015
- if args.savemovingsignal:
1016
- maplist += [
1017
- (
1018
- movingsignal,
1019
- "lfofilterRemoved",
1020
- "bold",
1021
- None,
1022
- "sLFO signal filtered out of this voxel",
1285
+ maplist = [
1286
+ (
1287
+ rvalue,
1288
+ "maxcorralt",
1289
+ "map",
1290
+ None,
1291
+ "R value for the lfo component of the delayed regressor, with sign",
1292
+ ),
1293
+ ]
1294
+ theheader = copy.deepcopy(lagtimes_header)
1295
+ tide_io.savemaplist(
1296
+ outputname,
1297
+ maplist,
1298
+ validvoxels,
1299
+ (xsize, ysize, numslices),
1300
+ theheader,
1301
+ bidsdict,
1302
+ debug=args.debug,
1023
1303
  )
1024
- ]
1304
+ if args.debug:
1305
+ # dump the fmri input file going to glm
1306
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
1025
1307
 
1026
- if args.saveallsLFOfiltfiles:
1308
+ maplist = [
1309
+ (
1310
+ fmri_data_valid,
1311
+ "prefilteredinputdata",
1312
+ "bold",
1313
+ None,
1314
+ "fMRI data after temporal filtering",
1315
+ ),
1316
+ ]
1317
+ tide_io.savemaplist(
1318
+ outputname,
1319
+ maplist,
1320
+ validvoxels,
1321
+ (xsize, ysize, numslices, validtimepoints),
1322
+ theheader,
1323
+ bidsbasedict,
1324
+ filetype=theinputdata.filetype,
1325
+ rt_floattype=rt_floattype,
1326
+ cifti_hdr=None,
1327
+ )
1328
+ else:
1329
+ # We are terminating early because we only want the regressors
1330
+ # write the EVs
1331
+ theheader = theinputdata.copyheader()
1332
+ maplist = []
1027
1333
  if args.regressderivs > 0:
1028
1334
  if args.debug:
1029
1335
  print("going down the multiple EV path")
@@ -1061,128 +1367,18 @@ def retroregress(args):
1061
1367
  "Shifted sLFO regressor to filter",
1062
1368
  ),
1063
1369
  ]
1064
- if args.makepseudofile:
1065
- print("reading mean image")
1066
- meanfile = f"{args.datafileroot}_desc-mean_map.nii.gz"
1067
- (
1068
- mean_input,
1069
- mean,
1070
- mean_header,
1071
- mean_dims,
1072
- mean_sizes,
1073
- ) = tide_io.readfromnifti(meanfile)
1074
- if not tide_io.checkspacematch(fmri_header, mean_header):
1075
- raise ValueError("mean dimensions do not match fmri dimensions")
1076
- if args.debug:
1077
- print(f"{mean.shape=}")
1078
- mean_spacebytime = mean.reshape((numspatiallocs))
1079
- if args.debug:
1080
- print(f"{mean_spacebytime.shape=}")
1081
- pseudofile = mean_spacebytime[validvoxels, None] + movingsignal[:, :]
1082
- maplist.append((pseudofile, "pseudofile", "bold", None, None))
1083
- tide_io.savemaplist(
1084
- outputname,
1085
- maplist,
1086
- validvoxels,
1087
- (xsize, ysize, numslices, validtimepoints),
1088
- theheader,
1089
- bidsdict,
1090
- debug=args.debug,
1091
- )
1092
- TimingLGR.info("Finishing output save")
1093
-
1094
- if args.refinecorr:
1095
- TimingLGR.info("Filtering for maxcorralt calculation start")
1096
- for thevoxel in range(fmri_data_valid.shape[0]):
1097
- fmri_data_valid[thevoxel, :] = theprefilter.apply(
1098
- 1.0 / fmritr, fmri_data_valid[thevoxel, :]
1099
- )
1100
- TimingLGR.info("Filtering for maxcorralt calculation complete")
1101
- TimingLGR.info("GLM for maxcorralt calculation start")
1102
- voxelsprocessed_regressionfilt, regressorset, evset = tide_regressfrommaps.regressfrommaps(
1103
- fmri_data_valid,
1104
- validvoxels,
1105
- initial_fmri_x,
1106
- lagstouse_valid,
1107
- corrmask_valid,
1108
- genlagtc,
1109
- mode,
1110
- outputname,
1111
- oversamptr,
1112
- sLFOfitmean,
1113
- rvalue,
1114
- r2value,
1115
- fitNorm[:, : args.regressderivs + 1],
1116
- fitcoeff[:, : args.regressderivs + 1],
1117
- movingsignal,
1118
- lagtc,
1119
- filtereddata,
1120
- LGR,
1121
- TimingLGR,
1122
- threshval,
1123
- args.saveminimumsLFOfiltfiles,
1124
- nprocs_makelaggedtcs=args.nprocs,
1125
- nprocs_regressionfilt=args.nprocs,
1126
- regressderivs=args.regressderivs,
1127
- showprogressbar=args.showprogressbar,
1128
- debug=args.debug,
1129
- )
1130
- TimingLGR.info(
1131
- "GLM for maxcorralt calculation done",
1132
- {
1133
- "message2": voxelsprocessed_regressionfilt,
1134
- "message3": "voxels",
1135
- },
1136
- )
1137
-
1138
- maplist = [
1139
- (
1140
- rvalue,
1141
- "maxcorralt",
1142
- "map",
1143
- None,
1144
- "R value for the lfo component of the delayed regressor, with sign",
1145
- ),
1146
- ]
1147
- theheader = copy.deepcopy(lagtimes_header)
1370
+ bidsdict = bidsbasedict.copy()
1148
1371
  tide_io.savemaplist(
1149
1372
  outputname,
1150
1373
  maplist,
1151
1374
  validvoxels,
1152
- (xsize, ysize, numslices),
1375
+ (xsize, ysize, numslices, validtimepoints),
1153
1376
  theheader,
1154
1377
  bidsdict,
1155
1378
  debug=args.debug,
1156
1379
  )
1157
- if args.debug:
1158
- # dump the fmri input file going to glm
1159
- theheader = copy.deepcopy(fmri_header)
1160
- theheader["dim"][4] = validtimepoints
1161
- theheader["pixdim"][4] = fmritr
1162
-
1163
- maplist = [
1164
- (
1165
- fmri_data_valid,
1166
- "prefilteredinputdata",
1167
- "bold",
1168
- None,
1169
- "fMRI data after temporal filtering",
1170
- ),
1171
- ]
1172
- tide_io.savemaplist(
1173
- outputname,
1174
- maplist,
1175
- validvoxels,
1176
- (xsize, ysize, numslices, validtimepoints),
1177
- theheader,
1178
- bidsbasedict,
1179
- textio=therunoptions["textio"],
1180
- fileiscifti=False,
1181
- rt_floattype=rt_floattype,
1182
- cifti_hdr=None,
1183
- )
1184
1380
 
1185
- # read the runoptions file
1381
+ # write the runoptions file
1186
1382
  print("writing runoptions")
1187
1383
  if args.refinedelay:
1188
1384
  therunoptions["retroregress_delayoffsetMAD"] = delayoffsetMAD