diff --git a/nipype/interfaces/freesurfer/tests/test_auto_EulerNumber.py b/nipype/interfaces/freesurfer/tests/test_auto_EulerNumber.py index d31c9278bc..a90be6bca4 100644 --- a/nipype/interfaces/freesurfer/tests/test_auto_EulerNumber.py +++ b/nipype/interfaces/freesurfer/tests/test_auto_EulerNumber.py @@ -17,7 +17,7 @@ def test_EulerNumber_inputs(): def test_EulerNumber_outputs(): - output_map = dict(out_file=dict(extensions=None,),) + output_map = dict(defects=dict(), euler=dict(),) outputs = EulerNumber.output_spec() for key, metadata in list(output_map.items()): diff --git a/nipype/interfaces/freesurfer/tests/test_utils.py b/nipype/interfaces/freesurfer/tests/test_utils.py index 52348bb5e0..996453d654 100644 --- a/nipype/interfaces/freesurfer/tests/test_utils.py +++ b/nipype/interfaces/freesurfer/tests/test_utils.py @@ -230,3 +230,19 @@ def test_mrisexpand(tmpdir): assert op.dirname(if_out_file) == op.dirname(fsavginfo["smoothwm"]) # Node places output in working directory assert op.dirname(nd_out_file) == nd_res.runtime.cwd + + +@pytest.mark.skipif(fs.no_freesurfer(), reason="freesurfer is not installed") +def test_eulernumber(tmpdir): + # grab a surface from fsaverage + fssrc = FreeSurferSource( + subjects_dir=fs.Info.subjectsdir(), subject_id="fsaverage", hemi="lh" + ) + pial = fssrc.run().outputs.pial + assert isinstance(pial, str), "Problem when fetching surface file" + + eu = fs.EulerNumber() + eu.inputs.in_file = pial + res = eu.run() + assert res.outputs.defects == 0 + assert res.outputs.euler == 2 diff --git a/nipype/interfaces/freesurfer/utils.py b/nipype/interfaces/freesurfer/utils.py index a2b3b7a47b..5a4d6ca425 100644 --- a/nipype/interfaces/freesurfer/utils.py +++ b/nipype/interfaces/freesurfer/utils.py @@ -2592,7 +2592,9 @@ class EulerNumberInputSpec(FSTraitedSpec): class EulerNumberOutputSpec(TraitedSpec): - out_file = File(exists=False, desc="Output file for EulerNumber") + euler = traits.Int(desc="Euler number of cortical surface. A value of 2 signals a " + "topologically correct surface model with no holes") + defects = traits.Int(desc="Number of defects") class EulerNumber(FSCommand): @@ -2612,9 +2614,22 @@ class EulerNumber(FSCommand): input_spec = EulerNumberInputSpec output_spec = EulerNumberOutputSpec + def _run_interface(self, runtime): + runtime = super()._run_interface(runtime) + self._parse_output(runtime.stdout, runtime.stderr) + return runtime + + def _parse_output(self, stdout, stderr): + """Parse stdout / stderr and extract defects""" + m = re.search(r'(?<=total defect index = )\d+', stdout or stderr) + if m is None: + raise RuntimeError("Could not fetch defect index") + self._defects = int(m.group()) + def _list_outputs(self): outputs = self._outputs().get() - outputs["out_file"] = os.path.abspath(self.inputs.in_file) + outputs["defects"] = self._defects + outputs["euler"] = 2 - (2 * self._defects) return outputs