Source code for capsul.in_context.fsl

# -*- coding: utf-8 -*-
'''
Specific subprocess-like functions to call FSL taking into account 
configuration stored in ExecutionContext. To functions and class in
this module it is mandatory to activate an ExecutionContext (using a
with statement). For instance::

   from capsul.engine import capsul_engine
   from capsul.in_context.fsl import fsl_check_call

   ce = capsul_engine()
   with ce:
       fsl_check_call(['bet', '/somewhere/myimage.nii'])

For calling FSL command with this module, the first argument of
command line must be the FSL executable without any path nor prefix. 
Prefix are used 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 ExecutionContext.
'''

from __future__ import absolute_import

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

from traits.api import Undefined
from soma.path import find_in_path
from soma.utils.env import parse_env_lines


'''
If this variable is set, it contains FS runtime env variables, allowing to run directly freesurfer commands from this process.
'''
fsl_runtime_env = None


[docs] def fsl_command_with_environment(command, use_prefix=True, use_runtime_env=True): ''' 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 FSL configuration stored in the activated ExecutionContext. Usinfg :func`fsl_env` is an alternative to this. ''' if use_prefix: fsl_prefix = os.environ.get('FSL_PREFIX', '') else: fsl_prefix = '' if use_runtime_env and fsl_runtime_env: c0 = list(osp.split(command[0])) c0[-1] = '%s%s' % (fsl_prefix, c0[-1]) c0 = osp.join(*c0) cmd = [c0] + command[1:] return cmd fsl_dir = os.environ.get('FSLDIR') if fsl_dir: dir_prefix = '%s/bin/' % fsl_dir else: dir_prefix = '' fsl_config = os.environ.get('FSL_CONFIG') if fsl_prefix and not os.path.isdir(dir_prefix): dir_prefix = '' if fsl_config: fsldir = osp.dirname(osp.dirname(osp.dirname(fsl_config))) shell = os.environ.get('SHELL', '/bin/sh') if shell.endswith('csh'): cmd = [shell, '-c', 'setenv FSLDIR "{0}"; setenv PATH "{0}/bin:$PATH"; source {0}/etc/fslconf/fsl.csh;exec {1}{2} '.format( fsldir, fsl_prefix, command[0]) + \ ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] else: cmd = [shell, '-c', 'export FSLDIR="{0}"; export PATH="{0}/bin:$PATH"; . {0}/etc/fslconf/fsl.sh;exec {1}{2} '.format( fsldir, fsl_prefix, command[0]) + \ ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] else: cmd = ['%s%s%s' % (dir_prefix, fsl_prefix, command[0])] + command[1:] return cmd
[docs] def fsl_env(): ''' get FSL env variables by running the setup script in a separate bash process ''' global fsl_runtime_env if fsl_runtime_env is not None: return fsl_runtime_env fsl_config = os.environ.get('FSL_CONFIG') fsl_dir = os.environ.get('FSLDIR') kwargs = {} if not fsl_config: cmd = ['env'] if fsl_dir: kwargs = {'env': {'PATH': os.pathsep.join( ['%s/bin' % fsl_dir, os.environ.get('PATH', '')])}} else: cmd = fsl_command_with_environment(['env'], use_prefix=False, use_runtime_env=False) new_env = soma.subprocess.check_output(cmd, **kwargs).decode( 'utf-8').strip() new_env = parse_env_lines(new_env) env = {} for l in new_env: name, val = l.strip().split('=', 1) name = six.ensure_str(name) val = six.ensure_str(val) if name not in ('_', 'SHLVL') and (name not in os.environ or os.environ[name] != val): env[name] = val # add PATH if fsl_dir: fsl_bin = osp.join(fsl_dir, 'bin') env['PATH'] = os.pathsep.join([fsl_bin, os.environ.get('PATH', '')]) # cache dict fsl_runtime_env = env return env
[docs] class FslPopen(soma.subprocess.Popen): ''' Equivalent to Python subprocess.Popen for FSL commands ''' def __init__(self, command, **kwargs): cmd = fsl_command_with_environment(command) env = fsl_env() if 'env' in kwargs: env = dict(env) env.update(kwargs['env']) kwargs = dict(kwargs) del kwargs['env'] super(FslPopen, self).__init__(cmd, env=env, **kwargs)
[docs] def fsl_call(command, **kwargs): ''' Equivalent to Python subprocess.call for FSL commands ''' cmd = fsl_command_with_environment(command) env = fsl_env() if 'env' in kwargs: env = dict(env) env.update(kwargs['env']) kwargs = dict(kwargs) del kwargs['env'] return soma.subprocess.call(cmd, env=env, **kwargs)
[docs] def fsl_check_call(command, **kwargs): ''' Equivalent to Python subprocess.check_call for FSL commands ''' cmd = fsl_command_with_environment(command) env = fsl_env() if 'env' in kwargs: env = dict(env) env.update(kwargs['env']) kwargs = dict(kwargs) del kwargs['env'] return soma.subprocess.check_call(cmd, env=env, **kwargs)
[docs] def fsl_check_output(command, **kwargs): ''' Equivalent to Python subprocess.check_output for FSL commands ''' cmd = fsl_command_with_environment(command) env = fsl_env() if 'env' in kwargs: env = dict(env) env.update(kwargs['env']) kwargs = dict(kwargs) del kwargs['env'] return soma.subprocess.check_output(cmd, env=env, **kwargs)