30
30
class ComputeDVARSInputSpec (BaseInterfaceInputSpec ):
31
31
in_file = File (exists = True , mandatory = True , desc = 'functional data, after HMC' )
32
32
in_mask = File (exists = True , mandatory = True , desc = 'a brain mask' )
33
+ remove_zerovariance = traits .Bool (False , usedefault = True ,
34
+ desc = 'remove voxels with zero variance' )
33
35
save_std = traits .Bool (True , usedefault = True ,
34
36
desc = 'save standardized DVARS' )
35
37
save_nstd = traits .Bool (False , usedefault = True ,
@@ -120,7 +122,8 @@ def _gen_fname(self, suffix, ext=None):
120
122
return op .abspath ('{}_{}.{}' .format (fname , suffix , ext ))
121
123
122
124
def _run_interface (self , runtime ):
123
- dvars = compute_dvars (self .inputs .in_file , self .inputs .in_mask )
125
+ dvars = compute_dvars (self .inputs .in_file , self .inputs .in_mask ,
126
+ remove_zerovariance = self .inputs .remove_zerovariance )
124
127
125
128
self ._results ['avg_std' ] = dvars [0 ].mean ()
126
129
self ._results ['avg_nstd' ] = dvars [1 ].mean ()
@@ -180,6 +183,8 @@ def _run_interface(self, runtime):
180
183
header = 'std DVARS\t non-std DVARS\t vx-wise std DVARS' )
181
184
self ._results ['out_all' ] = out_file
182
185
186
+ return runtime
187
+
183
188
def _list_outputs (self ):
184
189
return self ._results
185
190
@@ -250,7 +255,6 @@ def _run_interface(self, runtime):
250
255
}
251
256
np .savetxt (self .inputs .out_file , fd_res )
252
257
253
-
254
258
if self .inputs .save_plot :
255
259
tr = None
256
260
if isdefined (self .inputs .series_tr ):
@@ -266,13 +270,14 @@ def _run_interface(self, runtime):
266
270
format = self .inputs .out_figure [- 3 :],
267
271
bbox_inches = 'tight' )
268
272
fig .clf ()
273
+
269
274
return runtime
270
275
271
276
def _list_outputs (self ):
272
277
return self ._results
273
278
274
279
275
- def compute_dvars (in_file , in_mask ):
280
+ def compute_dvars (in_file , in_mask , remove_zerovariance = False ):
276
281
"""
277
282
Compute the :abbr:`DVARS (D referring to temporal
278
283
derivative of timecourses, VARS referring to RMS variance over voxels)`
@@ -313,24 +318,32 @@ def compute_dvars(in_file, in_mask):
313
318
raise RuntimeError (
314
319
"Input fMRI dataset should be 4-dimensional" )
315
320
316
- # Remove zero-variance voxels across time axis
317
- zv_mask = zero_variance (func , mask )
318
- idx = np .where (zv_mask > 0 )
319
- mfunc = func [idx [0 ], idx [1 ], idx [2 ], :]
320
-
321
321
# Robust standard deviation
322
- func_sd = (np .percentile (mfunc , 75 ) -
323
- np .percentile (mfunc , 25 )) / 1.349
322
+ func_sd = (np .percentile (func , 75 , axis = 3 ) -
323
+ np .percentile (func , 25 , axis = 3 )) / 1.349
324
+ func_sd [mask <= 0 ] = 0
325
+
326
+ # ar1_img = np.zeros_like(func_sd)
327
+ # ar1_img[idx] = diff_SDhat
328
+ nb .Nifti1Image (func_sd , nb .load (in_mask ).get_affine ()).to_filename ('func_sd.nii.gz' )
329
+
330
+
331
+ if remove_zerovariance :
332
+ # Remove zero-variance voxels across time axis
333
+ mask = zero_variance (func , mask )
334
+
335
+ idx = np .where (mask > 0 )
336
+ mfunc = func [idx [0 ], idx [1 ], idx [2 ], :]
324
337
325
338
# Demean
326
339
mfunc -= mfunc .mean (axis = 1 ).astype (np .float32 )[..., np .newaxis ]
327
340
328
- # AR1
329
- ak_coeffs = np .apply_along_axis (AR_est_YW , 1 , mfunc , 1 )
341
+ # Compute (non-robust) estimate of lag-1 autocorrelation
342
+ ar1 = np .apply_along_axis (AR_est_YW , 1 , mfunc , 1 )[:, 0 ]
330
343
331
- # Predicted standard deviation of temporal derivative
332
- func_sd_pd = np .squeeze (np .sqrt ((2. * ( 1. - ak_coeffs [:, 0 ])) .tolist ()) * func_sd )
333
- diff_sd_mean = func_sd_pd [ func_sd_pd > 0 ] .mean ()
344
+ # Compute (predicted) standard deviation of temporal difference time series
345
+ diff_SDhat = np .squeeze (np .sqrt ((( 1 - ar1 ) * 2 ) .tolist ())) * func_sd [ mask > 0 ]. reshape ( - 1 )
346
+ diff_sd_mean = diff_SDhat .mean ()
334
347
335
348
# Compute temporal difference time series
336
349
func_diff = np .diff (mfunc , axis = 1 )
@@ -342,7 +355,7 @@ def compute_dvars(in_file, in_mask):
342
355
dvars_stdz = dvars_nstd / diff_sd_mean
343
356
344
357
# voxelwise standardization
345
- diff_vx_stdz = func_diff / np .array ([func_sd_pd ] * func_diff .shape [- 1 ]).T
358
+ diff_vx_stdz = func_diff / np .array ([diff_SDhat ] * func_diff .shape [- 1 ]).T
346
359
dvars_vx_stdz = diff_vx_stdz .std (axis = 0 , ddof = 1 )
347
360
348
361
return (dvars_stdz , dvars_nstd , dvars_vx_stdz )
0 commit comments