rapidtide 3.0.7.1__py3-none-any.whl → 3.0.8__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 (50) hide show
  1. rapidtide/_version.py +3 -3
  2. rapidtide/calcnullsimfunc.py +1 -3
  3. rapidtide/data/examples/src/test_findmaxlag.py +1 -1
  4. rapidtide/data/examples/src/testfmri +22 -16
  5. rapidtide/data/examples/src/testnewrefine +0 -23
  6. rapidtide/fMRIData_class.py +29 -52
  7. rapidtide/fit.py +4 -4
  8. rapidtide/happy_supportfuncs.py +1 -1
  9. rapidtide/helper_classes.py +0 -1099
  10. rapidtide/linfitfiltpass.py +59 -0
  11. rapidtide/makelaggedtcs.py +10 -0
  12. rapidtide/refinedelay.py +10 -19
  13. rapidtide/simFuncClasses.py +1132 -0
  14. rapidtide/simfuncfit.py +30 -30
  15. rapidtide/stats.py +5 -2
  16. rapidtide/tests/.coveragerc +6 -0
  17. rapidtide/tests/cleanposttest +1 -1
  18. rapidtide/tests/runlocaltest +2 -2
  19. rapidtide/tests/test_cleanregressor.py +3 -3
  20. rapidtide/tests/test_congrid.py +1 -1
  21. rapidtide/tests/test_corrpass.py +3 -3
  22. rapidtide/tests/test_delayestimation.py +8 -7
  23. rapidtide/tests/test_findmaxlag.py +2 -2
  24. rapidtide/tests/test_fullrunrapidtide_v3.py +2 -1
  25. rapidtide/tests/test_getparsers.py +14 -6
  26. rapidtide/tests/test_io.py +2 -6
  27. rapidtide/tests/test_nullcorr.py +3 -3
  28. rapidtide/tests/test_refinedelay.py +20 -5
  29. rapidtide/tidepoolTemplate_alt.py +1 -1
  30. rapidtide/util.py +7 -0
  31. rapidtide/voxelData.py +3 -6
  32. rapidtide/workflows/cleanregressor.py +2 -2
  33. rapidtide/workflows/delayvar.py +44 -58
  34. rapidtide/workflows/{delayestimation.py → estimateDelayMap.py} +84 -31
  35. rapidtide/workflows/rapidtide.py +349 -859
  36. rapidtide/workflows/rapidtide_parser.py +5 -38
  37. rapidtide/workflows/refineDelayMap.py +138 -0
  38. rapidtide/{RegressorRefiner.py → workflows/refineRegressor.py} +200 -28
  39. rapidtide/workflows/regressfrommaps.py +35 -27
  40. rapidtide/workflows/retrolagtcs.py +5 -6
  41. rapidtide/workflows/retroregress.py +73 -191
  42. rapidtide/workflows/showarbcorr.py +2 -2
  43. rapidtide/workflows/showxcorrx.py +5 -5
  44. rapidtide/workflows/tidepool.py +5 -5
  45. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/METADATA +2 -2
  46. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/RECORD +50 -48
  47. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/WHEEL +0 -0
  48. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/entry_points.txt +0 -0
  49. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/licenses/LICENSE +0 -0
  50. {rapidtide-3.0.7.1.dist-info → rapidtide-3.0.8.dist-info}/top_level.txt +0 -0
@@ -25,7 +25,6 @@ import warnings
25
25
  from pathlib import Path
26
26
 
27
27
  import numpy as np
28
- from scipy import ndimage
29
28
  from scipy.stats import rankdata
30
29
 
31
30
  import rapidtide.calccoherence as tide_calccoherence
@@ -40,17 +39,16 @@ import rapidtide.linfitfiltpass as tide_linfitfiltpass
40
39
  import rapidtide.maskutil as tide_mask
41
40
  import rapidtide.miscmath as tide_math
42
41
  import rapidtide.multiproc as tide_multiproc
43
- import rapidtide.patchmatch as tide_patch
44
- import rapidtide.peakeval as tide_peakeval
45
- import rapidtide.refinedelay as tide_refinedelay
46
- import rapidtide.RegressorRefiner as tide_regrefiner
47
42
  import rapidtide.resample as tide_resample
48
- import rapidtide.simfuncfit as tide_simfuncfit
43
+ import rapidtide.simFuncClasses as tide_simFuncClasses
49
44
  import rapidtide.stats as tide_stats
50
45
  import rapidtide.util as tide_util
51
46
  import rapidtide.voxelData as tide_voxelData
52
47
  import rapidtide.wiener as tide_wiener
53
48
  import rapidtide.workflows.cleanregressor as tide_cleanregressor
49
+ import rapidtide.workflows.estimateDelayMap as tide_estimateDelayMap
50
+ import rapidtide.workflows.refineDelayMap as tide_refineDelayMap
51
+ import rapidtide.workflows.refineRegressor as tide_refineRegressor
54
52
  import rapidtide.workflows.regressfrommaps as tide_regressfrommaps
55
53
 
56
54
  from .utils import setup_logger
@@ -117,8 +115,8 @@ def echocancel(thetimecourse, echooffset, thetimestep, outputname, padtimepoints
117
115
 
118
116
 
119
117
  def rapidtide_main(argparsingfunc):
120
- threaddebug = False
121
118
  optiondict, theprefilter = argparsingfunc
119
+ optiondict["threaddebug"] = False
122
120
 
123
121
  optiondict["nodename"] = platform.node()
124
122
 
@@ -277,7 +275,7 @@ def rapidtide_main(argparsingfunc):
277
275
  mklmaxthreads = mkl.get_max_threads()
278
276
  if not (1 <= optiondict["mklthreads"] <= mklmaxthreads):
279
277
  optiondict["mklthreads"] = mklmaxthreads
280
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
278
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
281
279
  LGR.info(f"using {optiondict['mklthreads']} MKL threads")
282
280
 
283
281
  # Generate MemoryLGR output file with column names
@@ -298,15 +296,6 @@ def rapidtide_main(argparsingfunc):
298
296
  nativespaceshape = theinputdata.nativespaceshape
299
297
  fmritr = theinputdata.timestep
300
298
  optiondict["filetype"] = theinputdata.filetype
301
- if theinputdata.filetype == "cifti":
302
- fileiscifti = True
303
- optiondict["textio"] = False
304
- elif theinputdata.filetype == "text":
305
- fileiscifti = False
306
- optiondict["textio"] = True
307
- else:
308
- fileiscifti = False
309
- optiondict["textio"] = False
310
299
 
311
300
  # check to see if we need to adjust the oversample factor
312
301
  if optiondict["oversampfactor"] < 0:
@@ -700,7 +689,7 @@ def rapidtide_main(argparsingfunc):
700
689
  print(f"{fmritr=}")
701
690
  print(f"{validstart=}")
702
691
  print(f"{validend=}")
703
- tide_util.disablemkl(optiondict["nprocs_confoundregress"], debug=threaddebug)
692
+ tide_util.disablemkl(optiondict["nprocs_confoundregress"], debug=optiondict["threaddebug"])
704
693
  (
705
694
  mergedregressors,
706
695
  mergedregressorlabels,
@@ -717,7 +706,7 @@ def rapidtide_main(argparsingfunc):
717
706
  orthogonalize=optiondict["orthogonalize"],
718
707
  showprogressbar=optiondict["showprogressbar"],
719
708
  )
720
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
709
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
721
710
  if confoundr2 is None:
722
711
  print("There are no nonzero confound regressors - exiting")
723
712
  sys.exit()
@@ -1255,7 +1244,7 @@ def rapidtide_main(argparsingfunc):
1255
1244
  # Set up for the delay finding/refinement passes
1256
1245
  ####################################################
1257
1246
  # initialize the Correlator
1258
- theCorrelator = tide_classes.Correlator(
1247
+ theCorrelator = tide_simFuncClasses.Correlator(
1259
1248
  Fs=oversampfreq,
1260
1249
  ncprefilter=theprefilter,
1261
1250
  negativegradient=optiondict["negativegradient"],
@@ -1288,7 +1277,7 @@ def rapidtide_main(argparsingfunc):
1288
1277
  dummy, trimmedcorrscale, dummy = theCorrelator.getfunction()
1289
1278
 
1290
1279
  # initialize the MutualInformationator
1291
- theMutualInformationator = tide_classes.MutualInformationator(
1280
+ theMutualInformationator = tide_simFuncClasses.MutualInformationator(
1292
1281
  Fs=oversampfreq,
1293
1282
  smoothingtime=optiondict["smoothingtime"],
1294
1283
  ncprefilter=theprefilter,
@@ -1383,26 +1372,35 @@ def rapidtide_main(argparsingfunc):
1383
1372
  LGR.debug(
1384
1373
  f"allocating memory for correlation arrays {internalcorrshape} {internalvalidcorrshape}"
1385
1374
  )
1375
+ corrout, corrout_shm = tide_util.allocarray(
1376
+ internalvalidcorrshape,
1377
+ rt_floatset,
1378
+ shared=optiondict["sharedmem"],
1379
+ name=f"corrout_{optiondict['pid']}",
1380
+ )
1381
+ gaussout, gaussout_shm = tide_util.allocarray(
1382
+ internalvalidcorrshape,
1383
+ rt_floatset,
1384
+ shared=optiondict["sharedmem"],
1385
+ name=f"gaussout_{optiondict['pid']}",
1386
+ )
1387
+ windowout, windowout_shm = tide_util.allocarray(
1388
+ internalvalidcorrshape,
1389
+ rt_floatset,
1390
+ shared=optiondict["sharedmem"],
1391
+ name=f"windowout_{optiondict['pid']}",
1392
+ )
1393
+ outcorrarray, outcorrarray_shm = tide_util.allocarray(
1394
+ internalcorrshape,
1395
+ rt_floatset,
1396
+ shared=optiondict["sharedmem"],
1397
+ name=f"outcorrarray_{optiondict['pid']}",
1398
+ )
1386
1399
  if optiondict["sharedmem"]:
1387
- corrout, corrout_shm = tide_util.allocshared(
1388
- internalvalidcorrshape, rt_floatset, name=f"corrout_{optiondict['pid']}"
1389
- )
1390
- gaussout, gaussout_shm = tide_util.allocshared(
1391
- internalvalidcorrshape, rt_floatset, name=f"gaussout_{optiondict['pid']}"
1392
- )
1393
- windowout, windowout_shm = tide_util.allocshared(
1394
- internalvalidcorrshape, rt_floatset, name=f"windowout_{optiondict['pid']}"
1395
- )
1396
- outcorrarray, outcorrarray_shm = tide_util.allocshared(
1397
- internalcorrshape, rt_floatset, name=f"outcorrarray_{optiondict['pid']}"
1398
- )
1399
1400
  ramlocation = "in shared memory"
1400
1401
  else:
1401
- corrout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1402
- gaussout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1403
- windowout = np.zeros(internalvalidcorrshape, dtype=rt_floattype)
1404
- outcorrarray = np.zeros(internalcorrshape, dtype=rt_floattype)
1405
1402
  ramlocation = "locally"
1403
+
1406
1404
  optiondict["totalcorrelationbytes"] = (
1407
1405
  corrout.nbytes + gaussout.nbytes + windowout.nbytes + outcorrarray.nbytes
1408
1406
  )
@@ -1466,6 +1464,69 @@ def rapidtide_main(argparsingfunc):
1466
1464
  2 * numpadtrs + np.shape(initial_fmri_x)[0],
1467
1465
  )
1468
1466
 
1467
+ # now do the arrays for delay refinement
1468
+ if optiondict["dolinfitfilt"] or optiondict["docvrmap"] or optiondict["refinedelay"]:
1469
+ if optiondict["refinedelay"]:
1470
+ derivaxissize = np.max([2, optiondict["regressderivs"] + 1])
1471
+ else:
1472
+ derivaxissize = optiondict["regressderivs"] + 1
1473
+ internalvalidspaceshapederivs = (
1474
+ internalvalidspaceshape,
1475
+ derivaxissize,
1476
+ )
1477
+ sLFOfitmean, sLFOfitmean_shm = tide_util.allocarray(
1478
+ internalvalidspaceshape,
1479
+ rt_outfloattype,
1480
+ shared=optiondict["sharedmem"],
1481
+ name=f"sLFOfitmean_{optiondict['pid']}",
1482
+ )
1483
+ rvalue, rvalue_shm = tide_util.allocarray(
1484
+ internalvalidspaceshape,
1485
+ rt_outfloattype,
1486
+ shared=optiondict["sharedmem"],
1487
+ name=f"rvalue_{optiondict['pid']}",
1488
+ )
1489
+ r2value, r2value_shm = tide_util.allocarray(
1490
+ internalvalidspaceshape,
1491
+ rt_outfloattype,
1492
+ shared=optiondict["sharedmem"],
1493
+ name=f"r2value_{optiondict['pid']}",
1494
+ )
1495
+ fitNorm, fitNorm_shm = tide_util.allocarray(
1496
+ internalvalidspaceshapederivs,
1497
+ rt_outfloattype,
1498
+ shared=optiondict["sharedmem"],
1499
+ name=f"fitNorm_{optiondict['pid']}",
1500
+ )
1501
+ fitcoeff, fitcoeff_shm = tide_util.allocarray(
1502
+ internalvalidspaceshapederivs,
1503
+ rt_outfloattype,
1504
+ shared=optiondict["sharedmem"],
1505
+ name=f"fitcoeff_{optiondict['pid']}",
1506
+ )
1507
+ lagtc, lagtc_shm = tide_util.allocarray(
1508
+ internalvalidfmrishape,
1509
+ rt_floattype,
1510
+ shared=optiondict["sharedmem"],
1511
+ name=f"lagtc_{optiondict['pid']}",
1512
+ )
1513
+ if optiondict["sharedmem"]:
1514
+ ramlocation = "in shared memory"
1515
+ else:
1516
+ ramlocation = "locally"
1517
+
1518
+ optiondict["totalRefineDelaybytes"] = (
1519
+ sLFOfitmean.nbytes
1520
+ + rvalue.nbytes
1521
+ + r2value.nbytes
1522
+ + fitNorm.nbytes
1523
+ + fitcoeff.nbytes
1524
+ + lagtc.nbytes
1525
+ )
1526
+ thesize, theunit = tide_util.format_bytes(optiondict["totalRefineDelaybytes"])
1527
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for delay refinement")
1528
+ tide_util.logmem("after derivative delay/sLFO filter array allocation")
1529
+
1469
1530
  # prepare for regressor refinement, if we're doing it
1470
1531
  if (
1471
1532
  optiondict["passes"] > 1
@@ -1474,7 +1535,7 @@ def rapidtide_main(argparsingfunc):
1474
1535
  or optiondict["convergencethresh"] is not None
1475
1536
  ):
1476
1537
  # we will be doing regressor refinement, so configure the refiner
1477
- theRegressorRefiner = tide_regrefiner.RegressorRefiner(
1538
+ theRegressorRefiner = tide_refineRegressor.RegressorRefiner(
1478
1539
  internalvalidfmrishape,
1479
1540
  internalvalidpaddedfmrishape,
1480
1541
  optiondict["pid"],
@@ -1523,7 +1584,7 @@ def rapidtide_main(argparsingfunc):
1523
1584
  LGR.verbose(f"edgebufferfrac set to {optiondict['edgebufferfrac']}")
1524
1585
 
1525
1586
  # initialize the correlation fitter
1526
- theFitter = tide_classes.SimilarityFunctionFitter(
1587
+ theFitter = tide_simFuncClasses.SimilarityFunctionFitter(
1527
1588
  lagmod=optiondict["lagmod"],
1528
1589
  lthreshval=optiondict["lthreshval"],
1529
1590
  uthreshval=optiondict["uthreshval"],
@@ -1551,7 +1612,7 @@ def rapidtide_main(argparsingfunc):
1551
1612
  windowfunc=optiondict["windowfunc"],
1552
1613
  )
1553
1614
 
1554
- tide_util.disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
1615
+ tide_util.disablemkl(optiondict["nprocs_calcsimilarity"], debug=optiondict["threaddebug"])
1555
1616
  (
1556
1617
  voxelsprocessed_echo,
1557
1618
  theglobalmaxlist,
@@ -1575,7 +1636,7 @@ def rapidtide_main(argparsingfunc):
1575
1636
  rt_floatset=rt_floatset,
1576
1637
  rt_floattype=rt_floattype,
1577
1638
  )
1578
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
1639
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
1579
1640
 
1580
1641
  for i in range(len(theglobalmaxlist)):
1581
1642
  theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
@@ -1730,7 +1791,7 @@ def rapidtide_main(argparsingfunc):
1730
1791
  theSimFunc = theMutualInformationator
1731
1792
  else:
1732
1793
  theSimFunc = theCorrelator
1733
- tide_util.disablemkl(optiondict["nprocs_getNullDist"], debug=threaddebug)
1794
+ tide_util.disablemkl(optiondict["nprocs_getNullDist"], debug=optiondict["threaddebug"])
1734
1795
  simdistdata = tide_nullsimfunc.getNullDistributionData(
1735
1796
  oversampfreq,
1736
1797
  theSimFunc,
@@ -1745,7 +1806,7 @@ def rapidtide_main(argparsingfunc):
1745
1806
  rt_floatset=np.float64,
1746
1807
  rt_floattype="float64",
1747
1808
  )
1748
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
1809
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
1749
1810
 
1750
1811
  tide_io.writebidstsv(
1751
1812
  f"{outputname}_desc-simdistdata_info",
@@ -1785,6 +1846,8 @@ def rapidtide_main(argparsingfunc):
1785
1846
  twotail=optiondict["bipolar"],
1786
1847
  nozero=optiondict["nohistzero"],
1787
1848
  )
1849
+ if sigfit is None:
1850
+ optiondict["ampthreshfromsig"] = False
1788
1851
  if pcts is not None:
1789
1852
  for i in range(len(thepvalnames)):
1790
1853
  optiondict[
@@ -1840,455 +1903,108 @@ def rapidtide_main(argparsingfunc):
1840
1903
  optiondict["currentstage"] = f"precorrelation_pass{thepass}"
1841
1904
  tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
1842
1905
 
1843
- # tide_delayestimate.estimateDelay(
1844
- # fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1845
- # initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
1846
- # os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
1847
- # theMutualInformationator,
1848
- # thepass,
1849
- # )
1850
- ########################
1851
- # Delay estimation start
1852
- ########################
1853
- # Step 1 - Correlation step
1854
- if optiondict["similaritymetric"] == "mutualinfo":
1855
- similaritytype = "Mutual information"
1856
- elif optiondict["similaritymetric"] == "correlation":
1857
- similaritytype = "Correlation"
1858
- else:
1859
- similaritytype = "MI enhanced correlation"
1860
- LGR.info(f"\n\n{similaritytype} calculation, pass {thepass}")
1861
- TimingLGR.info(f"{similaritytype} calculation start, pass {thepass}")
1862
-
1863
- tide_util.disablemkl(optiondict["nprocs_calcsimilarity"], debug=threaddebug)
1864
- if optiondict["similaritymetric"] == "mutualinfo":
1865
- theMutualInformationator.setlimits(lagmininpts, lagmaxinpts)
1866
- (
1867
- voxelsprocessed_cp,
1868
- theglobalmaxlist,
1869
- trimmedcorrscale,
1870
- ) = tide_calcsimfunc.correlationpass(
1871
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1872
- cleaned_referencetc,
1873
- theMutualInformationator,
1874
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
1875
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
1876
- lagmininpts,
1877
- lagmaxinpts,
1878
- corrout,
1879
- meanval,
1880
- nprocs=optiondict["nprocs_calcsimilarity"],
1881
- alwaysmultiproc=optiondict["alwaysmultiproc"],
1882
- oversampfactor=optiondict["oversampfactor"],
1883
- interptype=optiondict["interptype"],
1884
- showprogressbar=optiondict["showprogressbar"],
1885
- chunksize=optiondict["mp_chunksize"],
1886
- rt_floatset=rt_floatset,
1887
- rt_floattype=rt_floattype,
1888
- debug=optiondict["focaldebug"],
1889
- )
1890
- else:
1891
- (
1892
- voxelsprocessed_cp,
1893
- theglobalmaxlist,
1894
- trimmedcorrscale,
1895
- ) = tide_calcsimfunc.correlationpass(
1896
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1897
- cleaned_referencetc,
1898
- theCorrelator,
1899
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
1900
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
1901
- lagmininpts,
1902
- lagmaxinpts,
1903
- corrout,
1904
- meanval,
1905
- nprocs=optiondict["nprocs_calcsimilarity"],
1906
- alwaysmultiproc=optiondict["alwaysmultiproc"],
1907
- oversampfactor=optiondict["oversampfactor"],
1908
- interptype=optiondict["interptype"],
1909
- showprogressbar=optiondict["showprogressbar"],
1910
- chunksize=optiondict["mp_chunksize"],
1911
- rt_floatset=rt_floatset,
1912
- rt_floattype=rt_floattype,
1913
- debug=optiondict["focaldebug"],
1914
- )
1915
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
1916
-
1917
- for i in range(len(theglobalmaxlist)):
1918
- theglobalmaxlist[i] = corrscale[theglobalmaxlist[i]] - optiondict["simcalcoffset"]
1919
- namesuffix = "_desc-globallag_hist"
1920
- tide_stats.makeandsavehistogram(
1921
- np.asarray(theglobalmaxlist),
1922
- len(corrscale),
1923
- 0,
1924
- outputname + namesuffix,
1925
- displaytitle="Histogram of lag times from global lag calculation",
1926
- therange=(corrscale[0], corrscale[-1]),
1927
- refine=False,
1928
- dictvarname="globallaghist_pass" + str(thepass),
1929
- append=(optiondict["echocancel"] or (thepass > 1)),
1930
- thedict=optiondict,
1931
- )
1932
-
1933
- if optiondict["checkpoint"]:
1934
- outcorrarray[:, :] = 0.0
1935
- outcorrarray[validvoxels, :] = corrout[:, :]
1936
- if theinputdata.filetype == "text":
1937
- tide_io.writenpvecs(
1938
- outcorrarray.reshape(nativecorrshape),
1939
- f"{outputname}_corrout_prefit_pass" + str(thepass) + ".txt",
1940
- )
1941
- else:
1942
- savename = f"{outputname}_desc-corroutprefit_pass-" + str(thepass)
1943
- tide_io.savetonifti(outcorrarray.reshape(nativecorrshape), theheader, savename)
1944
-
1945
- TimingLGR.info(
1946
- f"{similaritytype} calculation end, pass {thepass}",
1947
- {
1948
- "message2": voxelsprocessed_cp,
1949
- "message3": "voxels",
1950
- },
1951
- )
1952
-
1953
- # Step 1b. Do a peak prefit
1954
- if optiondict["similaritymetric"] == "hybrid":
1955
- LGR.info(f"\n\nPeak prefit calculation, pass {thepass}")
1956
- TimingLGR.info(f"Peak prefit calculation start, pass {thepass}")
1957
-
1958
- tide_util.disablemkl(optiondict["nprocs_peakeval"], debug=threaddebug)
1959
- voxelsprocessed_pe, thepeakdict = tide_peakeval.peakevalpass(
1960
- fmri_data_valid[:, validsimcalcstart : validsimcalcend + 1],
1961
- cleaned_referencetc,
1962
- initial_fmri_x[validsimcalcstart : validsimcalcend + 1],
1963
- os_fmri_x[osvalidsimcalcstart : osvalidsimcalcend + 1],
1964
- theMutualInformationator,
1965
- trimmedcorrscale,
1966
- corrout,
1967
- nprocs=optiondict["nprocs_peakeval"],
1968
- alwaysmultiproc=optiondict["alwaysmultiproc"],
1969
- bipolar=optiondict["bipolar"],
1970
- oversampfactor=optiondict["oversampfactor"],
1971
- interptype=optiondict["interptype"],
1972
- showprogressbar=optiondict["showprogressbar"],
1973
- chunksize=optiondict["mp_chunksize"],
1974
- rt_floatset=rt_floatset,
1975
- rt_floattype=rt_floattype,
1976
- )
1977
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
1978
-
1979
- TimingLGR.info(
1980
- f"Peak prefit end, pass {thepass}",
1981
- {
1982
- "message2": voxelsprocessed_pe,
1983
- "message3": "voxels",
1984
- },
1985
- )
1986
- mipeaks = lagtimes * 0.0
1987
- for i in range(numvalidspatiallocs):
1988
- if len(thepeakdict[str(i)]) > 0:
1989
- mipeaks[i] = thepeakdict[str(i)][0][0]
1990
- else:
1991
- thepeakdict = None
1992
-
1993
- # Step 2 - similarity function fitting and time lag estimation
1994
- # write out the current version of the run options
1995
- optiondict["currentstage"] = f"presimfuncfit_pass{thepass}"
1996
- tide_io.writedicttojson(optiondict, f"{outputname}_desc-runoptions_info.json")
1997
- LGR.info(f"\n\nTime lag estimation pass {thepass}")
1998
- TimingLGR.info(f"Time lag estimation start, pass {thepass}")
1999
-
2000
- theFitter.setfunctype(optiondict["similaritymetric"])
2001
- theFitter.setcorrtimeaxis(trimmedcorrscale)
2002
-
2003
- # use initial lags if this is a hybrid fit
2004
- if optiondict["similaritymetric"] == "hybrid" and thepeakdict is not None:
2005
- initlags = mipeaks
2006
- else:
2007
- initlags = None
2008
-
2009
- tide_util.disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2010
- voxelsprocessed_fc = tide_simfuncfit.fitcorr(
2011
- trimmedcorrscale,
2012
- theFitter,
1906
+ # step 1 - do the initial delay estimation
1907
+ internaldespeckleincludemask = tide_estimateDelayMap.estimateDelay(
1908
+ fmri_data_valid,
1909
+ validsimcalcstart,
1910
+ validsimcalcend,
1911
+ osvalidsimcalcstart,
1912
+ osvalidsimcalcend,
1913
+ initial_fmri_x,
1914
+ os_fmri_x,
1915
+ theCorrelator,
1916
+ theMutualInformationator,
1917
+ cleaned_referencetc,
2013
1918
  corrout,
1919
+ meanval,
1920
+ corrscale,
1921
+ outputname,
1922
+ outcorrarray,
1923
+ validvoxels,
1924
+ nativecorrshape,
1925
+ nativespaceshape,
1926
+ bidsbasedict,
1927
+ numspatiallocs,
1928
+ gaussout,
1929
+ theinitialdelay,
1930
+ windowout,
1931
+ R2,
1932
+ thesizes,
1933
+ internalspaceshape,
1934
+ numvalidspatiallocs,
1935
+ theinputdata,
1936
+ theheader,
1937
+ theFitter,
2014
1938
  fitmask,
2015
- failreason,
2016
1939
  lagtimes,
2017
1940
  lagstrengths,
2018
1941
  lagsigma,
2019
- gaussout,
2020
- windowout,
2021
- R2,
2022
- despeckling=False,
2023
- peakdict=thepeakdict,
2024
- nprocs=optiondict["nprocs_fitcorr"],
2025
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2026
- fixdelay=optiondict["fixdelay"],
2027
- initialdelayvalue=theinitialdelay,
2028
- showprogressbar=optiondict["showprogressbar"],
2029
- chunksize=optiondict["mp_chunksize"],
2030
- despeckle_thresh=optiondict["despeckle_thresh"],
2031
- initiallags=initlags,
2032
- rt_floatset=rt_floatset,
2033
- rt_floattype=rt_floattype,
1942
+ failreason,
1943
+ outmaparray,
1944
+ lagmininpts,
1945
+ lagmaxinpts,
1946
+ thepass,
1947
+ optiondict,
1948
+ LGR,
1949
+ TimingLGR,
1950
+ rt_floatset=np.float64,
1951
+ rt_floattype="float64",
2034
1952
  )
2035
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
2036
1953
 
2037
- TimingLGR.info(
2038
- f"Time lag estimation end, pass {thepass}",
2039
- {
2040
- "message2": voxelsprocessed_fc,
2041
- "message3": "voxels",
2042
- },
2043
- )
1954
+ # refine delay
1955
+ if optiondict["refinedelayeachpass"]:
1956
+ if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
1957
+ # set gausssigma automatically
1958
+ optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
2044
1959
 
2045
- # Step 2b - Correlation time despeckle
2046
- if optiondict["despeckle_passes"] > 0:
2047
- LGR.info(f"\n\n{similaritytype} despeckling pass {thepass}")
2048
- LGR.info(f"\tUsing despeckle_thresh = {optiondict['despeckle_thresh']:.3f}")
2049
- TimingLGR.info(f"{similaritytype} despeckle start, pass {thepass}")
2050
-
2051
- # find lags that are very different from their neighbors, and refit starting at the median lag for the point
2052
- voxelsprocessed_fc_ds = 0
2053
- despecklingdone = False
2054
- lastnumdespeckled = 1000000
2055
- for despecklepass in range(optiondict["despeckle_passes"]):
2056
- LGR.info(f"\n\n{similaritytype} despeckling subpass {despecklepass + 1}")
2057
- outmaparray *= 0.0
2058
- outmaparray[validvoxels] = eval("lagtimes")[:]
2059
-
2060
- # find voxels to despeckle
2061
- medianlags = ndimage.median_filter(
2062
- outmaparray.reshape(nativespaceshape), 3
2063
- ).reshape(numspatiallocs)
2064
- # voxels that we're happy with have initlags set to -1000000.0
2065
- initlags = np.where(
2066
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2067
- medianlags,
2068
- -1000000.0,
2069
- )[validvoxels]
2070
-
2071
- if len(initlags) > 0:
2072
- numdespeckled = len(np.where(initlags != -1000000.0)[0])
2073
- if lastnumdespeckled > numdespeckled > 0:
2074
- lastnumdespeckled = numdespeckled
2075
- tide_util.disablemkl(optiondict["nprocs_fitcorr"], debug=threaddebug)
2076
- voxelsprocessed_thispass = tide_simfuncfit.fitcorr(
2077
- trimmedcorrscale,
2078
- theFitter,
2079
- corrout,
2080
- fitmask,
2081
- failreason,
2082
- lagtimes,
2083
- lagstrengths,
2084
- lagsigma,
2085
- gaussout,
2086
- windowout,
2087
- R2,
2088
- despeckling=True,
2089
- peakdict=thepeakdict,
2090
- nprocs=optiondict["nprocs_fitcorr"],
2091
- alwaysmultiproc=optiondict["alwaysmultiproc"],
2092
- fixdelay=optiondict["fixdelay"],
2093
- initialdelayvalue=theinitialdelay,
2094
- showprogressbar=optiondict["showprogressbar"],
2095
- chunksize=optiondict["mp_chunksize"],
2096
- despeckle_thresh=optiondict["despeckle_thresh"],
2097
- initiallags=initlags,
2098
- rt_floatset=rt_floatset,
2099
- rt_floattype=rt_floattype,
2100
- )
2101
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
2102
-
2103
- voxelsprocessed_fc_ds += voxelsprocessed_thispass
2104
- optiondict[
2105
- "despecklemasksize_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2106
- ] = voxelsprocessed_thispass
2107
- optiondict[
2108
- "despecklemaskpct_pass" + str(thepass) + "_d" + str(despecklepass + 1)
2109
- ] = (100.0 * voxelsprocessed_thispass / optiondict["corrmasksize"])
2110
- else:
2111
- despecklingdone = True
2112
- else:
2113
- despecklingdone = True
2114
- if despecklingdone:
2115
- LGR.info("Nothing left to do! Terminating despeckling")
2116
- break
2117
-
2118
- internaldespeckleincludemask = np.where(
2119
- np.abs(outmaparray - medianlags) > optiondict["despeckle_thresh"],
2120
- medianlags,
2121
- 0.0,
2122
- )
2123
- if optiondict["savedespecklemasks"] and (optiondict["despeckle_passes"] > 0):
2124
- despecklesavemask = np.where(
2125
- internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2126
- )
2127
- if thepass == optiondict["passes"]:
2128
- if theinputdata.filetype != "text":
2129
- if theinputdata.filetype == "cifti":
2130
- timeindex = theheader["dim"][0] - 1
2131
- spaceindex = theheader["dim"][0]
2132
- theheader["dim"][timeindex] = 1
2133
- theheader["dim"][spaceindex] = numspatiallocs
2134
- else:
2135
- theheader["dim"][0] = 3
2136
- theheader["dim"][4] = 1
2137
- theheader["pixdim"][4] = 1.0
2138
- masklist = [
2139
- (
2140
- despecklesavemask,
2141
- "despeckle",
2142
- "mask",
2143
- None,
2144
- "Voxels that underwent despeckling in the final pass",
2145
- )
2146
- ]
2147
- tide_io.savemaplist(
2148
- outputname,
2149
- masklist,
2150
- validvoxels,
2151
- nativespaceshape,
2152
- theheader,
2153
- bidsbasedict,
2154
- filetype=theinputdata.filetype,
2155
- rt_floattype=rt_floattype,
2156
- cifti_hdr=theinputdata.cifti_hdr,
2157
- )
2158
- LGR.info(
2159
- f"\n\n{voxelsprocessed_fc_ds} voxels despeckled in "
2160
- f"{optiondict['despeckle_passes']} passes"
2161
- )
2162
- TimingLGR.info(
2163
- f"{similaritytype} despeckle end, pass {thepass}",
2164
- {
2165
- "message2": voxelsprocessed_fc_ds,
2166
- "message3": "voxels",
2167
- },
2168
- )
1960
+ if optiondict["sLFOfiltmask"]:
1961
+ sLFOfiltmask = fitmask + 0.0
1962
+ else:
1963
+ sLFOfiltmask = fitmask * 0.0 + 1.0
2169
1964
 
2170
- # Step 2c - patch shifting
2171
- if optiondict["patchshift"]:
2172
- outmaparray *= 0.0
2173
- outmaparray[validvoxels] = eval("lagtimes")[:]
2174
- # new method
2175
- masklist = [
2176
- (
2177
- outmaparray[validvoxels],
2178
- f"lagtimes_prepatch_pass{thepass}",
2179
- "map",
2180
- None,
2181
- f"Input lagtimes map prior to patch map generation pass {thepass}",
2182
- ),
2183
- ]
2184
- tide_io.savemaplist(
1965
+ optiondict["regressfiltthreshval"] = 0.0
1966
+
1967
+ (
1968
+ delayoffset,
1969
+ regressderivratios,
1970
+ medfiltregressderivratios,
1971
+ filteredregressderivratios,
1972
+ optiondict["delayoffsetMAD"],
1973
+ ) = tide_refineDelayMap.refineDelay(
1974
+ fmri_data_valid,
1975
+ initial_fmri_x,
1976
+ xdim,
1977
+ ydim,
1978
+ slicethickness,
1979
+ sLFOfiltmask,
1980
+ genlagtc,
1981
+ oversamptr,
1982
+ sLFOfitmean,
1983
+ rvalue,
1984
+ r2value,
1985
+ fitNorm,
1986
+ fitcoeff,
1987
+ lagtc,
2185
1988
  outputname,
2186
- masklist,
2187
1989
  validvoxels,
2188
1990
  nativespaceshape,
2189
- theheader,
2190
- bidsbasedict,
2191
- filetype=theinputdata.filetype,
1991
+ theinputdata,
1992
+ lagtimes,
1993
+ optiondict,
1994
+ LGR,
1995
+ TimingLGR,
1996
+ outputlevel=optiondict["outputlevel"],
1997
+ gausssigma=optiondict["delayoffsetgausssigma"],
1998
+ patchthresh=optiondict["delaypatchthresh"],
1999
+ mindelay=optiondict["mindelay"],
2000
+ maxdelay=optiondict["maxdelay"],
2001
+ numpoints=optiondict["numpoints"],
2002
+ histlen=optiondict["histlen"],
2003
+ rt_floatset=rt_floatset,
2192
2004
  rt_floattype=rt_floattype,
2193
- cifti_hdr=theinputdata.cifti_hdr,
2005
+ debug=optiondict["debug"],
2194
2006
  )
2195
-
2196
- # create list of anomalous 3D regions that don't match surroundings
2197
- if theinputdata.nim_affine is not None:
2198
- # make an atlas of anomalous patches - each patch shares the same integer value
2199
- step1 = tide_patch.calc_DoG(
2200
- outmaparray.reshape(nativespaceshape).copy(),
2201
- theinputdata.nim_affine,
2202
- thesizes,
2203
- fwhm=optiondict["patchfwhm"],
2204
- ratioopt=False,
2205
- debug=True,
2206
- )
2207
- masklist = [
2208
- (
2209
- step1.reshape(internalspaceshape)[validvoxels],
2210
- f"DoG_pass{thepass}",
2211
- "map",
2212
- None,
2213
- f"DoG map for pass {thepass}",
2214
- ),
2215
- ]
2216
- tide_io.savemaplist(
2217
- outputname,
2218
- masklist,
2219
- validvoxels,
2220
- nativespaceshape,
2221
- theheader,
2222
- bidsbasedict,
2223
- filetype=theinputdata.filetype,
2224
- rt_floattype=rt_floattype,
2225
- cifti_hdr=theinputdata.cifti_hdr,
2226
- )
2227
- step2 = tide_patch.invertedflood3D(
2228
- step1,
2229
- 1,
2230
- )
2231
- masklist = [
2232
- (
2233
- step2.reshape(internalspaceshape)[validvoxels],
2234
- f"invertflood_pass{thepass}",
2235
- "map",
2236
- None,
2237
- f"Inverted flood map for pass {thepass}",
2238
- ),
2239
- ]
2240
- tide_io.savemaplist(
2241
- outputname,
2242
- masklist,
2243
- validvoxels,
2244
- nativespaceshape,
2245
- theheader,
2246
- bidsbasedict,
2247
- filetype=theinputdata.filetype,
2248
- rt_floattype=rt_floattype,
2249
- cifti_hdr=theinputdata.cifti_hdr,
2250
- )
2251
-
2252
- patchmap = tide_patch.separateclusters(
2253
- step2,
2254
- sizethresh=optiondict["patchminsize"],
2255
- debug=True,
2256
- )
2257
- # patchmap = tide_patch.getclusters(
2258
- # outmaparray.reshape(nativespaceshape),
2259
- # theinputdata.nim_affine,
2260
- # thesizes,
2261
- # fwhm=optiondict["patchfwhm"],
2262
- # ratioopt=True,
2263
- # sizethresh=optiondict["patchminsize"],
2264
- # debug=True,
2265
- # )
2266
- masklist = [
2267
- (
2268
- patchmap[validvoxels],
2269
- f"patch_pass{thepass}",
2270
- "map",
2271
- None,
2272
- f"Patch map for despeckling pass {thepass}",
2273
- ),
2274
- ]
2275
- tide_io.savemaplist(
2276
- outputname,
2277
- masklist,
2278
- validvoxels,
2279
- nativespaceshape,
2280
- theheader,
2281
- bidsbasedict,
2282
- filetype=theinputdata.filetype,
2283
- rt_floattype=rt_floattype,
2284
- cifti_hdr=theinputdata.cifti_hdr,
2285
- )
2286
-
2287
- # now shift the patches to align with the majority of the image
2288
- tide_patch.interppatch(lagtimes, patchmap[validvoxels])
2289
- ########################
2290
- # Delay estimation end
2291
- ########################
2007
+ lagtimes[:] = lagtimes + delayoffset
2292
2008
 
2293
2009
  # Step 2d - make a rank order map
2294
2010
  timepercentile = (
@@ -2332,147 +2048,37 @@ def rapidtide_main(argparsingfunc):
2332
2048
  or optiondict["initregressorpreselect"]
2333
2049
  or optiondict["dofinalrefine"]
2334
2050
  ):
2335
- LGR.info(f"\n\nRegressor refinement, pass {thepass}")
2336
- TimingLGR.info(f"Regressor refinement start, pass {thepass}")
2337
- if optiondict["refineoffset"]:
2338
- # check that we won't end up excluding all voxels from offset calculation before accepting mask
2339
- offsetmask = np.uint16(fitmask)
2340
- if internaloffsetincludemask_valid is not None:
2341
- offsetmask[np.where(internaloffsetincludemask_valid == 0)] = 0
2342
- if internaloffsetexcludemask_valid is not None:
2343
- offsetmask[np.where(internaloffsetexcludemask_valid != 0.0)] = 0
2344
- if tide_stats.getmasksize(offsetmask) == 0:
2345
- LGR.warning(
2346
- "NB: cannot exclude voxels from offset calculation mask - including for this pass"
2347
- )
2348
- offsetmask = fitmask + 0
2349
-
2350
- peaklag, dummy, dummy = tide_stats.gethistprops(
2351
- lagtimes[np.where(offsetmask > 0)],
2352
- optiondict["histlen"],
2353
- pickleft=optiondict["pickleft"],
2354
- peakthresh=optiondict["pickleftthresh"],
2355
- )
2356
- optiondict["offsettime"] = peaklag
2357
- optiondict["offsettime_total"] += peaklag
2358
- optiondict[f"offsettime_pass{thepass}"] = optiondict["offsettime"]
2359
- optiondict[f"offsettime_total_pass{thepass}"] = optiondict["offsettime_total"]
2360
- LGR.info(
2361
- f"offset time set to {optiondict['offsettime']:.3f}, "
2362
- f"total is {optiondict['offsettime_total']:.3f}"
2363
- )
2364
-
2365
- if optiondict["refinedespeckled"] or (optiondict["despeckle_passes"] == 0):
2366
- # if refinedespeckled is true, or there is no despeckling, masks are unaffected
2367
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2368
- else:
2369
- # if refinedespeckled is false and there is despeckling, need to make a proper mask
2370
- if internalrefineexcludemask_valid is None:
2371
- # if there is currently no exclude mask, set exclude mask = despeckle mask
2372
- thisinternalrefineexcludemask_valid = np.where(
2373
- internaldespeckleincludemask[validvoxels] == 0.0, 0, 1
2374
- )
2375
- else:
2376
- # if there is a current exclude mask, add any voxels that are being despeckled
2377
- thisinternalrefineexcludemask_valid = np.where(
2378
- internalrefineexcludemask_valid > 0, 1, 0
2379
- )
2380
- thisinternalrefineexcludemask_valid[
2381
- np.where(internaldespeckleincludemask[validvoxels] != 0.0)
2382
- ] = 1
2383
-
2384
- # now check that we won't end up excluding all voxels from refinement before accepting mask
2385
- overallmask = np.uint16(fitmask)
2386
- if internalrefineincludemask_valid is not None:
2387
- overallmask[np.where(internalrefineincludemask_valid == 0)] = 0
2388
- if thisinternalrefineexcludemask_valid is not None:
2389
- overallmask[np.where(thisinternalrefineexcludemask_valid != 0.0)] = 0
2390
- if tide_stats.getmasksize(overallmask) == 0:
2391
- LGR.warning(
2392
- "NB: cannot exclude despeckled voxels from refinement - including for this pass"
2393
- )
2394
- thisinternalrefineexcludemask_valid = internalrefineexcludemask_valid
2395
- theRegressorRefiner.setmasks(
2396
- internalrefineincludemask_valid, thisinternalrefineexcludemask_valid
2397
- )
2398
-
2399
- # regenerate regressor for next pass
2400
- # create the refinement mask
2401
- LGR.info("making refine mask")
2402
- createdmask = theRegressorRefiner.makemask(lagstrengths, lagtimes, lagsigma, fitmask)
2403
- print(f"Refine mask has {theRegressorRefiner.refinemaskvoxels} voxels")
2404
- if not createdmask:
2405
- print("no voxels qualify for refinement - exiting")
2406
- sys.exit()
2407
-
2408
- # align timecourses to prepare for refinement
2409
- LGR.info("aligning timecourses")
2410
- tide_util.disablemkl(optiondict["nprocs_refine"], debug=threaddebug)
2411
- voxelsprocessed_rra = theRegressorRefiner.alignvoxels(
2412
- fmri_data_valid, fmritr, lagtimes
2413
- )
2414
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
2415
- LGR.info(f"align complete: {voxelsprocessed_rra=}")
2416
-
2417
- # prenormalize
2418
- LGR.info("prenormalizing timecourses")
2419
- theRegressorRefiner.prenormalize(lagtimes, lagstrengths, R2)
2420
-
2421
- # now doing the refinement
2422
- (
2423
- voxelsprocessed_rr,
2424
- outputdict,
2425
- previousnormoutputdata,
2426
- resampref_y,
2427
- resampnonosref_y,
2428
- stoprefining,
2429
- refinestopreason,
2430
- genlagtc,
2431
- ) = theRegressorRefiner.refine(
2432
- theprefilter,
2433
- fmritr,
2434
- thepass,
2435
- lagstrengths,
2436
- lagtimes,
2437
- previousnormoutputdata,
2438
- optiondict["corrmasksize"],
2439
- )
2440
- TimingLGR.info(
2441
- f"Regressor refinement end, pass {thepass}",
2442
- {
2443
- "message2": voxelsprocessed_rr,
2444
- "message3": "voxels",
2445
- },
2446
- )
2447
- for key, value in outputdict.items():
2448
- optiondict[key] = value
2449
-
2450
- # Save shifted timecourses for César
2451
- if optiondict["saveintermediatemaps"] and optiondict["savelagregressors"]:
2452
- theheader = theinputdata.copyheader()
2453
- bidspasssuffix = f"_intermediatedata-pass{thepass}"
2454
- maplist = [
2455
- (
2456
- (theRegressorRefiner.getpaddedshiftedtcs())[:, numpadtrs:-numpadtrs],
2457
- "shiftedtcs",
2458
- "bold",
2459
- None,
2460
- "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.",
2461
- ),
2462
- ]
2463
- tide_io.savemaplist(
2464
- f"{outputname}{bidspasssuffix}",
2465
- maplist,
2051
+ (resampref_y, resampnonosref_y, stoprefining, refinestopreason, genlagtc) = (
2052
+ tide_refineRegressor.refineRegressor(
2053
+ LGR,
2054
+ TimingLGR,
2055
+ thepass,
2056
+ optiondict,
2057
+ fitmask,
2058
+ internaloffsetincludemask_valid,
2059
+ internaloffsetexcludemask_valid,
2060
+ internalrefineincludemask_valid,
2061
+ internalrefineexcludemask_valid,
2062
+ internaldespeckleincludemask,
2466
2063
  validvoxels,
2064
+ theRegressorRefiner,
2065
+ lagtimes,
2066
+ lagstrengths,
2067
+ lagsigma,
2068
+ fmri_data_valid,
2069
+ fmritr,
2070
+ R2,
2071
+ theprefilter,
2072
+ previousnormoutputdata,
2073
+ theinputdata,
2074
+ numpadtrs,
2075
+ outputname,
2467
2076
  nativefmrishape,
2468
- theheader,
2469
2077
  bidsbasedict,
2470
- filetype=theinputdata.filetype,
2471
- rt_floattype=rt_floattype,
2472
- cifti_hdr=theinputdata.cifti_hdr,
2473
- debug=True,
2078
+ rt_floatset=np.float64,
2079
+ rt_floattype="float64",
2474
2080
  )
2475
- # We are done with refinement.
2081
+ )
2476
2082
  # End of main pass loop
2477
2083
 
2478
2084
  if optiondict["convergencethresh"] is None:
@@ -2535,23 +2141,27 @@ def rapidtide_main(argparsingfunc):
2535
2141
  internalvalidcoherenceshape = (numvalidspatiallocs, coherencefreqaxissize)
2536
2142
 
2537
2143
  # now allocate the arrays needed for the coherence calculation
2144
+ coherencefunc, coherencefunc_shm = tide_util.allocarray(
2145
+ internalvalidcoherenceshape,
2146
+ rt_outfloatset,
2147
+ shared=optiondict["sharedmem"],
2148
+ name=f"coherencefunc_{optiondict['pid']}",
2149
+ )
2150
+ coherencepeakval, coherencepeakval_shm = tide_util.allocarray(
2151
+ numvalidspatiallocs,
2152
+ rt_outfloatset,
2153
+ shared=optiondict["sharedmem"],
2154
+ name=f"coherencepeakval_{optiondict['pid']}",
2155
+ )
2156
+ coherencepeakfreq, coherencepeakfreq_shm = tide_util.allocarray(
2157
+ numvalidspatiallocs,
2158
+ rt_outfloatset,
2159
+ shared=optiondict["sharedmem"],
2160
+ name=f"coherencepeakfreq_{optiondict['pid']}",
2161
+ )
2538
2162
  if optiondict["sharedmem"]:
2539
- coherencefunc, coherencefunc_shm = tide_util.allocshared(
2540
- internalvalidcoherenceshape,
2541
- rt_outfloatset,
2542
- name=f"coherencefunc_{optiondict['pid']}",
2543
- )
2544
- coherencepeakval, coherencepeakval_shm = tide_util.allocshared(
2545
- numvalidspatiallocs, rt_outfloatset, name=f"coherencepeakval_{optiondict['pid']}"
2546
- )
2547
- coherencepeakfreq, coherencepeakfreq_shm = tide_util.allocshared(
2548
- numvalidspatiallocs, rt_outfloatset, name=f"coherencepeakfreq_{optiondict['pid']}"
2549
- )
2550
2163
  ramlocation = "in shared memory"
2551
2164
  else:
2552
- coherencefunc = np.zeros(internalvalidcoherenceshape, dtype=rt_outfloattype)
2553
- coherencepeakval = np.zeros(numvalidspatiallocs, dtype=rt_outfloattype)
2554
- coherencepeakfreq = np.zeros(numvalidspatiallocs, dtype=rt_outfloattype)
2555
2165
  ramlocation = "locally"
2556
2166
  optiondict["totalcoherencebytes"] = (
2557
2167
  coherencefunc.nbytes + coherencepeakval.nbytes + coherencepeakfreq.nbytes
@@ -2559,7 +2169,7 @@ def rapidtide_main(argparsingfunc):
2559
2169
  thesize, theunit = tide_util.format_bytes(optiondict["totalcoherencebytes"])
2560
2170
  print(f"allocated {thesize:.3f} {theunit} {ramlocation} for coherence calculation")
2561
2171
 
2562
- tide_util.disablemkl(1, debug=threaddebug)
2172
+ tide_util.disablemkl(1, debug=optiondict["threaddebug"])
2563
2173
  voxelsprocessed_coherence = tide_calccoherence.coherencepass(
2564
2174
  fmri_data_valid,
2565
2175
  theCoherer,
@@ -2569,10 +2179,10 @@ def rapidtide_main(argparsingfunc):
2569
2179
  alt=True,
2570
2180
  showprogressbar=optiondict["showprogressbar"],
2571
2181
  chunksize=optiondict["mp_chunksize"],
2572
- nprocs=1,
2182
+ nprocs=optiondict["nprocs"],
2573
2183
  alwaysmultiproc=optiondict["alwaysmultiproc"],
2574
2184
  )
2575
- tide_util.enablemkl(optiondict["mklthreads"], debug=threaddebug)
2185
+ tide_util.enablemkl(optiondict["mklthreads"], debug=optiondict["threaddebug"])
2576
2186
 
2577
2187
  # save the results of the calculations
2578
2188
  theheader = theinputdata.copyheader(
@@ -2607,17 +2217,21 @@ def rapidtide_main(argparsingfunc):
2607
2217
  LGR.info("\n\nWiener deconvolution")
2608
2218
 
2609
2219
  # now allocate the arrays needed for Wiener deconvolution
2220
+ wienerdeconv, wienerdeconv_shm = tide_util.allocarray(
2221
+ internalvalidspaceshape,
2222
+ rt_outfloatset,
2223
+ shared=optiondict["sharedmem"],
2224
+ name=f"wienerdeconv_{optiondict['pid']}",
2225
+ )
2226
+ wpeak, wpeak_shm = tide_util.allocarray(
2227
+ internalvalidspaceshape,
2228
+ rt_outfloatset,
2229
+ shared=optiondict["sharedmem"],
2230
+ name=f"wpeak_{optiondict['pid']}",
2231
+ )
2610
2232
  if optiondict["sharedmem"]:
2611
- wienerdeconv, wienerdeconv_shm = tide_util.allocshared(
2612
- internalvalidspaceshape, rt_outfloatset, name=f"wienerdeconv_{optiondict['pid']}"
2613
- )
2614
- wpeak, wpeak_shm = tide_util.allocshared(
2615
- internalvalidspaceshape, rt_outfloatset, name=f"wpeak_{optiondict['pid']}"
2616
- )
2617
2233
  ramlocation = "in shared memory"
2618
2234
  else:
2619
- wienerdeconv = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2620
- wpeak = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2621
2235
  ramlocation = "locally"
2622
2236
  optiondict["totalwienerbytes"] = wienerdeconv.nbytes + wpeak.nbytes
2623
2237
  thesize, theunit = tide_util.format_bytes(optiondict["totalwienerbytes"])
@@ -2627,6 +2241,7 @@ def rapidtide_main(argparsingfunc):
2627
2241
  numspatiallocs,
2628
2242
  fmri_data_valid,
2629
2243
  threshval,
2244
+ lagtc,
2630
2245
  optiondict,
2631
2246
  wienerdeconv,
2632
2247
  wpeak,
@@ -2721,66 +2336,27 @@ def rapidtide_main(argparsingfunc):
2721
2336
  TimingLGR.info("End moving fmri_data to shared memory")
2722
2337
  theinputdata.unload()
2723
2338
 
2724
- # now allocate the arrays needed for sLFO filtering
2725
- if optiondict["refinedelay"]:
2726
- derivaxissize = np.max(
2727
- [optiondict["refineregressderivs"] + 1, optiondict["regressderivs"] + 1]
2728
- )
2729
- else:
2730
- derivaxissize = optiondict["regressderivs"] + 1
2731
- internalvalidspaceshapederivs = (
2732
- internalvalidspaceshape,
2733
- derivaxissize,
2339
+ # allocate the arrays needed for sLFO filtering
2340
+ movingsignal, movingsignal_shm = tide_util.allocarray(
2341
+ internalvalidfmrishape,
2342
+ rt_outfloattype,
2343
+ shared=optiondict["sharedmem"],
2344
+ name=f"movingsignal_{optiondict['pid']}",
2345
+ )
2346
+ filtereddata, filtereddata_shm = tide_util.allocarray(
2347
+ internalvalidfmrishape,
2348
+ rt_outfloattype,
2349
+ shared=optiondict["sharedmem"],
2350
+ name=f"filtereddata_{optiondict['pid']}",
2734
2351
  )
2735
2352
  if optiondict["sharedmem"]:
2736
- sLFOfitmean, sLFOfitmean_shm = tide_util.allocshared(
2737
- internalvalidspaceshape, rt_outfloatset, name=f"sLFOfitmean_{optiondict['pid']}"
2738
- )
2739
- rvalue, rvalue_shm = tide_util.allocshared(
2740
- internalvalidspaceshape, rt_outfloatset, name=f"rvalue_{optiondict['pid']}"
2741
- )
2742
- r2value, r2value_shm = tide_util.allocshared(
2743
- internalvalidspaceshape, rt_outfloatset, name=f"r2value_{optiondict['pid']}"
2744
- )
2745
- fitNorm, fitNorm_shm = tide_util.allocshared(
2746
- internalvalidspaceshapederivs, rt_outfloatset, name=f"fitNorm_{optiondict['pid']}"
2747
- )
2748
- fitcoeff, fitcoeff_shm = tide_util.allocshared(
2749
- internalvalidspaceshapederivs, rt_outfloatset, name=f"fitcoeff_{optiondict['pid']}"
2750
- )
2751
- movingsignal, movingsignal_shm = tide_util.allocshared(
2752
- internalvalidfmrishape, rt_outfloatset, name=f"movingsignal_{optiondict['pid']}"
2753
- )
2754
- lagtc, lagtc_shm = tide_util.allocshared(
2755
- internalvalidfmrishape, rt_floatset, name=f"lagtc_{optiondict['pid']}"
2756
- )
2757
- filtereddata, filtereddata_shm = tide_util.allocshared(
2758
- internalvalidfmrishape, rt_outfloatset, name=f"filtereddata_{optiondict['pid']}"
2759
- )
2760
2353
  ramlocation = "in shared memory"
2761
2354
  else:
2762
- sLFOfitmean = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2763
- rvalue = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2764
- r2value = np.zeros(internalvalidspaceshape, dtype=rt_outfloattype)
2765
- fitNorm = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
2766
- fitcoeff = np.zeros(internalvalidspaceshapederivs, dtype=rt_outfloattype)
2767
- movingsignal = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
2768
- lagtc = np.zeros(internalvalidfmrishape, dtype=rt_floattype)
2769
- filtereddata = np.zeros(internalvalidfmrishape, dtype=rt_outfloattype)
2770
2355
  ramlocation = "locally"
2771
2356
 
2772
- optiondict["totalsLFOfilterbytes"] = (
2773
- sLFOfitmean.nbytes
2774
- + rvalue.nbytes
2775
- + r2value.nbytes
2776
- + fitNorm.nbytes
2777
- + fitcoeff.nbytes
2778
- + movingsignal.nbytes
2779
- + lagtc.nbytes
2780
- + filtereddata.nbytes
2781
- )
2357
+ optiondict["totalsLFOfilterbytes"] = movingsignal.nbytes + filtereddata.nbytes
2782
2358
  thesize, theunit = tide_util.format_bytes(optiondict["totalsLFOfilterbytes"])
2783
- print(f"allocated {thesize:.3f} {theunit} {ramlocation} for sLFO filter/delay refinement")
2359
+ print(f"allocated {thesize:.3f} {theunit} {ramlocation} for sLFO filter")
2784
2360
  tide_util.logmem("before sLFO filter")
2785
2361
 
2786
2362
  if optiondict["dolinfitfilt"]:
@@ -2829,121 +2405,52 @@ def rapidtide_main(argparsingfunc):
2829
2405
  if optiondict["refinedelay"]:
2830
2406
  TimingLGR.info("Delay refinement start")
2831
2407
  LGR.info("\n\nDelay refinement")
2408
+
2832
2409
  if optiondict["delayoffsetgausssigma"] < 0.0 and theinputdata.filetype != "text":
2833
2410
  # set gausssigma automatically
2834
2411
  optiondict["delayoffsetgausssigma"] = np.mean([xdim, ydim, slicethickness]) / 2.0
2835
2412
 
2836
- regressderivratios, regressrvalues = tide_refinedelay.getderivratios(
2413
+ (
2414
+ delayoffset,
2415
+ regressderivratios,
2416
+ medfiltregressderivratios,
2417
+ filteredregressderivratios,
2418
+ optiondict["delayoffsetMAD"],
2419
+ ) = tide_refineDelayMap.refineDelay(
2837
2420
  fmri_data_valid,
2838
- validvoxels,
2839
2421
  initial_fmri_x,
2840
- lagtimes,
2422
+ xdim,
2423
+ ydim,
2424
+ slicethickness,
2841
2425
  sLFOfiltmask,
2842
2426
  genlagtc,
2843
- mode,
2844
- outputname,
2845
2427
  oversamptr,
2846
2428
  sLFOfitmean,
2847
2429
  rvalue,
2848
2430
  r2value,
2849
- fitNorm[:, : (optiondict["refineregressderivs"] + 1)],
2850
- fitcoeff[:, : (optiondict["refineregressderivs"] + 1)],
2851
- movingsignal,
2431
+ fitNorm,
2432
+ fitcoeff,
2852
2433
  lagtc,
2853
- filtereddata,
2434
+ outputname,
2435
+ validvoxels,
2436
+ nativespaceshape,
2437
+ theinputdata,
2438
+ lagtimes,
2439
+ optiondict,
2854
2440
  LGR,
2855
2441
  TimingLGR,
2856
- optiondict,
2857
- regressderivs=optiondict["refineregressderivs"],
2442
+ outputlevel=optiondict["outputlevel"],
2443
+ gausssigma=optiondict["delayoffsetgausssigma"],
2444
+ patchthresh=optiondict["delaypatchthresh"],
2445
+ mindelay=optiondict["mindelay"],
2446
+ maxdelay=optiondict["maxdelay"],
2447
+ numpoints=optiondict["numpoints"],
2448
+ histlen=optiondict["histlen"],
2449
+ rt_floatset=rt_floatset,
2450
+ rt_floattype=rt_floattype,
2858
2451
  debug=optiondict["debug"],
2859
2452
  )
2860
-
2861
- if optiondict["refineregressderivs"] == 1:
2862
- medfiltregressderivratios, filteredregressderivratios, delayoffsetMAD = (
2863
- tide_refinedelay.filterderivratios(
2864
- regressderivratios,
2865
- nativespaceshape,
2866
- validvoxels,
2867
- (xdim, ydim, slicethickness),
2868
- gausssigma=optiondict["delayoffsetgausssigma"],
2869
- patchthresh=optiondict["delaypatchthresh"],
2870
- filetype=theinputdata.filetype,
2871
- rt_floattype="float64",
2872
- debug=optiondict["debug"],
2873
- )
2874
- )
2875
- optiondict["delayoffsetMAD"] = delayoffsetMAD
2876
-
2877
- # find the mapping of derivative ratios to delays
2878
- tide_refinedelay.trainratiotooffset(
2879
- genlagtc,
2880
- initial_fmri_x,
2881
- outputname,
2882
- optiondict["outputlevel"],
2883
- mindelay=optiondict["mindelay"],
2884
- maxdelay=optiondict["maxdelay"],
2885
- numpoints=optiondict["numpoints"],
2886
- debug=optiondict["debug"],
2887
- )
2888
-
2889
- # now calculate the delay offsets
2890
- delayoffset = np.zeros_like(filteredregressderivratios)
2891
- if optiondict["debug"]:
2892
- print(
2893
- f"calculating delayoffsets for {filteredregressderivratios.shape[0]} voxels"
2894
- )
2895
- for i in range(filteredregressderivratios.shape[0]):
2896
- delayoffset[i], closestoffset = tide_refinedelay.ratiotodelay(
2897
- filteredregressderivratios[i]
2898
- )
2899
- else:
2900
- medfiltregressderivratios = np.zeros_like(regressderivratios)
2901
- filteredregressderivratios = np.zeros_like(regressderivratios)
2902
- delayoffsetMAD = np.zeros(optiondict["refineregressderivs"], dtype=float)
2903
- for i in range(optiondict["refineregressderivs"]):
2904
- (
2905
- medfiltregressderivratios[i, :],
2906
- filteredregressderivratios[i, :],
2907
- delayoffsetMAD[i],
2908
- ) = tide_refinedelay.filterderivratios(
2909
- regressderivratios[i, :],
2910
- (xsize, ysize, numslices),
2911
- validvoxels,
2912
- (xdim, ydim, slicethickness),
2913
- gausssigma=optiondict["delayoffsetgausssigma"],
2914
- patchthresh=optiondict["delaypatchthresh"],
2915
- filetype=theinputdata.filetype,
2916
- rt_floattype=rt_floattype,
2917
- debug=optiondict["debug"],
2918
- )
2919
- optiondict[f"delayoffsetMAD_{i + 1}"] = delayoffsetMAD[i]
2920
-
2921
- # now calculate the delay offsets
2922
- delayoffset = np.zeros_like(filteredregressderivratios[0, :])
2923
- if optiondict["debug"]:
2924
- print(
2925
- f"calculating delayoffsets for {filteredregressderivratios.shape[1]} voxels"
2926
- )
2927
- for i in range(filteredregressderivratios.shape[1]):
2928
- delayoffset[i] = tide_refinedelay.coffstodelay(
2929
- filteredregressderivratios[:, i],
2930
- mindelay=optiondict["mindelay"],
2931
- maxdelay=optiondict["maxdelay"],
2932
- )
2933
-
2934
- namesuffix = "_desc-delayoffset_hist"
2935
- if optiondict["dolinfitfilt"]:
2936
- tide_stats.makeandsavehistogram(
2937
- delayoffset[np.where(sLFOfiltmask > 0)],
2938
- optiondict["histlen"],
2939
- 1,
2940
- outputname + namesuffix,
2941
- displaytitle="Histogram of delay offsets calculated from regression coefficients",
2942
- dictvarname="delayoffsethist",
2943
- thedict=optiondict,
2944
- )
2945
2453
  lagtimesrefined = lagtimes + delayoffset
2946
-
2947
2454
  ####################################################
2948
2455
  # Delay refinement end
2949
2456
  ####################################################
@@ -3176,6 +2683,10 @@ def rapidtide_main(argparsingfunc):
3176
2683
  lagstrengths[np.where(fitmask > 0)], histpcts, nozero=False
3177
2684
  )
3178
2685
  thesigmapcts = tide_stats.getfracvals(lagsigma[np.where(fitmask > 0)], histpcts, nozero=False)
2686
+ if optiondict["refinedelay"]:
2687
+ therefinedtimepcts = tide_stats.getfracvals(
2688
+ lagtimesrefined[np.where(fitmask > 0)], histpcts, nozero=False
2689
+ )
3179
2690
  for i in range(len(histpcts)):
3180
2691
  optiondict[f"lagtimes_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3181
2692
  thetimepcts[i]
@@ -3186,6 +2697,10 @@ def rapidtide_main(argparsingfunc):
3186
2697
  optiondict[f"lagsigma_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"] = (
3187
2698
  thesigmapcts[i]
3188
2699
  )
2700
+ if optiondict["refinedelay"]:
2701
+ optiondict[
2702
+ f"lagtimesrefined_{str(int(np.round(100 * histpcts[i], 0))).zfill(2)}pct"
2703
+ ] = therefinedtimepcts[i]
3189
2704
  optiondict["fitmasksize"] = np.sum(fitmask)
3190
2705
  optiondict["fitmaskpct"] = 100.0 * optiondict["fitmasksize"] / optiondict["corrmasksize"]
3191
2706
 
@@ -3239,55 +2754,29 @@ def rapidtide_main(argparsingfunc):
3239
2754
  ),
3240
2755
  ]
3241
2756
  if (optiondict["outputlevel"] != "min") and (optiondict["outputlevel"] != "less"):
3242
- if optiondict["refineregressderivs"] > 1:
3243
- for i in range(optiondict["refineregressderivs"]):
3244
- savelist += [
3245
- (
3246
- regressderivratios[i, :],
3247
- f"regressderivratios_{i}",
3248
- "map",
3249
- None,
3250
- f"Ratio of derivative {i + 1} of delayed sLFO to the delayed sLFO",
3251
- ),
3252
- (
3253
- medfiltregressderivratios[i, :],
3254
- f"medfiltregressderivratios_{i}",
3255
- "map",
3256
- None,
3257
- f"Median filtered version of the regressderivratios_{i} map",
3258
- ),
3259
- (
3260
- filteredregressderivratios[i, :],
3261
- f"filteredregressderivratios_{i}",
3262
- "map",
3263
- None,
3264
- f"regressderivratios_{i}, with outliers patched using median filtered data",
3265
- ),
3266
- ]
3267
- else:
3268
- savelist += [
3269
- (
3270
- regressderivratios,
3271
- "regressderivratios",
3272
- "map",
3273
- None,
3274
- "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
3275
- ),
3276
- (
3277
- medfiltregressderivratios,
3278
- "medfiltregressderivratios",
3279
- "map",
3280
- None,
3281
- "Median filtered version of the regressderivratios map",
3282
- ),
3283
- (
3284
- filteredregressderivratios,
3285
- "filteredregressderivratios",
3286
- "map",
3287
- None,
3288
- "regressderivratios, with outliers patched using median filtered data",
3289
- ),
3290
- ]
2757
+ savelist += [
2758
+ (
2759
+ regressderivratios,
2760
+ "regressderivratios",
2761
+ "map",
2762
+ None,
2763
+ "Ratio of the first derivative of delayed sLFO to the delayed sLFO",
2764
+ ),
2765
+ (
2766
+ medfiltregressderivratios,
2767
+ "medfiltregressderivratios",
2768
+ "map",
2769
+ None,
2770
+ "Median filtered version of the regressderivratios map",
2771
+ ),
2772
+ (
2773
+ filteredregressderivratios,
2774
+ "filteredregressderivratios",
2775
+ "map",
2776
+ None,
2777
+ "regressderivratios, with outliers patched using median filtered data",
2778
+ ),
2779
+ ]
3291
2780
  if optiondict["calccoherence"]:
3292
2781
  savelist += [
3293
2782
  (coherencepeakval, "coherencepeakval", "map", None, "Coherence peak value"),
@@ -3585,27 +3074,28 @@ def rapidtide_main(argparsingfunc):
3585
3074
  if optiondict["numestreps"] > 0:
3586
3075
  masklist = []
3587
3076
 
3588
- # we can only calculate this map if we have enough data for a good fit
3077
+ # we can only calculate this map if we have enough data for a good fit, and the fit succeeded
3589
3078
  if optiondict["numestreps"] >= 1000:
3590
- neglogpmax = np.log10(optiondict["numestreps"])
3591
- # generate a neglogp map
3592
- neglog10pmap = lagstrengths * 0.0
3593
- for voxel in range(neglog10pmap.shape[0]):
3594
- neglog10pmap[voxel] = tide_stats.neglog10pfromr(
3595
- lagstrengths[voxel],
3596
- sigfit,
3597
- neglogpmax=neglogpmax,
3598
- debug=optiondict["debug"],
3599
- )
3600
- masklist += [
3601
- (
3602
- neglog10pmap.copy(),
3603
- "neglog10p",
3604
- "map",
3605
- None,
3606
- f"Negative log(10) of the p value of the r at each voxel",
3607
- )
3608
- ]
3079
+ if sigfit is not None:
3080
+ neglogpmax = np.log10(optiondict["numestreps"])
3081
+ # generate a neglogp map
3082
+ neglog10pmap = lagstrengths * 0.0
3083
+ for voxel in range(neglog10pmap.shape[0]):
3084
+ neglog10pmap[voxel] = tide_stats.neglog10pfromr(
3085
+ lagstrengths[voxel],
3086
+ sigfit,
3087
+ neglogpmax=neglogpmax,
3088
+ debug=optiondict["debug"],
3089
+ )
3090
+ masklist += [
3091
+ (
3092
+ neglog10pmap.copy(),
3093
+ "neglog10p",
3094
+ "map",
3095
+ None,
3096
+ f"Negative log(10) of the p value of the r at each voxel",
3097
+ )
3098
+ ]
3609
3099
 
3610
3100
  tide_io.savemaplist(
3611
3101
  outputname,