![]() |
CNS: Cortical Network Simulator Programming Guide |
For a brief overview of this process, click here.
"m"
. The model structure identifies the package and describes the number, types, and sizes of layers as well as the connectivity between cells. It must also provide an initial value for all fields that do not have default values.
See the script demopkg_run
in the demo package for an example of some code that sets up a simple model structure. Here is some of that structure, which will be explained in the sections to follow.
m = package: 'demopkg' layers: {[1x1 struct] [1x1 struct] [1x1 struct]} m.layers{1} = type: 'input' pz: 0 size: {[1] [256] [256]} y_start: 0.0020 y_space: 0.0039 x_start: 0.0020 x_space: 0.0039 m.layers{2} = type: 'scale' pz: 1 size: {[1] [128] [128]} y_start: 0.0039 y_space: 0.0078 x_start: 0.0039 x_space: 0.0078 m.layers{3} = type: 'filter' pz: 2 rfCount: 11 size: {[4] [118] [118]} y_start: 0.0430 y_space: 0.0078 x_start: 0.0430 x_space: 0.0078
For example:m.package = name;
m.package = 'demopkg';
CNSInit
method, which gets called automatically by CNS to fill in the values of some fields for you.
Click here for details on setting values for the different classes of fields.m.field = value;
m.layers
. The following sections describe the various elements of a layer definition and how to set them up.
Property | Usage |
name |
Optional. Provides the layer with a name. This can be useful when models have lots of layers; the cns_layerno function can be used to find the number of a named layer. If given, must be unique. Example: m.layers{1}.name = 'image'; |
type |
Required. Tells CNS the cell type of this layer. Must be a non-abstract type defined in the selected package. Example: m.layers{1}.type = 'input'; |
size |
Required. Tells CNS how many cells are in the layer along each dimension. The dimensionality is determined by the cell type. Example: Note 1: if the cell type maps some dimensions to a common coordinate space, the sizes of those dimensions will probably be determined by that process (which will probably involve them.layers{1}.size = {500 100 100}; cns_mapdim function).Note 2: CNS issues performance warnings if your layer size will lead to inefficient processing; see performance note here. To turn off these warnings, you can set: m.quiet = true; |
cns_mapdim
function for each mapped dimension. This sets:
dim_start
and dim_space
. (You can see examples of these above.)
cns_mapdim
has a number of different options. The following code sets up two layers of the demo model above. Note:
Once common coordinates have been set up, there are several useful functions you can call from MATLAB:
m.layers{2}.size{1} = 1; m = cns_mapdim(m, 2, 'y', 'scaledpixels', 256, 2); m = cns_mapdim(m, 2, 'x', 'scaledpixels', 256, 2); m.layers{3}.size{1} = 4; m = cns_mapdim(m, 3, 'y', 'int', 2, 11, 1); m = cns_mapdim(m, 3, 'x', 'int', 2, 11, 1);
cns_center
- find the position of a cell in common coordinates.
cns_findnearest
, cns_findnearest_at
- find the nearest n
cells to a given cell or position.
cns_findwithin
, cns_findwithin_at
- find cells within radius r
of a given cell or position.
synType
property) may be enumerated for all the cells in a layer using the following three properties.
Property | Usage |
synapseZs |
The layer number of the presynaptic cell for each synapse, for each cell in this layer. This is a numeric array of size [ns n1 n2 ...] , where:
z is a 3-D layer of size [8 64 64], with at most 50 synapses per cell, we would have:
Thesize(m.layers{z}.synapseZs) = [50 8 64 64] synapseZs values for cell (1, 1, 1) will be in synapseZs(:, 1, 1, 1) .
If some cells have less than
If all synapses for this layer originate in the same presynaptic layer, you can set |
synapseIs |
This holds the linear index of each presynaptic cell within its own layer. For example, if we want to point to presynaptic cell (5, 2, 4) which sits in a layer of size [10 20 30], that cell's linear index within its layer can be computed as:
(Note:sub2ind([10 20 30], 5, 2, 4) = 615 cns_iconv provides the same functionality and is more convenient to use with CNS model structures.)
Like |
synapseTs |
If desired, you can attach a positive integer to each synapse, which is a good way to differentiate types of synapses. If present, synapseTs must be the same size as synapseIs and have zeros exactly where synapseIs has zeros. If all synapses have the same type, synapseTs can also be a scalar.
|
Once explicit synapses have been enumerated for all layers, the cns_trace
function is a useful tool for tracing connectivity through the network.
CNS would then expect to find the values of any "group" fields (fields of the classes listed above) in:m.layers{1}.groupNo = 1; m.layers{2}.groupNo = 1;
If a given layerm.groups{1}
z
is not assigned to any group, CNS will look for any "group" fields in:
If groups are used, they must be contiguously numbered. For example, if group 5 exists, then groups 1-4 must also exist.m.layers{z}
Groups may have names, e.g.:
Named groups can be found in a large model using the functionm.groups{1}.name = 'c1';
cns_groupno
.
This is done for layer z
as follows:
Exception: if layerm.layers{z}.field = value;
z
belongs to group g
, fields having group scope are set as follows:
Click here for details on setting values for the different classes of fields.m.groups{g}.field = value;
t
use inputs from iteration t-1
.
More than one layer can be computed in a single step. (Indeed, in the default case, where nom.layers{1}.stepNo = 1; m.layers{2}.stepNo = 2; m.layers{3}.stepNo = 3;
stepNos
are specified, all layers get assigned to step 1.)
The function cns_setstepnos
can automatically assign step numbers for some common cases.
A layer can also be computed more than once in a single network iteration. Here, layer z
will get computed twice, once in step 3 and once in step 6.
In networks that are computed in steps, it is often the case that the cells within a single step are independent of each other. They depend on cells in previous steps, but not on each other. If this is true for all steps, then the double-buffering referred to above is unnecessary, and you can get a performance gain by turning it off. This is done with the setting:m.layers{z}.stepNo = [3 6];
m.independent = true;
The following table shows where each class/scope of field is initialized, and the format required. Note:m.field = value; m.layers{z}.field = value; m.groups{g}.field = value;
Field Class | Scope | Initialized in | Format (Single-Valued) |
Format (Multivalued) |
parameter pointer |
model | m |
layer | m.layers{z} |
group | m.groups{g} |
N-D array | model | m |
layer | m.layers{z} |
group | m.groups{g} |
cell field | cell | m.layers{z} |
||
synapse field | synapse | m.layers{z} |
A few functions that might be useful here are:
cns_getconsts
- returns the values of compile-time constants defined by the package.
cns_intmin
, cns_intmax
- lower and upper bounds for an integer.
cns_fltmin
, cns_fltmax
- lower and upper bounds for a single-precision floating point number.
You may be relying on CNS to fill in some default values for you. If you want to check these, you can get a complete model structure with all the defaults filled in by calling cns_getdflts.
You are also free to use the model structure to store additional information that CNS doesn't know about. This is fine, as long as you don't overwrite anything CNS needs. If you've forgotten what's yours and what's CNS's, the function cns_getknownfields will tell you.
cns
function.