@@ -90,6 +90,58 @@ def _run_interface(self, runtime):
90
90
return runtime
91
91
92
92
93
+ class _FSLRMSDeviationInputSpec (BaseInterfaceInputSpec ):
94
+ xfm_file = File (exists = True , mandatory = True , desc = 'Head motion transform file' )
95
+ boldref_file = File (exists = True , mandatory = 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
+
93
145
class _FSLMotionParamsInputSpec (BaseInterfaceInputSpec ):
94
146
xfm_file = File (exists = True , desc = 'Head motion transform file' )
95
147
boldref_file = File (exists = True , desc = 'BOLD reference file' )
@@ -139,7 +191,7 @@ def _run_interface(self, runtime):
139
191
columns = ['trans_x' , 'trans_y' , 'trans_z' , 'rot_x' , 'rot_y' , 'rot_z' ],
140
192
)
141
193
142
- params .to_csv (self ._results ['out_file' ], sep = '\t ' , index = False )
194
+ params .to_csv (self ._results ['out_file' ], sep = '\t ' , index = False , na_rep = 'n/a' )
143
195
144
196
return runtime
145
197
@@ -172,7 +224,7 @@ def _run_interface(self, runtime):
172
224
173
225
fd = pd .DataFrame (diff .abs ().sum (axis = 1 , skipna = False ), columns = ['FramewiseDisplacement' ])
174
226
175
- fd .to_csv (self ._results ['out_file' ], sep = '\t ' , index = False )
227
+ fd .to_csv (self ._results ['out_file' ], sep = '\t ' , index = False , na_rep = 'n/a' )
176
228
177
229
return runtime
178
230
@@ -200,7 +252,9 @@ def _run_interface(self, runtime):
200
252
)
201
253
202
254
metadata = pd .read_csv (self .inputs .in_file , sep = '\t ' )
203
- metadata [metadata .retained ].to_csv (self ._results ['out_file' ], sep = '\t ' , index = False )
255
+ metadata [metadata .retained ].to_csv (
256
+ self ._results ['out_file' ], sep = '\t ' , index = False , na_rep = 'n/a'
257
+ )
204
258
205
259
return runtime
206
260
@@ -263,13 +317,15 @@ def _run_interface(self, runtime):
263
317
final_components = components .rename (columns = dict (zip (c_orig , c_new , strict = False )))
264
318
final_components .rename (columns = dict (zip (w_orig , w_new , strict = False )), inplace = True )
265
319
final_components .rename (columns = dict (zip (a_orig , a_new , strict = False )), inplace = True )
266
- final_components .to_csv (self ._results ['components_file' ], sep = '\t ' , index = False )
320
+ final_components .to_csv (
321
+ self ._results ['components_file' ], sep = '\t ' , index = False , na_rep = 'n/a'
322
+ )
267
323
268
324
metadata .loc [c_comp_cor .index , 'component' ] = c_new
269
325
metadata .loc [w_comp_cor .index , 'component' ] = w_new
270
326
metadata .loc [a_comp_cor .index , 'component' ] = a_new
271
327
272
- metadata .to_csv (self ._results ['metadata_file' ], sep = '\t ' , index = False )
328
+ metadata .to_csv (self ._results ['metadata_file' ], sep = '\t ' , index = False , na_rep = 'n/a' )
273
329
274
330
return runtime
275
331
0 commit comments