The Network
object¶
We’ll familiarize ourselves with the Network
object by interactively building the elements of the network one by one.
Usually, we’d initialize all the elements of the network at once by providing the full 'network'
tree as an argument to the Network
class during initialization.
In this tutorial we:
- Initialize an empty
Network
object - Initialize all the elements of the network using the
Network.build_*
methods- Models (neuron models, recorder models, synapse models
- Layers
- Projection models
- Individual projections
- Population and projection recorders
- Create the network in NEST
- Access the network elements (GIDs, etc)
- Export and reuse the parameter tree allowing us to replicate the network
[1]:
import nest
import yaml
from pathlib import Path
from pprint import pprint
[2]:
from denest import *
import denest
[3]:
PARAMS_DIR = Path('./data/params/network')
Initialize an empty network¶
When initialized without argument or with an empty tree as an argument, all the expected subtrees are initialized as empty.
When building the elements interactively, the network’s parameters are updated.
[4]:
net = Network()
2020-06-30 13:42:37,794 [denest.utils.validation] INFO: 'None' tree: adding empty child neuron_models
2020-06-30 13:42:37,795 [denest.utils.validation] INFO: 'None' tree: adding empty child synapse_models
2020-06-30 13:42:37,796 [denest.utils.validation] INFO: 'None' tree: adding empty child layers
2020-06-30 13:42:37,797 [denest.utils.validation] INFO: 'None' tree: adding empty child projection_models
2020-06-30 13:42:37,799 [denest.utils.validation] INFO: 'None' tree: adding empty child topology
2020-06-30 13:42:37,800 [denest.utils.validation] INFO: 'None' tree: adding empty child recorder_models
2020-06-30 13:42:37,803 [denest.utils.validation] INFO: 'None' tree: adding empty child recorders
2020-06-30 13:42:37,806 [denest.network] INFO: Build N=0 ``Model`` objects
2020-06-30 13:42:37,809 [denest.network] INFO: Build N=0 ``SynapseModel`` objects
2020-06-30 13:42:37,809 [denest.network] INFO: Build N=0 ``Model`` objects
2020-06-30 13:42:37,812 [denest.network] INFO: Build N=0 ``Layer`` or ``InputLayer`` objects.
2020-06-30 13:42:37,814 [denest.network] INFO: Build N=0 ``ProjectionModel`` objects
2020-06-30 13:42:37,815 [denest.utils.validation] INFO: Object `topology`: params: using default value for optional parameters:
{'projections': []}
2020-06-30 13:42:37,816 [denest.network] INFO: Build N=0 ``TopoProjection`` objects
2020-06-30 13:42:37,819 [denest.utils.validation] INFO: Object `recorders`: params: using default value for optional parameters:
{'population_recorders': [], 'projection_recorders': []}
2020-06-30 13:42:37,823 [denest.network] INFO: Build N=0 population recorders.
2020-06-30 13:42:37,824 [denest.network] INFO: Build N=0 projection recorders.
The Network
’s parameter tree is empty:
[5]:
net.tree
[5]:
ParamsTree(name='None', parent=None)
params: {}
nest_params: {}
neuron_models:
params: {}
nest_params: {}
synapse_models:
params: {}
nest_params: {}
layers:
params: {}
nest_params: {}
projection_models:
params: {}
nest_params: {}
topology:
params: {}
nest_params: {}
recorder_models:
params: {}
nest_params: {}
recorders:
params: {}
nest_params: {}
Build the network components (models, layers, projections, recorders)¶
Define new models¶
We can define neuron, recorder, stimulator and synapse models with arbitrary parameters from parameter trees.
Each leaf corresponds to a new (named) model. Its nest_params
and params
are hierarchically inherited.
The nest_model
used is specified in the leaf’s params
'neuron_models'
tree:¶
Initalize Network.neuron_models
with the Network.build_neuron_models
method
[6]:
neuron_models_tree = ParamsTree.read(PARAMS_DIR/'models.yml').children['neuron_models']
pprint(neuron_models_tree)
ParamsTree(name='neuron_models', parent='None')
params: {}
nest_params: {}
my_neuron:
params:
nest_model: ht_neuron
nest_params:
g_KL: 1.0
g_NaL: 1.0
l1_exc:
params: {}
nest_params:
V_m: -44.0
l1_inh:
params: {}
nest_params:
V_m: -55.0
[7]:
net.build_neuron_models(neuron_models_tree)
2020-06-30 13:42:38,050 [denest.network] INFO: Build N=2 ``Model`` objects
[8]:
# The neuron models are saved as an attribute for the Network object
print("\n``Network.neuron_models`` :")
pprint(net.neuron_models)
``Network.neuron_models`` :
{'l1_exc': Model(l1_exc, {'nest_model': 'ht_neuron'}, {'V_m': -44.0, 'g_KL': 1.0, 'g_NaL': 1.0}),
'l1_inh': Model(l1_inh, {'nest_model': 'ht_neuron'}, {'V_m': -55.0, 'g_KL': 1.0, 'g_NaL': 1.0})}
[9]:
pprint(net.neuron_models['l1_exc'])
pprint(net.neuron_models['l1_exc'].params)
pprint(net.neuron_models['l1_exc'].nest_params)
Model(l1_exc, {'nest_model': 'ht_neuron'}, {'V_m': -44.0, 'g_KL': 1.0, 'g_NaL': 1.0})
{'nest_model': 'ht_neuron'}
{'V_m': -44.0, 'g_KL': 1.0, 'g_NaL': 1.0}
'recorder_models'
tree¶
Initalize Network.recorder_models
with the Network.build_recorder_models
method, as with neuron models:
[10]:
# ``Network.build_*`` methods accept as argument ``ParamsTree`` objects, but also tree-like dictionaries
recorder_models_tree = ParamsTree.read(PARAMS_DIR/'models.yml').children['recorder_models']
recorder_models_tree
[10]:
ParamsTree(name='recorder_models', parent='None')
params: {}
nest_params:
record_to:
- memory
- file
weight_recorder:
params:
nest_model: weight_recorder
nest_params: {}
my_multimeter:
params:
nest_model: multimeter
nest_params:
record_from:
- V_m
interval: 20.0
my_spike_detector:
params:
nest_model: spike_detector
nest_params: {}
[11]:
# ``Network.build_*`` methods accept as argument ``ParamsTree`` objects, but also tree-like dictionaries
recorder_models_tree = recorder_models_tree.asdict()
recorder_models_tree
[11]:
{'params': {},
'nest_params': {'record_to': ['memory', 'file']},
'weight_recorder': {'params': {'nest_model': 'weight_recorder'},
'nest_params': {}},
'my_multimeter': {'params': {'nest_model': 'multimeter'},
'nest_params': {'record_from': ['V_m'], 'interval': 20.0}},
'my_spike_detector': {'params': {'nest_model': 'spike_detector'},
'nest_params': {}}}
[12]:
net.build_recorder_models(recorder_models_tree)
2020-06-30 13:42:38,389 [denest.network] INFO: Build N=3 ``Model`` objects
[13]:
print("\n``Network.recorder_models`` :")
pprint(net.recorder_models)
``Network.recorder_models`` :
{'my_multimeter': Model(my_multimeter, {'nest_model': 'multimeter'}, {'interval': 20.0, 'record_from': ['V_m'], 'record_to': ['memory', 'file']}),
'my_spike_detector': Model(my_spike_detector, {'nest_model': 'spike_detector'}, {'record_to': ['memory', 'file']}),
'weight_recorder': Model(weight_recorder, {'nest_model': 'weight_recorder'}, {'record_to': ['memory', 'file']})}
'synapse_model'
tree¶
Initalize Network.synapse_models
with the Network.build_synapse_model
method.
- Same as for neuron models, with as a bonus a convenient way of specifying the receptor type of the synapse.
- If specifying the
receptor_type
andtarget_model
in theSynapseModel
params, the corresponding port is determined automatically.
[14]:
synapse_models_tree = ParamsTree.read(PARAMS_DIR/'models.yml').children['synapse_models']
synapse_models_tree
[14]:
ParamsTree(name='synapse_models', parent='None')
params: {}
nest_params: {}
my_AMPA_synapse:
params:
nest_model: ht_synapse
receptor_type: AMPA
target_neuron: ht_neuron
nest_params: {}
my_GABAA_synapse:
params:
nest_model: ht_synapse
receptor_type: GABA_A
target_neuron: ht_neuron
nest_params: {}
[15]:
net.build_synapse_models(synapse_models_tree)
2020-06-30 13:42:38,570 [denest.network] INFO: Build N=2 ``SynapseModel`` objects
[16]:
print("\n``Network.synapse_models`` :")
pprint(net.synapse_models)
``Network.synapse_models`` :
{'my_AMPA_synapse': SynapseModel(my_AMPA_synapse, {'nest_model': 'ht_synapse'}, {'receptor_type': 1}),
'my_GABAA_synapse': SynapseModel(my_GABAA_synapse, {'nest_model': 'ht_synapse'}, {'receptor_type': 3})}
Note that the receptor_type
nest_parameter was inferred
Define layers¶
As for models, we can create nest.Topology
layers from the leaves of a tree.
- The elements can be nest models with their default parameters, or the ones we just created with custom params.
- For layers of stimulator devices, we can use the
InputLayer
object, which can automatically create paired parrot neurons for each stimulator units, by addingtype: 'InputLayer'
to the params
'layers'
tree¶
[17]:
layer_tree = ParamsTree.read(PARAMS_DIR/'layers.yml')
layer_tree
[17]:
ParamsTree(name='None', parent=None)
params: {}
nest_params: {}
layers:
params:
type: null
nest_params:
rows: 5
columns: 5
extent:
- 5.0
- 5.0
edge_wrap: true
input_layer:
params:
type: InputLayer
add_parrots: true
populations:
spike_generator: 1
nest_params: {}
l1:
params:
populations:
l1_exc: 4
l1_inh: 2
nest_params: {}
[18]:
net.build_layers(layer_tree)
2020-06-30 13:42:38,801 [denest.network] INFO: Build N=2 ``Layer`` or ``InputLayer`` objects.
[19]:
pprint(net.layers)
{'input_layer': InputLayer(input_layer, {'add_parrots': True,
'populations': {'parrot_neuron': 1, 'spike_generator': 1},
'type': 'InputLayer'}, {'columns': 5,
'edge_wrap': True,
'elements': ('spike_generator', 1, 'parrot_neuron', 1),
'extent': [5.0, 5.0],
'rows': 5}),
'l1': Layer(l1, {'populations': {'l1_exc': 4, 'l1_inh': 2}, 'type': None}, {'columns': 5,
'edge_wrap': True,
'elements': ('l1_exc', 4, 'l1_inh', 2),
'extent': [5.0, 5.0],
'rows': 5})}
[20]:
print("'l1' layer")
pprint(net.layers['l1'].params)
pprint(net.layers['l1'].nest_params)
'l1' layer
{'populations': {'l1_exc': 4, 'l1_inh': 2}, 'type': None}
{'columns': 5,
'edge_wrap': True,
'elements': ('l1_exc', 4, 'l1_inh', 2),
'extent': [5.0, 5.0],
'rows': 5}
Define projections¶
We create projections using a two step process:
- Create
ProjectionModel
objects from a tree. Each named leaf will define a template from which individual projections can inherit their parameters - Create
Projection
objects from a list, specifying for each item the source layer x population, target layer x population and the projection model to inherit parameters from
Define templates from the projection_models
tree¶
[21]:
proj_model_tree = ParamsTree.read(PARAMS_DIR/'projections.yml').children['projection_models']
proj_model_tree
[21]:
ParamsTree(name='projection_models', parent='None')
params: {}
nest_params:
connection_type: divergent
mask:
circular:
radius: 2.0
kernel: 1.0
proj_1_AMPA:
params: {}
nest_params:
synapse_model: my_AMPA_synapse
weights: 1.0
proj_2_GABAA:
params: {}
nest_params:
synapse_model: my_GABAA_synapse
weights: 2.0
[22]:
net.build_projection_models(proj_model_tree)
2020-06-30 13:42:39,014 [denest.utils.validation] INFO: Object `proj_1_AMPA`: params: using default value for optional parameters:
{'type': 'topological'}
2020-06-30 13:42:39,021 [denest.utils.validation] INFO: Object `proj_2_GABAA`: params: using default value for optional parameters:
{'type': 'topological'}
2020-06-30 13:42:39,022 [denest.network] INFO: Build N=2 ``ProjectionModel`` objects
[23]:
net.projection_models
[23]:
{'proj_1_AMPA': ProjectionModel(proj_1_AMPA,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_AMPA_synapse',
'weights': 1.0}),
'proj_2_GABAA': ProjectionModel(proj_2_GABAA,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_GABAA_synapse',
'weights': 2.0})}
Define individual projections from the topology
tree¶
The list of projections is defined in the projections
params of the topology
tree
Check out the doc of Network.build_projections
for expected formatting
[24]:
conns_tree = ParamsTree.read(PARAMS_DIR/'projections.yml').children['topology']
conns_tree
[24]:
ParamsTree(name='topology', parent='None')
params:
projections:
- source_layers:
- input_layer
source_population: parrot_neuron
target_layers:
- l1
target_population: l1_exc
projection_model: proj_1_AMPA
- source_layers:
- l1
source_population: l1_exc
target_layers:
- l1
target_population: l1_inh
projection_model: proj_1_AMPA
- source_layers:
- l1
source_population: l1_inh
target_layers:
- l1
target_population: l1_exc
projection_model: proj_2_GABAA
nest_params: {}
[25]:
net.projection_models
[25]:
{'proj_1_AMPA': ProjectionModel(proj_1_AMPA,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_AMPA_synapse',
'weights': 1.0}),
'proj_2_GABAA': ProjectionModel(proj_2_GABAA,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_GABAA_synapse',
'weights': 2.0})}
[26]:
net.build_projections(conns_tree)
2020-06-30 13:42:39,277 [denest.network] INFO: Build N=3 ``TopoProjection`` objects
[27]:
net.projections
[27]:
[TopoProjection(proj_1_AMPA-input_layer-parrot_neuron-l1-l1_exc,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_AMPA_synapse',
'weights': 1.0,
'sources': {'model': 'parrot_neuron'},
'targets': {'model': 'l1_exc'}}),
TopoProjection(proj_1_AMPA-l1-l1_exc-l1-l1_inh,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_AMPA_synapse',
'weights': 1.0,
'sources': {'model': 'l1_exc'},
'targets': {'model': 'l1_inh'}}),
TopoProjection(proj_2_GABAA-l1-l1_inh-l1-l1_exc,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_GABAA_synapse',
'weights': 2.0,
'sources': {'model': 'l1_inh'},
'targets': {'model': 'l1_exc'}})]
Define recorders from the recorders
tree¶
Similarly to the topology
tree, recorders are defined from lists.
We separate recorders connected to synapses (e.g. weight recorder) and those connected to units (e.g. spike detectors), which are defined in the projection_recorders
and population_recorders
params, respectively, of the recorders
tree.
See the documentation for the Network.build_recorders()
, Network.build_population_recorders()
and Network.build_projection_recorders()
methods for expected formatting.
The parameters of the recorders can be changed by using custom recorder models (in the recorder_models
tree; see above).
[28]:
recorders_tree = ParamsTree.read(PARAMS_DIR/'recorders.yml').children['recorders']
recorders_tree
[28]:
ParamsTree(name='recorders', parent='None')
params:
population_recorders:
- layers:
- l1
populations:
- l1_exc
model: my_multimeter
- layers:
- input_layer
populations: null
model: my_spike_detector
projection_recorders:
- source_layers:
- l1
source_population: l1_exc
target_layers:
- l1
target_population: l1_inh
projection_model: proj_1_AMPA
model: weight_recorder
nest_params: {}
[29]:
net.build_recorders(recorders_tree)
2020-06-30 13:42:39,443 [denest.network] INFO: Build N=2 population recorders.
2020-06-30 13:42:39,444 [denest.network] INFO: Build N=1 projection recorders.
[30]:
net.population_recorders
[30]:
[PopulationRecorder(my_multimeter_l1_l1_exc, {}{}),
PopulationRecorder(my_spike_detector_input_layer_parrot_neuron, {}{})]
[31]:
net.projection_recorders
[31]:
[ProjectionRecorder(weight_recorder_proj_1_AMPA-l1-l1_exc-l1-l1_inh, {}{})]
Create the network¶
[32]:
nest.ResetKernel()
nest.SetKernelStatus({'overwrite_files': True})
[33]:
net.create()
2020-06-30 13:42:39,792 [denest.network] INFO: Creating neuron models...
100%|██████████| 2/2 [00:00<00:00, 1881.70it/s]
2020-06-30 13:42:39,804 [denest.network] INFO: Creating synapse models...
100%|██████████| 2/2 [00:00<00:00, 1215.21it/s]
2020-06-30 13:42:39,811 [denest.network] INFO: Creating recorder models...
100%|██████████| 3/3 [00:00<00:00, 1383.80it/s]
2020-06-30 13:42:39,839 [denest.network] INFO: Creating layers...
0%| | 0/2 [00:00<?, ?it/s]/Users/tom/nest/nest-simulator-2.20.0/lib/python3.7/site-packages/nest/lib/hl_api_helper.py:127: UserWarning:
GetNodes is deprecated and will be removed in NEST 3.0. Use GIDCollection instead.
100%|██████████| 2/2 [00:00<00:00, 9.04it/s]
2020-06-30 13:42:40,070 [denest.network] INFO: Creating population recorders...
100%|██████████| 2/2 [00:00<00:00, 54.77it/s]
2020-06-30 13:42:40,123 [denest.network] INFO: Creating projection recorders...
100%|██████████| 1/1 [00:00<00:00, 139.27it/s]
2020-06-30 13:42:40,145 [denest.network] INFO: Connecting layers...
100%|██████████| 3/3 [00:00<00:00, 137.19it/s]
2020-06-30 13:42:40,182 [denest.network] INFO: Network size (including recorders and parrot neurons):
Number of nodes: 206
Number of projections: 6650
Examine the network¶
deNEST provides convenient ways of accessing the objects in NEST.
Check the defaults of the created models¶
[34]:
print("`l1_exc` neuron models `nest_params`: ", net.neuron_models['l1_exc'].nest_params)
`l1_exc` neuron models `nest_params`: {'g_KL': 1.0, 'g_NaL': 1.0, 'V_m': -44.0}
[35]:
print('Corresponding params of the `l1_exc` model in nest:', nest.GetDefaults('l1_exc', list(net.neuron_models['l1_exc'].nest_params.keys())))
Corresponding params of the `l1_exc` model in nest: (1.0, 1.0, -44.0)
Access the layers’ units¶
[36]:
print('Layer `l1` shape: ', net.layers['l1'].layer_shape)
print('Population shapes: ', net.layers['l1'].population_shape)
Layer `l1` shape: (5, 5)
Population shapes: {'l1_exc': (5, 5, 4), 'l1_inh': (5, 5, 2)}
[37]:
net.layers['l1'].gids(location=(0, 0), population='l1_exc')
[37]:
[53, 78, 103, 128]
Access the projections created in NEST¶
[38]:
conn = net.projections[0]
conn
[38]:
TopoProjection(proj_1_AMPA-input_layer-parrot_neuron-l1-l1_exc,
{'type': 'topological'}{'connection_type': 'divergent',
'mask': {'circular': {'radius': 2.0}},
'kernel': 1.0,
'synapse_model': 'my_AMPA_synapse',
'weights': 1.0,
'sources': {'model': 'parrot_neuron'},
'targets': {'model': 'l1_exc'}})
[39]:
nest_conns = nest.GetConnections(
source=conn.source.gids(conn.source_population),
target=conn.target.gids(conn.target_population),
synapse_model=conn.nest_params['synapse_model']
)
nest_conns[0:5]
[39]:
(array('l', [27, 53, 0, 68, 0]),
array('l', [27, 88, 0, 68, 1]),
array('l', [27, 83, 0, 68, 2]),
array('l', [27, 152, 0, 68, 3]),
array('l', [27, 84, 0, 68, 4]))
Access the recorders¶
[40]:
rec = net.population_recorders[0]
print(rec, rec.gid, rec.model, rec.layer, rec.population_name)
my_multimeter_l1_l1_exc (203,) my_multimeter l1 l1_exc
[41]:
connrec = net.projection_recorders[0]
print(connrec, connrec.gid, connrec.model)
weight_recorder_proj_1_AMPA-l1-l1_exc-l1-l1_inh (205,) weight_recorder
Save and replicate the network¶
When building each of the network’s elements using the Network.build_*
methods, the Network.tree
parameters were updated.
[42]:
net.tree
[42]:
ParamsTree(name='None', parent=None)
params: {}
nest_params: {}
neuron_models:
params: {}
nest_params: {}
my_neuron:
params:
nest_model: ht_neuron
nest_params:
g_KL: 1.0
g_NaL: 1.0
l1_exc:
params: {}
nest_params:
V_m: -44.0
... [117 lines] ...
- layers:
- input_layer
populations: null
model: my_spike_detector
projection_recorders:
- source_layers:
- l1
source_population: l1_exc
target_layers:
- l1
target_population: l1_inh
projection_model: proj_1_AMPA
model: weight_recorder
nest_params: {}
We can save the parameter tree defining the whole network…
[43]:
net.tree.write(PARAMS_DIR/'network_tree.yml')
[43]:
PosixPath('data/params/network/network_tree.yml')
And use it to recreate another identical network.
[44]:
net2 = Network(ParamsTree.read(PARAMS_DIR/'network_tree.yml'))
2020-06-30 13:42:41,016 [denest.network] INFO: Build N=2 ``Model`` objects
2020-06-30 13:42:41,017 [denest.network] INFO: Build N=2 ``SynapseModel`` objects
2020-06-30 13:42:41,018 [denest.network] INFO: Build N=3 ``Model`` objects
2020-06-30 13:42:41,019 [denest.network] INFO: Build N=2 ``Layer`` or ``InputLayer`` objects.
2020-06-30 13:42:41,021 [denest.utils.validation] INFO: Object `proj_1_AMPA`: params: using default value for optional parameters:
{'type': 'topological'}
2020-06-30 13:42:41,024 [denest.utils.validation] INFO: Object `proj_2_GABAA`: params: using default value for optional parameters:
{'type': 'topological'}
2020-06-30 13:42:41,025 [denest.network] INFO: Build N=2 ``ProjectionModel`` objects
2020-06-30 13:42:41,030 [denest.network] INFO: Build N=3 ``TopoProjection`` objects
2020-06-30 13:42:41,033 [denest.network] INFO: Build N=2 population recorders.
2020-06-30 13:42:41,034 [denest.network] INFO: Build N=1 projection recorders.
[45]:
nest.ResetKernel()
net2.create()
2020-06-30 13:42:41,185 [denest.network] INFO: Creating neuron models...
100%|██████████| 2/2 [00:00<00:00, 134.07it/s]
2020-06-30 13:42:41,215 [denest.network] INFO: Creating synapse models...
100%|██████████| 2/2 [00:00<00:00, 1224.97it/s]
2020-06-30 13:42:41,234 [denest.network] INFO: Creating recorder models...
100%|██████████| 3/3 [00:00<00:00, 1727.24it/s]
2020-06-30 13:42:41,249 [denest.network] INFO: Creating layers...
100%|██████████| 2/2 [00:00<00:00, 10.27it/s]
2020-06-30 13:42:41,474 [denest.network] INFO: Creating population recorders...
100%|██████████| 2/2 [00:00<00:00, 24.22it/s]
2020-06-30 13:42:41,596 [denest.network] INFO: Creating projection recorders...
100%|██████████| 1/1 [00:00<00:00, 55.00it/s]
2020-06-30 13:42:41,616 [denest.network] INFO: Connecting layers...
100%|██████████| 3/3 [00:00<00:00, 184.37it/s]
2020-06-30 13:42:41,645 [denest.network] INFO: Network size (including recorders and parrot neurons):
Number of nodes: 206
Number of projections: 6650
[46]:
print(net.layers['l1'].gids(location=(0, 0), population='l1_exc'))
print(net2.layers['l1'].gids(location=(0, 0), population='l1_exc'))
[53, 78, 103, 128]
[53, 78, 103, 128]