In order to keep the code as generic and easy to maintain as possible, the generation of graphs or networks is divided in several steps:
The library as been designed so that these various operations can be realized in any order!
The weights can be either user-defined or generated by one of the available distributions (MAKE A REF). User-defined weights are generated via:
Pre-defined distributions require the following variables:
There are several ways of settings the weights of a graph which depend on the time at which you assign them.
weight_prop
argument to the constructor; this should be a dictionary containing at least the name of the weight distribution: {"distrib": "distribution_name"}
.
If entered, this will be stored as a graph property and used to assign the weights whenever new edges are created unless you specifically assign rules for those new edges’ weights.You can use the Connections
class to set the weights of a graph
explicitely by using:
>>> nngt.Connections.weights(graph, elist=edges_to_weigh, distrib="distrib_of_choice", ...)
import nngt
import nngt.generation as ng
num_nodes = 1000
degree = 25
# random graphs
g1 = ng.erdos_renyi(num_nodes, avg_deg=degree)
g2 = ng.erdos_renyi(num_nodes, avg_deg=degree, directed=False) # the same graph
# but undirected
# 2-step generation of a scale-free with Gaussian weight distribution
w = {
"distribution": "gaussian",
"distrib_prop": {"avg": 60., "std":5.}
}
g3 = nngt.Graph(num_nodes, weights=w)
ng.random_scale_free(2.2, 2.9, from_graph=g3)
# same in 1 step
g4 = ng.random_scale_free(2.2, 2.9, nodes=num_nodes, weights=w)
num_nodes = 1000
'''
Make the population
'''
# two groups of neurons
g1 = nngt.NeuralGroup(500) # neurons 0 to 499
g2 = nngt.NeuralGroup(500) # neurons 500 to 999
# make population (without NEST models)
pop = nngt.NeuralPop.from_groups(
(g1, g2), ("left", "right"), with_models=False)
# create network from this population
net = nngt.Network(population=pop)
'''
Connect the groups
'''
# inter-groups (Erdos-Renyi)
prop_er1 = {"density": 0.005}
ng.connect_neural_groups(net, "left", "right", "erdos_renyi", prop_er1)
# intra-groups (Newman-Watts)
prop_nw = {
"coord_nb": 20,
"proba_shortcut": 0.1
}
ng.connect_neural_groups(net, "left", "left", "newman_watts", prop_nw)
ng.connect_neural_groups(net, "right", "right", "newman_watts", prop_nw)
Generating a network with excitatory and inhibitory neurons:
# 800 excitatory neurons, 200 inhibitory
net = nngt.Network.ei_network(num_nodes, ei_ratio=0.2)
'''
Connect the populations.
'''
# exc -> inhib (Erdos-Renyi)
prop_er1 = {"density": 0.035}
ng.connect_neural_types(net, 1, -1, "erdos_renyi", prop_er1)
# exc -> exc (Newmann-Watts)
prop_nw = {
"coord_nb": 10,
"proba_shortcut": 0.1
}
ng.connect_neural_types(net, 1, 1, "newman_watts", prop_nw)
# inhib -> exc (Random scale-free)
prop_rsf = {
"in_exp": 2.1,
"out_exp": 2.6,
"density": 0.2
}
ng.connect_neural_types(net, -1, 1, "random_scale_free", prop_rsf)
# inhib -> inhib (Erdos-Renyi)
prop_er2 = { "density": 0.04 }
ng.connect_neural_types(net, -1, -1, "erdos_renyi", prop_er2)
Send the network to NEST:
import nest
from nngt.simulation import monitor_groups, plot_activity, set_poisson_input
'''
Prepare the network and devices.
'''
# send to NEST,
gids = net.to_nest()
# excite
set_poisson_input(gids, rate=100000.)
# record
groups = [key for key in net.population]
recorder, record = monitor_groups(groups, net)
'''
Simulate and plot.
'''
simtime = 100.
nest.Simulate(simtime)
plot_activity(
recorder, record, network=net, show=True, hist=False,
limits=(0,simtime))
Some models, such as multisynaptic neurons, or advanced models incorporating various neurotransmitters use an additional information, called "port"
to identify the synapse that will be used by the nest.Connect
method.
These models can also be used with NNGT by telling the NeuralGroup
which type of port the neuron should try to bind to.
NB: the port is specified in the source neuron and declares which synapse of the target neuron is concerned.
'''
Build a network with two populations:
* excitatory (80%)
* inhibitory (20%)
'''
num_neurons = 50 # number of neurons
avg_degree = 20 # average number of neighbours
std_degree = 3 # deviation for the Gaussian graph
# parameters
neuron_model = "ht_neuron" # hill-tononi model
exc_syn = {'receptor_type': 1} # 1 is 'AMPA' in this model
inh_syn = {'receptor_type': 3} # 3 is 'GABA_A' in this model
pop = nngt.NeuralPop.exc_and_inhib(
num_neurons, en_model=neuron_model, in_model=neuron_model,
es_param=exc_syn, is_param=inh_syn)
# create the network and send it to NEST
w_prop = {"distribution": "gaussian", "avg": 1., "std": .2}
net = nngt.generation.gaussian_degree(
avg_degree, std_degree, population=pop, weights=w_prop)
'''
Send to NEST and set excitation and recorders
'''
import nest
from nngt.simulation import monitor_groups, plot_activity, set_noise
gids = net.to_nest()
# add noise to the excitatory neurons
excs = list(pop["excitatory"].nest_gids)
set_noise(excs, 10., 2.)
# record
groups = [key for key in net.population]
recorder, record = monitor_groups(groups, net)
'''
Simulate and plot.
'''
simtime = 2000.
nest.Simulate(simtime)
plot_activity(
recorder, record, network=net, show=True, hist=False,
limits=(0, simtime))