NeuroML 2 and LEMS#
LEMS is an XML based language originally developed by Robert Cannon for specifying generic models of hybrid dynamical systems. Models defined in LEMS can also be simulated directly through a native interpreter.
ComponentType elements define the behaviour of a specific type of model and specify Parameters, StateVariables, and their Dynamics and Structure can be defined as templates for model elements (e.g. HH ion channels, abstract cells, etc.). The notion of a ComponentType is thus similar to that of a class in object oriented programming.
Components are instances of these types, with specific values of Parameters (e.g. HH squid axon Na+ channel, I&F cell with threshold -60mV, etc.). Components play the same role as objects in object oriented programming.
On the left side of the figure, examples are shown of the (truncated) XML representations of:
(green) a spiking neuron model as described by Izhikevich (2003);
(yellow) a conductance based synapse with a single exponential decay waveform.
On the right, the definition of the structure and dynamics of these elements in the LEMS language is shown. Each element has a corresponding ComponentType definition, describing the parameters (as well as their dimensions, not shown) and the dynamics in terms of state variables and their derivatives, any derived variables, and the behaviour when certain conditions are met or events are received (for example, the emission of a spike after a given threshold is crossed).
NeuroML 2 Component Type definitions in LEMS#
The standard set of ComponentType definitions for the core NeuroML2 elements are contained in a curated set of files (below) though users are free to define their own ComponentTypes to extend the scope of the language.
<xs:complexType name="Izhikevich2007Cell"> <xs:complexContent> <xs:extension base="BaseCellMembPotCap"> <xs:attribute name="v0" type="Nml2Quantity_voltage" use="required"/> <xs:attribute name="k" type="Nml2Quantity_conductancePerVoltage" use="required"/> <xs:attribute name="vr" type="Nml2Quantity_voltage" use="required"/> <xs:attribute name="vt" type="Nml2Quantity_voltage" use="required"/> <xs:attribute name="vpeak" type="Nml2Quantity_voltage" use="required"/> <xs:attribute name="a" type="Nml2Quantity_pertime" use="required"/> <xs:attribute name="b" type="Nml2Quantity_conductance" use="required"/> <xs:attribute name="c" type="Nml2Quantity_voltage" use="required"/> <xs:attribute name="d" type="Nml2Quantity_current" use="required"/> </xs:extension> </xs:complexContent> </xs:complexType>
Correspondingly, its ComponentType dynamics are defined in the LEMS file, Cells.xml. (Note: you do not need to read the XML LEMS definitions, you can see this information in a well formatted form here in the documentation itself)
<ComponentType name="izhikevich2007Cell" extends="baseCellMembPotCap" description="Cell based on the modified Izhikevich model in Izhikevich 2007, Dynamical systems in neuroscience, MIT Press"> <Parameter name="v0" dimension="voltage"/> <!-- Defined in baseCellMembPotCap: <Parameter name="C" dimension="capacitance"/> --> <Parameter name="k" dimension="conductance_per_voltage"/> <Parameter name="vr" dimension="voltage"/> <Parameter name="vt" dimension="voltage"/> <Parameter name="vpeak" dimension="voltage"/> <Parameter name="a" dimension="per_time"/> <Parameter name="b" dimension="conductance"/> <Parameter name="c" dimension="voltage"/> <Parameter name="d" dimension="current"/> <Attachments name="synapses" type="basePointCurrent"/> <Exposure name="u" dimension="current"/> <Dynamics> <StateVariable name="v" dimension="voltage" exposure="v"/> <StateVariable name="u" dimension="current" exposure="u"/> <DerivedVariable name="iSyn" dimension="current" exposure="iSyn" select="synapses[*]/i" reduce="add" /> <DerivedVariable name="iMemb" dimension="current" exposure="iMemb" value="k * (v-vr) * (v-vt) + iSyn - u"/> <TimeDerivative variable="v" value="iMemb / C"/> <TimeDerivative variable="u" value="a * (b * (v-vr) - u)"/> <OnStart> <StateAssignment variable="v" value="v0"/> <StateAssignment variable="u" value="0"/> </OnStart> <OnCondition test="v .gt. vpeak"> <StateAssignment variable="v" value="c"/> <StateAssignment variable="u" value="u + d"/> <EventOut port="spike"/> </OnCondition> </Dynamics> </ComponentType>
We can define Components of the izhikevich2007Cell ComponentType with the parameters we need. For example, the izhikevich2007Cell neuron model can exhibit different spiking behaviours, so we can define a regular spiking Component, or another Component that exhibits bursting.
<izhikevich2007Cell id="iz2007RS" v0 = "-60mV" C="100 pF" k = "0.7 nS_per_mV" vr = "-60 mV" vt = "-40 mV" vpeak = "35 mV" a = "0.03 per_ms" b = "-2 nS" c = "-50 mV" d = "100 pA"/>
Once these Components are defined in the NeuroML document, we can use Instances of them to create populations and networks, and so on.
You don’t have to write in XML…
A quick reminder that while XML files can be edited in a standard text editor, you generally don’t have to create/update them by hand. This guide goes through the steps of creating an example using the izhikevich2007Cell model in Python using libNeuroML and pyNeuroML
Using LEMS to specify the core of NeuroML version 2 has the following significant advantages:
NeuroML 2 XML files can be used standalone by applications (exported/imported) in the same way as NeuroML v1.x, without reference to the LEMS definitions, easing the transition for v1.x compliant applications
Any NeuroML 2 ComponentType can be extended and will be usable/translatable by any application (e.g. jLEMS) which understands LEMS
The first point above means that a parsing application does not necessarily have to natively read the LEMS type definition for, e.g. an izhikevich2007Cell element: it just has to map the NeuroML element parameters onto its own object model implementing that entity. Ideally, the behaviour should be the same − which could be ascertained by testing against the reference LEMS interpreter implementation (jLEMS).
The second point above means that if an application does support LEMS, it can automatically parse (and generate code for) a wide range of NeuroML 2 cells, channels and synapses, including any new ComponentType derived from these, without having to natively know anything about channels, cell models, etc.
While the tutorials cover many of the key points of using LEMS with NeuroML, there are some points which require further explanation: