def add_time_derivative(self, variable, value): """ Adds a state variable to the behavior current object. @param variable: Name of the state variable whose time derivative is being specified. @type variable: string @param value: Time derivative expression. @type value: string @raise ModelError: Raised when the time derivative for this state variable is already defined in this behavior regime. """ if variable in self.time_derivatives: raise ModelError('Duplicate time derivative for ' + variable) self.time_derivatives[variable] = TimeDerivative(variable, value)
def add(self, child): """ Adds a typed child object to the structure object. @param child: Child object to be added. """ if isinstance(child, With): self.add_with(child) elif isinstance(child, EventConnection): self.add_event_connection(child) elif isinstance(child, ChildInstance): self.add_child_instance(child) elif isinstance(child, MultiInstantiate): self.add_multi_instantiate(child) elif isinstance(child, ForEach): self.add_for_each(child) else: raise ModelError('Unsupported child element')
def add_component_ref(self, name, type): """ Adds a component reference to the list of defined component references in the current context. @param name: Name of the component reference. @type name: string @param type: Type of the component reference. @type type: string @raise ModelError: Raised when the component reference is already defined in the current context. """ if name in self.component_refs: raise ModelError("Duplicate component reference '{0}'".format(\ name)) self.component_refs[name] = type
def resolve_component_type(self, component_type): """ Resolves references in the specified component type. @param component_type: Component type to be resolved. @type component_type: lems.model.component.ComponentType """ # Resolve component type from base types if present. if component_type.extends: try: base_ct = self.component_types[component_type.extends] except: raise ModelError("Component type '{0}' trying to extend unknown component type '{1}'", component_type.name, component_type.extends) self.resolve_component_type(base_ct) self.merge_component_types(component_type, base_ct) component_type.types = set.union(component_type.types, base_ct.types) component_type.extends = None
def add_children_def(self, name, type): """ Adds a child object definition to the list of multi-instance child object definitions in the current context. @param name: Name of the child object. @type name: string @param type: Type of the child object. @type type: string @raise ModelError: Raised when the definition is already in the current context. """ if name in self.children_defs: raise ModelError("Duplicate children definition '{0}'".format(\ name)) self.children_defs[name] = type
def add_record(self, quantity, scale, color): """ Adds a record objects to the list of record objects in this behavior regime. @param quantity: Path to the quantity to be recorded @type quantity: string @param scale: Scale of the quantity to be recorded @type scale: string @param color: Color of the quantity to be recorded as a 24-bit hex RGB value (#RRGGBB) @type color: string """ if quantity in self.records: raise ModelError('Duplicate record {0}'.format(quantity)) self.records[quantity] = Record(quantity, scale, color)
def add(self, child): """ Adds a typed child object to the component type. @param child: Child object to be added. """ if isinstance(child, Parameter): self.add_parameter(child) elif isinstance(child, Property): self.add_property(child) elif isinstance(child, DerivedParameter): self.add_derived_parameter(child) elif isinstance(child, IndexParameter): self.add_index_parameter(child) elif isinstance(child, Constant): self.add_constant(child) elif isinstance(child, Exposure): self.add_exposure(child) elif isinstance(child, Requirement): self.add_requirement(child) elif isinstance(child, ComponentRequirement): self.add_component_requirement(child) elif isinstance(child, InstanceRequirement): self.add_instance_requirement(child) elif isinstance(child, Children): self.add_children(child) elif isinstance(child, Text): self.add_text(child) elif isinstance(child, Link): self.add_link(child) elif isinstance(child, Path): self.add_path(child) elif isinstance(child, EventPort): self.add_event_port(child) elif isinstance(child, ComponentReference): self.add_component_reference(child) elif isinstance(child, Attachments): self.add_attachments(child) else: raise ModelError('Unsupported child element')
def add(self, child): """ Adds a typed child object to the model. @param child: Child object to be added. """ if isinstance(child, Dimension): self.add_dimension(child) elif isinstance(child, Unit): self.add_unit(child) elif isinstance(child, ComponentType): self.add_component_type(child) elif isinstance(child, Component): self.add_component(child) elif isinstance(child, FatComponent): self.add_fat_component(child) elif isinstance(child, Constant): self.add_constant(child) else: raise ModelError('Unsupported child element')
def add(self, child): """ Adds a typed child object to the behavioral object. @param child: Child object to be added. """ if isinstance(child, StateVariable): self.add_state_variable(child) elif isinstance(child, DerivedVariable): self.add_derived_variable(child) elif isinstance(child, ConditionalDerivedVariable): self.add_conditional_derived_variable(child) elif isinstance(child, TimeDerivative): self.add_time_derivative(child) elif isinstance(child, EventHandler): self.add_event_handler(child) elif isinstance(child, KineticScheme): self.add_kinetic_scheme(child) else: raise ModelError('Unsupported child element')
def add(self, child): """ Adds a typed child object to the simulation spec. @param child: Child object to be added. """ if isinstance(child, Run): self.add_run(child) elif isinstance(child, Record): self.add_record(child) elif isinstance(child, EventRecord): self.add_event_record(child) elif isinstance(child, DataDisplay): self.add_data_display(child) elif isinstance(child, DataWriter): self.add_data_writer(child) elif isinstance(child, EventWriter): self.add_event_writer(child) else: raise ModelError('Unsupported child element')
def add_state_variable(self, name, exposure, dimension): """ Adds a state variable to the behavior current object. @param name: Name of the state variable. @type name: string @param exposure: Exposed name of the state variable. @type exposure: string @param dimension: Dimension ofthe state variable. @type dimension: string @raise ModelError: Raised when the state variable is already defined in this behavior regime. """ if name in self.state_variables: raise ModelError('Duplicate state variable ' + name) self.state_variables[name] = StateVariable(name, exposure, dimension)
def add_event_port(self, name, direction): """ Adds an event port to the list of event ports handled by this component or component type. @param name: Name of the event port. @type name: string @param direction: Event direction ('in' or 'out'). @type direction: string @raise ModelError: Raised when the definition is already in the current context. """ if name in self.event_in_ports or name in self.event_out_ports: raise ModelError("Duplicate event '{0}'".format(name)) if direction == 'in': self.event_in_ports.append(name) else: self.event_out_ports.append(name)
def __init__(self, name, direction, description=''): """ Constructor. See instance variable documentation for more details on parameters. """ self.name = name """ Name of the event port. @type: str """ d = direction.lower() if d != 'in' and d != 'out': raise ModelError( "Invalid direction '{0}' in event port '{1}'".format( direction, name)) self.direction = direction """ Direction - IN/OUT . @type: str """ self.description = description """ Description of the event port.
def add_run(self, component, variable, increment, total): """ Adds a runnable target component definition to the list of runnable components stored in this context. @param component: Name of the target component to be run. @type component: string @param variable: Name of an indendent state variable used to control the target component (usually time). @type variable: string @param increment: Value by which the control variable is to be incremented in each step. @type increment: string @param total: End value for the control variable. @type total: string """ if component in self.runs: raise ModelError('Duplicate run for ' + component) self.runs[component] = Run(component, variable, increment, total)
def resolve_structure(self, fc, ct): """ Resolve structure specifications. """ if self.debug: print("++++++++ Resolving structure of (%s) with %s" % (fc, ct)) for w in ct.structure.withs: try: if w.instance == 'parent' or w.instance == 'this': w2 = With(w.instance, w.as_) else: w2 = With(fc.paths[w.instance].value, w.as_) except: raise ModelError( "Unable to resolve With parameters for " "'{0}' in component '{1}'", w.as_, fc.id) fc.structure.add(w2) for fe in ct.structure.for_eachs: fc.structure.add_for_each(fe) for ev in ct.structure.event_connections: try: from_inst = fc.structure.withs[ev.from_].instance to_inst = fc.structure.withs[ev.to].instance if self.debug: print("EC..: " + from_inst + " to " + to_inst + " in " + str(fc.paths)) if len(fc.texts) > 0 or len(fc.paths) > 0: source_port = fc.texts[ ev.source_port].value if ev.source_port and len( ev.source_port ) > 0 and ev.source_port in fc.texts else None target_port = fc.texts[ ev.target_port].value if ev.target_port and len( ev.target_port ) > 0 and ev.target_port in fc.texts else None if self.debug: print("sp: %s" % source_port) if self.debug: print("tp: %s" % target_port) receiver = None # TODO: Get more efficient way to find parent comp if '../' in ev.receiver: receiver_id = None parent_attr = ev.receiver[3:] if self.debug: print("Finding %s in the parent of: %s (%i)" % (parent_attr, fc, id(fc))) for comp in self.components.values(): if self.debug: print(" - Checking %s (%i)" % (comp.id, id(comp))) for child in comp.children: if self.debug: print(" - Checking %s (%i)" % (child.id, id(child))) for child2 in child.children: if child2.id == fc.id and child2.type == fc.type and child.id == fc.parent_id: if self.debug: print( " - Got it?: %s (%i), child: %s" % (child.id, id(child), child2)) receiver_id = child.parameters[ parent_attr] if self.debug: print("Got it: " + receiver_id) break if receiver_id is not None: for comp in self.fat_components: if comp.id == receiver_id: receiver = comp if self.debug: print("receiver is: %s" % receiver) if self.debug: print("rec1: %s" % receiver) if not receiver: receiver = fc.component_references[ ev. receiver].referenced_component if ev.receiver else None receiver_container = fc.texts[ ev.receiver_container].value if ( fc.texts and ev.receiver_container) else '' if self.debug: print("rec2: %s" % receiver) if len(receiver_container) == 0: # TODO: remove this hard coded check! receiver_container = 'synapses' else: #if from_inst == 'parent': #par = fc.component_references[ev.receiver] if self.debug: print("+++++++++++++++++++") print(ev.toxml()) print(ev.source_port) print(fc) source_port = ev.source_port target_port = ev.target_port receiver = None receiver_container = None ev2 = EventConnection(from_inst, to_inst, source_port, target_port, receiver, receiver_container) if self.debug: print("Created EC: " + ev2.toxml()) print(receiver) print(receiver_container) except: logging.exception("Something awful happened!") raise ModelError( "Unable to resolve event connection parameters in component '{0}'", fc) fc.structure.add(ev2) for ch in ct.structure.child_instances: try: if self.debug: print(ch.toxml()) if '../' in ch.component: parent = self.get_parent_component(fc) if self.debug: print("Parent: %s" % parent) comp_ref = ch.component[3:] if self.debug: print("comp_ref: %s" % comp_ref) comp_id = parent.parameters[comp_ref] comp = self.fat_components[comp_id] ch2 = ChildInstance(ch.component, comp) else: ref_comp = fc.component_references[ ch.component].referenced_component ch2 = ChildInstance(ch.component, ref_comp) except Exception as e: if self.debug: print(e) raise ModelError( "Unable to resolve child instance parameters for " "'{0}' in component '{1}'", ch.component, fc.id) fc.structure.add(ch2) for mi in ct.structure.multi_instantiates: try: mi2 = MultiInstantiate( fc.component_references[mi.component].referenced_component, int(fc.parameters[mi.number].numeric_value)) except: raise ModelError( "Unable to resolve multi-instantiate parameters for " "'{0}' in component '{1}'", mi.component, fc) fc.structure.add(mi2)
def fatten_component(self, c): """ Fatten a component but resolving all references into the corresponding component type. @param c: Lean component to be fattened. @type c: lems.model.component.Component @return: Fattened component. @rtype: lems.model.component.FatComponent """ if self.debug: print("Fattening %s" % c.id) try: ct = self.component_types[c.type] except: raise ModelError( "Unable to resolve type '{0}' for component '{1}'; existing: {2}", c.type, c.id, self.component_types.keys()) fc = FatComponent(c.id, c.type) if c.parent_id: fc.set_parent_id(c.parent_id) ### Resolve parameters for parameter in ct.parameters: if parameter.name in c.parameters: p = parameter.copy() p.value = c.parameters[parameter.name] p.numeric_value = self.get_numeric_value(p.value, p.dimension) fc.add_parameter(p) elif parameter.fixed: p = parameter.copy() p.numeric_value = self.get_numeric_value(p.value, p.dimension) fc.add_parameter(p) else: raise ModelError( "Parameter '{0}' not initialized for component '{1}'", parameter.name, c.id) ### Resolve derived_parameters for derived_parameter in ct.derived_parameters: derived_parameter2 = derived_parameter.copy() #derived_parameter2.numeric_value = self.get_numeric_value(constant2.value, constant2.dimension) fc.add(derived_parameter2) ### Resolve constants for constant in ct.constants: constant2 = constant.copy() constant2.numeric_value = self.get_numeric_value( constant2.value, constant2.dimension) fc.add(constant2) ### Resolve texts for text in ct.texts: t = text.copy() t.value = c.parameters[ text.name] if text.name in c.parameters else '' fc.add(t) ### Resolve texts for link in ct.links: if link.name in c.parameters: l = link.copy() l.value = c.parameters[link.name] fc.add(l) else: raise ModelError( "Link parameter '{0}' not initialized for component '{1}'", link.name, c.id) ### Resolve paths for path in ct.paths: if path.name in c.parameters: p = path.copy() p.value = c.parameters[path.name] fc.add(p) else: raise ModelError( "Path parameter '{0}' not initialized for component '{1}'", path.name, c.id) ### Resolve component references. for cref in ct.component_references: if cref.name in c.parameters: cref2 = cref.copy() cid = c.parameters[cref.name] if cid not in self.fat_components: self.add(self.fatten_component(self.components[cid])) cref2.referenced_component = self.fat_components[cid] fc.add(cref2) else: raise ModelError( "Component reference '{0}' not initialized for component '{1}'", cref.name, c.id) merge_maps(fc.exposures, ct.exposures) merge_maps(fc.requirements, ct.requirements) merge_maps(fc.children, ct.children) merge_maps(fc.texts, ct.texts) merge_maps(fc.links, ct.links) merge_maps(fc.paths, ct.paths) merge_maps(fc.event_ports, ct.event_ports) merge_maps(fc.attachments, ct.attachments) fc.dynamics = ct.dynamics.copy() if len(fc.dynamics.regimes) != 0: fc.dynamics.clear() self.resolve_structure(fc, ct) self.resolve_simulation(fc, ct) fc.types = ct.types ### Resolve children for child in c.children: fc.add(self.fatten_component(child)) return fc
def resolve_simulation(self, fc, ct): """ Resolve simulation specifications. """ for run in ct.simulation.runs: try: run2 = Run( fc.component_references[ run.component].referenced_component, run.variable, fc.parameters[run.increment].numeric_value, fc.parameters[run.total].numeric_value) except: raise ModelError( "Unable to resolve simulation run parameters in component '{0}'", fc.id) fc.simulation.add(run2) for record in ct.simulation.records: try: record2 = Record( fc.paths[record.quantity].value, fc.parameters[record.scale].numeric_value if record.scale else 1, fc.texts[record.color].value if record.color else '#000000') except: raise ModelError( "Unable to resolve simulation record parameters in component '{0}'", fc.id) fc.simulation.add(record2) for event_record in ct.simulation.event_records: try: event_record2 = EventRecord( fc.paths[event_record.quantity].value, fc.texts[event_record.eventPort].value) except: raise ModelError( "Unable to resolve simulation event_record parameters in component '{0}'", fc.id) fc.simulation.add(event_record2) for dd in ct.simulation.data_displays: try: dd2 = DataDisplay(fc.texts[dd.title].value, '') if 'timeScale' in fc.parameters: dd2.timeScale = fc.parameters['timeScale'].numeric_value except: raise ModelError( "Unable to resolve simulation display parameters in component '{0}'", fc.id) fc.simulation.add(dd2) for dw in ct.simulation.data_writers: try: path = '.' if fc.texts[dw.path] and fc.texts[dw.path].value: path = fc.texts[dw.path].value dw2 = DataWriter(path, fc.texts[dw.file_name].value) except: raise ModelError( "Unable to resolve simulation writer parameters in component '{0}'", fc.id) fc.simulation.add(dw2) for ew in ct.simulation.event_writers: try: path = '.' if fc.texts[ew.path] and fc.texts[ew.path].value: path = fc.texts[ew.path].value ew2 = EventWriter(path, fc.texts[ew.file_name].value, fc.texts[ew.format].value) except: raise ModelError( "Unable to resolve simulation writer parameters in component '{0}'", fc.id) fc.simulation.add(ew2)