Example #1
0
 def configure_controller(cls):
     c = Controller()
     c.add_trait('parameters', traits.List(traits.Str()))
     c.add_trait('concat_plug', traits.Str())
     c.add_trait('outputs', traits.List(traits.Str()))
     c.add_trait('param_types', traits.List(traits.Str('Str')))
     return c
Example #2
0
 def configure_controller(cls):
     c = Controller()
     c.add_trait('param_type', traits.Str('Str'))
     c.add_trait('is_output', traits.Bool(True))
     c.add_trait('test_is_output', traits.Bool(True))
     c.add_trait('has_index', traits.Bool(True))
     return c
Example #3
0
def get_node_instance(node_type, pipeline, conf_dict=None, **kwargs):
    """
    Get a custom node instance from a module + class name (see
    :func:`get_node_class`) and a configuration dict or Controller.
    The configuration contains parameters needed to instantiate the node type.
    Each node class may specify its parameters via its class method
    `configure_node`.

    Parameters
    ----------
    node_type: str or Node subclass or Node instance
        node type to be built. Either a class (Node subclass) or a Node
        instance (the node will be re-instantiated), or a string
        describing a module and class.
    pipeline: Pipeline
        pipeline in which the node will be inserted.
    conf_dict: dict or Controller
        configuration dict or Controller defining parameters needed to build
        the node. The controller should be obtained using the node class's
        `configure_node()` static method, then filled with the desired values.
        If not given the node is supposed to be built with no parameters, which
        will not work for every node type.
    kwargs:
        default values of the node instance parameters.
    """
    cls_and_name = get_node_class(node_type)
    if cls_and_name is None:
        raise ValueError("Could not find node class %s" % node_type)
    name, cls = cls_and_name

    if isinstance(conf_dict, Controller):
        conf_controller = conf_dict
    elif conf_dict is not None:
        if hasattr(cls, 'configure_controller'):
            conf_controller = cls.configure_controller()
            if conf_controller is None:
                raise ValueError("node type %s has a configuration controller "
                                 "problem (see %s.configure_controller()"
                                 % (node_type, node_type))
            conf_controller.import_from_dict(conf_dict)
        else:
            conf_controller = Controller()
    else:
        if hasattr(cls, 'configure_controller'):
            conf_controller = cls.configure_controller()
        else:
            conf_controller = Controller()
    if hasattr(cls, 'build_node'):
        node = cls.build_node(pipeline, name, conf_controller)
    else:
        # probably bound to fail...
        node = cls(pipeline, name, [], [])

    # Set the instance default parameters
    for name, value in six.iteritems(kwargs):
        setattr(node, name, value)

    return node
Example #4
0
 def configure_controller(cls):
     c = Controller()
     c.add_trait('input_types', traits.List(traits.Str))
     c.add_trait('input_names', traits.List(traits.Str))
     c.add_trait('output_names', traits.List(traits.Str))
     c.input_names = ['inputs']
     c.output_names = ['output_%d']
     c.input_types = ['File']
     return c
Example #5
0
    def __init__(self,
                 study_name=None,
                 init_config=None,
                 modules=None,
                 **override_config):
        """ Initilize the StudyConfig class

        Parameters
        ----------
        study_name: Name of the study to configure. This name is used to
            identify specific configuration for a study.
        init_config: if not None, must contain a dictionary that will be used
            to configure this StudyConfig (instead of reading configuration
            from configuration files).
        modules: list of string (default self.default_modules).
            the names of configuration module classes that will be included
            in this study configuration.
        override_config: dictionary
            The content of these keyword parameters will be set on the
            configuration after it has been initialized from configuration
            files (or from init_config).
        """

        # Inheritance
        super(StudyConfig, self).__init__()

        if study_name:
            self.study_name = study_name

        # Read the configuration for the given study
        if init_config is None:
            config = self.read_configuration()
            config.update(override_config)
        else:
            self.global_config_file = None
            self.study_config_file = None
            if override_config:
                config = init_config.copy()
                config.update(override_config)
            else:
                config = init_config

        # Create modules
        if modules is None:
            # Make it possible for a study to define its own set of modules
            modules = config.pop('config_modules', self.default_modules)

        # 'modules_data' is a container for modules-specific internal data
        # each module is encouraged to prefix its variables there by its
        # module name
        self.modules_data = Controller()

        self.modules = {}
        for module in modules:
            self.load_module(module, config)

        # Set self attributes according to configuration values
        for k, v in six.iteritems(config):
            setattr(self, k, v)
        self.initialize_modules()
    def get_attribute_values(self):
        ''' Get attributes Controller associated to a process

        Returns
        -------
        attributes: Controller
        '''
        t = self.trait('capsul_attributes')
        if t is None:
            try:
                pattributes = ProcessCompletionEngine.get_completion_engine(
                    self.process.process).get_attribute_values()
            except AttributeError:
                # ProcessCompletionEngine not implemented for this process:
                # no completion
                return

            schemas = self._get_schemas()
            attributes = ProcessAttributes(self.process, schemas)

            self.add_trait('capsul_attributes', ControllerTrait(Controller()))
            self.capsul_attributes = attributes
            iter_attrib = self.get_iterated_attributes()
            for attrib, trait in six.iteritems(pattributes.user_traits()):
                if attrib not in iter_attrib:
                    attributes.add_trait(attrib, trait)
            for attrib in iter_attrib:
                trait = pattributes.trait(attrib)
                if trait is not None:
                    attributes.add_trait(
                        attrib, traits.List(trait, output=trait.output))
                value = getattr(pattributes, attrib, None)
                if value is not None and value is not traits.Undefined:
                    setattr(attributes, attrib, [value])
        return self.capsul_attributes
Example #7
0
 def test_controller(self):
     c1 = Controller()
     c1.add_trait('gogo', traits.Str())
     c1.add_trait('bozo', traits.Int(12))
     self.assertEqual(c1.gogo, '')
     self.assertEqual(c1.bozo, 12)
     self.assertEqual(c1.user_traits().keys(), ['gogo', 'bozo'])
     c1.gogo = 'blop krok'
     self.assertEqual(c1.gogo, 'blop krok')
Example #8
0
def edition_widget(engine, environment):
    ''' Edition GUI for AFNI 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):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('afni', widget.environment)
            values = {'config_id': 'afni'}
            for k in ['directory']:
                value = getattr(controller, k)
                if value is traits.Undefined:
                    value = None
                values[k] = value
            if conf is None:
                session.new_config('afni', widget.environment, values)
            else:
                for k, value in values.items():
                    if k == 'config_id':
                        continue
                    setattr(conf, k, values[k])

    controller = Controller()

    controller.add_trait(
        'directory',
        traits.Directory(traits.Undefined,
                         desc='Directory where AFNI is installed'))

    conf = engine.settings.select_configurations(environment, {'afni': 'any'})
    if conf:
        fconf = conf.get('capsul.engine.module.afni', {})
        controller.directory = fconf.get('directory', traits.Undefined)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #9
0
    def connect_resource(self, resource_id=None, force_reconnect=False):
        ''' Connect a soma-workflow computing resource.

        Sets the current resource to the given resource_id (transformed by
        get_resource_id() if None or "localhost" is given, for instance).

        Parameters
        ----------
        resource_id: str (optional)
            resource name, may be None or "localhost". If None, the current
            one (study_config.somaworkflow_computing_resource) is used, or
            the localhost if none is configured.
        force_reconnect: bool (optional)
            if True, if an existing workflow controller is already connected,
            it will be disconnected (deleted) and a new one will be connected.
            If False, an existing controller will be reused without
            reconnection.

        Returns
        -------
        :somaworkflow:`WorkflowController <client_API.html>` object
        '''
        import soma_workflow.client as swclient

        resource_id = self.get_resource_id(resource_id, True)

        if force_reconnect:
            self.disconnect_resource(resource_id)

        r = self.study_config.modules_data.somaworkflow.setdefault(
            resource_id, Controller())

        if not force_reconnect:
            wc = self.get_workflow_controller(resource_id)
            if wc is not None:
                return wc

        conf_file = self.study_config.somaworkflow_config_file
        if conf_file in (None, Undefined):
            conf_file \
                = swclient.configuration.Configuration.search_config_path()
        login = swclient.configuration.Configuration.get_logins(conf_file).get(
            resource_id)
        config = getattr(r, 'config', None)
        if config is None:
            config = swclient.configuration.Configuration.load_from_file(
                config_file_path=conf_file)
            r.config = config
        password = getattr(r, 'password', None)
        rsa_key_pass = getattr(r, 'rsa_key_password', None)
        wc = swclient.WorkflowController(resource_id=resource_id,
                                         login=login,
                                         password=password,
                                         rsa_key_pass=rsa_key_pass,
                                         config=config)
        r.workflow_controller = wc
        return wc
Example #10
0
    def get_workflow_controller(self, resource_id=None):
        ''' Get a connected
        :somaworkflow:`WorkflowController <client_API.html>` for the given
        resource
        '''
        resource_id = self.get_resource_id(resource_id)

        r = self.study_config.modules_data.somaworkflow.setdefault(
            resource_id, Controller())
        wc = getattr(r, 'workflow_controller', None)
        return wc
Example #11
0
def edition_widget(engine, environment):
    ''' Edition GUI for matlab 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):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('matlab', widget.environment)
            values = {'config_id': 'matlab'}
            if controller.executable in (None, traits.Undefined, ''):
                values['executable'] = None
            else:
                values['executable'] = controller.executable
            if conf is None:
                session.new_config('matlab', widget.environment, values)
            else:
                for k in ('executable', ):
                    setattr(conf, k, values[k])

    controller = Controller()
    controller.add_trait('executable',
                         traits.Str(desc='Full path of the matlab executable'))

    conf = engine.settings.select_configurations(environment,
                                                 {'matlab': 'any'})
    if conf:
        controller.executable = conf.get('capsul.engine.module.matlab',
                                         {}).get('executable',
                                                 traits.Undefined)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #12
0
def edition_widget(engine, environment):
    ''' Edition GUI for axon 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):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('axon', widget.environment)
            values = {'config_id': 'axon', 'user_level': controller.user_level}
            if controller.shared_directory in (None, traits.Undefined, ''):
                values['shared_directory'] = None
            else:
                values['shared_directory'] = controller.shared_directory
            if conf is None:
                session.new_config('axon', widget.environment, values)
            else:
                for k in ('shared_directory', 'user_level'):
                    setattr(conf, k, values[k])

    controller = Controller()
    controller.add_trait(
        'shared_directory',
        traits.Directory(desc='Directory where BrainVisa '
                         'shared data is installed'))
    controller.add_trait(
        'user_level',
        traits.Int(desc='0: basic, 1: advanced, 2: expert, or more. '
                   'used to display or hide some advanced features or '
                   'process parameters that would be confusing to a novice '
                   'user'))

    conf = engine.settings.select_configurations(environment, {'axon': 'any'})
    if conf:
        controller.shared_directory = conf.get('capsul.engine.module.axon',
                                               {}).get('shared_directory',
                                                       traits.Undefined)
        controller.user_level = conf.get('capsul.engine.module.axon',
                                         {}).get('user_level', 0)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #13
0
def disable_runtime_steps_with_existing_outputs(pipeline):
    '''
    Disable steps in a pipeline which outputs contain existing files. This
    disabling is the "runtime steps disabling" one (see
    :py:class:`capsul.pipeline.Pipeline`), not the node disabling with
    activation propagation, so it doesn't affect the actual pipeline state.
    The aim is to prevent overwriting files which have already been processed,
    and to allow downstream execution of the remaining steps of the pipeline.

    Parameters
    ----------
    pipeline: Pipeline (mandatory)
        pipeline to disbale nodes in.
    '''
    steps = getattr(pipeline, 'pipeline_steps', Controller())
    for step, trait in six.iteritems(steps.user_traits()):
        if not getattr(steps, step):
            continue  # already inactive
        for node_name in trait.nodes:
            node = pipeline.nodes[node_name]
            if not node.enabled or not node.activated:
                continue  # node not active anyway
            process = node.process
            for param in node.plugs:
                trait = process.trait(param)
                if trait.output and (isinstance(trait.trait_type, traits.File)
                        or isinstance(trait.trait_type, traits.Directory)):
                    value = getattr(process, param)
                    if value is not None and value is not traits.Undefined \
                            and os.path.exists(value):
                        # check special case when the output is also an input
                        # (of the same node)
                        disable = True
                        for n, t in six.iteritems(process.user_traits()):
                            if not t.output and (isinstance(t.trait_type,
                                                            traits.File)
                                    or isinstance(t.trait_type,
                                                  traits.Directory)):
                                v = getattr(process, n)
                                if v == value:
                                    disable = False
                                    break # found in inputs
                        if disable:
                            # disable step
                            print('disable step', step, 'because of:',
                                  node_name, '.', param)
                            setattr(steps, step, False)
                            # no need to iterate other nodes in same step
                            break
Example #14
0
    def get_attribute_values(self):
        ''' Get attributes Controller associated to a process

        Returns
        -------
        attributes: Controller
        '''
        if self.trait('capsul_attributes') is not None \
                and hasattr(self, 'capsul_attributes'):
            return self.capsul_attributes

        self.add_trait('capsul_attributes', ControllerTrait(Controller()))
        schemas = self._get_schemas()
        #schemas = self.process.get_study_config().modules_data.foms.keys()
        self.capsul_attributes = ProcessAttributes(self.process, schemas)

        self.create_attributes_with_fom()

        return self.capsul_attributes
Example #15
0
    def set_computing_resource_password(self, resource_id, password=None,
                                        rsa_key_password=None):
        ''' Set credentials for a given computinf resource.

        Such credentials are stored in the config object, but will not be
        written when the config is saved in a file. They are thus non-
        persistant.

        Parameters
        ----------
        resource_id: str (optional)
        password: str (optional)
        rsa_key_password: str (optional)
        '''
        resource_id = self.get_resource_id(resource_id)
        r = self.study_config.modules_data.somaworkflow.setdefault(
            resource_id, Controller())
        if password:
            r.password = password
        if rsa_key_password:
            r.rsa_key_password = rsa_key_password
Example #16
0
    def get_attribute_values(self):
        ''' Get attributes Controller associated to a process

        Returns
        -------
        attributes: ProcessAttributes instance

        The default implementation does nothing for a
        single Process instance, and merges attributes from its children if
        the process is a pipeline.

        '''
        if not self._rebuild_attributes \
                and self.trait('capsul_attributes') is not None \
                and hasattr(self, 'capsul_attributes'):
            return self.capsul_attributes

        schemas = self._get_schemas()

        study_config = self.process.get_study_config()
        proc_attr_cls = ProcessAttributes

        if 'AttributesConfig' in study_config.modules:
            factory = study_config.modules_data.attributes_factory
            names = [self.process.name]
            if hasattr(self.process, 'context_name'):
                names.insert(0, self.process.context_name)
            for name in names:
                try:
                    proc_attr_cls = factory.get('process_attributes', name)
                    found = True
                    break
                except ValueError:
                    pass

        if not hasattr(self, 'capsul_attributes'):
            self.add_trait('capsul_attributes', ControllerTrait(Controller()))
            self.capsul_attributes = proc_attr_cls(self.process, schemas)
        self._rebuild_attributes = False

        # if no specialized attributes set and process is a pipeline,
        # try building from children nodes
        if proc_attr_cls is ProcessAttributes \
                and isinstance(self.process, Pipeline):
            attributes = self.capsul_attributes
            name = getattr(self.process, 'context_name', self.process.name)

            for node_name, node in six.iteritems(self.process.nodes):
                if node_name == '':
                    continue
                subprocess = None
                if hasattr(node, 'process'):
                    subprocess = node.process
                elif isinstance(node, Switch):
                    subprocess = node
                if subprocess is not None:
                    pname = '.'.join([name, node_name])
                    subprocess_compl = \
                        ProcessCompletionEngine.get_completion_engine(
                            subprocess, pname)
                    try:
                        sub_attributes \
                            = subprocess_compl.get_attribute_values()
                    except:
                        try:
                            subprocess_compl = self.__class__(subprocess)
                            sub_attributes \
                                = subprocess_compl.get_attribute_values()
                        except:
                            continue
                    for attribute, trait \
                            in six.iteritems(sub_attributes.user_traits()):
                        if attributes.trait(attribute) is None:
                            attributes.add_trait(attribute, trait)
                            setattr(attributes, attribute,
                                    getattr(sub_attributes, attribute))

            self._get_linked_attributes()

        return self.capsul_attributes
Example #17
0
    def get_attribute_values(self):
        if self.trait('capsul_attributes') is not None \
                and hasattr(self, 'capsul_attributes'):
            return self.capsul_attributes

        self.add_trait('capsul_attributes', ControllerTrait(Controller()))
        capsul_attributes = ProcessAttributes(self.process, {})
        self.capsul_attributes = capsul_attributes
        outputs = self.process._outputs
        schema = 'switch'  # FIXME
        name = getattr(self.process, 'context_name', self.name)
        pipeline_name = '.'.join(name.split('.')[:-1])
        if pipeline_name == '':
            pipeline_name = []
        else:
            pipeline_name = [pipeline_name]
        forbidden_attributes = set(
            ['generated_by_parameter', 'generated_by_process'])
        traits_types = {
            str: traits.Str,
            unicode: traits.Str,
            int: traits.Int,
            float: traits.Float,
            list: traits.List
        }
        for out_name in outputs:
            in_name = '_switch_'.join((self.process.switch, out_name))
            found = False
            for output, name in ((False, in_name), (True, out_name)):
                plug = self.process.plugs.get(name)
                if plug is None:
                    continue
                if output:
                    links = plug.links_to
                else:
                    links = plug.links_from
                for link in links:
                    node = link[2]
                    if isinstance(node, Switch):
                        # FIXME: just for now
                        continue
                    if link[0] == '':
                        # link to the parent pipeline: don't call it to avoid
                        # an infinite loop.
                        # Either it will provide attributes by its own, either
                        # we must not take them into account, so skip it.
                        continue
                    if hasattr(node, 'process'):
                        process = node.process
                    else:
                        process = node
                    proc_name = '.'.join(pipeline_name + [link[0]])
                    completion_engine \
                        = ProcessCompletionEngine.get_completion_engine(
                            process, name=proc_name)
                    attributes = completion_engine.get_attribute_values()
                    try:
                        param_attributes \
                            = attributes.get_parameters_attributes()[link[1]]
                    except:
                        continue

                    if len(param_attributes) != 0 \
                            and len([x for x in param_attributes.keys()
                                     if x not in forbidden_attributes]) != 0:
                        ea = EditableAttributes()
                        for attribute, value in six.iteritems(
                                param_attributes):
                            if attribute not in forbidden_attributes:
                                ttype = traits_types.get(type(value))
                                if ttype is not None:
                                    trait = ttype()
                                else:
                                    trait = value
                                ea.add_trait(attribute, ttype)
                                setattr(ea, attribute, value)

                        capsul_attributes.set_parameter_attributes(
                            name, schema, ea, {})
                        found = True
                        break
                if found:
                    break
            if found:
                # propagate from input/output to other side
                ea = EditableAttributes()
                for attribute, value in six.iteritems(param_attributes):
                    ttype = traits_types.get(type(value))
                    if ttype is not None:
                        trait = ttype()
                    else:
                        trait = value
                    ea.add_trait(attribute, ttype)
                    setattr(ea, attribute, value)
                if output:
                    capsul_attributes.set_parameter_attributes(
                        in_name, schema, ea, {})
                else:
                    capsul_attributes.set_parameter_attributes(
                        out_name, schema, ea, {})

        self.install_switch_observer()
        return capsul_attributes
Example #18
0
 def configure_controller(cls):
     c = Controller()
     c.add_trait('param_type', traits.Str('Any'))
     return c
Example #19
0
def edition_widget(engine, environment):
    ''' Edition GUI for attributes 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):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('attributes', widget.environment)
            values = {'config_id': 'attributes'}
            values['attributes_schema_paths'] \
                = controller.attributes_schema_paths
            values['attributes_schemas'] = controller.attributes_schemas
            values['process_completion'] = controller.process_completion
            if controller.process_completion is traits.Undefined:
                values['process_completion'] = None
            values['path_completion'] = controller.path_completion
            if controller.path_completion is traits.Undefined:
                values['path_completion'] = None
            if conf is None:
                session.new_config('attributes', widget.environment, values)
            else:
                for k in ('attributes_schema_paths', 'attributes_schemas',
                          'process_completion', 'path_completion'):
                    setattr(conf, k, values[k])

    controller = Controller()
    controller.add_trait(
        'attributes_schema_paths',
        traits.List(traits.Str(), desc='attributes shchemas modules names'))
    controller.add_trait(
        'attributes_schemas',
        traits.DictStrStr(desc='attributes shchemas names'))
    controller.add_trait(
        'process_completion',
        traits.Str(desc='process completion model name'))
    controller.add_trait(
        'path_completion',
        traits.Str(desc='path completion model name',
                   optional=True))

    conf = engine.settings.select_configurations(
        environment, {'attributes': 'any'})
    if conf:
        aconf = conf.get(
            'capsul.engine.module.attributes', {})
        controller.attributes_schema_paths = aconf.get(
            'attributes_schema_paths', [])
        controller.attributes_schemas = aconf.get(
            'attributes_schemas', {})
        controller.process_completion = aconf.get(
            'process_completion', 'builtin')
        controller.path_completion = aconf.get(
            'path_completion', traits.Undefined)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #20
0
 def test_controller(self):
     c1 = Controller()
     c1.add_trait('gogo', traits.Str())
     c1.add_trait('bozo', traits.Int(12))
     self.assertEqual(c1.gogo, '')
     self.assertEqual(c1.bozo, 12)
     self.assertEqual(c1.user_traits().keys(), ['gogo', 'bozo'])
     c1.gogo = 'blop krok'
     self.assertEqual(c1.gogo, 'blop krok')
     d = c1.export_to_dict()
     self.assertEqual(d, {'gogo': 'blop krok', 'bozo': 12})
     c1.reorder_traits(['bozo', 'gogo'])
     self.assertEqual(c1.user_traits().keys(), ['bozo', 'gogo'])
     c1.reorder_traits(['gogo', 'bozo'])
     self.assertEqual(c1.user_traits().keys(), ['gogo', 'bozo'])
Example #21
0
    def __init__(self, attributed_process, enable_attr_from_filename=False,
                 enable_load_buttons=False, override_control_types=None,
                 separate_outputs=True, user_data=None, userlevel=0,
                 scroll=True):
        """
        Parameters
        ----------
        attributed_process: Process instance
            process with attributes to be displayed
        enable_attr_from_filename: bool (optional)
            if enabled, it will be possible to specify an input filename to
            build attributes from
        override_control_types: dict (optional)
            if given, this is a "factory" dict assigning new controller editor
            types to some traits types in the parameters controller.
        separate_outputs: bool
            if True, inputs and outputs (traits with output=True set) will
            be separated into two boxes.
        user_data: any type (optional)
            optional user data that can be accessed by individual control
            editors
        userlevel: int
            the current user level: some traits may be marked with a non-zero userlevel, and will only be visible if the ControllerWidget userlevel is more than (or equal) the trait level.
        scroll: bool
            if True, the widget includes scrollbars in the parameters and
            attributes sections when needed, otherwise it will be a fixed size
            widget.
        """
        super(AttributedProcessWidget, self).__init__()
        self.setLayout(QtGui.QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.attributed_process = attributed_process
        self._show_completion = False
        self.user_data = user_data
        self.separate_outputs = separate_outputs
        self._userlevel = userlevel

        process = attributed_process
        completion_engine = getattr(process, 'completion_engine', None)

        if completion_engine is not None:
            splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
            self.layout().addWidget(splitter)
            spl_up = QtGui.QWidget()
            spl_up.setLayout(QtGui.QVBoxLayout())
            splitter.addWidget(spl_up)
            spl_down = QtGui.QWidget()
            spl_down.setLayout(QtGui.QVBoxLayout())
            splitter.addWidget(spl_down)
        else:
            spl_up = self
            spl_down = self

        filename_widget = None
        if enable_attr_from_filename and completion_engine is not None:
            c = Controller()
            c.add_trait('attributes_from_input_filename', File(optional=True))
            filename_widget = ControllerWidget(c, live=True,
                                               user_data=user_data)
            spl_up.layout().addWidget(filename_widget)
            self.input_filename_controller = c
            c.on_trait_change(self.on_input_filename_changed,
                              'attributes_from_input_filename', dispatch='ui')
            filename_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                          QtGui.QSizePolicy.Fixed)

        # groupbox area to show attributes
        attrib_widget = QtGui.QGroupBox('Attributes:')
        attrib_widget.setFlat(True)
        attrib_widget.setAlignment(QtCore.Qt.AlignLeft)
        attrib_widget.setLayout(QtGui.QVBoxLayout())
        self.attrib_widget = attrib_widget
        spl_up.layout().addWidget(attrib_widget)
        attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                    QtGui.QSizePolicy.Preferred)

        hlay = QtGui.QHBoxLayout()
        spl_up.layout().addLayout(hlay)
        # CheckBox to completion rules or not
        self.checkbox_fom = QtGui.QCheckBox('Follow completion rules')
        self.checkbox_fom.setChecked(True)
        self.checkbox_fom.stateChanged.connect(self.on_use_fom_change)
        hlay.addWidget(self.checkbox_fom)

        # Button Show/Hide completion
        self.btn_show_completion = QtGui.QCheckBox('Show completion')
        self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed,
                                               QtGui.QSizePolicy.Fixed)
        hlay.addWidget(self.btn_show_completion)
        self.btn_show_completion.stateChanged.connect(self.on_show_completion)

        params = QtGui.QWidget()
        playout = QtGui.QVBoxLayout()
        params.setLayout(playout)
        if scroll:
            scroll_a = QtGui.QScrollArea()
            scroll_a.setWidgetResizable(True)
            scroll_a.setWidget(params)
            spl_up.layout().addWidget(scroll_a)
            scroll_a.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                   QtGui.QSizePolicy.Preferred)
            params.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Preferred)
            CWidgetClass = ScrollControllerWidget
        else:
            spl_up.layout().addWidget(params)
            CWidgetClass = ControllerWidget

        # groupbox area to show completion
        if separate_outputs:
            param_widget = QtGui.QGroupBox('Inputs:')
        else:
            param_widget = QtGui.QGroupBox('Parameters:')
        param_widget.setFlat(True)
        param_widget.setAlignment(QtCore.Qt.AlignLeft)
        playout.addWidget(param_widget)
        param_widget.setLayout(QtGui.QVBoxLayout())
        param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)
        if separate_outputs:
            out_widget = QtGui.QGroupBox('Outputs:')
            out_widget.setFlat(True)
            out_widget.setAlignment(QtCore.Qt.AlignLeft)
            playout.addWidget(out_widget)
            out_widget.setLayout(QtGui.QVBoxLayout())
            out_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                     QtGui.QSizePolicy.Expanding)

        # use concise shape for lists GUI
        from  soma.qt_gui.controls import OffscreenListControlWidget
        control_types_a = {'List': OffscreenListControlWidget}
        control_types_p = {'List': OffscreenListControlWidget}
        if override_control_types:
            control_types_p.update(override_control_types)
        #ControllerWidget._defined_controls['List'] = OffscreenListControlWidget

        # Create controller widget for process and object_attribute
        sel = None
        if separate_outputs:
            sel = 'inputs'
        self.controller_widget = ControllerWidget(process, live=True,
            parent=param_widget, override_control_types=control_types_p,
            user_data=user_data, userlevel=userlevel, select_controls=sel)
        if separate_outputs:
            self.outputs_cwidget = ControllerWidget(process, live=True,
            parent=out_widget, override_control_types=control_types_p,
            user_data=user_data, userlevel=userlevel,
            select_controls='outputs')

        show_ce = (completion_engine is not None
                   and len(
                      completion_engine.get_attribute_values().user_traits())
                          != 0)

        if completion_engine is not None:
            self.controller_widget2 = CWidgetClass(
                completion_engine.get_attribute_values(),
                live=True, parent=attrib_widget,
                override_control_types=control_types_a, user_data=user_data,
                userlevel=userlevel)
            completion_engine.get_attribute_values().on_trait_change(
                completion_engine.attributes_changed, 'anytrait')
        else:
            self.controller_widget2 = CWidgetClass(
                Controller(), override_control_types=control_types_a,
                user_data=user_data, userlevel=userlevel)

        # Set controller of attributes and controller of process for each
        # corresponding area
        param_widget.layout().addWidget(self.controller_widget)
        if separate_outputs:
            out_widget.layout().addWidget(self.outputs_cwidget)
        attrib_widget.layout().addWidget(self.controller_widget2)

        if enable_load_buttons and completion_engine is not None:
            io_lay = QtGui.QHBoxLayout()
            self.layout().addLayout(io_lay)
            self.btn_load_json = QtGui.QPushButton('Load attributes')
            io_lay.addWidget(self.btn_load_json)
            self.btn_load_json.clicked.connect(self.on_btn_load_json)
            self.btn_save_json = QtGui.QPushButton('Save attributes')
            io_lay.addWidget(self.btn_save_json)
            self.btn_save_json.clicked.connect(self.on_btn_save_json)

        if not show_ce:
            if filename_widget:
                filename_widget.hide()
            attrib_widget.hide()
            self.checkbox_fom.hide()
            self.btn_show_completion.hide()
            if hasattr(self, 'btn_load_json'):
                self.btn_load_json.hide()
                self.btn_save_json.hide()
            self.show_completion(True) # hide file parts
        else:
            self.show_completion(False) # hide file parts

        if completion_engine is not None:
            completion_engine.on_trait_change(
                self._completion_progress_changed, 'completion_progress',
                dispatch='ui')
Example #22
0
def nodes_with_existing_outputs(pipeline, exclude_inactive=True,
                                recursive=False, exclude_inputs=True):
    '''
    Checks nodes in a pipeline which outputs contain existing files on the
    filesystem. Such nodes, maybe, should not run again. Only nodes which
    actually produce outputs are selected this way (switches are skipped).

    Parameters
    ----------
    pipeline: Pipeline (mandatory)
        pipeline to disbale nodes in.
    exclude_inactive: bool (optional)
        if this option is set, inactive nodes will not be checked
        nor returned in the list. Inactive means disabled, not active, or in a
        disabled runtime step.
        Default: True
    recursive: bool (optional)
        if this option is set, sub-pipelines will not be returned as a whole
        but will be parsed recursively to select individual leaf nodes.
        Default: False
    exclude_inputs: bool (optional, default: True)
        Some processes or pipelines have input/output files: files taken as
        inputs which are re-written as outputs, or may carry an input file to
        the outputs through a switch selection (in the case of preprocessing
        steps, for instance).
        If this option is set, such outputs which also appear in the same node
        inputs will not be listed in the existing outputs, so that they will
        not be erased by a cleaning operation, and will not prevent execution
        of these nodes.

    Returns
    -------
    selected_nodes: dict
        keys: node names
        values: list of pairs (param_name, file_name)
    '''
    selected_nodes = {}
    if exclude_inactive:
        steps = getattr(pipeline, 'pipeline_steps', Controller())
        disabled_nodes = set()
        for step, trait in six.iteritems(steps.user_traits()):
            if not getattr(steps, step):
                disabled_nodes.update(trait.nodes)

    nodes = pipeline.nodes.items()
    while nodes:
        node_name, node = nodes.pop(0)
        if node_name == '' or not hasattr(node, 'process'):
            # main pipeline node, switch...
            continue
        if not node.enabled or not node.activated \
                or (exclude_inactive and node_name in disabled_nodes):
            continue
        process = node.process
        if recursive and isinstance(process, Pipeline):
            nodes += [('%s.%s' % (node_name, new_name), new_node)
                      for new_name, new_node in six.iteritems(process.nodes)
                      if new_name != '']
            continue
        plug_list = []
        input_files_list = set()
        for plug_name, plug in six.iteritems(node.plugs):
            trait = process.trait(plug_name)
            if isinstance(trait.trait_type, traits.File) \
                    or isinstance(trait.trait_type, traits.Directory) \
                    or isinstance(trait.trait_type, traits.Any):
                value = getattr(process, plug_name)
                if isinstance(value, basestring) \
                        and os.path.exists(value) \
                        and value not in input_files_list:
                    if plug.output:
                        plug_list.append((plug_name, value))
                    elif exclude_inputs:
                        input_files_list.add(value)
        if exclude_inputs:
            new_plug_list = [item for item in plug_list
                             if item[1] not in input_files_list]
            plug_list = new_plug_list
        if plug_list:
            selected_nodes[node_name] = plug_list
    return selected_nodes
    def __init__(self, process_with_fom, enable_attr_from_filename=False,
                 enable_load_buttons=False):
        """
        Parameters
        ----------
        process_with_fom: ProcessWithFom instance
            process with FOM to be displayed
        enable_attr_from_filename: bool (optional)
            if enabled, it will be possible to specify an input filename to
            build FOM attributes from
        """
        super(ProcessWithFomWidget, self).__init__()
        self.setLayout(QtGui.QVBoxLayout())
        self.process_with_fom = process_with_fom

        if enable_attr_from_filename:
            c = Controller()
            c.add_trait('attributes_from_input_filename', File(optional=True))
            cw = ControllerWidget(c, live=True)
            self.layout().addWidget(cw)
            self.input_filename_controller = c
            c.on_trait_change(self.on_input_filename_changed,
                              'attributes_from_input_filename')
            cw.setSizePolicy(QtGui.QSizePolicy.Expanding,
                             QtGui.QSizePolicy.Fixed)

            #if self.process_with_fom.study_config.input_fom \
                    #!= self.process_with_fom.study_config.output_fom:
                #c.add_trait('attributes_from_output_filename', File())
                #c.on_trait_change(self.on_input_filename_changed,
                                  #'attributes_from_output_filename')

        # groupbox area to show attributs
        attrib_widget = QtGui.QGroupBox('Attributes:')
        attrib_widget.setAlignment(QtCore.Qt.AlignLeft)
        attrib_widget.setLayout(QtGui.QVBoxLayout())
        self.attrib_widget = attrib_widget
        self.layout().addWidget(attrib_widget)
        attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                    QtGui.QSizePolicy.Preferred)

        hlay = QtGui.QHBoxLayout()
        self.layout().addLayout(hlay)
        # CheckBox to foms rules or not
        self.checkbox_fom = QtGui.QCheckBox('Follow FOM rules')
        self.checkbox_fom.setChecked(True)
        self.checkbox_fom.stateChanged.connect(self.on_use_fom_change)
        hlay.addWidget(self.checkbox_fom)

        # Button Show/Hide completion
        self.btn_show_completion = QtGui.QCheckBox('Show completion')
        self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed,
                                               QtGui.QSizePolicy.Fixed)
        hlay.addWidget(self.btn_show_completion)
        self.btn_show_completion.stateChanged.connect(self.on_show_completion)

        # groupbox area to show completion
        param_widget = QtGui.QGroupBox('Parameters:')
        param_widget.setAlignment(QtCore.Qt.AlignLeft)
        self.layout().addWidget(param_widget)
        param_widget.setLayout(QtGui.QVBoxLayout())
        param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)

        # Create controller widget for process and object_attribute
        process = process_with_fom.process
        self.controller_widget = ScrollControllerWidget(process, live=True,
            parent=param_widget)

        self.controller_widget2 = ScrollControllerWidget(self.process_with_fom,
            live=True, parent=attrib_widget)
        self.process_with_fom.on_trait_change(
            self.process_with_fom.attributes_changed, 'anytrait')

        # Set controller of attributs and controller of process for each
        # corresponding area
        param_widget.layout().addWidget(self.controller_widget)
        attrib_widget.layout().addWidget(self.controller_widget2)

        if enable_load_buttons:
            io_lay = QtGui.QHBoxLayout()
            self.layout().addLayout(io_lay)
            self.btn_load_json = QtGui.QPushButton('Load attributes')
            io_lay.addWidget(self.btn_load_json)
            self.btn_load_json.clicked.connect(self.on_btn_load_json)
            self.btn_save_json = QtGui.QPushButton('Save attributes')
            io_lay.addWidget(self.btn_save_json)
            self.btn_save_json.clicked.connect(self.on_btn_save_json)

        self.show_completion(False) # hide file parts
Example #24
0
File: spm.py Project: servoz/capsul
def edition_widget(engine, environment):
    ''' 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):
        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
            values['version'] = controller.version
            id = 'spm%s%s' % (controller.version,
                              '-standalone' if controller.standalone else '')
            values['config_id'] = id
            query = 'config_id == "%s"' % id
            conf = session.config('spm', 'global', selection=query)
            if conf is None:
                session.new_config('spm', widget.environment, values)
            else:
                for k in ('directory', 'standalone', 'version'):
                    setattr(conf, k, values[k])

    controller = Controller()
    controller.add_trait(
        "directory",
        traits.Directory(traits.Undefined,
                         output=False,
                         desc="Directory containing SPM."))
    controller.add_trait(
        "standalone",
        traits.Bool(True, 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 = engine.settings.select_configurations(environment, {'spm': 'any'})
    if conf:
        controller.directory = conf.get('capsul.engine.module.spm',
                                        {}).get('directory', traits.Undefined)
        controller.standalone = conf.get('capsul.engine.module.spm',
                                         {}).get('standalone', True)
        controller.version = conf.get('capsul.engine.module.spm',
                                      {}).get('version', '12')

    # TODO handle several configs

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #25
0
    def __init__(self,
                 attributed_process,
                 enable_attr_from_filename=False,
                 enable_load_buttons=False):
        """
        Parameters
        ----------
        attributed_process: Process instance
            process with attributes to be displayed
        enable_attr_from_filename: bool (optional)
            if enabled, it will be possible to specify an input filename to
            build attributes from
        """
        super(AttributedProcessWidget, self).__init__()
        self.setLayout(QtGui.QVBoxLayout())
        self.attributed_process = attributed_process
        self._show_completion = False

        process = attributed_process
        completion_engine = getattr(process, 'completion_engine', None)

        if completion_engine is not None:
            splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
            self.layout().addWidget(splitter)
            spl_up = QtGui.QWidget()
            spl_up.setLayout(QtGui.QVBoxLayout())
            splitter.addWidget(spl_up)
            spl_down = QtGui.QWidget()
            spl_down.setLayout(QtGui.QVBoxLayout())
            splitter.addWidget(spl_down)
        else:
            spl_up = self
            spl_down = self

        if enable_attr_from_filename and completion_engine is not None:
            c = Controller()
            c.add_trait('attributes_from_input_filename', File(optional=True))
            cw = ControllerWidget(c, live=True)
            spl_up.layout().addWidget(cw)
            self.input_filename_controller = c
            c.on_trait_change(self.on_input_filename_changed,
                              'attributes_from_input_filename',
                              dispatch='ui')
            cw.setSizePolicy(QtGui.QSizePolicy.Expanding,
                             QtGui.QSizePolicy.Fixed)

        # groupbox area to show attributs
        attrib_widget = QtGui.QGroupBox('Attributes:')
        attrib_widget.setAlignment(QtCore.Qt.AlignLeft)
        attrib_widget.setLayout(QtGui.QVBoxLayout())
        self.attrib_widget = attrib_widget
        spl_up.layout().addWidget(attrib_widget)
        attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                    QtGui.QSizePolicy.Preferred)

        hlay = QtGui.QHBoxLayout()
        spl_up.layout().addLayout(hlay)
        # CheckBox to completion rules or not
        self.checkbox_fom = QtGui.QCheckBox('Follow completion rules')
        self.checkbox_fom.setChecked(True)
        self.checkbox_fom.stateChanged.connect(self.on_use_fom_change)
        hlay.addWidget(self.checkbox_fom)

        # Button Show/Hide completion
        self.btn_show_completion = QtGui.QCheckBox('Show completion')
        self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed,
                                               QtGui.QSizePolicy.Fixed)
        hlay.addWidget(self.btn_show_completion)
        self.btn_show_completion.stateChanged.connect(self.on_show_completion)

        # groupbox area to show completion
        param_widget = QtGui.QGroupBox('Parameters:')
        param_widget.setAlignment(QtCore.Qt.AlignLeft)
        spl_down.layout().addWidget(param_widget)
        param_widget.setLayout(QtGui.QVBoxLayout())
        param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)

        # Create controller widget for process and object_attribute
        self.controller_widget = ScrollControllerWidget(process,
                                                        live=True,
                                                        parent=param_widget)

        if completion_engine is not None:
            self.controller_widget2 = ScrollControllerWidget(
                completion_engine.get_attribute_values(),
                live=True,
                parent=attrib_widget)
            completion_engine.get_attribute_values().on_trait_change(
                completion_engine.attributes_changed, 'anytrait')
        else:
            self.controller_widget2 = ScrollControllerWidget(Controller())

        # Set controller of attributs and controller of process for each
        # corresponding area
        param_widget.layout().addWidget(self.controller_widget)
        attrib_widget.layout().addWidget(self.controller_widget2)

        if enable_load_buttons and completion_engine is not None:
            io_lay = QtGui.QHBoxLayout()
            self.layout().addLayout(io_lay)
            self.btn_load_json = QtGui.QPushButton('Load attributes')
            io_lay.addWidget(self.btn_load_json)
            self.btn_load_json.clicked.connect(self.on_btn_load_json)
            self.btn_save_json = QtGui.QPushButton('Save attributes')
            io_lay.addWidget(self.btn_save_json)
            self.btn_save_json.clicked.connect(self.on_btn_save_json)

        if completion_engine is None:
            attrib_widget.hide()
            self.checkbox_fom.hide()
            self.btn_show_completion.hide()
            self.show_completion(True)  # hide file parts
        else:
            self.show_completion(False)  # hide file parts

        if completion_engine is not None:
            completion_engine.on_trait_change(
                self._completion_progress_changed,
                'completion_progress',
                dispatch='ui')
Example #26
0
File: fsl.py Project: servoz/capsul
def edition_widget(engine, environment):
    ''' Edition GUI for FSL 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):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('fsl', widget.environment)
            values = {'config_id': 'fsl'}
            for k in ('directory', 'config', 'prefix'):
                value = getattr(controller, k)
                if value is traits.Undefined:
                    value = None
                values[k] = value
            if conf is None:
                session.new_config('fsl', widget.environment, values)
            else:
                for k, value in values.items():
                    if k == 'config_id':
                        continue
                    setattr(conf, k, values[k])

    controller = Controller()

    controller.add_trait(
        'directory',
        traits.Directory(traits.Undefined,
                         desc='Directory where FSL is installed'))
    controller.add_trait(
        'config',
        traits.File(traits.Undefined,
                    output=False,
                    desc='Parameter to specify the fsl.sh path'))
    controller.add_trait(
        'prefix',
        traits.String(traits.Undefined, desc='Prefix to add to FSL commands'))

    conf = engine.settings.select_configurations(environment, {'fsl': 'any'})
    if conf:
        fconf = conf.get('capsul.engine.module.fsl', {})
        controller.directory = fconf.get('directory', traits.Undefined)
        controller.config = fconf.get('config', traits.Undefined)
        controller.prefix = fconf.get('prefix', traits.Undefined)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget
Example #27
0
def nodes_with_missing_inputs(pipeline, recursive=True):
    '''
    Checks nodes in a pipeline which inputs contain invalid inputs.
    Inputs which are files non-existing on the filesystem (so, which cannot
    run), or have missing mandatory inputs, or take as input a temporary file
    which should be the output from another disabled node, are recorded.

    Parameters
    ----------
    pipeline: Pipeline (mandatory)
        pipeline to disbale nodes in.
    recursive: bool (optional)
        if this option is set, sub-pipelines will not be returned as a whole
        but will be parsed recursively to select individual leaf nodes. Note
        that if not set, a pipeline is regarded as a process, but pipelines may
        not use all their inputs/outputs so the result might be inaccurate.
        Default: True

    Returns
    -------
    selected_nodes: dict
        keys: node names
        values: list of pairs (param_name, file_name)
    '''
    selected_nodes = {}
    steps = getattr(pipeline, 'pipeline_steps', Controller())
    disabled_nodes = set()
    for step, trait in six.iteritems(steps.user_traits()):
        if not getattr(steps, step):
            disabled_nodes.update(
                [pipeline.nodes[node_name] for node_name in trait.nodes])

    nodes = pipeline.nodes.items()
    while nodes:
        node_name, node = nodes.pop(0)
        if node_name == '' or not hasattr(node, 'process'):
            # main pipeline node, switch...
            continue
        if not node.enabled or not node.activated or node in disabled_nodes:
            continue
        process = node.process
        if recursive and isinstance(process, Pipeline):
            nodes += [('%s.%s' % (node_name, new_name), new_node)
                      for new_name, new_node in six.iteritems(process.nodes)
                      if new_name != '']
            continue
        for plug_name, plug in six.iteritems(node.plugs):
            if not plug.output:
                trait = process.trait(plug_name)
                if isinstance(trait.trait_type, traits.File) \
                        or isinstance(trait.trait_type, traits.Directory):
                    value = getattr(process, plug_name)
                    keep_me = False
                    if value is None or value is traits.Undefined \
                            or value == '' or not os.path.exists(value):
                        # check where this file comes from
                        origin_node, origin_param, origin_parent \
                            = where_is_plug_value_from(plug, recursive)
                        if origin_node is not None \
                                and (origin_node in disabled_nodes
                                     or origin_parent in disabled_nodes):
                            # file coming from another disabled node
                            #if not value or value is traits.Undefined:
                                ## temporary one
                                #print('TEMP: %s.%s' % (node_name, plug_name))
                                #value = None
                            keep_me = True
                        elif origin_node is None:
                            # unplugged: does not come from anywhere else
                            if (value is not traits.Undefined and value) \
                                    or not plug.optional:
                                # non-empty value, non-existing file
                                # or mandatory, empty value
                                keep_me = True
                        # the rest is a plugged input from another process,
                        # or an optional empty value
                    if keep_me:
                        plug_list = selected_nodes.setdefault(node_name, [])
                        plug_list.append((plug_name, value))
    return selected_nodes
Example #28
0
    def __init__(self, study_name=None, init_config=None, modules=None,
                 engine=None, **override_config):
        """ Initialize the StudyConfig class

        Parameters
        ----------
        study_name: Name of the study to configure. This name is used to
            identify specific configuration for a study.
        init_config: if not None, must contain a dictionary that will be used
            to configure this StudyConfig (instead of reading configuration
            from configuration files).
        modules: list of string (default self.default_modules).
            the names of configuration module classes that will be included
            in this study configuration.
        engine: CapsulEngine
            this parameter is temporary, it just helps to handle the transition
            to :class:`capsul.engine.CapsulEngine`. Don't use it in client code.
        override_config: dictionary
            The content of these keyword parameters will be set on the
            configuration after it has been initialized from configuration
            files (or from init_config).
        """

        super(StudyConfig, self).__init__()
        
        if study_name:
            self.study_name = study_name

        if engine is None:
            from capsul.engine import capsul_engine
            self.engine = capsul_engine()
            self.engine.study_config = weakref.proxy(self)
        else:
            self.engine = weakref.proxy(engine)

        # Read the configuration for the given study
        if init_config is None:
            config = self.read_configuration()
            config.update(override_config)
        else:
            self.global_config_file = None
            self.study_config_file = None
            if override_config:
                config = init_config.copy()
                config.update(override_config)
            else:
                config = init_config

        self.visible_groups = set(['study'])

        # Create modules
        if modules is None:
            # Make it possible for a study to define its own set of modules
            modules = config.pop('config_modules', self.default_modules)

        # 'modules_data' is a container for modules-specific internal data
        # each module is encouraged to prefix its variables there by its
        # module name
        self.modules_data = Controller()

        self.modules = {}
        for module in modules:
            self.load_module(module, config)

        # Set self attributes according to configuration values
        for k, v in six.iteritems(config):
            setattr(self, k, v)
        self.initialize_modules()
        self.run_lock = threading.RLock()
        self.run_interruption_request = False
Example #29
0
    def edit_elements(controller_widget, control_instance, edit_button):
        """ Callback to view/edit a 'ListControlWidget'.

        Parameters
        ----------
        control_instance: QFrame (mandatory)
            the list widget item
        edit_button: QToolButton
            the signal sender
        """
        controller_widget = get_ref(controller_widget)
        widget = QtGui.QDialog(controller_widget)
        widget.setModal(True)
        layout = QtGui.QVBoxLayout()
        widget.setLayout(layout)
        #hlayout = QtGui.QHBoxLayout()
        #layout.addLayout(hlayout)

        temp_controller = Controller()
        trait = control_instance.trait

        temp_controller.add_trait(control_instance.trait_name, trait)
        if temp_controller.trait(control_instance.trait_name).groups \
                is not None:
            temp_controller.trait(control_instance.trait_name).groups = None

        value = getattr(controller_widget.controller,
                        control_instance.trait_name)

        try:
            setattr(temp_controller, control_instance.trait_name, value)
        except Exception:
            # invalid value - don't prevent using the GUI
            pass
        control_types = dict(controller_widget._defined_controls)
        control_types['List'] = ListControlWidget
        control_types['List_File'] = ListControlWidget
        temp_controller_widget = ScrollControllerWidget(
            temp_controller,
            live=True,
            override_control_types=control_types,
            user_data=control_instance.user_data)

        layout.addWidget(temp_controller_widget)

        hlayout2 = QtGui.QHBoxLayout()
        layout.addLayout(hlayout2)
        hlayout2.addStretch(1)
        ok = QtGui.QPushButton('OK')
        cancel = QtGui.QPushButton('Cancel')
        hlayout2.addWidget(ok)
        hlayout2.addWidget(cancel)

        ok.pressed.connect(widget.accept)
        cancel.pressed.connect(widget.reject)

        if widget.exec_():

            ctrl = temp_controller_widget.controller_widget._controls.get(
                control_instance.trait_name)[None]
            ListControlWidget.validate_all_values(
                temp_controller_widget.controller_widget, ctrl[2])
            new_trait_value = getattr(temp_controller,
                                      control_instance.trait_name)

            setattr(controller_widget.controller, control_instance.trait_name,
                    new_trait_value)

        del temp_controller_widget
Example #30
0
def edition_widget(engine, environment):
    ''' Edition GUI for FOM 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

    def validate_config(widget):
        controller = widget.controller_widget.controller
        with widget.engine.settings as session:
            conf = session.config('fom', widget.environment)
            values = {'config_id': 'fom'}
            for k in ('input_fom', 'output_fom', 'shared_fom',
                      'volumes_format', 'meshes_format', 'auto_fom',
                      'fom_path', 'input_directory', 'output_directory'):
                value = getattr(controller, k)
                if value is traits.Undefined:
                    if k in ('fom_path', ):
                        value = []
                    else:
                        value = None
                values[k] = value
            if conf is None:
                session.new_config('fom', widget.environment, values)
            else:
                for k, value in values.items():
                    if k == 'config_id':
                        continue
                    setattr(conf, k, values[k])

    controller = Controller()

    controller.add_trait(
        'input_fom',
        traits.Str(traits.Undefined, output=False, desc='input FOM'))
    controller.add_trait(
        'output_fom',
        traits.Str(traits.Undefined, output=False, desc='output FOM'))
    controller.add_trait(
        'shared_fom',
        traits.Str(traits.Undefined, output=False, desc='shared data FOM'))
    controller.add_trait(
        'volumes_format',
        traits.Str(traits.Undefined,
                   output=False,
                   desc='Format used for volumes'))
    controller.add_trait(
        'meshes_format',
        traits.Str(traits.Undefined,
                   output=False,
                   desc='Format used for meshes'))
    controller.add_trait(
        'auto_fom',
        traits.Bool(
            True,
            output=False,
            desc='Look in all FOMs when a process is not found (in '
            'addition to the standard share/foms). Note that auto_fom '
            'looks for the first FOM matching the process to get '
            'completion for, and does not handle ambiguities. Moreover '
            'it brings an overhead (typically 6-7 seconds) the first '
            'time it is used since it has to parse all available FOMs.'))
    controller.add_trait(
        'fom_path',
        traits.List(
            traits.Directory(output=False),
            desc='list of additional directories where to look for FOMs'))
    # FIXME: until directories are included in another config module
    controller.add_trait(
        'input_directory',
        traits.Directory(traits.Undefined,
                         output=False,
                         desc='input study data directory'))
    controller.add_trait(
        'output_directory',
        traits.Directory(traits.Undefined,
                         output=False,
                         desc='output study data directory'))

    conf = engine.settings.select_configurations(environment, {'fom': 'any'})
    if conf:
        fconf = conf.get('capsul.engine.module.fom', {})
        controller.input_fom = fconf.get('input_fom', traits.Undefined)
        controller.output_fom = fconf.get('output_fom', traits.Undefined)
        controller.shared_fom = fconf.get('shared_fom', traits.Undefined)
        controller.volumes_format = fconf.get('volumes_format',
                                              traits.Undefined)
        controller.meshes_format = fconf.get('meshes_format', traits.Undefined)
        controller.auto_fom = fconf.get('auto_fom', traits.Undefined)
        controller.fom_path = fconf.get('fom_path', traits.Undefined)
        controller.input_directory = fconf.get('input_directory',
                                               traits.Undefined)
        controller.output_directory = fconf.get('output_directory',
                                                traits.Undefined)

    widget = ScrollControllerWidget(controller, live=True)
    widget.engine = engine
    widget.environment = environment
    widget.accept = types.MethodType(validate_config, widget)

    return widget