1# coding: utf-8
2"""
3Examples of connections and plots of the connection matrices.
4
5It loops over most connector types and plots the resulting connection matrices.
6
7The network used is made of:
8- a population of stimuli
9- a population of inhibitory neurons
10- a population of excitatory neurons
11
12Usage: python connections.py <simulator> --plot-figure=name_figure
13
14    <simulator> is either mock, neuron, nest, brian,...
15
16It gives the results as png file, whose name is name_figure_ConnectorType, for each ConnectorType used.
17The connection parameters used are defined in the __main__ loop at the bottom of the file
18
19Joel Chavas, UNIC, CNRS
20June 2014
21
22"""
23
24import os
25import socket
26from math import *
27
28from pyNN.utility import get_simulator, Timer, ProgressBar, init_logging, normalized_filename
29
30from pyNN.random import NumpyRNG, RandomDistribution
31from pyNN.core import IndexBasedExpression
32from numpy import nan_to_num, array, ones, savetxt
33
34
35def initialize():
36    global sim
37    global options
38    global extra
39    global rngseed
40    global parallel_safe
41    global rng
42    global n_ext
43    global n_exc
44    global n_inh
45
46    sim, options = get_simulator(
47        ("--plot-figure", "Plot the connections to a file."))
48
49    init_logging(None, debug=True)
50
51    # === General parameters =================================================
52
53    threads = 1
54    rngseed = 98765
55    parallel_safe = True
56    rng = NumpyRNG(seed=rngseed, parallel_safe=parallel_safe)
57
58    # === general network parameters (except connections) ====================
59
60    n_ext = 60   # number of external stimuli
61    n_exc = 60  # number of excitatory cells
62    n_inh = 60  # number of inhibitory cells
63
64    # === Options ============================================================
65
66    extra = {'loglevel': 2, 'useSystemSim': True,
67            'maxNeuronLoss': 0., 'maxSynapseLoss': 0.4,
68            'hardwareNeuronSize': 8,
69            'threads': threads,
70            'filename': "connections.xml",
71            'label': 'VA'}
72    if sim.__name__ == "pyNN.hardware.brainscales":
73        extra['hardware'] = sim.hardwareSetup['small']
74
75    if options.simulator == "neuroml":
76        extra["file"] = "connections.xml"
77
78
79def build_connections(connector_type, connector_parameters):
80
81    # === Setup ==============================================================
82
83    node_id = sim.setup(**extra)
84    np = sim.num_processes()
85
86    host_name = socket.gethostname()
87    print("Host #%d is on %s" % (node_id + 1, host_name))
88
89    print("%s Initialising the simulator with %d thread(s)..." % (node_id, extra['threads']))
90
91    # === Type references ====================================================
92    celltype = sim.IF_cond_exp
93    synapsetype = sim.StaticSynapse
94
95    # === Definition of the types of neurons, synapses and connections =======
96    progress_bar = ProgressBar(width=20)
97
98    cell_stim = sim.SpikeSourceArray(spike_times=[1.0])
99    cell_exc = celltype()
100    cell_inh = celltype()
101    syn_stim = synapsetype()
102    syn_exc = synapsetype()
103    syn_inh = synapsetype()
104    conn_stim = connector_type(**connector_parameters)
105    conn_exc = connector_type(**connector_parameters)
106    conn_inh = connector_type(**connector_parameters)
107
108    # === Populations ========================================================
109
110    print("%s Creating cell populations..." % node_id)
111    pop_stim = sim.Population(n_ext, cell_stim, label="spikes")
112    pop_exc = sim.Population(n_exc, cell_exc, label="Excitatory_Cells")
113    pop_inh = sim.Population(n_inh, cell_inh, label="Inhibitory_Cells")
114
115    print("%s Connecting populations..." % node_id)
116
117    connections = {}
118    connections['stim2e'] = sim.Projection(
119        pop_stim, pop_exc, connector=conn_stim, synapse_type=syn_stim, receptor_type='excitatory')
120    connections['stim2i'] = sim.Projection(
121        pop_stim, pop_inh, connector=conn_stim, synapse_type=syn_stim, receptor_type='excitatory')
122    connections['e2e'] = sim.Projection(
123        pop_exc, pop_exc, conn_exc, syn_exc, receptor_type='excitatory')
124    connections['e2i'] = sim.Projection(
125        pop_exc, pop_inh, conn_exc, syn_exc, receptor_type='excitatory')
126    connections['i2e'] = sim.Projection(
127        pop_inh, pop_exc, conn_inh, syn_inh, receptor_type='inhibitory')
128    connections['i2i'] = sim.Projection(
129        pop_inh, pop_inh, conn_inh, syn_inh, receptor_type='inhibitory')
130
131    # === Output connection results ===========================================
132
133    # for prj in connections.keys():
134        # connections[prj].saveConnections('Results/VAconnections_%s_%s_np%d.conn'
135        # % (prj, options.simulator, np))
136
137    str_connections = "%d e->e  %d e->i  %d i->e  %d i->i" % (connections['e2e'].size(),
138                                                            connections[
139                                                                'e2i'].size(),
140                                                            connections[
141                                                                'i2e'].size(),
142                                                            connections['i2i'].size())
143    str_stim_connections = "%d stim->e  %d stim->i" % (
144        connections['stim2e'].size(), connections['stim2i'].size())
145
146    if node_id == 0:
147        print("\n\n--- Connector : %s ---" % connector_type.__name__)
148        print("Nodes                  : %d" % np)
149        print("Number of Stims        : %d" % n_ext)
150        print("Number of Exc Neurons  : %d" % n_exc)
151        print("Number of Inh Neurons  : %d" % n_inh)
152        print("Number of Synapses     : %s" % str_connections)
153        print("Number of inputs       : %s" % str_stim_connections)
154        print("\n")
155
156    def normalize_array(arr):
157        res = nan_to_num(arr)
158        res = (res != 0)
159        return res.astype(int)
160
161    if options.plot_figure:
162        filename = options.plot_figure + '_' + connector_type.__name__
163        from pyNN.utility.plotting import Figure, Panel
164        array_stim_exc = normalize_array(
165            connections['stim2e'].get('delay', format="array")[0:20, :])
166        array_stim_inh = normalize_array(
167            connections['stim2i'].get('delay', format="array")[0:20, :])
168        array_exc_exc = normalize_array(
169            connections['e2e'].get('delay', format="array")[0:20, :])
170        array_exc_inh = normalize_array(
171            connections['e2i'].get('delay', format="array")[0:20, :])
172        array_inh_exc = normalize_array(
173            connections['i2e'].get('delay', format="array")[0:20, :])
174        array_inh_inh = normalize_array(
175            connections['i2i'].get('delay', format="array")[0:20, :])
176
177        Figure(
178            Panel(array_stim_exc, data_labels=["stim->exc"], line_properties=[
179                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
180            Panel(array_stim_inh, data_labels=["stim->inh"], line_properties=[
181                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
182            Panel(array_exc_exc, data_labels=["exc->exc"], line_properties=[
183                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
184            Panel(array_exc_inh, data_labels=["exc->inh"], line_properties=[
185                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
186            Panel(array_inh_exc, data_labels=["inh->exc"], line_properties=[
187                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
188            Panel(array_inh_inh, data_labels=["inh->inh"], line_properties=[
189                {'xticks': True, 'yticks': True, 'cmap': 'Greys', 'vmin': 0.}]),
190        ).save(filename)
191
192    # === Finished with simulator ============================================
193
194    sim.end()
195
196# ===========================================================================
197# Utility functions
198# ===========================================================================
199
200
201def build_connection_parameters():
202    global connection_list
203    global path
204    global array_connections
205
206    connection_list = [
207                (0, 0, 0.1, 0.1),
208                (3, 0, 0.2, 0.11),
209                (2, 3, 0.3, 0.12),
210                (5, 1, 0.4, 0.13),
211                (0, 1, 0.5, 0.14),
212                ]
213    path = "test.connections"
214    if os.path.exists(path):
215        os.remove(path)
216    savetxt(path, connection_list)
217
218    array_connections = ones((60, 60), dtype=bool)
219    array_connections[15, 15] = False
220
221
222class IndexBasedProbability(IndexBasedExpression):
223
224    def __call__(self, i, j):
225        return array((i + j) % 3 == 0, dtype=float)
226
227
228def displacement_expression(d):
229    return 0.5 * ((d[0] >= -1) * (d[0] <= 2)) + 0.25 * (d[1] >= 0) * (d[1] <= 1)
230
231
232# ===========================================================================
233# ===========================================================================
234# MAIN PROGRAM
235# ===========================================================================
236# ===========================================================================
237
238if __name__ == "__main__":
239
240    # === Initializes =======================================================
241    initialize()
242    build_connection_parameters()
243
244    # === Loop over connector types =========================================
245
246    connector_type = [
247        [ sim.FixedProbabilityConnector, {'p_connect': 1.0, 'rng': rng} ],
248        [ sim.AllToAllConnector, {'allow_self_connections': False} ],
249        [ sim.DistanceDependentProbabilityConnector, {'d_expression': "exp(-abs(d))", 'rng': rng} ],
250        [ sim.IndexBasedProbabilityConnector, {'index_expression': IndexBasedProbability(), 'rng': rng} ],
251        [ sim.DisplacementDependentProbabilityConnector, {'disp_function': displacement_expression, 'rng': rng} ],
252        [ sim.FromListConnector, {'conn_list': connection_list} ],
253        [ sim.FromFileConnector, {'file': path, 'distributed': False} ],
254        [ sim.FixedNumberPreConnector, {'n': 3, 'rng': rng} ],
255        [ sim.ArrayConnector, {'array': array_connections, 'safe': True} ]
256        ]
257    for conn in connector_type:
258        build_connections(conn[0], conn[1])
259
260