Ejemplo n.º 1
0
    def __init__(self, regimes=None, aliases=None, state_variables=None):
        """Dynamics object constructor

           :param aliases: A list of aliases, which must be either |Alias|
               objects or ``string``s.
           :param regimes: A list containing at least one |Regime| object.
           :param state_variables: An optional list of the state variables,
                which can either be |StateVariable| objects or `string` s. If
                provided, it must match the inferred state-variables from the
                regimes; if it is not provided it will be inferred
                automatically.
        """

        aliases = nineml.utility.normalise_parameter_as_list(aliases)
        regimes = nineml.utility.normalise_parameter_as_list(regimes)
        state_variables = nineml.utility.normalise_parameter_as_list(state_variables)

        # Load the aliases as objects or strings:
        from nineml.utility import filter_discrete_types
        alias_td = filter_discrete_types(aliases, (basestring, Alias))
        aliases_from_strs = [StrToExpr.alias(o) for o in alias_td[basestring]]
        aliases = alias_td[Alias] + aliases_from_strs

        # Load the state variables as objects or strings:
        sv_types = (basestring, StateVariable)
        sv_td = filter_discrete_types(state_variables, sv_types)
        sv_from_strings = [StateVariable(o) for o in sv_td[basestring]]
        state_variables = sv_td[StateVariable] + sv_from_strings

        self._regimes = regimes
        self._aliases = aliases
        self._state_variables = state_variables
Ejemplo n.º 2
0
    def __init__(self, *args, **kwargs):
        """Regime constructor

            :param name: The name of the constructor. If none, then a name will
                be automatically generated.
            :param time_derivatives: A list of time derivatives, as
                either ``string``s (e.g 'dg/dt = g/gtau') or as
                |TimeDerivative| objects.
            :param transitions: A list containing either |OnEvent| or
                |OnCondition| objects, which will automatically be sorted into
                the appropriate classes automatically.
            :param *args: Any non-keyword arguments will be treated as
                time_derivatives.


        """
        valid_kwargs = ('name', 'transitions', 'time_derivatives')
        for arg in kwargs:
            if not arg in valid_kwargs:
                err = 'Unexpected Arg: %s' % arg
                raise NineMLRuntimeError(err)

        transitions = kwargs.get('transitions', None)
        name = kwargs.get('name', None)
        kw_tds = normalise_parameter_as_list(kwargs.get('time_derivatives',
                                                        None))
        time_derivatives = list(args) + kw_tds

        # Generate a name for unnamed regions:
        self._name = name.strip() if name else Regime.get_next_name()
        ensure_valid_c_variable_name(self._name)

        # Un-named arguments are time_derivatives:
        time_derivatives = normalise_parameter_as_list(time_derivatives)
        # time_derivatives.extend( args )

        td_types = (basestring, TimeDerivative)
        td_type_dict = filter_discrete_types(time_derivatives, td_types)
        td_from_str = [StrToExpr.time_derivative(o)
                       for o in td_type_dict[basestring]]
        self._time_derivatives = td_type_dict[TimeDerivative] + td_from_str

        # Check for double definitions:
        td_dep_vars = [td.dependent_variable for td in self._time_derivatives]
        assert_no_duplicates(td_dep_vars)

        # We support passing in 'transitions', which is a list of both OnEvents
        # and OnConditions. So, lets filter this by type and add them
        # appropriately:
        transitions = normalise_parameter_as_list(transitions)
        f_dict = filter_discrete_types(transitions, (OnEvent, OnCondition))
        self._on_events = []
        self._on_conditions = []

        # Add all the OnEvents and OnConditions:
        for event in f_dict[OnEvent]:
            self.add_on_event(event)
        for condition in f_dict[OnCondition]:
            self.add_on_condition(condition)
Ejemplo n.º 3
0
    def test_filter_discrete_types(self):
        # Signature: name(lst, acceptedtypes)
                # Creates a dictionary mapping types to objects of that type.
                #
                # Starting with a list of object, and a list of types, this returns a
                # dictionary mapping each type to a list of objects of that type.
                #
                # For example::
                #
                #     >>> import types
                # >>> filter_discrete_types( ['hello',1,2,'world'], ( basestring, types.IntType) ) #doctest: +NORMALIZE_WHITESPACE
                #     {<type 'basestring'>: ['hello', 'world'], <type 'int'>: [1, 2]}
                #
                #
                # The function checks that each object is mapped to exactly one type
        from nineml.utility import filter_discrete_types
        import numbers
        import types
        from nineml.exceptions import NineMLRuntimeError

        # Good Case:
        data = ['hello', 'world', 1, 2, 3]
        types = [basestring, numbers.Number, types.BooleanType]
        filtered = filter_discrete_types(data, types)

        self.assertEqual(filtered[basestring], ['hello', 'world'])
        self.assertEqual(filtered[numbers.Number], [1, 2, 3])

        # Not all objects covered by listed classes:
        self.assertRaises(
            NineMLRuntimeError,
            filter_discrete_types, data, [basestring]
        )
Ejemplo n.º 4
0
 def __init__(self, name, parameters=None):
     self._name = name
     
     # Turn any strings in the parameter list into Parameters:
     if parameters is None:
         self._parameters = []
     else:
         param_types = (basestring, Parameter)
         param_td = filter_discrete_types(parameters, param_types)
         params_from_strings = [Parameter(s) for s in param_td[basestring]]
         self._parameters = param_td[Parameter] + params_from_strings
Ejemplo n.º 5
0
def do_to_assignments_and_events(doList):
    if not doList:
        return [], []
    # 'doList' is a list of strings, OutputEvents, and StateAssignments.
    do_type_list = (OutputEvent, basestring, StateAssignment)
    do_types = filter_discrete_types(doList, do_type_list)

    # Convert strings to StateAssignments:
    sa_from_strs = [StrToExpr.state_assignment(s) for s in do_types[basestring]]

    return do_types[StateAssignment] + sa_from_strs, do_types[OutputEvent]
Ejemplo n.º 6
0
    def __init__(self, state_assignments=None, event_outputs=None,
                 target_regime_name=None):
        """Abstract class representing a transition from one |Regime| to
        another.

        |Transition| objects are not created directly, but via the subclasses
        |OnEvent| and |OnCondition|.

        :param state_assignments: A list of the state-assignments performed
            when this transition occurs. Objects in this list are either
            `string` (e.g A = A+13) or |StateAssignment| objects.
        :param event_outputs: A list of |OutputEvent| objects emitted when
            this transition occurs.
        :param target_regime_name: The name of the regime to go into after this
            transition.  ``None`` implies staying in the same regime. This has
            to be specified as a string, not the object, because in general the
            |Regime| object is not yet constructed. This is automatically
            resolved by the |ComponentClass| in
            ``_ResolveTransitionRegimeNames()`` during construction.


        .. todo::

            For more information about what happens at a regime transition, see
            here: XXXXXXX

        """
        if target_regime_name:
            assert isinstance(target_regime_name, basestring)

        # Load state-assignment objects as strings or StateAssignment objects
        from nineml.utility import filter_discrete_types
        state_assignments = state_assignments or []

        sa_types = (basestring, StateAssignment)
        sa_type_dict = filter_discrete_types(state_assignments, sa_types)
        sa_from_str = [StrToExpr.state_assignment(o) for o in sa_type_dict[basestring]]
        self._state_assignments = sa_type_dict[StateAssignment] + sa_from_str

        self._event_outputs = event_outputs or []

        self._target_regime_name = target_regime_name
        self._source_regime_name = None

        # Set later, once attached to a regime:
        self._target_regime = None
        self._source_regime = None
Ejemplo n.º 7
0
    def __init__(self, name, parameters=None, analog_ports=None,
                 event_ports=None, dynamics=None, subnodes=None,
                 portconnections=None, regimes=None,
                 aliases=None, state_variables=None):
        """Constructs a ComponentClass

        :param name: The name of the component.
        :param parameters: A list containing either |Parameter| objects
            or strings representing the parameter names. If ``None``, then the
            parameters are automatically inferred from the |Dynamics| block.
        :param analog_ports: A list of |AnalogPorts|, which will be the
            local |AnalogPorts| for this object.
        :param event_ports: A list of |EventPorts| objects, which will be the
            local event-ports for this object. If this is ``None``, then they
            will be automatically inferred from the dynamics block.
        :param dynamics: A |Dynamics| object, defining the local dynamics of the
            component.
        :param subnodes: A dictionary mapping namespace-names to sub-component.
            [Type: ``{string:|ComponentClass|, string:|ComponentClass|,
            string:|ComponentClass|}`` ] describing the namespace of subcomponents
            for this component.
        :param portconnections: A list of pairs, specifying the connections
            between the ports of the subcomponents in this component. These can
            be `(|NamespaceAddress|, |NamespaceAddress|)' or ``(string, string)``.
        :param interface: A shorthand way of specifying the **interface** for
            this component; |Parameters|, |AnalogPorts| and |EventPorts|.
            ``interface`` takes a list of these objects, and automatically
            resolves them by type into the correct types.

        Examples:

        >>> a = ComponentClass(name='MyComponent1')

        .. todo::

            Point this towards and example of constructing ComponentClasses.
            This can't be here, because we also need to know about dynamics.
            For examples

        """

        # We can specify in the componentclass, and they will get forwarded to
        # the dynamics class. We check that we do not specify half-and-half:
        if dynamics is not None:
            if regimes or aliases or state_variables:
                err = "Either specify a 'dynamics' parameter, or "
                err += "state_variables /regimes/aliases, but not both!"
                raise NineMLRuntimeError(err)

        else:
            # We should always create a dynamics object, even is it is empty:
            dynamics = dyn.Dynamics(regimes=regimes,
                                    aliases=aliases,
                                    state_variables=state_variables)

        # Turn any strings in the parameter list into Parameters:
        from nineml.utility import filter_discrete_types
        if parameters is not None:
            param_types = (basestring, Parameter)
            param_td = filter_discrete_types(parameters, param_types)
            params_from_strings = [Parameter(s) for s in param_td[basestring]]
            parameters = param_td[Parameter] + params_from_strings

        self._query = componentqueryer.ComponentQueryer(self)

        # EventPort, StateVariable and Parameter Inference:
        inferred_struct = InterfaceInferer(dynamics, analog_ports=analog_ports)
        inf_check = lambda l1, l2, desc: check_list_contain_same_items(l1, l2,
                                                                       desc1='Declared', desc2='Inferred', ignore=['t'], desc=desc)

        # Check any supplied parameters match:
        if parameters is not None:
            parameter_names = [p.name for p in parameters]
            inf_check(parameter_names,
                      inferred_struct.parameter_names,
                      'Parameters')
        else:
            parameters = [Parameter(n) for n in inferred_struct.parameter_names]

        # Check any supplied state_variables match:
        if dynamics._state_variables:
            state_var_names = [p.name for p in dynamics.state_variables]
            inf_check(state_var_names,
                      inferred_struct.state_variable_names,
                      'StateVariables')
        else:
            state_vars = [StateVariable(n) for n in
                          inferred_struct.state_variable_names]
            dynamics._state_variables = state_vars

        # Check Event Ports Match:
        if event_ports is not None:
            ip_evt_names = [ep.name for ep in event_ports if ep.is_incoming()]
            op_evt_names = [ep.name for ep in event_ports if ep.is_outgoing()]
            # Check things Match:
            inf_check(ip_evt_names,
                      inferred_struct.input_event_port_names,
                      'Event Ports In')
            inf_check(op_evt_names,
                      inferred_struct.output_event_port_names,
                      'Event Ports Out')
        else:
            event_ports = []
            # Event ports not supplied, so lets use the inferred ones.
            for evt_port_name in inferred_struct.input_event_port_names:
                event_ports.append(EventPort(name=evt_port_name, mode='recv'))
            for evt_port_name in inferred_struct.output_event_port_names:
                event_ports.append(EventPort(name=evt_port_name, mode='send'))

        # Construct super-classes:
        ComponentClassMixinFlatStructure.__init__(self,
                                                  name=name,
                                                  parameters=parameters,
                                                  analog_ports=analog_ports,
                                                  event_ports=event_ports,
                                                  dynamics=dynamics)

        ComponentClassMixinNamespaceStructure.__init__(self,
                                                       subnodes=subnodes,
                                                       portconnections=portconnections)

        # Finalise initiation:
        self._resolve_transition_regime_names()

        # Store flattening Information:
        self._flattener = None

        # Is the finished component valid?:
        self._validate_self()