This page is structured as a walk-through of a single example file example1.xml explaining the various elements as they occur.
The whole model is wrapped in a block which, for now, is called "Lems" (Low Entropy Model Specification). Then we define the dimensions that will be used in this model. Typically these would be loaded from an external file along with various other stuff, not repeated in each model, but it is included here in the interests of having a single file for everything.
Each dimension element just associates a dimension name with the exponents for mass, length, time and current.
At this stage, one can begin defining component types. This is done with the
Each of the
Defining a unit involves supplying the symbol, dimension and the power of ten by which it is scaled from the IS base unit. Note that units have a symbol, not a name. This is because they occur as a component of an assignment expression such as 'threshold="-45mV"' not as a reference such as 'dimension="voltage"'. In general, where one component refers to another, then the attribute value is the name of the thing being referred to, and the attribute name is the lower case version of the type of the thing being referred to. Thus when a dimension is declared with <Dimension name="voltage".../> then it is referred to from a Parameter as <Parameter dimension="voltage"/>. This holds for all references to components of a particular type.
Returning to the units, this model will use the following, which normally would also be loaded from an external file of standard settings.
Once the units are available it is possible to define a component.
There are two equivalent ways of doing this: either
by using the
In specifying a component, a value must be supplied for each of the parameters defined in the corresponding type. The value is composed of a number and a unit. It can't include expressions with multiple units for the values so, for example, to express an acceleration you couldn't write "3 m s^-2". Instead would need to define a unit element for the compound unit (and a dimension element for acceleration) and use that.
Specifying all the parameters for each component can lead to duplication. Suppose, for example, you want to build a range of cell models all based on cell1, but you don't want to change the threshold. You could define a new type without the threshold, but it is neater to still use the same type but specify that you are restricting attention to the set that all have a particular value for the threshold. This can be done by creating a new type that extends the cell1 type and includes a Fixed element to fix the threshold:
The cell2 type can now be used by only setting the remaining two parameters.
As well as restricting types when you extend them, you can also add new parameters as shown in the next type. This also
introduces an
Here is a basic capacitative cell with a leaking potential and a simple event handler.
The
Below is another example of a Dynamics, this time with an output port and a condition testing block that sends an event
when the condition becomes true. The test attribute in the
The above model is one way of writing a regular event generator. It has a state variable that grows in sync with t until it reaches a threshold when the event fires and it is reset. The model below achieves the same effect without solving a differential equation. Instead, it asks for access to the global time variable ("t" is the one global variable that is always available) and uses that in the test condition. [aside - there's a slight problem here since t exists even if the model doesn't define a dimension called time].
The examples so far have all been of very simple components which just had a single set of parameters. Real models however require rather more structure than this with components having children of various types and possibly multiple children of certain types. To illustrate this, the next example shows how the concept of an ion channel using Hodgkin-Huxley Dynamics can be defined.
Starting from the bottom, we define the different types of rate equations that occur. These will supply terms in the equations for the derivatives of the gating particles. There are three different expressions used in the HH equations, but they can all be expressed with three parameters, rate, midpoint and scale. We first define a general rate class, and then extend it for the three cases.
The
Note that the general
So here is the basic HHRate and its three extensions:
Now the rate elements are available, they can be used to define a component for a gate in a HH model. This introduces the
The above is a perfectly reasonable way to define a HH gate but unfortunately it needs smarter numerics than the simple forward Euler rule used in the proof of concept interpreter. Running this model with the Euler method leads to numerical instabilities. Happily, this problem can be circumvented without improving the numerics by changing the state variable. Instead of q which is defined on [0, 1] you can use x defined on (-infinity, infinity) which works much better with a naive integration scheme. This is what it looks like with x instead of q:
Now the gate type has been defined, it can be used to say what a HH Channel actually is. In this picture, a channel just has a conductance and one or more gates:
This introduces one new construct, the
With these definitions in place, it is now possible to define some channel models. The classic Hodgkin-Huxley sodium channel can be represented as:
The potassium channel uses exactly the same types, but has only one gate:
These channel models are an example where the ability to use the type name as the XML tag makes the model much clearer: the alternative just with three levels of Component elements would look rather unhelpful.
Although the channel models have now been defined, they still need to be used in a cell before anything can
be run. For this we'll just define a basic channel population type. There is one new construct here: the
The Dynamics block for a cannel population just computes the total conductance and then the current, in this case using Ohm's law.
To use these populations, they need inserting in a cell. The following type represents a simple cell with a number of populations and an option to inject a current so it does something interesting.
This Dynamics block introduces the
Now all the definitions are in place to define a cell model with a couple of channel populations:
To go with this cell type, we can define some components using the other types defined earlier. Note how celltype_d is based on an existing component via the "extends" attribute and only replaces one parameter value.
Finally a simulation element says what component is to be run and for how long. It also contains an embedded display element so the results of the simulation can be visualized. These are also user-defined types: their definitions will be presented in example 6.
That's it. When this model is run it produces the figure shown below (after rescaling a bit).
The next example shows a few more constructs that are needed for defining synapse models.