Beispiel #1
0
    def test_load_get_dom(self):
        
        model = Model()

        file_name = 'lems/test/hhcell_resaved2.xml'

        model.import_from_file(file_name)

        dom0 = model.export_to_dom()
Beispiel #2
0
def load_model(model_filename, folder=None):
    "Load model from filename"

    fp_xml = lems_file(model_filename, folder)

    model = Model()
    model.import_from_file(fp_xml)
    # modelextended = model.resolve()

    return model
Beispiel #3
0
    def load_model(self):
        "Load model from filename"

        # instantiate LEMS lib
        model = Model()
        model.import_from_file(self.xml_location)

        self.XSD_validate_XML()

        # Do some preprocessing on the template to easify rendering
        self.pp_pow(model)
        noisepresent, nsigpresent = self.pp_noise(model)
        couplinglist = self.pp_cplist(model)
        svboundaries = self.pp_bound(model)

        return model, svboundaries, couplinglist, noisepresent, nsigpresent
def get_component_types(srcdir):
    """Obtain a list of all defined component types.


    Does not return anything. Fills global variables.
    It works in two stages.

    First, from the XML comp_definition files, we read all the models and get the required metadata:
    - names,
    - the xml source file in which it is defined,
    - description of the component.

    Next, we read all the XML files to get an ordered list of components.

    We get this list by reading the XML files and parsing them rather than
    using the LEMS API used above because the LEMS API does not guarantee what
    order the components will be returned in. By using the file as the source
    here, we ensure that we get the component list in the same order in which
    they are defined in the XML file.

    :returns: nothing

    """
    for comp_definition in comp_definitions:
        fullpath = "{}/{}.xml".format(srcdir, comp_definition)
        """Stage 1"""
        model = Model(include_includes=False)
        model.import_from_file(fullpath)

        for comp_type in model.component_types:
            comp_types[comp_type.name] = comp_type
            comp_type_src[comp_type.name] = comp_definition
            comp_type_desc[
                comp_type.
                name] = comp_type.description if comp_type.description is not None else "ComponentType: " + comp_type.name
        """Stage 2"""
        ordered_comp_type_list = []
        with open(fullpath) as fp:
            for line in fp:
                s = '<ComponentType name='
                if s in line:
                    i = line.index(s)
                    e = line.find('"', i + len(s) + 1)
                    comp_type_defined = line[i + len(s) + 1:e]
                    ordered_comp_type_list.append(comp_type_defined)
        ordered_comp_types[comp_definition] = ordered_comp_type_list
Beispiel #5
0
def main():
    """
    Program entry point.
    """

    args = process_args()

    print('Parsing and resolving model: ' + args.lems_file)
    model = Model()
    if args.I is not None:
        for dir in args.I:
            model.add_include_directory(dir)
    model.import_from_file(args.lems_file)

    resolved_model = model.resolve()

    print('Building simulation')
    sim = SimulationBuilder(resolved_model).build()
    #sim.dump("Afterbuild:")

    if args.dlems:
        print('Exporting as: ' + dlems_info)

        from lems.dlems.exportdlems import export_component

        target = model.targets[0]

        sim_comp = model.components[target]

        target_net = sim_comp.parameters['target']

        target_comp = model.components[target_net]

        dlems_file_name = args.lems_file.replace('.xml', '.json')
        if dlems_file_name == args.lems_file:
            dlems_file_name = args.lems_file + '.json'

        if target_comp.type == 'network':

            for child in target_comp.children:

                if child.type == 'population':

                    comp = model.components[child.parameters['component']]

                    export_component(model,
                                     comp,
                                     sim_comp,
                                     child.id,
                                     file_name=dlems_file_name)
        else:
            export_component(model, sim_comp, target_comp)

    else:
        print('Running simulation')
        sim.run()

        process_simulation_output(sim, args)
Beispiel #6
0
    def test_load_write_xml(self):
        
        model = Model()

        file_name = 'lems/test/hhcell_resaved2.xml'

        model.import_from_file(file_name)

        file_name2 = 'lems/test/hhcell_resaved3.xml'
        model.export_to_file(file_name2)

        print("----------------------------------------------")
        print(open(file_name2,'r').read())
        print("----------------------------------------------")

        print("Written generated LEMS to %s"%file_name2)

        from lems.base.util import validate_lems

        validate_lems(file_name2)
Beispiel #7
0
def main(args=None):
    """
    Program entry point.
    """
    
    if args is None:
        args = process_args()
    
    print('Parsing and resolving model: '+args.lems_file)
    model = Model()
    if args.I is not None:
        for dir in args.I:
            model.add_include_directory(dir)
    model.import_from_file(args.lems_file)
    
    resolved_model = model.resolve()
    
    print('Building simulation')
    sim = SimulationBuilder(resolved_model).build()
    #sim.dump("Afterbuild:")

    if args.dlems:
        print('Exporting as: '+dlems_info)
        
        from lems.dlems.exportdlems import export_component
        
        target = model.targets[0]

        sim_comp = model.components[target]

        target_net = sim_comp.parameters['target']

        target_comp = model.components[target_net]
        
        dlems_file_name = args.lems_file.replace('.xml', '.json')
        if dlems_file_name == args.lems_file:
            dlems_file_name = args.lems_file + '.json'

        if target_comp.type == 'network':

            for child in target_comp.children:

                if child.type == 'population':

                    comp =  model.components[child.parameters['component']]

                    export_component(model, comp, sim_comp, child.id, file_name=dlems_file_name)
        else:
            export_component(model, sim_comp, target_comp)
    
    else:
        print('Running simulation')
        sim.run()
        process_simulation_output(sim, model, args)
def validate_model(filename, name=None, config=None):
    """ Check that a model is valid

    Args:
        filename (:obj:`str`): path to model
        name (:obj:`str`, optional): name of model for use in error messages
        config (:obj:`Config`, optional): whether to fail on missing includes

    Returns:
        :obj:`tuple`:

            * nested :obj:`list` of :obj:`str`: nested list of errors (e.g., required ids missing or ids not unique)
            * nested :obj:`list` of :obj:`str`: nested list of errors (e.g., required ids missing or ids not unique)
            * :obj:`Model`: model
    """
    config = config or get_config()

    errors = []
    warnings = []
    model = None

    with StandardOutputErrorCapturer(relay=False, level=StandardOutputErrorCapturerLevel.c):
        valid, output = validate_neuroml2_lems_file(filename, exit_on_fail=False, return_string=True)
        if not valid:
            errors.append(['`{}` is not a valid LEMS file.'.format(filename), [[output]]])
            return (errors, warnings, model)

    core_types_dir = tempfile.mkdtemp()
    jar_filename = get_path_to_jnml_jar()
    with zipfile.ZipFile(jar_filename, 'r') as jar_file:
        neuroml2_core_type_members = (name for name in jar_file.namelist() if name.startswith('NeuroML2CoreTypes/'))
        jar_file.extractall(core_types_dir, members=neuroml2_core_type_members)

    model = Model(include_includes=True, fail_on_missing_includes=config.VALIDATE_IMPORTED_MODEL_FILES)
    model.add_include_directory(os.path.join(core_types_dir, 'NeuroML2CoreTypes'))
    model.import_from_file(filename)
    shutil.rmtree(core_types_dir)

    return (errors, warnings, model)
Beispiel #9
0
class LEMSParser(Parser):
    """
    Parser for LEMS files
    """

    base_path = "."
    """ Base path for the file being parsed
    @type: string """

    model = None
    """ Model built during parsing
    @type: lems.model.model.model """

    tag_parse_table = None
    """ Dictionary of xml tags to parse methods
    @type: dict(string -> function) """

    valid_children = None
    """ Dictionary mapping each tag to it's list of valid child tags.
    @type: dict(string -> string) """

    context_stack = []
    """ Stack of contexts used for handling nested contexts.
    @type: list(lems.model.context.Context) """

    current_context = None
    """ Currently active (being parsed) context.
    @type: lems.model.context.Context """

    component_type_stack = []
    """ Stack of component type objects used for handling nested
    component types.
    @type: list(lems.model.parameter.ComponentType) """

    current_component_type = None
    """ Component type object being parsed.
    @type: lems.model.parameter.ComponentType """

    current_regime = None
    """ Current behavior regime being parsed.
    @type: lems.model.behavior.Regime """

    current_event_handler = None
    """ Current event_handler being parsed.
    @type: lems.model.behavior.EventHandler """

    current_structure = None
    """ Current structure being parsed.
    @type: lems.model.structure.Structure """

    xml_node_stack = []
    """ XML node stack.
    @type: list(xml.etree.Element) """

    def push_context(self, context):
        self.context_stack = [context] + self.context_stack
        self.current_context = context

    def pop_context(self):
        if len(self.context_stack) == 0:
            self.raise_error("Context stack underflow")
        self.context_stack = self.context_stack[1:]
        if len(self.context_stack) == 0:
            self.current_context = None
        else:
            self.current_context = self.context_stack[0]

    def push_component_type(self, component_type):
        self.component_type_stack = [component_type] + self.component_type_stack
        self.current_component_type = component_type

    def pop_component_type(self):
        if len(self.component_type_stack) == 0:
            self.raise_error("Component_Type stack underflow")
        self.component_type_stack = self.component_type_stack[1:]
        if len(self.component_type_stack) == 0:
            self.current_component_type = None
        else:
            self.current_component_type = self.component_type_stack[0]

    def init_parser(self):
        """
        Initializes the parser
        """

        self.model = Model()
        self.token_list = None
        self.prev_token_lists = None

        self.valid_children = dict()
        self.valid_children["lems"] = ["component", "componenttype", "defaultrun", "dimension", "include", "unit"]
        self.valid_children["componenttype"] = [
            "behavior",
            "behaviour",
            "child",
            "children",
            "componentref",
            "exposure",
            "eventport",
            "fixed",
            "link",
            "parameter",
            "path",
            "requirement",
            "structure",
            "text",
        ]
        self.valid_children["behavior"] = [
            "derivedvariable",
            "oncondition",
            "onentry",
            "onevent",
            "onstart",
            "record",
            "run",
            "show",
            "statevariable",
            "timederivative",
        ]
        self.valid_children["oncondition"] = ["eventout", "stateassignment"]
        self.valid_children["onentry"] = ["eventout", "stateassignment"]
        self.valid_children["onevent"] = ["eventout", "stateassignment"]
        self.valid_children["onstart"] = ["eventout", "stateassignment"]
        self.valid_children["structure"] = ["childinstance", "eventconnection", "foreach", "multiinstantiate"]

        self.tag_parse_table = dict()
        self.tag_parse_table["behavior"] = self.parse_behavior
        self.tag_parse_table["child"] = self.parse_child
        self.tag_parse_table["childinstance"] = self.parse_child_instance
        self.tag_parse_table["children"] = self.parse_children
        self.tag_parse_table["component"] = self.parse_component
        self.tag_parse_table["componentref"] = self.parse_component_ref
        self.tag_parse_table["componenttype"] = self.parse_component_type
        self.tag_parse_table["defaultrun"] = self.parse_default_run
        self.tag_parse_table["derivedvariable"] = self.parse_derived_variable
        self.tag_parse_table["dimension"] = self.parse_dimension
        self.tag_parse_table["eventconnection"] = self.parse_event_connection
        self.tag_parse_table["eventout"] = self.parse_event_out
        self.tag_parse_table["eventport"] = self.parse_event_port
        self.tag_parse_table["exposure"] = self.parse_exposure
        self.tag_parse_table["fixed"] = self.parse_fixed
        self.tag_parse_table["foreach"] = self.parse_foreach
        self.tag_parse_table["include"] = self.parse_include
        self.tag_parse_table["link"] = self.parse_link
        self.tag_parse_table["multiinstantiate"] = self.parse_multi_instantiate
        self.tag_parse_table["oncondition"] = self.parse_on_condition
        self.tag_parse_table["onevent"] = self.parse_on_event
        self.tag_parse_table["onstart"] = self.parse_on_start
        self.tag_parse_table["parameter"] = self.parse_parameter
        self.tag_parse_table["path"] = self.parse_path
        self.tag_parse_table["record"] = self.parse_record
        self.tag_parse_table["requirement"] = self.parse_requirement
        self.tag_parse_table["run"] = self.parse_run
        self.tag_parse_table["show"] = self.parse_show
        self.tag_parse_table["stateassignment"] = self.parse_state_assignment
        self.tag_parse_table["statevariable"] = self.parse_state_variable
        self.tag_parse_table["structure"] = self.parse_structure
        self.tag_parse_table["text"] = self.parse_text
        self.tag_parse_table["timederivative"] = self.parse_time_derivative
        self.tag_parse_table["unit"] = self.parse_unit

        def counter():
            count = 1
            while True:
                yield count
                count = count + 1

        self.id_counter = counter()
        """ Counter genertor for generating unique ids.
        @type: int """

    prefix = ""

    def process_nested_tags(self, node):
        """
        Process child tags.

        @param node: Current node being parsed.
        @type node: xml.etree.Element

        @raise ParseError: Raised when an unexpected nested tag is found.
        """

        # self.prefix += '  '

        for child in node:
            # print self.prefix, child.tag,
            # print child.attrib['name'] if 'name' in child.attrib else '',
            # print child.attrib['id'] if 'id' in child.attrib else ''

            self.xml_node_stack = [child] + self.xml_node_stack

            ctagl = child.tag.lower()

            if ctagl in self.tag_parse_table:
                self.tag_parse_table[ctagl](child)
            else:
                self.parse_component_by_typename(child, child.tag)

            self.xml_node_stack = self.xml_node_stack[1:]

        # self.prefix = self.prefix[2:]

    def resolve_typename(self, typename):
        """ 
        Resolves type name from the contex stack.

        @param typename: Name of the type to be resolved.
        @type typename: string

        @return: Component type corresponding to the type name or None if
        undefined.
        @rtype: lems.model.component.ComponentType
        """

        stack = self.context_stack
        found = False
        while stack != [] and (not found):
            if typename in stack[0].component_types:
                found = True

        if found:
            return stack[0].component_types[typename]
        else:
            return None

    def resolve_component_name(self, component_name):
        """ 
        Resolves component name from the contex stack.

        @param component_name: Name of the component to be resolved.
        @type component_name: string

        @return: Component corresponding to the name or None if undefined.
        @rtype: lems.model.component.Component
        """

        stack = self.context_stack
        found = False
        while stack != [] and (not found):
            if component_name in stack[0].components:
                found = True

        if found:
            return stack[0].components[component_name]
        else:
            return None

    def raise_error(self, message):
        s = "Parser error in "

        self.xml_node_stack.reverse()
        if len(self.xml_node_stack) > 1:
            node = self.xml_node_stack[0]
            s += "<{0}".format(node.tag)
            if "name" in node.lattrib:
                s += ' name="{0}"'.format(node.lattrib["name"])
            if "id" in node.lattrib:
                s += ' id="{0}"'.format(node.lattrib["id"])
            s += ">"

        for node in self.xml_node_stack[1:]:
            s += ".<{0}".format(node.tag)
            if "name" in node.lattrib:
                s += ' name="{0}"'.format(node.lattrib["name"])
            if "id" in node.lattrib:
                s += ' id="{0}"'.format(node.lattrib["id"])
            s += ">"

        s += ":\n  " + message

        raise ParseError(s)

        self.xml_node_stack.reverse()

    def get_model(self):
        """
        Returns the generated model.

        @return: The generated model.
        @rtype: lems.model.model.Model
        """

        return self.model

    def parse_behavior(self, node):
        """
        Parses <Behavior>

        @param node: Node containing the <Behaviour> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Behavior must be defined inside a " + "component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            name = ""

        self.current_context.add_behavior_profile(name)

        old_regime = self.current_regime
        self.current_regime = self.current_context.selected_behavior_profile.default_regime

        self.process_nested_tags(node)

        self.current_regime = old_regime

    ## def parse_build(self, node):
    ##     """
    ##     Parses <Build>

    ##     @param node: Node containing the <Build> element
    ##     @type node: xml.etree.Element
    ##     """

    ##     pass

    def parse_child(self, node):
        """
        Parses <Child>

        @param node: Node containing the <Child> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Child definitions can only be made in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("<Child> must specify a name for the " + "reference.")

        if "type" in node.lattrib:
            type = node.lattrib["type"]
        else:
            self.raise_error("<Child> must specify a type for the " + "reference.")

        self.current_context.add_child_def(name, type)

    def parse_child_instance(self, node):
        """
        Parses <ChildInstance>

        @param node: Node containing the <ChildInstance> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error("Child instantiations can only be made within " + "a structure definition")

        if "component" in node.lattrib:
            component = node.lattrib["component"]
        else:
            self.raise_error("<ChildInstance> must specify a component " "reference")

        self.current_structure.add_single_child_def(component)

    def parse_children(self, node):
        """
        Parses <Children>

        @param node: Node containing the <Children> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Children definitions can only be made in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("<Children> must specify a name for the " + "reference.")

        if "type" in node.lattrib:
            type = node.lattrib["type"]
        else:
            self.raise_error("<Children> must specify a type for the " + "reference.")

        self.current_context.add_children_def(name, type)

    def parse_component_by_typename(self, node, type):
        """
        Parses components defined directly by component name.

        @param node: Node containing the <Component> element
        @type node: xml.etree.Element

        @param type: Type of this component.
        @type type: string

        @raise ParseError: Raised when the component does not have an id.
        """

        if self.current_context.context_type == Context.GLOBAL:
            # Global component instatiation
            if "id" in node.lattrib:
                id = node.lattrib["id"]
            else:
                self.raise_error("Component must have an id")

            type = node.tag

            component = Component(id, self.current_context, type, None)

            self.current_context.add_component(component)

        else:
            # Child instantiation

            if "id" in node.lattrib:
                id = node.lattrib["id"]
                type = node.tag
            else:
                id = node.tag
                type = "__type_inherited__"

            component = Component(id, self.current_context, type)

            self.current_context.add_child(component)

        for key in node.attrib:
            if key.lower() not in ["extends", "id", "type"]:
                param = Parameter(key, "__dimension_inherited__")
                param.set_value(node.attrib[key])
                component.add_parameter(param)

        self.push_context(component.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_component(self, node):
        """
        Parses <Component>

        @param node: Node containing the <ComponentType> element
        @type node: xml.etree.Element
        """

        if "id" in node.lattrib:
            id = node.lattrib["id"]
        else:
            self.raise_error("Component must have an id")

        if "type" in node.lattrib:
            type = node.lattrib["type"]
        else:
            type = None

        if type == None:
            if "extends" in node.lattrib:
                extends = node.lattrib["extends"]
            else:
                self.raise_error("Component must have a type or must " + "extend another component")
        else:
            extends = None

        component = Component(id, self.current_context, type, extends)
        self.current_context.add_component(component)

        for key in node.attrib:
            if key.lower() not in ["extends", "id", "type"]:
                param = Parameter(key, "__dimension_inherited__")
                param.set_value(node.attrib[key])
                component.add_parameter(param)

        self.push_context(component.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_component_ref(self, node):
        """
        Parses <ComponentRef>

        @param node: Node containing the <ComponentTypeRef> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Component references can only be defined in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("<ComponentRef> must specify a name for the " + "reference.")

        if "type" in node.lattrib:
            type = node.lattrib["type"]
        else:
            self.raise_error("<ComponentRef> must specify a type for the " + "reference.")

        self.current_context.add_component_ref(name, type)

    def parse_component_type(self, node):
        """
        Parses <ComponentType>

        @param node: Node containing the <ComponentType> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the component type does not have a
        name.
        """

        try:
            name = node.lattrib["name"]
        except:
            self.raise_error("Component type must have a name")

        if "extends" in node.lattrib:
            extends = node.lattrib["extends"]
        else:
            extends = None

        component_type = ComponentType(name, self.current_context, extends)
        self.current_context.add_component_type(component_type)

        self.push_context(component_type.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_default_run(self, node):
        """
        Parses <DefaultRun>

        @param node: Node containing the <DefaultRun> element
        @type node: xml.etree.Element
        """

        self.model.add_default_run(node.lattrib["component"])

    def parse_derived_variable(self, node):
        """
        Parses <DerivedVariable>

        @param node: Node containing the <DerivedVariable> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<DerivedVariable> must be defined inside a " + "behavior profile or regime")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("A derived variable must have a name")

        if "exposure" in node.lattrib:
            exposure = node.lattrib["exposure"]
        else:
            exposure = None

        if "dimension" in node.lattrib:
            dimension = node.lattrib["dimension"]
        else:
            dimension = None

        if "value" in node.lattrib:
            value = node.lattrib["value"]
        else:
            value = None

        if "select" in node.lattrib:
            select = node.lattrib["select"]
        else:
            select = None

        if "reduce" in node.lattrib:
            reduce = node.lattrib["reduce"]
        else:
            reduce = None

        self.current_regime.add_derived_variable(name, exposure, dimension, value, select, reduce)

    def parse_dimension(self, node):
        """
        Parses <Dimension>

        @param node: Node containing the <Dimension> element
        @type node: xml.etree.Element

        @raise ParseError: When the name is not a string or if the
        dimension is not a signed integer.
        """

        dim = list()
        try:
            name = node.lattrib["name"]
            for d in ["l", "m", "t", "i", "k", "c", "n"]:
                dim.append(int(node.lattrib.get(d, 0)))
        except:
            self.raise_error("Invalid dimensionality format")

        self.model.add_dimension(Dimension(name, dim[0], dim[1], dim[2], dim[3], dim[4], dim[4], dim[6]))

    def parse_event_out(self, node):
        """
        Parses <EventOut>

        @param node: Node containing the <EventOut> element
        @type node: xml.etree.Element
        """

        if self.current_event_handler == None:
            self.raise_error("<EventOut> must be defined inside an " + "event handler in a behavior profile or regime")

        if "port" in node.lattrib:
            port = node.lattrib["port"]
        else:
            self.raise_error("'port' attribute not provided for " + "<StateAssignment>")

        action = EventOut(port)

        self.current_event_handler.add_action(action)

    def parse_event_connection(self, node):
        """
        Parses <EventConnection>

        @param node: Node containing the <EventConnection> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error("<EventConnection> must be defined inside a " + "structure definition")

        if "from" in node.lattrib:
            from_ = node.lattrib["from"]
        else:
            self.raise_error("'from' attribute not provided for " + "<EventConnection>")

        if "to" in node.lattrib:
            to = node.lattrib["to"]
        else:
            self.raise_error("'to' attribute not provided for " + "<EventConnection>")

        self.current_structure.add_event_connection(from_, to)

    def parse_event_port(self, node):
        """
        Parses <EventPort>

        @param node: Node containing the <EventPort> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Event ports can only be defined in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error(("<EventPort> must specify a name for the " "event port"))

        if "direction" in node.lattrib:
            direction = node.lattrib["direction"]
        else:
            self.raise_error(("<EventPort> must specify a direction for the " "event port"))

        direction = direction.lower()
        if direction != "in" and direction != "out":
            self.raise_error(("Event port direction must be 'in' " "or 'out'"))

        self.current_context.add_event_port(name, direction)

    def parse_exposure(self, node):
        """
        Parses <Exposure>

        @param node: Node containing the <Exposure> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the exposure name is not
        being defined in the context of a component type.
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Exposure names can only be defined in " + "a component type")

        if "name" in node.lattrib:
            self.current_context.add_exposure(node.lattrib["name"])

    def parse_fixed(self, node):
        """
        Parses <Fixed>

        @param node: Node containing the <Fixed> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when
        """

        try:
            parameter = node.lattrib["parameter"]
        except:
            self.raise_error("Parameter to be fixed must be specified")

        try:
            value = node.lattrib["value"]
        except:
            self.raise_error("Value to be fixed must be specified")

        if self.current_context.lookup_parameter(parameter) == None:
            self.current_context.add_parameter(Parameter(parameter, "__dimension_inherited__"))
        self.current_context.lookup_parameter(parameter).fix_value(value)

    def parse_foreach(self, node):
        """
        Parses <ForEach>

        @param node: Node containing the <ForEach> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error("<ForEach> can only be made within " + "a structure definition")

        if "instances" in node.lattrib:
            target = node.lattrib["instances"]
        else:
            self.raise_error("<ForEach> must specify a reference to target" "instances")

        if "as" in node.lattrib:
            name = node.lattrib["as"]
        else:
            self.raise_error("<ForEach> must specify a name for the " "enumerated target instances")

        old_structure = self.current_structure
        self.current_structure = self.current_structure.add_foreach(name, target)

        self.process_nested_tags(node)

        self.current_structure = old_structure

    def parse_include(self, node):
        """
        Parses <Include>

        @param node: Node containing the <Include> element
        @type node: xml.etree.Element
        """

        if "file" not in node.lattrib:
            self.raise_error("Include file must be specified.")

        path = self.base_path + "/" + node.lattrib["file"]

        root = xml.parse(path).getroot()
        xmltolower(root)

        self.parse_root(root)

    def parse_link(self, node):
        """
        Parses <Link>

        @param node: Node containing the <Link> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Link variables can only be defined in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("A name must be provided for <Link>")

        if "type" in node.lattrib:
            type = node.lattrib["type"]
        else:
            type = None

        self.current_context.add_link_var(name, type)

    def parse_multi_instantiate(self, node):
        """
        Parses <MultiInstantiate>

        @param node: Node containing the <MultiInstantiate> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error("Child instantiations can only be made within " + "a structure definition")

        if "component" in node.lattrib:
            component = node.lattrib["component"]
        else:
            self.raise_error("<MultiInstantiate> must specify a component " "reference")

        if "number" in node.lattrib:
            number = node.lattrib["number"]
        else:
            self.raise_error("<MultiInstantiate> must specify a number")

        self.current_structure.add_multi_child_def(component, number)

    def parse_on_condition(self, node):
        """
        Parses <OnCondition>

        @param node: Node containing the <OnCondition> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<OnCondition> must be defined inside a " + "behavior profile or regime")

        if "test" in node.lattrib:
            test = node.lattrib["test"]
        else:
            self.raise_error("Test expression required for <OnCondition>")

        event_handler = OnCondition(test)

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_entry(self, node):
        """
        Parses <OnEntry>

        @param node: Node containing the <OnEntry> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<OnEvent> must be defined inside a " + "behavior profile or regime")

        event_handler = OnEntry()

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_event(self, node):
        """
        Parses <OnEvent>

        @param node: Node containing the <OnEvent> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<OnEvent> must be defined inside a " + "behavior profile or regime")

        if "port" in node.lattrib:
            port = node.lattrib["port"]
        else:
            self.raise_error("Port name required for <OnCondition>")

        event_handler = OnEvent(port)

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_start(self, node):
        """
        Parses <OnStart>

        @param node: Node containing the <OnStart> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<OnEvent> must be defined inside a " + "behavior profile or regime")

        event_handler = OnStart()

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_parameter(self, node):
        """
        Parses <Parameter>

        @param node: Node containing the <Parameter> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the parameter does not have a name.
        @raise ParseError: Raised when the parameter does not have a
        dimension.
        """

        try:
            name = node.lattrib["name"]
        except:
            self.raise_error("Parameter must have a name")

        try:
            dimension = node.lattrib["dimension"]
        except:
            self.raise_error("Parameter must have a dimension")

        parameter = Parameter(name, dimension)

        self.current_context.add_parameter(parameter)

    def parse_path(self, node):
        """
        Parses <Path>

        @param node: Node containing the <Path> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Path variables can only be defined in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("A name must be provided for <Path>")

        if "value" in node.lattrib:
            value = node.lattrib["value"]
        else:
            value = None

        self.current_context.add_path_var(name, value)

    def parse_record(self, node):
        """
        Parses <Record>

        @param node: Node containing the <Record> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<Record> must be only be used inside a " + "behavior profile or regime")

        if "quantity" in node.lattrib:
            quantity = node.lattrib["quantity"]
        else:
            self.raise_error("'quantity' attribute required for <Text>")

        if "scale" in node.lattrib:
            scale = node.lattrib["scale"]
        else:
            self.raise_error("'scale' attribute required for <Text>")

        if "color" in node.lattrib:
            color = node.lattrib["color"]
        else:
            self.raise_error("'color' attribute required for <Text>")

        self.current_regime.add_record(quantity, scale, color)

    def parse_requirement(self, node):
        """
        Parses <Requirement>

        @param node: Node containing the <Requirement> element
        @type node: xml.etree.Element
        """

        pass

    def parse_run(self, node):
        """
        Parses <Run>

        @param node: Node containing the <Run> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error("<Run> must be defined inside a " + "behavior profile or regime")

        if "component" in node.lattrib:
            component = node.lattrib["component"]
        else:
            self.raise_error("<Run> must specify a target component")

        if "variable" in node.lattrib:
            variable = node.lattrib["variable"]
        else:
            self.raise_error("<Run> must specify a state variable")

        if "increment" in node.lattrib:
            increment = node.lattrib["increment"]
        else:
            self.raise_error("<Run> must specify an increment for the " + "state variable")

        if "total" in node.lattrib:
            total = node.lattrib["total"]
        else:
            self.raise_error("<Run> must specify a final value for the " + "state variable")

        self.current_regime.add_run(component, variable, increment, total)

    def parse_show(self, node):
        """
        Parses <Show>

        @param node: Node containing the <Show> element
        @type node: xml.etree.Element
        """

        pass

    def parse_state_assignment(self, node):
        """
        Parses <StateAssignment>

        @param node: Node containing the <StateAssignment> element
        @type node: xml.etree.Element
        """

        if self.current_event_handler == None:
            self.raise_error(
                "<StateAssignment> must be defined inside an " + "event handler in a behavior profile or regime"
            )

        if "variable" in node.lattrib:
            variable = node.lattrib["variable"]
        else:
            self.raise_error("'variable' attribute not provided for " + "<StateAssignment>")

        if "value" in node.lattrib:
            value = node.lattrib["value"]
        else:
            self.raise_error("'value' attribute not provided for " + "<StateAssignment>")

        action = StateAssignment(variable, value)

        self.current_event_handler.add_action(action)

    def parse_state_variable(self, node):
        """
        Parses <StateVariable>

        @param node: Node containing the <StateVariable> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the state variable is not
        being defined in the context of a component type.
        """

        if self.current_regime == None:
            self.raise_error("<StateVariable> must be defined inside a " + "behavior profile or regime")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("A state variable must have a name")

        if "exposure" in node.lattrib:
            exposure = node.lattrib["exposure"]
        else:
            exposure = None

        if "dimension" in node.lattrib:
            dimension = node.lattrib["dimension"]
        else:
            self.raise_error("A state variable must have a dimension")

        self.current_regime.add_state_variable(name, exposure, dimension)

    def parse_structure(self, node):
        """
        Parses <Structure>

        @param node: Node containing the <Structure> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Structure must be defined inside a " + "component type")

        old_structure = self.current_structure
        self.current_structure = self.current_context.structure

        self.process_nested_tags(node)

        self.current_structure = old_structure

    def parse_text(self, node):
        """
        Parses <Text>

        @param node: Node containing the <Text> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Text variables can only be defined in " + "a component type")

        if "name" in node.lattrib:
            name = node.lattrib["name"]
        else:
            self.raise_error("A name must be provided for <Text>")

        if "value" in node.lattrib:
            value = node.lattrib["value"]
        else:
            value = None

        self.current_context.add_text_var(name, value)

    def parse_time_derivative(self, node):
        """
        Parses <TimeDerivative>

        @param node: Node containing the <TimeDerivative> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the time derivative is not
        being defined in the context of a component type.
        """

        if self.current_regime == None:
            self.raise_error("<TimeDerivative> must be defined inside a " + "behavior profile or regime")

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error("Time derivatives can only be defined in " + "a component type")

        if "variable" in node.lattrib:
            name = node.lattrib["variable"]
        else:
            self.raise_error("The state variable being differentiated wrt " + "time must be specified")

        if "value" in node.lattrib:
            value = node.lattrib["value"]
        else:
            self.raise_error("The time derivative expression must be " + "provided")

        self.current_regime.add_time_derivative(name, value)

    def parse_unit(self, node):
        """
        Parses <Unit>

        @param node: Node containing the <Unit> element
        @type node: xml.etree.Element

        @raise ParseError: When the name is not a string or the unit
        specfications are incorrect.

        @raise ModelError: When the unit refers to an undefined dimension.
        """

        try:
            symbol = node.lattrib["symbol"]
            dimension = node.lattrib["dimension"]
        except:
            self.raise_error("Unit must have a symbol and dimension.")

        if "powten" in node.lattrib:
            pow10 = int(node.lattrib["powten"])
        else:
            pow10 = 0

        self.model.add_unit(Unit(symbol, dimension, pow10))

    def parse_root(self, node):
        """
        Parse the <lems> (root) element of a LEMS file
        
        @param node: Node containing the <LEMS> element
        @type node: xml.etree.Element
        """

        if node.tag.lower() != "lems":
            self.raise_error("Not a LEMS file")

        self.xml_node_stack = [node] + self.xml_node_stack
        self.process_nested_tags(node)
        self.xml_node_stack = self.xml_node_stack[1:]

    def parse_file(self, filename):
        """
        Parse a LEMS file and generate a LEMS model

        @param filename: Path to the LEMS file to be parsed
        @type filename: string
        """

        root = xml.parse(filename).getroot()
        xmltolower(root)

        self.base_path = os.path.dirname(filename)
        if self.base_path == "":
            self.base_path = "."

        context = Context("__root_context__", self.current_context)
        if self.model.context == None:
            self.model.context = context

        self.push_context(context)

        self.parse_root(root)

        self.pop_context()

    def parse_string(self, str):
        pass
Beispiel #10
0
    def init_parser(self):
        """
        Initializes the parser
        """

        self.model = Model()
        self.token_list = None
        self.prev_token_lists = None

        self.valid_children = dict()
        self.valid_children["lems"] = ["component", "componenttype", "defaultrun", "dimension", "include", "unit"]
        self.valid_children["componenttype"] = [
            "behavior",
            "behaviour",
            "child",
            "children",
            "componentref",
            "exposure",
            "eventport",
            "fixed",
            "link",
            "parameter",
            "path",
            "requirement",
            "structure",
            "text",
        ]
        self.valid_children["behavior"] = [
            "derivedvariable",
            "oncondition",
            "onentry",
            "onevent",
            "onstart",
            "record",
            "run",
            "show",
            "statevariable",
            "timederivative",
        ]
        self.valid_children["oncondition"] = ["eventout", "stateassignment"]
        self.valid_children["onentry"] = ["eventout", "stateassignment"]
        self.valid_children["onevent"] = ["eventout", "stateassignment"]
        self.valid_children["onstart"] = ["eventout", "stateassignment"]
        self.valid_children["structure"] = ["childinstance", "eventconnection", "foreach", "multiinstantiate"]

        self.tag_parse_table = dict()
        self.tag_parse_table["behavior"] = self.parse_behavior
        self.tag_parse_table["child"] = self.parse_child
        self.tag_parse_table["childinstance"] = self.parse_child_instance
        self.tag_parse_table["children"] = self.parse_children
        self.tag_parse_table["component"] = self.parse_component
        self.tag_parse_table["componentref"] = self.parse_component_ref
        self.tag_parse_table["componenttype"] = self.parse_component_type
        self.tag_parse_table["defaultrun"] = self.parse_default_run
        self.tag_parse_table["derivedvariable"] = self.parse_derived_variable
        self.tag_parse_table["dimension"] = self.parse_dimension
        self.tag_parse_table["eventconnection"] = self.parse_event_connection
        self.tag_parse_table["eventout"] = self.parse_event_out
        self.tag_parse_table["eventport"] = self.parse_event_port
        self.tag_parse_table["exposure"] = self.parse_exposure
        self.tag_parse_table["fixed"] = self.parse_fixed
        self.tag_parse_table["foreach"] = self.parse_foreach
        self.tag_parse_table["include"] = self.parse_include
        self.tag_parse_table["link"] = self.parse_link
        self.tag_parse_table["multiinstantiate"] = self.parse_multi_instantiate
        self.tag_parse_table["oncondition"] = self.parse_on_condition
        self.tag_parse_table["onevent"] = self.parse_on_event
        self.tag_parse_table["onstart"] = self.parse_on_start
        self.tag_parse_table["parameter"] = self.parse_parameter
        self.tag_parse_table["path"] = self.parse_path
        self.tag_parse_table["record"] = self.parse_record
        self.tag_parse_table["requirement"] = self.parse_requirement
        self.tag_parse_table["run"] = self.parse_run
        self.tag_parse_table["show"] = self.parse_show
        self.tag_parse_table["stateassignment"] = self.parse_state_assignment
        self.tag_parse_table["statevariable"] = self.parse_state_variable
        self.tag_parse_table["structure"] = self.parse_structure
        self.tag_parse_table["text"] = self.parse_text
        self.tag_parse_table["timederivative"] = self.parse_time_derivative
        self.tag_parse_table["unit"] = self.parse_unit

        def counter():
            count = 1
            while True:
                yield count
                count = count + 1

        self.id_counter = counter()
        """ Counter genertor for generating unique ids.
import tempfile
from lems.model.model import Model
import xml.etree.ElementTree as ET

import sys
import numpy as np
import matplotlib.pyplot as plt
from math import exp

link = "https://raw.githubusercontent.com/NeuroML/NeuroML2/master/NeuroML2CoreTypes/NeuroMLCoreDimensions.xml"
nml2_dims_contents = urllib.urlopen(link).read()
nml2_dims_file = tempfile.NamedTemporaryFile(delete=False)
nml2_dims_file.write(nml2_dims_contents)
nml2_dims_file.close()

model = Model()
model.import_from_file(nml2_dims_file.name)

def get_si_value(nml2_value):
    return model.get_numeric_value(nml2_value, None)

cell_doc = loaders.NeuroMLLoader.load("../../../NeuroML2/SingleCompMuscle.cell.nml")
k_slow = loaders.NeuroMLLoader.load("../../../NeuroML2/k_slow.channel.nml").ion_channel[0]
k_fast = loaders.NeuroMLLoader.load("../../../NeuroML2/k_fast.channel.nml").ion_channel[0]
ca_boyle = loaders.NeuroMLLoader.load("../../../NeuroML2/ca_boyle.channel.nml").ion_channel[0]
ca_pool = loaders.NeuroMLLoader.load("../../../NeuroML2/CaPool.nml").fixed_factor_concentration_models[0]
tree = ET.parse('../../../NeuroML2/ca_boyle.channel.nml')

cell = cell_doc.cells[0]

d = cell.morphology.segments[0].distal
def main(srcdir, destdir):
    """Main parser and generator function.

    :param srcdir: directory holding source NeuroML Core Type XML files
    :type srcdir: str
    :param destdir: directory where generated files should be stored
    :type destdir: str

    :returns: nothing
    """

    # If not defined or empty, download a new copy to a temporary directory
    if not srcdir or src == "":
        print("No src directory specified. Cloning NeuroML2 repo")
        tempdir = tempfile.TemporaryDirectory()
        tmpsrcdir = tempdir.name
        print("Temporariy directory: {}".format(tmpsrcdir))
        clone_command = [
            "git", "clone", "--depth", "1", "--branch", nml_branch, GitHubRepo,
            tmpsrcdir
        ]
        subprocess.run(clone_command)
    else:
        tmpsrcdir = srcdir

    # TODO: add LEMS examples
    # We can't do this at the moment, because the LEMS python bits are in
    # pyneuroml, while we point to the libNeuroML docs for the NeuroML2 usage
    # examples. pyneuroml does not currently have docs on RTD, and some more
    # work will be required to tell our templates when an example is NeuroML
    # and when it is LEMS so it can point to the correct docs.
    #  exampledirs = [tmpsrcdir + "/examples/", tmpsrcdir + "/LEMSexamples/"]
    exampledirs = [tmpsrcdir + "/examples/"]
    tmpsrcdir = tmpsrcdir + "/NeuroML2CoreTypes/"

    # Get current commit
    commit_command = ["git", "log", "-1", "--pretty=format:%H"]
    output = subprocess.run(commit_command,
                            capture_output=True,
                            cwd=tmpsrcdir,
                            text=True)
    nml_commit = output.stdout

    # read the downloaded files
    get_component_types(tmpsrcdir)

    # get examples
    get_comp_examples(exampledirs)

    # get python signatures
    get_libneuroml_signatures()

    if not destdir or destdir == "":
        destdir = "."
    print("Output files will be written to {} directory".format(destdir))

    for comp_definition in comp_definitions:
        fullpath = "{}/{}.xml".format(tmpsrcdir, comp_definition)
        outputfile = "{}/{}.md".format(destdir, comp_definition)
        """Stage 1"""
        model = Model(include_includes=False)
        model.import_from_file(fullpath)

        print("Processing {}".format(fullpath))
        print("Writing output to {}".format(outputfile))
        ast_doc = open(outputfile, 'w')
        """Page header"""
        print(asttemplates.page_header.render(
            comp_definition=comp_definition,
            comp_description=format_description(model.description),
            GitHubCompSources=GitHubCompSources,
            nml_version=nml_version,
            nml_branch=nml_branch,
            nml_date=nml_date,
            nml_commit=nml_commit),
              file=ast_doc)
        """Dimensions and units"""
        if "Dimensions" in comp_definition:
            dimensions = model.dimensions
            dimensions = sorted(dimensions, key=lambda dim: dim.name)
            units = model.units
            units = sorted(units, key=lambda unit: unit.symbol)

            # lables are translated as lowercase in jupyter, so we append two
            # consecutive underscores to differentiate same ones, like M and m.
            symbols = []
            for unit in units:
                if unit.symbol.lower() in symbols:
                    unit.symbol = unit.symbol + "__"
                symbols.append(unit.symbol.lower())

            print(asttemplates.dimension.render(
                comp_definition=comp_definition,
                dimensions=dimensions,
                units=units),
                  file=ast_doc)

            # Get factors
            for unit in units:
                unit.factors = []
                for unit2 in units:
                    if unit.symbol != unit2.symbol and unit.dimension == unit2.dimension:

                        si_val = model.get_numeric_value(
                            "1%s" % unit.symbol.replace("__", ""),
                            unit.dimension)
                        unit_val = (
                            (Decimal(si_val) /
                             Decimal(math.pow(10, unit2.power))) /
                            Decimal(unit2.scale)) - Decimal(unit2.offset)
                        conversion = float(unit_val)

                        # to catch 60.0001 etc.
                        if conversion > 1 and int(conversion) != conversion:
                            if conversion - int(conversion) < 0.001:
                                conversion = int(conversion)

                        if conversion > 10000:
                            conversion = '%.2e' % conversion
                        else:
                            conversion = '%s' % conversion
                        if conversion.endswith('.0'):
                            conversion = conversion[:-2]

                        unit.factors.append([conversion, unit2.symbol])

            print(asttemplates.unit.render(comp_definition=comp_definition,
                                           units=units),
                  file=ast_doc)
        """Component Types"""
        for o_comp_type in ordered_comp_types[comp_definition]:
            o_comp_type = o_comp_type.replace('rdf:', 'rdf_')
            comp_type = model.component_types[o_comp_type]
            """Header"""
            cno = None
            if " cno_00" in str(comp_type.description):
                cno = comp_type.description.split(" ")[-1]
                comp_type.description = comp_type.description.replace(cno, "")
            comp_type.description = format_description(comp_type.description)
            if len(comp_type.description) > 0:
                if comp_type.description[-1] not in "!.":
                    comp_type.description += "."
            else:
                comp_type.description = ""
            print(asttemplates.comp.render(comp_definition=comp_definition,
                                           comp_type=comp_type,
                                           cno=cno),
                  file=ast_doc)
            """Process parameters, derived parameters, texts, paths, expsures,
            requirements and ports"""
            params = {}
            derived_params = {}
            texts = {}
            paths = {}
            exposures = {}
            requirements = {}
            eventPorts = {}
            """Get lists of them all"""
            for param in comp_type.parameters:
                params[param] = comp_type.name
            for derived_param in comp_type.derived_parameters:
                derived_params[derived_param] = comp_type.name
            for text in comp_type.texts:
                texts[text] = comp_type.name
            for path in comp_type.paths:
                paths[path] = comp_type.paths
            for exp in comp_type.exposures:
                exposures[exp] = comp_type.name
            for req in comp_type.requirements:
                requirements[req] = comp_type.name
            for ep in comp_type.event_ports:
                eventPorts[ep] = comp_type.name
            """Get parent ComponentType if derived from one."""
            extd_comp_type = get_extended_from_comp_type(comp_type.name)
            """Recursively go up the tree and get attributes inherited from ancestors."""
            while extd_comp_type is not None:
                for param in extd_comp_type.parameters:
                    pk = params.copy().keys()
                    for pp0 in pk:
                        if pp0.name == param.name:
                            del params[pp0]
                    params[param] = extd_comp_type.name
                for derived_param in extd_comp_type.derived_parameters:
                    derived_params[derived_param] = extd_comp_type.name
                for text in extd_comp_type.texts:
                    texts[text] = extd_comp_type.name
                for path in extd_comp_type.paths:
                    paths[path] = extd_comp_type.paths
                for exp in extd_comp_type.exposures:
                    ek = exposures.copy().keys()
                    for ee0 in ek:
                        if ee0.name == exp.name:
                            del exposures[ee0]
                    exposures[exp] = extd_comp_type.name
                for req in extd_comp_type.requirements:
                    requirements[req] = extd_comp_type.name
                for ep in extd_comp_type.event_ports:
                    eventPorts[ep] = extd_comp_type.name
                """Recurse up the next parent"""
                extd_comp_type = get_extended_from_comp_type(
                    extd_comp_type.name)

            if len(params) > 0:
                keysort = sorted(params.keys(), key=lambda param: param.name)
                print(asttemplates.params.render(title="Parameters",
                                                 comp_type=comp_type,
                                                 entries=params,
                                                 keysort=keysort),
                      file=ast_doc)
            if len(derived_params) > 0:
                keysort = sorted(derived_params.keys(),
                                 key=lambda derived_param: derived_param.name)
                print(asttemplates.params.render(title="Derived parameters",
                                                 comp_type=comp_type,
                                                 entries=derived_params,
                                                 keysort=keysort),
                      file=ast_doc)

            if len(comp_type.texts
                   ) > 0:  # TODO: Check if Text elements are inherited...
                print(asttemplates.misc2c.render(title="Text fields",
                                                 textlist=comp_type.texts),
                      file=ast_doc)
            if len(comp_type.paths
                   ) > 0:  # TODO: Check if Path elements are inherited...
                print(asttemplates.misc2c.render(title="Paths",
                                                 textlist=comp_type.paths),
                      file=ast_doc)
            if len(comp_type.component_references) > 0:
                print(asttemplates.misc3c.render(
                    title="Component References",
                    textlist=comp_type.component_references),
                      file=ast_doc)

            if len(comp_type.children) > 0:
                childlist = []
                childrenlist = []
                for child_or_children in comp_type.children:
                    if not child_or_children.multiple:
                        childlist.append(child_or_children)
                    else:
                        childrenlist.append(child_or_children)

                if len(childlist) > 0:
                    print(asttemplates.misc3c.render(title="Child list",
                                                     textlist=childlist),
                          file=ast_doc)
                if len(childrenlist) > 0:
                    print(asttemplates.misc3c.render(title="Children list",
                                                     textlist=childrenlist),
                          file=ast_doc)

            if len(comp_type.constants) > 0:
                print(asttemplates.constants.render(
                    title="Constants", textlist=comp_type.constants),
                      file=ast_doc)

            if len(comp_type.properties) > 0:
                print(asttemplates.properties.render(
                    title="Properties", textlist=comp_type.properties),
                      file=ast_doc)

            if len(exposures) > 0:
                keysort = sorted(exposures, key=lambda entry: entry.name)
                print(asttemplates.exposures.render(title="Exposures",
                                                    comp_type=comp_type,
                                                    entries=exposures,
                                                    keysort=keysort),
                      file=ast_doc)

            if len(requirements) > 0:
                keysort = sorted(requirements, key=lambda entry: entry.name)
                print(asttemplates.requirements.render(title="Requirements",
                                                       comp_type=comp_type,
                                                       entries=requirements,
                                                       keysort=keysort),
                      file=ast_doc)

            if len(eventPorts) > 0:
                keysort = sorted(eventPorts, key=lambda entry: entry.name)
                print(asttemplates.eventPorts.render(title="Event Ports",
                                                     comp_type=comp_type,
                                                     entries=eventPorts,
                                                     keysort=keysort),
                      file=ast_doc)

            if len(comp_type.attachments) > 0:
                print(asttemplates.misc3c.render(
                    title="Attachments", textlist=comp_type.attachments),
                      file=ast_doc)

            if comp_type.dynamics and comp_type.dynamics.has_content():
                print(asttemplates.dynamics.render(title="Dynamics",
                                                   comp_type=comp_type),
                      file=ast_doc)

            # Examples
            """
            print("{} has: ".format(comp_type.name))
            if comp_type_py_api[comp_type.name]:
                print("\t1 Py def")
            if len(comp_type_examples[comp_type.name]) > 0:
                print("\t{} XML examples".format(len(comp_type_examples[comp_type.name])))

            """
            if comp_type_py_api[comp_type.name] or len(
                    comp_type_examples[comp_type.name]) > 0:
                print(asttemplates.examples.render(
                    title="Usage",
                    comp_type=comp_type,
                    lemsexamples=comp_type_examples[comp_type.name],
                    pysig=comp_type_py_api[comp_type.name]),
                      file=ast_doc)

        ast_doc.close()
        print("Finished processing {}".format(fullpath))

    if not srcdir:
        tempdir.cleanup()
Beispiel #13
0
#! /usr/bin/python

from lems.model.model import Model
import sys

model = Model()

file_name = 'examples/hhcell.xml'
#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml'
#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml'
#file_name = '../org.neuroml.import/src/test/resources/BIOMD0000000185_LEMS.xml'

if len(sys.argv) == 2:
    file_name = sys.argv[1]

model.import_from_file(file_name)

fn = '/tmp/hhmodel.xml'
model.export_to_file(fn)

print("----------------------------------------------")
print(open(fn, 'r').read())
print("----------------------------------------------")

print("Written generated LEMS to %s" % fn)

from lems.base.util import validate_lems

validate_lems(fn)
Beispiel #14
0
    def get_model(self):

        model = Model()

        model.add(Dimension('voltage', m=1, l=3, t=-3, i=-1))
        model.add(Dimension('time', t=1))
        model.add(Dimension('capacitance', m=-1, l=-2, t=4, i=2))
        model.add(Dimension('conductanceDensity', m="-1", l="-4", t="3",
                            i="2"))
        model.add(Dimension('temperature', k=1))

        model.add(Unit('volt', 'V', 'voltage', 0))
        model.add(Unit('milliVolt', 'mV', 'voltage', -3))
        model.add(Unit('milliSecond', 'ms', 'time', -3))
        model.add(Unit('microFarad', 'uF', 'capacitance', -12))
        model.add(Unit('mS_per_cm2', 'mS_per_cm2', 'conductanceDensity', 1))

        model.add(Unit('Kelvin', 'K', 'temperature', 0))
        model.add(Unit('celsius', 'degC', 'temperature', 0, offset=273.15))

        model.add(Unit('hour', 'hour', 'time', scale=3600))
        model.add(Unit('min', 'min', 'time', scale=60))

        return model
Beispiel #15
0
            dlems_file_name = 'comp_%s.json'%comp.id
            
        dlems_file = open(dlems_file_name, 'w')

        dlems_file.write(json.dumps(dlems, indent=4, separators=(',', ': ')))

        dlems_file.close()

        print(open(dlems_file_name,'r').read())

        print("Written to %s"%dlems_file_name)
    


if __name__ == '__main__':
    model = Model()

    try:
        lems_file = sys.argv[1] 
    except:
        lems_file = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex9_FN.xml'

    print('Importing LEMS file from: %s'%lems_file)
    model.import_from_file(lems_file)

    target = model.targets[0]

    sim_comp = model.components[target]

    target_net = sim_comp.parameters['target']
            dlems_file_name = 'comp_%s.json'%comp.id
            
        dlems_file = open(dlems_file_name, 'w')

        dlems_file.write(json.dumps(dlems, indent=4, separators=(',', ': ')))

        dlems_file.close()

        print(open(dlems_file_name,'r').read())

        print("Written to %s"%dlems_file_name)
    


if __name__ == '__main__':
    model = Model()

    try:
        lems_file = sys.argv[1] 
    except:
        lems_file = '../NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml'
        model.add_include_directory('../NeuroML2/NeuroML2CoreTypes')

    print('Importing LEMS file from: %s'%lems_file)
    model.import_from_file(lems_file)

    target = model.targets[0]

    sim_comp = model.components[target]

    target_net = sim_comp.parameters['target']
Beispiel #17
0
    def init_parser(self):
        """
        Initializes the parser
        """

        self.model = Model()
        self.token_list = None
        self.prev_token_lists = None

        self.valid_children = dict()
        self.valid_children['lems'] = [
            'component', 'componenttype', 'defaultrun', 'dimension', 'include',
            'unit'
        ]
        self.valid_children['componenttype'] = [
            'behavior', 'behaviour', 'child', 'children', 'componentref',
            'exposure', 'eventport', 'fixed', 'link', 'parameter', 'path',
            'requirement', 'structure', 'text'
        ]
        self.valid_children['behavior'] = [
            'derivedvariable', 'oncondition', 'onentry', 'onevent', 'onstart',
            'record', 'run', 'show', 'statevariable', 'timederivative'
        ]
        self.valid_children['oncondition'] = ['eventout', 'stateassignment']
        self.valid_children['onentry'] = ['eventout', 'stateassignment']
        self.valid_children['onevent'] = ['eventout', 'stateassignment']
        self.valid_children['onstart'] = ['eventout', 'stateassignment']
        self.valid_children['structure'] = [
            'childinstance', 'eventconnection', 'foreach', 'multiinstantiate'
        ]

        self.tag_parse_table = dict()
        self.tag_parse_table['behavior'] = self.parse_behavior
        self.tag_parse_table['child'] = self.parse_child
        self.tag_parse_table['childinstance'] = self.parse_child_instance
        self.tag_parse_table['children'] = self.parse_children
        self.tag_parse_table['component'] = self.parse_component
        self.tag_parse_table['componentref'] = self.parse_component_ref
        self.tag_parse_table['componenttype'] = self.parse_component_type
        self.tag_parse_table['defaultrun'] = self.parse_default_run
        self.tag_parse_table['derivedvariable'] = self.parse_derived_variable
        self.tag_parse_table['dimension'] = self.parse_dimension
        self.tag_parse_table['eventconnection'] = self.parse_event_connection
        self.tag_parse_table['eventout'] = self.parse_event_out
        self.tag_parse_table['eventport'] = self.parse_event_port
        self.tag_parse_table['exposure'] = self.parse_exposure
        self.tag_parse_table['fixed'] = self.parse_fixed
        self.tag_parse_table['foreach'] = self.parse_foreach
        self.tag_parse_table['include'] = self.parse_include
        self.tag_parse_table['link'] = self.parse_link
        self.tag_parse_table['multiinstantiate'] = \
                                                 self.parse_multi_instantiate
        self.tag_parse_table['oncondition'] = self.parse_on_condition
        self.tag_parse_table['onevent'] = self.parse_on_event
        self.tag_parse_table['onstart'] = self.parse_on_start
        self.tag_parse_table['parameter'] = self.parse_parameter
        self.tag_parse_table['path'] = self.parse_path
        self.tag_parse_table['record'] = self.parse_record
        self.tag_parse_table['requirement'] = self.parse_requirement
        self.tag_parse_table['run'] = self.parse_run
        self.tag_parse_table['show'] = self.parse_show
        self.tag_parse_table['stateassignment'] = self.parse_state_assignment
        self.tag_parse_table['statevariable'] = self.parse_state_variable
        self.tag_parse_table['structure'] = self.parse_structure
        self.tag_parse_table['text'] = self.parse_text
        self.tag_parse_table['timederivative'] = self.parse_time_derivative
        self.tag_parse_table['unit'] = self.parse_unit

        def counter():
            count = 1
            while True:
                yield count
                count = count + 1

        self.id_counter = counter()
        """ Counter genertor for generating unique ids.
Beispiel #18
0

files = [
    "Cells", "Synapses", "Channels", "Inputs", "Networks", "PyNN",
    "NeuroMLCoreDimensions", "NeuroMLCoreCompTypes"
]

comp_types = {}
comp_type_src = {}
comp_type_desc = {}
ordered_comp_types = {}

for file in files:
    fullfile = "%s/%s.xml" % (nml_src, file)
    print "\n----------  Reading LEMS file: " + fullfile
    model = Model(include_includes=False)
    model.import_from_file(fullfile)

    for comp_type in model.component_types:
        comp_types[comp_type.name] = comp_type
        comp_type_src[comp_type.name] = file
        comp_type_desc[
            comp_type.
            name] = comp_type.description if comp_type.description is not None else "ComponentType: " + comp_type.name
    ordered_comp_type_list = []
    with open(fullfile) as fp:
        for line in fp:
            s = '<ComponentType name='
            if s in line:
                i = line.index(s)
                e = line.find('"', i + len(s) + 1)
Beispiel #19
0
class LEMSParser(Parser):
    """
    Parser for LEMS files
    """

    base_path = '.'
    """ Base path for the file being parsed
    @type: string """

    model = None
    """ Model built during parsing
    @type: lems.model.model.model """

    tag_parse_table = None
    """ Dictionary of xml tags to parse methods
    @type: dict(string -> function) """

    valid_children = None
    """ Dictionary mapping each tag to it's list of valid child tags.
    @type: dict(string -> string) """

    context_stack = []
    """ Stack of contexts used for handling nested contexts.
    @type: list(lems.model.context.Context) """

    current_context = None
    """ Currently active (being parsed) context.
    @type: lems.model.context.Context """

    component_type_stack = []
    """ Stack of component type objects used for handling nested
    component types.
    @type: list(lems.model.parameter.ComponentType) """

    current_component_type = None
    """ Component type object being parsed.
    @type: lems.model.parameter.ComponentType """

    current_regime = None
    """ Current behavior regime being parsed.
    @type: lems.model.behavior.Regime """

    current_event_handler = None
    """ Current event_handler being parsed.
    @type: lems.model.behavior.EventHandler """

    current_structure = None
    """ Current structure being parsed.
    @type: lems.model.structure.Structure """

    xml_node_stack = []
    """ XML node stack.
    @type: list(xml.etree.Element) """
    def push_context(self, context):
        self.context_stack = [context] + self.context_stack
        self.current_context = context

    def pop_context(self):
        if len(self.context_stack) == 0:
            self.raise_error('Context stack underflow')
        self.context_stack = self.context_stack[1:]
        if len(self.context_stack) == 0:
            self.current_context = None
        else:
            self.current_context = self.context_stack[0]

    def push_component_type(self, component_type):
        self.component_type_stack = [component_type] + \
                                    self.component_type_stack
        self.current_component_type = component_type

    def pop_component_type(self):
        if len(self.component_type_stack) == 0:
            self.raise_error('Component_Type stack underflow')
        self.component_type_stack = self.component_type_stack[1:]
        if len(self.component_type_stack) == 0:
            self.current_component_type = None
        else:
            self.current_component_type = self.component_type_stack[0]

    def init_parser(self):
        """
        Initializes the parser
        """

        self.model = Model()
        self.token_list = None
        self.prev_token_lists = None

        self.valid_children = dict()
        self.valid_children['lems'] = [
            'component', 'componenttype', 'defaultrun', 'dimension', 'include',
            'unit'
        ]
        self.valid_children['componenttype'] = [
            'behavior', 'behaviour', 'child', 'children', 'componentref',
            'exposure', 'eventport', 'fixed', 'link', 'parameter', 'path',
            'requirement', 'structure', 'text'
        ]
        self.valid_children['behavior'] = [
            'derivedvariable', 'oncondition', 'onentry', 'onevent', 'onstart',
            'record', 'run', 'show', 'statevariable', 'timederivative'
        ]
        self.valid_children['oncondition'] = ['eventout', 'stateassignment']
        self.valid_children['onentry'] = ['eventout', 'stateassignment']
        self.valid_children['onevent'] = ['eventout', 'stateassignment']
        self.valid_children['onstart'] = ['eventout', 'stateassignment']
        self.valid_children['structure'] = [
            'childinstance', 'eventconnection', 'foreach', 'multiinstantiate'
        ]

        self.tag_parse_table = dict()
        self.tag_parse_table['behavior'] = self.parse_behavior
        self.tag_parse_table['child'] = self.parse_child
        self.tag_parse_table['childinstance'] = self.parse_child_instance
        self.tag_parse_table['children'] = self.parse_children
        self.tag_parse_table['component'] = self.parse_component
        self.tag_parse_table['componentref'] = self.parse_component_ref
        self.tag_parse_table['componenttype'] = self.parse_component_type
        self.tag_parse_table['defaultrun'] = self.parse_default_run
        self.tag_parse_table['derivedvariable'] = self.parse_derived_variable
        self.tag_parse_table['dimension'] = self.parse_dimension
        self.tag_parse_table['eventconnection'] = self.parse_event_connection
        self.tag_parse_table['eventout'] = self.parse_event_out
        self.tag_parse_table['eventport'] = self.parse_event_port
        self.tag_parse_table['exposure'] = self.parse_exposure
        self.tag_parse_table['fixed'] = self.parse_fixed
        self.tag_parse_table['foreach'] = self.parse_foreach
        self.tag_parse_table['include'] = self.parse_include
        self.tag_parse_table['link'] = self.parse_link
        self.tag_parse_table['multiinstantiate'] = \
                                                 self.parse_multi_instantiate
        self.tag_parse_table['oncondition'] = self.parse_on_condition
        self.tag_parse_table['onevent'] = self.parse_on_event
        self.tag_parse_table['onstart'] = self.parse_on_start
        self.tag_parse_table['parameter'] = self.parse_parameter
        self.tag_parse_table['path'] = self.parse_path
        self.tag_parse_table['record'] = self.parse_record
        self.tag_parse_table['requirement'] = self.parse_requirement
        self.tag_parse_table['run'] = self.parse_run
        self.tag_parse_table['show'] = self.parse_show
        self.tag_parse_table['stateassignment'] = self.parse_state_assignment
        self.tag_parse_table['statevariable'] = self.parse_state_variable
        self.tag_parse_table['structure'] = self.parse_structure
        self.tag_parse_table['text'] = self.parse_text
        self.tag_parse_table['timederivative'] = self.parse_time_derivative
        self.tag_parse_table['unit'] = self.parse_unit

        def counter():
            count = 1
            while True:
                yield count
                count = count + 1

        self.id_counter = counter()
        """ Counter genertor for generating unique ids.
        @type: int """

    prefix = ''

    def process_nested_tags(self, node):
        """
        Process child tags.

        @param node: Current node being parsed.
        @type node: xml.etree.Element

        @raise ParseError: Raised when an unexpected nested tag is found.
        """

        #self.prefix += '  '

        for child in node:
            #print self.prefix, child.tag,
            #print child.attrib['name'] if 'name' in child.attrib else '',
            #print child.attrib['id'] if 'id' in child.attrib else ''

            self.xml_node_stack = [child] + self.xml_node_stack

            ctagl = child.tag.lower()

            if ctagl in self.tag_parse_table:
                self.tag_parse_table[ctagl](child)
            else:
                self.parse_component_by_typename(child, child.tag)

            self.xml_node_stack = self.xml_node_stack[1:]

        #self.prefix = self.prefix[2:]

    def resolve_typename(self, typename):
        """ 
        Resolves type name from the contex stack.

        @param typename: Name of the type to be resolved.
        @type typename: string

        @return: Component type corresponding to the type name or None if
        undefined.
        @rtype: lems.model.component.ComponentType
        """

        stack = self.context_stack
        found = False
        while stack != [] and (not found):
            if typename in stack[0].component_types:
                found = True

        if found:
            return stack[0].component_types[typename]
        else:
            return None

    def resolve_component_name(self, component_name):
        """ 
        Resolves component name from the contex stack.

        @param component_name: Name of the component to be resolved.
        @type component_name: string

        @return: Component corresponding to the name or None if undefined.
        @rtype: lems.model.component.Component
        """

        stack = self.context_stack
        found = False
        while stack != [] and (not found):
            if component_name in stack[0].components:
                found = True

        if found:
            return stack[0].components[component_name]
        else:
            return None

    def raise_error(self, message):
        s = 'Parser error in '

        self.xml_node_stack.reverse()
        if len(self.xml_node_stack) > 1:
            node = self.xml_node_stack[0]
            s += '<{0}'.format(node.tag)
            if 'name' in node.lattrib:
                s += ' name=\"{0}\"'.format(node.lattrib['name'])
            if 'id' in node.lattrib:
                s += ' id=\"{0}\"'.format(node.lattrib['id'])
            s += '>'

        for node in self.xml_node_stack[1:]:
            s += '.<{0}'.format(node.tag)
            if 'name' in node.lattrib:
                s += ' name=\"{0}\"'.format(node.lattrib['name'])
            if 'id' in node.lattrib:
                s += ' id=\"{0}\"'.format(node.lattrib['id'])
            s += '>'

        s += ':\n  ' + message

        raise ParseError(s)

        self.xml_node_stack.reverse()

    def get_model(self):
        """
        Returns the generated model.

        @return: The generated model.
        @rtype: lems.model.model.Model
        """

        return self.model

    def parse_behavior(self, node):
        """
        Parses <Behavior>

        @param node: Node containing the <Behaviour> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Behavior must be defined inside a ' +
                             'component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            name = ''

        self.current_context.add_behavior_profile(name)

        old_regime = self.current_regime
        self.current_regime = self.current_context.selected_behavior_profile.\
                              default_regime

        self.process_nested_tags(node)

        self.current_regime = old_regime

    ## def parse_build(self, node):
    ##     """
    ##     Parses <Build>

    ##     @param node: Node containing the <Build> element
    ##     @type node: xml.etree.Element
    ##     """

    ##     pass

    def parse_child(self, node):
        """
        Parses <Child>

        @param node: Node containing the <Child> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Child definitions can only be made in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('<Child> must specify a name for the ' +
                             'reference.')

        if 'type' in node.lattrib:
            type = node.lattrib['type']
        else:
            self.raise_error('<Child> must specify a type for the ' +
                             'reference.')

        self.current_context.add_child_def(name, type)

    def parse_child_instance(self, node):
        """
        Parses <ChildInstance>

        @param node: Node containing the <ChildInstance> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error('Child instantiations can only be made within ' +
                             'a structure definition')

        if 'component' in node.lattrib:
            component = node.lattrib['component']
        else:
            self.raise_error('<ChildInstance> must specify a component '
                             'reference')

        self.current_structure.add_single_child_def(component)

    def parse_children(self, node):
        """
        Parses <Children>

        @param node: Node containing the <Children> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Children definitions can only be made in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('<Children> must specify a name for the ' +
                             'reference.')

        if 'type' in node.lattrib:
            type = node.lattrib['type']
        else:
            self.raise_error('<Children> must specify a type for the ' +
                             'reference.')

        self.current_context.add_children_def(name, type)

    def parse_component_by_typename(self, node, type):
        """
        Parses components defined directly by component name.

        @param node: Node containing the <Component> element
        @type node: xml.etree.Element

        @param type: Type of this component.
        @type type: string

        @raise ParseError: Raised when the component does not have an id.
        """

        if self.current_context.context_type == Context.GLOBAL:
            # Global component instatiation
            if 'id' in node.lattrib:
                id = node.lattrib['id']
            else:
                self.raise_error('Component must have an id')

            type = node.tag

            component = Component(id, self.current_context, type, None)

            self.current_context.add_component(component)

        else:
            # Child instantiation

            if 'id' in node.lattrib:
                id = node.lattrib['id']
                type = node.tag
            else:
                id = node.tag
                type = '__type_inherited__'

            component = Component(id, self.current_context, type)

            self.current_context.add_child(component)

        for key in node.attrib:
            if key.lower() not in ['extends', 'id', 'type']:
                param = Parameter(key, '__dimension_inherited__')
                param.set_value(node.attrib[key])
                component.add_parameter(param)

        self.push_context(component.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_component(self, node):
        """
        Parses <Component>

        @param node: Node containing the <ComponentType> element
        @type node: xml.etree.Element
        """

        if 'id' in node.lattrib:
            id = node.lattrib['id']
        else:
            self.raise_error('Component must have an id')

        if 'type' in node.lattrib:
            type = node.lattrib['type']
        else:
            type = None

        if type == None:
            if 'extends' in node.lattrib:
                extends = node.lattrib['extends']
            else:
                self.raise_error('Component must have a type or must ' +
                                 'extend another component')
        else:
            extends = None

        component = Component(id, self.current_context, type, extends)
        self.current_context.add_component(component)

        for key in node.attrib:
            if key.lower() not in ['extends', 'id', 'type']:
                param = Parameter(key, '__dimension_inherited__')
                param.set_value(node.attrib[key])
                component.add_parameter(param)

        self.push_context(component.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_component_ref(self, node):
        """
        Parses <ComponentRef>

        @param node: Node containing the <ComponentTypeRef> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Component references can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('<ComponentRef> must specify a name for the ' +
                             'reference.')

        if 'type' in node.lattrib:
            type = node.lattrib['type']
        else:
            self.raise_error('<ComponentRef> must specify a type for the ' +
                             'reference.')

        self.current_context.add_component_ref(name, type)

    def parse_component_type(self, node):
        """
        Parses <ComponentType>

        @param node: Node containing the <ComponentType> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the component type does not have a
        name.
        """

        try:
            name = node.lattrib['name']
        except:
            self.raise_error('Component type must have a name')

        if 'extends' in node.lattrib:
            extends = node.lattrib['extends']
        else:
            extends = None

        component_type = ComponentType(name, self.current_context, extends)
        self.current_context.add_component_type(component_type)

        self.push_context(component_type.context)
        self.process_nested_tags(node)
        self.pop_context()

    def parse_default_run(self, node):
        """
        Parses <DefaultRun>

        @param node: Node containing the <DefaultRun> element
        @type node: xml.etree.Element
        """

        self.model.add_default_run(node.lattrib['component'])

    def parse_derived_variable(self, node):
        """
        Parses <DerivedVariable>

        @param node: Node containing the <DerivedVariable> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<DerivedVariable> must be defined inside a ' +
                             'behavior profile or regime')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('A derived variable must have a name')

        if 'exposure' in node.lattrib:
            exposure = node.lattrib['exposure']
        else:
            exposure = None

        if 'dimension' in node.lattrib:
            dimension = node.lattrib['dimension']
        else:
            dimension = None

        if 'value' in node.lattrib:
            value = node.lattrib['value']
        else:
            value = None

        if 'select' in node.lattrib:
            select = node.lattrib['select']
        else:
            select = None

        if 'reduce' in node.lattrib:
            reduce = node.lattrib['reduce']
        else:
            reduce = None

        self.current_regime.add_derived_variable(name, exposure, dimension,
                                                 value, select, reduce)

    def parse_dimension(self, node):
        """
        Parses <Dimension>

        @param node: Node containing the <Dimension> element
        @type node: xml.etree.Element

        @raise ParseError: When the name is not a string or if the
        dimension is not a signed integer.
        """

        dim = list()
        try:
            name = node.lattrib['name']
            for d in ['l', 'm', 't', 'i', 'k', 'c', 'n']:
                dim.append(int(node.lattrib.get(d, 0)))
        except:
            self.raise_error('Invalid dimensionality format')

        self.model.add_dimension(
            Dimension(name, dim[0], dim[1], dim[2], dim[3], dim[4], dim[4],
                      dim[6]))

    def parse_event_out(self, node):
        """
        Parses <EventOut>

        @param node: Node containing the <EventOut> element
        @type node: xml.etree.Element
        """

        if self.current_event_handler == None:
            self.raise_error('<EventOut> must be defined inside an ' +
                             'event handler in a behavior profile or regime')

        if 'port' in node.lattrib:
            port = node.lattrib['port']
        else:
            self.raise_error('\'port\' attribute not provided for ' +
                             '<StateAssignment>')

        action = EventOut(port)

        self.current_event_handler.add_action(action)

    def parse_event_connection(self, node):
        """
        Parses <EventConnection>

        @param node: Node containing the <EventConnection> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error('<EventConnection> must be defined inside a ' +
                             'structure definition')

        if 'from' in node.lattrib:
            from_ = node.lattrib['from']
        else:
            self.raise_error('\'from\' attribute not provided for ' +
                             '<EventConnection>')

        if 'to' in node.lattrib:
            to = node.lattrib['to']
        else:
            self.raise_error('\'to\' attribute not provided for ' +
                             '<EventConnection>')

        self.current_structure.add_event_connection(from_, to)

    def parse_event_port(self, node):
        """
        Parses <EventPort>

        @param node: Node containing the <EventPort> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Event ports can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error(('<EventPort> must specify a name for the '
                              'event port'))

        if 'direction' in node.lattrib:
            direction = node.lattrib['direction']
        else:
            self.raise_error(('<EventPort> must specify a direction for the '
                              'event port'))

        direction = direction.lower()
        if direction != 'in' and direction != 'out':
            self.raise_error(('Event port direction must be \'in\' '
                              'or \'out\''))

        self.current_context.add_event_port(name, direction)

    def parse_exposure(self, node):
        """
        Parses <Exposure>

        @param node: Node containing the <Exposure> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the exposure name is not
        being defined in the context of a component type.
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Exposure names can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            self.current_context.add_exposure(node.lattrib['name'])

    def parse_fixed(self, node):
        """
        Parses <Fixed>

        @param node: Node containing the <Fixed> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when
        """

        try:
            parameter = node.lattrib['parameter']
        except:
            self.raise_error('Parameter to be fixed must be specified')

        try:
            value = node.lattrib['value']
        except:
            self.raise_error('Value to be fixed must be specified')

        if self.current_context.lookup_parameter(parameter) == None:
            self.current_context.add_parameter(
                Parameter(parameter, '__dimension_inherited__'))
        self.current_context.lookup_parameter(parameter).fix_value(value)

    def parse_foreach(self, node):
        """
        Parses <ForEach>

        @param node: Node containing the <ForEach> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error('<ForEach> can only be made within ' +
                             'a structure definition')

        if 'instances' in node.lattrib:
            target = node.lattrib['instances']
        else:
            self.raise_error('<ForEach> must specify a reference to target'
                             'instances')

        if 'as' in node.lattrib:
            name = node.lattrib['as']
        else:
            self.raise_error('<ForEach> must specify a name for the '
                             'enumerated target instances')

        old_structure = self.current_structure
        self.current_structure = self.current_structure.add_foreach(\
            name, target)

        self.process_nested_tags(node)

        self.current_structure = old_structure

    def parse_include(self, node):
        """
        Parses <Include>

        @param node: Node containing the <Include> element
        @type node: xml.etree.Element
        """

        if 'file' not in node.lattrib:
            self.raise_error('Include file must be specified.')

        path = self.base_path + '/' + node.lattrib['file']

        root = xml.parse(path).getroot()
        xmltolower(root)

        self.parse_root(root)

    def parse_link(self, node):
        """
        Parses <Link>

        @param node: Node containing the <Link> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Link variables can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('A name must be provided for <Link>')

        if 'type' in node.lattrib:
            type = node.lattrib['type']
        else:
            type = None

        self.current_context.add_link_var(name, type)

    def parse_multi_instantiate(self, node):
        """
        Parses <MultiInstantiate>

        @param node: Node containing the <MultiInstantiate> element
        @type node: xml.etree.Element
        """

        if self.current_structure == None:
            self.raise_error('Child instantiations can only be made within ' +
                             'a structure definition')

        if 'component' in node.lattrib:
            component = node.lattrib['component']
        else:
            self.raise_error('<MultiInstantiate> must specify a component '
                             'reference')

        if 'number' in node.lattrib:
            number = node.lattrib['number']
        else:
            self.raise_error('<MultiInstantiate> must specify a number')

        self.current_structure.add_multi_child_def(component, number)

    def parse_on_condition(self, node):
        """
        Parses <OnCondition>

        @param node: Node containing the <OnCondition> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<OnCondition> must be defined inside a ' +
                             'behavior profile or regime')

        if 'test' in node.lattrib:
            test = node.lattrib['test']
        else:
            self.raise_error('Test expression required for <OnCondition>')

        event_handler = OnCondition(test)

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_entry(self, node):
        """
        Parses <OnEntry>

        @param node: Node containing the <OnEntry> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<OnEvent> must be defined inside a ' +
                             'behavior profile or regime')

        event_handler = OnEntry()

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_event(self, node):
        """
        Parses <OnEvent>

        @param node: Node containing the <OnEvent> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<OnEvent> must be defined inside a ' +
                             'behavior profile or regime')

        if 'port' in node.lattrib:
            port = node.lattrib['port']
        else:
            self.raise_error('Port name required for <OnCondition>')

        event_handler = OnEvent(port)

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_on_start(self, node):
        """
        Parses <OnStart>

        @param node: Node containing the <OnStart> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<OnEvent> must be defined inside a ' +
                             'behavior profile or regime')

        event_handler = OnStart()

        self.current_event_handler = event_handler
        self.current_regime.add_event_handler(event_handler)

        self.process_nested_tags(node)

        self.current_event_handler = None

    def parse_parameter(self, node):
        """
        Parses <Parameter>

        @param node: Node containing the <Parameter> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the parameter does not have a name.
        @raise ParseError: Raised when the parameter does not have a
        dimension.
        """

        try:
            name = node.lattrib['name']
        except:
            self.raise_error('Parameter must have a name')

        try:
            dimension = node.lattrib['dimension']
        except:
            self.raise_error('Parameter must have a dimension')

        parameter = Parameter(name, dimension)

        self.current_context.add_parameter(parameter)

    def parse_path(self, node):
        """
        Parses <Path>

        @param node: Node containing the <Path> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Path variables can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('A name must be provided for <Path>')

        if 'value' in node.lattrib:
            value = node.lattrib['value']
        else:
            value = None

        self.current_context.add_path_var(name, value)

    def parse_record(self, node):
        """
        Parses <Record>

        @param node: Node containing the <Record> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<Record> must be only be used inside a ' +
                             'behavior profile or regime')

        if 'quantity' in node.lattrib:
            quantity = node.lattrib['quantity']
        else:
            self.raise_error('\'quantity\' attribute required for <Text>')

        if 'scale' in node.lattrib:
            scale = node.lattrib['scale']
        else:
            self.raise_error('\'scale\' attribute required for <Text>')

        if 'color' in node.lattrib:
            color = node.lattrib['color']
        else:
            self.raise_error('\'color\' attribute required for <Text>')

        self.current_regime.add_record(quantity, scale, color)

    def parse_requirement(self, node):
        """
        Parses <Requirement>

        @param node: Node containing the <Requirement> element
        @type node: xml.etree.Element
        """

        pass

    def parse_run(self, node):
        """
        Parses <Run>

        @param node: Node containing the <Run> element
        @type node: xml.etree.Element
        """

        if self.current_regime == None:
            self.raise_error('<Run> must be defined inside a ' +
                             'behavior profile or regime')

        if 'component' in node.lattrib:
            component = node.lattrib['component']
        else:
            self.raise_error('<Run> must specify a target component')

        if 'variable' in node.lattrib:
            variable = node.lattrib['variable']
        else:
            self.raise_error('<Run> must specify a state variable')

        if 'increment' in node.lattrib:
            increment = node.lattrib['increment']
        else:
            self.raise_error('<Run> must specify an increment for the ' +
                             'state variable')

        if 'total' in node.lattrib:
            total = node.lattrib['total']
        else:
            self.raise_error('<Run> must specify a final value for the ' +
                             'state variable')

        self.current_regime.add_run(component, variable, increment, total)

    def parse_show(self, node):
        """
        Parses <Show>

        @param node: Node containing the <Show> element
        @type node: xml.etree.Element
        """

        pass

    def parse_state_assignment(self, node):
        """
        Parses <StateAssignment>

        @param node: Node containing the <StateAssignment> element
        @type node: xml.etree.Element
        """

        if self.current_event_handler == None:
            self.raise_error('<StateAssignment> must be defined inside an ' +
                             'event handler in a behavior profile or regime')

        if 'variable' in node.lattrib:
            variable = node.lattrib['variable']
        else:
            self.raise_error('\'variable\' attribute not provided for ' +
                             '<StateAssignment>')

        if 'value' in node.lattrib:
            value = node.lattrib['value']
        else:
            self.raise_error('\'value\' attribute not provided for ' +
                             '<StateAssignment>')

        action = StateAssignment(variable, value)

        self.current_event_handler.add_action(action)

    def parse_state_variable(self, node):
        """
        Parses <StateVariable>

        @param node: Node containing the <StateVariable> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the state variable is not
        being defined in the context of a component type.
        """

        if self.current_regime == None:
            self.raise_error('<StateVariable> must be defined inside a ' +
                             'behavior profile or regime')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('A state variable must have a name')

        if 'exposure' in node.lattrib:
            exposure = node.lattrib['exposure']
        else:
            exposure = None

        if 'dimension' in node.lattrib:
            dimension = node.lattrib['dimension']
        else:
            self.raise_error('A state variable must have a dimension')

        self.current_regime.add_state_variable(name, exposure, dimension)

    def parse_structure(self, node):
        """
        Parses <Structure>

        @param node: Node containing the <Structure> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Structure must be defined inside a ' +
                             'component type')

        old_structure = self.current_structure
        self.current_structure = self.current_context.structure

        self.process_nested_tags(node)

        self.current_structure = old_structure

    def parse_text(self, node):
        """
        Parses <Text>

        @param node: Node containing the <Text> element
        @type node: xml.etree.Element
        """

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Text variables can only be defined in ' +
                             'a component type')

        if 'name' in node.lattrib:
            name = node.lattrib['name']
        else:
            self.raise_error('A name must be provided for <Text>')

        if 'value' in node.lattrib:
            value = node.lattrib['value']
        else:
            value = None

        self.current_context.add_text_var(name, value)

    def parse_time_derivative(self, node):
        """
        Parses <TimeDerivative>

        @param node: Node containing the <TimeDerivative> element
        @type node: xml.etree.Element

        @raise ParseError: Raised when the time derivative is not
        being defined in the context of a component type.
        """

        if self.current_regime == None:
            self.raise_error('<TimeDerivative> must be defined inside a ' +
                             'behavior profile or regime')

        if self.current_context.context_type != Context.COMPONENT_TYPE:
            self.raise_error('Time derivatives can only be defined in ' +
                             'a component type')

        if 'variable' in node.lattrib:
            name = node.lattrib['variable']
        else:
            self.raise_error('The state variable being differentiated wrt ' +
                             'time must be specified')

        if 'value' in node.lattrib:
            value = node.lattrib['value']
        else:
            self.raise_error('The time derivative expression must be ' +
                             'provided')

        self.current_regime.add_time_derivative(name, value)

    def parse_unit(self, node):
        """
        Parses <Unit>

        @param node: Node containing the <Unit> element
        @type node: xml.etree.Element

        @raise ParseError: When the name is not a string or the unit
        specfications are incorrect.

        @raise ModelError: When the unit refers to an undefined dimension.
        """

        try:
            symbol = node.lattrib['symbol']
            dimension = node.lattrib['dimension']
        except:
            self.raise_error('Unit must have a symbol and dimension.')

        if 'powten' in node.lattrib:
            pow10 = int(node.lattrib['powten'])
        else:
            pow10 = 0

        self.model.add_unit(Unit(symbol, dimension, pow10))

    def parse_root(self, node):
        """
        Parse the <lems> (root) element of a LEMS file
        
        @param node: Node containing the <LEMS> element
        @type node: xml.etree.Element
        """

        if node.tag.lower() != 'lems':
            self.raise_error('Not a LEMS file')

        self.xml_node_stack = [node] + self.xml_node_stack
        self.process_nested_tags(node)
        self.xml_node_stack = self.xml_node_stack[1:]

    def parse_file(self, filename):
        """
        Parse a LEMS file and generate a LEMS model

        @param filename: Path to the LEMS file to be parsed
        @type filename: string
        """

        root = xml.parse(filename).getroot()
        xmltolower(root)

        self.base_path = os.path.dirname(filename)
        if self.base_path == '':
            self.base_path = '.'

        context = Context('__root_context__', self.current_context)
        if self.model.context == None:
            self.model.context = context

        self.push_context(context)

        self.parse_root(root)

        self.pop_context()

    def parse_string(self, str):
        pass
Beispiel #20
0
        return ""
    return "<br/>%s<span %s><i>%s</i></span>"%(spacer4,grey_small_style_dark, desc)


files = ["Cells", "Synapses", "Channels", "Inputs", "Networks", "PyNN", "NeuroMLCoreDimensions", "NeuroMLCoreCompTypes"]

comp_types = {}
comp_type_src = {}
comp_type_desc = {}
ordered_comp_types = {}


for file in files:
    fullfile = "%s/%s.xml"%(nml_src,file)
    print "\n----------  Reading LEMS file: "+fullfile
    model = Model(include_includes=False)
    model.import_from_file(fullfile)
    
    for comp_type in model.component_types:
        comp_types[comp_type.name] = comp_type
        comp_type_src[comp_type.name] = file
        comp_type_desc[comp_type.name] = comp_type.description if comp_type.description is not None else "ComponentType: "+comp_type.name
    ordered_comp_type_list = []
    with open(fullfile) as fp:
        for line in fp:
            s = '<ComponentType name='
            if s in line:
                i = line.index(s)
                e = line.find('"', i+len(s)+1)
                comp_type_defined = line[i+len(s)+1: e]
                ordered_comp_type_list.append(comp_type_defined)
Beispiel #21
0
    def get_model(self):

        model = Model()

        model.add(Dimension('voltage', m=1, l=3, t=-3, i=-1))
        model.add(Dimension('time', t=1))
        model.add(Dimension('capacitance', m=-1, l=-2, t=4, i=2))
        model.add(Dimension('conductanceDensity', m="-1", l="-4", t="3", i="2"))
        model.add(Dimension('temperature', k=1))

        model.add(Unit('volt', 'V', 'voltage', 0))
        model.add(Unit('milliVolt', 'mV', 'voltage', -3))
        model.add(Unit('milliSecond', 'ms', 'time', -3))
        model.add(Unit('microFarad', 'uF', 'capacitance', -12))
        model.add(Unit('mS_per_cm2', 'mS_per_cm2', 'conductanceDensity', 1))

        model.add(Unit('Kelvin', 'K', 'temperature', 0))
        model.add(Unit('celsius', 'degC', 'temperature', 0, offset=273.15))
        
        model.add(Unit('hour', 'hour', 'time', scale=3600))
        model.add(Unit('min', 'min', 'time', scale=60))

        return model
Beispiel #22
0
    dlems_file = open(dlems_file_name, 'w')

    dlems_file.write(json.dumps(dlems, indent=4, separators=(',', ': ')))

    dlems_file.close()

    reopen = open(dlems_file_name, 'r')
    print(reopen.read())
    reopen.close()

    print("Written to %s" % dlems_file_name)


if __name__ == '__main__':
    model = Model()

    try:
        lems_file = sys.argv[1]
    except:
        lems_file = '../NeuroML2/LEMSexamples/LEMS_NML2_Ex9_FN.xml'
        model.add_include_directory('../NeuroML2/NeuroML2CoreTypes')

    print('Importing LEMS file from: %s' % lems_file)
    model.import_from_file(lems_file)

    target = model.targets[0]

    sim_comp = model.components[target]

    target_net = sim_comp.parameters['target']
Beispiel #23
0
#! /usr/bin/python

from lems.model.model import Model
import sys

model = Model()

file_name = 'examples/hhcell.xml'
#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex0_IaF.xml'
#file_name = '../NeuroML2/NeuroML2CoreTypes/LEMS_NML2_Ex3_Net.xml'
#file_name = '../org.neuroml.import/src/test/resources/BIOMD0000000185_LEMS.xml'

if len(sys.argv) == 2:
    file_name = sys.argv[1] 

model.import_from_file(file_name)

fn = '/tmp/hhmodel.xml'
model.export_to_file(fn)

print("----------------------------------------------")
print(open(fn,'r').read())
print("----------------------------------------------")

print("Written generated LEMS to %s"%fn)

from lems.base.util import validate_lems

validate_lems(fn)