Source code for capsul.subprocess.fsl

# -*- coding: utf-8 -*-
'''
Specific subprocess-like functions to call FSL taking into account a 
potential configuration done in StudyConfig. If a StudyConfig is not
configured to use FSL, it may be automatically configured. Automatic
configuration had been tested in the two following cases:

- FSL was installed from the FMRIB site and, at least, FSLDIR 
  environment variable is set (fsl.sh can be sourced or not)
- FSL was installed from Neurodebian packages

For calling FSL command with this module, the first argument of
command line must be the FSL executable without any path nor prefix. 
Prefix areused  in Neurodebian install. For instance on Ubuntu 16.04 
Neurodebian FSL commands are prefixed with "fsl5.0-".
The appropriate path and eventually prefix are added from the configuration
of the StudyConfig instance.

Classes
=======
:class:`Popen`
--------------

Functions
=========
:func:`fsl_command_with_environment`
------------------------------------
:func:`check_fsl_configuration`
-------------------------------
:func:`check_configuration_values`
----------------------------------
:func:`auto_configuration`
--------------------------
:func:`call`
------------
:func:`check_call`
------------------
:func:`check_output`
--------------------

'''

from __future__ import absolute_import

import os
import os.path as osp
import soma.subprocess

from traits.api import Undefined

from soma.path import find_in_path
from capsul.engine.module import fsl as fsl_engine


[docs] def fsl_command_with_environment(study_config, command): ''' Given an FSL command where first element is a command name without any path or prefix (e.g. "bet"). Returns the appropriate command to call taking into account the study_config FSL configuration. ''' fsl_dir = os.environ.get('FSLDIR') if fsl_dir: dir_prefix = '%s/bin/' % fsl_dir else: dir_prefix = '' fsl_prefix = getattr(study_config, 'fsl_prefix', '') if fsl_prefix is Undefined: fsl_prefix = '' if getattr(study_config, 'fsl_config', Undefined) is Undefined: cmd = ['%s%s%s' % (dir_prefix, fsl_prefix, command[0])] + command[1:] else: fsldir = osp.dirname(osp.dirname(osp.dirname(study_config.fsl_config))) shell = os.environ.get('SHELL', '/bin/sh') if shell.endswith('csh'): cmd = [shell, '-c', 'setenv FSLDIR "{0}";source {0}/etc/fslconf/fsl.csh;exec {0}/bin/{1}{2} '.format(fsldir, fsl_prefix, command[0]) + \ ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] else: cmd = [shell, '-c', 'export FSLDIR="{0}";. {0}/etc/fslconf/fsl.sh;exec {0}/bin/{1}{2} '.format(fsldir, fsl_prefix, command[0]) + \ ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] return cmd
[docs] def check_fsl_configuration(study_config): ''' Check thas study_config configuration is valid to call FSL commands. If not, try to automatically configure FSL. Finally raises an EnvironmentError if configuration is still wrong. ''' if getattr(study_config, '_fsl_config_checked', False): # Check FLS configuration only once return if 'FSLConfig' not in study_config.modules: raise EnvironmentError('FSLConfig module is missing in StudyConfig.') if study_config.use_fsl is False: raise EnvironmentError('Configuration is set not to use FLS. Set use_fsl to True in order to use FSL.') # Configuration must be valid otherwise # try to update configuration and recheck is validity if check_configuration_values(study_config) is not None: auto_configuration(study_config) error_message = check_configuration_values(study_config) if error_message: raise EnvironmentError(error_message) study_config.use_fsl = True study_config._fsl_config_checked = True
[docs] def check_configuration_values(study_config): ''' Check if the configuration is valid to run FLS and returns an error message if there is an error or None if everything is good. ''' fsl_prefix = getattr(study_config, 'fsl_prefix', '') if fsl_prefix is Undefined: fsl_prefix = '' if study_config.fsl_config is Undefined: if not find_in_path('%sbet' % fsl_prefix): return 'FSL command "%sbet" cannot be found in PATH' % fsl_prefix else: if fsl_prefix: return 'FSL configuration must either use fsl_config or fsl_prefix but not both' if not osp.exists(study_config.fsl_config): return 'File "%s" does not exist' % study_config.fsl_config if not study_config.fsl_config.endswith('fsl.sh'): return 'File "%s" is not a path to fsl.sh script' % study_config.fsl_config return None
[docs] def auto_configuration(study_config): ''' Try to automatically set the study_config configuration for FSL. ''' fsl_dir = os.environ.get('FSLDIR') fsl_prefix = getattr(study_config, 'fsl_prefix', '') if fsl_prefix is Undefined: fsl_prefix = '' if fsl_dir and not fsl_prefix: # Try to set fsl_config from FSLDIR environment variable fsl_config = '%s/etc/fslconf/fsl.sh' % fsl_dir if osp.exists(fsl_config): study_config.fsl_config = fsl_config elif not fsl_prefix: # Try to set fsl_prefix by searching fsl-*bet in PATH bet = find_in_path('fsl*-bet') if bet: study_config.fsl_prefix = osp.basename(bet)[:-3]
[docs] class Popen(soma.subprocess.Popen): ''' Equivalent to Python subprocess.Popen for FSL commands ''' def __init__(self, study_config, command, **kwargs): check_fsl_configuration(study_config) cmd = fsl_command_with_environment(study_config, command) super(Popen, self).__init__(cmd, **kwargs)
[docs] def call(study_config, command, **kwargs): ''' Equivalent to Python subprocess.call for FSL commands ''' check_fsl_configuration(study_config) cmd = fsl_command_with_environment(study_config, command) return soma.subprocess.call(cmd, **kwargs)
[docs] def check_call(study_config, command, **kwargs): ''' Equivalent to Python subprocess.check_call for FSL commands ''' check_fsl_configuration(study_config) cmd = fsl_command_with_environment(study_config, command) return soma.subprocess.check_call(cmd, **kwargs)
[docs] def check_output(study_config, command, **kwargs): ''' Equivalent to Python subprocess.check_output for FSL commands ''' check_fsl_configuration(study_config) cmd = fsl_command_with_environment(study_config, command) return soma.subprocess.check_output(cmd, **kwargs)