# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""The regutils module provides classes for interfacing with the `niftyreg
<http://niftyreg.sourceforge.net>`_ utility command line tools.

The interfaces were written to work with niftyreg version 1.5.10
"""

from __future__ import (print_function, division, unicode_literals,
                        absolute_import)
from builtins import len, open, property, super
import os

from ..base import TraitedSpec, File, traits, isdefined
from .base import get_custom_path, NiftyRegCommand, NiftyRegCommandInputSpec
from ...utils.filemanip import split_filename


class RegResampleInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegResample. """
    # Input reference file
    ref_file = File(
        exists=True,
        desc='The input reference/target image',
        argstr='-ref %s',
        mandatory=True)
    # Input floating file
    flo_file = File(
        exists=True,
        desc='The input floating/source image',
        argstr='-flo %s',
        mandatory=True)
    # Input deformation field
    trans_file = File(
        exists=True, desc='The input transformation file', argstr='-trans %s')

    type = traits.Enum(
        'res',
        'blank',
        argstr='-%s',
        position=-2,
        usedefault=True,
        desc='Type of output')

    # Output file name
    out_file = File(
        name_source=['flo_file'],
        name_template='%s',
        argstr='%s',
        position=-1,
        desc='The output filename of the transformed image')

    # Interpolation type
    inter_val = traits.Enum(
        'NN',
        'LIN',
        'CUB',
        'SINC',
        desc='Interpolation type',
        argstr='-inter %d')

    # Padding value
    pad_val = traits.Float(desc='Padding value', argstr='-pad %f')

    # Tensor flag
    tensor_flag = traits.Bool(desc='Resample Tensor Map', argstr='-tensor ')

    # Verbosity off
    verbosity_off_flag = traits.Bool(
        argstr='-voff', desc='Turn off verbose output')
    # PSF flag
    desc = 'Perform the resampling in two steps to resample an image to a \
lower resolution'

    psf_flag = traits.Bool(argstr='-psf', desc=desc)
    desc = 'Minimise the matrix metric (0) or the determinant (1) when \
estimating the PSF [0]'

    psf_alg = traits.Enum(0, 1, argstr='-psf_alg %d', desc=desc)


class RegResampleOutputSpec(TraitedSpec):
    """ Output Spec for RegResample. """
    out_file = File(desc='The output filename of the transformed image')


class RegResample(NiftyRegCommand):
    """Interface for executable reg_resample from NiftyReg platform.

    Tool to resample floating image in the space of a defined reference image
    given a transformation parametrisation generated by reg_aladin, reg_f3d or
    reg_transform

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------
    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegResample()
    >>> node.inputs.ref_file = 'im1.nii'
    >>> node.inputs.flo_file = 'im2.nii'
    >>> node.inputs.trans_file = 'warpfield.nii'
    >>> node.inputs.inter_val = 'LIN'
    >>> node.inputs.omp_core_val = 4
    >>> node.cmdline
    'reg_resample -flo im2.nii -inter 1 -omp 4 -ref im1.nii -trans \
warpfield.nii -res im2_res.nii.gz'

    """
    _cmd = get_custom_path('reg_resample')
    input_spec = RegResampleInputSpec
    output_spec = RegResampleOutputSpec

    # Need this overload to properly constraint the interpolation type input
    def _format_arg(self, name, spec, value):
        if name == 'inter_val':
            inter_val = {'NN': 0, 'LIN': 1, 'CUB': 3, 'SINC': 4}
            return spec.argstr % inter_val[value]
        else:
            return super(RegResample, self)._format_arg(name, spec, value)

    def _overload_extension(self, value, name=None):
        path, base, _ = split_filename(value)
        suffix = self.inputs.type
        return os.path.join(path, '{0}_{1}.nii.gz'.format(base, suffix))


class RegJacobianInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegJacobian. """
    # Reference file name
    desc = 'Reference/target file (required if specifying CPP transformations.'
    ref_file = File(exists=True, desc=desc, argstr='-ref %s')
    # Input transformation file
    trans_file = File(
        exists=True,
        desc='The input non-rigid transformation',
        argstr='-trans %s',
        mandatory=True)
    type = traits.Enum(
        'jac',
        'jacL',
        'jacM',
        usedefault=True,
        argstr='-%s',
        position=-2,
        desc='Type of jacobian outcome')
    out_file = File(
        name_source=['trans_file'],
        name_template='%s',
        desc='The output jacobian determinant file name',
        argstr='%s',
        position=-1)


class RegJacobianOutputSpec(TraitedSpec):
    """ Output Spec for RegJacobian. """
    out_file = File(desc='The output file')


class RegJacobian(NiftyRegCommand):
    """Interface for executable reg_resample from NiftyReg platform.

    Tool to generate Jacobian determinant maps from transformation
    parametrisation generated by reg_f3d

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------
    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegJacobian()
    >>> node.inputs.ref_file = 'im1.nii'
    >>> node.inputs.trans_file = 'warpfield.nii'
    >>> node.inputs.omp_core_val = 4
    >>> node.cmdline
    'reg_jacobian -omp 4 -ref im1.nii -trans warpfield.nii -jac \
warpfield_jac.nii.gz'

    """
    _cmd = get_custom_path('reg_jacobian')
    input_spec = RegJacobianInputSpec
    output_spec = RegJacobianOutputSpec

    def _overload_extension(self, value, name=None):
        path, base, _ = split_filename(value)
        suffix = self.inputs.type
        return os.path.join(path, '{0}_{1}.nii.gz'.format(base, suffix))


class RegToolsInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegTools. """
    # Input image file
    in_file = File(
        exists=True,
        desc='The input image file path',
        argstr='-in %s',
        mandatory=True)

    # Output file path
    out_file = File(
        name_source=['in_file'],
        name_template='%s_tools.nii.gz',
        desc='The output file name',
        argstr='-out %s')

    # Make the output image isotropic
    iso_flag = traits.Bool(argstr='-iso', desc='Make output image isotropic')

    # Set scale, slope to 0 and 1.
    noscl_flag = traits.Bool(
        argstr='-noscl', desc='Set scale, slope to 0 and 1')

    # Values outside the mask are set to NaN
    mask_file = File(
        exists=True,
        desc='Values outside the mask are set to NaN',
        argstr='-nan %s')

    # Threshold the input image
    desc = 'Binarise the input image with the given threshold'
    thr_val = traits.Float(desc=desc, argstr='-thr %f')

    # Binarise the input image
    bin_flag = traits.Bool(argstr='-bin', desc='Binarise the input image')

    # Compute the mean RMS between the two images
    rms_val = File(
        exists=True,
        desc='Compute the mean RMS between the images',
        argstr='-rms %s')

    # Perform division by image or value
    div_val = traits.Either(
        traits.Float,
        File(exists=True),
        desc='Divide the input by image or value',
        argstr='-div %s')

    # Perform multiplication by image or value
    mul_val = traits.Either(
        traits.Float,
        File(exists=True),
        desc='Multiply the input by image or value',
        argstr='-mul %s')

    # Perform addition by image or value
    add_val = traits.Either(
        traits.Float,
        File(exists=True),
        desc='Add to the input image or value',
        argstr='-add %s')

    # Perform subtraction by image or value
    sub_val = traits.Either(
        traits.Float,
        File(exists=True),
        desc='Add to the input image or value',
        argstr='-sub %s')

    # Downsample the image by a factor of 2.
    down_flag = traits.Bool(
        desc='Downsample the image by a factor of 2', argstr='-down')

    # Smoothing using spline kernel
    desc = 'Smooth the input image using a cubic spline kernel'
    smo_s_val = traits.Tuple(
        traits.Float,
        traits.Float,
        traits.Float,
        desc=desc,
        argstr='-smoS %f %f %f')

    # Change the resolution of the input image
    chg_res_val = traits.Tuple(
        traits.Float,
        traits.Float,
        traits.Float,
        desc='Change the resolution of the input image',
        argstr='-chgres %f %f %f')

    # Smoothing using Gaussian kernel
    desc = 'Smooth the input image using a Gaussian kernel'
    smo_g_val = traits.Tuple(
        traits.Float,
        traits.Float,
        traits.Float,
        desc=desc,
        argstr='-smoG %f %f %f')

    # Interpolation type
    inter_val = traits.Enum(
        'NN',
        'LIN',
        'CUB',
        'SINC',
        desc='Interpolation order to use to warp the floating image',
        argstr='-interp %d')


class RegToolsOutputSpec(TraitedSpec):
    """ Output Spec for RegTools. """
    out_file = File(desc='The output file', exists=True)


class RegTools(NiftyRegCommand):
    """Interface for executable reg_tools from NiftyReg platform.

    Tool delivering various actions related to registration such as
    resampling the input image to a chosen resolution or remove the nan and
    inf in the input image by a specified value.

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------
    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegTools()
    >>> node.inputs.in_file = 'im1.nii'
    >>> node.inputs.mul_val = 4
    >>> node.inputs.omp_core_val = 4
    >>> node.cmdline
    'reg_tools -in im1.nii -mul 4.0 -omp 4 -out im1_tools.nii.gz'

    """
    _cmd = get_custom_path('reg_tools')
    input_spec = RegToolsInputSpec
    output_spec = RegToolsOutputSpec
    _suffix = '_tools'

    # Need this overload to properly constraint the interpolation type input
    def _format_arg(self, name, spec, value):
        if name == 'inter_val':
            inter_val = {'NN': 0, 'LIN': 1, 'CUB': 3, 'SINC': 4}
            return spec.argstr % inter_val[value]
        else:
            return super(RegTools, self)._format_arg(name, spec, value)


class RegAverageInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegAverage. """
    avg_files = traits.List(
        File(exist=True),
        position=1,
        argstr='-avg %s',
        sep=' ',
        xor=[
            'avg_lts_files', 'avg_ref_file', 'demean1_ref_file',
            'demean2_ref_file', 'demean3_ref_file', 'warp_files'
        ],
        desc='Averaging of images/affine transformations')

    desc = 'Robust average of affine transformations'
    avg_lts_files = traits.List(
        File(exist=True),
        position=1,
        argstr='-avg_lts %s',
        sep=' ',
        xor=[
            'avg_files', 'avg_ref_file', 'demean1_ref_file',
            'demean2_ref_file', 'demean3_ref_file', 'warp_files'
        ],
        desc=desc)

    desc = 'All input images are resampled into the space of <reference image>\
 and averaged. A cubic spline interpolation scheme is used for resampling'

    avg_ref_file = File(
        position=1,
        argstr='-avg_tran %s',
        xor=[
            'avg_files', 'avg_lts_files', 'demean1_ref_file',
            'demean2_ref_file', 'demean3_ref_file'
        ],
        requires=['warp_files'],
        desc=desc)

    desc = 'Average images and demean average image that have affine \
transformations to a common space'

    demean1_ref_file = File(
        position=1,
        argstr='-demean1 %s',
        xor=[
            'avg_files', 'avg_lts_files', 'avg_ref_file', 'demean2_ref_file',
            'demean3_ref_file'
        ],
        requires=['warp_files'],
        desc=desc)

    desc = 'Average images and demean average image that have non-rigid \
transformations to a common space'

    demean2_ref_file = File(
        position=1,
        argstr='-demean2 %s',
        xor=[
            'avg_files', 'avg_lts_files', 'avg_ref_file', 'demean1_ref_file',
            'demean3_ref_file'
        ],
        requires=['warp_files'],
        desc=desc)

    desc = 'Average images and demean average image that have linear and \
non-rigid transformations to a common space'

    demean3_ref_file = File(
        position=1,
        argstr='-demean3 %s',
        xor=[
            'avg_files', 'avg_lts_files', 'avg_ref_file', 'demean1_ref_file',
            'demean2_ref_file'
        ],
        requires=['warp_files'],
        desc=desc)

    desc = 'transformation files and floating image pairs/triplets to the \
reference space'

    warp_files = traits.List(
        File(exist=True),
        position=-1,
        argstr='%s',
        sep=' ',
        xor=['avg_files', 'avg_lts_files'],
        desc=desc)

    out_file = File(
        genfile=True, position=0, desc='Output file name', argstr='%s')


class RegAverageOutputSpec(TraitedSpec):
    """ Output Spec for RegAverage. """
    out_file = File(desc='Output file name')


class RegAverage(NiftyRegCommand):
    """Interface for executable reg_average from NiftyReg platform.

    Compute average matrix or image from a list of matrices or image.
    The tool can be use to resample images given input transformation
    parametrisation as well as to demean transformations in Euclidean or
    log-Euclidean space.

    This interface is different than the others in the way that the options
    will be written in a command file that is given as a parameter.

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------

    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegAverage()
    >>> one_file = 'im1.nii'
    >>> two_file = 'im2.nii'
    >>> three_file = 'im3.nii'
    >>> node.inputs.avg_files = [one_file, two_file, three_file]
    >>> node.cmdline  # doctest: +ELLIPSIS
    'reg_average --cmd_file .../reg_average_cmd'
    """
    _cmd = get_custom_path('reg_average')
    input_spec = RegAverageInputSpec
    output_spec = RegAverageOutputSpec
    _suffix = 'avg_out'

    def _gen_filename(self, name):
        if name == 'out_file':
            if isdefined(self.inputs.avg_lts_files):
                return self._gen_fname(self._suffix, ext='.txt')
            elif isdefined(self.inputs.avg_files):
                _, _, _ext = split_filename(self.inputs.avg_files[0])
                if _ext not in ['.nii', '.nii.gz', '.hdr', '.img', '.img.gz']:
                    return self._gen_fname(self._suffix, ext=_ext)
            return self._gen_fname(self._suffix, ext='.nii.gz')

        return None

    def _list_outputs(self):
        outputs = self.output_spec().get()

        if isdefined(self.inputs.out_file):
            outputs['out_file'] = self.inputs.out_file
        else:
            outputs['out_file'] = self._gen_filename('out_file')

        return outputs

    @property
    def cmdline(self):
        """ Rewrite the cmdline to write options in text_file."""
        argv = super(RegAverage, self).cmdline
        reg_average_cmd = os.path.join(os.getcwd(), 'reg_average_cmd')
        with open(reg_average_cmd, 'w') as f:
            f.write(argv)
        return '%s --cmd_file %s' % (self.cmd, reg_average_cmd)


class RegTransformInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegTransform. """
    ref1_file = File(
        exists=True,
        desc='The input reference/target image',
        argstr='-ref %s',
        position=0)

    ref2_file = File(
        exists=True,
        desc='The input second reference/target image',
        argstr='-ref2 %s',
        position=1,
        requires=['ref1_file'])

    def_input = File(
        exists=True,
        argstr='-def %s',
        position=-2,
        desc='Compute deformation field from transformation',
        xor=[
            'disp_input', 'flow_input', 'comp_input', 'upd_s_form_input',
            'inv_aff_input', 'inv_nrr_input', 'half_input', 'make_aff_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    disp_input = File(
        exists=True,
        argstr='-disp %s',
        position=-2,
        desc='Compute displacement field from transformation',
        xor=[
            'def_input', 'flow_input', 'comp_input', 'upd_s_form_input',
            'inv_aff_input', 'inv_nrr_input', 'half_input', 'make_aff_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    flow_input = File(
        exists=True,
        argstr='-flow %s',
        position=-2,
        desc='Compute flow field from spline SVF',
        xor=[
            'def_input', 'disp_input', 'comp_input', 'upd_s_form_input',
            'inv_aff_input', 'inv_nrr_input', 'half_input', 'make_aff_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    comp_input = File(
        exists=True,
        argstr='-comp %s',
        position=-3,
        desc='compose two transformations',
        xor=[
            'def_input', 'disp_input', 'flow_input', 'upd_s_form_input',
            'inv_aff_input', 'inv_nrr_input', 'half_input', 'make_aff_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ],
        requires=['comp_input2'])

    comp_input2 = File(
        exists=True,
        argstr='%s',
        position=-2,
        desc='compose two transformations')

    desc = 'Update s-form using the affine transformation'
    upd_s_form_input = File(
        exists=True,
        argstr='-updSform %s',
        position=-3,
        desc=desc,
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'inv_aff_input', 'inv_nrr_input', 'half_input', 'make_aff_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ],
        requires=['upd_s_form_input2'])

    desc = 'Update s-form using the affine transformation'
    upd_s_form_input2 = File(
        exists=True,
        argstr='%s',
        position=-2,
        desc=desc,
        requires=['upd_s_form_input'])

    inv_aff_input = File(
        exists=True,
        argstr='-invAff %s',
        position=-2,
        desc='Invert an affine transformation',
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_nrr_input', 'half_input',
            'make_aff_input', 'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    inv_nrr_input = traits.Tuple(
        File(exists=True),
        File(exists=True),
        desc='Invert a non-linear transformation',
        argstr='-invNrr %s %s',
        position=-2,
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_aff_input', 'half_input',
            'make_aff_input', 'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    half_input = File(
        exists=True,
        argstr='-half %s',
        position=-2,
        desc='Half way to the input transformation',
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_aff_input', 'inv_nrr_input',
            'make_aff_input', 'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    argstr_tmp = '-makeAff %f %f %f %f %f %f %f %f %f %f %f %f'
    make_aff_input = traits.Tuple(
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        traits.Float,
        argstr=argstr_tmp,
        position=-2,
        desc='Make an affine transformation matrix',
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_aff_input', 'inv_nrr_input', 'half_input',
            'aff_2_rig_input', 'flirt_2_nr_input'
        ])

    desc = 'Extract the rigid component from affine transformation'
    aff_2_rig_input = File(
        exists=True,
        argstr='-aff2rig %s',
        position=-2,
        desc=desc,
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_aff_input', 'inv_nrr_input', 'half_input',
            'make_aff_input', 'flirt_2_nr_input'
        ])

    desc = 'Convert a FLIRT affine transformation to niftyreg affine \
transformation'

    flirt_2_nr_input = traits.Tuple(
        File(exists=True),
        File(exists=True),
        File(exists=True),
        argstr='-flirtAff2NR %s %s %s',
        position=-2,
        desc=desc,
        xor=[
            'def_input', 'disp_input', 'flow_input', 'comp_input',
            'upd_s_form_input', 'inv_aff_input', 'inv_nrr_input', 'half_input',
            'make_aff_input', 'aff_2_rig_input'
        ])

    out_file = File(
        genfile=True,
        position=-1,
        argstr='%s',
        desc='transformation file to write')


class RegTransformOutputSpec(TraitedSpec):
    """ Output Spec for RegTransform. """
    out_file = File(desc='Output File (transformation in any format)')


class RegTransform(NiftyRegCommand):
    """Interface for executable reg_transform from NiftyReg platform.

    Tools to convert transformation parametrisation from one type to another
    as well as to compose, inverse or half transformations.

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------
    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegTransform()
    >>> node.inputs.def_input = 'warpfield.nii'
    >>> node.inputs.omp_core_val = 4
    >>> node.cmdline  # doctest: +ELLIPSIS
    'reg_transform -omp 4 -def warpfield.nii .../warpfield_trans.nii.gz'

    """
    _cmd = get_custom_path('reg_transform')
    input_spec = RegTransformInputSpec
    output_spec = RegTransformOutputSpec
    _suffix = '_trans'

    def _find_input(self):
        inputs = [
            self.inputs.def_input, self.inputs.disp_input,
            self.inputs.flow_input, self.inputs.comp_input,
            self.inputs.comp_input2, self.inputs.upd_s_form_input,
            self.inputs.inv_aff_input, self.inputs.inv_nrr_input,
            self.inputs.half_input, self.inputs.make_aff_input,
            self.inputs.aff_2_rig_input, self.inputs.flirt_2_nr_input
        ]
        entries = []
        for entry in inputs:
            if isdefined(entry):
                entries.append(entry)
                _, _, ext = split_filename(entry)
                if ext == '.nii' or ext == '.nii.gz' or ext == '.hdr':
                    return entry
        if len(entries):
            return entries[0]
        return None

    def _gen_filename(self, name):
        if name == 'out_file':
            if isdefined(self.inputs.make_aff_input):
                return self._gen_fname(
                    'matrix', suffix=self._suffix, ext='.txt')

            if isdefined(self.inputs.comp_input) and \
               isdefined(self.inputs.comp_input2):
                _, bn1, ext1 = split_filename(self.inputs.comp_input)
                _, _, ext2 = split_filename(self.inputs.comp_input2)
                if ext1 in ['.nii', '.nii.gz', '.hdr', '.img', '.img.gz'] or \
                   ext2 in ['.nii', '.nii.gz', '.hdr', '.img', '.img.gz']:
                    return self._gen_fname(
                        bn1, suffix=self._suffix, ext='.nii.gz')
                else:
                    return self._gen_fname(bn1, suffix=self._suffix, ext=ext1)

            if isdefined(self.inputs.flirt_2_nr_input):
                return self._gen_fname(
                    self.inputs.flirt_2_nr_input[0],
                    suffix=self._suffix,
                    ext='.txt')

            input_to_use = self._find_input()
            _, _, ext = split_filename(input_to_use)
            if ext not in ['.nii', '.nii.gz', '.hdr', '.img', '.img.gz']:
                return self._gen_fname(
                    input_to_use, suffix=self._suffix, ext=ext)
            else:
                return self._gen_fname(
                    input_to_use, suffix=self._suffix, ext='.nii.gz')

        return None

    def _list_outputs(self):
        outputs = self.output_spec().get()

        if isdefined(self.inputs.out_file):
            outputs['out_file'] = self.inputs.out_file
        else:
            outputs['out_file'] = self._gen_filename('out_file')

        return outputs


class RegMeasureInputSpec(NiftyRegCommandInputSpec):
    """ Input Spec for RegMeasure. """
    # Input reference file
    ref_file = File(
        exists=True,
        desc='The input reference/target image',
        argstr='-ref %s',
        mandatory=True)
    # Input floating file
    flo_file = File(
        exists=True,
        desc='The input floating/source image',
        argstr='-flo %s',
        mandatory=True)
    measure_type = traits.Enum(
        'ncc',
        'lncc',
        'nmi',
        'ssd',
        mandatory=True,
        argstr='-%s',
        desc='Measure of similarity to compute')
    out_file = File(
        name_source=['flo_file'],
        name_template='%s',
        argstr='-out %s',
        desc='The output text file containing the measure')


class RegMeasureOutputSpec(TraitedSpec):
    """ Output Spec for RegMeasure. """
    out_file = File(desc='The output text file containing the measure')


class RegMeasure(NiftyRegCommand):
    """Interface for executable reg_measure from NiftyReg platform.

    Given two input images, compute the specified measure(s) of similarity

    `Source code <https://cmiclab.cs.ucl.ac.uk/mmodat/niftyreg>`_

    Examples
    --------
    >>> from nipype.interfaces import niftyreg
    >>> node = niftyreg.RegMeasure()
    >>> node.inputs.ref_file = 'im1.nii'
    >>> node.inputs.flo_file = 'im2.nii'
    >>> node.inputs.measure_type = 'lncc'
    >>> node.inputs.omp_core_val = 4
    >>> node.cmdline
    'reg_measure -flo im2.nii -lncc -omp 4 -out im2_lncc.txt -ref im1.nii'

    """
    _cmd = get_custom_path('reg_measure')
    input_spec = RegMeasureInputSpec
    output_spec = RegMeasureOutputSpec

    def _overload_extension(self, value, name=None):
        path, base, _ = split_filename(value)
        suffix = self.inputs.measure_type
        return os.path.join(path, '{0}_{1}.txt'.format(base, suffix))
