CommandLineInputSpec does not include absolute path of the input file

Hi,

I am writing a command line interface wrapper for eddy_correction. The expected command is:

eddy_correct /share/foxlab-backedup/necfdg/mri/ds_2017-09-26_09-00/dti_006_dwi_HF_1shell_b1200.nii /share/foxlab-backedup/necfdg/mri/ds_2017-09-26_09-00/dti_006_dwi_HF_1shell_b1200_eddy.nii 0

However, the new_file attribute of CommandLineInputSpec does not include the absolute path of the input_file when generating the name_template. Therefore I got this:

eddy_correct /share/foxlab-backedup/necfdg/mri/ds_2017-09-26_09-00/dti_005_dwi_FH_1shell_b1200.nii dti_005_dwi_FH_1shell_b1200_eddy_testing.nii 0

I am trying to input the files from multiple directories and output them back to their respective directories.

Is there a way to include input file as absolute path of the file, when in the working directory?

Any idea would be greatly appreciated!

Below is my code for the custom cli:

'''
Custom eddy_correct cmd line interface 
'''

#Import nipype interfaces 
from nipype.interfaces.base import (
        TraitedSpec,
        CommandLineInputSpec,
        CommandLine,
        File,
        traits
)
from nipype.utils.filemanip import split_filename
import os

#Create my own custom command line interface
#new file name ends w/ "_eddy_testing.nii"
class EddyInputSpec(CommandLineInputSpec):
        input_file = File(desc='file to be eddy corrected', exists=True,
                          mandatory=True, position=0, argstr="%s")
        new_file = File(desc='new file name', argstr='%s',
                        name_source=['input_file'],
                        name_template='%s_eddy_testing.nii', position=1)
        param = traits.Str(desc = 'Additional parameters to the command', position=2, argstr="%s")


class EddyOutputSpec(TraitedSpec):
        output_file = File(desc='eddy corrected file', exists=True)


class EddyTask(CommandLine):
        input_spec = EddyInputSpec
        output_spec = EddyOutputSpec
        _cmd = 'eddy_correct'

        def _list_outputs(self):
                input_path = os.path.dirname(self.inputs.input_file)
                path, fname, ext = split_filename(input_path)
                outputs = self.output_spec().get()
                outputs['output_file'] = os.path.abspath(path + '/' + fname + "_eddy_testing.nii.gz")
                return outputs

Also, would it be better to use fsl’s eddy_correction?

hi @yizizhang - are you having problems using our current Eddy interface? Or is it missing a specific input/output you would like? If the latter, I would suggest modifying the existing one instead of making a new interface from scratch!

Hi @mgxd,

Thank you for the reply! For eddy, I think I will try using the existing interface as you suggested. However, I would like to use some of my own command line executables later, and it would be helpful to know how to include the path of the input file as a source of naming template for the new file.

Do you by any chance know how to do this with the CommandLineInputSpec?

@yizizhang - you could add a _format_arg method to your interface (EddyTask) which further alters the command. In general, you should avoid hardcoding full paths - if you plan on using a Nipype workflow, files are copied and saved to working directories (by default) to avoid any data overwriting.

perhaps something like this…

def _format_arg(self, opt, spec, val):
    if opt == 'new_file':
        dirname = os.path.dirname(self.inputs.input_file)
        val = os.path.join(dirname, val)
    return super(EddyTask, self)._format_arg(opt, spec, val)

It solved my problem. Thank you for your help!