rapidtide 3.0.6__py3-none-any.whl → 3.0.7.1__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.
@@ -297,6 +297,8 @@ def showarbcorr(args):
297
297
  sys.exit()
298
298
  if starttime1 == None:
299
299
  starttime1 = 0.0
300
+ endtime1 = starttime1 + len(inputdata1) / Fs1
301
+ print(f"inputdata1 goes from {starttime1} to {endtime1}")
300
302
 
301
303
  if args.samplerate2 is not None:
302
304
  Fs2 = args.samplerate2
@@ -305,9 +307,19 @@ def showarbcorr(args):
305
307
  sys.exit()
306
308
  if starttime2 == None:
307
309
  starttime2 = 0.0
310
+ endtime2 = starttime2 + len(inputdata2) / Fs2
311
+ print(f"inputdata2 goes from {starttime2} to {endtime2}")
308
312
 
309
- trimdata1 = inputdata1
310
- trimdata2 = inputdata2
313
+ matchedinput1, matchedinput2, commonFs = tide_corr.matchsamplerates(
314
+ inputdata1,
315
+ Fs1,
316
+ inputdata2,
317
+ Fs2,
318
+ method="univariate",
319
+ debug=args.debug,
320
+ )
321
+ trimdata1 = matchedinput1
322
+ trimdata2 = matchedinput2
311
323
 
312
324
  if args.trimdata:
313
325
  minlen = np.min([len(trimdata1), len(trimdata2)])
@@ -324,12 +336,12 @@ def showarbcorr(args):
324
336
  if args.verbose:
325
337
  print("filtering to ", theprefilter.gettype(), " band")
326
338
  filtereddata1 = tide_math.corrnormalize(
327
- theprefilter.apply(Fs1, trimdata1),
339
+ theprefilter.apply(commonFs, trimdata1),
328
340
  detrendorder=args.detrendorder,
329
341
  windowfunc=args.windowfunc,
330
342
  )
331
343
  filtereddata2 = tide_math.corrnormalize(
332
- theprefilter.apply(Fs2, trimdata2),
344
+ theprefilter.apply(commonFs, trimdata2),
333
345
  detrendorder=args.detrendorder,
334
346
  windowfunc=args.windowfunc,
335
347
  )
@@ -341,9 +353,9 @@ def showarbcorr(args):
341
353
  print(f"{Fs1=}, {Fs2=}, {starttime1=}, {starttime2=}, {args.windowfunc=}")
342
354
  xcorr_x, thexcorr, corrFs, zeroloc = tide_corr.arbcorr(
343
355
  filtereddata1,
344
- Fs1,
356
+ commonFs,
345
357
  filtereddata2,
346
- Fs2,
358
+ commonFs,
347
359
  start1=starttime1,
348
360
  start2=starttime2,
349
361
  windowfunc=args.windowfunc,
@@ -375,6 +387,7 @@ def showarbcorr(args):
375
387
  thexcorr_trim = thexcorr[lowerlim:upperlim]
376
388
  print("trimmed Correlator lengths (x, y):", len(xcorr_x_trim), len(thexcorr_trim))
377
389
 
390
+ print(f"{len(filtereddata1)=}, {len(filtereddata2)=}")
378
391
  thepxcorr = pearsonr(filtereddata1, filtereddata2)
379
392
 
380
393
  # initialize the correlation fitter
@@ -18,12 +18,13 @@
18
18
  #
19
19
  import argparse
20
20
 
21
- import numpy as np
22
21
  from matplotlib.pyplot import *
23
22
 
23
+ import rapidtide.filter as tide_filt
24
24
  import rapidtide.io as tide_io
25
25
  import rapidtide.miscmath as tide_math
26
26
  import rapidtide.resample as tide_resample
27
+ import rapidtide.voxelData as tide_voxelData
27
28
  import rapidtide.workflows.parser_funcs as pf
28
29
 
29
30
 
@@ -38,21 +39,30 @@ def _get_parser():
38
39
  )
39
40
 
40
41
  # Required arguments
41
- pf.addreqinputniftifile(
42
- parser, "fmrifilename", addedtext="An exemplar BOLD fMRI file with the target dimensions"
42
+ parser.add_argument(
43
+ "fmritr",
44
+ type=lambda x: pf.is_float(parser, x, minval=0.0),
45
+ help="TR of the simulated data, in seconds.",
46
+ )
47
+ parser.add_argument(
48
+ "numtrs",
49
+ type=lambda x: pf.is_int(parser, x, minval=1),
50
+ help="Number of TRs in the simulated data.",
43
51
  )
44
52
  pf.addreqinputniftifile(
45
53
  parser, "immeanfilename", addedtext="3D file with the mean value for each voxel"
46
54
  )
47
55
  parser.add_argument("outputroot", type=str, help="Root name for the output files.")
48
- parser.add_argument(
49
- "slicetimefile",
50
- type=str,
51
- help="Slice acquisition time file, either FSL format or BIDS sidecar.",
52
- )
53
56
 
54
57
  for band in ["lfo", "resp", "cardiac"]:
55
- parser.add_argument(
58
+ if band == "lfo":
59
+ bandopts = parser.add_argument_group("LFO band options")
60
+ elif band == "resp":
61
+ bandopts = parser.add_argument_group("Resp band options")
62
+ else:
63
+ bandopts = parser.add_argument_group("Cardiac band options")
64
+ strengthopts = bandopts.add_mutually_exclusive_group()
65
+ strengthopts.add_argument(
56
66
  f"--{band}pctfile",
57
67
  dest=(f"{band}pctfile"),
58
68
  action="store",
@@ -61,7 +71,18 @@ def _get_parser():
61
71
  help=(f"3D NIFTI file with the {band} amplitude in percent of mean at every point"),
62
72
  default=None,
63
73
  )
64
- parser.add_argument(
74
+ strengthopts.add_argument(
75
+ f"--{band}signalfraction",
76
+ dest=(f"{band}sigfracfile"),
77
+ action="store",
78
+ type=lambda x: pf.is_valid_file(parser, x),
79
+ metavar="FILE",
80
+ help=(
81
+ f"3D NIFTI file with the {band} amplitude expressed as the percentage of inband variance accounted for by the regressor"
82
+ ),
83
+ default=None,
84
+ )
85
+ bandopts.add_argument(
65
86
  f"--{band}lagfile",
66
87
  dest=(f"{band}lagfile"),
67
88
  action="store",
@@ -70,7 +91,7 @@ def _get_parser():
70
91
  help=(f"3D NIFTI file with the {band} delay value in seconds at every point"),
71
92
  default=None,
72
93
  )
73
- parser.add_argument(
94
+ bandopts.add_argument(
74
95
  f"--{band}regressor",
75
96
  dest=(f"{band}regressor"),
76
97
  action="store",
@@ -79,7 +100,7 @@ def _get_parser():
79
100
  help=(f"The {band} regressor text file"),
80
101
  default=None,
81
102
  )
82
- parser.add_argument(
103
+ bandopts.add_argument(
83
104
  f"--{band}samprate",
84
105
  dest=(f"{band}samprate"),
85
106
  action="store",
@@ -88,7 +109,7 @@ def _get_parser():
88
109
  help=(f"The sample rate of the {band} regressor file, in Hz"),
89
110
  default=None,
90
111
  )
91
- parser.add_argument(
112
+ bandopts.add_argument(
92
113
  f"--{band}starttime",
93
114
  dest=(f"{band}starttime"),
94
115
  action="store",
@@ -103,6 +124,16 @@ def _get_parser():
103
124
  )
104
125
 
105
126
  # optional arguments
127
+ parser.add_argument(
128
+ "--slicetimefile",
129
+ dest="slicetimefile",
130
+ action="store",
131
+ type=str,
132
+ metavar="FILE",
133
+ help="Slice acquisition time file, either FSL format or BIDS sidecar.",
134
+ default=None,
135
+ )
136
+
106
137
  parser.add_argument(
107
138
  "--numskip",
108
139
  dest="numskip",
@@ -127,7 +158,9 @@ def _get_parser():
127
158
  action="store",
128
159
  type=float,
129
160
  metavar="LEVEL",
130
- help=("The variance of the voxel specific noise. Default is 0.0"),
161
+ help=(
162
+ "The variance of the voxel specific noise, as percent of the voxel mean. Default is 0.0"
163
+ ),
131
164
  default=0.0,
132
165
  )
133
166
  parser.add_argument(
@@ -144,8 +177,9 @@ def _get_parser():
144
177
 
145
178
 
146
179
  def prepareband(
147
- fmridims,
180
+ simdatadims,
148
181
  pctfile,
182
+ sigfracfile,
149
183
  lagfile,
150
184
  regressorfile,
151
185
  samprate,
@@ -155,8 +189,9 @@ def prepareband(
155
189
  debug=False,
156
190
  ):
157
191
  if debug:
158
- print("fmridims:", fmridims)
192
+ print("simdatadims:", simdatadims)
159
193
  print("pctfile:", pctfile)
194
+ print("sigfracfile:", sigfracfile)
160
195
  print("lagfile:", lagfile)
161
196
  print("regressorfile:", regressorfile)
162
197
  print("regressorname:", regressorname)
@@ -204,44 +239,66 @@ def prepareband(
204
239
  regressor_x[-1],
205
240
  )
206
241
 
207
- nim_pct, pctdata, pctheader, pctdims, pctsizes = tide_io.readfromnifti(pctfile)
208
- if not tide_io.checkspacedimmatch(pctdims, fmridims):
209
- print(regressorname, "pct file does not match fmri")
210
- exit()
242
+ if pctfile is not None:
243
+ nim_pct, pctdata, pctheader, pctdims, pctsizes = tide_io.readfromnifti(pctfile)
244
+ pctscale = True
245
+ else:
246
+ nim_pct, pctdata, pctheader, pctdims, pctsizes = tide_io.readfromnifti(sigfracfile)
247
+ pctscale = False
248
+ if not tide_io.checkspacedimmatch(pctdims, simdatadims):
249
+ print(regressorname, "pct file does not match fmri")
250
+ exit()
251
+ pctdata /= 100.0
211
252
  nim_lag, lagdata, lagheader, lagdims, lagsizes = tide_io.readfromnifti(lagfile)
212
- if not tide_io.checkspacedimmatch(lagdims, fmridims):
253
+ if not tide_io.checkspacedimmatch(lagdims, simdatadims):
213
254
  print(regressorname, "lag file does not match fmri")
214
255
  exit()
215
256
 
216
257
  generator = tide_resample.FastResampler(
217
258
  regressor_x, regressor_y, padtime=padtime, doplot=False
218
259
  )
219
- return pctdata, lagdata, generator
260
+ return pctdata, pctscale, lagdata, generator
220
261
 
221
262
 
222
263
  def fmrisignal(
264
+ Fs,
223
265
  times,
224
266
  meanvalue,
225
267
  dolfo=False,
226
268
  lfowave=None,
227
269
  lfomag=None,
228
270
  lfodelay=None,
271
+ lfonoise=0.0,
272
+ lfofilter=None,
229
273
  doresp=False,
230
274
  respwave=None,
231
275
  respmag=None,
232
276
  respdelay=None,
277
+ respnoise=0.0,
278
+ respfilter=None,
233
279
  docardiac=False,
234
280
  cardiacwave=None,
235
281
  cardiacmag=None,
236
282
  cardiacdelay=None,
283
+ cardiacnoise=0.0,
284
+ cardiacfilter=None,
237
285
  ):
238
286
  thesignal = np.zeros((len(times)), dtype=float)
239
287
  if dolfo:
240
- thesignal += meanvalue * (lfomag / 100.0) * lfowave.yfromx(times - lfodelay)
288
+ thesignal += meanvalue * (
289
+ lfomag * lfowave.yfromx(times - lfodelay)
290
+ + lfonoise * lfofilter.apply(Fs, np.random.standard_normal(len(times)))
291
+ )
241
292
  if doresp:
242
- thesignal += meanvalue * (respmag / 100.0) * respwave.yfromx(times - respdelay)
293
+ thesignal += meanvalue * (
294
+ respmag * respwave.yfromx(times - respdelay)
295
+ + respnoise * respfilter.apply(Fs, np.random.standard_normal(len(times)))
296
+ )
243
297
  if docardiac:
244
- thesignal += meanvalue * (cardiacmag / 100.0) * cardiacwave.yfromx(times - cardiacdelay)
298
+ thesignal += meanvalue * (
299
+ cardiacmag * cardiacwave.yfromx(times - cardiacdelay)
300
+ + cardiacnoise * cardiacfilter.apply(Fs, np.random.standard_normal(len(times)))
301
+ )
245
302
  return thesignal + meanvalue
246
303
 
247
304
 
@@ -250,33 +307,38 @@ def simdata(args):
250
307
  lfopctdata = None
251
308
  lfolagdata = None
252
309
  lfogenerator = None
310
+ lfofilter = None
253
311
 
254
312
  resppctdata = None
255
313
  resplagdata = None
256
314
  respgenerator = None
315
+ respfilter = None
257
316
 
258
317
  cardiacpctdata = None
259
318
  cardiaclagdata = None
260
319
  cardiacgenerator = None
320
+ cardiacfilter = None
261
321
 
262
322
  # check for complete information
263
323
  if (
264
- (args.lfopctfile is None)
324
+ ((args.lfopctfile is None) and (args.lfosigfracfile is None))
265
325
  or (args.lfolagfile is None)
266
326
  or (args.lforegressor is None)
267
327
  or ((args.lfosamprate is None) and (tide_io.parsefilespec(args.lforegressor)[1] is None))
268
328
  ):
269
329
  print("lfopctfile:", args.lfopctfile)
330
+ print("lfosigfracfile:", args.lfosigfracfile)
270
331
  print("lfolagfile:", args.lfolagfile)
271
332
  print("lforegressor:", args.lforegressor)
272
333
  print("lfopctsamprate:", args.lfosamprate)
273
334
  dolfo = False
274
335
  else:
275
336
  dolfo = True
337
+ lfofilter = tide_filt.NoncausalFilter("lfo")
276
338
  print("LFO information is complete, will be included.")
277
339
 
278
340
  if (
279
- (args.resppctfile is None)
341
+ ((args.resppctfile is None) and (args.respsigfracfile is None))
280
342
  or (args.resplagfile is None)
281
343
  or (args.respregressor is None)
282
344
  or ((args.respsamprate is None) and (tide_io.parsefilespec(args.respregressor)[1] is None))
@@ -284,10 +346,11 @@ def simdata(args):
284
346
  doresp = False
285
347
  else:
286
348
  doresp = True
349
+ respfilter = tide_filt.NoncausalFilter("resp")
287
350
  print("Respiratory information is complete, will be included.")
288
351
 
289
352
  if (
290
- (args.cardiacpctfile is None)
353
+ ((args.cardiacpctfile is None) and (args.cardiacsigfracfile is None))
291
354
  or (args.cardiaclagfile is None)
292
355
  or (args.cardiacregressor is None)
293
356
  or (
@@ -298,6 +361,7 @@ def simdata(args):
298
361
  docardiac = False
299
362
  else:
300
363
  docardiac = True
364
+ cardiacfilter = tide_filt.NoncausalFilter("cardiac")
301
365
  print("Cardiac information is complete, will be included.")
302
366
  if not (dolfo or doresp or docardiac):
303
367
  print(
@@ -306,23 +370,17 @@ def simdata(args):
306
370
  _get_parser().print_help()
307
371
  sys.exit()
308
372
 
309
- sliceoffsettimes, normalizedtotr, fileisjson = tide_io.getslicetimesfromfile(
310
- args.slicetimefile
311
- )
312
-
313
- fmritr, numtrs = tide_io.fmritimeinfo(args.fmrifilename)
314
- if normalizedtotr:
315
- sliceoffsettimes *= fmritr
316
-
317
- nim_fmri, fmridata, fmriheader, fmridims, fmrisizes = tide_io.readfromnifti(args.fmrifilename)
318
- print(f"fmri data: {numtrs} timepoints, tr = {fmritr}")
373
+ print(f"simulated fmri data: {args.numtrs} timepoints, tr = {args.fmritr}")
319
374
 
320
375
  # prepare the output timepoints
321
376
  initial_fmri_x = (
322
377
  np.linspace(
323
- 0.0, fmritr * (numtrs - args.numskip), num=(numtrs - args.numskip), endpoint=False
378
+ 0.0,
379
+ args.fmritr * (args.numtrs - args.numskip),
380
+ num=(args.numtrs - args.numskip),
381
+ endpoint=False,
324
382
  )
325
- + fmritr * args.numskip
383
+ + args.fmritr * args.numskip
326
384
  )
327
385
  print("length of fmri after removing skip:", len(initial_fmri_x))
328
386
  print(
@@ -332,34 +390,36 @@ def simdata(args):
332
390
 
333
391
  # read in the immean file
334
392
  print("reading in source files")
335
- (
336
- nim_immean,
337
- immeandata,
338
- immeanheader,
339
- immeandims,
340
- immeansizes,
341
- ) = tide_io.readfromnifti(args.immeanfilename)
342
- if not tide_io.checkspacedimmatch(immeandims, fmridims):
343
- print("immean file does not match")
344
- exit()
393
+ theimmeandata = tide_voxelData.VoxelData(args.immeanfilename, timestep=args.fmritr)
394
+ immeandata = theimmeandata.byvol()
345
395
 
346
396
  # now set up the simulated data array
347
- thedims = fmridims
348
- xsize = thedims[1]
349
- ysize = thedims[2]
350
- numslices = thedims[3]
351
- simdata = np.zeros((xsize, ysize, numslices, len(initial_fmri_x)), dtype="float")
397
+ simdataheader = theimmeandata.copyheader(
398
+ numtimepoints=len(initial_fmri_x), tr=args.fmritr, toffset=args.numskip * args.fmritr
399
+ )
400
+ simdatadims = simdataheader["dim"].copy()
401
+ xsize, ysize, numslices, timepoints = tide_io.parseniftidims(simdatadims)
402
+ simdata = np.zeros((xsize, ysize, numslices, timepoints), dtype="float")
403
+
404
+ # read in the slicetimes file if we have one
405
+ if args.slicetimefile is not None:
406
+ sliceoffsettimes, normalizedtotr, fileisjson = tide_io.getslicetimesfromfile(
407
+ args.slicetimefile
408
+ )
409
+ else:
410
+ sliceoffsettimes = np.zeros((numslices), dtype=float)
352
411
 
353
412
  # set up fast resampling
354
413
  padtime = 60.0
355
- numpadtrs = int(padtime / fmritr)
356
- padtime = fmritr * numpadtrs
414
+ numpadtrs = int(padtime / args.fmritr)
415
+ padtime = args.fmritr * numpadtrs
357
416
 
358
417
  # prepare the input data for interpolation
359
418
  if dolfo:
360
- lfopctdata, lfolagdata, lfogenerator = prepareband(
361
- fmridims,
419
+ lfopctdata, lfopctscale, lfolagdata, lfogenerator = prepareband(
420
+ simdatadims,
362
421
  args.lfopctfile,
422
+ args.lfosigfracfile,
363
423
  args.lfolagfile,
364
424
  args.lforegressor,
365
425
  args.lfosamprate,
@@ -369,9 +429,10 @@ def simdata(args):
369
429
  debug=args.debug,
370
430
  )
371
431
  if doresp:
372
- resppctdata, resplagdata, respgenerator = prepareband(
373
- fmridims,
432
+ resppctdata, resppctscale, resplagdata, respgenerator = prepareband(
433
+ simdatadims,
374
434
  args.resppctfile,
435
+ args.respsigfracfile,
375
436
  args.resplagfile,
376
437
  args.respregressor,
377
438
  args.respsamprate,
@@ -381,9 +442,10 @@ def simdata(args):
381
442
  debug=args.debug,
382
443
  )
383
444
  if docardiac:
384
- cardiacpctdata, cardiaclagdata, cardiacgenerator = prepareband(
385
- fmridims,
445
+ cardiacpctdata, cardiacpctscale, cardiaclagdata, cardiacgenerator = prepareband(
446
+ simdatadims,
386
447
  args.cardiacpctfile,
448
+ args.cardiacsigfracfile,
387
449
  args.cardiaclagfile,
388
450
  args.cardiacregressor,
389
451
  args.cardiacsamprate,
@@ -408,42 +470,64 @@ def simdata(args):
408
470
  # add in the signals
409
471
  if dolfo:
410
472
  lfopct = lfopctdata[i, j, k]
473
+ if lfopctscale:
474
+ lfonoise = 0.0
475
+ else:
476
+ lfonoise = 1.0 - lfopct
411
477
  lfolag = lfolagdata[i, j, k]
412
478
  else:
413
479
  lfopct = 0.0
414
480
  lfolag = 0.0
481
+ lfonoise = 0.0
415
482
  if doresp:
416
483
  resppct = resppctdata[i, j, k]
484
+ if resppctscale:
485
+ respnoise = 0.0
486
+ else:
487
+ respnoise = 1.0 - resppct
417
488
  resplag = resplagdata[i, j, k]
418
489
  else:
419
490
  resppct = 0.0
420
491
  resplag = 0.0
492
+ respnoise = 0.0
421
493
  if docardiac:
422
494
  cardiacpct = cardiacpctdata[i, j, k]
495
+ if cardiacpctscale:
496
+ cardiacnoise = 0.0
497
+ else:
498
+ cardiacnoise = 1.0 - cardiacpct
423
499
  cardiaclag = cardiaclagdata[i, j, k]
424
500
  else:
425
501
  cardiacpct = 0.0
426
502
  cardiaclag = 0.0
503
+ cardiacnoise = 0.0
427
504
 
428
505
  simdata[i, j, k, :] = (
429
506
  fmrisignal(
507
+ (1.0 / args.fmritr),
430
508
  fmri_x_slice,
431
509
  immeandata[i, j, k],
432
510
  dolfo=dolfo,
433
511
  lfowave=lfogenerator,
434
512
  lfomag=lfopct,
435
513
  lfodelay=lfolag,
514
+ lfonoise=lfonoise,
515
+ lfofilter=lfofilter,
436
516
  doresp=doresp,
437
517
  respwave=respgenerator,
438
518
  respmag=resppct,
439
519
  respdelay=resplag,
520
+ respnoise=respnoise,
521
+ respfilter=respfilter,
440
522
  docardiac=docardiac,
441
523
  cardiacwave=cardiacgenerator,
442
524
  cardiacmag=cardiacpct,
443
525
  cardiacdelay=cardiaclag,
526
+ cardiacnoise=cardiacnoise,
527
+ cardiacfilter=cardiacfilter,
444
528
  )
445
529
  + theglobalnoise
446
- + thevoxelnoise
530
+ + (thevoxelnoise) / 100.0 * immeandata[i, j, k]
447
531
  )
448
532
 
449
- tide_io.savetonifti(simdata, fmriheader, args.outputroot)
533
+ tide_io.savetonifti(simdata, simdataheader, args.outputroot)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rapidtide
3
- Version: 3.0.6
3
+ Version: 3.0.7.1
4
4
  Summary: Tools for performing correlation analysis on fMRI data.
5
5
  Author: Taylor Salo, Daniel M. Drucker, Ph.D., Jeffrey N Stout, Yaroslav O. Halchenko, Derek Monroe
6
6
  Author-email: "Blaise deB. Frederick" <blaise.frederick@gmail.com>