1"""
2Standard cells for nest
3
4:copyright: Copyright 2006-2021 by the PyNN team, see AUTHORS.
5:license: CeCILL, see LICENSE for details.
6
7"""
8
9from pyNN.standardmodels import cells, build_translations
10from .. import simulator
11
12
13class IF_curr_alpha(cells.IF_curr_alpha):
14
15    __doc__ = cells.IF_curr_alpha.__doc__
16
17    translations = build_translations(
18        ('v_rest',     'E_L'),
19        ('v_reset',    'V_reset'),
20        ('cm',         'C_m',      1000.0),  # C_m is in pF, cm in nF
21        ('tau_m',      'tau_m'),
22        ('tau_refrac', 't_ref'),
23        ('tau_syn_E',  'tau_syn_ex'),
24        ('tau_syn_I',  'tau_syn_in'),
25        ('v_thresh',   'V_th'),
26        ('i_offset',   'I_e',      1000.0),  # I_e is in pA, i_offset in nA
27    )
28    nest_name = {"on_grid": "iaf_psc_alpha",
29                 "off_grid": "iaf_psc_alpha"}
30    standard_receptor_type = True
31
32
33class IF_curr_exp(cells.IF_curr_exp):
34
35    __doc__ = cells.IF_curr_exp.__doc__
36
37    translations = build_translations(
38        ('v_rest',     'E_L'),
39        ('v_reset',    'V_reset'),
40        ('cm',         'C_m',      1000.0),  # C_m is in pF, cm in nF
41        ('tau_m',      'tau_m'),
42        ('tau_refrac', 't_ref'),
43        ('tau_syn_E',  'tau_syn_ex'),
44        ('tau_syn_I',  'tau_syn_in'),
45        ('v_thresh',   'V_th'),
46        ('i_offset',   'I_e',      1000.0),  # I_e is in pA, i_offset in nA
47    )
48    nest_name = {"on_grid": 'iaf_psc_exp',
49                 "off_grid": 'iaf_psc_exp_ps'}
50    standard_receptor_type = True
51
52
53class IF_cond_alpha(cells.IF_cond_alpha):
54
55    __doc__ = cells.IF_cond_alpha.__doc__
56
57    translations = build_translations(
58        ('v_rest',     'E_L'),
59        ('v_reset',    'V_reset'),
60        ('cm',         'C_m',        1000.0),  # C_m is in pF, cm in nF
61        ('tau_m',      'g_L',        "cm/tau_m*1000.0", "C_m/g_L"),
62        ('tau_refrac', 't_ref'),
63        ('tau_syn_E',  'tau_syn_ex'),
64        ('tau_syn_I',  'tau_syn_in'),
65        ('v_thresh',   'V_th'),
66        ('i_offset',   'I_e',        1000.0),  # I_e is in pA, i_offset in nA
67        ('e_rev_E',    'E_ex'),
68        ('e_rev_I',    'E_in'),
69    )
70    nest_name = {"on_grid": "iaf_cond_alpha",
71                 "off_grid": "iaf_cond_alpha"}
72    standard_receptor_type = True
73
74
75class IF_cond_exp(cells.IF_cond_exp):
76
77    __doc__ = cells.IF_cond_exp.__doc__
78
79    translations = build_translations(
80        ('v_rest',     'E_L'),
81        ('v_reset',    'V_reset'),
82        ('cm',         'C_m',        1000.0),  # C_m is in pF, cm in nF
83        ('tau_m',      'g_L',        "cm/tau_m*1000.0", "C_m/g_L"),
84        ('tau_refrac', 't_ref'),
85        ('tau_syn_E',  'tau_syn_ex'),
86        ('tau_syn_I',  'tau_syn_in'),
87        ('v_thresh',   'V_th'),
88        ('i_offset',   'I_e',        1000.0),  # I_e is in pA, i_offset in nA
89        ('e_rev_E',    'E_ex'),
90        ('e_rev_I',    'E_in'),
91    )
92    nest_name = {"on_grid": "iaf_cond_exp",
93                 "off_grid": "iaf_cond_exp"}
94    standard_receptor_type = True
95
96
97class IF_cond_exp_gsfa_grr(cells.IF_cond_exp_gsfa_grr):
98
99    __doc__ = cells.IF_cond_exp_gsfa_grr.__doc__
100
101    translations = build_translations(
102        ('v_rest',     'E_L'),
103        ('v_reset',    'V_reset'),
104        ('cm',         'C_m',        1000.0),  # C_m is in pF, cm in nF
105        ('tau_m',      'g_L',        "cm/tau_m*1000.0", "C_m/g_L"),
106        ('tau_refrac', 't_ref'),
107        ('tau_syn_E',  'tau_syn_ex'),
108        ('tau_syn_I',  'tau_syn_in'),
109        ('v_thresh',   'V_th'),
110        ('i_offset',   'I_e',        1000.0),  # I_e is in pA, i_offset in nA
111        ('e_rev_E',    'E_ex'),
112        ('e_rev_I',    'E_in'),
113        ('tau_sfa',    'tau_sfa'),
114        ('e_rev_sfa',  'E_sfa'),
115        ('q_sfa',      'q_sfa'),
116        ('tau_rr',     'tau_rr'),
117        ('e_rev_rr',   'E_rr'),
118        ('q_rr',       'q_rr')
119    )
120    nest_name = {"on_grid": "iaf_cond_exp_sfa_rr",
121                 "off_grid": "iaf_cond_exp_sfa_rr"}
122    standard_receptor_type = True
123
124
125class IF_facets_hardware1(cells.IF_facets_hardware1):
126
127    __doc__ = cells.IF_facets_hardware1.__doc__
128
129    # in 'iaf_cond_exp', the dimension of C_m is pF,
130    # while in the pyNN context, cm is given in nF
131    translations = build_translations(
132        ('v_reset',    'V_reset'),
133        ('v_rest',     'E_L'),
134        ('v_thresh',   'V_th'),
135        ('e_rev_I',    'E_in'),
136        ('tau_syn_E',  'tau_syn_ex'),
137        ('tau_syn_I',  'tau_syn_in'),
138        ('g_leak',     'g_L')
139    )
140    nest_name = {"on_grid": "iaf_cond_exp",
141                 "off_grid": "iaf_cond_exp"}
142    standard_receptor_type = True
143    extra_parameters = {
144        'C_m': 200.0,
145        't_ref': 1.0,
146        'E_ex': 0.0
147    }
148
149
150class HH_cond_exp(cells.HH_cond_exp):
151
152    __doc__ = cells.HH_cond_exp.__doc__
153
154    translations = build_translations(
155        ('gbar_Na',    'g_Na',  1000.0),  # uS --> nS
156        ('gbar_K',     'g_K',   1000.0),
157        ('g_leak',     'g_L',   1000.0),
158        ('cm',         'C_m',   1000.0),  # nF --> pF
159        ('v_offset',   'V_T'),
160        ('e_rev_Na',   'E_Na'),
161        ('e_rev_K',    'E_K'),
162        ('e_rev_leak', 'E_L'),
163        ('e_rev_E',    'E_ex'),
164        ('e_rev_I',    'E_in'),
165        ('tau_syn_E',  'tau_syn_ex'),
166        ('tau_syn_I',  'tau_syn_in'),
167        ('i_offset',   'I_e',   1000.0),  # nA --> pA
168    )
169    nest_name = {"on_grid": "hh_cond_exp_traub",
170                 "off_grid": "hh_cond_exp_traub"}
171    standard_receptor_type = True
172
173
174class EIF_cond_alpha_isfa_ista(cells.EIF_cond_alpha_isfa_ista):
175
176    __doc__ = cells.EIF_cond_alpha_isfa_ista.__doc__
177
178    translations = build_translations(
179        ('cm',         'C_m',       1000.0),  # nF -> pF
180        ('tau_refrac', 't_ref'),
181        ('v_spike',    'V_peak'),
182        ('v_reset',    'V_reset'),
183        ('v_rest',     'E_L'),
184        ('tau_m',      'g_L',       "cm/tau_m*1000.0", "C_m/g_L"),
185        ('i_offset',   'I_e',       1000.0),  # nA -> pA
186        ('a',          'a'),
187        ('b',          'b',         1000.0),  # nA -> pA.
188        ('delta_T',    'Delta_T'),
189        ('tau_w',      'tau_w'),
190        ('v_thresh',   'V_th'),
191        ('e_rev_E',    'E_ex'),
192        ('tau_syn_E',  'tau_syn_ex'),
193        ('e_rev_I',    'E_in'),
194        ('tau_syn_I',  'tau_syn_in'),
195    )
196    nest_name = {"on_grid": "aeif_cond_alpha",
197                 "off_grid": "aeif_cond_alpha"}
198    standard_receptor_type = True
199
200
201class SpikeSourcePoisson(cells.SpikeSourcePoisson):
202
203    __doc__ = cells.SpikeSourcePoisson.__doc__
204
205    translations = build_translations(
206        ('rate',     'rate'),
207        ('start',    'start'),
208        ('duration', 'stop',    "start+duration", "stop-start"),
209    )
210    nest_name = {"on_grid": 'poisson_generator',
211                 "off_grid": 'poisson_generator_ps'}
212    always_local = True
213    uses_parrot = True
214    extra_parameters = {
215        'origin': 1.0
216    }
217
218
219def unsupported(parameter_name, valid_value):
220    def error_if_invalid(**parameters):
221        if parameters[parameter_name].base_value != valid_value:
222            raise NotImplementedError(
223                "The `{}` parameter is not supported in NEST".format(parameter_name))
224        return valid_value
225    return error_if_invalid
226
227
228class SpikeSourcePoissonRefractory(cells.SpikeSourcePoissonRefractory):
229
230    __doc__ = cells.SpikeSourcePoissonRefractory.__doc__
231
232    translations = build_translations(
233        ('rate',       'rate'),
234        ('tau_refrac', 'dead_time'),
235        ('start',    'UNSUPPORTED', unsupported('start', 0.0), None),
236        ('duration', 'UNSUPPORTED', unsupported('duration', 1e10), None),
237    )
238    nest_name = {"on_grid": 'ppd_sup_generator',
239                 "off_grid": 'ppd_sup_generator'}
240    always_local = True
241    uses_parrot = True
242    extra_parameters = {
243        'n_proc': 1,
244        'frequency': 0.0,
245    }
246
247
248class SpikeSourceGamma(cells.SpikeSourceGamma):
249
250    __doc__ = cells.SpikeSourceGamma.__doc__
251
252    translations = build_translations(
253        ('alpha',    'gamma_shape'),
254        ('beta',     'rate',        'beta/alpha',   'gamma_shape * rate'),
255        ('start',    'UNSUPPORTED', unsupported('start', 0.0), None),
256        ('duration', 'UNSUPPORTED', unsupported('duration', 1e10), None),
257    )
258    nest_name = {"on_grid": 'gamma_sup_generator',
259                 "off_grid": 'gamma_sup_generator'}
260    always_local = True
261    uses_parrot = True
262    extra_parameters = {
263        'n_proc': 1
264    }
265
266
267class SpikeSourceInhGamma(cells.SpikeSourceInhGamma):
268
269    __doc__ = cells.SpikeSourceInhGamma.__doc__
270
271    translations = build_translations(
272        ('a',        'a'),
273        ('b',        'b'),
274        ('tbins',    'tbins'),
275        ('start',    'start'),
276        ('duration', 'stop',   "duration+start", "stop-start"),
277    )
278    nest_name = {"on_grid": 'inh_gamma_generator',
279                 "off_grid":  'inh_gamma_generator'}
280    always_local = True
281    uses_parrot = True
282    extra_parameters = {
283        'origin': 1.0
284    }
285
286
287def adjust_spike_times_forward(spike_times):
288    """
289    Since this cell type requires parrot neurons, we have to adjust the
290    spike times to account for the transmission delay from device to
291    parrot neuron.
292    """
293    # todo: emit warning if any times become negative
294    return spike_times - simulator.state.min_delay
295
296
297def adjust_spike_times_backward(spike_times):
298    """
299    Since this cell type requires parrot neurons, we have to adjust the
300    spike times to account for the transmission delay from device to
301    parrot neuron.
302    """
303    return spike_times + simulator.state.min_delay
304
305
306class SpikeSourceArray(cells.SpikeSourceArray):
307
308    __doc__ = cells.SpikeSourceArray.__doc__
309
310    translations = build_translations(
311        ('spike_times', 'spike_times',
312         adjust_spike_times_forward,
313         adjust_spike_times_backward),
314    )
315    nest_name = {"on_grid": 'spike_generator',
316                 "off_grid": 'spike_generator'}
317    uses_parrot = True
318    always_local = True
319
320
321class EIF_cond_exp_isfa_ista(cells.EIF_cond_exp_isfa_ista):
322
323    __doc__ = cells.EIF_cond_exp_isfa_ista.__doc__
324
325    translations = build_translations(
326        ('cm',         'C_m',       1000.0),  # nF -> pF
327        ('tau_refrac', 't_ref'),
328        ('v_spike',    'V_peak'),
329        ('v_reset',    'V_reset'),
330        ('v_rest',     'E_L'),
331        ('tau_m',      'g_L',       "cm/tau_m*1000.0", "C_m/g_L"),
332        ('i_offset',   'I_e',       1000.0),  # nA -> pA
333        ('a',          'a'),
334        ('b',          'b',         1000.0),  # nA -> pA.
335        ('delta_T',    'Delta_T'),
336        ('tau_w',      'tau_w'),
337        ('v_thresh',   'V_th'),
338        ('e_rev_E',    'E_ex'),
339        ('tau_syn_E',  'tau_syn_ex'),
340        ('e_rev_I',    'E_in'),
341        ('tau_syn_I',  'tau_syn_in'),
342    )
343    nest_name = {"on_grid": "aeif_cond_exp",
344                 "off_grid": "aeif_cond_exp"}
345    standard_receptor_type = True
346
347
348class Izhikevich(cells.Izhikevich):
349    __doc__ = cells.Izhikevich.__doc__
350
351    translations = build_translations(
352        ('a',        'a'),
353        ('b',        'b'),
354        ('c',        'c'),
355        ('d',        'd'),
356        ('i_offset', 'I_e', 1000.0),
357    )
358    nest_name = {"on_grid": "izhikevich",
359                 "off_grid": "izhikevich"}
360    standard_receptor_type = True
361    receptor_scale = 1e-3  # synaptic weight is in mV, so need to undo usual weight scaling
362
363
364class GIF_cond_exp(cells.GIF_cond_exp):
365
366    translations = build_translations(
367        ('v_rest',     'E_L'),
368        ('cm',         'C_m',       1000.0),  # nF -> pF
369        ('tau_m',      'g_L',       "cm/tau_m*1000.0", "C_m/g_L"),
370        ('tau_refrac', 't_ref'),
371        ('tau_syn_E',  'tau_syn_ex'),
372        ('tau_syn_I',  'tau_syn_in'),
373        ('e_rev_E',    'E_ex'),
374        ('e_rev_I',    'E_in'),
375        ('v_reset',    'V_reset'),
376        ('i_offset',   'I_e',       1000.0),  # nA -> pA
377        ('delta_v',    'Delta_V'),
378        ('v_t_star',   'V_T_star'),
379        ('lambda0',    'lambda_0'),
380        ('tau_eta',   'tau_stc'),
381        ('tau_gamma', 'tau_sfa'),
382        ('a_eta',     'q_stc',    1000.0),  # nA -> pA
383        ('a_gamma',   'q_sfa'),
384    )
385    nest_name = {"on_grid": "gif_cond_exp",
386                 "off_grid": "gif_cond_exp"}
387    standard_receptor_type = True
388