Source code for capsul.engine.module.spm
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from capsul import engine
import os
import six
#import glob
#import os.path as osp
#import weakref
##import subprocess # Only in case of matlab call (auto_configuration func)
#from soma.controller import Controller
#from traits.api import Directory, Undefined, Instance, String, Bool
#from . import matlab
def init_settings(capsul_engine):
with capsul_engine.settings as settings:
settings.ensure_module_fields('spm',
[dict(name='directory',
type='string',
description='Directory where SPM is installed'),
dict(name='version',
type='string',
description='Version of SPM release (8 or 12)'),
dict(name='standalone',
type='boolean',
description='If this parameter is set to True, use the '
'standalone SPM version, otherwise use Matlab.')
])
def config_dependencies(config):
return {'matlab': 'any'}
#def set_environ(config, environ):
#spm_config = config.get('spm', {})
#use = spm_config.get('use')
#if use is True or (use is None and 'directory' in spm_config):
#error_message = check_environ(environ)
#if error_message:
#complete_environ(config, environ)
#error_message = check_environ(environ)
#if error_message:
#raise EnvironmentError(error_message)
#def check_environ(environ):
#'''
#Check if the configuration is valid to run SPM and returns an error
#message if there is an error or None if everything is good.
#'''
#if not environ.get('SPM_DIRECTORY'):
#return 'SPM directory is not defined'
#if not environ.get('SPM_VERSION'):
#return 'SPM version is not defined (maybe %s is not a valid SPM directory)' % environ['SPM_DIRECTORY']
#if not environ.get('SPM_STANDALONE'):
#return 'No selection of SPM installation type : Standalone or Matlab'
#if not osp.isdir(environ['SPM_DIRECTORY']):
#return 'No valid SPM directory: %s' % environ['SPM_DIRECTORY']
#if environ['SPM_STANDALONE'] != 'yes':
#matlab_error = matlab.check_environ(environ)
#if matlab_error:
#return 'Matlab configuration must be valid for SPM: ' + matlab_error
#return None
#def complete_environ(config, environ):
#'''
#Try to automatically complete environment for SPM
#'''
#spm_directory = config.get('spm', {}).get('directory')
#if spm_directory:
#environ['SPM_DIRECTORY'] = spm_directory
#mcr = glob.glob(osp.join(spm_directory, 'spm*_mcr'))
#if mcr:
#fileName = osp.basename(mcr[0])
#inc = 1
#while fileName[fileName.find('spm') + 3:
#fileName.find('spm') + 3 + inc].isdigit():
#environ['SPM_VERSION'] = fileName[fileName.find('spm') + 3:
#fileName.find('spm') + 3
#+ inc]
#inc+=1
#environ['SPM_STANDALONE'] = 'yes'
#else:
#environ['SPM_STANDALONE'] = 'no'
## determine SPM version (currently 8 or 12)
#if osp.isdir(osp.join(spm_directory, 'toolbox', 'OldNorm')):
#environ['SPM_VERSION'] = '12'
#elif osp.isdir(osp.join(spm_directory, 'templates')):
#environ['SPM_VERSION'] = '8'
#else:
#environ.pop('SPM_VERSION', None)
# For SPM with MATLAB license, if we want to get the SPM version from a system
# call to matlab:.
# matlab_cmd = ('addpath("' + capsul_engine.spm.directory + '");'
# ' [name, ~]=spm("Ver");'
# ' fprintf(2, \"%s\", name(4:end));'
# ' exit')
#
# try:
# p = subprocess.Popen([capsul_engine.matlab.executable,
# '-nodisplay', '-nodesktop',
# '-nosplash', '-singleCompThread',
# '-batch', matlab_cmd],
# stdin=subprocess.PIPE,
# stdout=subprocess.PIPE,
# stderr=subprocess.PIPE)
# output, err = p.communicate()
# rc = p.returncode
#
# except FileNotFoundError as e:
# print('\n {0}'.format(e))
# rc = 111
#
# except Exception as e:
# print('\n {0}'.format(e))
# rc = 111
#
# if (rc != 111) and (rc != 0):
# print(err)
#
# if rc == 0:
# capsul_engine.spm.version = err.decode("utf-8")
#
[docs]
def activate_configurations():
'''
Activate the SPM module (set env variables) from the global configurations,
in order to use them via :mod:`capsul.in_context.spm` functions
'''
conf = engine.configurations.get('capsul.engine.module.spm', {})
mlab_conf = engine.configurations.get('capsul.engine.module.matlab', {})
spm_dir = conf.get('directory')
mcr_dir = mlab_conf.get('mcr_directory')
if spm_dir:
os.environ['SPM_DIRECTORY'] = six.ensure_str(spm_dir)
elif 'SPM_DIRECTORY' in os.environ:
del os.environ['SPM_DIRECTORY']
spm_version = conf.get('version')
if spm_version:
os.environ['SPM_VERSION'] = six.ensure_str(spm_version)
elif 'SPM_VERSION' in os.environ:
del os.environ['SPM_VERSION']
spm_standalone = conf.get('standalone')
if spm_standalone is not None:
os.environ['SPM_STANDALONE'] = 'yes' if spm_standalone else 'no'
if spm_standalone and mcr_dir:
os.environ['MCR_HOME'] = mcr_dir
elif 'SPM_STANDALONE' in os.environ:
del os.environ['SPM_STANDALONE']
[docs]
def check_notably_invalid_config(conf):
'''
Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled
Returns
-------
invalid: list
list of invalid config keys
'''
invalid = []
#for k in ('directory', 'version'):
# if getattr(conf, k, None) is None:
# invalid.append(k)
if getattr(conf, 'directory', None) is None:
invalid.append('directory')
return invalid
[docs]
def edition_widget(engine, environment, config_id='any'):
''' Edition GUI for SPM config - see
:class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor`
'''
from soma.qt_gui.controller_widget import ScrollControllerWidget
from soma.controller import Controller
import types
import traits.api as traits
def validate_config(widget):
widget.update_controller()
controller = widget.controller_widget.controller
with widget.engine.settings as session:
values = {}
if controller.directory in (None, traits.Undefined, ''):
values['directory'] = None
else:
values['directory'] = controller.directory
values['standalone'] = controller.standalone
if controller.version in (None, traits.Undefined, ''):
values['version'] = None
else:
values['version'] = controller.version
id = 'spm%s%s' % (controller.version if
controller.version != traits.Undefined else '',
'-standalone' if controller.standalone else '')
values['config_id'] = id
query = 'config_id == "%s"' % id
conf = session.config('spm', widget.environment, selection=query)
if conf is None:
session.new_config('spm', widget.environment, values)
else:
for k in ('directory', 'standalone', 'version'):
if (k == 'directory' and
values[k] and
not os.path.isdir(values[k])):
raise NotADirectoryError('\nSPM directory was not '
'updated:\n{} is not '
'existing!'.format(values[k]))
else:
setattr(conf, k, values[k])
if id != widget.config_id:
try:
session.remove_config('spm', widget.environment,
widget.config_id)
except Exception:
pass
widget.config_id = id
controller = Controller()
controller.add_trait("directory", traits.Directory(
traits.Undefined,
output=False,
desc="Directory containing SPM."))
controller.add_trait("standalone", traits.Bool(
False,
desc="If True, use the standalone version of SPM."))
controller.add_trait('version', traits.Str(
traits.Undefined, output=False,
desc='Version string for SPM: "12", "8", etc.'))
conf = None
if config_id == 'any':
conf = engine.settings.select_configurations(
environment, {'spm': 'any'})
else:
try:
conf = engine.settings.select_configurations(
environment, {'spm': 'config_id=="%s"' % config_id})
except Exception:
pass
if conf:
controller.directory = conf.get(
'capsul.engine.module.spm', {}).get('directory',
traits.Undefined)
controller.standalone = conf.get(
'capsul.engine.module.spm', {}).get('standalone', False)
controller.version = conf.get(
'capsul.engine.module.spm', {}).get('version', traits.Undefined)
config_id = conf.get(
'capsul.engine.module.spm', {}).get('config_id', config_id)
# TODO handle several configs
widget = ScrollControllerWidget(controller, live=True)
widget.engine = engine
widget.environment = environment
widget.config_id = config_id
widget.accept = types.MethodType(validate_config, widget)
return widget