Ejemplo n.º 1
0
    def build_event_connections(self, component, runnable, structure):
        """
        Adds event connections to a runnable component based on the structure
        specifications in the component model.

        @param component: Component model containing structure specifications.
        @type component: lems.model.component.FatComponent

        @param runnable: Runnable component to which structure is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param structure: The structure object to be used to add
        structure code in the runnable component.
        @type structure: lems.model.structure.Structure
        """
        if self.debug: print("\n++++++++ Calling build_event_connections of %s with runnable %s, parent %s"%(component.id, runnable.id, runnable.parent))
        # Process event connections
        for ec in structure.event_connections:
            if self.debug: print(ec.toxml())
            source = runnable.parent.resolve_path(ec.from_)
            target = runnable.parent.resolve_path(ec.to)
            if ec.receiver:
                receiver_template = self.build_runnable(ec.receiver,
                                                            target)
                                                            
                #receiver = copy.deepcopy(receiver_template)
                receiver = receiver_template.copy()
                receiver.id = "{0}__{1}__".format(component.id,
                                                  receiver_template.id)

                if ec.receiver_container:
                    target.add_attachment(receiver, ec.receiver_container)
                target.add_child(receiver_template.id, receiver)
                target = receiver
            else:
                source = runnable.resolve_path(ec.from_)
                target = runnable.resolve_path(ec.to)

            source_port = ec.source_port
            target_port = ec.target_port

            if not source_port:
                if len(source.event_out_ports) == 1:
                    source_port = source.event_out_ports[0]
                else:
                    raise SimBuildError(("No source event port "
                                         "uniquely identifiable"
                                         " in '{0}'").format(source.id))
            if not target_port:
                if len(target.event_in_ports) == 1:
                    target_port = target.event_in_ports[0]
                else:
                    raise SimBuildError(("No destination event port "
                                         "uniquely identifiable "
                                         "in '{0}'").format(target))
             
            if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
            source.register_event_out_callback(\
                source_port, lambda: target.inc_event_in(target_port))
Ejemplo n.º 2
0
    def build_foreach(self, component, runnable, foreach, name_mappings = {}):
        """
        Iterate over ForEach constructs and process nested elements.

        @param component: Component model containing structure specifications.
        @type component: lems.model.component.FatComponent

        @param runnable: Runnable component to which structure is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param foreach: The ForEach structure object to be used to add
        structure code in the runnable component.
        @type foreach: lems.model.structure.ForEach
        """
        if self.debug: print("\n++++++++ Calling build_foreach of %s with runnable %s, parent %s, name_mappings: %s"%(component.id, runnable.id, runnable.parent, name_mappings))

        target_array = runnable.resolve_path(foreach.instances)
        
        for target_runnable in target_array:
            if self.debug: print("Applying contents of for_each to %s, as %s"%(target_runnable.id, foreach.as_))
            name_mappings[foreach.as_] = target_runnable

            # Process foreach statements
            for fe2 in foreach.for_eachs:
                #print fe2.toxml()
                target_array2 = runnable.resolve_path(fe2.instances)

                for target_runnable2 in target_array2:
                    name_mappings[fe2.as_] = target_runnable2
                    self.build_foreach(component, runnable, fe2, name_mappings)

            # Process event connections
            for ec in foreach.event_connections:
                source = name_mappings[ec.from_]
                target = name_mappings[ec.to]

                source_port = ec.source_port
                target_port = ec.target_port

                if not source_port:
                    if len(source.event_out_ports) == 1:
                        source_port = source.event_out_ports[0]
                    else:
                        raise SimBuildError(("No source event port "
                                             "uniquely identifiable"
                                             " in '{0}'").format(source.id))
                if not target_port:
                    if len(target.event_in_ports) == 1:
                        target_port = target.event_in_ports[0]
                    else:
                        raise SimBuildError(("No destination event port "
                                             "uniquely identifiable "
                                             "in '{0}'").format(target))

                if self.debug: print("register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"%(source, id(source), source_port, target, id(target), target_port))
                source.register_event_out_callback(\
                    source_port, lambda: target.inc_event_in(target_port))
Ejemplo n.º 3
0
    def add_variable_recorder2(self, data_output, recorder, path, full_path):

        if path[0] == '/':
            self.parent.add_variable_recorder2(data_output, recorder, path,
                                               full_path)
        elif path.find('../') == 0:
            self.parent.add_variable_recorder2(data_output, recorder, path[3:],
                                               full_path)
        elif path.find('/') >= 1:
            (child, new_path) = path.split('/', 1)

            if ':' in child:
                syn_parts = child.split(":")
                if syn_parts[0] == 'synapses' and syn_parts[2] == '0':
                    child = syn_parts[1]
                else:
                    raise SimBuildError(
                        'Cannot determine what to do with (synapse?) path: %s (full path: %s)'
                        % (child, full_path))

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx == -1:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path, full_path)
                else:
                    childobj.array[idx].add_variable_recorder2(
                        data_output, recorder, new_path, full_path)
            elif child in self.component.children:
                cdef = self.component.children[child]
                childobj = None
                for cid in self.children:
                    c = self.children[cid]
                    if cdef.type in c.component.types:
                        childobj = c
                if childobj:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path)
                else:
                    raise SimBuildError('Unable to find the child \'{0}\' in '
                                        '\'{1}\''.format(child, self.id))
            else:
                raise SimBuildError('Unable to find a child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))
        else:
            self.recorded_variables.append(
                Recording(path, full_path, data_output, recorder))
Ejemplo n.º 4
0
    def get_numeric_value(self, value_str, dimension=None):
        """
        Get the numeric value for a parameter value specification.

        @param value_str: Value string
        @type value_str: str

        @param dimension: Dimension of the value
        @type dimension: str
        """

        n = None
        i = len(value_str)
        while n is None:
            try:
                part = value_str[0:i]
                nn = float(part)
                n = nn
                s = value_str[i:]
            except ValueError:
                i = i - 1

        number = n
        sym = s

        numeric_value = None

        if sym == '':
            numeric_value = number
        else:
            if sym in self.units:
                unit = self.units[sym]
                if dimension:
                    if dimension != unit.dimension and dimension != '*':
                        raise SimBuildError(
                            "Unit symbol '{0}' cannot "
                            "be used for dimension '{1}'", sym, dimension)
                else:
                    dimension = unit.dimension

                numeric_value = (number *
                                 (10**unit.power) * unit.scale) + unit.offset
            else:
                raise SimBuildError("Unknown unit symbol '{0}'. Known: {1}",
                                    sym, self.units)

        #print("Have converted %s to value: %s, dimension %s"%(value_str, numeric_value, dimension))
        return numeric_value
Ejemplo n.º 5
0
    def add_recording_behavior(self, component, runnable, behavior_profile):
        """
        Adds recording-related behavior to a runnable component based on
        the behavior specifications in the component model.

        @param component: Component model containing behavior specifications.
        @type component: lems.model.component.Component

        @param runnable: Runnable component to which behavior is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param behavior_profile: The behavior profile to be used to generate
        behavior code in the runnable component.
        @type behavior_profile: lems.model.behavior.Behavior

        @raise SimBuildError: Raised when a target for recording could not be
        found.
        """

        context = component.context
        regime = behavior_profile.default_regime

        for rn in regime.records:
            rec = regime.records[rn]
            if self.current_record_target == None:
                raise SimBuildError('No target available for '
                                    'recording variables')
            self.current_record_target.add_variable_recorder(rec.quantity)
Ejemplo n.º 6
0
    def add_variable_recorder(self, path):
        if path[0] == '/':
            self.parent.add_variable_recorder(path)
        elif path.find('../') == 0:
            self.parent.add_variable_recorder(path[3:])
        elif path.find('/') >= 1:
            (child, new_path) = path.split('/', 1)

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx == -1:
                    childobj.add_variable_recorder(new_path)
                else:
                    childobj.array[idx].add_variable_recorder(new_path)
            else:
                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))
        else:
            self.recorded_variables[path] = []
Ejemplo n.º 7
0
    def add_variable_recorder2(self, data_output, recorder, path, full_path):

        if path[0] == '/':
            self.parent.add_variable_recorder2(data_output, recorder, path,
                                               full_path)
        elif path.find('../') == 0:
            self.parent.add_variable_recorder2(data_output, recorder, path[3:],
                                               full_path)
        elif path.find('/') >= 1:
            (child, new_path) = path.split('/', 1)

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx == -1:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path, full_path)
                else:
                    childobj.array[idx].add_variable_recorder2(
                        data_output, recorder, new_path, full_path)
            elif child in self.component.children:
                cdef = self.component.children[child]
                childobj = None
                for cid in self.children:
                    c = self.children[cid]
                    if cdef.type in c.component.types:
                        childobj = c
                if childobj:
                    childobj.add_variable_recorder2(data_output, recorder,
                                                    new_path)
                else:
                    raise SimBuildError('Unable to find child \'{0}\' in '
                                        '\'{1}\''.format(child, self.id))
            else:
                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))
        else:
            self.recorded_variables.append(
                Recording(path, full_path, data_output, recorder))
Ejemplo n.º 8
0
    def add_event_connection(self, runnable, from_component, from_port,
                             to_component, to_port):
        if from_component in runnable.children:
            from_ = runnable.children[from_component]
        else:
            raise SimBuildError('Unable to find component \'{0}\' '
                                'under \'{1}\''.format(\
                                    from_component, runnable.id))

        if to_component in runnable.children:
            to = runnable.children[to_component]
        else:
            raise SimBuildError('Unable to find component \'{0}\' '
                                'under \'{1}\''.format(\
                                    to_component, runnable.id))

        from_.register_event_out_callback(\
            from_port, lambda: to.inc_event_in(to_port))
Ejemplo n.º 9
0
 def register_event_out_callback(self, port, callback):
     if self.debug:
         print("register_event_out_callback on %s, port: %s, callback: %s" %
               (self.id, port, callback))
     if port in self.event_out_callbacks:
         self.event_out_callbacks[port].append(callback)
     else:
         raise SimBuildError('No event out port \'{0}\' in '
                             'component \'{1}\''.format(port, self.id))
     if self.debug: print("EOC: " + str(self.event_out_callbacks))
Ejemplo n.º 10
0
    def add_attachment(self, runnable, container=None):
        for ctype in runnable.component.types:
            if ctype in self.attachments:
                name = self.attachments[ctype]
                if container is not None and container != name:
                    continue

                if name not in self.__dict__:
                    raise SimBuildError(
                        'Cannot attach {0} to {1} in {2}'.format(
                            runnable.id, name, self.id))

                runnable.id = runnable.id + str(len(self.__dict__[name]))

                self.__dict__[name].append(runnable)
                runnable.parent = self

                return

        raise SimBuildError(
            'Unable to find appropriate attachment for {0} in {1}',
            runnable.id, self.id)
Ejemplo n.º 11
0
def order_derived_parameters(component):
    """
    Finds ordering of derived_parameters.

    @param component: Component containing derived parameters.
    @type component: lems.model.component.Component

    @return: Returns ordered list of derived parameters.
    @rtype: list(string)

    @raise SimBuildError: Raised when a proper ordering of derived
    parameters could not be found.
    """

    if len(component.derived_parameters) == 0:
        return []
    
    ordering = []
    dps = []
    
    for dp in component.derived_parameters:
        dps.append(dp.name)
            
    maxcount = 5

    count = maxcount

    while count > 0 and dps != []:
        count = count - 1

        for dp1 in dps:
            #exp_tree = regime.derived_variables[dv1].expression_tree
            value = component.derived_parameters[dp1].value
            found = False
            for dp2 in dps:
                if dp1 != dp2 and dp2 in value:
                    found = True
            if not found:
                ordering.append(dp1)
                del dps[dps.index(dp1)]
                count = maxcount
                break

    if count == 0:
        raise SimBuildError(("Unable to find ordering for derived "
                             "parameter in component '{0}'").format(component))

    #return ordering + dvsnoexp
    return ordering
Ejemplo n.º 12
0
    def build(self):
        """
        Build the simulation components from the model.

        @return: A runnable simulation object
        @rtype: lems.sim.sim.Simulation
        """

        self.sim = Simulation()

        for component_id in self.model.targets:
            if component_id not in self.model.components:
                raise SimBuildError("Unable to find target component '{0}'",
                                    component_id)
            component = self.model.fat_components[component_id]

            runnable = self.build_runnable(component)
            self.sim.add_runnable(runnable)

        return self.sim 
Ejemplo n.º 13
0
    def build(self):
        """
        Build the simulation components from the model.

        @return: A runnable simulation object
        @rtype: lems.sim.sim.Simulation
        """

        self.sim = Simulation()

        for component_id in self.model.default_runs:
            if component_id not in self.model.context.components:
                raise SimBuildError('Unable to find component \'{0}\' to run'\
                                    .format(component_id))
            component = self.model.context.components[component_id]

            runnable = self.build_runnable(component)
            self.sim.add_runnable(component.id, runnable)

        return self.sim
Ejemplo n.º 14
0
    def build_expression_from_tree(self, runnable, regime, tree_node):
        """
        Recursively builds a Python expression from a parsed expression tree.

        @param runnable: Runnable object to which this expression would be added.
        @type runnable: lems.sim.runnable.Runnable

        @param regime: Dynamics regime being built.
        @type regime: lems.model.dynamics.Regime

        @param tree_node: Root node for the tree from which the expression
        is to be built.
        @type tree_node: lems.parser.expr.ExprNode

        @return: Generated Python expression.
        @rtype: string
        """

        component_type = self.model.component_types[runnable.component.type]
        dynamics = component_type.dynamics
        
        if tree_node.type == ExprNode.VALUE:
            if tree_node.value[0].isalpha():
                if tree_node.value == 't':
                    return 'self.time_completed'
                elif tree_node.value in component_type.requirements:
                    var_prefix = 'self'
                    v = tree_node.value

                    r = runnable

                    while (v not in r.instance_variables and
                           v not in r.derived_variables):
                        var_prefix = '{0}.{1}'.format(var_prefix, 'parent')
                        r = r.parent
                        if r == None:
                            raise SimBuildError("Unable to resolve required "
                                                "variable '{0}'".format(v))

                    return '{0}.{1}'.format(var_prefix, v)
                elif (tree_node.value in dynamics.derived_variables or (regime is not None and tree_node.value in regime.derived_variables)):
                    return 'self.{0}'.format(tree_node.value)
                else:
                    return 'self.{0}_shadow'.format(tree_node.value)
            else:
                return tree_node.value
        elif tree_node.type == ExprNode.FUNC1:
            pattern = '({0}({1}))'
            func = self.convert_func(tree_node.func)
            if 'random.uniform' in func:
                pattern = '({0}(0,{1}))'
            return pattern.format(\
                func,
                self.build_expression_from_tree(runnable,
                                                regime,
                                                tree_node.param))
        else:
            return '({0}) {1} ({2})'.format(\
                self.build_expression_from_tree(runnable,
                                                regime,
                                                tree_node.left),
                self.convert_op(tree_node.op),
                self.build_expression_from_tree(runnable,
                                                regime,
                                                tree_node.right))
Ejemplo n.º 15
0
    def add_dynamics_2(self, component, runnable, regime, dynamics):
        """
        Adds dynamics to a runnable component based on the dynamics
        specifications in the component model.

        This method builds dynamics dependent on child components.

        @param component: Component model containing dynamics specifications.
        @type component: lems.model.component.FatComponent

        @param runnable: Runnable component to which dynamics is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param regime: The dynamics regime to be used to generate
        dynamics code in the runnable component.
        @type regime: lems.model.dynamics.Regime

        @param dynamics: Shared dynamics specifications.
        @type dynamics: lems.model.dynamics.Regime

        @raise SimBuildError: Raised when a time derivative expression refers
        to an undefined variable.

        @raise SimBuildError: Raised when there are invalid time
        specifications for the <Run> statement.

        @raise SimBuildError: Raised when the component reference for <Run>
        cannot be resolved.
        """

        if isinstance(regime, Dynamics) or regime.name == '':
            suffix = ''
        else:
            suffix = '_regime_' + regime.name

        # Process kinetic schemes
        ks_code = []
        for ks in regime.kinetic_schemes:
            
            raise NotImplementedError("KineticScheme element is not stable in PyLEMS yet, see https://github.com/LEMS/pylems/issues/15")
        
            try:
                ###nodes = {node.id:node for node in runnable.__dict__[ks.nodes]}
                nodes = {}
                for node in runnable.__dict__[ks.nodes]:
                    nodes[node.id] = node
                edges = runnable.__dict__[ks.edges]

                for edge in edges:
                    from_ = edge.__dict__[ks.edge_source]
                    to = edge.__dict__[ks.edge_target]

                    ks_code += [('self.{0}.{2} += dt * (-self.{3}.{4} * self.{0}.{2}_shadow'
                                 ' + self.{3}.{5} * self.{1}.{2}_shadow)').format(
                        from_, to, ks.state_variable, edge.id,
                        ks.forward_rate, ks.reverse_rate)]

                    ks_code += [('self.{1}.{2} += dt * (self.{3}.{4} * self.{0}.{2}_shadow'
                                 ' - self.{3}.{5} * self.{1}.{2}_shadow)').format(
                        from_, to, ks.state_variable, edge.id,
                        ks.forward_rate, ks.reverse_rate)]

                ks_code += ['sum = 0']
                for node in nodes:
                    nodes[node].__dict__[ks.state_variable] = 1.0 / len(nodes)
                    nodes[node].__dict__[ks.state_variable + '_shadow'] = 1.0 / len(nodes)
                    ks_code += ['sum += self.{0}.{1}'.format(node, ks.state_variable)]

                for node in nodes:
                    ks_code += ['self.{0}.{1} /= sum'.format(node, ks.state_variable)]

                for node in nodes:
                    ks_code += [('self.{0}.{1}_shadow = '
                                 'self.{0}.{1}').format(node,
                                                        ks.state_variable)]

            except Exception as e:
                raise SimBuildError(("Unable to construct kinetic scheme '{0}' "
                                     "for component '{1}' - {2}").format(ks.name,
                                                                         component.id,
                                                                         str(e)))

        runnable.add_method('update_kinetic_scheme' + suffix, ['self', 'dt'],
                            ks_code)
Ejemplo n.º 16
0
 def register_event_out_callback(self, port, callback):
     if port in self.event_out_callbacks:
         self.event_out_callbacks[port].append(callback)
     else:
         raise SimBuildError('No event out port \'{0}\' in '
                             'component \'{1}\''.format(port, self.name))
Ejemplo n.º 17
0
                        found = True
            else:
                for case in dv.cases:
                    for dv2 in dvs:
                        if dv1 != dv2 and (is_var_in_exp_tree(dv2, case.condition_expression_tree) or
                                           is_var_in_exp_tree(dv2, case.value_expression_tree)):
                            found = True
                            
            if not found:
                ordering.append(dv1)
                del dvs[dvs.index(dv1)]
                count = maxcount
                break

    if count == 0:
        raise SimBuildError(("Unable to find ordering for derived "
                             "variables in regime '{0}'").format(regime.name))

    #return ordering + dvsnoexp
    return dvsnoexp + ordering

def is_var_in_exp_tree(var, exp_tree):
    node = exp_tree

    if node.type == ExprNode.VALUE:
        if node.value == var:
            return True
        else:
            return False
    elif node.type == ExprNode.OP:
        if is_var_in_exp_tree(var, node.left):
            return True
Ejemplo n.º 18
0
    def add_runnable_behavior(self, component, runnable, behavior_profile):
        """
        Adds behavior to a runnable component based on the behavior
        specifications in the component model.

        @param component: Component model containing behavior specifications.
        @type component: lems.model.component.Component

        @param runnable: Runnable component to which behavior is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param behavior_profile: The behavior profile to be used to generate
        behavior code in the runnable component.
        @type behavior_profile: lems.model.behavior.Behavior

        @raise SimBuildError: Raised when a time derivative expression refers
        to an undefined variable.

        @raise SimBuildError: Raised when there are invalid time
        specifications for the <Run> statement.

        @raise SimBuildError: Raised when the component reference for <Run>
        cannot be resolved.
        """

        context = component.context
        regime = behavior_profile.default_regime

        for svn in regime.state_variables:
            sv = regime.state_variables[svn]
            runnable.add_instance_variable(sv.name, 0)

        time_step_code = []
        for tdn in regime.time_derivatives:
            if tdn not in regime.state_variables:
                raise SimBuildError(('Time derivative for undefined state '
                                     'variable {0}').format(tdn))

            td = regime.time_derivatives[tdn]
            time_step_code += ['self.{0} += dt * ({1})'.format(td.variable,
                               self.build_expression_from_tree(\
                                   td.expression_tree))]
        runnable.add_method('update_state_variables', ['self', 'dt'],
                            time_step_code)

        pre_event_handler_code = []
        post_event_handler_code = []
        for eh in regime.event_handlers:
            if eh.type == EventHandler.ON_CONDITION:
                post_event_handler_code += self.build_event_handler(eh)
            else:
                pre_event_handler_code += self.build_event_handler(eh)
        runnable.add_method('run_preprocessing_event_handlers', ['self'],
                            pre_event_handler_code)
        runnable.add_method('run_postprocessing_event_handlers', ['self'],
                            post_event_handler_code)

        for rn in regime.runs:
            run = regime.runs[rn]
            c = context.lookup_component_ref(run.component)
            if c != None:
                target = self.build_runnable(c, self)
                self.sim.add_runnable(c.id, target)
                self.current_record_target = target
                time_step = context.lookup_parameter(run.increment)
                time_total = context.lookup_parameter(run.total)
                if time_step != None and time_total != None:
                    target.configure_time(time_step.numeric_value,
                                          time_total.numeric_value)
            else:
                raise SimBuildError(('Invalid component reference {0} in '
                                     '<Run>').format(c.id))
Ejemplo n.º 19
0
    def resolve_path(self, path):
        if self.debug: print("Resolving path: %s in %s" % (path, self))
        if path == '':
            return self
        if path == 'this':
            return self
        if path[0] == '/':
            return self.parent.resolve_path(path)
        elif path.find('../') == 0:
            return self.parent.resolve_path(path[3:])
        elif path.find('..') == 0:
            return self.parent
        elif path == 'parent':
            return self.parent
        else:
            if path.find('/') >= 1:
                (child, new_path) = path.split('/', 1)
            else:
                child = path
                new_path = ''

            idxbegin = child.find('[')
            idxend = child.find(']')
            if idxbegin != 0 and idxend > idxbegin:
                idx = int(child[idxbegin + 1:idxend])
                child = child[:idxbegin]
            else:
                idx = -1

            if child in self.children:
                childobj = self.children[child]
                if idx != -1:
                    childobj = childobj.array[idx]
            elif child in self.component.parameters:
                ctx = self.component
                p = ctx.parameters[child]
                return self.resolve_path('../' + p.value)
            elif child in self.__dict__.keys():
                child_resolved = self.__dict__[child]
                #print("Think it's a link from %s to %s"%(child, child_resolved))
                return self.resolve_path('../' + child_resolved)
            else:
                if self.debug:
                    keys = list(self.__dict__.keys())
                    keys.sort()
                    prefix = "--- "
                    print('{0}    Keys for {1}'.format(prefix, self.id))
                    for k in keys:
                        key_str = str(self.__dict__[k])
                        if len(
                                key_str
                        ) > 0 and not key_str == "[]" and not key_str == "{}":
                            print('{0}       {1} -> {2}'.format(
                                prefix, k, key_str))

                raise SimBuildError('Unable to find child \'{0}\' in '
                                    '\'{1}\''.format(child, self.id))

            if new_path == '':
                return childobj
            else:
                return childobj.resolve_path(new_path)
Ejemplo n.º 20
0
    def copy(self):
        """
        Make a copy of this runnable.

        @return: Copy of this runnable.
        @rtype: lems.sim.runnable.Runnable
        """
        if self.debug: print("Coping....." + self.id)
        r = Runnable(self.id, self.component, self.parent)
        copies = dict()

        # Copy simulation time parameters
        r.time_step = self.time_step
        r.time_completed = self.time_completed
        r.time_total = self.time_total

        # Plasticity and state stack (?)
        r.plastic = self.plastic
        r.state_stack = Stack()

        # Copy variables (GG - Faster using the add_* methods?)
        for v in self.instance_variables:
            r.instance_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        for v in self.derived_variables:
            r.derived_variables.append(v)
            r.__dict__[v] = self.__dict__[v]
            r.__dict__[v + '_shadow'] = self.__dict__[v + '_shadow']

        # Copy array elements
        for child in self.array:
            child_copy = child.copy()
            child_copy.parent = r
            r.array.append(child_copy)
            copies[child.uid] = child_copy

        # Copy attachment def
        for att in self.attachments:
            atn = self.attachments[att]
            r.attachments[att] = atn
            r.__dict__[atn] = []

        # Copy children
        for uid in self.uchildren:
            child = self.uchildren[uid]
            child_copy = child.copy()
            child_copy.parent = r
            copies[child.uid] = child_copy

            r.add_child(child_copy.id, child_copy)

            # For typerefs
            try:
                idx = [k for k in self.__dict__
                       if self.__dict__[k] == child][0]
                r.__dict__[idx] = child_copy
            except:
                pass

            # For groups and attachments:
            try:
                idx = [k for k in self.__dict__
                       if child in self.__dict__[k]][0]
                if idx not in r.__dict__:
                    r.__dict__[idx] = []
                r.__dict__[idx].append(child_copy)

            except:
                pass

        # Copy event ports
        for port in self.event_in_ports:
            r.event_in_ports.append(port)
            r.event_in_counters[port] = 0

        for port in self.event_out_ports:
            r.event_out_ports.append(port)
            r.event_out_callbacks[port] = self.event_out_callbacks[port]

        for ec in r.component.structure.event_connections:
            if self.debug:
                print("--- Fixing event_connection: %s in %s" %
                      (ec.toxml(), id(r)))

            source = r.parent.resolve_path(ec.from_)
            target = r.parent.resolve_path(ec.to)

            if ec.receiver:
                # Will throw error...
                receiver_template = self.build_runnable(ec.receiver, target)
                #receiver = copy.deepcopy(receiver_template)
                receiver = receiver_template.copy()
                receiver.id = "{0}__{1}__".format(component.id,
                                                  receiver_template.id)

                if ec.receiver_container:
                    target.add_attachment(receiver, ec.receiver_container)
                target.add_child(receiver_template.id, receiver)
                target = receiver
            else:
                source = r.resolve_path(ec.from_)
                target = r.resolve_path(ec.to)

            source_port = ec.source_port
            target_port = ec.target_port

            if not source_port:
                if len(source.event_out_ports) == 1:
                    source_port = source.event_out_ports[0]
                else:
                    raise SimBuildError(("No source event port "
                                         "uniquely identifiable"
                                         " in '{0}'").format(source.id))
            if not target_port:
                if len(target.event_in_ports) == 1:
                    target_port = target.event_in_ports[0]
                else:
                    raise SimBuildError(("No destination event port "
                                         "uniquely identifiable "
                                         "in '{0}'").format(target))

            if self.debug:
                print(
                    "register_event_out_callback\n   Source: %s, %s (port: %s) \n   -> %s, %s (port: %s)"
                    % (source, id(source), source_port, target, id(target),
                       target_port))
            source.register_event_out_callback(\
                source_port, lambda: target.inc_event_in(target_port))

        # Copy methods
        if getattr(self, "update_kinetic_scheme", None):
            r.update_kinetic_scheme = self.update_kinetic_scheme
        if getattr(self, "run_startup_event_handlers", None):
            r.run_startup_event_handlers = self.run_startup_event_handlers
        if getattr(self, "run_preprocessing_event_handlers", None):
            r.run_preprocessing_event_handlers = self.run_preprocessing_event_handlers
        if getattr(self, "run_postprocessing_event_handlers", None):
            r.run_postprocessing_event_handlers = self.run_postprocessing_event_handlers

        if getattr(self, "update_state_variables", None):
            r.update_state_variables = self.update_state_variables
        if getattr(self, "update_derived_variables", None):
            r.update_derived_variables = self.update_derived_variables
        #r.update_shadow_variables = self.update_shadow_variables
        if getattr(self, "update_derived_parameters", None):
            r.update_derived_parameters = self.update_derived_parameters

        for rn in self.regimes:
            r.add_regime(self.regimes[rn])
        r.current_regime = self.current_regime

        # Copy groups
        for gn in self.groups:
            g = self.__dict__[gn]
            for c in g:
                if c.uid in copies:
                    r.add_child_to_group(gn, copies[c.uid])
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.add_child_to_group(gn, c2)

        # Copy remaining runnable references.
        for k in self.__dict__:
            if k == 'parent':
                continue
            c = self.__dict__[k]
            if isinstance(c, Runnable):
                if c.uid in copies:
                    r.__dict__[k] = copies[c.uid]
                else:
                    c2 = c.copy()
                    c2.parent = r
                    copies[c.uid] = c2
                    r.__dict__[k] = c2

        # Copy text fields
        for k in self.__dict__:
            if not k in r.__dict__:
                c = self.__dict__[k]
                if self.debug:
                    print("Adding remaining field: %s = %s" % (k, c))
                r.__dict__[k] = c

        if self.debug:
            print('########################################')
            keys = list(self.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, self.__dict__[k])
            print('----------------------------------------')
            keys = list(r.__dict__.keys())
            keys.sort()
            print(len(keys))
            for k in keys:
                print(k, r.__dict__[k])
            print('########################################')
            print('')
            print('')
            print('')
            print('')

        if self.debug: print("Finished coping..." + self.id)

        return r
Ejemplo n.º 21
0
    def add_dynamics_1(self, component, runnable, regime, dynamics):
        """
        Adds dynamics to a runnable component based on the dynamics
        specifications in the component model.

        This method builds dynamics necessary for building child components.

        @param component: Component model containing dynamics specifications.
        @type component: lems.model.component.FatComponent

        @param runnable: Runnable component to which dynamics is to be added.
        @type runnable: lems.sim.runnable.Runnable

        @param regime: The dynamics regime to be used to generate
        dynamics code in the runnable component.
        @type regime: lems.model.dynamics.Regime

        @param dynamics: Shared dynamics specifications.
        @type dynamics: lems.model.dynamics.Regime

        @raise SimBuildError: Raised when a time derivative expression refers
        to an undefined variable.

        @raise SimBuildError: Raised when there are invalid time
        specifications for the <Run> statement.

        @raise SimBuildError: Raised when the component reference for <Run>
        cannot be resolved.
        """

        if isinstance(regime, Dynamics) or regime.name == '':
            suffix = ''
        else:
            suffix = '_regime_' + regime.name

        if isinstance(regime, Regime) and regime.initial:
            runnable.new_regime = regime.name

        # Process state variables
        for sv in regime.state_variables:
            runnable.add_instance_variable(sv.name, 0)

        # Process time derivatives
        time_step_code = []
        for td in regime.time_derivatives:
            if td.variable not in regime.state_variables and td.variable not in dynamics.state_variables:
                raise SimBuildError(('Time derivative for undefined state '
                                     'variable {0} in component {1}').format(td.variable, component.id))

            exp = self.build_expression_from_tree(runnable,
                                                  regime,
                                                  td.expression_tree)
            time_step_code += ['self.{0} += dt * ({1})'.format(td.variable,
                                                               exp)]
        runnable.add_method('update_state_variables' + suffix, ['self', 'dt'],
                            time_step_code)

        # Process derived variables
        derived_variable_code = []
        derived_variables_ordering = order_derived_variables(regime)
        for dvn in derived_variables_ordering: #regime.derived_variables:
            if dvn in dynamics.derived_variables:
                dv = dynamics.derived_variables[dvn]
                runnable.add_derived_variable(dv.name)
                if dv.value:
                    derived_variable_code += ['self.{0} = ({1})'.format(
                        dv.name,
                        self.build_expression_from_tree(runnable,
                                                        regime,
                                                        dv.expression_tree))]
                elif dv.select:
                    if dv.reduce:
                        derived_variable_code += self.build_reduce_code(dv.name,
                                                                        dv.select,
                                                                        dv.reduce)
                    else:
                        derived_variable_code += ['self.{0} = (self.{1})'.format(
                            dv.name,
                            dv.select.replace('/', '.'))]
                else:
                    raise SimBuildError(('Inconsistent derived variable settings'
                                         'for {0}').format(dvn))
            elif dvn in dynamics.conditional_derived_variables:
                dv = dynamics.conditional_derived_variables[dvn]
                runnable.add_derived_variable(dv.name)
                derived_variable_code += self.build_conditional_derived_var_code(runnable,
                                                                                 regime,
                                                                                 dv)
            else:
                raise SimBuildError("Unknown derived variable '{0}' in '{1}'",
                                     dvn, runnable.id)
        runnable.add_method('update_derived_variables' + suffix, ['self'],
                            derived_variable_code)

        # Process event handlers
        pre_event_handler_code = []
        post_event_handler_code = []
        startup_event_handler_code = []
        on_entry_added = False
        for eh in regime.event_handlers:
            if isinstance(eh, OnStart):
                startup_event_handler_code += self.build_event_handler(runnable,
                                                                       regime,
                                                                       eh)
            elif isinstance(eh, OnCondition):
                post_event_handler_code += self.build_event_handler(runnable,
                                                                    regime,
                                                                    eh)
            else:
                if isinstance(eh, OnEntry):
                    on_entry_added = True
                pre_event_handler_code += self.build_event_handler(runnable,
                                                                   regime,
                                                                   eh)
        if isinstance(regime, Regime) and not on_entry_added:
            pre_event_handler_code += self.build_event_handler(runnable, regime, OnEntry())
            
        runnable.add_method('run_startup_event_handlers' + suffix, ['self'],
                            startup_event_handler_code)
        runnable.add_method('run_preprocessing_event_handlers' + suffix, ['self'],
                            pre_event_handler_code)
        runnable.add_method('run_postprocessing_event_handlers' + suffix, ['self'],
                            post_event_handler_code)