GeNN
4.9.0
GPU enhanced Neuronal Networks (GeNN)
|
In this tutorial we will learn to add synapsePopulations to connect neurons in neuron groups to each other with synaptic models. As an example we will connect the ten Hodgkin-Huxley neurons from tutorial 1 in a ring of excitatory synapses.
First, copy the files from Tutorial 1 into a new directory and rename the tenHH.py
to tenHHRing.py
, e.g. on Linux or Mac:
Finally, to reduce confusion we should rename the model itself. Open tenHHRing.py
, change the model name inside,
You will also need to import some additional PyGeNN functions and constants:
We want to connect our ten neurons into a ring where each neuron connects to its neighbours. In order to initialise this connectivity we need to add a sparse connectivity initialisation snippet at the top of tenHHRing.cc
:
The row_build_code
code string will be called to generate each row of the synaptic matrix (connections coming from a single presynaptic neuron) and, in this case, each row consists of a single synapses from the presynaptic neuron $(id_pre) to $(id_pre) + 1 (the modulus operator is used to ensure that the final connection between neuron 9
and 0
is made correctly). In order to allow GeNN to better optimise the generated code we also provide a maximum row length. In this case each row always contains only one synapse but, when more complex connectivity is used, the number of neurons in the pre and postsynaptic population as well as any parameters used to configure the snippet can be accessed from this function.
Now we need additional initial values and parameters for the synapse and post-synaptic models. We will use the standard WeightUpdateModels::StaticPulse weight update model and PostsynapticModels::ExpCond post-synaptic model. They need the following initial variables and parameters:
We can then add a synapse population at the end of the modelDefinition(...)
function,
The pygenn.GeNNModel.add_synapse_population parameters are
pop_name
: The name of the synapse population matrix_type
: String specifying how the synaptic matrix is stored. See Synaptic matrix types for available options. delay_steps
: Homogeneous (axonal) delay for synapse population (in terms of the simulation time step DT
). source
: pygenn.NeuronGroup or name of the (existing!) presynaptic neuron population. target
: pygenn.NeuronGroup or name of the (existing!) postsynaptic neuron population. w_update_model
: The type of weight update model. This should either be a string containing the name of a built in model or user-defined neuron type returned by pygenn.genn_model.create_custom_weight_update_class (see Weight update models). wu_param_space
: Dictionary containing the parameter values (common to all synapses of the population) for the weight update model. wu_var_space
: Dictionary containing the initial values or initialisation snippets for the weight update model's state variables wu_pre_var_space
: Dictionary containing the initial values or initialisation snippets for the weight update model's presynaptic state variables wu_post_var_space
: Dictionary containg the initial values or initialisation snippets for the weight update model's postsynaptic state variables postsyn_model
: The type of postsynaptic model. This should either be a string containing the name of a built in model or user-defined neuron type returned by pygenn.genn_model.create_custom_postsynaptic_class (see Postsynaptic integration methods). ps_param_space
: Dictionary containing the parameter values (common to all postsynaptic neurons) for the postsynaptic model. ps_var_space
: Dictionary containing the initial values or initialisation snippets for variables for the postsynaptic model's state variables connectivity_initialiser
: Optional argument, specifying the initialisation snippet for synapse population's sparse connectivity (see Sparse connectivity initialisation).Adding the pygenn.GeNNModel.add_synapse_population command to the model definition informs GeNN that there will be synapses between the named neuron populations, here between population Pop1
and itself with a delay of 10 (0.1 ms) timesteps. At this point our script tenHHRing.py
should look like this
We can now we can build and run our new model in the same way we did in Tutorial 1 (Python). However, even after all our hard work, the result looks very similar to the plot we obtained at the end of Tutorial 1 (Python).
This is because none of the neurons are spiking so there are no spikes to propagate around the ring.
We can use a NeuronModels::SpikeSourceArray to inject an initial spike into the first neuron in the ring during the first timestep to start spikes propagating. We then need to add it to the network by adding the following before we call pygenn.GeNNModel.build:
Each neuron in the spike source array population has its own list of spikes which are concatenated together and stored in an array made accesible to all neurons in the population using an extra global parameter (see Extra global parameters). The startSpike
and endSpike
variables are then initialised with the indices of each neuron's section of the spikeTimes
extra global parameter array. We then connect the spike source array to Pop1 using another synapse population with sparse connectivity, initialised using the built in InitSparseConnectivitySnippet::OneToOne model so the single neuron in the Stim population is connected to the first neuron in the ring. At this point our user code tenHHRing.py
should look like this
Finally if we build, make and run this model; and plot the first 200 ms of the ten neurons' membrane voltages - they now looks like this: