diff --git a/nipype/interfaces/fsl/ICA_AROMA.py b/nipype/interfaces/fsl/ICA_AROMA.py new file mode 100644 index 0000000000..7d5a1a5362 --- /dev/null +++ b/nipype/interfaces/fsl/ICA_AROMA.py @@ -0,0 +1,118 @@ +# -*- 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: +"""This commandline module provides classes for interfacing with the +`ICA-AROMA.py`_ command line tool. + Change directory to provide relative paths for doctests + >>> import os + >>> filepath = os.path.dirname(os.path.realpath(__file__)) + >>> datadir = os.path.realpath(os.path.join(filepath, + ... '../../testing/data')) + >>> os.chdir(datadir) +""" +from nipype.interfaces.base import ( + TraitedSpec, + CommandLineInputSpec, + CommandLine, + File, + Directory, + traits, + OutputMultiPath +) +import os + +class ICA_AROMAInputSpec(CommandLineInputSpec): + feat_dir = Directory(exists=True, mandatory=True, + argstr='-feat %s', + xor=['in_file', 'mat_file', 'fnirt_warp_file', 'motion_parameters'], + desc='If a feat directory exists and temporal filtering ' + 'has not been run yet, ICA_AROMA can use the files in ' + 'this directory.') + in_file = File(exists=True, mandatory=True, + argstr='-i %s', xor=['feat_dir'], + desc='volume to be denoised') + out_dir = Directory('out', mandatory=True, + argstr='-o %s', + desc='output directory') + mask = File(exists=True, argstr='-m %s', xor=['feat_dir'], + desc='path/name volume mask') + dim = traits.Int(argstr='-dim %d', + desc='Dimensionality reduction when running ' + 'MELODIC (defualt is automatic estimation)') + TR = traits.Float(argstr='-tr %.3f', + desc='TR in seconds. If this is not specified ' + 'the TR will be extracted from the ' + 'header of the fMRI nifti file.') + melodic_dir = Directory(exists=True, argstr='-meldir %s', + desc='path to MELODIC directory if MELODIC has already been run') + mat_file = File(exists=True, argstr='-affmat %s', xor=['feat_dir'], + desc='path/name of the mat-file describing the ' + 'affine registration (e.g. FSL FLIRT) of the ' + 'functional data to structural space (.mat file)') + fnirt_warp_file = File(exists=True, argstr='-warp %s', xor=['feat_dir'], + desc='File name of the warp-file describing ' + 'the non-linear registration (e.g. FSL FNIRT) ' + 'of the structural data to MNI152 space (.nii.gz)') + motion_parameters = File(exists=True, mandatory=True, + argstr='-mc %s', xor=['feat_dir'], + desc='motion parameters file') + denoise_type = traits.Enum('nonaggr', 'aggr', 'both', 'no', usedefault=True, + mandatory=True, argstr='-den %s', + desc='Type of denoising strategy:\n' + '-none: only classification, no denoising\n' + '-nonaggr (default): non-aggresssive denoising, i.e. partial component regression\n' + '-aggr: aggressive denoising, i.e. full component regression\n' + '-both: both aggressive and non-aggressive denoising (two outputs)') + +class ICA_AROMAOutputSpec(TraitedSpec): + aggr_denoised_file = File(exists=True, + desc='if generated: aggressively denoised volume') + nonaggr_denoised_file = File(exists=True, + desc='if generated: non aggressively denoised volume' ) + out_dir = Directory(exists=True, + desc='directory contains (in addition to the denoised files): ' + 'melodic.ica + classified_motion_components + ' + 'classification_overview + feature_scores + melodic_ic_mni)') + +class ICA_AROMA(CommandLine): + """ + Interface for the ICA_AROMA.py script. + + ICA-AROMA (i.e. 'ICA-based Automatic Removal Of Motion Artifacts') concerns + a data-driven method to identify and remove motion-related independent + components from fMRI data. To that end it exploits a small, but robust + set of theoretically motivated features, preventing the need for classifier + re-training and therefore providing direct and easy applicability. + + See link for further documentation: https://github.com/rhr-pruim/ICA-AROMA + + Example + ------- + + >>> from nipype.interfaces.fsl import ICA_AROMA + >>> from nipype.testing import example_data + >>> AROMA_obj = ICA_AROMA.ICA_AROMA() + >>> AROMA_obj.inputs.in_file = 'functional.nii' + >>> AROMA_obj.inputs.mat_file = 'func_to_struct.mat' + >>> AROMA_obj.inputs.fnirt_warp_file = 'warpfield.nii' + >>> AROMA_obj.inputs.motion_parameters = 'fsl_mcflirt_movpar.txt' + >>> AROMA_obj.inputs.mask = 'mask.nii.gz' + >>> AROMA_obj.inputs.denoise_type = 'both' + >>> AROMA_obj.inputs.out_dir = 'ICA_testout' + >>> AROMA_obj.cmdline # doctest: +ALLOW_UNICODE + 'ICA_AROMA.py -den both -warp warpfield.nii -i functional.nii -m mask.nii.gz -affmat func_to_struct.mat -mc fsl_mcflirt_movpar.txt -o ICA_testout' + """ + _cmd = 'ICA_AROMA.py' + input_spec = ICA_AROMAInputSpec + output_spec = ICA_AROMAOutputSpec + + def _list_outputs(self): + out_dir = os.path.abspath(self.inputs.out_dir) + outputs['out_dir'] = out_dir + + if self.inputs.denoise_type in ('aggr', 'both'): + outputs['aggr_denoised_file'] = os.path.join(out_dir, 'denoised_func_data_aggr.nii.gz') + if self.inputs.denoise_type in ('nonaggr', 'both'): + outputs['nonaggr_denoised_file'] = os.path.join(out_dir, 'denoised_func_data_nonaggr.nii.gz') + + return outputs diff --git a/nipype/interfaces/fsl/tests/test_auto_ICA_AROMA.py b/nipype/interfaces/fsl/tests/test_auto_ICA_AROMA.py new file mode 100644 index 0000000000..98f1674639 --- /dev/null +++ b/nipype/interfaces/fsl/tests/test_auto_ICA_AROMA.py @@ -0,0 +1,68 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..ICA_AROMA import ICA_AROMA + + +def test_ICA_AROMA_inputs(): + input_map = dict(TR=dict(argstr='-tr %.3f', + ), + args=dict(argstr='%s', + ), + denoise_type=dict(argstr='-den %s', + mandatory=True, + usedefault=True, + ), + dim=dict(argstr='-dim %d', + ), + environ=dict(nohash=True, + usedefault=True, + ), + feat_dir=dict(argstr='-feat %s', + mandatory=True, + xor=['in_file', 'mat_file', 'fnirt_warp_file', 'motion_parameters'], + ), + fnirt_warp_file=dict(argstr='-warp %s', + xor=['feat_dir'], + ), + ignore_exception=dict(nohash=True, + usedefault=True, + ), + in_file=dict(argstr='-i %s', + mandatory=True, + xor=['feat_dir'], + ), + mask=dict(argstr='-m %s', + xor=['feat_dir'], + ), + mat_file=dict(argstr='-affmat %s', + xor=['feat_dir'], + ), + melodic_dir=dict(argstr='-meldir %s', + ), + motion_parameters=dict(argstr='-mc %s', + mandatory=True, + xor=['feat_dir'], + ), + out_dir=dict(argstr='-o %s', + mandatory=True, + ), + terminal_output=dict(nohash=True, + ), + ) + inputs = ICA_AROMA.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_ICA_AROMA_outputs(): + output_map = dict(aggr_denoised_file=dict(), + nonaggr_denoised_file=dict(), + out_dir=dict(), + ) + outputs = ICA_AROMA.output_spec() + + for key, metadata in list(output_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(outputs.traits()[key], metakey) == value