Repository: nipy/nipype

Issue:
antslegacy module
I notice that in the newest version the `nipype.interfaces.ants.legacy` module is missing, and I cannot find a class for `antsIntroduction()` anywhere in the package.

I know that using antsIntroduction is probably not the best idea, in fact I need it for an article recommending against it for preclinical imaging, but I need it for the benchmark. Is ti not coming back, and should I thus depend on older nipype for the article source code?

Discussion:

Patch:
diff --git a/nipype/interfaces/ants/legacy.py b/nipype/interfaces/ants/legacy.py
new file mode 100644
index 000000000..0cc8b7e86
--- /dev/null
+++ b/nipype/interfaces/ants/legacy.py
@@ -0,0 +1,372 @@
+# -*- coding: utf-8 -*-
+"""ANTS Legacy Interfaces
+
+These interfaces are for programs that have been deprecated by ANTs, but
+are preserved for backwards compatibility.
+"""
+
+from builtins import range
+
+import os
+from glob import glob
+
+from .base import ANTSCommand, ANTSCommandInputSpec
+from ..base import TraitedSpec, File, traits, isdefined, OutputMultiPath
+from ...utils.filemanip import split_filename
+
+
+class antsIntroductionInputSpec(ANTSCommandInputSpec):
+    dimension = traits.Enum(
+        3,
+        2,
+        argstr="-d %d",
+        usedefault=True,
+        desc="image dimension (2 or 3)",
+        position=1,
+    )
+    reference_image = File(
+        exists=True,
+        argstr="-r %s",
+        desc="template file to warp to",
+        mandatory=True,
+        copyfile=True,
+    )
+    input_image = File(
+        exists=True,
+        argstr="-i %s",
+        desc="input image to warp to template",
+        mandatory=True,
+        copyfile=False,
+    )
+    force_proceed = traits.Bool(
+        argstr="-f 1",
+        desc=("force script to proceed even if headers " "may be incompatible"),
+    )
+    inverse_warp_template_labels = traits.Bool(
+        argstr="-l",
+        desc=(
+            "Applies inverse warp to the template labels "
+            "to estimate label positions in target space (use "
+            "for template-based segmentation)"
+        ),
+    )
+    max_iterations = traits.List(
+        traits.Int,
+        argstr="-m %s",
+        sep="x",
+        desc=(
+            "maximum number of iterations (must be "
+            "list of integers in the form [J,K,L...]: "
+            "J = coarsest resolution iterations, K = "
+            "middle resolution interations, L = fine "
+            "resolution iterations"
+        ),
+    )
+    bias_field_correction = traits.Bool(
+        argstr="-n 1", desc=("Applies bias field correction to moving " "image")
+    )
+    similarity_metric = traits.Enum(
+        "PR",
+        "CC",
+        "MI",
+        "MSQ",
+        argstr="-s %s",
+        desc=(
+            "Type of similartiy metric used for registration "
+            "(CC = cross correlation, MI = mutual information, "
+            "PR = probability mapping, MSQ = mean square difference)"
+        ),
+    )
+    transformation_model = traits.Enum(
+        "GR",
+        "EL",
+        "SY",
+        "S2",
+        "EX",
+        "DD",
+        "RI",
+        "RA",
+        argstr="-t %s",
+        usedefault=True,
+        desc=(
+            "Type of transofmration model used for registration "
+            "(EL = elastic transformation model, SY = SyN with time, "
+            "arbitrary number of time points, S2 =  SyN with time "
+            "optimized for 2 time points, GR = greedy SyN, EX = "
+            "exponential, DD = diffeomorphic demons style exponential "
+            "mapping, RI = purely rigid, RA = affine rigid"
+        ),
+    )
+    out_prefix = traits.Str(
+        "ants_",
+        argstr="-o %s",
+        usedefault=True,
+        desc=("Prefix that is prepended to all output " "files (default = ants_)"),
+    )
+    quality_check = traits.Bool(
+        argstr="-q 1", desc="Perform a quality check of the result"
+    )
+
+
+class antsIntroductionOutputSpec(TraitedSpec):
+    affine_transformation = File(exists=True, desc="affine (prefix_Affine.txt)")
+    warp_field = File(exists=True, desc="warp field (prefix_Warp.nii)")
+    inverse_warp_field = File(
+        exists=True, desc="inverse warp field (prefix_InverseWarp.nii)"
+    )
+    input_file = File(exists=True, desc="input image (prefix_repaired.nii)")
+    output_file = File(exists=True, desc="output image (prefix_deformed.nii)")
+
+
+class antsIntroduction(ANTSCommand):
+    """Uses ANTS to generate matrices to warp data from one space to another.
+
+    Examples
+    --------
+
+    >>> from nipype.interfaces.ants.legacy import antsIntroduction
+    >>> warp = antsIntroduction()
+    >>> warp.inputs.reference_image = 'Template_6.nii'
+    >>> warp.inputs.input_image = 'structural.nii'
+    >>> warp.inputs.max_iterations = [30,90,20]
+    >>> warp.cmdline
+    'antsIntroduction.sh -d 3 -i structural.nii -m 30x90x20 -o ants_ -r Template_6.nii -t GR'
+
+    """
+
+    _cmd = "antsIntroduction.sh"
+    input_spec = antsIntroductionInputSpec
+    output_spec = antsIntroductionOutputSpec
+
+    def _list_outputs(self):
+        outputs = self._outputs().get()
+        transmodel = self.inputs.transformation_model
+
+        # When transform is set as 'RI'/'RA', wrap fields should not be expected
+        # The default transformation is GR, which outputs the wrap fields
+        if not isdefined(transmodel) or (
+            isdefined(transmodel) and transmodel not in ["RI", "RA"]
+        ):
+            outputs["warp_field"] = os.path.join(
+                os.getcwd(), self.inputs.out_prefix + "Warp.nii.gz"
+            )
+            outputs["inverse_warp_field"] = os.path.join(
+                os.getcwd(), self.inputs.out_prefix + "InverseWarp.nii.gz"
+            )
+
+        outputs["affine_transformation"] = os.path.join(
+            os.getcwd(), self.inputs.out_prefix + "Affine.txt"
+        )
+        outputs["input_file"] = os.path.join(
+            os.getcwd(), self.inputs.out_prefix + "repaired.nii.gz"
+        )
+        outputs["output_file"] = os.path.join(
+            os.getcwd(), self.inputs.out_prefix + "deformed.nii.gz"
+        )
+
+        return outputs
+
+
+# How do we make a pass through so that GenWarpFields is just an alias for  antsIntroduction ?
+
+
+class GenWarpFields(antsIntroduction):
+    pass
+
+
+class buildtemplateparallelInputSpec(ANTSCommandInputSpec):
+    dimension = traits.Enum(
+        3,
+        2,
+        4,
+        argstr="-d %d",
+        usedefault=True,
+        desc="image dimension (2, 3 or 4)",
+        position=1,
+    )
+    out_prefix = traits.Str(
+        "antsTMPL_",
+        argstr="-o %s",
+        usedefault=True,
+        desc=("Prefix that is prepended to all output " "files (default = antsTMPL_)"),
+    )
+    in_files = traits.List(
+        File(exists=True),
+        mandatory=True,
+        desc="list of images to generate template from",
+        argstr="%s",
+        position=-1,
+    )
+    parallelization = traits.Enum(
+        0,
+        1,
+        2,
+        argstr="-c %d",
+        usedefault=True,
+        desc=(
+            "control for parallel processing (0 = "
+            "serial, 1 = use PBS, 2 = use PEXEC, 3 = "
+            "use Apple XGrid"
+        ),
+    )
+    gradient_step_size = traits.Float(
+        argstr="-g %f",
+        desc=("smaller magnitude results in " "more cautious steps (default = " ".25)"),
+    )
+    iteration_limit = traits.Int(
+        4, argstr="-i %d", usedefault=True, desc="iterations of template construction"
+    )
+    num_cores = traits.Int(
+        argstr="-j %d",
+        requires=["parallelization"],
+        desc=(
+            "Requires parallelization = 2 (PEXEC). " "Sets number of cpu cores to use"
+        ),
+    )
+    max_iterations = traits.List(
+        traits.Int,
+        argstr="-m %s",
+        sep="x",
+        desc=(
+            "maximum number of iterations (must be "
+            "list of integers in the form [J,K,L...]: "
+            "J = coarsest resolution iterations, K = "
+            "middle resolution interations, L = fine "
+            "resolution iterations"
+        ),
+    )
+    bias_field_correction = traits.Bool(
+        argstr="-n 1", desc=("Applies bias field correction to moving " "image")
+    )
+    rigid_body_registration = traits.Bool(
+        argstr="-r 1",
+        desc=(
+            "registers inputs before creating template "
+            "(useful if no initial template available)"
+        ),
+    )
+    similarity_metric = traits.Enum(
+        "PR",
+        "CC",
+        "MI",
+        "MSQ",
+        argstr="-s %s",
+        desc=(
+            "Type of similartiy metric used for registration "
+            "(CC = cross correlation, MI = mutual information, "
+            "PR = probability mapping, MSQ = mean square difference)"
+        ),
+    )
+    transformation_model = traits.Enum(
+        "GR",
+        "EL",
+        "SY",
+        "S2",
+        "EX",
+        "DD",
+        argstr="-t %s",
+        usedefault=True,
+        desc=(
+            "Type of transofmration model used for registration "
+            "(EL = elastic transformation model, SY = SyN with time, "
+            "arbitrary number of time points, S2 =  SyN with time "
+            "optimized for 2 time points, GR = greedy SyN, EX = "
+            "exponential, DD = diffeomorphic demons style exponential "
+            "mapping"
+        ),
+    )
+    use_first_as_target = traits.Bool(
+        desc=(
+            "uses first volume as target of "
+            "all inputs. When not used, an "
+            "unbiased average image is used "
+            "to start."
+        )
+    )
+
+
+class buildtemplateparallelOutputSpec(TraitedSpec):
+    final_template_file = File(exists=True, desc="final ANTS template")
+    template_files = OutputMultiPath(
+        File(exists=True), desc="Templates from different stages of iteration"
+    )
+    subject_outfiles = OutputMultiPath(
+        File(exists=True),
+        desc=(
+            "Outputs for each input image. Includes warp "
+            "field, inverse warp, Affine, original image "
+            "(repaired) and warped image (deformed)"
+        ),
+    )
+
+
+class buildtemplateparallel(ANTSCommand):
+    """Generate a optimal average template
+
+    .. warning::
+
+      This can take a VERY long time to complete
+
+    Examples
+    --------
+
+    >>> from nipype.interfaces.ants.legacy import buildtemplateparallel
+    >>> tmpl = buildtemplateparallel()
+    >>> tmpl.inputs.in_files = ['T1.nii', 'structural.nii']
+    >>> tmpl.inputs.max_iterations = [30, 90, 20]
+    >>> tmpl.cmdline
+    'buildtemplateparallel.sh -d 3 -i 4 -m 30x90x20 -o antsTMPL_ -c 0 -t GR T1.nii structural.nii'
+
+    """
+
+    _cmd = "buildtemplateparallel.sh"
+    input_spec = buildtemplateparallelInputSpec
+    output_spec = buildtemplateparallelOutputSpec
+
+    def _format_arg(self, opt, spec, val):
+        if opt == "num_cores":
+            if self.inputs.parallelization == 2:
+                return "-j " + str(val)
+            else:
+                return ""
+        if opt == "in_files":
+            if self.inputs.use_first_as_target:
+                start = "-z "
+            else:
+                start = ""
+            return start + " ".join(name for name in val)
+        return super(buildtemplateparallel, self)._format_arg(opt, spec, val)
+
+    def _list_outputs(self):
+        outputs = self._outputs().get()
+        outputs["template_files"] = []
+        for i in range(len(glob(os.path.realpath("*iteration*")))):
+            temp = os.path.realpath(
+                "%s_iteration_%d/%stemplate.nii.gz"
+                % (self.inputs.transformation_model, i, self.inputs.out_prefix)
+            )
+            os.rename(
+                temp,
+                os.path.realpath(
+                    "%s_iteration_%d/%stemplate_i%d.nii.gz"
+                    % (self.inputs.transformation_model, i, self.inputs.out_prefix, i)
+                ),
+            )
+            file_ = "%s_iteration_%d/%stemplate_i%d.nii.gz" % (
+                self.inputs.transformation_model,
+                i,
+                self.inputs.out_prefix,
+                i,
+            )
+
+            outputs["template_files"].append(os.path.realpath(file_))
+            outputs["final_template_file"] = os.path.realpath(
+                "%stemplate.nii.gz" % self.inputs.out_prefix
+            )
+        outputs["subject_outfiles"] = []
+        for filename in self.inputs.in_files:
+            _, base, _ = split_filename(filename)
+            temp = glob(os.path.realpath("%s%s*" % (self.inputs.out_prefix, base)))
+            for file_ in temp:
+                outputs["subject_outfiles"].append(file_)
+        return outputs


Test patch:
diff --git a/nipype/interfaces/ants/tests/test_auto_GenWarpFields.py b/nipype/interfaces/ants/tests/test_auto_GenWarpFields.py
new file mode 100644
index 000000000..11fbe56cc
--- /dev/null
+++ b/nipype/interfaces/ants/tests/test_auto_GenWarpFields.py
@@ -0,0 +1,45 @@
+# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
+from ..legacy import GenWarpFields
+
+
+def test_GenWarpFields_inputs():
+    input_map = dict(
+        args=dict(argstr="%s",),
+        bias_field_correction=dict(argstr="-n 1",),
+        dimension=dict(argstr="-d %d", position=1, usedefault=True,),
+        environ=dict(nohash=True, usedefault=True,),
+        force_proceed=dict(argstr="-f 1",),
+        input_image=dict(
+            argstr="-i %s", copyfile=False, extensions=None, mandatory=True,
+        ),
+        inverse_warp_template_labels=dict(argstr="-l",),
+        max_iterations=dict(argstr="-m %s", sep="x",),
+        num_threads=dict(nohash=True, usedefault=True,),
+        out_prefix=dict(argstr="-o %s", usedefault=True,),
+        quality_check=dict(argstr="-q 1",),
+        reference_image=dict(
+            argstr="-r %s", copyfile=True, extensions=None, mandatory=True,
+        ),
+        similarity_metric=dict(argstr="-s %s",),
+        transformation_model=dict(argstr="-t %s", usedefault=True,),
+    )
+    inputs = GenWarpFields.input_spec()
+
+    for key, metadata in list(input_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(inputs.traits()[key], metakey) == value
+
+
+def test_GenWarpFields_outputs():
+    output_map = dict(
+        affine_transformation=dict(extensions=None,),
+        input_file=dict(extensions=None,),
+        inverse_warp_field=dict(extensions=None,),
+        output_file=dict(extensions=None,),
+        warp_field=dict(extensions=None,),
+    )
+    outputs = GenWarpFields.output_spec()
+
+    for key, metadata in list(output_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(outputs.traits()[key], metakey) == value
diff --git a/nipype/interfaces/ants/tests/test_auto_antsIntroduction.py b/nipype/interfaces/ants/tests/test_auto_antsIntroduction.py
new file mode 100644
index 000000000..d7950f38b
--- /dev/null
+++ b/nipype/interfaces/ants/tests/test_auto_antsIntroduction.py
@@ -0,0 +1,45 @@
+# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
+from ..legacy import antsIntroduction
+
+
+def test_antsIntroduction_inputs():
+    input_map = dict(
+        args=dict(argstr="%s",),
+        bias_field_correction=dict(argstr="-n 1",),
+        dimension=dict(argstr="-d %d", position=1, usedefault=True,),
+        environ=dict(nohash=True, usedefault=True,),
+        force_proceed=dict(argstr="-f 1",),
+        input_image=dict(
+            argstr="-i %s", copyfile=False, extensions=None, mandatory=True,
+        ),
+        inverse_warp_template_labels=dict(argstr="-l",),
+        max_iterations=dict(argstr="-m %s", sep="x",),
+        num_threads=dict(nohash=True, usedefault=True,),
+        out_prefix=dict(argstr="-o %s", usedefault=True,),
+        quality_check=dict(argstr="-q 1",),
+        reference_image=dict(
+            argstr="-r %s", copyfile=True, extensions=None, mandatory=True,
+        ),
+        similarity_metric=dict(argstr="-s %s",),
+        transformation_model=dict(argstr="-t %s", usedefault=True,),
+    )
+    inputs = antsIntroduction.input_spec()
+
+    for key, metadata in list(input_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(inputs.traits()[key], metakey) == value
+
+
+def test_antsIntroduction_outputs():
+    output_map = dict(
+        affine_transformation=dict(extensions=None,),
+        input_file=dict(extensions=None,),
+        inverse_warp_field=dict(extensions=None,),
+        output_file=dict(extensions=None,),
+        warp_field=dict(extensions=None,),
+    )
+    outputs = antsIntroduction.output_spec()
+
+    for key, metadata in list(output_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(outputs.traits()[key], metakey) == value
diff --git a/nipype/interfaces/ants/tests/test_auto_buildtemplateparallel.py b/nipype/interfaces/ants/tests/test_auto_buildtemplateparallel.py
new file mode 100644
index 000000000..35b225949
--- /dev/null
+++ b/nipype/interfaces/ants/tests/test_auto_buildtemplateparallel.py
@@ -0,0 +1,41 @@
+# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
+from ..legacy import buildtemplateparallel
+
+
+def test_buildtemplateparallel_inputs():
+    input_map = dict(
+        args=dict(argstr="%s",),
+        bias_field_correction=dict(argstr="-n 1",),
+        dimension=dict(argstr="-d %d", position=1, usedefault=True,),
+        environ=dict(nohash=True, usedefault=True,),
+        gradient_step_size=dict(argstr="-g %f",),
+        in_files=dict(argstr="%s", mandatory=True, position=-1,),
+        iteration_limit=dict(argstr="-i %d", usedefault=True,),
+        max_iterations=dict(argstr="-m %s", sep="x",),
+        num_cores=dict(argstr="-j %d", requires=["parallelization"],),
+        num_threads=dict(nohash=True, usedefault=True,),
+        out_prefix=dict(argstr="-o %s", usedefault=True,),
+        parallelization=dict(argstr="-c %d", usedefault=True,),
+        rigid_body_registration=dict(argstr="-r 1",),
+        similarity_metric=dict(argstr="-s %s",),
+        transformation_model=dict(argstr="-t %s", usedefault=True,),
+        use_first_as_target=dict(),
+    )
+    inputs = buildtemplateparallel.input_spec()
+
+    for key, metadata in list(input_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(inputs.traits()[key], metakey) == value
+
+
+def test_buildtemplateparallel_outputs():
+    output_map = dict(
+        final_template_file=dict(extensions=None,),
+        subject_outfiles=dict(),
+        template_files=dict(),
+    )
+    outputs = buildtemplateparallel.output_spec()
+
+    for key, metadata in list(output_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(outputs.traits()[key], metakey) == value