diff --git a/smriprep/interfaces/freesurfer.py b/smriprep/interfaces/freesurfer.py index b363c92008..9d00063350 100644 --- a/smriprep/interfaces/freesurfer.py +++ b/smriprep/interfaces/freesurfer.py @@ -293,13 +293,21 @@ def _gen_filename(self, name): return super()._gen_filename(name) -class MakeMidthickness(nwfs.MakeMidthickness): +class MakeMidthicknessInputSpec(nwfs._MakeMidthicknessInputSpec, fs.base.FSTraitedSpecOpenMP): + pass + + +class MakeMidthickness(nwfs.MakeMidthickness, fs.base.FSCommandOpenMP): """Patched MakeMidthickness interface Ensures output filenames are specified with hemisphere labels, when appropriate. This may not cover all use-cases in MRIsExpand, but we're just making midthickness files. + This interface also sets the OMP_NUM_THREADS environment variable to floor(1.5x) the + number of threads requested by the user, as tests indicate that cores are underutilized + by a factor of 2/3. + >>> from smriprep.interfaces.freesurfer import MakeMidthickness >>> mris_expand = MakeMidthickness(thickness=True, distance=0.5) >>> mris_expand.inputs.in_file = 'lh.white' @@ -316,9 +324,17 @@ class MakeMidthickness(nwfs.MakeMidthickness): 'mris_expand -thickness lh.white 0.5 rh.graymid' """ + input_spec = MakeMidthicknessInputSpec + def _format_arg(self, name, trait_spec, value): # FreeSurfer at some point changed whether it would add the hemi label onto the # surface. Therefore we'll do it ourselves. if name == "out_name": value = self._associated_file(self.inputs.in_file, value) return super()._format_arg(name, trait_spec, value) + + def _num_threads_update(self): + if self.inputs.num_threads: + self.inputs.environ.update( + {"OMP_NUM_THREADS": str(self.inputs.num_threads * 3 // 2)} + ) diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py index 20774c12fc..53e6f64550 100644 --- a/smriprep/workflows/surfaces.py +++ b/smriprep/workflows/surfaces.py @@ -220,6 +220,7 @@ def init_surface_recon_wf( MakeMidthickness(thickness=True, distance=0.5, out_name="midthickness"), iterfield="in_file", name="midthickness", + n_procs=min(omp_nthreads, 12), ) save_midthickness = pe.Node(nio.DataSink(parameterization=False), name="save_midthickness") @@ -232,7 +233,6 @@ def init_surface_recon_wf( name="sync", ) - # fmt:off workflow.connect([ # Configuration (inputnode, recon_config, [('t1w', 't1w_list'), @@ -275,21 +275,18 @@ def init_surface_recon_wf( (save_midthickness, sync, [('out_file', 'filenames')]), (sync, outputnode, [('subjects_dir', 'subjects_dir'), ('subject_id', 'subject_id')]), - ]) - # fmt:on + ]) # fmt:skip if "fsnative" not in precomputed.get("transforms", {}): fsnative2t1w_xfm = pe.Node( RobustRegister(auto_sens=True, est_int_scale=True), name="fsnative2t1w_xfm" ) - # fmt:off workflow.connect([ (inputnode, fsnative2t1w_xfm, [('t1w', 'target_file')]), (autorecon1, fsnative2t1w_xfm, [('T1', 'source_file')]), (fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]), - ]) - # fmt:on + ]) # fmt:skip return workflow