@@ -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 ,
@@ -47,14 +47,20 @@ class MCRIBReconAllInputSpec(CommandLineInputSpec):
4747
4848 # MCRIBS options
4949 conform = traits .Bool (
50+ False ,
51+ usedefault = True ,
5052 argstr = '--conform' ,
5153 desc = 'Reorients to radiological, axial slice orientation. Resamples to isotropic voxels' ,
5254 )
5355 tissueseg = traits .Bool (
56+ False ,
57+ usedefault = True ,
5458 argstr = '--tissueseg' ,
5559 desc = 'Perform tissue type segmentation' ,
5660 )
5761 surfrecon = traits .Bool (
62+ False ,
63+ usedefault = True ,
5864 argstr = '--surfrecon' ,
5965 desc = 'Reconstruct surfaces' ,
6066 )
@@ -75,6 +81,8 @@ class MCRIBReconAllInputSpec(CommandLineInputSpec):
7581 desc = 'Use Deformable fast collision test' ,
7682 )
7783 autorecon_after_surf = traits .Bool (
84+ False ,
85+ usedefault = True ,
7886 argstr = '--autoreconaftersurf' ,
7987 desc = 'Do all steps after surface reconstruction' ,
8088 )
@@ -99,25 +107,51 @@ class MCRIBReconAll(CommandLine):
99107 output_spec = MCRIBReconAllOutputSpec
100108 _no_run = False
101109
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+
102131 @property
103132 def cmdline (self ):
104133 cmd = super ().cmdline
105- # 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
106138 if self .inputs .outdir :
107139 sid = self .inputs .subject_id
108140 # Check MIRTK surface recon deformable
109141 if self .inputs .surfrecon :
110142 surfrecon_dir = Path (self .inputs .outdir ) / sid / 'SurfReconDeformable' / sid
111- if self ._verify_surfrecon_outputs ( surfrecon_dir , error = False ):
143+ if self ._verify_outputs ( 'surfrecon' , surfrecon_dir ):
112144 self ._no_run = True
113145 # Check FS directory population
114- elif self .inputs .autorecon_after_surf :
146+ if self .inputs .autorecon_after_surf :
115147 fs_dir = Path (self .inputs .outdir ) / sid / 'freesurfer' / sid
116- if self ._verify_autorecon_outputs ( fs_dir , error = False ):
148+ if self ._verify_outputs ( 'autorecon' , fs_dir ):
117149 self ._no_run = True
150+ else :
151+ self ._no_run = False
118152
119153 if self ._no_run :
120- return 'echo MCRIBSReconAll : nothing to do'
154+ return 'echo MCRIBReconAll : nothing to do'
121155 return cmd
122156
123157 def _setup_directory_structure (self , mcribs_dir : Path ) -> None :
@@ -204,8 +238,6 @@ def _run_interface(self, runtime):
204238 mcribs_dir = self .inputs .outdir or Path (runtime .cwd ) / 'mcribs'
205239 self ._mcribs_dir = Path (mcribs_dir )
206240 if self .inputs .surfrecon :
207- if not self .inputs .t2w_file :
208- raise AttributeError ('Missing T2w input' )
209241 self ._setup_directory_structure (self ._mcribs_dir )
210242 # overwrite CWD to be in MCRIB subject's directory
211243 runtime .cwd = str (self ._mcribs_dir / self .inputs .subject_id )
@@ -217,11 +249,11 @@ def _list_outputs(self):
217249 if self .inputs .surfrecon :
218250 # verify surface reconstruction was successful
219251 surfrecon_dir = self ._mcribs_dir / sid / 'SurfReconDeformable' / sid
220- self ._verify_surfrecon_outputs ( surfrecon_dir , error = True )
252+ self ._verify_outputs ( 'surfrecon' , surfrecon_dir , error = True )
221253
222254 mcribs_fs = self ._mcribs_dir / sid / 'freesurfer' / sid
223255 if self .inputs .autorecon_after_surf :
224- self ._verify_autorecon_outputs ( mcribs_fs , error = True )
256+ self ._verify_outputs ( 'autorecon' , mcribs_fs , error = True )
225257
226258 outputs ['mcribs_dir' ] = str (self ._mcribs_dir )
227259 if self .inputs .autorecon_after_surf and self .inputs .subjects_dir :
@@ -241,56 +273,19 @@ def _list_outputs(self):
241273
242274 return outputs
243275
244- @staticmethod
245- def _verify_surfrecon_outputs (surfrecon_dir : Path , error : bool ) -> bool :
276+ def _verify_outputs (self , step : str , root : Path , error : bool = False ) -> bool :
246277 """
247- Sanity check to ensure the surface reconstruction was successful.
278+ Method to check to ensure the expected files are present successful.
248279
249280 MCRIBReconAll does not return a failing exit code if a step failed, which leads
250281 this interface to be marked as completed without error in such cases.
251282 """
252- # fmt:off
253- surfrecon_files = {
254- 'meshes' : (
255- 'pial-lh-reordered.vtp' ,
256- 'pial-rh-reordered.vtp' ,
257- 'white-rh.vtp' ,
258- 'white-lh.vtp' ,
259- )
260- }
261- # fmt:on
262- for d , fls in surfrecon_files .items ():
263- for fl in fls :
264- if not (surfrecon_dir / d / fl ).exists ():
265- if error :
266- raise FileNotFoundError (f'SurfReconDeformable missing: { fl } ' )
267- return False
268- return True
269-
270- @staticmethod
271- def _verify_autorecon_outputs (fs_dir : Path , error : bool ) -> bool :
272- """
273- Sanity check to ensure the necessary FreeSurfer files have been created.
274283
275- MCRIBReconAll does not return a failing exit code if a step failed, which leads
276- this interface to be marked as completed without error in such cases.
277- """
278- # fmt:off
279- fs_files = {
280- 'mri' : ('T2.mgz' , 'aseg.presurf.mgz' , 'ribbon.mgz' , 'brain.mgz' ),
281- 'label' : ('lh.cortex.label' , 'rh.cortex.label' ),
282- 'stats' : ('aseg.stats' , 'brainvol.stats' , 'lh.aparc.stats' , 'rh.curv.stats' ),
283- 'surf' : (
284- 'lh.pial' , 'rh.pial' ,
285- 'lh.white' , 'rh.white' ,
286- 'lh.curv' , 'rh.curv' ,
287- 'lh.thickness' , 'rh.thickness' ),
288- }
289- # fmt:on
290- for d , fls in fs_files .items ():
291- for fl in fls :
292- 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 ():
293288 if error :
294- raise FileNotFoundError (f'FreeSurfer directory missing: { fl } ' )
289+ raise FileNotFoundError (f'{ step . capitalize () } missing: { fl } ' )
295290 return False
296291 return True
0 commit comments