Example #1
0
    def make_multiinstantiate(self, special_properties, name, parameters):
        """
        Adds ComponentType with MultiInstantiate in order to make
        a population of neurons.

        Parameters
        ----------
        special_properties : dict
            all variables to be defined in MultiInstantiate
        name : str
            MultiInstantiate component name
        parameters : dict
            all extra parameters needed
        """
        PARAM_SUBSCRIPT = "_p"
        self._model_namespace["ct_populationname"] = name+"Multi"
        multi_ct = lems.ComponentType(self._model_namespace["ct_populationname"], extends=BASE_POPULATION)
        structure = lems.Structure()
        multi_ins = lems.MultiInstantiate(component_type=name,
                                          number="N")
        param_dict = {}
        # number of neruons
        multi_ct.add(lems.Parameter(name="N", dimension="none"))
        # other parameters
        for sp in special_properties:
            if special_properties[sp] is None:
                multi_ct.add(lems.Parameter(name=sp+PARAM_SUBSCRIPT, dimension=self._all_params_unit[sp]))
                multi_ins.add(lems.Assign(property=sp, value=sp+PARAM_SUBSCRIPT))
                param_dict[sp] = parameters[sp]
            else:
                # multi_ct.add(lems.Parameter(name=sp, dimension=self._all_params_unit[sp]))
                # check if there are some units in equations
                equation = special_properties[sp]
                # add spaces around brackets to prevent mismatching
                equation = re.sub("\(", " ( ", equation)
                equation = re.sub("\)", " ) ", equation)
                for i in get_identifiers(equation):
                    # iterator is a special case
                    if i == "i":
                        regexp_noletter = "[^a-zA-Z0-9]"
                        equation = re.sub("{re}i{re}".format(re=regexp_noletter),
                                                  " {} ".format(INDEX), equation)
                    # here it's assumed that we don't use Netwton in neuron models
                    elif i in name_to_unit and i != "N":
                        const_i = i+'const'
                        multi_ct.add(lems.Constant(name=const_i, symbol=const_i,
                                     dimension=self._all_params_unit[sp], value="1"+i))
                        equation = re.sub(i, const_i, equation)
                multi_ins.add(lems.Assign(property=sp, value=equation))
        structure.add(multi_ins)
        multi_ct.structure = structure
        self._model.add(multi_ct)
        param_dict = dict([(k+"_p", v) for k, v in param_dict.items()])
        param_dict["N"] = self._nr_of_neurons
        self._model_namespace["populationname"] = self._model_namespace["ct_populationname"] + "pop"
        self._model_namespace["networkname"] = self._model_namespace["ct_populationname"] + "Net"
        self.add_population(self._model_namespace["networkname"],
                            self._model_namespace["populationname"],
                            self._model_namespace["ct_populationname"],
                            **param_dict)
def build_lems_for_model(src):
    model = lems.Model()

    model.add(lems.Dimension('time', t=1))
    # model.add(lems.Dimension('au'))

    # primary element of the model is a mass model component
    mass = lems.ComponentType(src.name, extends="baseCellMembPot")
    model.add(mass)
    
    ######### Adding v is required to ease mapping to NEURON...
    mass.dynamics.add(lems.StateVariable(name="v", dimension="voltage", exposure="v"))
    
    mass.add(lems.Attachments(name="synapses",type_="basePointCurrentDL"))
    

    for input in src.input:
        mass.dynamics.add(lems.DerivedVariable(name=input, 
                                               dimension='none',
                                               exposure=input,
                                               select='synapses[*]/I',
                                               reduce='add'))
        mass.add(lems.Exposure(input, 'none'))
        
        
    for key, val in src.const.items():
        mass.add(lems.Parameter(key, 'none'))  # TODO units
        
    
        
    mass.add(lems.Constant(name="MSEC", dimension="time", value="1ms"))
    mass.add(lems.Constant(name="PI", dimension="none", value="3.14159265359"))

    states = []
    der_vars = []
    # for key in src.param:
    #     mass.add(lems.Parameter(key, 'au'))  # TODO units

    for key, val in src.auxex:
        val = val.replace('**', '^')
        mass.dynamics.add(lems.DerivedVariable(key, value=val))

    for key in src.obsrv:
        name_dv = key.replace('(','_').replace(')','').replace(' - ','_min_')
        mass.dynamics.add(lems.DerivedVariable(name_dv, value=key, exposure=name_dv))
        mass.add(lems.Exposure(name_dv, 'none'))

    for src_svar in src.state_space:
        name = src_svar.name
        ddt = src_svar.drift.replace('**', '^')
        mass.dynamics.add(lems.StateVariable(name, 'none', name))
        mass.dynamics.add(lems.TimeDerivative(name, '(%s)/MSEC'%ddt))
        mass.add(lems.Exposure(name, 'none'))
        
    ''' On condition is not need on the model but NeuroML requires its definition -->
            <OnCondition test="r .lt. 0">
                <EventOut port="spike"/>
            </OnCondition>'''
            
    oc = lems.OnCondition(test='v .gt. 0')
    oc.actions.append(lems.EventOut(port='spike'))
    mass.dynamics.add(oc)

    return model
def channelpedia_xml_to_neuroml2(cpd_xml, nml2_file_name, unknowns=""):


    info = 'Automatic conversion of Channelpedia XML file to NeuroML2\n'+\
           'Uses: https://github.com/OpenSourceBrain/BlueBrainProjectShowcase/blob/master/Channelpedia/ChannelpediaToNeuroML2.py'
    print(info)

    root = ET.fromstring(cpd_xml)

    channel_id = 'Channelpedia_%s_%s' % (root.attrib['ModelName'].replace(
        "/", "_").replace(" ", "_").replace(".", "_"), root.attrib['ModelID'])

    doc = neuroml.NeuroMLDocument()

    metadata = osb.metadata.RDF(info)

    ion = root.findall('Ion')[0]
    chan = neuroml.IonChannelHH(
        id=channel_id,
        conductance='10pS',
        species=ion.attrib['Name'],
        notes=
        "This is an automated conversion to NeuroML 2 of an ion channel model from Channelpedia. "
        +
        "\nThe original channel model file can be found at: http://channelpedia.epfl.ch/ionchannels/%s"
        % root.attrib['ID'] +
        "\n\nConversion scripts at https://github.com/OpenSourceBrain/BlueBrainProjectShowcase"
    )

    chan.annotation = neuroml.Annotation()

    model_url_template = 'http://channelpedia.epfl.ch/ionchannels/%s/hhmodels/%s.xml'
    desc = osb.metadata.Description(channel_id)
    metadata.descriptions.append(desc)
    osb.metadata.add_simple_qualifier(desc, \
                                      'bqmodel', \
                                      'isDerivedFrom', \
                                      model_url_template%(root.attrib['ID'], root.attrib['ModelID']), \
                                      "Channelpedia channel ID: %s, ModelID: %s; direct link to original XML model" % (root.attrib['ID'], root.attrib['ModelID']))

    channel_url_template = 'http://channelpedia.epfl.ch/ionchannels/%s'
    osb.metadata.add_simple_qualifier(desc, \
                                      'bqmodel', \
                                      'isDescribedBy', \
                                      channel_url_template%(root.attrib['ID']), \
                                      "Channelpedia channel ID: %s; link to main page for channel" % (root.attrib['ID']))

    for reference in root.findall('Reference'):
        pmid = reference.attrib['PubmedID']
        #metadata = update_metadata(chan, metadata, channel_id, "http://identifiers.org/pubmed/%s"%pmid)
        ref_info = reference.text
        osb.metadata.add_simple_qualifier(desc, \
                                          'bqmodel', \
                                          'isDescribedBy', \
                                          osb.resources.PUBMED_URL_TEMPLATE % (pmid), \
                                          ("PubMed ID: %s is referenced in original XML\n"+\
                                          "                                 %s") % (pmid, ref_info))

    for environment in root.findall('Environment'):
        for animal in environment.findall('Animal'):

            species = animal.attrib['Name'].lower()

            if species:
                if species in osb.resources.KNOWN_SPECIES:
                    known_id = osb.resources.KNOWN_SPECIES[species]
                    osb.metadata.add_simple_qualifier(desc, \
                                                      'bqbiol', \
                                                      'hasTaxon', \
                                                      osb.resources.NCBI_TAXONOMY_URL_TEMPLATE % known_id, \
                                                      "Known species: %s; taxonomy id: %s" % (species, known_id))
                else:
                    print("Unknown species: %s" % species)
                    unknowns += "Unknown species: %s\n" % species

        for cell_type_el in environment.findall('CellType'):
            cell_type = cell_type_el.text.strip().lower()

            if cell_type:
                if cell_type in osb.resources.KNOWN_CELL_TYPES:
                    known_id = osb.resources.KNOWN_CELL_TYPES[cell_type]
                    osb.metadata.add_simple_qualifier(desc, \
                                                      'bqbiol', \
                                                      'isPartOf', \
                                                      osb.resources.NEUROLEX_URL_TEMPLATE % known_id, \
                                                      "Known cell type: %s; taxonomy id: %s" % (cell_type, known_id))
                else:
                    print("Unknown cell_type: %s" % cell_type)
                    unknowns += "Unknown cell_type: %s\n" % cell_type

    print("Currently unknown: <<<%s>>>" % unknowns)

    comp_types = {}
    for gate in root.findall('Gates'):

        eq_type = gate.attrib['EqType']
        gate_name = gate.attrib['Name']
        target = chan.gates

        if eq_type == '1':
            g = neuroml.GateHHUndetermined(id=gate_name,
                                           type='gateHHtauInf',
                                           instances=int(
                                               float(gate.attrib['Power'])))
        elif eq_type == '2':
            g = neuroml.GateHHUndetermined(id=gate_name,
                                           type='gateHHrates',
                                           instances=int(
                                               float(gate.attrib['Power'])))

        for inf in gate.findall('Inf_Alpha'):
            equation = check_equation(inf.findall('Equation')[0].text)

            if eq_type == '1':
                new_comp_type = "%s_%s_%s" % (channel_id, gate_name, 'inf')
                g.steady_state = neuroml.HHVariable(type=new_comp_type)

                comp_type = lems.ComponentType(
                    new_comp_type, extends="baseVoltageDepVariable")

                comp_type.add(lems.Constant('TIME_SCALE', '1 ms', 'time'))
                comp_type.add(lems.Constant('VOLT_SCALE', '1 mV', 'voltage'))

                comp_type.dynamics.add(
                    lems.DerivedVariable(name='V',
                                         dimension="none",
                                         value="v / VOLT_SCALE"))
                comp_type.dynamics.add(
                    lems.DerivedVariable(name='x',
                                         dimension="none",
                                         value="%s" % equation,
                                         exposure="x"))

                comp_types[new_comp_type] = comp_type

            elif eq_type == '2':
                new_comp_type = "%s_%s_%s" % (channel_id, gate_name, 'alpha')
                g.forward_rate = neuroml.HHRate(type=new_comp_type)

                comp_type = lems.ComponentType(new_comp_type,
                                               extends="baseVoltageDepRate")

                comp_type.add(lems.Constant('TIME_SCALE', '1 ms', 'time'))
                comp_type.add(lems.Constant('VOLT_SCALE', '1 mV', 'voltage'))

                comp_type.dynamics.add(
                    lems.DerivedVariable(name='V',
                                         dimension="none",
                                         value="v / VOLT_SCALE"))
                comp_type.dynamics.add(
                    lems.DerivedVariable(name='r',
                                         dimension="per_time",
                                         value="%s / TIME_SCALE" % equation,
                                         exposure="r"))

                comp_types[new_comp_type] = comp_type

        for tau in gate.findall('Tau_Beta'):
            equation = check_equation(tau.findall('Equation')[0].text)

            if eq_type == '1':
                new_comp_type = "%s_%s_tau" % (channel_id, gate_name)
                g.time_course = neuroml.HHTime(type=new_comp_type)

                comp_type = lems.ComponentType(new_comp_type,
                                               extends="baseVoltageDepTime")

                comp_type.add(lems.Constant('TIME_SCALE', '1 ms', 'time'))
                comp_type.add(lems.Constant('VOLT_SCALE', '1 mV', 'voltage'))

                comp_type.dynamics.add(
                    lems.DerivedVariable(name='V',
                                         dimension="none",
                                         value="v / VOLT_SCALE"))
                comp_type.dynamics.add(
                    lems.DerivedVariable(name='t',
                                         dimension="time",
                                         value="(%s) * TIME_SCALE" % equation,
                                         exposure="t"))

                comp_types[new_comp_type] = comp_type

            elif eq_type == '2':
                new_comp_type = "%s_%s_%s" % (channel_id, gate_name, 'beta')
                g.reverse_rate = neuroml.HHRate(type=new_comp_type)

                comp_type = lems.ComponentType(new_comp_type,
                                               extends="baseVoltageDepRate")

                comp_type.add(lems.Constant('TIME_SCALE', '1 ms', 'time'))
                comp_type.add(lems.Constant('VOLT_SCALE', '1 mV', 'voltage'))

                comp_type.dynamics.add(
                    lems.DerivedVariable(name='V',
                                         dimension="none",
                                         value="v / VOLT_SCALE"))
                comp_type.dynamics.add(
                    lems.DerivedVariable(name='r',
                                         dimension="per_time",
                                         value="%s  / TIME_SCALE" % equation,
                                         exposure="r"))

                comp_types[new_comp_type] = comp_type

        target.append(g)

    doc.ion_channel_hhs.append(chan)

    doc.id = channel_id

    writers.NeuroMLWriter.write(doc, nml2_file_name)

    print("Written NeuroML 2 channel file to: " + nml2_file_name)

    for comp_type_name in comp_types.keys():
        comp_type = comp_types[comp_type_name]
        ct_xml = comp_type.toxml()

        # Quick & dirty pretty printing..
        ct_xml = ct_xml.replace('<Const', '\n        <Const')
        ct_xml = ct_xml.replace('<Dyna', '\n        <Dyna')
        ct_xml = ct_xml.replace('</Dyna', '\n        </Dyna')
        ct_xml = ct_xml.replace('<Deriv', '\n            <Deriv')
        ct_xml = ct_xml.replace('</Compone', '\n    </Compone')

        # print("Adding definition for %s:\n%s\n"%(comp_type_name, ct_xml))
        nml2_file = open(nml2_file_name, 'r')
        orig = nml2_file.read()
        new_contents = orig.replace("</neuroml>",
                                    "\n    %s\n\n</neuroml>" % ct_xml)
        nml2_file.close()
        nml2_file = open(nml2_file_name, 'w')
        nml2_file.write(new_contents)
        nml2_file.close()

    print("Inserting metadata...")
    nml2_file = open(nml2_file_name, 'r')
    orig = nml2_file.read()
    new_contents = orig.replace(
        "<annotation/>", "\n        <annotation>\n%s        </annotation>\n" %
        metadata.to_xml("            "))
    nml2_file.close()
    nml2_file = open(nml2_file_name, 'w')
    nml2_file.write(new_contents)
    nml2_file.close()

    ###### Validate the NeuroML ######

    from neuroml.utils import validate_neuroml2

    validate_neuroml2(nml2_file_name)

    return unknowns
Example #4
0
                   description="Also named b elsewhere"))
lorenz.add(
    lems.Parameter(
        name="rho",
        dimension="none",
        description="Related to the Rayleigh number, also named r elsewhere"))

lorenz.add(lems.Parameter(name="x0", dimension="none"))
lorenz.add(lems.Parameter(name="y0", dimension="none"))
lorenz.add(lems.Parameter(name="z0", dimension="none"))

lorenz.add(lems.Exposure(name="x", dimension="none"))
lorenz.add(lems.Exposure(name="y", dimension="none"))
lorenz.add(lems.Exposure(name="z", dimension="none"))

lorenz.add(lems.Constant(name="sec", value="1s", dimension="time"))

lorenz.dynamics.add(
    lems.StateVariable(name="x", dimension="none", exposure="x"))
lorenz.dynamics.add(
    lems.StateVariable(name="y", dimension="none", exposure="y"))
lorenz.dynamics.add(
    lems.StateVariable(name="z", dimension="none", exposure="z"))

lorenz.dynamics.add(
    lems.TimeDerivative(variable="x", value="( sigma * (y - x)) / sec"))
lorenz.dynamics.add(
    lems.TimeDerivative(variable="y", value="( rho * x - y - x * z ) / sec"))
lorenz.dynamics.add(
    lems.TimeDerivative(variable="z", value="( x * y - beta * z) / sec"))