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:
the distances between neurons) * a optional value defining the variance of the Gaussian noise that should be applied on the weights
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
# ------------------- #
# Generate the graphs #
# ------------------- #
num_nodes = 1000
avg_deg_er = 25
avg_deg_sf = 100
# random graphs
g1 = ng.erdos_renyi(nodes=num_nodes, avg_deg=avg_deg_er)
# the same graph but undirected
g2 = ng.erdos_renyi(nodes=num_nodes, avg_deg=avg_deg_er, directed=False)
# 2-step generation of a scale-free with Gaussian weight distribution
w = {
"distribution": "gaussian",
"avg": 60.,
'''
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:
Build a network with two populations:
* excitatory (80%)
* inhibitory (20%)
'''
num_nodes = 1000
# 800 excitatory neurons, 200 inhibitory
net = nngt.Network.ei_network(num_nodes, ei_ratio=0.2)
'''
Connect the populations.
'''
# exc -> inhib (Erdos-Renyi)
ng.connect_neural_types(net, 1, -1, "erdos_renyi", density=0.035)
# 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
}
Send the network to NEST:
# ------------------ #
# Simulate with NEST #
# ------------------ #
if nngt.get_config('with_nest'):
import nest
import nngt.simulation as ns
'''
Prepare the network and devices.
'''
# send to NEST,
gids = net.to_nest()
# excite
ns.set_poisson_input(gids, rate=100000.)
# record
groups = [key for key in net.population]
recorder, record = ns.monitor_groups(groups, net)
'''
Simulate and plot.
'''
simtime = 100.
nest.Simulate(simtime)
if nngt.get_config('with_plot'):
ns.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.
# np.random.seed(0)
'''
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
synapses = {
(1, 1): exc_syn,
(1, -1): exc_syn,
(-1, 1): inh_syn,
(-1, -1): inh_syn,
}
pop = nngt.NeuralPop.exc_and_inhib(
num_neurons, en_model=neuron_model, in_model=neuron_model,
syn_spec=synapses)
# create the network and send it to NEST
w_prop = {"distribution": "gaussian", "avg": 0.1, "std": .05}
net = nngt.generation.gaussian_degree(
avg_degree, std_degree, population=pop, weights=w_prop)
'''
Send to NEST and set excitation and recorders
'''
if nngt.get_config('with_nest'):
import nest
import nngt.simulation as ns
nest.ResetKernel()
gids = net.to_nest()
# add noise to the excitatory neurons
excs = list(pop["excitatory"].nest_gids)
ns.set_noise(excs, 10., 2.)
# record
groups = [key for key in net.population]
recorder, record = ns.monitor_groups(groups, net)
'''
Simulate and plot.
'''
simtime = 2000.
nest.Simulate(simtime)
if nngt.get_config('with_plot'):
ns.plot_activity(
recorder, record, network=net, show=True, hist=False,
limits=(0, simtime))