-
Notifications
You must be signed in to change notification settings - Fork 6
/
simulator.py
158 lines (132 loc) · 5.57 KB
/
simulator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import os
import abc
from numpy import atleast_1d
from brian2 import device, Network
def initialize_parameter(variableview, value):
"""initialize parameter variable in static file, returns Dummy device"""
variable = variableview.variable
array_name = device.get_array_name(variable)
static_array_name = device.static_array(array_name, value)
device.main_queue.append(('set_by_array', (array_name,
static_array_name,
False)))
return static_array_name
def initialize_neurons(params_names, neurons, params):
"""
initialize each parameter for NeuronGroup returns dictionary of Dummy
devices
"""
params_init = dict()
for name in params_names:
params_init[name] = initialize_parameter(neurons.__getattr__(name),
params[name])
return params_init
def run_again():
"""re-run the NeuronGroup on cpp file"""
device.run(device.project_dir, with_output=False, run_args=[])
def set_parameter_value(identifier, value):
"""change parameter value in cpp file"""
atleast_1d(value).tofile(os.path.join(device.project_dir,
'static_arrays',
identifier))
def set_states(init_dict, values):
"""set parameters values in the file for the NeuronGroup"""
for obj_name, obj_values in values.items():
set_parameter_value(init_dict[obj_name], obj_values)
class Simulator(metaclass=abc.ABCMeta):
"""
Simulation class created to perform a simulation for fitting traces or
spikes.
"""
def __init__(self):
self.networks = {}
self.current_net = None
self.last_run_parameters = None
self.var_init = None
neurons = property(lambda self: self.networks[self.current_net]['neurons'])
statemonitor = property(lambda self: self.networks[self.current_net]['statemonitor'])
spikemonitor = property(lambda self: self.networks[self.current_net]['spikemonitor'])
def initialize(self, network, var_init, name='fit'):
"""
Prepares the simulation for running
Parameters
----------
network: `~brian2.core.network.Network`
Network consisting of a `~brian2.groups.neurongroup.NeuronGroup`
named ``neurons`` and either a monitor named ``spikemonitor``
or a monitor named ``statemonitor``(or both).
var_init: dict
dictionary to initialize the variable states
name: `str`, optional
name of the network
"""
assert isinstance(network, Network)
if 'neurons' not in network:
raise KeyError('Expected a group named "neurons" in the '
'network.')
if 'statemonitor' not in network and 'spikemonitor' not in network:
raise KeyError('Expected a monitor named "spikemonitor" or '
'"statemonitor" in the network.')
self.networks[name] = network
self.current_net = None # will be set in run
self.last_run_parameters = None
self.var_init = var_init
@abc.abstractmethod
def run(self, duration, params, params_names, iteration, name):
"""
Restores the network, sets neurons to required parameters and runs
the simulation
Parameters
----------
duration: `~brian2.units.fundamentalunits.Quantity`
Simulation duration
params: dict
parameters to be set
params_names: list[str]
names of parameters to set the dictionary
"""
pass
class RuntimeSimulator(Simulator):
"""Simulation class created for use with RuntimeDevice"""
def initialize(self, network, var_init, name='fit'):
super(RuntimeSimulator, self).initialize(network, var_init, name)
network.store()
def run(self, duration, params, params_names, iteration, name='fit'):
self.current_net = name
self.last_run_parameters = params
network = self.networks[name]
network.restore()
self.neurons.set_states(params, units=False)
self.neurons.iteration = iteration
if self.var_init is not None:
for k, v in self.var_init.items():
self.neurons.__setattr__(k, v)
network.run(duration, namespace={})
class CPPStandaloneSimulator(Simulator):
"""Simulation class created for use with CPPStandaloneDevice"""
def __init__(self):
super(CPPStandaloneSimulator, self).__init__()
self.params_init = None
def run(self, duration, params, params_names, iteration, name='fit'):
"""
Simulation has to be run in two stages in order to initialize the
code generation
"""
self.current_net = name
self.last_run_parameters = params
network = self.networks[name]
# Include the iteration index in the parameters
params_names = sorted(params_names) + ['iteration']
params = dict(params)
params.update({'iteration': iteration})
if not device.has_been_run:
self.params_init = initialize_neurons(params_names, self.neurons,
params)
if self.var_init is not None:
for k, v in self.var_init.items():
self.neurons.__setattr__(k, v)
self.neurons.iteration = iteration
network.run(duration, namespace={})
else:
set_states(self.params_init, params)
run_again()