Connections¶
The best way to understand the concept of a Connection
in
Brian is to work through Tutorial 2: Connections.
-
class
brian.
Connection
(source, target, state=0, delay=0.0 * second, modulation=None, structure='sparse', weight=None, sparseness=None, max_delay=5.0 * msecond, **kwds)¶ Mechanism for propagating spikes from one group to another
A Connection object declares that when spikes in a source group are generated, certain neurons in the target group should have a value added to specific states. See Tutorial 2: Connections to understand this better.
With arguments:
source
- The group from which spikes will be propagated.
target
- The group to which spikes will be propagated.
state
- The state variable name or number that spikes will be propagated to in the target group.
delay
- The delay between a spike being generated at the source
and received at the target. Depending on the type of
delay
it has different effects. Ifdelay
is a scalar value, then the connection will be initialised with all neurons having that delay. For very long delays, this may raise an error. Ifdelay=True
then the connection will be initialised as aDelayConnection
, allowing heterogeneous delays (a different delay for each synapse).delay
can also be a pair(min,max)
or a function of one or two variables, in both cases it will be initialised as aDelayConnection
, see the documentation for that class for details. Note that in these cases, initialisation of delays will only have the intended effect if used with theweight
andsparseness
arguments below. max_delay
- If you are using a connection with heterogeneous delays, specify this to set the maximum allowed delay (smaller values use less memory). The default is 5ms.
modulation
- The state variable name from the source group that scales the synaptic weights (for short-term synaptic plasticity).
structure
- Data structure:
sparse
(default),dense
ordynamic
. See below for more information on structures. weight
- If specified, the connection matrix will be initialised with
values specified by
weight
, which can be any of the values allowed in the methods connect*` below. sparseness
- If
weight
is specified andsparseness
is not, a full connection is assumed, otherwise random connectivity with this level of sparseness is assumed.
Methods
connect_random(P,Q,p[,weight=1[,fixed=False[,seed=None]]])
- Connects each neuron in
P
to each neuron inQ
with independent probabilityp
and weightweight
(this is the amount that gets added to the target state variable). Iffixed
is True, then the number of presynaptic neurons per neuron is constant. Ifseed
is given, it is used as the seed to the random number generators, for exactly repeatable results. connect_full(P,Q[,weight=1])
- Connect every neuron in
P
to every neuron inQ
with the given weight. connect_one_to_one(P,Q)
- If
P
andQ
have the same number of neurons then neuroni
inP
will be connected to neuroni
inQ
with weight 1. connect(P,Q,W)
- You can specify a matrix of weights directly (can be in any format
recognised by NumPy). Note that due to internal implementation details,
passing a full matrix rather than a sparse one may slow down your code
(because zeros will be propagated as well as nonzero values).
WARNING: No unit checking is done at the moment. For a more
efficient low-level method see
connect_from_sparse()
.
Additionally, you can directly access the matrix of weights by writing:
C = Connection(P,Q) print C[i,j] C[i,j] = ...
Where here
i
is the source neuron andj
is the target neuron. Note: ifC[i,j]
should be zero, it is more efficient not to writeC[i,j]=0
, if you write this then when neuroni
fires all the targets will have the value 0 added to them rather than just the nonzero ones. WARNING: No unit checking is currently done if you use this method. Take care to set the right units.Connection matrix structures
Brian currently features three types of connection matrix structures, each of which is suited for different situations. Brian has two stages of connection matrix. The first is the construction stage, used for building a weight matrix. This stage is optimised for the construction of matrices, with lots of features, but would be slow for runtime behaviour. Consequently, the second stage is the connection stage, used when Brian is being run. The connection stage is optimised for run time behaviour, but many features which are useful for construction are absent (e.g. the ability to add or remove synapses). Conversion between construction and connection stages is done by the
compress()
method ofConnection
which is called automatically when it is used for the first time.The structures are:
dense
- A dense matrix. Allows runtime modification of all values. If
connectivity is close to being dense this is probably the most
efficient, but in most cases it is less efficient. In addition,
a dense connection matrix will often do the wrong thing if
using STDP. Because a synapse will be considered to exist but
with weight 0, STDP will be able to create new synapses where
there were previously none. Memory requirements are
8NM
bytes where(N,M)
are the dimensions. (Adouble
float value uses 8 bytes.) sparse
- A sparse matrix. See
SparseConnectionMatrix
for details on implementation. This class features very fast row access, and slower column access if thecolumn_access=True
keyword is specified (making it suitable for learning algorithms such as STDP which require this). Memory requirements are 12 bytes per nonzero entry for row access only, or 20 bytes per nonzero entry if column access is specified. Synapses cannot be created or deleted at runtime with this class (although weights can be set to zero). dynamic
- A sparse matrix which allows runtime insertion and removal
of synapses. See
DynamicConnectionMatrix
for implementation details. This class features row and column access. The row access is slower than forsparse
so this class should only be used when insertion and removal of synapses is crucial. Memory requirements are 24 bytes per nonzero entry. However, note that more memory than this may be required because memory is allocated using a dynamic array which grows by doubling its size when it runs out. If you know the maximum number of nonzero entries you will have in advance, specify thennzmax
keyword to set the initial size of the array.
Low level methods
-
connect_from_sparse
(W, delay=None, column_access=True)¶ Bypasses the usual Brian mechanisms for constructing and compressing matrices, and allows you to directly set the weight (and optionally delay) matrices from scipy sparse matrix objects. This can be more memory efficient, because the default sparse matrix used for construction is
scipy.sparse.lil_matrix
which is very memory inefficient.Arguments:
W
- The weight matrix
delay
- Optional delay matrix if you are using heterogeneous delays.
column_access=True
- Set to
False
to save memory if you are not using STDP.
Warning
This is a low-level method that bypasses the usual checks on the data. In particular, make sure that if you pass a weight and delay matrix, that they have the same structure.
Advanced information
The following methods are also defined and used internally, if you are writing your own derived connection class you need to understand what these do.
propagate(spikes)
- Action to take when source neurons with indices in
spikes
fired. do_propagate()
- The method called by the
Network
update()
step, typically just propagates the spikes obtained by calling theget_spikes
method of thesource
NeuronGroup
.
-
class
brian.
DelayConnection
(source, target, state=0, modulation=None, structure='sparse', weight=None, sparseness=None, delay=None, max_delay=5.0 * msecond, **kwds)¶ Connection which implements heterogeneous postsynaptic delays
Initialised as for a
Connection
, but with the additional keyword:max_delay
- Specifies the maximum delay time for any neuron. Note, the smaller you make this the less memory will be used.
Overrides the following attribute of
Connection
:-
delay
¶ A matrix of delays. This array can be changed during a run, but at no point should it be greater than
max_delay
.
In addition, the methods
connect
,connect_random
,connect_full
, andconnect_one_to_one
have a new keyworddelay=...
for setting the initial values of the delays, wheredelay
can be one of:- A float, all delays will be set to this value
- A pair (min, max), delays will be uniform between these two values.
- A function of no arguments, will be called for each nonzero entry in the weight matrix.
- A function of two argument
(i,j)
will be called for each nonzero entry in the weight matrix. - A matrix of an appropriate type (e.g. ndarray or lil_matrix).
Finally, there is a method:
set_delays(source, target, delay)
- Where
delay
must be of one of the types above.
Notes
This class implements post-synaptic delays. This means that the spike is propagated immediately from the presynaptic neuron with the synaptic weight at the time of the spike, but arrives at the postsynaptic neuron with the given delay. At the moment, Brian only provides support for presynaptic delays if they are homogeneous, using the
delay
keyword of a standardConnection
.Implementation
DelayConnection
stores an array of size(n,m)
wheren
ismax_delay/dt
fordt
of the targetNeuronGroup
‘s clock, andm
is the number of neurons in the target. This array can potentially be quite large. Each row in this array represents the array that should be added to the target state variable at some particular future time. Which row corresponds to which time is tracked using a circular indexing scheme.When a spike from neuron
i
in the source is encountered, the delay time of neuroni
is looked up, the row corresponding to the current time plus that delay time is found using the circular indexing scheme, and then the spike is propagated to that row as for a standard connection (although this won’t be propagated to the target until a later time).Warning
If you are using a dynamic connection matrix, it is your responsibility to ensure that the nonzero entries of the weight matrix and the delay matrix exactly coincide. This is not an issue for sparse or dense matrices.
-
class
brian.
IdentityConnection
(source, target, state=0, weight=1, delay=0.0 * second)¶ A
Connection
between two groups of the same size, where neuroni
in the source group is connected to neuroni
in the target group.Initialised with arguments:
source
,target
- The source and target
NeuronGroup
objects. state
- The target state variable.
weight
- The weight of the synapse, must be a scalar.
delay
- Only homogeneous delays are allowed.
The benefit of this class is that it has no storage requirements and is optimised for this special case.
Connection matrix types¶
-
class
brian.
ConnectionMatrix
¶ Base class for connection matrix objects
Connection matrix objects support a subset of the following methods:
get_row(i)
,get_col(i)
- Returns row/col
i
as aDenseConnectionVector
orSparseConnectionVector
as appropriate for the class. set_row(i, val)
,set_col(i, val)
- Sets row/col with an array,
DenseConnectionVector
orSparseConnectionVector
(if supported). get_element(i, j)
,set_element(i, j, val)
- Gets or sets a single value.
get_rows(rows)
- Returns a list of rows, should be implemented without Python function calls for efficiency if possible.
get_cols(cols)
- Returns a list of cols, should be implemented without Python function calls for efficiency if possible.
insert(i,j,x)
,remove(i,j)
- For sparse connection matrices which support it, insert a new entry or remove an existing one.
getnnz()
- Return the number of nonzero entries.
todense()
- Return the matrix as a dense array.
The
__getitem__
and__setitem__
methods are implemented by default, and automatically select the appropriate methods from the above in the cases where the item to be got or set is of the form:
,i,:
,:,j
ori,j
.
-
class
brian.
DenseConnectionMatrix
(val, **kwds)¶ Dense connection matrix
See documentation for
ConnectionMatrix
for details on connection matrix types.This matrix implements a dense connection matrix. It is just a numpy array. The
get_row
andget_col
methods returnDenseConnectionVector`
objects.
-
class
brian.
SparseConnectionMatrix
(val, column_access=True, use_minimal_indices=False, **kwds)¶ Sparse connection matrix
See documentation for
ConnectionMatrix
for details on connection matrix types.This class implements a sparse matrix with a fixed number of nonzero entries. Row access is very fast, and if the
column_access
keyword isTrue
then column access is also supported (but is not as fast as row access). If theuse_minimal_indices
keyword isTrue
then the neuron and synapse indices will use the smallest possible integer type (16 bits for neuron indices if the number of neurons is less than2**16
, otherwise 32 bits). Otherwise, it will use the word size for the CPU architecture (32 or 64 bits).The matrix should be initialised with a scipy sparse matrix.
The
get_row
andget_col
methods returnSparseConnectionVector
objects. In addition to the usual slicing operations supported,M[:]=val
is supported, whereval
must be a scalar or an array of lengthnnz
.Implementation details:
The values are stored in an array
alldata
of lengthnnz
(number of nonzero entries). The slicealldata[rowind[i]:rowind[i+1]]
gives the values for rowi
. These slices are stored in the listrowdata
so thatrowdata[i]
is the data for rowi
. The arrayrowj[i]
gives the corresponding columnj
indices. For row access, the memory requirements are 12 bytes per entry (8 bytes for the float value, and 4 bytes for the column indices). The arrayallj
of lengthnnz
gives the columnj
coordinates for each element inalldata
(the elements ofrowj
are slices of this array so no extra memory is used).If column access is being used, then in addition to the above there are lists
coli
andcoldataindices
. For columnj
, the arraycoli[j]
gives the row indices for the data values in columnj
, whilecoldataindices[j]
gives the indices in the arrayalldata
for the values in columnj
. Column access therefore involves a copy operation rather than a slice operation. Column access increases the memory requirements to 20 bytes per entry (4 extra bytes for the row indices and 4 extra bytes for the data indices).TODO: update size numbers when use_minimal_indices=True for different architectures.
-
class
brian.
DynamicConnectionMatrix
(val, nnzmax=None, dynamic_array_const=2, **kwds)¶ Dynamic (sparse) connection matrix
See documentation for
ConnectionMatrix
for details on connection matrix types.This class implements a sparse matrix with a variable number of nonzero entries. Row access and column access are provided, but are not as fast as for
SparseConnectionMatrix
.The matrix should be initialised with a scipy sparse matrix.
The
get_row
andget_col
methods returnSparseConnectionVector
objects. In addition to the usual slicing operations supported,M[:]=val
is supported, whereval
must be a scalar or an array of lengthnnz
.Implementation details
The values are stored in an array
alldata
of lengthnnzmax
(maximum number of nonzero entries). This is a dynamic array, see:You can set the resizing constant with the argument
dynamic_array_const
. Normally the default value 2 is fine but if memory is a worry it could be made smaller.Rows and column point in to this data array, and the list
rowj
consists of an array of column indices for each row, withcoli
containing arrays of row indices for each column. Similarly,rowdataind
andcoldataind
consist of arrays of pointers to the indices in thealldata
array.
Construction matrix types¶
-
class
brian.
ConstructionMatrix
¶ Base class for construction matrices
A construction matrix is used to initialise and build connection matrices. A
ConstructionMatrix
class has to implement a methodconnection_matrix(*args, **kwds)
which returns aConnectionMatrix
object of the appropriate type.
-
class
brian.
DenseConstructionMatrix
(val, **kwds)¶ Dense construction matrix. Essentially just numpy.ndarray.
The
connection_matrix
method returns aDenseConnectionMatrix
object.The
__setitem__
method is overloaded so that you can set values with a sparse matrix.
-
class
brian.
SparseConstructionMatrix
(arg, **kwds)¶ SparseConstructionMatrix is converted to SparseConnectionMatrix.
-
class
brian.
DynamicConstructionMatrix
(arg, **kwds)¶ DynamicConstructionMatrix is converted to DynamicConnectionMatrix.
Connection vector types¶
-
class
brian.
ConnectionVector
¶ Base class for connection vectors, just used for defining the interface
ConnectionVector objects are returned by ConnectionMatrix objects when they retrieve rows or columns. At the moment, there are two choices, sparse or dense.
This class has no real function at the moment.
-
class
brian.
DenseConnectionVector
¶ Just a numpy array.
-
class
brian.
SparseConnectionVector
¶ Sparse vector class
A sparse vector is typically a row or column of a sparse matrix. This class can be treated in many cases as if it were just a vector without worrying about the fact that it is sparse. For example, if you write
2*v
it will evaluate to a new sparse vector. There is one aspect of the semantics which is potentially confusing. In a binary operation with a dense vector such assv+dv
wheresv
is sparse anddv
is dense, the result will be a sparse vector with zeros wheresv
has zeros, the potentially nonzero elements ofdv
wheresv
has no entry will be simply ignored. It is for this reason that it is aSparseConnectionVector
and not a generalSparseVector
, because these semantics make sense for rows and columns of connection matrices but not in general.Implementation details:
The underlying numpy array contains the values, the attribute
n
is the length of the sparse vector, andind
is an array of the indices of the nonzero elements.