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
@@ -71,75 +71,6 @@ ErrorLGR = logging.getLogger("ERROR")
71
71
  TimingLGR = logging.getLogger("TIMING")
72
72
 
73
73
 
74
- def getglobalsignal(
75
- indata, optiondict, includemask=None, excludemask=None, pcacomponents=0.8, debug=False
76
- ):
77
- # Start with all voxels
78
- themask = indata[:, 0] * 0 + 1
79
-
80
- # modify the mask if needed
81
- if includemask is not None:
82
- themask = themask * includemask
83
- if excludemask is not None:
84
- themask = themask * (1 - excludemask)
85
-
86
- # combine all the voxels using one of the three methods
87
- global rt_floatset, rt_floattype
88
- globalmean = rt_floatset(indata[0, :])
89
- thesize = np.shape(themask)
90
- numvoxelsused = int(np.sum(np.where(themask > 0.0, 1, 0)))
91
- selectedvoxels = indata[np.where(themask > 0.0), :][0]
92
- if debug:
93
- print(f"getglobalsignal: {selectedvoxels.shape=}")
94
- LGR.info(f"constructing global mean signal using {optiondict['globalsignalmethod']}")
95
- if optiondict["globalsignalmethod"] == "sum":
96
- globalmean = np.mean(selectedvoxels, axis=0)
97
- globalmean -= np.mean(globalmean)
98
- elif optiondict["globalsignalmethod"] == "meanscale":
99
- themean = np.mean(indata, axis=1)
100
- for vox in range(0, thesize[0]):
101
- if themask[vox] > 0.0:
102
- if themean[vox] != 0.0:
103
- globalmean += indata[vox, :] / themean[vox] - 1.0
104
- elif optiondict["globalsignalmethod"] == "pca":
105
- themean = np.mean(indata, axis=1)
106
- thevar = np.var(indata, axis=1)
107
- scaledvoxels = selectedvoxels * 0.0
108
- for vox in range(0, selectedvoxels.shape[0]):
109
- scaledvoxels[vox, :] = selectedvoxels[vox, :] - themean[vox]
110
- if thevar[vox] > 0.0:
111
- scaledvoxels[vox, :] = selectedvoxels[vox, :] / thevar[vox]
112
- try:
113
- thefit = PCA(n_components=pcacomponents).fit(np.transpose(scaledvoxels))
114
- except ValueError:
115
- if pcacomponents == "mle":
116
- LGR.warning("mle estimation failed - falling back to pcacomponents=0.8")
117
- thefit = PCA(n_components=0.8).fit(np.transpose(scaledvoxels))
118
- else:
119
- raise ValueError("unhandled math exception in PCA refinement - exiting")
120
-
121
- varex = 100.0 * np.cumsum(thefit.explained_variance_ratio_)[len(thefit.components_) - 1]
122
- thetransform = thefit.transform(np.transpose(scaledvoxels))
123
- if debug:
124
- print(f"getglobalsignal: {thetransform.shape=}")
125
- globalmean = np.mean(thetransform, axis=0)
126
- globalmean -= np.mean(globalmean)
127
- if debug:
128
- print(f"getglobalsignal: {varex=}")
129
- LGR.info(
130
- f"Using {len(thefit.components_)} component(s), accounting for "
131
- f"{varex:.2f}% of the variance"
132
- )
133
- elif optiondict["globalsignalmethod"] == "random":
134
- globalmean = np.random.standard_normal(size=len(globalmean))
135
- else:
136
- raise ValueError(f"illegal globalsignalmethod: {optiondict['globalsignalmethod']}")
137
- LGR.info(f"used {numvoxelsused} voxels to calculate global mean signal")
138
- if debug:
139
- print(f"getglobalsignal: {globalmean=}")
140
- return tide_math.stdnormalize(globalmean), themask
141
-
142
-
143
74
  def checkforzeromean(thedataset):
144
75
  themean = np.mean(thedataset, axis=1)
145
76
  thestd = np.std(thedataset, axis=1)
@@ -227,7 +158,7 @@ def rapidtide_main(argparsingfunc):
227
158
  gc.enable()
228
159
  print("turning on garbage collection")
229
160
 
230
- # if running in Docker or Apptainer/Singularity, this is necessary to enforce memory limits properly
161
+ # If running in Docker or Apptainer/Singularity, this is necessary to enforce memory limits properly
231
162
  # otherwise likely to error out in gzip.py or at voxelnormalize step. But do nothing if running in CircleCI
232
163
  # because it does NOT like you messing with the container.
233
164
  optiondict["containertype"] = tide_util.checkifincontainer()
@@ -364,16 +295,13 @@ def rapidtide_main(argparsingfunc):
364
295
  theinputdata = tide_voxelData.VoxelData(inputdatafilename, timestep=optiondict["realtr"])
365
296
  if optiondict["debug"]:
366
297
  theinputdata.summarize()
367
- nim = theinputdata.nim
368
- nim_hdr = theinputdata.nim_hdr
369
- nim_affine = theinputdata.nim_affine
370
298
  xsize, ysize, numslices, timepoints = theinputdata.getdims()
371
299
  thesizes = theinputdata.thesizes
372
300
  xdim, ydim, slicethickness, fmritr = theinputdata.getsizes()
373
301
  numspatiallocs = theinputdata.numspatiallocs
374
302
  nativespaceshape = theinputdata.nativespaceshape
375
- cifti_hdr = theinputdata.cifti_hdr
376
303
  fmritr = theinputdata.timestep
304
+ optiondict["filetype"] = theinputdata.filetype
377
305
  if theinputdata.filetype == "cifti":
378
306
  fileiscifti = True
379
307
  optiondict["textio"] = False
@@ -440,6 +368,7 @@ def rapidtide_main(argparsingfunc):
440
368
  ["brainmaskincludename", "brainmaskincludevals", "brainmask"],
441
369
  ["graymatterincludename", "graymatterincludevals", "graymattermask"],
442
370
  ["whitematterincludename", "whitematterincludevals", "whitemattermask"],
371
+ ["csfincludename", "csfincludevals", "csfmask"],
443
372
  ]
444
373
  anatomicmasks = []
445
374
  for thisanatomic in anatomiclist:
@@ -447,12 +376,13 @@ def rapidtide_main(argparsingfunc):
447
376
  anatomicmasks.append(
448
377
  tide_mask.readamask(
449
378
  optiondict[thisanatomic[0]],
450
- nim_hdr,
379
+ theinputdata.nim_hdr,
451
380
  xsize,
452
- istext=optiondict["textio"],
381
+ istext=(theinputdata.filetype == "text"),
453
382
  valslist=optiondict[thisanatomic[1]],
454
383
  maskname=thisanatomic[2],
455
384
  tolerance=optiondict["spatialtolerance"],
385
+ debug=optiondict["focaldebug"],
456
386
  )
457
387
  )
458
388
  anatomicmasks[-1] = np.uint16(np.where(anatomicmasks[-1] > 0.1, 1, 0))
@@ -462,6 +392,7 @@ def rapidtide_main(argparsingfunc):
462
392
  brainmask = anatomicmasks[0]
463
393
  graymask = anatomicmasks[1]
464
394
  whitemask = anatomicmasks[2]
395
+ csfmask = anatomicmasks[3]
465
396
 
466
397
  # do spatial filtering if requested
467
398
  optiondict["gausssigma"] = theinputdata.smooth(
@@ -476,8 +407,8 @@ def rapidtide_main(argparsingfunc):
476
407
  if optiondict["gausssigma"] > 0.0:
477
408
  TimingLGR.info("End 3D smoothing")
478
409
 
479
- # reshape the data and trim to a time range, if specified. Check for special case of no trimming to save RAM
480
- fmri_data = theinputdata.voxelbytime()
410
+ # Reshape the data and trim to a time range, if specified. Check for special case of no trimming to save RAM
411
+ fmri_data = theinputdata.byvoxel()
481
412
  print(f"{fmri_data.shape=}")
482
413
 
483
414
  # detect zero mean data
@@ -492,7 +423,7 @@ def rapidtide_main(argparsingfunc):
492
423
  )
493
424
  optiondict["refineprenorm"] = "None"
494
425
 
495
- # reformat the brain mask, if it exists
426
+ # reformat the anatomic masks, if they exist
496
427
  if brainmask is None:
497
428
  invbrainmask = None
498
429
 
@@ -506,22 +437,25 @@ def rapidtide_main(argparsingfunc):
506
437
  # read in the optional masks
507
438
  tide_util.logmem("before setting masks")
508
439
 
509
- internalglobalmeanincludemask, internalglobalmeanexcludemask, dummy = tide_mask.getmaskset(
510
- "global mean",
511
- optiondict["globalmeanincludename"],
512
- optiondict["globalmeanincludevals"],
513
- optiondict["globalmeanexcludename"],
514
- optiondict["globalmeanexcludevals"],
515
- nim_hdr,
516
- numspatiallocs,
517
- istext=optiondict["textio"],
518
- tolerance=optiondict["spatialtolerance"],
440
+ internalinitregressorincludemask, internalinitregressorexcludemask, dummy = (
441
+ tide_mask.getmaskset(
442
+ "global mean",
443
+ optiondict["initregressorincludename"],
444
+ optiondict["initregressorincludevals"],
445
+ optiondict["initregressorexcludename"],
446
+ optiondict["initregressorexcludevals"],
447
+ theinputdata.nim_hdr,
448
+ numspatiallocs,
449
+ istext=(theinputdata.filetype == "text"),
450
+ tolerance=optiondict["spatialtolerance"],
451
+ debug=optiondict["focaldebug"],
452
+ )
519
453
  )
520
454
  if internalinvbrainmask is not None:
521
- if internalglobalmeanexcludemask is not None:
522
- internalglobalmeanexcludemask *= internalinvbrainmask
455
+ if internalinitregressorexcludemask is not None:
456
+ internalinitregressorexcludemask *= internalinvbrainmask
523
457
  else:
524
- internalglobalmeanexcludemask = internalinvbrainmask
458
+ internalinitregressorexcludemask = internalinvbrainmask
525
459
 
526
460
  internalrefineincludemask, internalrefineexcludemask, dummy = tide_mask.getmaskset(
527
461
  "refine",
@@ -529,10 +463,11 @@ def rapidtide_main(argparsingfunc):
529
463
  optiondict["refineincludevals"],
530
464
  optiondict["refineexcludename"],
531
465
  optiondict["refineexcludevals"],
532
- nim_hdr,
466
+ theinputdata.nim_hdr,
533
467
  numspatiallocs,
534
- istext=optiondict["textio"],
468
+ istext=(theinputdata.filetype == "text"),
535
469
  tolerance=optiondict["spatialtolerance"],
470
+ debug=optiondict["focaldebug"],
536
471
  )
537
472
  if internalinvbrainmask is not None:
538
473
  if internalrefineexcludemask is not None:
@@ -546,10 +481,11 @@ def rapidtide_main(argparsingfunc):
546
481
  optiondict["offsetincludevals"],
547
482
  optiondict["offsetexcludename"],
548
483
  optiondict["offsetexcludevals"],
549
- nim_hdr,
484
+ theinputdata.nim_hdr,
550
485
  numspatiallocs,
551
- istext=optiondict["textio"],
486
+ istext=(theinputdata.filetype == "text"),
552
487
  tolerance=optiondict["spatialtolerance"],
488
+ debug=optiondict["focaldebug"],
553
489
  )
554
490
  if internalinvbrainmask is not None:
555
491
  if internaloffsetexcludemask is not None:
@@ -565,19 +501,20 @@ def rapidtide_main(argparsingfunc):
565
501
  if optiondict["corrmaskincludename"] is not None:
566
502
  thecorrmask = tide_mask.readamask(
567
503
  optiondict["corrmaskincludename"],
568
- nim_hdr,
504
+ theinputdata.nim_hdr,
569
505
  xsize,
570
- istext=optiondict["textio"],
506
+ istext=(theinputdata.filetype == "text"),
571
507
  valslist=optiondict["corrmaskincludevals"],
572
508
  maskname="correlation",
573
509
  tolerance=optiondict["spatialtolerance"],
510
+ debug=optiondict["focaldebug"],
574
511
  )
575
512
 
576
513
  corrmask = np.uint16(np.where(thecorrmask > 0, 1, 0).reshape(numspatiallocs))
577
514
 
578
515
  # last line sanity check - if data is 0 over all time in a voxel, force corrmask to zero.
579
516
  datarange = np.max(fmri_data, axis=1) - np.min(fmri_data, axis=1)
580
- if optiondict["textio"]:
517
+ if theinputdata.filetype == "text":
581
518
  tide_io.writenpvecs(
582
519
  datarange.reshape((numspatiallocs)),
583
520
  f"{outputname}_motionr2.txt",
@@ -586,18 +523,20 @@ def rapidtide_main(argparsingfunc):
586
523
  savename = f"{outputname}_desc-datarange"
587
524
  tide_io.savetonifti(
588
525
  datarange.reshape((xsize, ysize, numslices)),
589
- nim_hdr,
526
+ theinputdata.nim_hdr,
590
527
  savename,
591
528
  )
592
529
  corrmask[np.where(datarange == 0)] = 0.0
593
530
  else:
594
531
  # check to see if the data has been demeaned
595
- if fileiscifti or optiondict["textio"]:
596
- corrmask = np.uint(theinputdata.voxelbytime()[:, 0] * 0 + 1)
532
+ if theinputdata.filetype != "nifti":
533
+ corrmask = np.uint(theinputdata.byvoxel()[:, 0] * 0 + 1)
597
534
  else:
598
535
  if not optiondict["dataiszeromean"]:
599
536
  LGR.verbose("generating correlation mask from mean image")
600
- corrmask = np.uint16(tide_mask.makeepimask(nim).dataobj.reshape(numspatiallocs))
537
+ corrmask = np.uint16(
538
+ tide_mask.makeepimask(theinputdata.nim).dataobj.reshape(numspatiallocs)
539
+ )
601
540
  else:
602
541
  LGR.verbose("generating correlation mask from std image")
603
542
  corrmask = np.uint16(
@@ -605,8 +544,8 @@ def rapidtide_main(argparsingfunc):
605
544
  np.std(fmri_data, axis=1), threshpct=optiondict["corrmaskthreshpct"]
606
545
  )
607
546
  )
608
- if internalbrainmask is not None:
609
- corrmask = internalbrainmask
547
+ if internalbrainmask is not None:
548
+ corrmask = internalbrainmask
610
549
  if tide_stats.getmasksize(corrmask) == 0:
611
550
  raise ValueError("ERROR: there are no voxels in the correlation mask - exiting")
612
551
 
@@ -638,11 +577,8 @@ def rapidtide_main(argparsingfunc):
638
577
  corrmask *= 0
639
578
  corrmask += 1
640
579
  threshval = -10000000.0
641
- if not (fileiscifti or optiondict["textio"]):
642
- theheader = copy.deepcopy(nim_hdr)
643
- theheader["dim"][0] = 3
644
- theheader["dim"][4] = 1
645
- theheader["pixdim"][4] = 1.0
580
+ if theinputdata.filetype == "nifti":
581
+ theheader = theinputdata.copyheader(numtimepoints=1)
646
582
  savename = f"{outputname}_desc-processed_mask"
647
583
  tide_io.savetonifti(corrmask.reshape(xsize, ysize, numslices), theheader, savename)
648
584
 
@@ -654,7 +590,7 @@ def rapidtide_main(argparsingfunc):
654
590
  numvalidspatiallocs = np.shape(validvoxels)[0]
655
591
  LGR.debug(f"validvoxels shape = {numvalidspatiallocs}")
656
592
  theinputdata.setvalidvoxels(validvoxels)
657
- fmri_data_valid = theinputdata.getvalidvoxels() + 0.0
593
+ fmri_data_valid = theinputdata.validdata() + 0.0
658
594
  LGR.verbose(
659
595
  f"original size = {np.shape(fmri_data)}, trimmed size = {np.shape(fmri_data_valid)}"
660
596
  )
@@ -714,7 +650,7 @@ def rapidtide_main(argparsingfunc):
714
650
  ),
715
651
  labels=["xtrans", "ytrans", "ztrans", "xrot", "yrot", "zrot"],
716
652
  deriv=optiondict["mot_deriv"],
717
- order=1,
653
+ order=optiondict["mot_power"],
718
654
  )
719
655
  domotion = True
720
656
  else:
@@ -757,7 +693,7 @@ def rapidtide_main(argparsingfunc):
757
693
  append=False,
758
694
  )
759
695
 
760
- if optiondict["focaldebug"]:
696
+ if optiondict["debug"]:
761
697
  print(f"{mergedregressors.shape=}")
762
698
  print(f"{mergedregressorlabels}")
763
699
  print(f"{fmri_data_valid.shape=}")
@@ -794,8 +730,8 @@ def rapidtide_main(argparsingfunc):
794
730
  },
795
731
  )
796
732
  # save the confound filter R2 map
797
- if not optiondict["textio"]:
798
- if fileiscifti:
733
+ if theinputdata.filetype != "text":
734
+ if theinputdata.filetype == "cifti":
799
735
  timeindex = theheader["dim"][0] - 1
800
736
  spaceindex = theheader["dim"][0]
801
737
  theheader["dim"][timeindex] = 1
@@ -814,10 +750,9 @@ def rapidtide_main(argparsingfunc):
814
750
  nativespaceshape,
815
751
  theheader,
816
752
  bidsbasedict,
817
- textio=optiondict["textio"],
818
- fileiscifti=fileiscifti,
753
+ filetype=theinputdata.filetype,
819
754
  rt_floattype=rt_floattype,
820
- cifti_hdr=cifti_hdr,
755
+ cifti_hdr=theinputdata.cifti_hdr,
821
756
  )
822
757
  tide_stats.makeandsavehistogram(
823
758
  confoundr2,
@@ -843,23 +778,7 @@ def rapidtide_main(argparsingfunc):
843
778
  tide_util.logmem("after confound sLFO filter")
844
779
 
845
780
  if optiondict["saveconfoundfiltered"]:
846
- if not optiondict["textio"]:
847
- theheader = copy.deepcopy(nim_hdr)
848
- if fileiscifti:
849
- nativefmrishape = (1, 1, 1, validtimepoints, numspatiallocs)
850
- timeindex = theheader["dim"][0] - 1
851
- spaceindex = theheader["dim"][0]
852
- theheader["dim"][timeindex] = validtimepoints
853
- theheader["dim"][spaceindex] = numspatiallocs
854
- else:
855
- nativefmrishape = (xsize, ysize, numslices, validtimepoints)
856
- theheader["dim"][4] = validtimepoints
857
- theheader["pixdim"][4] = fmritr
858
- else:
859
- nativefmrishape = (xsize, validtimepoints)
860
- theheader = None
861
- cifti_hdr = None
862
-
781
+ theheader = theinputdata.copyheader(numtimepoints=validtimepoints, tr=fmritr)
863
782
  maplist = [
864
783
  (
865
784
  fmri_data_valid,
@@ -873,23 +792,22 @@ def rapidtide_main(argparsingfunc):
873
792
  outputname,
874
793
  maplist,
875
794
  validvoxels,
876
- nativefmrishape,
795
+ theinputdata.nativefmrishape,
877
796
  theheader,
878
797
  bidsbasedict,
879
- textio=optiondict["textio"],
880
- fileiscifti=fileiscifti,
798
+ filetype=theinputdata.filetype,
881
799
  rt_floattype=rt_floattype,
882
- cifti_hdr=cifti_hdr,
800
+ cifti_hdr=theinputdata.cifti_hdr,
883
801
  )
884
802
 
885
803
  # get rid of memory we aren't using
886
804
  tide_util.logmem("before purging full sized fmri data")
887
805
  meanvalue = np.mean(
888
- theinputdata.voxelbytime(),
806
+ theinputdata.byvoxel(),
889
807
  axis=1,
890
808
  )
891
809
  stddevvalue = np.std(
892
- theinputdata.voxelbytime(),
810
+ theinputdata.byvoxel(),
893
811
  axis=1,
894
812
  )
895
813
  covvalue = np.where(meanvalue > 0.0, stddevvalue / meanvalue, 0.0)
@@ -902,15 +820,86 @@ def rapidtide_main(argparsingfunc):
902
820
  meanfreq = 1.0 / fmritr
903
821
  meanperiod = 1.0 * fmritr
904
822
  meanstarttime = 0.0
905
- meanvec, meanmask = getglobalsignal(
823
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
824
+ "initial regressor",
825
+ "startregressormask",
906
826
  fmri_data,
907
- optiondict,
908
- includemask=internalglobalmeanincludemask,
909
- excludemask=internalglobalmeanexcludemask,
910
- pcacomponents=optiondict["globalpcacomponents"],
911
- debug=False,
827
+ internalinitregressorincludemask,
828
+ meanfreq,
829
+ outputname,
830
+ initfile=True,
831
+ signalgenmethod=optiondict["initregressorsignalmethod"],
832
+ pcacomponents=optiondict["initregressorpcacomponents"],
833
+ excludemask=internalinitregressorexcludemask,
834
+ filedesc="regionalprefilter",
835
+ suffix="",
836
+ debug=optiondict["debug"],
912
837
  )
913
838
 
839
+ if brainmask is not None:
840
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
841
+ "whole brain",
842
+ "brain",
843
+ fmri_data,
844
+ internalbrainmask,
845
+ meanfreq,
846
+ outputname,
847
+ filedesc="regionalprefilter",
848
+ suffix="",
849
+ debug=optiondict["debug"],
850
+ )
851
+
852
+ if graymask is None:
853
+ internalgraymask = None
854
+ else:
855
+ internalgraymask = graymask.reshape((numspatiallocs))
856
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
857
+ "gray matter",
858
+ "GM",
859
+ fmri_data,
860
+ internalgraymask,
861
+ meanfreq,
862
+ outputname,
863
+ excludemask=internalinvbrainmask,
864
+ filedesc="regionalprefilter",
865
+ suffix="",
866
+ debug=optiondict["debug"],
867
+ )
868
+
869
+ if whitemask is None:
870
+ internalwhitemask = None
871
+ else:
872
+ internalwhitemask = whitemask.reshape((numspatiallocs))
873
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
874
+ "white matter",
875
+ "WM",
876
+ fmri_data,
877
+ internalwhitemask,
878
+ meanfreq,
879
+ outputname,
880
+ excludemask=internalinvbrainmask,
881
+ filedesc="regionalprefilter",
882
+ suffix="",
883
+ debug=optiondict["debug"],
884
+ )
885
+
886
+ if csfmask is None:
887
+ internalcsfmask = None
888
+ else:
889
+ internalcsfmask = csfmask.reshape((numspatiallocs))
890
+ csfvec, dummy = tide_mask.saveregionaltimeseries(
891
+ "CSF",
892
+ "CSF",
893
+ fmri_data,
894
+ internalcsfmask,
895
+ meanfreq,
896
+ outputname,
897
+ excludemask=internalinvbrainmask,
898
+ filedesc="regionalprefilter",
899
+ suffix="",
900
+ debug=optiondict["debug"],
901
+ )
902
+
914
903
  # get rid of more memory we aren't using
915
904
  theinputdata.unload()
916
905
  uncollected = gc.collect()
@@ -925,31 +914,23 @@ def rapidtide_main(argparsingfunc):
925
914
  TimingLGR.info("Start of reference prep")
926
915
  if regressorfilename is None:
927
916
  LGR.info("no regressor file specified - will use the global mean regressor")
928
- optiondict["useglobalref"] = True
917
+ optiondict["useinitregressorref"] = True
929
918
  else:
930
- optiondict["useglobalref"] = False
919
+ optiondict["useinitregressorref"] = False
931
920
 
932
921
  # now set the regressor that we'll use
933
- if optiondict["useglobalref"]:
922
+ if optiondict["useinitregressorref"]:
934
923
  LGR.verbose("using global mean as probe regressor")
935
924
  inputfreq = meanfreq
936
925
  inputperiod = meanperiod
937
926
  inputstarttime = meanstarttime
938
927
  inputvec = meanvec
939
- theheader = copy.deepcopy(nim_hdr)
940
928
 
941
929
  # save the meanmask
942
- if not optiondict["textio"]:
943
- if fileiscifti:
944
- timeindex = theheader["dim"][0] - 1
945
- spaceindex = theheader["dim"][0]
946
- theheader["dim"][timeindex] = 1
947
- theheader["dim"][spaceindex] = numspatiallocs
948
- else:
949
- theheader["dim"][0] = 3
950
- theheader["dim"][4] = 1
951
- theheader["pixdim"][4] = 1.0
952
- masklist = [(meanmask, "globalmean", "mask", None, "Voxels used to calculate global mean")]
930
+ theheader = theinputdata.copyheader(numtimepoints=1)
931
+ masklist = [
932
+ (meanmask, "initregressor", "mask", None, "Voxels used to calculate initial regressor")
933
+ ]
953
934
  tide_io.savemaplist(
954
935
  outputname,
955
936
  masklist,
@@ -957,10 +938,9 @@ def rapidtide_main(argparsingfunc):
957
938
  nativespaceshape,
958
939
  theheader,
959
940
  bidsbasedict,
960
- textio=optiondict["textio"],
961
- fileiscifti=fileiscifti,
941
+ filetype=theinputdata.filetype,
962
942
  rt_floattype=rt_floattype,
963
- cifti_hdr=cifti_hdr,
943
+ cifti_hdr=theinputdata.cifti_hdr,
964
944
  )
965
945
  optiondict["preprocskip"] = 0
966
946
  else:
@@ -1001,7 +981,7 @@ def rapidtide_main(argparsingfunc):
1001
981
  LGR.verbose(f"input freq: {inputfreq}")
1002
982
  LGR.verbose(f"input start time: {inputstarttime:.3f}")
1003
983
 
1004
- if not optiondict["useglobalref"]:
984
+ if not optiondict["useinitregressorref"]:
1005
985
  globalcorrx, globalcorry, dummy, dummy = tide_corr.arbcorr(
1006
986
  meanvec, meanfreq, inputvec, inputfreq, start2=(inputstarttime)
1007
987
  )
@@ -1286,6 +1266,10 @@ def rapidtide_main(argparsingfunc):
1286
1266
  corrpadding=optiondict["corrpadding"],
1287
1267
  debug=optiondict["debug"],
1288
1268
  )
1269
+ if optiondict["focaldebug"]:
1270
+ print(
1271
+ f"calling setreftc during initialization with length {optiondict['oversampfactor'] * validtimepoints}"
1272
+ )
1289
1273
  theCorrelator.setreftc(
1290
1274
  np.zeros((optiondict["oversampfactor"] * validtimepoints), dtype=np.float64)
1291
1275
  )
@@ -1387,10 +1371,10 @@ def rapidtide_main(argparsingfunc):
1387
1371
  tide_util.logmem("after main array allocation")
1388
1372
 
1389
1373
  corroutlen = np.shape(trimmedcorrscale)[0]
1390
- if optiondict["textio"]:
1374
+ if theinputdata.filetype == "text":
1391
1375
  nativecorrshape = (xsize, corroutlen)
1392
1376
  else:
1393
- if fileiscifti:
1377
+ if theinputdata.filetype == "cifti":
1394
1378
  nativecorrshape = (1, 1, 1, corroutlen, numspatiallocs)
1395
1379
  else:
1396
1380
  nativecorrshape = (xsize, ysize, numslices, corroutlen)
@@ -1438,17 +1422,7 @@ def rapidtide_main(argparsingfunc):
1438
1422
  initialdelay_dims,
1439
1423
  initialdelay_sizes,
1440
1424
  ) = tide_io.readfromnifti(optiondict["initialdelayvalue"])
1441
- theheader = copy.deepcopy(nim_hdr)
1442
- if not optiondict["textio"]:
1443
- if fileiscifti:
1444
- timeindex = theheader["dim"][0] - 1
1445
- spaceindex = theheader["dim"][0]
1446
- theheader["dim"][timeindex] = 1
1447
- theheader["dim"][spaceindex] = numspatiallocs
1448
- else:
1449
- theheader["dim"][0] = 3
1450
- theheader["dim"][4] = 1
1451
- theheader["pixdim"][4] = 1.0
1425
+ theheader = theinputdata.copyheader(numtimepoints=1)
1452
1426
  if not tide_io.checkspacematch(theheader, initialdelay_header):
1453
1427
  raise ValueError("fixed delay map dimensions do not match fmri dimensions")
1454
1428
  theinitialdelay = initialdelay.reshape(numspatiallocs)[validvoxels]
@@ -1478,9 +1452,9 @@ def rapidtide_main(argparsingfunc):
1478
1452
  - fmritr * numpadtrs
1479
1453
  )
1480
1454
 
1481
- if optiondict["textio"]:
1455
+ if theinputdata.filetype == "text":
1482
1456
  nativefmrishape = (xsize, np.shape(initial_fmri_x)[0])
1483
- elif fileiscifti:
1457
+ elif theinputdata.filetype == "cifti":
1484
1458
  nativefmrishape = (1, 1, 1, np.shape(initial_fmri_x)[0], numspatiallocs)
1485
1459
  else:
1486
1460
  nativefmrishape = (xsize, ysize, numslices, np.shape(initial_fmri_x)[0])
@@ -1495,7 +1469,7 @@ def rapidtide_main(argparsingfunc):
1495
1469
  # prepare for regressor refinement, if we're doing it
1496
1470
  if (
1497
1471
  optiondict["passes"] > 1
1498
- or optiondict["globalpreselect"]
1472
+ or optiondict["initregressorpreselect"]
1499
1473
  or optiondict["dofinalrefine"]
1500
1474
  or optiondict["convergencethresh"] is not None
1501
1475
  ):
@@ -1710,6 +1684,10 @@ def rapidtide_main(argparsingfunc):
1710
1684
  rt_floattype=rt_floattype,
1711
1685
  rt_floatset=rt_floatset,
1712
1686
  )
1687
+ if optiondict["focaldebug"]:
1688
+ print(
1689
+ f"after cleanregressor: {len(referencetc)=}, {len(cleaned_referencetc)=}, {osvalidsimcalcstart=}, {osvalidsimcalcend=}, {lagmininpts=}, {lagmaxinpts=}"
1690
+ )
1713
1691
 
1714
1692
  # Step 0 - estimate significance
1715
1693
  if optiondict["numestreps"] > 0:
@@ -1737,6 +1715,10 @@ def rapidtide_main(argparsingfunc):
1737
1715
  f"{outputname}_options_pregetnull_pass" + str(thepass) + ".json",
1738
1716
  )
1739
1717
  theCorrelator.setlimits(lagmininpts, lagmaxinpts)
1718
+ if optiondict["focaldebug"]:
1719
+ print(
1720
+ f"calling setreftc prior to significance estimation with length {len(cleaned_resampref_y)}"
1721
+ )
1740
1722
  theCorrelator.setreftc(cleaned_resampref_y)
1741
1723
  theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
1742
1724
  theMutualInformationator.setreftc(cleaned_resampref_y)
@@ -1904,6 +1886,7 @@ def rapidtide_main(argparsingfunc):
1904
1886
  chunksize=optiondict["mp_chunksize"],
1905
1887
  rt_floatset=rt_floatset,
1906
1888
  rt_floattype=rt_floattype,
1889
+ debug=optiondict["focaldebug"],
1907
1890
  )
1908
1891
  else:
1909
1892
  (
@@ -1928,6 +1911,7 @@ def rapidtide_main(argparsingfunc):
1928
1911
  chunksize=optiondict["mp_chunksize"],
1929
1912
  rt_floatset=rt_floatset,
1930
1913
  rt_floattype=rt_floattype,
1914
+ debug=optiondict["focaldebug"],
1931
1915
  )
1932
1916
  tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
1933
1917
 
@@ -1950,7 +1934,7 @@ def rapidtide_main(argparsingfunc):
1950
1934
  if optiondict["checkpoint"]:
1951
1935
  outcorrarray[:, :] = 0.0
1952
1936
  outcorrarray[validvoxels, :] = corrout[:, :]
1953
- if optiondict["textio"]:
1937
+ if theinputdata.filetype == "text":
1954
1938
  tide_io.writenpvecs(
1955
1939
  outcorrarray.reshape(nativecorrshape),
1956
1940
  f"{outputname}_corrout_prefit_pass" + str(thepass) + ".txt",
@@ -2142,8 +2126,8 @@ def rapidtide_main(argparsingfunc):
2142
2126
  internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2143
2127
  )
2144
2128
  if thepass == optiondict["passes"]:
2145
- if not optiondict["textio"]:
2146
- if fileiscifti:
2129
+ if theinputdata.filetype != "text":
2130
+ if theinputdata.filetype == "cifti":
2147
2131
  timeindex = theheader["dim"][0] - 1
2148
2132
  spaceindex = theheader["dim"][0]
2149
2133
  theheader["dim"][timeindex] = 1
@@ -2168,10 +2152,9 @@ def rapidtide_main(argparsingfunc):
2168
2152
  nativespaceshape,
2169
2153
  theheader,
2170
2154
  bidsbasedict,
2171
- textio=optiondict["textio"],
2172
- fileiscifti=fileiscifti,
2155
+ filetype=theinputdata.filetype,
2173
2156
  rt_floattype=rt_floattype,
2174
- cifti_hdr=cifti_hdr,
2157
+ cifti_hdr=theinputdata.cifti_hdr,
2175
2158
  )
2176
2159
  LGR.info(
2177
2160
  f"\n\n{voxelsprocessed_fc_ds} voxels despeckled in "
@@ -2206,18 +2189,17 @@ def rapidtide_main(argparsingfunc):
2206
2189
  nativespaceshape,
2207
2190
  theheader,
2208
2191
  bidsbasedict,
2209
- textio=optiondict["textio"],
2210
- fileiscifti=fileiscifti,
2192
+ filetype=theinputdata.filetype,
2211
2193
  rt_floattype=rt_floattype,
2212
- cifti_hdr=cifti_hdr,
2194
+ cifti_hdr=theinputdata.cifti_hdr,
2213
2195
  )
2214
2196
 
2215
2197
  # create list of anomalous 3D regions that don't match surroundings
2216
- if nim_affine is not None:
2198
+ if theinputdata.nim_affine is not None:
2217
2199
  # make an atlas of anomalous patches - each patch shares the same integer value
2218
2200
  step1 = tide_patch.calc_DoG(
2219
2201
  outmaparray.reshape(nativespaceshape).copy(),
2220
- nim_affine,
2202
+ theinputdata.nim_affine,
2221
2203
  thesizes,
2222
2204
  fwhm=optiondict["patchfwhm"],
2223
2205
  ratioopt=False,
@@ -2239,10 +2221,9 @@ def rapidtide_main(argparsingfunc):
2239
2221
  nativespaceshape,
2240
2222
  theheader,
2241
2223
  bidsbasedict,
2242
- textio=optiondict["textio"],
2243
- fileiscifti=fileiscifti,
2224
+ filetype=theinputdata.filetype,
2244
2225
  rt_floattype=rt_floattype,
2245
- cifti_hdr=cifti_hdr,
2226
+ cifti_hdr=theinputdata.cifti_hdr,
2246
2227
  )
2247
2228
  step2 = tide_patch.invertedflood3D(
2248
2229
  step1,
@@ -2264,10 +2245,9 @@ def rapidtide_main(argparsingfunc):
2264
2245
  nativespaceshape,
2265
2246
  theheader,
2266
2247
  bidsbasedict,
2267
- textio=optiondict["textio"],
2268
- fileiscifti=fileiscifti,
2248
+ filetype=theinputdata.filetype,
2269
2249
  rt_floattype=rt_floattype,
2270
- cifti_hdr=cifti_hdr,
2250
+ cifti_hdr=theinputdata.cifti_hdr,
2271
2251
  )
2272
2252
 
2273
2253
  patchmap = tide_patch.separateclusters(
@@ -2277,7 +2257,7 @@ def rapidtide_main(argparsingfunc):
2277
2257
  )
2278
2258
  # patchmap = tide_patch.getclusters(
2279
2259
  # outmaparray.reshape(nativespaceshape),
2280
- # nim_affine,
2260
+ # theinputdata.nim_affine,
2281
2261
  # thesizes,
2282
2262
  # fwhm=optiondict["patchfwhm"],
2283
2263
  # ratioopt=True,
@@ -2300,10 +2280,9 @@ def rapidtide_main(argparsingfunc):
2300
2280
  nativespaceshape,
2301
2281
  theheader,
2302
2282
  bidsbasedict,
2303
- textio=optiondict["textio"],
2304
- fileiscifti=fileiscifti,
2283
+ filetype=theinputdata.filetype,
2305
2284
  rt_floattype=rt_floattype,
2306
- cifti_hdr=cifti_hdr,
2285
+ cifti_hdr=theinputdata.cifti_hdr,
2307
2286
  )
2308
2287
 
2309
2288
  # now shift the patches to align with the majority of the image
@@ -2318,17 +2297,7 @@ def rapidtide_main(argparsingfunc):
2318
2297
  )
2319
2298
 
2320
2299
  if optiondict["saveintermediatemaps"]:
2321
- if not optiondict["textio"]:
2322
- theheader = copy.deepcopy(nim_hdr)
2323
- if fileiscifti:
2324
- timeindex = theheader["dim"][0] - 1
2325
- spaceindex = theheader["dim"][0]
2326
- theheader["dim"][timeindex] = 1
2327
- theheader["dim"][spaceindex] = numspatiallocs
2328
- else:
2329
- theheader["dim"][0] = 3
2330
- theheader["dim"][4] = 1
2331
- theheader["pixdim"][4] = 1.0
2300
+ theheader = theinputdata.copyheader(numtimepoints=1)
2332
2301
  bidspasssuffix = f"_intermediatedata-pass{thepass}"
2333
2302
  maplist = [
2334
2303
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
@@ -2349,10 +2318,9 @@ def rapidtide_main(argparsingfunc):
2349
2318
  nativespaceshape,
2350
2319
  theheader,
2351
2320
  bidsbasedict,
2352
- textio=optiondict["textio"],
2353
- fileiscifti=fileiscifti,
2321
+ filetype=theinputdata.filetype,
2354
2322
  rt_floattype=rt_floattype,
2355
- cifti_hdr=cifti_hdr,
2323
+ cifti_hdr=theinputdata.cifti_hdr,
2356
2324
  )
2357
2325
 
2358
2326
  # Step 3 - regressor refinement for next pass
@@ -2362,7 +2330,7 @@ def rapidtide_main(argparsingfunc):
2362
2330
  if (
2363
2331
  thepass < optiondict["passes"]
2364
2332
  or optiondict["convergencethresh"] is not None
2365
- or optiondict["globalpreselect"]
2333
+ or optiondict["initregressorpreselect"]
2366
2334
  or optiondict["dofinalrefine"]
2367
2335
  ):
2368
2336
  LGR.info(f"\n\nRegressor refinement, pass {thepass}")
@@ -2378,7 +2346,7 @@ def rapidtide_main(argparsingfunc):
2378
2346
  LGR.warning(
2379
2347
  "NB: cannot exclude voxels from offset calculation mask - including for this pass"
2380
2348
  )
2381
- offsetmask = fitmask
2349
+ offsetmask = fitmask + 0
2382
2350
 
2383
2351
  peaklag, dummy, dummy = tide_stats.gethistprops(
2384
2352
  lagtimes[np.where(offsetmask > 0)],
@@ -2479,7 +2447,34 @@ def rapidtide_main(argparsingfunc):
2479
2447
  )
2480
2448
  for key, value in outputdict.items():
2481
2449
  optiondict[key] = value
2482
- # We are done with refinement.
2450
+
2451
+ # Save shifted timecourses for César
2452
+ if optiondict["saveintermediatemaps"] and optiondict["savelagregressors"]:
2453
+ theheader = theinputdata.copyheader()
2454
+ bidspasssuffix = f"_intermediatedata-pass{thepass}"
2455
+ maplist = [
2456
+ (
2457
+ (theRegressorRefiner.getpaddedshiftedtcs())[:, numpadtrs:-numpadtrs],
2458
+ "shiftedtcs",
2459
+ "bold",
2460
+ None,
2461
+ "The filtered input fMRI data, in voxels used for refinement, time shifted by the negated delay in every voxel so that the moving blood component is aligned.",
2462
+ ),
2463
+ ]
2464
+ tide_io.savemaplist(
2465
+ f"{outputname}{bidspasssuffix}",
2466
+ maplist,
2467
+ validvoxels,
2468
+ nativefmrishape,
2469
+ theheader,
2470
+ bidsbasedict,
2471
+ filetype=theinputdata.filetype,
2472
+ rt_floattype=rt_floattype,
2473
+ cifti_hdr=theinputdata.cifti_hdr,
2474
+ debug=True,
2475
+ )
2476
+ # We are done with refinement.
2477
+ # End of main pass loop
2483
2478
 
2484
2479
  if optiondict["convergencethresh"] is None:
2485
2480
  optiondict["actual_passes"] = optiondict["passes"]
@@ -2530,10 +2525,10 @@ def rapidtide_main(argparsingfunc):
2530
2525
  coherencefreqstep,
2531
2526
  coherencefreqaxissize,
2532
2527
  ) = theCoherer.getaxisinfo()
2533
- if optiondict["textio"]:
2528
+ if theinputdata.filetype == "text":
2534
2529
  nativecoherenceshape = (xsize, coherencefreqaxissize)
2535
2530
  else:
2536
- if fileiscifti:
2531
+ if theinputdata.filetype == "cifti":
2537
2532
  nativecoherenceshape = (1, 1, 1, coherencefreqaxissize, numspatiallocs)
2538
2533
  else:
2539
2534
  nativecoherenceshape = (xsize, ysize, numslices, coherencefreqaxissize)
@@ -2583,19 +2578,11 @@ def rapidtide_main(argparsingfunc):
2583
2578
  tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
2584
2579
 
2585
2580
  # save the results of the calculations
2586
- if not optiondict["textio"]:
2587
- theheader = copy.deepcopy(nim_hdr)
2588
- theheader["toffset"] = coherencefreqstart
2589
- theheader["pixdim"][4] = coherencefreqstep
2590
- if fileiscifti:
2591
- timeindex = theheader["dim"][0] - 1
2592
- spaceindex = theheader["dim"][0]
2593
- theheader["dim"][timeindex] = coherencefreqaxissize
2594
- theheader["dim"][spaceindex] = numspatiallocs
2595
- else:
2596
- theheader["dim"][0] = 3
2597
- theheader["dim"][4] = coherencefreqaxissize
2598
- theheader["pixdim"][4] = 1.0
2581
+ theheader = theinputdata.copyheader(
2582
+ numtimepoints=coherencefreqaxissize,
2583
+ tr=coherencefreqstep,
2584
+ toffset=coherencefreqstart,
2585
+ )
2599
2586
  maplist = [(coherencefunc, "coherence", "info", None, "Coherence function")]
2600
2587
  tide_io.savemaplist(
2601
2588
  outputname,
@@ -2604,10 +2591,9 @@ def rapidtide_main(argparsingfunc):
2604
2591
  nativecoherenceshape,
2605
2592
  theheader,
2606
2593
  bidsbasedict,
2607
- textio=optiondict["textio"],
2608
- fileiscifti=fileiscifti,
2594
+ filetype=theinputdata.filetype,
2609
2595
  rt_floattype=rt_floattype,
2610
- cifti_hdr=cifti_hdr,
2596
+ cifti_hdr=theinputdata.cifti_hdr,
2611
2597
  )
2612
2598
 
2613
2599
  TimingLGR.info(
@@ -2703,7 +2689,7 @@ def rapidtide_main(argparsingfunc):
2703
2689
  theinputdata.setvalidtimes(validstart, validend)
2704
2690
  theinputdata.setvalidvoxels(validvoxels)
2705
2691
 
2706
- fmri_data_valid = theinputdata.getvalidvoxels() + 0.0
2692
+ fmri_data_valid = theinputdata.validdata() + 0.0
2707
2693
 
2708
2694
  if optiondict["docvrmap"]:
2709
2695
  # percent normalize the fmri data
@@ -2806,20 +2792,13 @@ def rapidtide_main(argparsingfunc):
2806
2792
 
2807
2793
  if optiondict["debug"]:
2808
2794
  # dump the fmri input file going to sLFO filter
2809
- if not optiondict["textio"]:
2795
+ if theinputdata.filetype != "text":
2810
2796
  outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
2811
- theheader = copy.deepcopy(nim_hdr)
2812
- if fileiscifti:
2813
- timeindex = theheader["dim"][0] - 1
2814
- spaceindex = theheader["dim"][0]
2815
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
2816
- theheader["dim"][spaceindex] = numspatiallocs
2817
- else:
2818
- theheader["dim"][4] = np.shape(outfmriarray)[1]
2819
- theheader["pixdim"][4] = fmritr
2797
+ theheader = theinputdata.copyheader(
2798
+ numtimepoints=np.shape(outfmriarray)[1], tr=fmritr
2799
+ )
2820
2800
  else:
2821
2801
  theheader = None
2822
- cifti_hdr = None
2823
2802
  outfmriarray = None
2824
2803
 
2825
2804
  maplist = [
@@ -2838,10 +2817,9 @@ def rapidtide_main(argparsingfunc):
2838
2817
  nativefmrishape,
2839
2818
  theheader,
2840
2819
  bidsbasedict,
2841
- textio=optiondict["textio"],
2842
- fileiscifti=fileiscifti,
2820
+ filetype=theinputdata.filetype,
2843
2821
  rt_floattype=rt_floattype,
2844
- cifti_hdr=cifti_hdr,
2822
+ cifti_hdr=theinputdata.cifti_hdr,
2845
2823
  )
2846
2824
  else:
2847
2825
  outfmriarray = None
@@ -2850,7 +2828,7 @@ def rapidtide_main(argparsingfunc):
2850
2828
  if optiondict["refinedelay"]:
2851
2829
  TimingLGR.info("Delay refinement start")
2852
2830
  LGR.info("\n\nDelay refinement")
2853
- if optiondict["delayoffsetgausssigma"] < 0.0 and not optiondict["textio"]:
2831
+ if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
2854
2832
  # set gausssigma automatically
2855
2833
  optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
2856
2834
 
@@ -2888,8 +2866,7 @@ def rapidtide_main(argparsingfunc):
2888
2866
  (xdim, ydim, slicethickness),
2889
2867
  gausssigma=optiondict["delayoffsetgausssigma"],
2890
2868
  patchthresh=optiondict["delaypatchthresh"],
2891
- fileiscifti=fileiscifti,
2892
- textio=optiondict["textio"],
2869
+ filetype=theinputdata.filetype,
2893
2870
  rt_floattype="float64",
2894
2871
  debug=optiondict["debug"],
2895
2872
  )
@@ -2934,8 +2911,7 @@ def rapidtide_main(argparsingfunc):
2934
2911
  (xdim, ydim, slicethickness),
2935
2912
  gausssigma=optiondict["delayoffsetgausssigma"],
2936
2913
  patchthresh=optiondict["delaypatchthresh"],
2937
- fileiscifti=False,
2938
- textio=False,
2914
+ filetype=theinputdata.filetype,
2939
2915
  rt_floattype=rt_floattype,
2940
2916
  debug=optiondict["debug"],
2941
2917
  )
@@ -3052,6 +3028,79 @@ def rapidtide_main(argparsingfunc):
3052
3028
  "message3": "voxels",
3053
3029
  },
3054
3030
  )
3031
+ if internalinitregressorincludemask is not None:
3032
+ thisincludemask = internalinitregressorincludemask[validvoxels]
3033
+ else:
3034
+ thisincludemask = None
3035
+ if internalinitregressorexcludemask is not None:
3036
+ thisexcludemask = internalinitregressorexcludemask[validvoxels]
3037
+ else:
3038
+ thisexcludemask = None
3039
+
3040
+ meanvec, meanmask = tide_mask.saveregionaltimeseries(
3041
+ "initial regressor",
3042
+ "startregressormask",
3043
+ filtereddata,
3044
+ thisincludemask,
3045
+ meanfreq,
3046
+ outputname,
3047
+ initfile=True,
3048
+ excludemask=thisexcludemask,
3049
+ filedesc="regionalpostfilter",
3050
+ suffix="",
3051
+ debug=optiondict["debug"],
3052
+ )
3053
+ if brainmask is not None:
3054
+ brainvec, dummy = tide_mask.saveregionaltimeseries(
3055
+ "whole brain",
3056
+ "brain",
3057
+ filtereddata,
3058
+ internalbrainmask[validvoxels],
3059
+ meanfreq,
3060
+ outputname,
3061
+ filedesc="regionalpostfilter",
3062
+ suffix="",
3063
+ debug=optiondict["debug"],
3064
+ )
3065
+ if graymask is not None:
3066
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
3067
+ "gray matter",
3068
+ "GM",
3069
+ filtereddata,
3070
+ internalgraymask[validvoxels],
3071
+ meanfreq,
3072
+ outputname,
3073
+ excludemask=internalinvbrainmask[validvoxels],
3074
+ filedesc="regionalpostfilter",
3075
+ suffix="",
3076
+ debug=optiondict["debug"],
3077
+ )
3078
+ if whitemask is not None:
3079
+ whitevec, dummy = tide_mask.saveregionaltimeseries(
3080
+ "white matter",
3081
+ "WM",
3082
+ filtereddata,
3083
+ internalwhitemask[validvoxels],
3084
+ meanfreq,
3085
+ outputname,
3086
+ excludemask=internalinvbrainmask[validvoxels],
3087
+ filedesc="regionalpostfilter",
3088
+ suffix="",
3089
+ debug=optiondict["debug"],
3090
+ )
3091
+ if csfmask is not None:
3092
+ grayvec, dummy = tide_mask.saveregionaltimeseries(
3093
+ "CSF",
3094
+ "CSF",
3095
+ filtereddata,
3096
+ internalcsfmask[validvoxels],
3097
+ meanfreq,
3098
+ outputname,
3099
+ excludemask=internalinvbrainmask[validvoxels],
3100
+ filedesc="regionalpostfilter",
3101
+ suffix="",
3102
+ debug=optiondict["debug"],
3103
+ )
3055
3104
  tide_util.logmem("after sLFO filter")
3056
3105
  LGR.info("")
3057
3106
  else:
@@ -3145,21 +3194,7 @@ def rapidtide_main(argparsingfunc):
3145
3194
 
3146
3195
  # write the 3D maps that need to be remapped
3147
3196
  TimingLGR.info("Start saving maps")
3148
- if not optiondict["textio"]:
3149
- theheader = copy.deepcopy(nim_hdr)
3150
- if fileiscifti:
3151
- timeindex = theheader["dim"][0] - 1
3152
- spaceindex = theheader["dim"][0]
3153
- theheader["dim"][timeindex] = 1
3154
- theheader["dim"][spaceindex] = numspatiallocs
3155
- else:
3156
- theheader["dim"][0] = 3
3157
- theheader["dim"][4] = 1
3158
- theheader["pixdim"][4] = 1.0
3159
- else:
3160
- theheader = None
3161
- cifti_hdr = None
3162
-
3197
+ theheader = theinputdata.copyheader(numtimepoints=1)
3163
3198
  savelist = [
3164
3199
  (lagtimes, "maxtime", "map", "second", "Lag time in seconds"),
3165
3200
  (
@@ -3264,10 +3299,9 @@ def rapidtide_main(argparsingfunc):
3264
3299
  nativespaceshape,
3265
3300
  theheader,
3266
3301
  bidsbasedict,
3267
- textio=optiondict["textio"],
3268
- fileiscifti=fileiscifti,
3302
+ filetype=theinputdata.filetype,
3269
3303
  rt_floattype=rt_floattype,
3270
- cifti_hdr=cifti_hdr,
3304
+ cifti_hdr=theinputdata.cifti_hdr,
3271
3305
  )
3272
3306
  namesuffix = "_desc-MTT_hist"
3273
3307
  tide_stats.makeandsavehistogram(
@@ -3424,10 +3458,9 @@ def rapidtide_main(argparsingfunc):
3424
3458
  nativespaceshape,
3425
3459
  theheader,
3426
3460
  bidsbasedict,
3427
- textio=optiondict["textio"],
3428
- fileiscifti=fileiscifti,
3461
+ filetype=theinputdata.filetype,
3429
3462
  rt_floattype=rt_floattype,
3430
- cifti_hdr=cifti_hdr,
3463
+ cifti_hdr=theinputdata.cifti_hdr,
3431
3464
  )
3432
3465
 
3433
3466
  if optiondict["refinedelay"] and False:
@@ -3481,10 +3514,9 @@ def rapidtide_main(argparsingfunc):
3481
3514
  nativespaceshape,
3482
3515
  theheader,
3483
3516
  bidsbasedict,
3484
- textio=optiondict["textio"],
3485
- fileiscifti=fileiscifti,
3517
+ filetype=theinputdata.filetype,
3486
3518
  rt_floattype=rt_floattype,
3487
- cifti_hdr=cifti_hdr,
3519
+ cifti_hdr=theinputdata.cifti_hdr,
3488
3520
  )
3489
3521
 
3490
3522
  del fmri_data_valid
@@ -3518,6 +3550,8 @@ def rapidtide_main(argparsingfunc):
3518
3550
  maplist.append((graymask, "GM", "mask", None, "Gray matter mask"))
3519
3551
  if whitemask is not None:
3520
3552
  maplist.append((whitemask, "WM", "mask", None, "White matter mask"))
3553
+ if csfmask is not None:
3554
+ maplist.append((csfmask, "CSF", "mask", None, "CSF mask"))
3521
3555
  tide_io.savemaplist(
3522
3556
  outputname,
3523
3557
  maplist,
@@ -3525,10 +3559,9 @@ def rapidtide_main(argparsingfunc):
3525
3559
  nativespaceshape,
3526
3560
  theheader,
3527
3561
  bidsbasedict,
3528
- textio=optiondict["textio"],
3529
- fileiscifti=fileiscifti,
3562
+ filetype=theinputdata.filetype,
3530
3563
  rt_floattype=rt_floattype,
3531
- cifti_hdr=cifti_hdr,
3564
+ cifti_hdr=theinputdata.cifti_hdr,
3532
3565
  )
3533
3566
  del meanvalue
3534
3567
 
@@ -3564,22 +3597,21 @@ def rapidtide_main(argparsingfunc):
3564
3597
  nativespaceshape,
3565
3598
  theheader,
3566
3599
  bidsbasedict,
3567
- textio=optiondict["textio"],
3568
- fileiscifti=fileiscifti,
3600
+ filetype=theinputdata.filetype,
3569
3601
  rt_floattype=rt_floattype,
3570
- cifti_hdr=cifti_hdr,
3602
+ cifti_hdr=theinputdata.cifti_hdr,
3571
3603
  )
3572
3604
  del masklist
3573
3605
 
3574
- if (optiondict["passes"] > 1 or optiondict["globalpreselect"]) and optiondict[
3606
+ if (optiondict["passes"] > 1 or optiondict["initregressorpreselect"]) and optiondict[
3575
3607
  "refinestopreason"
3576
3608
  ] != "emptymask":
3577
3609
  refinemask = theRegressorRefiner.getrefinemask()
3578
- if optiondict["globalpreselect"]:
3610
+ if optiondict["initregressorpreselect"]:
3579
3611
  masklist = [
3580
3612
  (
3581
3613
  refinemask,
3582
- "globalmeanpreselect",
3614
+ "initregressorpreselect",
3583
3615
  "mask",
3584
3616
  None,
3585
3617
  "I really don't know what this file is for",
@@ -3594,10 +3626,9 @@ def rapidtide_main(argparsingfunc):
3594
3626
  nativespaceshape,
3595
3627
  theheader,
3596
3628
  bidsbasedict,
3597
- textio=optiondict["textio"],
3598
- fileiscifti=fileiscifti,
3629
+ filetype=theinputdata.filetype,
3599
3630
  rt_floattype=rt_floattype,
3600
- cifti_hdr=cifti_hdr,
3631
+ cifti_hdr=theinputdata.cifti_hdr,
3601
3632
  )
3602
3633
  del refinemask
3603
3634
 
@@ -3609,21 +3640,11 @@ def rapidtide_main(argparsingfunc):
3609
3640
  del fitmask
3610
3641
 
3611
3642
  # now do the 4D maps of the similarity function and friends
3612
- if not optiondict["textio"]:
3613
- theheader = copy.deepcopy(nim_hdr)
3614
- theheader["toffset"] = corrscale[corrorigin - lagmininpts]
3615
- if fileiscifti:
3616
- timeindex = theheader["dim"][0] - 1
3617
- spaceindex = theheader["dim"][0]
3618
- theheader["dim"][timeindex] = np.shape(outcorrarray)[1]
3619
- theheader["dim"][spaceindex] = numspatiallocs
3620
- else:
3621
- theheader["dim"][4] = np.shape(outcorrarray)[1]
3622
- theheader["pixdim"][4] = corrtr
3623
- else:
3624
- theheader = None
3625
- cifti_hdr = None
3626
-
3643
+ theheader = theinputdata.copyheader(
3644
+ numtimepoints=np.shape(outcorrarray)[1],
3645
+ tr=corrtr,
3646
+ toffset=(corrscale[corrorigin - lagmininpts]),
3647
+ )
3627
3648
  if (
3628
3649
  optiondict["savecorrout"]
3629
3650
  or (optiondict["outputlevel"] != "min")
@@ -3650,10 +3671,9 @@ def rapidtide_main(argparsingfunc):
3650
3671
  nativecorrshape,
3651
3672
  theheader,
3652
3673
  bidsbasedict,
3653
- textio=optiondict["textio"],
3654
- fileiscifti=fileiscifti,
3674
+ filetype=theinputdata.filetype,
3655
3675
  rt_floattype=rt_floattype,
3656
- cifti_hdr=cifti_hdr,
3676
+ cifti_hdr=theinputdata.cifti_hdr,
3657
3677
  )
3658
3678
  del windowout
3659
3679
  del gaussout
@@ -3668,20 +3688,7 @@ def rapidtide_main(argparsingfunc):
3668
3688
  # now save all the files that are of the same length as the input data file and masked
3669
3689
  if outfmriarray is None:
3670
3690
  outfmriarray = np.zeros(internalfmrishape, dtype=rt_floattype)
3671
- if not optiondict["textio"]:
3672
- theheader = copy.deepcopy(nim_hdr)
3673
- if fileiscifti:
3674
- timeindex = theheader["dim"][0] - 1
3675
- spaceindex = theheader["dim"][0]
3676
- theheader["dim"][timeindex] = np.shape(outfmriarray)[1]
3677
- theheader["dim"][spaceindex] = numspatiallocs
3678
- else:
3679
- theheader["dim"][4] = np.shape(outfmriarray)[1]
3680
- theheader["pixdim"][4] = fmritr
3681
- else:
3682
- theheader = None
3683
- cifti_hdr = None
3684
-
3691
+ theheader = theinputdata.copyheader(numtimepoints=np.shape(outfmriarray)[1], tr=fmritr)
3685
3692
  maplist = []
3686
3693
  if optiondict["saveallsLFOfiltfiles"] and (
3687
3694
  optiondict["dolinfitfilt"] or optiondict["docvrmap"]
@@ -3775,10 +3782,9 @@ def rapidtide_main(argparsingfunc):
3775
3782
  nativefmrishape,
3776
3783
  theheader,
3777
3784
  bidsbasedict,
3778
- textio=optiondict["textio"],
3779
- fileiscifti=fileiscifti,
3785
+ filetype=theinputdata.filetype,
3780
3786
  rt_floattype=rt_floattype,
3781
- cifti_hdr=cifti_hdr,
3787
+ cifti_hdr=theinputdata.cifti_hdr,
3782
3788
  )
3783
3789
 
3784
3790
  # clean up