Skip to content

Commit 18dfabe

Browse files
authored
Merge pull request #1929 from clane9/fdj-center
Add optional volume center to FD-J calculation
2 parents 7b13bce + 6509674 commit 18dfabe

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3030
- Added NodeBlock information to `pypeline.log` when verbose debugging is on
3131
- Added the ability to ingress FreeSurfer data into CPAC
3232
- Added the ability to toggle FreeSurfer derived masks for brain extraction
33+
- Added an optional volume center to FD-J calculation
3334

3435
### Changed
3536
- Freesurfer output directory ingress moved to the data configuration YAML

CPAC/generate_motion_statistics/generate_motion_statistics.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,21 +324,31 @@ def calculate_FD_P(in_file):
324324
return out_file
325325

326326

327-
def calculate_FD_J(in_file, motion_correct_tool='3dvolreg'):
327+
def calculate_FD_J(in_file, motion_correct_tool='3dvolreg', center=None):
328328
"""
329329
Method to calculate framewise displacement as per Jenkinson et al. 2002
330330
331331
Parameters
332332
----------
333333
in_file : string
334-
matrix transformations from volume alignment file path
334+
matrix transformations from volume alignment file path if
335+
motion_correct_tool is '3dvolreg', or FDRMS (*_rel.rms) output if
336+
motion_correct_tool is 'mcflirt'.
337+
motion_correct_tool : string
338+
motion correction tool used, '3dvolreg' or 'mcflirt'.
339+
center : ndarray
340+
optional volume center for the calculation.
335341
336342
Returns
337343
-------
338344
out_file : string
339345
Frame-wise displacement file path
340346
341347
"""
348+
if center is None:
349+
center = np.zeros((3, 1))
350+
else:
351+
center = np.asarray(center).reshape((3, 1))
342352

343353
if motion_correct_tool == '3dvolreg':
344354
pm_ = np.genfromtxt(in_file)
@@ -359,7 +369,7 @@ def calculate_FD_J(in_file, motion_correct_tool='3dvolreg'):
359369

360370
M = np.dot(T_rb, np.linalg.inv(T_rb_prev)) - np.eye(4)
361371
A = M[0:3, 0:3]
362-
b = M[0:3, 3]
372+
b = M[0:3, 3:4] + A @ center
363373

364374
fd[i] = np.sqrt(
365375
(rmax * rmax / 5) * np.trace(np.dot(A.T, A)) + np.dot(b.T, b)
@@ -370,13 +380,39 @@ def calculate_FD_J(in_file, motion_correct_tool='3dvolreg'):
370380
elif motion_correct_tool == 'mcflirt':
371381
rel_rms = np.loadtxt(in_file)
372382
fd = np.append(0, rel_rms)
383+
384+
else:
385+
raise ValueError(f"motion_correct_tool {motion_correct_tool} not supported")
373386

374387
out_file = os.path.join(os.getcwd(), 'FD_J.1D')
375388
np.savetxt(out_file, fd, fmt='%.8f')
376389

377390
return out_file
378391

379392

393+
def find_volume_center(img_file):
394+
"""
395+
Find the center of mass of a Nifti image volume
396+
397+
Parameters
398+
----------
399+
img_file : string (nifti file)
400+
path to nifti volume image
401+
402+
Returns
403+
-------
404+
center : ndarray
405+
volume center of mass vector
406+
"""
407+
img = nb.load(img_file)
408+
dim = np.array(img.header["dim"][1:4])
409+
pixdim = np.array(img.header["pixdim"][1:4])
410+
# Calculation follows MCFLIRT
411+
# https://github.com/fithisux/FSL/blob/7aa2932949129f5c61af912ea677d4dbda843895/src/mcflirt/mcflirt.cc#L479
412+
center = 0.5 * (dim - 1) * pixdim
413+
return center
414+
415+
380416
def gen_motion_parameters(subject_id, scan_id, movement_parameters,
381417
max_displacement, motion_correct_tool):
382418
"""

0 commit comments

Comments
 (0)