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. If delay 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. If delay=True then the connection will be initialised as a DelayConnection, 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 a DelayConnection, 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 the weight and sparseness 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 or dynamic. 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 and sparseness 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 in Q with independent probability p and weight weight (this is the amount that gets added to the target state variable). If fixed is True, then the number of presynaptic neurons per neuron is constant. If seed 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 in Q with the given weight.
connect_one_to_one(P,Q)
If P and Q have the same number of neurons then neuron i in P will be connected to neuron i in Q 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 and j is the target neuron. Note: if C[i,j] should be zero, it is more efficient not to write C[i,j]=0, if you write this then when neuron i 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 of Connection 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. (A double 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 the column_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 for sparse 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 the nnzmax 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 the get_spikes method of the source 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, and connect_one_to_one have a new keyword delay=... for setting the initial values of the delays, where delay 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 standard Connection.

Implementation

DelayConnection stores an array of size (n,m) where n is max_delay/dt for dt of the target NeuronGroup’s clock, and m 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 neuron i 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 neuron i in the source group is connected to neuron i 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 a DenseConnectionVector or SparseConnectionVector as appropriate for the class.
set_row(i, val), set_col(i, val)
Sets row/col with an array, DenseConnectionVector or SparseConnectionVector (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 or i,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 and get_col methods return DenseConnectionVector` 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 is True then column access is also supported (but is not as fast as row access). If the use_minimal_indices keyword is True 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 than 2**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 and get_col methods return SparseConnectionVector objects. In addition to the usual slicing operations supported, M[:]=val is supported, where val must be a scalar or an array of length nnz.

Implementation details:

The values are stored in an array alldata of length nnz (number of nonzero entries). The slice alldata[rowind[i]:rowind[i+1]] gives the values for row i. These slices are stored in the list rowdata so that rowdata[i] is the data for row i. The array rowj[i] gives the corresponding column j 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 array allj of length nnz gives the column j coordinates for each element in alldata (the elements of rowj 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 and coldataindices. For column j, the array coli[j] gives the row indices for the data values in column j, while coldataindices[j] gives the indices in the array alldata for the values in column j. 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 and get_col methods return SparseConnectionVector objects. In addition to the usual slicing operations supported, M[:]=val is supported, where val must be a scalar or an array of length nnz.

Implementation details

The values are stored in an array alldata of length nnzmax (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, with coli containing arrays of row indices for each column. Similarly, rowdataind and coldataind consist of arrays of pointers to the indices in the alldata 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 method connection_matrix(*args, **kwds) which returns a ConnectionMatrix object of the appropriate type.

class brian.DenseConstructionMatrix(val, **kwds)

Dense construction matrix. Essentially just numpy.ndarray.

The connection_matrix method returns a DenseConnectionMatrix 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 as sv+dv where sv is sparse and dv is dense, the result will be a sparse vector with zeros where sv has zeros, the potentially nonzero elements of dv where sv has no entry will be simply ignored. It is for this reason that it is a SparseConnectionVector and not a general SparseVector, 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, and ind is an array of the indices of the nonzero elements.