Skip to content

Commit d3c1a41

Browse files
committed
feat: Add implementation of FSL RMS Deviation (rmsd)
1 parent f53185e commit d3c1a41

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

fmriprep/interfaces/confounds.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,58 @@ def _run_interface(self, runtime):
9090
return runtime
9191

9292

93+
class _FSLRMSDeviationInputSpec(BaseInterfaceInputSpec):
94+
xfm_file = File(exists=True, desc='Head motion transform file')
95+
boldref_file = File(exists=True, desc='BOLD reference file')
96+
97+
98+
class _FSLRMSDeviationOutputSpec(TraitedSpec):
99+
out_file = File(desc='Output motion parameters file')
100+
101+
102+
class FSLRMSDeviation(SimpleInterface):
103+
"""Reconstruct FSL root mean square deviation from affine transforms."""
104+
105+
input_spec = _FSLRMSDeviationInputSpec
106+
output_spec = _FSLRMSDeviationOutputSpec
107+
108+
def _run_interface(self, runtime):
109+
self._results['out_file'] = fname_presuffix(
110+
self.inputs.boldref_file, suffix='_motion.tsv', newpath=runtime.cwd
111+
)
112+
113+
boldref = nb.load(self.inputs.boldref_file)
114+
hmc = nt.linear.load(self.inputs.xfm_file)
115+
116+
center = 0.5 * (np.array(boldref.shape[:3]) - 1) * boldref.header.get_zooms()[:3]
117+
118+
# Revert to vox2vox transforms
119+
fsl_hmc = nt.io.fsl.FSLLinearTransformArray.from_ras(
120+
hmc.matrix, reference=boldref, moving=boldref
121+
)
122+
fsl_matrix = np.stack([xfm['parameters'] for xfm in fsl_hmc.xforms])
123+
124+
diff = fsl_matrix[1:] @ np.linalg.inv(fsl_matrix[:-1]) - np.eye(4)
125+
M = diff[:, :3, :3]
126+
t = diff[:, :3, 3] + M @ center
127+
Rmax = 80.0
128+
129+
rmsd = np.concatenate(
130+
[
131+
[np.nan],
132+
np.sqrt(
133+
np.diag(t @ t.T)
134+
+ np.trace(M.transpose(0, 2, 1) @ M, axis1=1, axis2=2) * Rmax**2 / 5
135+
),
136+
]
137+
)
138+
139+
params = pd.DataFrame(data=rmsd, columns=['rmsd'])
140+
params.to_csv(self._results['out_file'], sep='\t', index=False, na_rep='n/a')
141+
142+
return runtime
143+
144+
93145
class _FSLMotionParamsInputSpec(BaseInterfaceInputSpec):
94146
xfm_file = File(exists=True, desc='Head motion transform file')
95147
boldref_file = File(exists=True, desc='BOLD reference file')

0 commit comments

Comments
 (0)