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
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"))