Exemple #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)
Exemple #2
0
 def add_synapses(self, obj):
     """
     TO DO - not ready to use
     Adds synapses to the model.
     Parameters
     ----------
     obj : brian2.Synapse
         Synapse object
     """
     synapse_ct = lems.ComponentType('Synapse')
     dynamics_synapse = lems.Dynamics()
     synapse_ct.add(dynamics_synapse)
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
Exemple #4
0
#! /usr/bin/python

import lems.api as lems

model = lems.Model()

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

model.add(lems.Unit('milliVolt', 'mV', 'voltage', -3))
model.add(lems.Unit('milliSecond', 'ms', 'time', -3))
model.add(lems.Unit('microFarad', 'uF', 'capacitance', -12))

iaf1 = lems.ComponentType('iaf1')
model.add(iaf1)

iaf1.add(lems.Parameter('threshold', 'voltage'))
iaf1.add(lems.Parameter('reset', 'voltage'))
iaf1.add(lems.Parameter('refractoryPeriod', 'time'))
iaf1.add(lems.Parameter('capacitance', 'capacitance'))
iaf1.add(lems.Exposure('vexp', 'voltage'))
dp = lems.DerivedParameter('range', 'threshold - reset', 'voltage')
iaf1.add(dp)

iaf1.dynamics.add(lems.StateVariable('v','voltage', 'vexp')) 
iaf1.dynamics.add(lems.DerivedVariable('v2',dimension='voltage', value='v*2'))
cdv = lems.ConditionalDerivedVariable('v_abs','voltage')
cdv.add(lems.Case('v .geq. 0','v'))
cdv.add(lems.Case('v .lt. 0','-1*v'))
iaf1.dynamics.add(cdv)
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
Exemple #6
0
    def add_neurongroup(self, neurongrp, index_neurongrp, initializers):
        """
        Add NeuronGroup to self._model
    
        If number of elements is 1 it adds component of that type, if
        it's bigger, the network is created by calling:
        `make_multiinstantiate`.

        Parameters
        ----------
        neurongrp : dict
            Standard dictionary representation of NeuronGroup object
        index_neurongrp : int
            Index of neurongroup in the network
        initializers : list
            List of initializers defined in the network
        """
        # get name of the neurongrp
        component_name = neurongrp['name']
        self._model_namespace["neuronname"] = component_name
        # add BASE_CELL component
        self._component_type = lems.ComponentType(component_name,
                                                  extends=BASE_CELL)
        # get identifiers attached to neurongrp and create special_properties dict
        identifiers = []
        special_properties = {}

        if 'identifiers' in neurongrp:
            identifiers = neurongrp['identifiers']

        for initializer in initializers:
            if 'identifiers' in initializer:
                identifiers.update(initializer['identifiers'])

        for identifier in identifiers.keys():
            special_properties.update({identifier: None})

        # add the identifers as properties of the component
        for param in self._determine_properties(identifiers):
            self._component_type.add(param)
        # common things for every neuron definition
        # TODO: Is this same for custom events too?
        self._component_type.add(lems.EventPort(name='spike', direction='out'))

        # dynamics of the network
        dynamics = lems.Dynamics()
        # get neurongrp equations
        equations = neurongrp['equations']
        # loop over the variables
        initializer_vars = []
        for initializer in initializers:
            if initializer['source'] == neurongrp['name']:
                initializer_vars.append(initializer['variable'])

        for var in equations.keys():

            # determine the dimension
            dimension = _determine_dimension(equations[var]['unit'])
            # add to all_params_unit
            self._all_params_unit[var] = dimension
            # identify diff eqns to add Exposure
            if equations[var]['type'] == 'differential equation':
                state_var = lems.StateVariable(var,
                                               dimension=dimension,
                                               exposure=var)
                self._component_type.add(
                    lems.Exposure(var, dimension=dimension))
                dynamics.add_state_variable(state_var)
            else:
                if var in initializer_vars and 'i' in initializer['value']:
                    self._component_type.add(lems.Property(var, dimension))
                    special_properties[var] = initializer['value']
                    continue
                state_var = lems.StateVariable(var, dimension=dimension)
                dynamics.add_state_variable(state_var)

        # what happens at initialization
        onstart = lems.OnStart()
        # loop over the initializers
        for var in equations.keys():
            if var in (NOT_REFRACTORY, LAST_SPIKE):
                continue
            # check the initializer is connected to this neurongrp
            if var not in initializer_vars:
                continue
            if var in special_properties:
                continue
            for initializer in initializers:
                if initializer['variable'] == var and initializer[
                        'source'] == neurongrp['name']:
                    init_value = initializer['value']
            if type(init_value) != str:
                value = brian_unit_to_lems(init_value)
            else:
                value = renderer.render_expr(str(init_value))
            # add to onstart
            onstart.add(lems.StateAssignment(var, value))
        dynamics.add(onstart)

        # check whether refractoriness is defined
        if ('events' in neurongrp and 'spike' in neurongrp['events']
                and 'refractory' in neurongrp['events']['spike']):
            # if refractoriness, we create separate regimes for integrating
            integr_regime = lems.Regime(INTEGRATING, dynamics,
                                        True)  # True -> initial regime
            # check spike event
            # NOTE: isn't refractory only for spike events?
            for spike_flag, on_cond in self._event_builder(
                    neurongrp['events']):
                if spike_flag:
                    # if spike occured we make transition to refractory regime
                    on_cond.add_action(lems.Transition(REFRACTORY))
                integr_regime.add_event_handler(on_cond)
            # add refractory regime
            refrac_regime = lems.Regime(REFRACTORY, dynamics)
            # make lastspike variable and initialize it
            refrac_regime.add_state_variable(
                lems.StateVariable(LAST_SPIKE, dimension='time'))
            oe = lems.OnEntry()
            oe.add(lems.StateAssignment(LAST_SPIKE, 't'))
            refrac_regime.add(oe)
            # after refractory time we make transition to integrating regime
            refractory_code = neurongrp['events']['spike']['refractory']
            if not _equation_separator(str(refractory_code)):
                # if there is no specific variable given, we assume
                # that this is time condition
                ref_oc = lems.OnCondition('t .gt. ( {0} + {1} )'.format(
                    LAST_SPIKE, brian_unit_to_lems(refractory_code)))
            else:
                ref_oc = lems.OnCondition(
                    renderer.render_expr(refractory_code))
            ref_trans = lems.Transition(INTEGRATING)
            ref_oc.add_action(ref_trans)
            refrac_regime.add_event_handler(ref_oc)
            # identify variables with differential equation
            for var in neurongrp['equations']:
                if neurongrp['equations'][var][
                        'type'] == 'differential equation':
                    diff_var = neurongrp['equations'][var]
                    # get the expression
                    td = lems.TimeDerivative(
                        var, renderer.render_expr(diff_var['expr']))
                    # check flags for UNLESS_REFRACTORY TODO: is this available in 'flags' key?
                    if 'flags' in diff_var:
                        # if unless refratory we add only do integration regime
                        if UNLESS_REFRACTORY in diff_var['flags']:
                            integr_regime.add_time_derivative(td)
                            continue
                    # add time derivative to both regimes
                    integr_regime.add_time_derivative(td)
                    refrac_regime.add_time_derivative(td)
            # add the regimes to dynamics
            dynamics.add_regime(integr_regime)
            dynamics.add_regime(refrac_regime)

        else:
            # adding events directly to dynamics
            for spike_flag, on_cond in self._event_builder(
                    neurongrp['events']):
                dynamics.add_event_handler(on_cond)
            # get variables with diff eqns
            for var in neurongrp['equations']:
                if neurongrp['equations'][var][
                        'type'] == 'differential equation':
                    diff_var = neurongrp['equations'][var]
                    td = lems.TimeDerivative(
                        var, renderer.render_expr(diff_var['expr']))
                    # add to dynamics
                    dynamics.add_time_derivative(td)
        # add dynamics to _component_type
        self._component_type.dynamics = dynamics
        # add _component_type to _model
        self._model.add_component_type(self._component_type)
        # get identifiers
        paramdict = dict()
        for ident_name, ident_value in neurongrp['identifiers'].items():
            paramdict[ident_name] = self._unit_lems_validator(ident_value)
        # if more than one neuron use multiinstantiate
        if neurongrp['N'] == 1:
            self._model.add(
                lems.Component("n{}".format(index_neurongrp), component_name,
                               **paramdict))
        else:
            self.make_multiinstantiate(special_properties, component_name,
                                       paramdict, neurongrp['N'])
Exemple #7
0
#!/usr/bin/env python3

import lems.api as lems
from lems.base.util import validate_lems

model = lems.Model()

model.add(lems.Dimension(name="time", t=1))
model.add(lems.Unit(name="second", symbol="s", dimension="time", power=1))
model.add(
    lems.Unit(name="milli second", symbol="ms", dimension="time", power=-3))

lorenz = lems.ComponentType(
    name="lorenz1963",
    description=
    "The Lorenz system is a simplified model for atomspheric convection, derived from the Navier Stokes equations"
)
model.add(lorenz)

lorenz.add(
    lems.Parameter(name="sigma",
                   dimension="none",
                   description="Prandtl Number"))
lorenz.add(
    lems.Parameter(name="beta",
                   dimension="none",
                   description="Also named b elsewhere"))
lorenz.add(
    lems.Parameter(
        name="rho",
        dimension="none",
Exemple #8
0
    def add_neurongroup(self, obj, idx_of_ng, namespace, initializers):
        """
        Adds NeuronGroup object *obj* to self._model.

        If number of elements is 1 it adds component of that type, if
        it's bigger, the network is created by calling:
        `make_multiinstantiate`.

        Parameters
        ----------
        obj : brian2.NeuronGroup
            NeuronGroup object to parse
        idx_of_ng : int
            index of neurongroup
        namespace : dict
            dictionary with all neccassary variables definition
        initializers : dict
            initial values for all model variables
        """
        if hasattr(obj, "namespace") and not obj.namespace:
            obj.namespace = namespace
        self._nr_of_neurons = obj.N  # maybe not the most robust solution
        ct_name = "neuron{}".format(idx_of_ng+1)
        self._model_namespace["neuronname"] = ct_name
        self._component_type = lems.ComponentType(ct_name, extends=BASE_CELL)
        # adding parameters
        special_properties = {}
        for key in obj.namespace.keys():
            special_properties[key] = None
        for param in self._determine_properties(obj.namespace):
            self._component_type.add(param)
        # common things for every neuron definition
        self._component_type.add(lems.EventPort(name='spike', direction='out'))
        # dynamics of the network
        dynamics = lems.Dynamics()
        ng_equations = obj.user_equations
        for var in ng_equations:
            if ng_equations[var].type == DIFFERENTIAL_EQUATION:
                dim_ = _determine_dimension(ng_equations[var].unit)
                sv_ = lems.StateVariable(var, dimension=dim_, exposure=var)
                self._all_params_unit[var] = dim_
                dynamics.add_state_variable(sv_)
                self._component_type.add(lems.Exposure(var, dimension=dim_))
            elif ng_equations[var].type in (PARAMETER, SUBEXPRESSION):
                if var == NOT_REFRACTORY:
                    continue
                dim_ = _determine_dimension(ng_equations[var].unit)
                self._all_params_unit[var] = dim_
                # all initializers contatining iterator need to be assigned
                # as a property
                # i is default iterator in Brian2
                if var in initializers and "i" in get_identifiers(str(initializers[var])):
                    self._component_type.add(lems.Property(var, dim_))
                    special_properties[var] = initializers[var]
                    continue
                sv_ = lems.StateVariable(var, dimension=dim_)
                dynamics.add_state_variable(sv_)
        # what happens at initialization
        onstart = lems.OnStart()
        for var in obj.equations.names:
            if var in (NOT_REFRACTORY, LAST_SPIKE):
                continue
            if var not in initializers:
                continue
            if var in special_properties:
                continue
            init_value = initializers[var]
            if type(init_value) != str:
                init_value = brian_unit_to_lems(init_value)
            else:
                init_value = renderer.render_expr(str(init_value))
            onstart.add(lems.StateAssignment(var, init_value))
        dynamics.add(onstart)

        if obj._refractory:
            # if refractoriness, we create separate regimes
            # - for integrating
            integr_regime = lems.Regime(INTEGRATING, dynamics, True)  # True -> initial regime
            for spike_flag, oc in self._event_builder(obj.events, obj.event_codes):
                if spike_flag:
                    # if spike occured we make transition to refractory regime
                    oc.add_action(lems.Transition(REFRACTORY))
                integr_regime.add_event_handler(oc)
            # - for refractory
            refrac_regime = lems.Regime(REFRACTORY, dynamics)
            # we make lastspike variable and initialize it
            refrac_regime.add_state_variable(lems.StateVariable(LAST_SPIKE, dimension='time'))
            oe = lems.OnEntry()
            oe.add(lems.StateAssignment(LAST_SPIKE, 't'))
            refrac_regime.add(oe)
            # after time spiecified in _refractory we make transition
            # to integrating regime
            if not _equation_separator(str(obj._refractory)):
                # if there is no specific variable given, we assume
                # that this is time condition
                ref_oc = lems.OnCondition('t .gt. ( {0} + {1} )'.format(LAST_SPIKE, brian_unit_to_lems(obj._refractory)))
            else:
                ref_oc = lems.OnCondition(renderer.render_expr(obj._refractory))
            ref_trans = lems.Transition(INTEGRATING)
            ref_oc.add_action(ref_trans)
            refrac_regime.add_event_handler(ref_oc)
            for var in obj.user_equations.diff_eq_names:
                td = lems.TimeDerivative(var, renderer.render_expr(str(ng_equations[var].expr)))
                # if unless refratory we add only do integration regime
                if UNLESS_REFRACTORY in ng_equations[var].flags:
                    integr_regime.add_time_derivative(td)
                    continue
                integr_regime.add_time_derivative(td)
                refrac_regime.add_time_derivative(td)
            dynamics.add_regime(integr_regime)
            dynamics.add_regime(refrac_regime)
        else:
            # here we add events directly to dynamics
            for spike_flag, oc in self._event_builder(obj.events, obj.event_codes):
                dynamics.add_event_handler(oc)
            for var in obj.user_equations.diff_eq_names:
                td = lems.TimeDerivative(var, renderer.render_expr(str(ng_equations[var].expr)))
                dynamics.add_time_derivative(td)

        self._component_type.dynamics = dynamics
        # making componenttype is done so we add it to the model
        self._model.add_component_type(self._component_type)
        obj.namespace.pop("init", None)                # kick out init
        # adding component to the model
        paramdict = dict()
        for param in obj.namespace:
            paramdict[param] = self._unit_lems_validator(obj.namespace[param])
        if obj.N == 1:
            self._model.add(lems.Component("n{}".format(idx_of_ng), ct_name, **paramdict))
        else:
            self.make_multiinstantiate(special_properties, ct_name, paramdict)
Exemple #9
0
def mdf_to_neuroml(graph, save_to=None, format=None, run_duration_sec=2):

    print("Converting graph: %s to NeuroML" % (graph.id))

    net = neuromllite.Network(id=graph.id)
    net.notes = "NeuroMLlite export of {} graph: {}".format(
        format if format else "MDF",
        graph.id,
    )

    model = lems.Model()
    lems_definitions = "%s_lems_definitions.xml" % graph.id

    for node in graph.nodes:
        print("    Node: %s" % node.id)

        node_comp_type = "%s__definition" % node.id
        node_comp = "%s__instance" % node.id

        # Create the ComponentType which defines behaviour of the general class
        ct = lems.ComponentType(node_comp_type, extends="baseCellMembPotDL")
        ct.add(lems.Attachments("only_input_port", "basePointCurrentDL"))
        ct.dynamics.add(
            lems.DerivedVariable(name="V",
                                 dimension="none",
                                 value="0",
                                 exposure="V"))
        model.add(ct)

        # Define the Component - an instance of the ComponentType
        comp = lems.Component(node_comp, node_comp_type)
        model.add(comp)

        cell = neuromllite.Cell(id=node_comp,
                                lems_source_file=lems_definitions)
        net.cells.append(cell)

        pop = neuromllite.Population(
            id=node.id,
            size=1,
            component=cell.id,
            properties={
                "color": "0.2 0.2 0.2",
                "radius": 3
            },
        )
        net.populations.append(pop)

        if len(node.input_ports) > 1:
            raise Exception(
                "Currently only max 1 input port supported in NeuroML...")

        for ip in node.input_ports:
            ct.add(lems.Exposure(ip.id, "none"))
            ct.dynamics.add(
                lems.DerivedVariable(
                    name=ip.id,
                    dimension="none",
                    select="only_input_port[*]/I",
                    reduce="add",
                    exposure=ip.id,
                ))

        on_start = None

        for p in node.parameters:
            print("Converting %s" % p)
            if p.value is not None:
                try:
                    v_num = float(p.value)
                    ct.add(lems.Parameter(p.id, "none"))
                    comp.parameters[p.id] = v_num
                    print(comp.parameters[p.id])
                except Exception as e:

                    ct.add(lems.Exposure(p.id, "none"))
                    dv = lems.DerivedVariable(
                        name=p.id,
                        dimension="none",
                        value="%s" % (p.value),
                        exposure=p.id,
                    )
                    ct.dynamics.add(dv)

            elif p.function is not None:
                ct.add(lems.Exposure(p.id, "none"))
                func_info = mdf_functions[p.function]
                expr = func_info["expression_string"]
                expr2 = substitute_args(expr, p.args)
                for arg in p.args:
                    expr += ";{}={}".format(arg, p.args[arg])
                dv = lems.DerivedVariable(name=p.id,
                                          dimension="none",
                                          value="%s" % (expr2),
                                          exposure=p.id)
                ct.dynamics.add(dv)
            else:
                ct.add(lems.Exposure(p.id, "none"))
                ct.dynamics.add(
                    lems.StateVariable(name=p.id,
                                       dimension="none",
                                       exposure=p.id))
                if p.default_initial_value:
                    if on_start is None:
                        on_start = lems.OnStart()
                        ct.dynamics.add(on_start)
                    sa = lems.StateAssignment(
                        variable=p.id,
                        value=str(evaluate_expr(p.default_initial_value)))
                    on_start.actions.append(sa)

                if p.time_derivative:
                    td = lems.TimeDerivative(variable=p.id,
                                             value=p.time_derivative)
                    ct.dynamics.add(td)

        if len(node.output_ports) > 1:
            raise Exception(
                "Currently only max 1 output port supported in NeuroML...")

        for op in node.output_ports:
            ct.add(lems.Exposure(op.id, "none"))
            ct.dynamics.add(
                lems.DerivedVariable(name=op.id,
                                     dimension="none",
                                     value=op.value,
                                     exposure=op.id))
            only_output_port = "only_output_port"
            ct.add(lems.Exposure(only_output_port, "none"))
            ct.dynamics.add(
                lems.DerivedVariable(
                    name=only_output_port,
                    dimension="none",
                    value=op.id,
                    exposure=only_output_port,
                ))

    if len(graph.edges) > 0:

        model.add(
            lems.Include(
                os.path.join(os.path.dirname(__file__),
                             "syn_definitions.xml")))
        rsDL = neuromllite.Synapse(id="rsDL",
                                   lems_source_file=lems_definitions)
        net.synapses.append(rsDL)
        # syn_id = 'silentSyn'
        # silentSynDL = neuromllite.Synapse(id=syn_id, lems_source_file=lems_definitions)

    for edge in graph.edges:
        print(f"    Edge: {edge.id} connects {edge.sender} to {edge.receiver}")

        ssyn_id = "silentSyn_proj_%s" % edge.id
        ssyn_id = "silentSyn_proj_%s" % edge.id
        # ssyn_id = 'silentSynX'
        silentDLin = neuromllite.Synapse(id=ssyn_id,
                                         lems_source_file=lems_definitions)

        model.add(lems.Component(ssyn_id, "silentRateSynapseDL"))

        net.synapses.append(silentDLin)

        net.projections.append(
            neuromllite.Projection(
                id="proj_%s" % edge.id,
                presynaptic=edge.sender,
                postsynaptic=edge.receiver,
                synapse=rsDL.id,
                pre_synapse=silentDLin.id,
                type="continuousProjection",
                weight=1,
                random_connectivity=neuromllite.RandomConnectivity(
                    probability=1),
            ))

    # Much more todo...
    model.export_to_file(lems_definitions)

    print("Nml net: %s" % net)
    if save_to:
        new_file = net.to_json_file(save_to)
        print("Saved NML to: %s" % save_to)

    ################################################################################
    ###   Build Simulation object & save as JSON

    simtime = 1000 * run_duration_sec
    dt = 0.1
    sim = neuromllite.Simulation(
        id="Sim%s" % net.id,
        network=new_file,
        duration=simtime,
        dt=dt,
        seed=123,
        recordVariables={"OUTPUT": {
            "all": "*"
        }},
    )

    recordVariables = {}
    for node in graph.nodes:
        for ip in node.input_ports:
            if not ip.id in recordVariables:
                recordVariables[ip.id] = {}
            recordVariables[ip.id][node.id] = 0

        for p in node.parameters:
            if p.is_stateful():
                if not p.id in recordVariables:
                    recordVariables[p.id] = {}
                recordVariables[p.id][node.id] = 0

        for op in node.output_ports:
            if not op.id in recordVariables:
                recordVariables[op.id] = {}
            recordVariables[op.id][node.id] = 0

    sim.recordVariables = recordVariables
    if save_to:
        sf = sim.to_json_file()

        print("Saved Simulation to: %s" % sf)

    return net, sim