From 3b255281e6221c8789e698e6e1cffcd2ad904320 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 12:43:38 -0400 Subject: [PATCH 01/11] ENH: Add LibraryBaseInterface --- nipype/interfaces/base/__init__.py | 2 +- nipype/interfaces/base/core.py | 29 +++++++++++++++++++++++++++++ nipype/interfaces/dipy/base.py | 13 +++---------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/nipype/interfaces/base/__init__.py b/nipype/interfaces/base/__init__.py index cb24ea50a9..642363479a 100644 --- a/nipype/interfaces/base/__init__.py +++ b/nipype/interfaces/base/__init__.py @@ -10,7 +10,7 @@ """ from .core import (Interface, BaseInterface, SimpleInterface, CommandLine, StdOutCommandLine, MpiCommandLine, SEMLikeCommandLine, - PackageInfo) + LibraryBaseInterface, PackageInfo) from .specs import (BaseTraitedSpec, TraitedSpec, DynamicTraitedSpec, BaseInterfaceInputSpec, CommandLineInputSpec, diff --git a/nipype/interfaces/base/core.py b/nipype/interfaces/base/core.py index c199af3ca8..80c209fcba 100644 --- a/nipype/interfaces/base/core.py +++ b/nipype/interfaces/base/core.py @@ -1267,6 +1267,35 @@ def _format_arg(self, name, spec, value): return super(SEMLikeCommandLine, self)._format_arg(name, spec, value) +class LibraryBaseInterface(BaseInterface): + _pkg = None + imports = () + + def __init__(self, check_import=True, *args, **kwargs): + super(LibraryBaseInterface, self).__init__(*args, **kwargs) + if check_import: + import importlib + failed_imports = [] + for pkg in (self._pkg,) + tuple(self.imports): + try: + importlib.import_module(pkg) + except ImportError: + failed_imports.append(pkg) + if failed_imports: + iflogger.warn('Unable to import %s; %s interface may fail to ' + 'run', failed_imports, self.__class__.__name__) + + @property + def version(self): + if self._version is None: + import importlib + try: + self._version = importlib.import_module(self._pkg).__version__ + except (ImportError, AttributeError): + pass + return super(LibraryBaseInterface, self).version + + class PackageInfo(object): _version = None version_cmd = None diff --git a/nipype/interfaces/dipy/base.py b/nipype/interfaces/dipy/base.py index 6c05da6f16..7a9221e3d1 100644 --- a/nipype/interfaces/dipy/base.py +++ b/nipype/interfaces/dipy/base.py @@ -6,11 +6,9 @@ import os.path as op import numpy as np from ... import logging -from ..base import (traits, File, isdefined, BaseInterface, +from ..base import (traits, File, isdefined, LibraryBaseInterface, BaseInterfaceInputSpec) -IFLOGGER = logging.getLogger('interface') - HAVE_DIPY = True try: import dipy @@ -32,16 +30,11 @@ def dipy_version(): return dipy.__version__ -class DipyBaseInterface(BaseInterface): +class DipyBaseInterface(LibraryBaseInterface): """ A base interface for py:mod:`dipy` computations """ - - def __init__(self, **inputs): - if no_dipy(): - IFLOGGER.warn('dipy was not found') - # raise ImportError('dipy was not found') - super(DipyBaseInterface, self).__init__(**inputs) + _pkg = 'dipy' class DipyBaseInterfaceInputSpec(BaseInterfaceInputSpec): From 3a544096b9eb08e819c9606705dd48826a58ba37 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 19:44:10 -0400 Subject: [PATCH 02/11] RF: NipyBaseInterface --- nipype/interfaces/nipy/base.py | 20 +++++++++++++++++++ nipype/interfaces/nipy/model.py | 30 ++++++++++------------------ nipype/interfaces/nipy/preprocess.py | 27 +++++++------------------ nipype/interfaces/nipy/utils.py | 17 +++++----------- 4 files changed, 43 insertions(+), 51 deletions(-) create mode 100644 nipype/interfaces/nipy/base.py diff --git a/nipype/interfaces/nipy/base.py b/nipype/interfaces/nipy/base.py new file mode 100644 index 0000000000..077499c52a --- /dev/null +++ b/nipype/interfaces/nipy/base.py @@ -0,0 +1,20 @@ +# -*- 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: +""" Base interface for nipy """ + +from ..base import LibraryBaseInterface +from ...utils.misc import package_check + +# Originally set in model, preprocess and utils +# Set here to be imported, in case anybody depends on its presence +# Remove in 2.0 +have_nipy = True +try: + package_check('nipy') +except ImportError: + have_nipy = False + + +class NipyBaseInterface(LibraryBaseInterface): + _pkg = 'nipy' diff --git a/nipype/interfaces/nipy/model.py b/nipype/interfaces/nipy/model.py index 7df9cb609d..8746728990 100644 --- a/nipype/interfaces/nipy/model.py +++ b/nipype/interfaces/nipy/model.py @@ -8,27 +8,12 @@ import nibabel as nb import numpy as np -from ...utils.misc import package_check from ...utils import NUMPY_MMAP -from ..base import (BaseInterface, TraitedSpec, traits, File, OutputMultiPath, +from .base import NipyBaseInterface, have_nipy +from ..base import (TraitedSpec, traits, File, OutputMultiPath, BaseInterfaceInputSpec, isdefined) -have_nipy = True -try: - package_check('nipy') -except Exception as e: - have_nipy = False -else: - import nipy.modalities.fmri.design_matrix as dm - import nipy.modalities.fmri.glm as GLM - -if have_nipy: - try: - BlockParadigm = dm.BlockParadigm - except AttributeError: - from nipy.modalities.fmri.experimental_paradigm import BlockParadigm - class FitGLMInputSpec(BaseInterfaceInputSpec): session_info = traits.List( @@ -94,7 +79,7 @@ class FitGLMOutputSpec(TraitedSpec): a = File(exists=True) -class FitGLM(BaseInterface): +class FitGLM(NipyBaseInterface): ''' Fit GLM model based on the specified design. Supports only single or concatenated runs. ''' @@ -102,6 +87,12 @@ class FitGLM(BaseInterface): output_spec = FitGLMOutputSpec def _run_interface(self, runtime): + import nipy.modalities.fmri.glm as GLM + import nipy.modalities.fmri.design_matrix as dm + try: + BlockParadigm = dm.BlockParadigm + except AttributeError: + from nipy.modalities.fmri.experimental_paradigm import BlockParadigm session_info = self.inputs.session_info @@ -283,7 +274,7 @@ class EstimateContrastOutputSpec(TraitedSpec): p_maps = OutputMultiPath(File(exists=True)) -class EstimateContrast(BaseInterface): +class EstimateContrast(NipyBaseInterface): ''' Estimate contrast of a fitted model. ''' @@ -291,6 +282,7 @@ class EstimateContrast(BaseInterface): output_spec = EstimateContrastOutputSpec def _run_interface(self, runtime): + import nipy.modalities.fmri.glm as GLM beta_nii = nb.load(self.inputs.beta) if isdefined(self.inputs.mask): diff --git a/nipype/interfaces/nipy/preprocess.py b/nipype/interfaces/nipy/preprocess.py index 6a73fbca30..252463e3f7 100644 --- a/nipype/interfaces/nipy/preprocess.py +++ b/nipype/interfaces/nipy/preprocess.py @@ -8,22 +8,12 @@ import nibabel as nb import numpy as np -from ...utils.misc import package_check from ...utils import NUMPY_MMAP - from ...utils.filemanip import split_filename, fname_presuffix -from ..base import (TraitedSpec, BaseInterface, traits, BaseInterfaceInputSpec, - isdefined, File, InputMultiPath, OutputMultiPath) -have_nipy = True -try: - package_check('nipy') -except Exception as e: - have_nipy = False -else: - import nipy - from nipy import save_image, load_image - nipy_version = nipy.__version__ +from .base import NipyBaseInterface, have_nipy +from ..base import (TraitedSpec, traits, BaseInterfaceInputSpec, + isdefined, File, InputMultiPath, OutputMultiPath) class ComputeMaskInputSpec(BaseInterfaceInputSpec): @@ -44,7 +34,7 @@ class ComputeMaskOutputSpec(TraitedSpec): brain_mask = File(exists=True) -class ComputeMask(BaseInterface): +class ComputeMask(NipyBaseInterface): input_spec = ComputeMaskInputSpec output_spec = ComputeMaskOutputSpec @@ -118,7 +108,7 @@ class SpaceTimeRealignerOutputSpec(TraitedSpec): "euler angles")) -class SpaceTimeRealigner(BaseInterface): +class SpaceTimeRealigner(NipyBaseInterface): """Simultaneous motion and slice timing correction algorithm If slice_times is not specified, this algorithm performs spatial motion @@ -157,11 +147,8 @@ class SpaceTimeRealigner(BaseInterface): output_spec = SpaceTimeRealignerOutputSpec keywords = ['slice timing', 'motion correction'] - @property - def version(self): - return nipy_version - def _run_interface(self, runtime): + from nipy import save_image, load_image all_ims = [load_image(fname) for fname in self.inputs.in_file] if not isdefined(self.inputs.slice_times): @@ -233,7 +220,7 @@ class TrimOutputSpec(TraitedSpec): out_file = File(exists=True) -class Trim(BaseInterface): +class Trim(NipyBaseInterface): """ Simple interface to trim a few volumes from a 4d fmri nifti file Examples diff --git a/nipype/interfaces/nipy/utils.py b/nipype/interfaces/nipy/utils.py index 12e593e1b1..406960fc6d 100644 --- a/nipype/interfaces/nipy/utils.py +++ b/nipype/interfaces/nipy/utils.py @@ -5,19 +5,10 @@ import warnings import nibabel as nb -from ...utils.misc import package_check -from ..base import (TraitedSpec, BaseInterface, traits, BaseInterfaceInputSpec, +from .base import NipyBaseInterface, have_nipy +from ..base import (TraitedSpec, traits, BaseInterfaceInputSpec, File, isdefined) -have_nipy = True -try: - package_check('nipy') -except Exception as e: - have_nipy = False -else: - from nipy.algorithms.registration.histogram_registration import HistogramRegistration - from nipy.algorithms.registration.affine import Affine - class SimilarityInputSpec(BaseInterfaceInputSpec): volume1 = File(exists=True, desc="3D volume", mandatory=True) @@ -42,7 +33,7 @@ class SimilarityOutputSpec(TraitedSpec): similarity = traits.Float(desc="Similarity between volume 1 and 2") -class Similarity(BaseInterface): +class Similarity(NipyBaseInterface): """Calculates similarity between two 3D volumes. Both volumes have to be in the same coordinate system, same space within that coordinate system and with the same voxel dimensions. @@ -72,6 +63,8 @@ def __init__(self, **inputs): super(Similarity, self).__init__(**inputs) def _run_interface(self, runtime): + from nipy.algorithms.registration.histogram_registration import HistogramRegistration + from nipy.algorithms.registration.affine import Affine vol1_nii = nb.load(self.inputs.volume1) vol2_nii = nb.load(self.inputs.volume2) From 2723c619cad3ae30f9207a154b2d0c3468cdffd5 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 19:58:24 -0400 Subject: [PATCH 03/11] RF: NitimeBaseInterface --- nipype/interfaces/nitime/analysis.py | 27 +++++++-------------------- nipype/interfaces/nitime/base.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 20 deletions(-) create mode 100644 nipype/interfaces/nitime/base.py diff --git a/nipype/interfaces/nitime/analysis.py b/nipype/interfaces/nitime/analysis.py index 36c550ca27..6e8ff17d0f 100644 --- a/nipype/interfaces/nitime/analysis.py +++ b/nipype/interfaces/nitime/analysis.py @@ -19,18 +19,15 @@ from ...utils.misc import package_check from ...utils.filemanip import fname_presuffix -from ..base import (TraitedSpec, File, Undefined, traits, BaseInterface, +from .base import NitimeBaseInterface +from ..base import (TraitedSpec, File, Undefined, traits, isdefined, BaseInterfaceInputSpec) have_nitime = True try: package_check('nitime') -except Exception as e: +except ImportError: have_nitime = False -else: - import nitime.analysis as nta - from nitime.timeseries import TimeSeries - import nitime.viz as viz class CoherenceAnalyzerInputSpec(BaseInterfaceInputSpec): @@ -116,7 +113,7 @@ class CoherenceAnalyzerOutputSpec(TraitedSpec): timedelay_fig = File(desc=('Figure representing coherence values')) -class CoherenceAnalyzer(BaseInterface): +class CoherenceAnalyzer(NitimeBaseInterface): input_spec = CoherenceAnalyzerInputSpec output_spec = CoherenceAnalyzerOutputSpec @@ -148,6 +145,7 @@ def _read_csv(self): def _csv2ts(self): """ Read data from the in_file and generate a nitime TimeSeries object""" + from nitime.timeseries import TimeSeries data, roi_names = self._read_csv() TS = TimeSeries( @@ -159,6 +157,7 @@ def _csv2ts(self): # Rewrite _run_interface, but not run def _run_interface(self, runtime): + import nitime.analysis as nta lb, ub = self.inputs.frequency_range if self.inputs.in_TS is Undefined: @@ -253,6 +252,7 @@ def _make_output_figures(self): self.inputs.output_figure_file """ + import nitime.viz as viz if self.inputs.figure_type == 'matrix': fig_coh = viz.drawmatrix_channels( self.coherence, channel_names=self.ROIs, color_anchor=0) @@ -281,16 +281,3 @@ def _make_output_figures(self): fig_dt.savefig( fname_presuffix( self.inputs.output_figure_file, suffix='_delay')) - - -class GetTimeSeriesInputSpec(object): - pass - - -class GetTimeSeriesOutputSpec(object): - pass - - -class GetTimeSeries(object): - # getting time series data from nifti files and ROIs - pass diff --git a/nipype/interfaces/nitime/base.py b/nipype/interfaces/nitime/base.py new file mode 100644 index 0000000000..d9139f2c71 --- /dev/null +++ b/nipype/interfaces/nitime/base.py @@ -0,0 +1,10 @@ +# -*- 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: +""" Base interface for nitime """ + +from ..base import LibraryBaseInterface + + +class NitimeBaseInterface(LibraryBaseInterface): + _pkg = 'nitime' From 37c78950b5e2e59874f5236930292d4961d37698 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 19:58:57 -0400 Subject: [PATCH 04/11] RF: NilearnBaseInterface --- nipype/interfaces/nilearn.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/nipype/interfaces/nilearn.py b/nipype/interfaces/nilearn.py index 3a77af9f57..699b7dc8d3 100644 --- a/nipype/interfaces/nilearn.py +++ b/nipype/interfaces/nilearn.py @@ -11,10 +11,13 @@ import numpy as np import nibabel as nb -from .. import logging -from ..interfaces.base import (traits, TraitedSpec, BaseInterface, - BaseInterfaceInputSpec, File, InputMultiPath) -IFLOGGER = logging.getLogger('interface') +from ..interfaces.base import (traits, TraitedSpec, LibraryBaseInterface, + SimpleInterface, BaseInterfaceInputSpec, File, + InputMultiPath) + + +class NilearnBaseInterface(LibraryBaseInterface): + _pkg = 'nilearn' class SignalExtractionInputSpec(BaseInterfaceInputSpec): @@ -70,7 +73,7 @@ class SignalExtractionOutputSpec(TraitedSpec): 'header row with values from class_labels') -class SignalExtraction(BaseInterface): +class SignalExtraction(NilearnBaseInterface, SimpleInterface): ''' Extracts signals over tissue classes or brain regions @@ -85,7 +88,6 @@ class SignalExtraction(BaseInterface): ''' input_spec = SignalExtractionInputSpec output_spec = SignalExtractionOutputSpec - _results = {} def _run_interface(self, runtime): maskers = self._process_inputs() @@ -99,14 +101,16 @@ def _run_interface(self, runtime): region_signals.astype(str))) # save output - self._results['out_file'] = os.path.join(runtime.cwd, self.inputs.out_file) + self._results['out_file'] = os.path.join(runtime.cwd, + self.inputs.out_file) np.savetxt( self._results['out_file'], output, fmt=b'%s', delimiter='\t') return runtime def _process_inputs(self): ''' validate and process inputs into useful form. - Returns a list of nilearn maskers and the list of corresponding label names.''' + Returns a list of nilearn maskers and the list of corresponding label + names.''' import nilearn.input_data as nl import nilearn.image as nli @@ -119,12 +123,12 @@ def _process_inputs(self): maskers.append(nl.NiftiLabelsMasker(label_data)) else: # 4d labels n_labels = label_data.get_data().shape[3] - if self.inputs.incl_shared_variance: # 4d labels, independent computation + if self.inputs.incl_shared_variance: # independent computation for img in nli.iter_img(label_data): maskers.append( nl.NiftiMapsMasker( self._4d(img.get_data(), img.affine))) - else: # 4d labels, one computation fitting all + else: # one computation fitting all maskers.append(nl.NiftiMapsMasker(label_data)) # check label list size @@ -160,6 +164,3 @@ def _4d(self, array, affine): ''' takes a 3-dimensional numpy array and an affine, returns the equivalent 4th dimensional nifti file ''' return nb.Nifti1Image(array[:, :, :, np.newaxis], affine) - - def _list_outputs(self): - return self._results From 7a99c27b1fc11b1cba98c9b1349df6bb2dcf2351 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 21:12:12 -0400 Subject: [PATCH 05/11] RF: CMTK with LibraryBaseInterface --- nipype/interfaces/cmtk/base.py | 33 ++++++++++++++++++++++++++ nipype/interfaces/cmtk/convert.py | 18 +++++--------- nipype/interfaces/cmtk/nbs.py | 19 ++++----------- nipype/interfaces/cmtk/nx.py | 10 +------- nipype/interfaces/cmtk/parcellation.py | 31 ++++++++++-------------- 5 files changed, 58 insertions(+), 53 deletions(-) create mode 100644 nipype/interfaces/cmtk/base.py diff --git a/nipype/interfaces/cmtk/base.py b/nipype/interfaces/cmtk/base.py new file mode 100644 index 0000000000..4aedd56bdb --- /dev/null +++ b/nipype/interfaces/cmtk/base.py @@ -0,0 +1,33 @@ +# -*- 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: +""" Base interface for cmtk """ + +from ..base import LibraryBaseInterface +from ...utils.misc import package_check + + +class CFFBaseInterface(LibraryBaseInterface): + _pkg = 'cfflib' + + +# Originally set in convert, nbs, nx, parcellation +# Set here to be imported, in case anybody depends on its presence +# Remove in 2.0 +have_cmp = True +try: + package_check('cmp') +except ImportError: + have_cmp = False + +have_cfflib = True +try: + package_check('cfflib') +except ImportError: + have_cfflib = False + +have_cv = True +try: + package_check('cviewer') +except ImportError: + have_cv = False diff --git a/nipype/interfaces/cmtk/convert.py b/nipype/interfaces/cmtk/convert.py index 793b92bd4b..93802d5eb8 100644 --- a/nipype/interfaces/cmtk/convert.py +++ b/nipype/interfaces/cmtk/convert.py @@ -8,18 +8,10 @@ import string import networkx as nx -from ...utils.misc import package_check from ...utils.filemanip import split_filename -from ..base import (BaseInterface, BaseInterfaceInputSpec, traits, File, +from ..base import (BaseInterfaceInputSpec, traits, File, TraitedSpec, InputMultiPath, isdefined) - -have_cfflib = True -try: - package_check('cfflib') -except Exception as e: - have_cfflib = False -else: - import cfflib as cf +from .base import CFFBaseInterface, have_cfflib class CFFConverterInputSpec(BaseInterfaceInputSpec): @@ -67,7 +59,7 @@ class CFFConverterOutputSpec(TraitedSpec): connectome_file = File(exists=True, desc='Output connectome file') -class CFFConverter(BaseInterface): +class CFFConverter(CFFBaseInterface): """ Creates a Connectome File Format (CFF) file from input networks, surfaces, volumes, tracts, etcetera.... @@ -87,6 +79,7 @@ class CFFConverter(BaseInterface): output_spec = CFFConverterOutputSpec def _run_interface(self, runtime): + import cfflib as cf a = cf.connectome() if isdefined(self.inputs.title): @@ -232,7 +225,7 @@ class MergeCNetworksOutputSpec(TraitedSpec): exists=True, desc='Output CFF file with all the networks added') -class MergeCNetworks(BaseInterface): +class MergeCNetworks(CFFBaseInterface): """ Merges networks from multiple CFF files into one new CFF file. Example @@ -248,6 +241,7 @@ class MergeCNetworks(BaseInterface): output_spec = MergeCNetworksOutputSpec def _run_interface(self, runtime): + import cfflib as cf extracted_networks = [] for i, con in enumerate(self.inputs.in_files): diff --git a/nipype/interfaces/cmtk/nbs.py b/nipype/interfaces/cmtk/nbs.py index 954b4d53df..11ed59b1ad 100644 --- a/nipype/interfaces/cmtk/nbs.py +++ b/nipype/interfaces/cmtk/nbs.py @@ -10,19 +10,11 @@ import networkx as nx from ... import logging -from ...utils.misc import package_check -from ..base import (BaseInterface, BaseInterfaceInputSpec, traits, File, +from ..base import (LibraryBaseInterface, BaseInterfaceInputSpec, traits, File, TraitedSpec, InputMultiPath, OutputMultiPath, isdefined) +from .base import have_cv iflogger = logging.getLogger('interface') -have_cv = True -try: - package_check('cviewer') -except Exception as e: - have_cv = False -else: - import cviewer.libs.pyconto.groupstatistics.nbs as nbs - def ntwks_to_matrices(in_files, edge_key): first = nx.read_gpickle(in_files[0]) @@ -92,7 +84,7 @@ class NetworkBasedStatisticOutputSpec(TraitedSpec): desc='Output network with edges identified by the NBS') -class NetworkBasedStatistic(BaseInterface): +class NetworkBasedStatistic(LibraryBaseInterface): """ Calculates and outputs the average network given a set of input NetworkX gpickle files @@ -111,11 +103,10 @@ class NetworkBasedStatistic(BaseInterface): """ input_spec = NetworkBasedStatisticInputSpec output_spec = NetworkBasedStatisticOutputSpec + _pkg = 'cviewer' def _run_interface(self, runtime): - - if not have_cv: - raise ImportError("cviewer library is not available") + from cviewer.libs.pyconto.groupstatistics import nbs THRESH = self.inputs.threshold K = self.inputs.number_of_permutations diff --git a/nipype/interfaces/cmtk/nx.py b/nipype/interfaces/cmtk/nx.py index bbc5de77b9..dce35ad627 100644 --- a/nipype/interfaces/cmtk/nx.py +++ b/nipype/interfaces/cmtk/nx.py @@ -14,20 +14,12 @@ from ... import logging from ...utils.filemanip import split_filename -from ...utils.misc import package_check from ..base import (BaseInterface, BaseInterfaceInputSpec, traits, File, TraitedSpec, InputMultiPath, OutputMultiPath, isdefined) +from .base import have_cmp iflogger = logging.getLogger('interface') -have_cmp = True -try: - package_check('cmp') -except Exception as e: - have_cmp = False -else: - import cmp - def read_unknown_ntwk(ntwk): if not isinstance(ntwk, nx.classes.graph.Graph): diff --git a/nipype/interfaces/cmtk/parcellation.py b/nipype/interfaces/cmtk/parcellation.py index 824d653027..6947cb852f 100644 --- a/nipype/interfaces/cmtk/parcellation.py +++ b/nipype/interfaces/cmtk/parcellation.py @@ -8,29 +8,22 @@ import os import os.path as op import shutil -import warnings import numpy as np import nibabel as nb import networkx as nx from ... import logging -from ...utils.misc import package_check -from ..base import (BaseInterface, BaseInterfaceInputSpec, traits, File, +from ..base import (BaseInterface, LibraryBaseInterface, + BaseInterfaceInputSpec, traits, File, TraitedSpec, Directory, isdefined) +from .base import have_cmp iflogger = logging.getLogger('interface') -have_cmp = True -try: - package_check('cmp') -except Exception as e: - have_cmp = False -else: - import cmp - from cmp.util import runCmd - def create_annot_label(subject_id, subjects_dir, fs_dir, parcellation_name): + import cmp + from cmp.util import runCmd iflogger.info("Create the cortical labels necessary for our ROIs") iflogger.info("=================================================") fs_label_dir = op.join(op.join(subjects_dir, subject_id), 'label') @@ -174,6 +167,8 @@ def create_annot_label(subject_id, subjects_dir, fs_dir, parcellation_name): def create_roi(subject_id, subjects_dir, fs_dir, parcellation_name, dilation): """ Creates the ROI_%s.nii.gz files using the given parcellation information from networks. Iteratively create volume. """ + import cmp + from cmp.util import runCmd iflogger.info("Create the ROIs:") output_dir = op.abspath(op.curdir) fs_dir = op.join(subjects_dir, subject_id) @@ -306,6 +301,8 @@ def create_roi(subject_id, subjects_dir, fs_dir, parcellation_name, dilation): def create_wm_mask(subject_id, subjects_dir, fs_dir, parcellation_name): + import cmp + import scipy.ndimage.morphology as nd iflogger.info("Create white matter mask") fs_dir = op.join(subjects_dir, subject_id) cmp_config = cmp.configuration.PipelineConfiguration() @@ -328,11 +325,6 @@ def create_wm_mask(subject_id, subjects_dir, fs_dir, parcellation_name): aseg = nb.load(op.join(fs_dir, 'mri', 'aseg.nii.gz')) asegd = aseg.get_data() - try: - import scipy.ndimage.morphology as nd - except ImportError: - raise Exception('Need scipy for binary erosion of white matter mask') - # need binary erosion function imerode = nd.binary_erosion @@ -438,6 +430,7 @@ def create_wm_mask(subject_id, subjects_dir, fs_dir, parcellation_name): def crop_and_move_datasets(subject_id, subjects_dir, fs_dir, parcellation_name, out_roi_file, dilation): + from cmp.util import runCmd fs_dir = op.join(subjects_dir, subject_id) cmp_config = cmp.configuration.PipelineConfiguration() cmp_config.parcellation_scheme = "Lausanne2008" @@ -549,7 +542,7 @@ class ParcellateOutputSpec(TraitedSpec): ) -class Parcellate(BaseInterface): +class Parcellate(LibraryBaseInterface): """Subdivides segmented ROI file into smaller subregions This interface implements the same procedure as in the ConnectomeMapper's @@ -571,6 +564,8 @@ class Parcellate(BaseInterface): input_spec = ParcellateInputSpec output_spec = ParcellateOutputSpec + _pkg = 'cmp' + imports = ('scipy', ) def _run_interface(self, runtime): if self.inputs.subjects_dir: From 2c1e47b339d4027804291f55631f204f257c3eeb Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 21:20:34 -0400 Subject: [PATCH 06/11] RF: MRTrix2TrackVis is a DipyBaseInterface --- nipype/interfaces/mrtrix/convert.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/nipype/interfaces/mrtrix/convert.py b/nipype/interfaces/mrtrix/convert.py index 36b21ae2d7..98c8d62a39 100644 --- a/nipype/interfaces/mrtrix/convert.py +++ b/nipype/interfaces/mrtrix/convert.py @@ -15,23 +15,15 @@ from ... import logging from ...utils.filemanip import split_filename -from ...utils.misc import package_check from ...workflows.misc.utils import get_data_dims, get_vox_dims -from ..base import TraitedSpec, BaseInterface, File, isdefined - -import warnings -have_dipy = True -try: - package_check('dipy') -except Exception as e: - have_dipy = False -else: - from dipy.tracking.utils import move_streamlines, affine_from_fsl_mat_file +from ..base import TraitedSpec, File, isdefined +from ..dipy.base import DipyBaseInterface, HAVE_DIPY as have_dipy iflogger = logging.getLogger('interface') def transform_to_affine(streams, header, affine): + from dipy.tracking.utils import move_streamlines rotation, scale = np.linalg.qr(affine) streams = move_streamlines(streams, rotation) scale[0:3, 0:3] = np.dot(scale[0:3, 0:3], @@ -168,7 +160,7 @@ class MRTrix2TrackVisOutputSpec(TraitedSpec): out_file = File(exists=True) -class MRTrix2TrackVis(BaseInterface): +class MRTrix2TrackVis(DipyBaseInterface): """ Converts MRtrix (.tck) tract files into TrackVis (.trk) format using functions from dipy @@ -184,6 +176,8 @@ class MRTrix2TrackVis(BaseInterface): output_spec = MRTrix2TrackVisOutputSpec def _run_interface(self, runtime): + from dipy.tracking.utils import move_streamlines, \ + affine_from_fsl_mat_file dx, dy, dz = get_data_dims(self.inputs.image_file) vx, vy, vz = get_vox_dims(self.inputs.image_file) image_file = nb.load(self.inputs.image_file) From 7e83fac0b5eec3f603fa936c1013fe601774f441 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Wed, 11 Apr 2018 21:26:09 -0400 Subject: [PATCH 07/11] RF: algorithms.metric.Similarity is a NipyBaseInterface --- nipype/algorithms/metrics.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/nipype/algorithms/metrics.py b/nipype/algorithms/metrics.py index f95e80edd0..beeced288a 100644 --- a/nipype/algorithms/metrics.py +++ b/nipype/algorithms/metrics.py @@ -19,11 +19,11 @@ from scipy.ndimage.measurements import center_of_mass, label from .. import config, logging -from ..utils.misc import package_check from ..interfaces.base import (BaseInterface, traits, TraitedSpec, File, InputMultiPath, BaseInterfaceInputSpec, isdefined) +from ..interfaces.nipy.base import NipyBaseInterface from ..utils import NUMPY_MMAP iflogger = logging.getLogger('interface') @@ -651,7 +651,7 @@ class SimilarityOutputSpec(TraitedSpec): traits.Float(desc="Similarity between volume 1 and 2, frame by frame")) -class Similarity(BaseInterface): +class Similarity(NipyBaseInterface): """Calculates similarity between two 3D or 4D volumes. Both volumes have to be in the same coordinate system, same space within that coordinate system and with the same voxel dimensions. @@ -674,19 +674,8 @@ class Similarity(BaseInterface): input_spec = SimilarityInputSpec output_spec = SimilarityOutputSpec - _have_nipy = True - - def __init__(self, **inputs): - try: - package_check('nipy') - except Exception: - self._have_nipy = False - super(Similarity, self).__init__(**inputs) def _run_interface(self, runtime): - if not self._have_nipy: - raise RuntimeError('nipy is not installed') - from nipy.algorithms.registration.histogram_registration import HistogramRegistration from nipy.algorithms.registration.affine import Affine From 516ae7a741c5818f25103c1bfed8487f2a9279fc Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 12 Apr 2018 16:39:45 -0400 Subject: [PATCH 08/11] TEST: Update NBS import test --- nipype/interfaces/cmtk/tests/test_nbs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nipype/interfaces/cmtk/tests/test_nbs.py b/nipype/interfaces/cmtk/tests/test_nbs.py index e3e527ec81..122465b74f 100644 --- a/nipype/interfaces/cmtk/tests/test_nbs.py +++ b/nipype/interfaces/cmtk/tests/test_nbs.py @@ -4,6 +4,7 @@ import numpy as np import networkx as nx import pytest +from nibabel.testing import clear_and_catch_warnings have_cv = True try: @@ -41,7 +42,7 @@ def test_importerror(creating_graphs, tmpdir): with pytest.raises(ImportError) as e: nbs.run() - assert "cviewer library is not available" == str(e.value) + assert "No module named 'cviewer'" == str(e.value) @pytest.mark.skipif(not have_cv, reason="cviewer has to be available") From be47ff8fa3164a47ef2083c2034585e82809a6ee Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 12 Apr 2018 20:00:29 -0400 Subject: [PATCH 09/11] TEST: Don't match error message string --- nipype/interfaces/cmtk/tests/test_nbs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nipype/interfaces/cmtk/tests/test_nbs.py b/nipype/interfaces/cmtk/tests/test_nbs.py index 122465b74f..f71eab62fd 100644 --- a/nipype/interfaces/cmtk/tests/test_nbs.py +++ b/nipype/interfaces/cmtk/tests/test_nbs.py @@ -42,7 +42,6 @@ def test_importerror(creating_graphs, tmpdir): with pytest.raises(ImportError) as e: nbs.run() - assert "No module named 'cviewer'" == str(e.value) @pytest.mark.skipif(not have_cv, reason="cviewer has to be available") From c3ee8d405f7cf1f376ba94b9c5f313f538ed23e8 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 12 Apr 2018 20:00:59 -0400 Subject: [PATCH 10/11] TEST: Drop unused import --- nipype/interfaces/cmtk/tests/test_nbs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nipype/interfaces/cmtk/tests/test_nbs.py b/nipype/interfaces/cmtk/tests/test_nbs.py index f71eab62fd..be3008fb09 100644 --- a/nipype/interfaces/cmtk/tests/test_nbs.py +++ b/nipype/interfaces/cmtk/tests/test_nbs.py @@ -4,7 +4,6 @@ import numpy as np import networkx as nx import pytest -from nibabel.testing import clear_and_catch_warnings have_cv = True try: From 3d5661c47bd498e0b3728b4a695dea0f26b970d7 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 13 Apr 2018 20:38:33 -0400 Subject: [PATCH 11/11] TEST: make specs --- .../tests/test_auto_LibraryBaseInterface.py | 17 +++++++++++++++++ .../cmtk/tests/test_auto_CFFBaseInterface.py | 17 +++++++++++++++++ .../nipy/tests/test_auto_NipyBaseInterface.py | 17 +++++++++++++++++ .../tests/test_auto_NitimeBaseInterface.py | 17 +++++++++++++++++ .../tests/test_auto_NilearnBaseInterface.py | 17 +++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 nipype/interfaces/base/tests/test_auto_LibraryBaseInterface.py create mode 100644 nipype/interfaces/cmtk/tests/test_auto_CFFBaseInterface.py create mode 100644 nipype/interfaces/nipy/tests/test_auto_NipyBaseInterface.py create mode 100644 nipype/interfaces/nitime/tests/test_auto_NitimeBaseInterface.py create mode 100644 nipype/interfaces/tests/test_auto_NilearnBaseInterface.py diff --git a/nipype/interfaces/base/tests/test_auto_LibraryBaseInterface.py b/nipype/interfaces/base/tests/test_auto_LibraryBaseInterface.py new file mode 100644 index 0000000000..c624c7d9d0 --- /dev/null +++ b/nipype/interfaces/base/tests/test_auto_LibraryBaseInterface.py @@ -0,0 +1,17 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..core import LibraryBaseInterface + + +def test_LibraryBaseInterface_inputs(): + input_map = dict( + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), ) + inputs = LibraryBaseInterface.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/cmtk/tests/test_auto_CFFBaseInterface.py b/nipype/interfaces/cmtk/tests/test_auto_CFFBaseInterface.py new file mode 100644 index 0000000000..7e07630c0b --- /dev/null +++ b/nipype/interfaces/cmtk/tests/test_auto_CFFBaseInterface.py @@ -0,0 +1,17 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..base import CFFBaseInterface + + +def test_CFFBaseInterface_inputs(): + input_map = dict( + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), ) + inputs = CFFBaseInterface.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/nipy/tests/test_auto_NipyBaseInterface.py b/nipype/interfaces/nipy/tests/test_auto_NipyBaseInterface.py new file mode 100644 index 0000000000..95b06f882b --- /dev/null +++ b/nipype/interfaces/nipy/tests/test_auto_NipyBaseInterface.py @@ -0,0 +1,17 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..base import NipyBaseInterface + + +def test_NipyBaseInterface_inputs(): + input_map = dict( + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), ) + inputs = NipyBaseInterface.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/nitime/tests/test_auto_NitimeBaseInterface.py b/nipype/interfaces/nitime/tests/test_auto_NitimeBaseInterface.py new file mode 100644 index 0000000000..bcade22ef5 --- /dev/null +++ b/nipype/interfaces/nitime/tests/test_auto_NitimeBaseInterface.py @@ -0,0 +1,17 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..base import NitimeBaseInterface + + +def test_NitimeBaseInterface_inputs(): + input_map = dict( + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), ) + inputs = NitimeBaseInterface.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value diff --git a/nipype/interfaces/tests/test_auto_NilearnBaseInterface.py b/nipype/interfaces/tests/test_auto_NilearnBaseInterface.py new file mode 100644 index 0000000000..76021c3b30 --- /dev/null +++ b/nipype/interfaces/tests/test_auto_NilearnBaseInterface.py @@ -0,0 +1,17 @@ +# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT +from __future__ import unicode_literals +from ..nilearn import NilearnBaseInterface + + +def test_NilearnBaseInterface_inputs(): + input_map = dict( + ignore_exception=dict( + deprecated='1.0.0', + nohash=True, + usedefault=True, + ), ) + inputs = NilearnBaseInterface.input_spec() + + for key, metadata in list(input_map.items()): + for metakey, value in list(metadata.items()): + assert getattr(inputs.traits()[key], metakey) == value