@@ -32,7 +32,7 @@ class MCRIBReconAllInputSpec(CommandLineInputSpec):
3232 t1w_file = File (
3333 exists = True ,
3434 copyfile = True ,
35- desc = 'T1w to be used for deformable (must be registered to T2w image)' ,
35+ desc = 'T1w to be used for deformable (must be in register with T2w image)' ,
3636 )
3737 t2w_file = File (
3838 exists = True ,
@@ -107,26 +107,51 @@ class MCRIBReconAll(CommandLine):
107107 output_spec = MCRIBReconAllOutputSpec
108108 _no_run = False
109109
110+ _expected_files = {
111+ 'surfrecon' : {
112+ 'meshes' : (
113+ 'pial-lh-reordered.vtp' ,
114+ 'pial-rh-reordered.vtp' ,
115+ 'white-rh.vtp' ,
116+ 'white-lh.vtp' ,
117+ )
118+ },
119+ 'autorecon' : {
120+ 'mri' : ('T2.mgz' , 'aseg.presurf.mgz' , 'ribbon.mgz' , 'brain.mgz' ),
121+ 'label' : ('lh.cortex.label' , 'rh.cortex.label' ),
122+ 'stats' : ('aseg.stats' , 'brainvol.stats' , 'lh.aparc.stats' , 'rh.curv.stats' ),
123+ 'surf' : (
124+ 'lh.pial' , 'rh.pial' ,
125+ 'lh.white' , 'rh.white' ,
126+ 'lh.curv' , 'rh.curv' ,
127+ 'lh.thickness' , 'rh.thickness' ),
128+ }
129+ } # fmt:skip
130+
110131 @property
111132 def cmdline (self ):
112133 cmd = super ().cmdline
113- # Avoid processing if valid
134+ if self .inputs .surfrecon and not self .inputs .t2w_file :
135+ raise AttributeError ('Missing `t2w_file` input.' )
136+
137+ # If an output directory is provided, check if we can skip the run
114138 if self .inputs .outdir :
115139 sid = self .inputs .subject_id
116140 # Check MIRTK surface recon deformable
117141 if self .inputs .surfrecon :
118142 surfrecon_dir = Path (self .inputs .outdir ) / sid / 'SurfReconDeformable' / sid
119- if self ._verify_surfrecon_outputs (surfrecon_dir ):
120- self .inputs .surfrecon = False
143+ if self ._verify_outputs ('surfrecon' , surfrecon_dir ):
121144 self ._no_run = True
122145 # Check FS directory population
123146 if self .inputs .autorecon_after_surf :
124147 fs_dir = Path (self .inputs .outdir ) / sid / 'freesurfer' / sid
125- if self ._verify_autorecon_outputs ( fs_dir ):
148+ if self ._verify_outputs ( 'autorecon' , fs_dir ):
126149 self ._no_run = True
150+ else :
151+ self ._no_run = False
127152
128153 if self ._no_run :
129- return 'echo MCRIBSReconAll : nothing to do'
154+ return 'echo MCRIBReconAll : nothing to do'
130155 return cmd
131156
132157 def _setup_directory_structure (self , mcribs_dir : Path ) -> None :
@@ -213,8 +238,6 @@ def _run_interface(self, runtime):
213238 mcribs_dir = self .inputs .outdir or Path (runtime .cwd ) / 'mcribs'
214239 self ._mcribs_dir = Path (mcribs_dir )
215240 if self .inputs .surfrecon :
216- if not self .inputs .t2w_file :
217- raise AttributeError ('Missing T2w input' )
218241 self ._setup_directory_structure (self ._mcribs_dir )
219242 # overwrite CWD to be in MCRIB subject's directory
220243 runtime .cwd = str (self ._mcribs_dir / self .inputs .subject_id )
@@ -226,11 +249,11 @@ def _list_outputs(self):
226249 if self .inputs .surfrecon :
227250 # verify surface reconstruction was successful
228251 surfrecon_dir = self ._mcribs_dir / sid / 'SurfReconDeformable' / sid
229- self ._verify_surfrecon_outputs ( surfrecon_dir , error = True )
252+ self ._verify_outputs ( 'surfrecon' , surfrecon_dir , error = True )
230253
231254 mcribs_fs = self ._mcribs_dir / sid / 'freesurfer' / sid
232255 if self .inputs .autorecon_after_surf :
233- self ._verify_autorecon_outputs ( mcribs_fs , error = True )
256+ self ._verify_outputs ( 'autorecon' , mcribs_fs , error = True )
234257
235258 outputs ['mcribs_dir' ] = str (self ._mcribs_dir )
236259 if self .inputs .autorecon_after_surf and self .inputs .subjects_dir :
@@ -250,56 +273,19 @@ def _list_outputs(self):
250273
251274 return outputs
252275
253- @staticmethod
254- def _verify_surfrecon_outputs (surfrecon_dir : Path , error : bool = False ) -> bool :
255- """
256- Sanity check to ensure the surface reconstruction was successful.
257-
258- MCRIBReconAll does not return a failing exit code if a step failed, which leads
259- this interface to be marked as completed without error in such cases.
260- """
261-
262- surfrecon_files = {
263- 'meshes' : (
264- 'pial-lh-reordered.vtp' ,
265- 'pial-rh-reordered.vtp' ,
266- 'white-rh.vtp' ,
267- 'white-lh.vtp' ,
268- )
269- } # fmt:skip
270-
271- for d , fls in surfrecon_files .items ():
272- for fl in fls :
273- if not (surfrecon_dir / d / fl ).exists ():
274- if error :
275- raise FileNotFoundError (f'SurfReconDeformable missing: { fl } ' )
276- return False
277- return True
278-
279- @staticmethod
280- def _verify_autorecon_outputs (fs_dir : Path , error : bool = False ) -> bool :
276+ def _verify_outputs (self , step : str , root : Path , error : bool = False ) -> bool :
281277 """
282- Sanity check to ensure the necessary FreeSurfer files have been created .
278+ Method to check to ensure the expected files are present successful .
283279
284280 MCRIBReconAll does not return a failing exit code if a step failed, which leads
285281 this interface to be marked as completed without error in such cases.
286282 """
287283
288- fs_files = {
289- 'mri' : ('T2.mgz' , 'aseg.presurf.mgz' , 'ribbon.mgz' , 'brain.mgz' ),
290- 'label' : ('lh.cortex.label' , 'rh.cortex.label' ),
291- 'stats' : ('aseg.stats' , 'brainvol.stats' , 'lh.aparc.stats' , 'rh.curv.stats' ),
292- 'surf' : (
293- 'lh.pial' , 'rh.pial' ,
294- 'lh.white' , 'rh.white' ,
295- 'lh.curv' , 'rh.curv' ,
296- 'lh.thickness' , 'rh.thickness' ),
297- } # fmt:skip
298-
299- for d , fls in fs_files .items ():
300- for fl in fls :
301- if not (fs_dir / d / fl ).exists ():
284+ expected = self ._expected_files [step ]
285+ for d , files in expected .items ():
286+ for fl in files :
287+ if not (root / d / fl ).exists ():
302288 if error :
303- raise FileNotFoundError (f'FreeSurfer directory missing: { fl } ' )
289+ raise FileNotFoundError (f'{ step . capitalize () } missing: { fl } ' )
304290 return False
305291 return True
0 commit comments