1. ModelSpec structured model specification
1.1. Learning by example
In the absence of comprehensive documentation at this time, we recommend studying the examples provided in the /tests/ directory. These focus on ODE models, but in most cases discrete-time equations could be substituted for the ODEs by making the target Generators MapSystem rather than an ODE solver. Also see the computational neuroscience tutorial in the intermediate section.
1.2. Hierarchical model construction
The goal of the ModelSpec classes is to provide a class hierarchy that allows complex dynamical models to be composed from simple units of mathematical expression.
There is a low-level QuantSpec wrapper around a parser class, which in turn is built into the Quantity classes. These classes are really the elementary model building blocks, and are discussed on the page Symbolic.
On this page we continue to develop the hierarchical structure from that point.
1.2.1. Multiple Quantity definitions
A useful short-hand is available for defining a range of numbered Quantities, for instance x0-x10. This is achieved by making the Quantity name consist of an alphanumeric string followed (with no whitespace) by a three-element list containing an index name, the starting index value, and the ending index value (in increasing order). The definition may use the index as a locally-defined integer value in expressions. It may itself be used inside references to other multiply-defined Quantities. These definitions are also discussed on the page Symbolic.
>>> m=Var('3*i-a', 'm[i,1,4]') >>> m Quantity m2 (ExpFuncSpec) >>> print m() 3*2-a >>> print m.eval(a=1) 8 >>> print m IndexError: Index to multiple Quantity definition out of the valid range [1,4] >>> n=Var('2+m[k*2]', 'n[k,0,2]') >>> print n() >>> 2+m4
Here, the 'k*2' forms the index to the 'm' Quantities. The expression forming the index must statically evaluate to an integer when 'k' is substituted with the values in the declared range, at the time of definition. For example, the index cannot involve a parameter or variable value that will not be known until run-time. Built-in functions that return integers (such as 'mod' or 'pow' with integer arguments) can be used to create the index expression.
At the next level of the model specification hierarchy are "components" (class Component). These may be either regular components or "leaf" components (class LeafComponent, a sub-class of Component) that cannot themselves contain other components, i.e. are at the "tips" of the tree structure.
Access down the levels of hierachical composition of model components is represented in the familiar "dot" notation of Python object-oriented classes. For instance, "mysuper.leaf1" and "mysuper.leaf2" would describe a Component "mysuper" that can contain LeafComponents "leaf1" and "leaf2".
1.4. ModelSpec objects as databases
The searchModelSpec function is powerful way to access or probe the contents of a ModelSpec object according to a variety of search criteria. The criteria may include wild-cards, for instance, and makes use of the "dot" notation for representing hierarchical depth.
A range of information is held in a _registry attribute of a ModelSpec component. Sub-components can be added, renamed, and deleted.
2. Transforming specifications into models
In order to turn a hierarchical specification of a model into a target Generator or Model object, the specification must be "flattened", and information about the sub-components that is embedded in this specification in a structured way must also be extracted and listed out. A ModelSpec component has a method flattenSpec which can be called once the model has been fully defined. A fully defined model is one that has no free names in need of resolving. The component has the attribute freeSymbols, but names external to the specification, such as t for time in non-autonomous systems, or names of built-in auxiliary functions, will be treated as free symbols. The flattenSpec function takes an optional list argument globalRefs to specify such names in order to complete the definition of the system.
2.1. The ModelConstructor utility
The ModelConstructor classes simplify some of the tasks in converting a ModelSpec specification into a FuncSpec call that ultimately produces a target Generator or Model class instance (see page FunctionalSpec).
Models created in this way contain a copy of their source ModelSpec in the mspecdict attribute.
Examples of usage are provided in /tests/CIN.py and /tests/ModelSpec_test.py.