rapidtide 3.0.6__py3-none-any.whl → 3.0.7__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.
- rapidtide/RapidtideDataset.py +17 -0
- rapidtide/_version.py +3 -3
- rapidtide/correlate.py +25 -6
- rapidtide/data/examples/src/testfmri +15 -0
- rapidtide/data/examples/src/testhappy +56 -60
- rapidtide/data/examples/src/testsimdata +45 -28
- rapidtide/happy_supportfuncs.py +599 -107
- rapidtide/resample.py +24 -14
- rapidtide/tests/test_congrid.py +68 -79
- rapidtide/voxelData.py +17 -3
- rapidtide/workflows/cleanregressor.py +3 -2
- rapidtide/workflows/happy.py +59 -2
- rapidtide/workflows/happy_parser.py +36 -0
- rapidtide/workflows/rapidtide.py +16 -5
- rapidtide/workflows/rapidtide_parser.py +7 -0
- rapidtide/workflows/showarbcorr.py +19 -6
- rapidtide/workflows/simdata.py +149 -65
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/METADATA +1 -1
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/RECORD +23 -23
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/WHEEL +1 -1
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/entry_points.txt +0 -0
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/licenses/LICENSE +0 -0
- {rapidtide-3.0.6.dist-info → rapidtide-3.0.7.dist-info}/top_level.txt +0 -0
rapidtide/happy_supportfuncs.py
CHANGED
|
@@ -22,13 +22,14 @@ import warnings
|
|
|
22
22
|
|
|
23
23
|
import numpy as np
|
|
24
24
|
from scipy.signal import savgol_filter, welch
|
|
25
|
-
from scipy.stats import kurtosis, skew
|
|
25
|
+
from scipy.stats import kurtosis, skew, pearsonr
|
|
26
26
|
from statsmodels.robust import mad
|
|
27
27
|
from tqdm import tqdm
|
|
28
28
|
|
|
29
29
|
import rapidtide.correlate as tide_corr
|
|
30
30
|
import rapidtide.filter as tide_filt
|
|
31
31
|
import rapidtide.fit as tide_fit
|
|
32
|
+
import rapidtide.genericmultiproc as tide_genericmultiproc
|
|
32
33
|
import rapidtide.io as tide_io
|
|
33
34
|
import rapidtide.miscmath as tide_math
|
|
34
35
|
import rapidtide.resample as tide_resample
|
|
@@ -364,6 +365,41 @@ def getcardcoeffs(
|
|
|
364
365
|
return peakfreq
|
|
365
366
|
|
|
366
367
|
|
|
368
|
+
def _procOneVoxelDetrend(
|
|
369
|
+
vox,
|
|
370
|
+
voxelargs,
|
|
371
|
+
**kwargs,
|
|
372
|
+
):
|
|
373
|
+
# unpack arguments
|
|
374
|
+
options = {
|
|
375
|
+
"detrendorder": 1,
|
|
376
|
+
"demean": False,
|
|
377
|
+
"debug": False,
|
|
378
|
+
}
|
|
379
|
+
options.update(kwargs)
|
|
380
|
+
detrendorder = options["detrendorder"]
|
|
381
|
+
demean = options["demean"]
|
|
382
|
+
debug = options["debug"]
|
|
383
|
+
[fmri_voxeldata] = voxelargs
|
|
384
|
+
if debug:
|
|
385
|
+
print(f"{vox=}, {detrendorder=}, {demean=}, {fmri_voxeldata.shape=}")
|
|
386
|
+
|
|
387
|
+
detrended_voxeldata = tide_fit.detrend(fmri_voxeldata, order=detrendorder, demean=demean)
|
|
388
|
+
|
|
389
|
+
return (
|
|
390
|
+
vox,
|
|
391
|
+
detrended_voxeldata,
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _packDetrendvoxeldata(voxnum, voxelargs):
|
|
396
|
+
return [(voxelargs[0])[voxnum, :]]
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def _unpackDetrendvoxeldata(retvals, voxelproducts):
|
|
400
|
+
(voxelproducts[0])[retvals[0], :] = retvals[1]
|
|
401
|
+
|
|
402
|
+
|
|
367
403
|
def normalizevoxels(
|
|
368
404
|
fmri_data,
|
|
369
405
|
detrendorder,
|
|
@@ -371,8 +407,12 @@ def normalizevoxels(
|
|
|
371
407
|
time,
|
|
372
408
|
timings,
|
|
373
409
|
LGR=None,
|
|
410
|
+
mpcode=True,
|
|
374
411
|
nprocs=1,
|
|
375
|
-
|
|
412
|
+
alwaysmultiproc=False,
|
|
413
|
+
showprogressbar=True,
|
|
414
|
+
chunksize=1000,
|
|
415
|
+
debug=False,
|
|
376
416
|
):
|
|
377
417
|
print("Normalizing voxels...")
|
|
378
418
|
normdata = fmri_data * 0.0
|
|
@@ -382,17 +422,54 @@ def normalizevoxels(
|
|
|
382
422
|
numspatiallocs = fmri_data.shape[0]
|
|
383
423
|
if detrendorder > 0:
|
|
384
424
|
print("Detrending to order", detrendorder, "...")
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
425
|
+
if mpcode:
|
|
426
|
+
if debug:
|
|
427
|
+
print(f"detrend multiproc path: {detrendorder=}")
|
|
428
|
+
inputshape = fmri_data.shape
|
|
429
|
+
voxelargs = [
|
|
430
|
+
fmri_data,
|
|
431
|
+
]
|
|
432
|
+
voxelfunc = _procOneVoxelDetrend
|
|
433
|
+
packfunc = _packDetrendvoxeldata
|
|
434
|
+
unpackfunc = _unpackDetrendvoxeldata
|
|
435
|
+
voxelmask = fmri_data[:, 0] * 0.0
|
|
436
|
+
voxelmask[validvoxels] = 1
|
|
437
|
+
voxeltargets = [fmri_data]
|
|
438
|
+
|
|
439
|
+
numspatiallocs = tide_genericmultiproc.run_multiproc(
|
|
440
|
+
voxelfunc,
|
|
441
|
+
packfunc,
|
|
442
|
+
unpackfunc,
|
|
443
|
+
voxelargs,
|
|
444
|
+
voxeltargets,
|
|
445
|
+
inputshape,
|
|
446
|
+
voxelmask,
|
|
447
|
+
LGR,
|
|
448
|
+
nprocs,
|
|
449
|
+
alwaysmultiproc,
|
|
450
|
+
showprogressbar,
|
|
451
|
+
chunksize,
|
|
452
|
+
debug=debug,
|
|
453
|
+
detrendorder=detrendorder,
|
|
454
|
+
demean=False,
|
|
395
455
|
)
|
|
456
|
+
else:
|
|
457
|
+
if debug:
|
|
458
|
+
print(f"detrend nonmultiproc path: {detrendorder=}")
|
|
459
|
+
for idx, thevox in enumerate(
|
|
460
|
+
tqdm(
|
|
461
|
+
validvoxels,
|
|
462
|
+
desc="Voxel",
|
|
463
|
+
unit="voxels",
|
|
464
|
+
disable=(not showprogressbar),
|
|
465
|
+
)
|
|
466
|
+
):
|
|
467
|
+
fmri_data[thevox, :] = tide_fit.detrend(
|
|
468
|
+
fmri_data[thevox, :], order=detrendorder, demean=False
|
|
469
|
+
)
|
|
470
|
+
timings.append(["Detrending finished", time.time(), numspatiallocs, "voxels"])
|
|
471
|
+
print(" done")
|
|
472
|
+
|
|
396
473
|
timings.append(["Detrending finished", time.time(), numspatiallocs, "voxels"])
|
|
397
474
|
print(" done")
|
|
398
475
|
|
|
@@ -969,6 +1046,7 @@ def cardiaccycleaverage(
|
|
|
969
1046
|
congridbins,
|
|
970
1047
|
gridkernel,
|
|
971
1048
|
centric,
|
|
1049
|
+
cache=True,
|
|
972
1050
|
cyclic=True,
|
|
973
1051
|
):
|
|
974
1052
|
rawapp_bypoint = np.zeros(len(destinationphases), dtype=np.float64)
|
|
@@ -980,13 +1058,14 @@ def cardiaccycleaverage(
|
|
|
980
1058
|
1.0,
|
|
981
1059
|
congridbins,
|
|
982
1060
|
kernel=gridkernel,
|
|
1061
|
+
cache=cache,
|
|
983
1062
|
cyclic=cyclic,
|
|
984
1063
|
)
|
|
985
1064
|
for i in range(len(theindices)):
|
|
986
1065
|
weight_bypoint[theindices[i]] += theweights[i]
|
|
987
1066
|
rawapp_bypoint[theindices[i]] += theweights[i] * waveform[t]
|
|
988
1067
|
rawapp_bypoint = np.where(
|
|
989
|
-
weight_bypoint > np.max(weight_bypoint) / 50.0,
|
|
1068
|
+
weight_bypoint > (np.max(weight_bypoint) / 50.0),
|
|
990
1069
|
np.nan_to_num(rawapp_bypoint / weight_bypoint),
|
|
991
1070
|
0.0,
|
|
992
1071
|
)
|
|
@@ -1007,6 +1086,285 @@ def circularderivs(timecourse):
|
|
|
1007
1086
|
)
|
|
1008
1087
|
|
|
1009
1088
|
|
|
1089
|
+
def _procOnePhaseProject(slice, sliceargs, **kwargs):
|
|
1090
|
+
options = {
|
|
1091
|
+
"cache": True,
|
|
1092
|
+
"debug": False,
|
|
1093
|
+
}
|
|
1094
|
+
options.update(kwargs)
|
|
1095
|
+
cache = options["cache"]
|
|
1096
|
+
debug = options["debug"]
|
|
1097
|
+
(
|
|
1098
|
+
validlocslist,
|
|
1099
|
+
proctrs,
|
|
1100
|
+
demeandata_byslice,
|
|
1101
|
+
fmri_data_byslice,
|
|
1102
|
+
outphases,
|
|
1103
|
+
cardphasevals,
|
|
1104
|
+
congridbins,
|
|
1105
|
+
gridkernel,
|
|
1106
|
+
weights_byslice,
|
|
1107
|
+
cine_byslice,
|
|
1108
|
+
destpoints,
|
|
1109
|
+
rawapp_byslice,
|
|
1110
|
+
) = sliceargs
|
|
1111
|
+
# now smooth the projected data along the time dimension
|
|
1112
|
+
validlocs = validlocslist[slice]
|
|
1113
|
+
if len(validlocs) > 0:
|
|
1114
|
+
for t in proctrs:
|
|
1115
|
+
filteredmr = -demeandata_byslice[validlocs, slice, t]
|
|
1116
|
+
cinemr = fmri_data_byslice[validlocs, slice, t]
|
|
1117
|
+
thevals, theweights, theindices = tide_resample.congrid(
|
|
1118
|
+
outphases,
|
|
1119
|
+
cardphasevals[slice, t],
|
|
1120
|
+
1.0,
|
|
1121
|
+
congridbins,
|
|
1122
|
+
kernel=gridkernel,
|
|
1123
|
+
cache=cache,
|
|
1124
|
+
cyclic=True,
|
|
1125
|
+
)
|
|
1126
|
+
for i in range(len(theindices)):
|
|
1127
|
+
weights_byslice[validlocs, slice, theindices[i]] += theweights[i]
|
|
1128
|
+
rawapp_byslice[validlocs, slice, theindices[i]] += filteredmr
|
|
1129
|
+
cine_byslice[validlocs, slice, theindices[i]] += theweights[i] * cinemr
|
|
1130
|
+
for d in range(destpoints):
|
|
1131
|
+
if weights_byslice[validlocs[0], slice, d] == 0.0:
|
|
1132
|
+
weights_byslice[validlocs, slice, d] = 1.0
|
|
1133
|
+
rawapp_byslice[validlocs, slice, :] = np.nan_to_num(
|
|
1134
|
+
rawapp_byslice[validlocs, slice, :] / weights_byslice[validlocs, slice, :]
|
|
1135
|
+
)
|
|
1136
|
+
cine_byslice[validlocs, slice, :] = np.nan_to_num(
|
|
1137
|
+
cine_byslice[validlocs, slice, :] / weights_byslice[validlocs, slice, :]
|
|
1138
|
+
)
|
|
1139
|
+
else:
|
|
1140
|
+
rawapp_byslice[:, slice, :] = 0.0
|
|
1141
|
+
cine_byslice[:, slice, :] = 0.0
|
|
1142
|
+
|
|
1143
|
+
return (
|
|
1144
|
+
slice,
|
|
1145
|
+
rawapp_byslice[:, slice, :],
|
|
1146
|
+
cine_byslice[:, slice, :],
|
|
1147
|
+
weights_byslice[:, slice, :],
|
|
1148
|
+
validlocs,
|
|
1149
|
+
)
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
def _packslicedataPhaseProject(slicenum, sliceargs):
|
|
1153
|
+
return [
|
|
1154
|
+
sliceargs[0],
|
|
1155
|
+
sliceargs[1],
|
|
1156
|
+
sliceargs[2],
|
|
1157
|
+
sliceargs[3],
|
|
1158
|
+
sliceargs[4],
|
|
1159
|
+
sliceargs[5],
|
|
1160
|
+
sliceargs[6],
|
|
1161
|
+
sliceargs[7],
|
|
1162
|
+
sliceargs[8],
|
|
1163
|
+
sliceargs[9],
|
|
1164
|
+
sliceargs[10],
|
|
1165
|
+
sliceargs[11],
|
|
1166
|
+
]
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
def _unpackslicedataPhaseProject(retvals, voxelproducts):
|
|
1170
|
+
(voxelproducts[0])[retvals[4], retvals[0], :] = (retvals[1])[retvals[4], :]
|
|
1171
|
+
(voxelproducts[1])[retvals[4], retvals[0], :] = (retvals[2])[retvals[4], :]
|
|
1172
|
+
(voxelproducts[2])[retvals[4], retvals[0], :] = (retvals[3])[retvals[4], :]
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
def preloadcongrid(outphases, congridbins, gridkernel="kaiser", cyclic=True, debug=False):
|
|
1176
|
+
outphasestep = outphases[1] - outphases[0]
|
|
1177
|
+
outphasecenter = outphases[int(len(outphases) / 2)]
|
|
1178
|
+
fillargs = outphasestep * (
|
|
1179
|
+
np.linspace(-0.5, 0.5, 10001, endpoint=True, dtype=float) + outphasecenter
|
|
1180
|
+
)
|
|
1181
|
+
for thearg in fillargs:
|
|
1182
|
+
dummy, dummy, dummy = tide_resample.congrid(
|
|
1183
|
+
outphases,
|
|
1184
|
+
thearg,
|
|
1185
|
+
1.0,
|
|
1186
|
+
congridbins,
|
|
1187
|
+
kernel=gridkernel,
|
|
1188
|
+
cyclic=cyclic,
|
|
1189
|
+
cache=True,
|
|
1190
|
+
debug=debug,
|
|
1191
|
+
)
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
def phaseprojectpass(
|
|
1195
|
+
numslices,
|
|
1196
|
+
demeandata_byslice,
|
|
1197
|
+
fmri_data_byslice,
|
|
1198
|
+
validlocslist,
|
|
1199
|
+
proctrs,
|
|
1200
|
+
weights_byslice,
|
|
1201
|
+
cine_byslice,
|
|
1202
|
+
rawapp_byslice,
|
|
1203
|
+
outphases,
|
|
1204
|
+
cardphasevals,
|
|
1205
|
+
congridbins,
|
|
1206
|
+
gridkernel,
|
|
1207
|
+
destpoints,
|
|
1208
|
+
mpcode=False,
|
|
1209
|
+
nprocs=1,
|
|
1210
|
+
alwaysmultiproc=False,
|
|
1211
|
+
showprogressbar=True,
|
|
1212
|
+
cache=True,
|
|
1213
|
+
debug=False,
|
|
1214
|
+
):
|
|
1215
|
+
if mpcode:
|
|
1216
|
+
inputshape = rawapp_byslice.shape
|
|
1217
|
+
sliceargs = [
|
|
1218
|
+
validlocslist,
|
|
1219
|
+
proctrs,
|
|
1220
|
+
demeandata_byslice,
|
|
1221
|
+
fmri_data_byslice,
|
|
1222
|
+
outphases,
|
|
1223
|
+
cardphasevals,
|
|
1224
|
+
congridbins,
|
|
1225
|
+
gridkernel,
|
|
1226
|
+
weights_byslice,
|
|
1227
|
+
cine_byslice,
|
|
1228
|
+
destpoints,
|
|
1229
|
+
rawapp_byslice,
|
|
1230
|
+
]
|
|
1231
|
+
slicefunc = _procOnePhaseProject
|
|
1232
|
+
packfunc = _packslicedataPhaseProject
|
|
1233
|
+
unpackfunc = _unpackslicedataPhaseProject
|
|
1234
|
+
slicetargets = [rawapp_byslice, cine_byslice, weights_byslice]
|
|
1235
|
+
slicemask = rawapp_byslice[0, :, 0] * 0.0 + 1
|
|
1236
|
+
|
|
1237
|
+
slicetotal = tide_genericmultiproc.run_multiproc(
|
|
1238
|
+
slicefunc,
|
|
1239
|
+
packfunc,
|
|
1240
|
+
unpackfunc,
|
|
1241
|
+
sliceargs,
|
|
1242
|
+
slicetargets,
|
|
1243
|
+
inputshape,
|
|
1244
|
+
slicemask,
|
|
1245
|
+
None,
|
|
1246
|
+
nprocs,
|
|
1247
|
+
alwaysmultiproc,
|
|
1248
|
+
showprogressbar,
|
|
1249
|
+
8,
|
|
1250
|
+
indexaxis=1,
|
|
1251
|
+
procunit="slices",
|
|
1252
|
+
cache=cache,
|
|
1253
|
+
debug=debug,
|
|
1254
|
+
)
|
|
1255
|
+
else:
|
|
1256
|
+
for theslice in tqdm(
|
|
1257
|
+
range(numslices),
|
|
1258
|
+
desc="Slice",
|
|
1259
|
+
unit="slices",
|
|
1260
|
+
disable=(not showprogressbar),
|
|
1261
|
+
):
|
|
1262
|
+
validlocs = validlocslist[theslice]
|
|
1263
|
+
if len(validlocs) > 0:
|
|
1264
|
+
for t in proctrs:
|
|
1265
|
+
filteredmr = -demeandata_byslice[validlocs, theslice, t]
|
|
1266
|
+
cinemr = fmri_data_byslice[validlocs, theslice, t]
|
|
1267
|
+
thevals, theweights, theindices = tide_resample.congrid(
|
|
1268
|
+
outphases,
|
|
1269
|
+
cardphasevals[theslice, t],
|
|
1270
|
+
1.0,
|
|
1271
|
+
congridbins,
|
|
1272
|
+
kernel=gridkernel,
|
|
1273
|
+
cyclic=True,
|
|
1274
|
+
cache=cache,
|
|
1275
|
+
debug=debug,
|
|
1276
|
+
)
|
|
1277
|
+
for i in range(len(theindices)):
|
|
1278
|
+
weights_byslice[validlocs, theslice, theindices[i]] += theweights[i]
|
|
1279
|
+
rawapp_byslice[validlocs, theslice, theindices[i]] += filteredmr
|
|
1280
|
+
cine_byslice[validlocs, theslice, theindices[i]] += theweights[i] * cinemr
|
|
1281
|
+
for d in range(destpoints):
|
|
1282
|
+
if weights_byslice[validlocs[0], theslice, d] == 0.0:
|
|
1283
|
+
weights_byslice[validlocs, theslice, d] = 1.0
|
|
1284
|
+
rawapp_byslice[validlocs, theslice, :] = np.nan_to_num(
|
|
1285
|
+
rawapp_byslice[validlocs, theslice, :]
|
|
1286
|
+
/ weights_byslice[validlocs, theslice, :]
|
|
1287
|
+
)
|
|
1288
|
+
cine_byslice[validlocs, theslice, :] = np.nan_to_num(
|
|
1289
|
+
cine_byslice[validlocs, theslice, :] / weights_byslice[validlocs, theslice, :]
|
|
1290
|
+
)
|
|
1291
|
+
else:
|
|
1292
|
+
rawapp_byslice[:, theslice, :] = 0.0
|
|
1293
|
+
cine_byslice[:, theslice, :] = 0.0
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
def _procOneSliceSmoothing(slice, sliceargs, **kwargs):
|
|
1297
|
+
options = {
|
|
1298
|
+
"debug": False,
|
|
1299
|
+
}
|
|
1300
|
+
options.update(kwargs)
|
|
1301
|
+
debug = options["debug"]
|
|
1302
|
+
(validlocslist, rawapp_byslice, appsmoothingfilter, phaseFs, derivatives_byslice) = sliceargs
|
|
1303
|
+
# now smooth the projected data along the time dimension
|
|
1304
|
+
validlocs = validlocslist[slice]
|
|
1305
|
+
if len(validlocs) > 0:
|
|
1306
|
+
for loc in validlocs:
|
|
1307
|
+
rawapp_byslice[loc, slice, :] = appsmoothingfilter.apply(
|
|
1308
|
+
phaseFs, rawapp_byslice[loc, slice, :]
|
|
1309
|
+
)
|
|
1310
|
+
derivatives_byslice[loc, slice, :] = circularderivs(rawapp_byslice[loc, slice, :])
|
|
1311
|
+
return slice, rawapp_byslice[:, slice, :], derivatives_byslice[:, slice, :]
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
def _packslicedataSliceSmoothing(slicenum, sliceargs):
|
|
1315
|
+
return [
|
|
1316
|
+
sliceargs[0],
|
|
1317
|
+
sliceargs[1],
|
|
1318
|
+
sliceargs[2],
|
|
1319
|
+
sliceargs[3],
|
|
1320
|
+
sliceargs[4],
|
|
1321
|
+
]
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
def _unpackslicedataSliceSmoothing(retvals, voxelproducts):
|
|
1325
|
+
(voxelproducts[0])[:, retvals[0], :] = retvals[1]
|
|
1326
|
+
(voxelproducts[1])[:, retvals[0], :] = retvals[2]
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
def tcsmoothingpass(
|
|
1330
|
+
numslices,
|
|
1331
|
+
validlocslist,
|
|
1332
|
+
rawapp_byslice,
|
|
1333
|
+
appsmoothingfilter,
|
|
1334
|
+
phaseFs,
|
|
1335
|
+
derivatives_byslice,
|
|
1336
|
+
nprocs=1,
|
|
1337
|
+
alwaysmultiproc=False,
|
|
1338
|
+
showprogressbar=True,
|
|
1339
|
+
debug=False,
|
|
1340
|
+
):
|
|
1341
|
+
inputshape = rawapp_byslice.shape
|
|
1342
|
+
sliceargs = [validlocslist, rawapp_byslice, appsmoothingfilter, phaseFs, derivatives_byslice]
|
|
1343
|
+
slicefunc = _procOneSliceSmoothing
|
|
1344
|
+
packfunc = _packslicedataSliceSmoothing
|
|
1345
|
+
unpackfunc = _unpackslicedataSliceSmoothing
|
|
1346
|
+
slicetargets = [rawapp_byslice, derivatives_byslice]
|
|
1347
|
+
slicemask = rawapp_byslice[0, :, 0] * 0.0 + 1
|
|
1348
|
+
|
|
1349
|
+
slicetotal = tide_genericmultiproc.run_multiproc(
|
|
1350
|
+
slicefunc,
|
|
1351
|
+
packfunc,
|
|
1352
|
+
unpackfunc,
|
|
1353
|
+
sliceargs,
|
|
1354
|
+
slicetargets,
|
|
1355
|
+
inputshape,
|
|
1356
|
+
slicemask,
|
|
1357
|
+
None,
|
|
1358
|
+
nprocs,
|
|
1359
|
+
alwaysmultiproc,
|
|
1360
|
+
showprogressbar,
|
|
1361
|
+
16,
|
|
1362
|
+
indexaxis=1,
|
|
1363
|
+
procunit="slices",
|
|
1364
|
+
debug=debug,
|
|
1365
|
+
)
|
|
1366
|
+
|
|
1367
|
+
|
|
1010
1368
|
def phaseproject(
|
|
1011
1369
|
input_data,
|
|
1012
1370
|
demeandata_byslice,
|
|
@@ -1039,112 +1397,156 @@ def phaseproject(
|
|
|
1039
1397
|
xsize, ysize, numslices, timepoints = input_data.getdims()
|
|
1040
1398
|
fmri_data_byslice = input_data.byslice()
|
|
1041
1399
|
|
|
1400
|
+
# first find the validlocs for each slice
|
|
1401
|
+
validlocslist = []
|
|
1402
|
+
if args.verbose:
|
|
1403
|
+
print("Finding validlocs")
|
|
1404
|
+
for theslice in range(numslices):
|
|
1405
|
+
validlocslist.append(np.where(projmask_byslice[:, theslice] > 0)[0])
|
|
1406
|
+
|
|
1407
|
+
# phase project each slice
|
|
1408
|
+
print("Phase projecting")
|
|
1409
|
+
phaseprojectpass(
|
|
1410
|
+
numslices,
|
|
1411
|
+
demeandata_byslice,
|
|
1412
|
+
fmri_data_byslice,
|
|
1413
|
+
validlocslist,
|
|
1414
|
+
proctrs,
|
|
1415
|
+
weights_byslice,
|
|
1416
|
+
cine_byslice,
|
|
1417
|
+
rawapp_byslice,
|
|
1418
|
+
outphases,
|
|
1419
|
+
cardphasevals,
|
|
1420
|
+
args.congridbins,
|
|
1421
|
+
args.gridkernel,
|
|
1422
|
+
args.destpoints,
|
|
1423
|
+
cache=args.congridcache,
|
|
1424
|
+
mpcode=args.mpphaseproject,
|
|
1425
|
+
nprocs=args.nprocs,
|
|
1426
|
+
showprogressbar=args.showprogressbar,
|
|
1427
|
+
)
|
|
1428
|
+
|
|
1429
|
+
# smooth the phase projection, if requested
|
|
1430
|
+
if args.smoothapp:
|
|
1431
|
+
print("Smoothing timecourses")
|
|
1432
|
+
tcsmoothingpass(
|
|
1433
|
+
numslices,
|
|
1434
|
+
validlocslist,
|
|
1435
|
+
rawapp_byslice,
|
|
1436
|
+
appsmoothingfilter,
|
|
1437
|
+
phaseFs,
|
|
1438
|
+
derivatives_byslice,
|
|
1439
|
+
nprocs=args.nprocs,
|
|
1440
|
+
showprogressbar=args.showprogressbar,
|
|
1441
|
+
)
|
|
1442
|
+
|
|
1443
|
+
# now do the flips
|
|
1444
|
+
print("Doing flips")
|
|
1042
1445
|
for theslice in tqdm(
|
|
1043
1446
|
range(numslices),
|
|
1044
1447
|
desc="Slice",
|
|
1045
1448
|
unit="slices",
|
|
1046
1449
|
disable=(not args.showprogressbar),
|
|
1047
1450
|
):
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
validlocs = np.where(projmask_byslice[:, theslice] > 0)[0]
|
|
1051
|
-
# indexlist = range(0, len(cardphasevals[theslice, :]))
|
|
1451
|
+
# now do the flips
|
|
1452
|
+
validlocs = validlocslist[theslice]
|
|
1052
1453
|
if len(validlocs) > 0:
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
cinemr = fmri_data_byslice[validlocs, theslice, t]
|
|
1056
|
-
thevals, theweights, theindices = tide_resample.congrid(
|
|
1057
|
-
outphases,
|
|
1058
|
-
cardphasevals[theslice, t],
|
|
1059
|
-
1.0,
|
|
1060
|
-
args.congridbins,
|
|
1061
|
-
kernel=args.gridkernel,
|
|
1062
|
-
cyclic=True,
|
|
1063
|
-
)
|
|
1064
|
-
for i in range(len(theindices)):
|
|
1065
|
-
weights_byslice[validlocs, theslice, theindices[i]] += theweights[i]
|
|
1066
|
-
# rawapp_byslice[validlocs, theslice, theindices[i]] += (
|
|
1067
|
-
# theweights[i] * filteredmr
|
|
1068
|
-
# )
|
|
1069
|
-
rawapp_byslice[validlocs, theslice, theindices[i]] += filteredmr
|
|
1070
|
-
cine_byslice[validlocs, theslice, theindices[i]] += theweights[i] * cinemr
|
|
1071
|
-
for d in range(args.destpoints):
|
|
1072
|
-
if weights_byslice[validlocs[0], theslice, d] == 0.0:
|
|
1073
|
-
weights_byslice[validlocs, theslice, d] = 1.0
|
|
1074
|
-
rawapp_byslice[validlocs, theslice, :] = np.nan_to_num(
|
|
1075
|
-
rawapp_byslice[validlocs, theslice, :] / weights_byslice[validlocs, theslice, :]
|
|
1454
|
+
appflips_byslice = np.where(
|
|
1455
|
+
-derivatives_byslice[:, :, 2] > derivatives_byslice[:, :, 0], -1.0, 1.0
|
|
1076
1456
|
)
|
|
1077
|
-
|
|
1078
|
-
|
|
1457
|
+
timecoursemean = np.mean(rawapp_byslice[validlocs, theslice, :], axis=1).reshape(
|
|
1458
|
+
(-1, 1)
|
|
1459
|
+
)
|
|
1460
|
+
if args.fliparteries:
|
|
1461
|
+
corrected_rawapp_byslice[validlocs, theslice, :] = (
|
|
1462
|
+
rawapp_byslice[validlocs, theslice, :] - timecoursemean
|
|
1463
|
+
) * appflips_byslice[validlocs, theslice, None] + timecoursemean
|
|
1464
|
+
if args.doaliasedcorrelation and (thispass > 0):
|
|
1465
|
+
for theloc in validlocs:
|
|
1466
|
+
thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
|
|
1467
|
+
-appflips_byslice[theloc, theslice]
|
|
1468
|
+
* demeandata_byslice[theloc, theslice, :],
|
|
1469
|
+
int(sliceoffsets[theslice]),
|
|
1470
|
+
)[corrstartloc : correndloc + 1]
|
|
1471
|
+
maxloc = np.argmax(thecorrfunc_byslice[theloc, theslice, :])
|
|
1472
|
+
wavedelay_byslice[theloc, theslice] = (
|
|
1473
|
+
thealiasedcorrx[corrstartloc : correndloc + 1]
|
|
1474
|
+
)[maxloc]
|
|
1475
|
+
waveamp_byslice[theloc, theslice] = np.fabs(
|
|
1476
|
+
thecorrfunc_byslice[theloc, theslice, maxloc]
|
|
1477
|
+
)
|
|
1478
|
+
wavedelayCOM_byslice[theloc, theslice] = theCOM(
|
|
1479
|
+
thealiasedcorrx[corrstartloc : correndloc + 1],
|
|
1480
|
+
np.fabs(thecorrfunc_byslice[theloc, theslice, :]),
|
|
1481
|
+
)
|
|
1482
|
+
else:
|
|
1483
|
+
corrected_rawapp_byslice[validlocs, theslice, :] = rawapp_byslice[
|
|
1484
|
+
validlocs, theslice, :
|
|
1485
|
+
]
|
|
1486
|
+
if args.doaliasedcorrelation and (thispass > 0):
|
|
1487
|
+
for theloc in validlocs:
|
|
1488
|
+
thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
|
|
1489
|
+
-demeandata_byslice[theloc, theslice, :],
|
|
1490
|
+
int(sliceoffsets[theslice]),
|
|
1491
|
+
)[corrstartloc : correndloc + 1]
|
|
1492
|
+
maxloc = np.argmax(np.abs(thecorrfunc_byslice[theloc, theslice, :]))
|
|
1493
|
+
wavedelay_byslice[theloc, theslice] = (
|
|
1494
|
+
thealiasedcorrx[corrstartloc : correndloc + 1]
|
|
1495
|
+
)[maxloc]
|
|
1496
|
+
waveamp_byslice[theloc, theslice] = np.fabs(
|
|
1497
|
+
thecorrfunc_byslice[theloc, theslice, maxloc]
|
|
1498
|
+
)
|
|
1499
|
+
timecoursemin = np.min(
|
|
1500
|
+
corrected_rawapp_byslice[validlocs, theslice, :], axis=1
|
|
1501
|
+
).reshape((-1, 1))
|
|
1502
|
+
app_byslice[validlocs, theslice, :] = (
|
|
1503
|
+
corrected_rawapp_byslice[validlocs, theslice, :] - timecoursemin
|
|
1504
|
+
)
|
|
1505
|
+
normapp_byslice[validlocs, theslice, :] = np.nan_to_num(
|
|
1506
|
+
app_byslice[validlocs, theslice, :] / means_byslice[validlocs, theslice, None]
|
|
1079
1507
|
)
|
|
1080
|
-
else:
|
|
1081
|
-
rawapp_byslice[:, theslice, :] = 0.0
|
|
1082
|
-
cine_byslice[:, theslice, :] = 0.0
|
|
1083
|
-
|
|
1084
|
-
# smooth the projected data along the time dimension
|
|
1085
|
-
if args.smoothapp:
|
|
1086
|
-
for loc in validlocs:
|
|
1087
|
-
rawapp_byslice[loc, theslice, :] = appsmoothingfilter.apply(
|
|
1088
|
-
phaseFs, rawapp_byslice[loc, theslice, :]
|
|
1089
|
-
)
|
|
1090
|
-
derivatives_byslice[loc, theslice, :] = circularderivs(
|
|
1091
|
-
rawapp_byslice[loc, theslice, :]
|
|
1092
|
-
)
|
|
1093
|
-
appflips_byslice = np.where(
|
|
1094
|
-
-derivatives_byslice[:, :, 2] > derivatives_byslice[:, :, 0], -1.0, 1.0
|
|
1095
|
-
)
|
|
1096
|
-
timecoursemean = np.mean(rawapp_byslice[validlocs, theslice, :], axis=1).reshape((-1, 1))
|
|
1097
|
-
if args.fliparteries:
|
|
1098
|
-
corrected_rawapp_byslice[validlocs, theslice, :] = (
|
|
1099
|
-
rawapp_byslice[validlocs, theslice, :] - timecoursemean
|
|
1100
|
-
) * appflips_byslice[validlocs, theslice, None] + timecoursemean
|
|
1101
|
-
if args.doaliasedcorrelation and (thispass > 0):
|
|
1102
|
-
for theloc in validlocs:
|
|
1103
|
-
thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
|
|
1104
|
-
-appflips_byslice[theloc, theslice]
|
|
1105
|
-
* demeandata_byslice[theloc, theslice, :],
|
|
1106
|
-
int(sliceoffsets[theslice]),
|
|
1107
|
-
)[corrstartloc : correndloc + 1]
|
|
1108
|
-
maxloc = np.argmax(thecorrfunc_byslice[theloc, theslice, :])
|
|
1109
|
-
wavedelay_byslice[theloc, theslice] = (
|
|
1110
|
-
thealiasedcorrx[corrstartloc : correndloc + 1]
|
|
1111
|
-
)[maxloc]
|
|
1112
|
-
waveamp_byslice[theloc, theslice] = np.fabs(
|
|
1113
|
-
thecorrfunc_byslice[theloc, theslice, maxloc]
|
|
1114
|
-
)
|
|
1115
|
-
wavedelayCOM_byslice[theloc, theslice] = theCOM(
|
|
1116
|
-
thealiasedcorrx[corrstartloc : correndloc + 1],
|
|
1117
|
-
np.fabs(thecorrfunc_byslice[theloc, theslice, :]),
|
|
1118
|
-
)
|
|
1119
|
-
else:
|
|
1120
|
-
corrected_rawapp_byslice[validlocs, theslice, :] = rawapp_byslice[
|
|
1121
|
-
validlocs, theslice, :
|
|
1122
|
-
]
|
|
1123
|
-
if args.doaliasedcorrelation and (thispass > 0):
|
|
1124
|
-
for theloc in validlocs:
|
|
1125
|
-
thecorrfunc_byslice[theloc, theslice, :] = theAliasedCorrelator.apply(
|
|
1126
|
-
-demeandata_byslice[theloc, theslice, :],
|
|
1127
|
-
int(sliceoffsets[theslice]),
|
|
1128
|
-
)[corrstartloc : correndloc + 1]
|
|
1129
|
-
maxloc = np.argmax(np.abs(thecorrfunc_byslice[theloc, theslice, :]))
|
|
1130
|
-
wavedelay_byslice[theloc, theslice] = (
|
|
1131
|
-
thealiasedcorrx[corrstartloc : correndloc + 1]
|
|
1132
|
-
)[maxloc]
|
|
1133
|
-
waveamp_byslice[theloc, theslice] = np.fabs(
|
|
1134
|
-
thecorrfunc_byslice[theloc, theslice, maxloc]
|
|
1135
|
-
)
|
|
1136
|
-
timecoursemin = np.min(corrected_rawapp_byslice[validlocs, theslice, :], axis=1).reshape(
|
|
1137
|
-
(-1, 1)
|
|
1138
|
-
)
|
|
1139
|
-
app_byslice[validlocs, theslice, :] = (
|
|
1140
|
-
corrected_rawapp_byslice[validlocs, theslice, :] - timecoursemin
|
|
1141
|
-
)
|
|
1142
|
-
normapp_byslice[validlocs, theslice, :] = np.nan_to_num(
|
|
1143
|
-
app_byslice[validlocs, theslice, :] / means_byslice[validlocs, theslice, None]
|
|
1144
|
-
)
|
|
1145
1508
|
return appflips_byslice
|
|
1146
1509
|
|
|
1147
1510
|
|
|
1511
|
+
def findvessels(
|
|
1512
|
+
app,
|
|
1513
|
+
normapp,
|
|
1514
|
+
validlocs,
|
|
1515
|
+
numspatiallocs,
|
|
1516
|
+
outputroot,
|
|
1517
|
+
unnormvesselmap,
|
|
1518
|
+
destpoints,
|
|
1519
|
+
softvesselfrac,
|
|
1520
|
+
histlen,
|
|
1521
|
+
outputlevel,
|
|
1522
|
+
debug=False,
|
|
1523
|
+
):
|
|
1524
|
+
if unnormvesselmap:
|
|
1525
|
+
app2d = app.reshape((numspatiallocs, destpoints))
|
|
1526
|
+
else:
|
|
1527
|
+
app2d = normapp.reshape((numspatiallocs, destpoints))
|
|
1528
|
+
histinput = app2d[validlocs, :].reshape((len(validlocs), destpoints))
|
|
1529
|
+
if outputlevel > 0:
|
|
1530
|
+
namesuffix = "_desc-apppeaks_hist"
|
|
1531
|
+
tide_stats.makeandsavehistogram(
|
|
1532
|
+
histinput,
|
|
1533
|
+
histlen,
|
|
1534
|
+
0,
|
|
1535
|
+
outputroot + namesuffix,
|
|
1536
|
+
debug=debug,
|
|
1537
|
+
)
|
|
1538
|
+
|
|
1539
|
+
# find vessel thresholds
|
|
1540
|
+
tide_util.logmem("before making vessel masks")
|
|
1541
|
+
hardvesselthresh = tide_stats.getfracvals(np.max(histinput, axis=1), [0.98])[0] / 2.0
|
|
1542
|
+
softvesselthresh = softvesselfrac * hardvesselthresh
|
|
1543
|
+
print(
|
|
1544
|
+
"hard, soft vessel thresholds set to",
|
|
1545
|
+
"{:.3f}".format(hardvesselthresh),
|
|
1546
|
+
"{:.3f}".format(softvesselthresh),
|
|
1547
|
+
)
|
|
1548
|
+
|
|
1549
|
+
|
|
1148
1550
|
def upsampleimage(input_data, numsteps, sliceoffsets, slicesamplerate, outputroot):
|
|
1149
1551
|
fmri_data = input_data.byvol()
|
|
1150
1552
|
timepoints = input_data.timepoints
|
|
@@ -1189,3 +1591,93 @@ def upsampleimage(input_data, numsteps, sliceoffsets, slicesamplerate, outputroo
|
|
|
1189
1591
|
)
|
|
1190
1592
|
tide_io.savetonifti(upsampleimage, theheader, outputroot + "_upsampled")
|
|
1191
1593
|
print("upsampling complete")
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
def wrightmap(
|
|
1597
|
+
input_data,
|
|
1598
|
+
demeandata_byslice,
|
|
1599
|
+
rawapp_byslice,
|
|
1600
|
+
projmask_byslice,
|
|
1601
|
+
outphases,
|
|
1602
|
+
cardphasevals,
|
|
1603
|
+
proctrs,
|
|
1604
|
+
congridbins,
|
|
1605
|
+
gridkernel,
|
|
1606
|
+
destpoints,
|
|
1607
|
+
iterations=100,
|
|
1608
|
+
nprocs=-1,
|
|
1609
|
+
verbose=False,
|
|
1610
|
+
debug=False,
|
|
1611
|
+
):
|
|
1612
|
+
xsize = input_data.xsize
|
|
1613
|
+
ysize = input_data.ysize
|
|
1614
|
+
numslices = input_data.numslices
|
|
1615
|
+
# make a vessel map using Wright's method
|
|
1616
|
+
wrightcorrs_byslice = np.zeros((xsize * ysize, numslices, iterations))
|
|
1617
|
+
# first find the validlocs for each slice
|
|
1618
|
+
validlocslist = []
|
|
1619
|
+
if verbose:
|
|
1620
|
+
print("Finding validlocs")
|
|
1621
|
+
for theslice in range(numslices):
|
|
1622
|
+
validlocslist.append(np.where(projmask_byslice[:, theslice] > 0)[0])
|
|
1623
|
+
for theiteration in range(iterations):
|
|
1624
|
+
print(f"wright iteration: {theiteration + 1} of {iterations}")
|
|
1625
|
+
# split timecourse into two sets
|
|
1626
|
+
scrambledprocs = np.random.permutation(proctrs)
|
|
1627
|
+
proctrs1 = scrambledprocs[: int(len(scrambledprocs) // 2)]
|
|
1628
|
+
proctrs2 = scrambledprocs[int(len(scrambledprocs) // 2) :]
|
|
1629
|
+
if debug:
|
|
1630
|
+
print(f"{proctrs1=}, {proctrs2=}")
|
|
1631
|
+
|
|
1632
|
+
# phase project each slice
|
|
1633
|
+
rawapp_byslice1 = rawapp_byslice * 0.0
|
|
1634
|
+
cine_byslice1 = rawapp_byslice * 0.0
|
|
1635
|
+
weights_byslice1 = rawapp_byslice * 0.0
|
|
1636
|
+
phaseprojectpass(
|
|
1637
|
+
numslices,
|
|
1638
|
+
demeandata_byslice,
|
|
1639
|
+
input_data.byslice(),
|
|
1640
|
+
validlocslist,
|
|
1641
|
+
proctrs1,
|
|
1642
|
+
weights_byslice1,
|
|
1643
|
+
cine_byslice1,
|
|
1644
|
+
rawapp_byslice1,
|
|
1645
|
+
outphases,
|
|
1646
|
+
cardphasevals,
|
|
1647
|
+
congridbins,
|
|
1648
|
+
gridkernel,
|
|
1649
|
+
destpoints,
|
|
1650
|
+
nprocs=nprocs,
|
|
1651
|
+
showprogressbar=False,
|
|
1652
|
+
)
|
|
1653
|
+
rawapp_byslice2 = rawapp_byslice * 0.0
|
|
1654
|
+
cine_byslice2 = rawapp_byslice * 0.0
|
|
1655
|
+
weights_byslice2 = rawapp_byslice * 0.0
|
|
1656
|
+
phaseprojectpass(
|
|
1657
|
+
numslices,
|
|
1658
|
+
demeandata_byslice,
|
|
1659
|
+
input_data.byslice(),
|
|
1660
|
+
validlocslist,
|
|
1661
|
+
proctrs2,
|
|
1662
|
+
weights_byslice2,
|
|
1663
|
+
cine_byslice2,
|
|
1664
|
+
rawapp_byslice2,
|
|
1665
|
+
outphases,
|
|
1666
|
+
cardphasevals,
|
|
1667
|
+
congridbins,
|
|
1668
|
+
gridkernel,
|
|
1669
|
+
destpoints,
|
|
1670
|
+
nprocs=nprocs,
|
|
1671
|
+
showprogressbar=False,
|
|
1672
|
+
)
|
|
1673
|
+
for theslice in range(numslices):
|
|
1674
|
+
for thepoint in validlocslist[theslice]:
|
|
1675
|
+
theRvalue, thepvalue = pearsonr(
|
|
1676
|
+
rawapp_byslice1[thepoint, theslice, :],
|
|
1677
|
+
rawapp_byslice2[thepoint, theslice, :],
|
|
1678
|
+
)
|
|
1679
|
+
if debug:
|
|
1680
|
+
print("theRvalue = ", theRvalue)
|
|
1681
|
+
wrightcorrs_byslice[thepoint, theslice, theiteration] = theRvalue
|
|
1682
|
+
wrightcorrs = np.mean(wrightcorrs_byslice, axis=2).reshape(xsize, ysize, numslices)
|
|
1683
|
+
return wrightcorrs
|