From c1548a6ca19af21b3f5b10c71ae9247865c892e1 Mon Sep 17 00:00:00 2001 From: oesteban Date: Thu, 18 May 2017 16:30:27 -0700 Subject: [PATCH 1/3] [ENH] Add copy_header option to N4BiasFieldCorrection This N4 algorithm does not propagate the nifti headers after run. This PR allows setting the option ``copy_header=True`` and that will overwrite the N4 output with the corrected data and the original headers. --- nipype/interfaces/ants/segmentation.py | 20 +++++++++++++++++++ .../tests/test_auto_N4BiasFieldCorrection.py | 3 +++ 2 files changed, 23 insertions(+) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index bb012c868f..8d3594fb6c 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -259,6 +259,9 @@ class N4BiasFieldCorrectionInputSpec(ANTSCommandInputSpec): ' to file.'), xor=['bias_image']) bias_image = File(desc='Filename for the estimated bias.', hash_files=False) + copy_header = traits.Bool(False, mandatory=True, usedefault=True, + desc='copy headers of the original image into the ' + 'output (corrected) file') class N4BiasFieldCorrectionOutputSpec(TraitedSpec): @@ -384,6 +387,23 @@ def _list_outputs(self): self._gen_filename('bias_image')) return outputs + def _run_interface(self, runtime, correct_return_codes=(0,)): + runtime = super(N4BiasFieldCorrection, self)._run_interface( + runtime, correct_return_codes) + + if self.inputs.copy_header: + import nibabel as nb + refnii = nb.load(self.inputs.input_image) + hdr = refnii.header.copy() + out_file = self._gen_filename('output_image') + nii = nb.load(out_file) + hdr.set_data_dtype(nii.header.get_data_dtype()) + nb.Nifti1Image(nii.get_data(), refnii.affine, hdr).to_filename( + out_file) + + return runtime + + class CorticalThicknessInputSpec(ANTSCommandInputSpec): dimension = traits.Enum(3, 2, argstr='-d %d', usedefault=True, diff --git a/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py b/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py index 87819a81b7..b863f888d9 100644 --- a/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py +++ b/nipype/interfaces/ants/tests/test_auto_N4BiasFieldCorrection.py @@ -14,6 +14,9 @@ def test_N4BiasFieldCorrection_inputs(): ), convergence_threshold=dict(requires=['n_iterations'], ), + copy_header=dict(mandatory=True, + usedefault=True, + ), dimension=dict(argstr='-d %d', usedefault=True, ), From 98af18ec765a1dde702700eeecca4cfa51357e1a Mon Sep 17 00:00:00 2001 From: oesteban Date: Thu, 18 May 2017 17:08:29 -0700 Subject: [PATCH 2/3] @effigies suggestions --- nipype/interfaces/ants/segmentation.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index 8d3594fb6c..411b45cada 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -391,15 +391,14 @@ def _run_interface(self, runtime, correct_return_codes=(0,)): runtime = super(N4BiasFieldCorrection, self)._run_interface( runtime, correct_return_codes) - if self.inputs.copy_header: + if self.inputs.copy_header and runtime.returncode in correct_return_codes: import nibabel as nb - refnii = nb.load(self.inputs.input_image) - hdr = refnii.header.copy() + in_img = nb.load(self.inputs.input_image) out_file = self._gen_filename('output_image') - nii = nb.load(out_file) - hdr.set_data_dtype(nii.header.get_data_dtype()) - nb.Nifti1Image(nii.get_data(), refnii.affine, hdr).to_filename( - out_file) + out_img = nb.load(out_file, mmap=False) + new_img = out_img.__class__(out_img.get_data(), in_img.affine, in_img.header) + new_img.set_data_dtype(out_img.get_data_dtype()) + new_img.to_filename(out_file) return runtime From d9731052ea841e185bb5963742f1750e735487e0 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 19 May 2017 10:19:54 -0400 Subject: [PATCH 3/3] RF: Factor _copy_header, update bias image --- nipype/interfaces/ants/segmentation.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/nipype/interfaces/ants/segmentation.py b/nipype/interfaces/ants/segmentation.py index 411b45cada..aff6f2c6c0 100644 --- a/nipype/interfaces/ants/segmentation.py +++ b/nipype/interfaces/ants/segmentation.py @@ -392,16 +392,21 @@ def _run_interface(self, runtime, correct_return_codes=(0,)): runtime, correct_return_codes) if self.inputs.copy_header and runtime.returncode in correct_return_codes: - import nibabel as nb - in_img = nb.load(self.inputs.input_image) - out_file = self._gen_filename('output_image') - out_img = nb.load(out_file, mmap=False) - new_img = out_img.__class__(out_img.get_data(), in_img.affine, in_img.header) - new_img.set_data_dtype(out_img.get_data_dtype()) - new_img.to_filename(out_file) + self._copy_header(self._gen_filename('output_image')) + if self.inputs.save_bias or isdefined(self.inputs.bias_image): + self._copy_header(self._gen_filename('bias_image')) return runtime + def _copy_header(self, fname): + """Copy header from input image to an output image""" + import nibabel as nb + in_img = nb.load(self.inputs.input_image) + out_img = nb.load(fname, mmap=False) + new_img = out_img.__class__(out_img.get_data(), in_img.affine, + in_img.header) + new_img.set_data_dtype(out_img.get_data_dtype()) + new_img.to_filename(fname) class CorticalThicknessInputSpec(ANTSCommandInputSpec):