rapidtide 3.0a15__py3-none-any.whl → 3.0.2__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.
@@ -16,7 +16,6 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  #
19
- import copy
20
19
  import os
21
20
  import platform
22
21
  import sys
@@ -31,7 +30,6 @@ import rapidtide.correlate as tide_corr
31
30
  import rapidtide.filter as tide_filt
32
31
  import rapidtide.fit as tide_fit
33
32
  import rapidtide.happy_supportfuncs as happy_support
34
- import rapidtide.helper_classes as tide_classes
35
33
  import rapidtide.io as tide_io
36
34
  import rapidtide.linfitfiltpass as tide_linfitfiltpass
37
35
  import rapidtide.maskutil as tide_mask
@@ -39,6 +37,7 @@ import rapidtide.miscmath as tide_math
39
37
  import rapidtide.resample as tide_resample
40
38
  import rapidtide.stats as tide_stats
41
39
  import rapidtide.util as tide_util
40
+ import rapidtide.voxelData as tide_voxelData
42
41
 
43
42
  from .utils import setup_logger
44
43
 
@@ -179,34 +178,25 @@ def happy_main(argparsingfunc):
179
178
 
180
179
  # read in the image data
181
180
  tide_util.logmem("before reading in fmri data")
182
- nim, nim_data, nim_hdr, thedims, thesizes = tide_io.readfromnifti(fmrifilename)
183
- input_data = tide_classes.fMRIDataset(nim_data, numskip=args.numskip)
184
- timepoints = input_data.timepoints
185
- xsize = input_data.xsize
186
- ysize = input_data.ysize
187
- numslices = input_data.numslices
188
-
189
- xdim, ydim, slicethickness, tr = tide_io.parseniftisizes(thesizes)
190
- spaceunit, timeunit = nim_hdr.get_xyzt_units()
191
- if timeunit == "msec":
192
- tr /= 1000.0
181
+ input_data = tide_voxelData.VoxelData(fmrifilename, validstart=args.numskip)
182
+ xsize, ysize, numslices, dummy = input_data.getdims()
183
+ timepoints = input_data.realtimepoints
184
+ xdim, ydim, slicethickness, tr = input_data.getsizes()
185
+ numspatiallocs = input_data.numspatiallocs
193
186
  mrsamplerate = 1.0 / tr
194
187
  print("tr is", tr, "seconds, mrsamplerate is", "{:.3f}".format(mrsamplerate))
195
- numspatiallocs = int(xsize) * int(ysize) * int(numslices)
196
188
  infodict["tr"] = tr
197
189
  infodict["mrsamplerate"] = mrsamplerate
198
190
  timings.append(["Image data read in", time.time(), None, None])
199
191
 
200
192
  # remap to space by time
201
- fmri_data = input_data.byvol()
202
- del nim_data
193
+ fmri_data = input_data.byvoxel()
194
+ print("fmri_data has shape", fmri_data.shape)
203
195
 
204
196
  # make and save a mask of the voxels to process based on image intensity
205
197
  tide_util.logmem("before mask creation")
206
- # mask = np.uint16(masking.compute_epi_mask(nim).dataobj.reshape(numspatiallocs))
207
- mask = np.uint16(tide_mask.makeepimask(nim).dataobj.reshape(numspatiallocs))
208
- theheader = copy.deepcopy(nim_hdr)
209
- theheader["dim"][4] = 1
198
+ mask = np.uint16(tide_mask.makeepimask(input_data.nim).dataobj.reshape(numspatiallocs))
199
+ theheader = input_data.copyheader(numtimepoints=1)
210
200
  timings.append(["Mask created", time.time(), None, None])
211
201
  if args.outputlevel > 0:
212
202
  maskfilename = outputroot + "_desc-processvoxels_mask"
@@ -220,7 +210,7 @@ def happy_main(argparsingfunc):
220
210
  if args.projmaskname is not None:
221
211
  tide_util.logmem("before reading in projmask")
222
212
  projmask = happy_support.readextmask(
223
- args.projmaskname, nim_hdr, xsize, ysize, numslices, args.debug
213
+ args.projmaskname, input_data.nim_hdr, xsize, ysize, numslices, args.debug
224
214
  )
225
215
  # * np.float64(mask_byslice)
226
216
  projmask_byslice = projmask.reshape(xsize * ysize, numslices)
@@ -276,8 +266,7 @@ def happy_main(argparsingfunc):
276
266
  debug=args.debug,
277
267
  )
278
268
  # save motionr2 map
279
- theheader = copy.deepcopy(nim_hdr)
280
- theheader["dim"][4] = 1
269
+ theheader = input_data.copyheader(numtimepoints=1)
281
270
  motionr2filename = outputroot + "_desc-motionr2_map"
282
271
  bidsdict = bidsbasedict.copy()
283
272
  tide_io.writedicttojson(bidsdict, motionr2filename + ".json")
@@ -287,6 +276,7 @@ def happy_main(argparsingfunc):
287
276
  outarray.reshape((xsize, ysize, numslices)), theheader, motionr2filename
288
277
  )
289
278
  if args.savemotionglmfilt:
279
+ print("prior to save - fmri_data has shape", fmri_data.shape)
290
280
  motionfilteredfilename = outputroot + "_desc-motionfiltered_bold"
291
281
  bidsdict = bidsbasedict.copy()
292
282
  bidsdict["Units"] = "second"
@@ -329,8 +319,7 @@ def happy_main(argparsingfunc):
329
319
  normdata_byslice = normdata.reshape((xsize * ysize, numslices, timepoints))
330
320
 
331
321
  # save means, medians, and mads
332
- theheader = copy.deepcopy(nim_hdr)
333
- theheader["dim"][4] = 1
322
+ theheader = input_data.copyheader(numtimepoints=1)
334
323
  meansfilename = outputroot + "_desc-means_map"
335
324
  mediansfilename = outputroot + "_desc-medians_map"
336
325
  madsfilename = outputroot + "_desc-mads_map"
@@ -349,7 +338,7 @@ def happy_main(argparsingfunc):
349
338
  if args.estweightsname is not None:
350
339
  tide_util.logmem("before reading in estweights")
351
340
  estweights = happy_support.readextmask(
352
- args.estweightsname, nim_hdr, xsize, ysize, numslices, args.debug
341
+ args.estweightsname, input_data.nim_hdr, xsize, ysize, numslices, args.debug
353
342
  )
354
343
  estweights_byslice = estweights.reshape(xsize * ysize, numslices)
355
344
  print("using estweights from file", args.estweightsname)
@@ -432,7 +421,7 @@ def happy_main(argparsingfunc):
432
421
  )
433
422
  if (thispass == 0) and args.doupsampling:
434
423
  happy_support.upsampleimage(
435
- input_data, nim_hdr, numsteps, sliceoffsets, slicesamplerate, outputroot
424
+ input_data, numsteps, sliceoffsets, slicesamplerate, outputroot
436
425
  )
437
426
  sys.exit(0)
438
427
 
@@ -1139,6 +1128,10 @@ def happy_main(argparsingfunc):
1139
1128
  tide_io.writedict(infodict, outputroot + "_info.txt")
1140
1129
 
1141
1130
  # interpolate the instantaneous phase
1131
+ print(f"{tr=}")
1132
+ print(f"{timepoints=}")
1133
+ print(f"{numsteps=}")
1134
+ print(f"{args.upsamplefac=}")
1142
1135
  upsampledslicetimeaxis = np.linspace(
1143
1136
  0.0,
1144
1137
  tr * timepoints,
@@ -1235,32 +1228,6 @@ def happy_main(argparsingfunc):
1235
1228
  # now do the phase projection
1236
1229
  #
1237
1230
  #
1238
- """app, rawapp, corrected_rawapp, normapp, weights, cine, derivatives = (
1239
- happy_support.phaseproject(
1240
- demeandata,
1241
- means,
1242
- args.destpoints,
1243
- numsteps,
1244
- timings,
1245
- cardfromfmri_sliceres,
1246
- instantaneous_cardiacphase,
1247
- thispass,
1248
- numpasses,
1249
- args,
1250
- outputroot,
1251
- slicesamplerate,
1252
- pleth_sliceres,
1253
- mrsamplerate,
1254
- projmask_byslice,
1255
- cardphasevals,
1256
- thetimes,
1257
- centric=True,
1258
- passstring="",
1259
- badpointlist=None,
1260
- congridbins=3.0,
1261
- gridkernel="kaiser",
1262
- )
1263
- )"""
1264
1231
  app_byslice = app.reshape((xsize * ysize, numslices, args.destpoints))
1265
1232
  rawapp_byslice = rawapp.reshape((xsize * ysize, numslices, args.destpoints))
1266
1233
  corrected_rawapp_byslice = corrected_rawapp.reshape(
@@ -1437,115 +1404,46 @@ def happy_main(argparsingfunc):
1437
1404
  wavedelay *= 0.0
1438
1405
  wavedelayCOM *= 0.0
1439
1406
  waveamp *= 0.0
1407
+ else:
1408
+ thecorrfunc_byslice = None
1409
+ waveamp_byslice = None
1410
+ wavedelay_byslice = None
1411
+ wavedelayCOM_byslice = None
1412
+ corrstartloc = None
1413
+ correndloc = None
1414
+ thealiasedcorrx = None
1415
+ theAliasedCorrelator = None
1440
1416
 
1441
1417
  # now project the data
1442
- fmri_data_byslice = input_data.byslice()
1443
- for theslice in tqdm(
1444
- range(numslices),
1445
- desc="Slice",
1446
- unit="slices",
1447
- disable=(not args.showprogressbar),
1448
- ):
1449
- if args.verbose:
1450
- print("Phase projecting for slice", theslice)
1451
- validlocs = np.where(projmask_byslice[:, theslice] > 0)[0]
1452
- # indexlist = range(0, len(cardphasevals[theslice, :]))
1453
- if len(validlocs) > 0:
1454
- for t in proctrs:
1455
- filteredmr = -demeandata_byslice[validlocs, theslice, t]
1456
- cinemr = fmri_data_byslice[validlocs, theslice, t]
1457
- thevals, theweights, theindices = tide_resample.congrid(
1458
- outphases,
1459
- cardphasevals[theslice, t],
1460
- 1.0,
1461
- args.congridbins,
1462
- kernel=args.gridkernel,
1463
- cyclic=True,
1464
- )
1465
- for i in range(len(theindices)):
1466
- weights_byslice[validlocs, theslice, theindices[i]] += theweights[i]
1467
- # rawapp_byslice[validlocs, theslice, theindices[i]] += (
1468
- # theweights[i] * filteredmr
1469
- # )
1470
- rawapp_byslice[validlocs, theslice, theindices[i]] += filteredmr
1471
- cine_byslice[validlocs, theslice, theindices[i]] += theweights[i] * cinemr
1472
- for d in range(args.destpoints):
1473
- if weights_byslice[validlocs[0], theslice, d] == 0.0:
1474
- weights_byslice[validlocs, theslice, d] = 1.0
1475
- rawapp_byslice[validlocs, theslice, :] = np.nan_to_num(
1476
- rawapp_byslice[validlocs, theslice, :]
1477
- / weights_byslice[validlocs, theslice, :]
1478
- )
1479
- cine_byslice[validlocs, theslice, :] = np.nan_to_num(
1480
- cine_byslice[validlocs, theslice, :] / weights_byslice[validlocs, theslice, :]
1481
- )
1482
- else:
1483
- rawapp_byslice[:, theslice, :] = 0.0
1484
- cine_byslice[:, theslice, :] = 0.0
1485
-
1486
- # smooth the projected data along the time dimension
1487
- if args.smoothapp:
1488
- for loc in validlocs:
1489
- rawapp_byslice[loc, theslice, :] = appsmoothingfilter.apply(
1490
- phaseFs, rawapp_byslice[loc, theslice, :]
1491
- )
1492
- derivatives_byslice[loc, theslice, :] = happy_support.circularderivs(
1493
- rawapp_byslice[loc, theslice, :]
1494
- )
1495
- appflips_byslice = np.where(
1496
- -derivatives_byslice[:, :, 2] > derivatives_byslice[:, :, 0], -1.0, 1.0
1497
- )
1498
- timecoursemean = np.mean(rawapp_byslice[validlocs, theslice, :], axis=1).reshape(
1499
- (-1, 1)
1500
- )
1501
- if args.fliparteries:
1502
- corrected_rawapp_byslice[validlocs, theslice, :] = (
1503
- rawapp_byslice[validlocs, theslice, :] - timecoursemean
1504
- ) * appflips_byslice[validlocs, theslice, None] + timecoursemean
1505
- if args.doaliasedcorrelation and (thispass > 0):
1506
- for theloc in validlocs:
1507
- thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
1508
- -appflips_byslice[theloc, theslice]
1509
- * demeandata_byslice[theloc, theslice, :],
1510
- int(sliceoffsets[theslice]),
1511
- )[corrstartloc : correndloc + 1]
1512
- maxloc = np.argmax(thecorrfunc_byslice[theloc, theslice, :])
1513
- wavedelay_byslice[theloc, theslice] = (
1514
- thealiasedcorrx[corrstartloc : correndloc + 1]
1515
- )[maxloc]
1516
- waveamp_byslice[theloc, theslice] = np.fabs(
1517
- thecorrfunc_byslice[theloc, theslice, maxloc]
1518
- )
1519
- wavedelayCOM_byslice[theloc, theslice] = happy_support.theCOM(
1520
- thealiasedcorrx[corrstartloc : correndloc + 1],
1521
- np.fabs(thecorrfunc_byslice[theloc, theslice, :]),
1522
- )
1523
- else:
1524
- corrected_rawapp_byslice[validlocs, theslice, :] = rawapp_byslice[
1525
- validlocs, theslice, :
1526
- ]
1527
- if args.doaliasedcorrelation and (thispass > 0):
1528
- for theloc in validlocs:
1529
- thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
1530
- -demeandata_byslice[theloc, theslice, :],
1531
- int(sliceoffsets[theslice]),
1532
- )[corrstartloc : correndloc + 1]
1533
- maxloc = np.argmax(np.abs(thecorrfunc_byslice[theloc, theslice, :]))
1534
- wavedelay_byslice[theloc, theslice] = (
1535
- thealiasedcorrx[corrstartloc : correndloc + 1]
1536
- )[maxloc]
1537
- waveamp_byslice[theloc, theslice] = np.fabs(
1538
- thecorrfunc_byslice[theloc, theslice, maxloc]
1539
- )
1540
- timecoursemin = np.min(
1541
- corrected_rawapp_byslice[validlocs, theslice, :], axis=1
1542
- ).reshape((-1, 1))
1543
- app_byslice[validlocs, theslice, :] = (
1544
- corrected_rawapp_byslice[validlocs, theslice, :] - timecoursemin
1545
- )
1546
- normapp_byslice[validlocs, theslice, :] = np.nan_to_num(
1547
- app_byslice[validlocs, theslice, :] / means_byslice[validlocs, theslice, None]
1548
- )
1418
+ appflips_byslice = happy_support.phaseproject(
1419
+ input_data,
1420
+ demeandata_byslice,
1421
+ means_byslice,
1422
+ rawapp_byslice,
1423
+ app_byslice,
1424
+ normapp_byslice,
1425
+ weights_byslice,
1426
+ cine_byslice,
1427
+ projmask_byslice,
1428
+ derivatives_byslice,
1429
+ proctrs,
1430
+ thispass,
1431
+ args,
1432
+ sliceoffsets,
1433
+ cardphasevals,
1434
+ outphases,
1435
+ appsmoothingfilter,
1436
+ phaseFs,
1437
+ thecorrfunc_byslice,
1438
+ waveamp_byslice,
1439
+ wavedelay_byslice,
1440
+ wavedelayCOM_byslice,
1441
+ corrected_rawapp_byslice,
1442
+ corrstartloc,
1443
+ correndloc,
1444
+ thealiasedcorrx,
1445
+ theAliasedCorrelator,
1446
+ )
1549
1447
  if not args.verbose:
1550
1448
  print(" done")
1551
1449
  timings.append(
@@ -1561,10 +1459,7 @@ def happy_main(argparsingfunc):
1561
1459
  # calculate the flow field from the normapp
1562
1460
  if args.doflowfields:
1563
1461
  print("calculating flow fields")
1564
- flowhdr = copy.deepcopy(nim_hdr)
1565
- flowhdr["dim"][4] = 3
1566
- flowhdr["toffset"] = 0
1567
- flowhdr["pixdim"][4] = 1
1462
+ flowhdr = input_data.copyheader(numtimepoints=3, tr=1.0, toffset=0.0)
1568
1463
 
1569
1464
  flowfield = happy_support.calc_3d_optical_flow(
1570
1465
  app,
@@ -1577,10 +1472,9 @@ def happy_main(argparsingfunc):
1577
1472
  print(f"flow field shape: {flowfield.shape}")
1578
1473
 
1579
1474
  # save the analytic phase projection image
1580
- theheader = copy.deepcopy(nim_hdr)
1581
- theheader["dim"][4] = args.destpoints
1582
- theheader["toffset"] = -np.pi
1583
- theheader["pixdim"][4] = 2.0 * np.pi / args.destpoints
1475
+ theheader = input_data.copyheader(
1476
+ numtimepoints=args.destpoints, tr=-np.pi, toffset=2.0 * np.pi / args.destpoints
1477
+ )
1584
1478
  if thispass == numpasses - 1:
1585
1479
  appfilename = outputroot + "_desc-app_info"
1586
1480
  normappfilename = outputroot + "_desc-normapp_info"
@@ -1602,10 +1496,11 @@ def happy_main(argparsingfunc):
1602
1496
  timings.append(["Phase projected data saved" + passstring, time.time(), None, None])
1603
1497
 
1604
1498
  if args.doaliasedcorrelation and thispass == numpasses - 1:
1605
- theheader = copy.deepcopy(nim_hdr)
1606
- theheader["dim"][4] = aliasedcorrelationpts
1607
- theheader["toffset"] = 0.0
1608
- theheader["pixdim"][4] = thealiasedcorrx[1] - thealiasedcorrx[0]
1499
+ theheader = input_data.copyheader(
1500
+ numtimepoints=aliasedcorrelationpts,
1501
+ tr=(thealiasedcorrx[1] - thealiasedcorrx[0]),
1502
+ toffset=0.0,
1503
+ )
1609
1504
  corrfuncfilename = outputroot + "_desc-corrfunc_info"
1610
1505
  wavedelayfilename = outputroot + "_desc-wavedelay_map"
1611
1506
  wavedelayCOMfilename = outputroot + "_desc-wavedelayCOM_map"
@@ -1689,8 +1584,7 @@ def happy_main(argparsingfunc):
1689
1584
  risediff = (maxphase - minphase) * vesselmask
1690
1585
  arteries = np.where(appflips_byslice.reshape((xsize, ysize, numslices)) < 0, vesselmask, 0)
1691
1586
  veins = np.where(appflips_byslice.reshape((xsize, ysize, numslices)) > 0, vesselmask, 0)
1692
- theheader = copy.deepcopy(nim_hdr)
1693
- theheader["dim"][4] = 1
1587
+ theheader = input_data.copyheader(numtimepoints=1)
1694
1588
  if thispass == numpasses - 1:
1695
1589
  vesselmaskfilename = outputroot + "_desc-vessels_mask"
1696
1590
  minphasefilename = outputroot + "_desc-minphase_map"
@@ -1765,7 +1659,7 @@ def happy_main(argparsingfunc):
1765
1659
  cardiacnoise_byslice[validlocs, theslice, t] = rawapp_byslice[
1766
1660
  validlocs, theslice, phaseindices_byslice[validlocs, theslice, t]
1767
1661
  ]
1768
- theheader = copy.deepcopy(nim_hdr)
1662
+ theheader = input_data.copyheader()
1769
1663
  timings.append(["Cardiac signal generated", time.time(), None, None])
1770
1664
  if args.savecardiacnoise:
1771
1665
  cardiacnoisefilename = outputroot + "_desc-cardiacnoise_info"
@@ -1829,7 +1723,7 @@ def happy_main(argparsingfunc):
1829
1723
  tide_io.writevec(fitcoffs, outputroot + "_fitcoff.txt")
1830
1724
  tide_io.writevec(meanvals, outputroot + "_fitmean.txt")
1831
1725
  tide_io.writevec(rvals, outputroot + "_fitR.txt")
1832
- theheader = copy.deepcopy(nim_hdr)
1726
+ theheader = input_data.copyheader()
1833
1727
  cardfiltresultfilename = outputroot + "_desc-cardfiltResult_bold"
1834
1728
  cardfiltremovedfilename = outputroot + "_desc-cardfiltRemoved_bold"
1835
1729
  tide_io.savetonifti(
@@ -1888,8 +1782,7 @@ def happy_main(argparsingfunc):
1888
1782
  "voxels",
1889
1783
  ]
1890
1784
  )
1891
- theheader = copy.deepcopy(nim_hdr)
1892
- theheader["dim"][4] = 1
1785
+ theheader = input_data.copyheader(numtimepoints=1)
1893
1786
  cardfiltcoeffsfilename = outputroot + "_desc-cardfiltCoeffs_map"
1894
1787
  cardfiltmeanfilename = outputroot + "_desc-cardfiltMean_map"
1895
1788
  cardfiltRfilename = outputroot + "_desc-cardfiltR_map"
@@ -1907,7 +1800,7 @@ def happy_main(argparsingfunc):
1907
1800
  rvals.reshape((xsize, ysize, numslices)), theheader, cardfiltRfilename
1908
1801
  )
1909
1802
 
1910
- theheader = copy.deepcopy(nim_hdr)
1803
+ theheader = input_data.copyheader()
1911
1804
  cardfiltresultfilename = outputroot + "_desc-cardfiltResult_bold"
1912
1805
  cardfiltremovedfilename = outputroot + "_desc-cardfiltRemoved_bold"
1913
1806
  tide_io.savetonifti(