NEST main@caf0ae8
 
Loading...
Searching...
No Matches
pp_cond_exp_mc_urbanczik.h
Go to the documentation of this file.
1/*
2 * pp_cond_exp_mc_urbanczik.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef PP_COND_EXP_MC_URBANCZIK_H
24#define PP_COND_EXP_MC_URBANCZIK_H
25
26// Generated includes:
27#include "config.h"
28
29#ifdef HAVE_GSL
30
31// C++ includes:
32#include <vector>
33
34// C includes:
35#include <gsl/gsl_errno.h>
36#include <gsl/gsl_matrix.h>
37#include <gsl/gsl_odeiv.h>
38
39// Includes from nestkernel:
40#include "connection.h"
41#include "event.h"
42#include "nest_types.h"
43#include "random_generators.h"
44#include "recordables_map.h"
45#include "ring_buffer.h"
49
50
51namespace nest
52{
60extern "C" int pp_cond_exp_mc_urbanczik_dynamics( double, const double*, double*, void* );
61
73class pp_cond_exp_mc_urbanczik_parameters
74{
75 friend class pp_cond_exp_mc_urbanczik;
76 friend class UrbanczikArchivingNode< pp_cond_exp_mc_urbanczik_parameters >;
77
78private:
80 enum Compartments_
81 {
82 SOMA = 0,
83 DEND,
84 NCOMP
85 };
86
87 double phi_max;
88 double rate_slope;
89 double beta;
90 double theta;
91 double phi( double u ) const;
92 double h( double u ) const;
93
94public:
95 // The Urbanczik parameters need to be public within this class as they are passed to the GSL solver
96 double g_conn[ NCOMP ];
97 double g_L[ NCOMP ];
98 double C_m[ NCOMP ];
99 double E_L[ NCOMP ];
100 double tau_syn_ex[ NCOMP ];
101 double tau_syn_in[ NCOMP ];
102};
103
104/* BeginUserDocs: neuron, point process, conductance-based, stochastic
105
106Short description
107+++++++++++++++++
108
109Two-compartment point process neuron with conductance-based synapses
110
111Description
112+++++++++++
113
114pp_cond_exp_mc_urbanczik is an implementation of a two-compartment spiking
115point process neuron with conductance-based synapses as it is used
116in :footcite:p:`Urbanczik2014`. It is capable of connecting to an :doc:`Urbanczik synapse
117<urbanczik_synapse>`.
118
119The model has two compartments: soma and dendrite, labeled as s and p,
120respectively. Each compartment can receive spike events and current input
121from a current generator. Additionally, an external (rheobase) current can be
122set for each compartment.
123
124Synapses, including those for injection external currents, are addressed through
125the receptor types given in the receptor_types entry of the state Dictionary.
126Note that in contrast to the single-compartment models, all
127synaptic weights must be positive numbers! The distinction between excitatory
128and inhibitory synapses is made explicitly by specifying the receptor type of
129the synapse. For example, receptor_type=dendritic_exc results in an excitatory
130input and receptor_type=dendritic_inh results in an inhibitory input to the
131dendritic compartment.
132
133.. _multicompartment-models:
134
135Multicompartment models and synaptic delays
136+++++++++++++++++++++++++++++++++++++++++++
137
138Note that in case of multicompartment models that represent the dendrite
139explicitly, the interpretation of the synaptic delay in NEST requires careful
140consideration. In NEST, the delay is at least one simulation time step and is
141assumed to be located entirely at the postsynaptic side. For point neurons, it
142represents the time it takes for an incoming spike to travel along the
143postsynaptic dendrite before it reaches the soma, see :ref:`panel a)
144<fig-multicompartment>`. Conversely, if the synaptic weight depends on the
145state of the postsynaptic neuron, the delay also represents the time it takes
146for the information on the state to propagate back through the dendrite to the
147synapse.
148
149For multicompartment models in NEST, this means the delay is positioned directly
150behind the incoming synapse, that is, before the first dendritic compartment on the
151postsynaptic side, see :ref:`panel b) <fig-multicompartment>`. Therefore, the
152delay specified in the synapse model does *not* account for any delay that might
153be associated with information traveling through the explicitly modeled
154dendritic compartments.
155
156In the :doc:`Urbanczik synapse <urbanczik_synapse>`, the change of the synaptic
157weight is driven by an error signal, which is the difference between the firing
158rate of the soma (derived from the somatic spike train :math:`S_{post}`) and the
159dendritic prediction of the firing rate of the soma (derived from the dendritic
160membrane potential :math:`V`). The original publication :footcite:p:`Urbanczik2014` does not assume any
161delay in the interaction between the soma and the dendritic compartment.
162Therefore, we evaluate the firing rate and the dendritic prediction at equal
163time points to calculate the error signal at that time point. Due to the
164synaptic delay :math:`d`, the synapse combines a delayed version of the error
165signal with the presynaptic spike train (:math:`S_{pre}`), see :ref:`panel c)
166<fig-multicompartment>`.
167
168.. _fig-multicompartment:
169
170.. figure:: ../static/img/multicompartment.png
171 :width: 75 %
172
173 a) Two point neurons (red circles *pre* and *post*) connected via a synapse.
174 In NEST, the delay is entirely on the postsynaptic side, and in the case of point
175 neurons, it is interpreted as the dendritic delay. b) Two two-compartment
176 neuron models composed of a somatic (green) and a dendritic (blue)
177 compartment. The soma of the presynaptic neuron is connected to the dendrite
178 of the postsynaptic neuron. The synaptic delay is located behind the synapse
179 and before the dendrite. c) Time trace of the State variables that enter the
180 Urbanczik-Senn rule. Due to the synaptic delay :math:`d`, the presynaptic
181 spike train (top) is combined with a delayed version of the postsynaptic
182 quantities; the dendritic membrane potential (middle) and the somatic spike
183 train (bottom).
184
185See :doc:`../auto_examples/urbanczik_synapse_example` to learn more.
186
187Parameters
188++++++++++
189
190The following parameters can be set in the status Dictionary. Parameters
191for each compartment are collected in a sub-Dictionary; these sub-dictionaries
192are called "soma" and "dendritic", respectively. In the list below,
193these parameters are marked with an asterisk.
194
195============ ===== =====================================================
196 V_m* mV Membrane potential
197 E_L* mV Leak reversal potential
198 C_m* pF Capacity of the membrane
199 E_ex* mV Excitatory reversal potential
200 E_in* mV Inhibitory reversal potential
201 g_L* nS Leak conductance
202 tau_syn_ex* ms Rise time of the excitatory synaptic alpha function
203 tau_syn_in* ms Rise time of the inhibitory synaptic alpha function
204 I_e* pA Constant input current
205 g_sp nS Coupling between soma and dendrite
206 g_ps nS Coupling between dendrite and soma
207 t_ref ms Duration of refractory period
208============ ===== =====================================================
209
210.. note::
211
212 The neuron model uses standard units of NEST instead of the unitless quantities
213 used in :footcite:p:`Urbanczik2014`.
214
215.. note::
216
217 All parameters that occur for both compartments are stored as C arrays, with
218 index 0 being soma.
219
220Sends
221+++++
222
223SpikeEvent
224
225Receives
226++++++++
227
228SpikeEvent, CurrentEvent, DataLoggingRequest
229
230References
231++++++++++
232
233.. footbibliography::
234
235See also
236++++++++
237
238urbanczik_synapse
239
240Examples using this model
241+++++++++++++++++++++++++
242
243.. listexamples:: pp_cond_exp_mc_urbanczik
244
245EndUserDocs */
246
247void register_pp_cond_exp_mc_urbanczik( const std::string& name );
248
249class pp_cond_exp_mc_urbanczik : public UrbanczikArchivingNode< pp_cond_exp_mc_urbanczik_parameters >
250{
251
252 // Boilerplate function declarations --------------------------------
253
254public:
255 pp_cond_exp_mc_urbanczik();
256 pp_cond_exp_mc_urbanczik( const pp_cond_exp_mc_urbanczik& );
257 ~pp_cond_exp_mc_urbanczik() override;
258
264 using Node::handle;
265 using Node::handles_test_event;
266
267 size_t send_test_event( Node&, size_t, synindex, bool ) override;
268
269 void handle( SpikeEvent& ) override;
270 void handle( CurrentEvent& ) override;
271 void handle( DataLoggingRequest& ) override;
272
273 size_t handles_test_event( SpikeEvent&, size_t ) override;
274 size_t handles_test_event( CurrentEvent&, size_t ) override;
275 size_t handles_test_event( DataLoggingRequest&, size_t ) override;
276
277 void get_status( Dictionary& ) const override;
278 void set_status( const Dictionary& ) override;
279
280private:
281 void init_buffers_() override;
282 void pre_run_hook() override;
283 void update( Time const&, const long, const long ) override;
284
285 // Enumerations and constants specifying structure and properties ----
286
288 enum Compartments_
289 {
290 SOMA = 0,
291 DEND,
292 NCOMP
293 };
294
300 static const size_t MIN_SPIKE_RECEPTOR = 1;
301
305 enum SpikeSynapseTypes
306 {
307 SOMA_EXC = MIN_SPIKE_RECEPTOR,
308 SOMA_INH,
309 DEND_EXC,
310 DEND_INH,
311 SUP_SPIKE_RECEPTOR
312 };
313
314 static const size_t NUM_SPIKE_RECEPTORS = SUP_SPIKE_RECEPTOR - MIN_SPIKE_RECEPTOR;
315
321 static const size_t MIN_CURR_RECEPTOR = SUP_SPIKE_RECEPTOR;
322
326 enum CurrentSynapseTypes
327 {
328 I_SOMA = MIN_CURR_RECEPTOR,
329 I_DEND,
330 SUP_CURR_RECEPTOR
331 };
332
333 static const size_t NUM_CURR_RECEPTORS = SUP_CURR_RECEPTOR - MIN_CURR_RECEPTOR;
334
335 // Friends --------------------------------------------------------
336
337 friend int pp_cond_exp_mc_urbanczik_dynamics( double, const double*, double*, void* );
338
339 friend class RecordablesMap< pp_cond_exp_mc_urbanczik >;
340 friend class UniversalDataLogger< pp_cond_exp_mc_urbanczik >;
341
342
343 // Parameters ------------------------------------------------------
344
363 struct Parameters_
364 {
365 double t_ref;
366 double E_ex[ NCOMP ];
367 double E_in[ NCOMP ];
368 double I_e[ NCOMP ];
369
370 pp_cond_exp_mc_urbanczik_parameters urbanczik_params;
371
373 double dead_time_;
374
375 Parameters_();
376 Parameters_( const Parameters_& );
377 Parameters_& operator=( const Parameters_& );
378
379 void get( Dictionary& ) const;
380 void set( const Dictionary& );
381 };
382
383
384 // State variables ------------------------------------------------------
385
390public:
391 struct State_
392 {
393
400 enum StateVecElems_
401 {
402 V_M = 0,
403 G_EXC,
404 G_INH,
405 I_EXC, // in the paper it is I_dnd which accounts for both excitation and inhibition
406 I_INH,
407 STATE_VEC_COMPS
408 };
409
411 static const size_t STATE_VEC_SIZE = to_underlying( STATE_VEC_COMPS ) * to_underlying( NCOMP );
412
414 double y_[ STATE_VEC_SIZE ];
415 int r_;
416
417 State_( const Parameters_& );
418 State_( const State_& );
419
420 State_& operator=( const State_& );
421
422 void get( Dictionary& ) const;
423 void set( const Dictionary&, const Parameters_& );
424
432 static size_t
433 idx( size_t comp, StateVecElems_ elem )
434 {
435 assert( comp * STATE_VEC_COMPS + elem < STATE_VEC_SIZE );
436 return comp * STATE_VEC_COMPS + elem;
437 }
438 };
439
440private:
441 // Internal buffers --------------------------------------------------------
442
446 struct Buffers_
447 {
448 Buffers_( pp_cond_exp_mc_urbanczik& );
450 Buffers_( const Buffers_&, pp_cond_exp_mc_urbanczik& );
451
453 UniversalDataLogger< pp_cond_exp_mc_urbanczik > logger_;
454
458 std::vector< RingBuffer > spikes_;
459 std::vector< RingBuffer > currents_;
460
462 gsl_odeiv_step* s_;
463 gsl_odeiv_control* c_;
464 gsl_odeiv_evolve* e_;
465 gsl_odeiv_system sys_;
466
467 // IntegrationStep_ should be reset with the neuron on ResetNetwork,
468 // but remain unchanged during calibration. Since it is initialized with
469 // step_, and the resolution cannot change after nodes have been created,
470 // it is safe to place both here.
471 double step_;
472 double IntegrationStep_;
473
481 double I_stim_[ NCOMP ];
482 };
483
484 // Internal variables ---------------------------------------------
485
489 struct Variables_
490 {
491 int RefractoryCounts_;
492
493 double h_;
494 RngPtr rng_;
495 poisson_distribution poisson_dist_;
496 };
497
498 // Access functions for UniversalDataLogger -------------------------------
499
504 template < State_::StateVecElems_ elem, Compartments_ comp >
505 double
506 get_y_elem_() const
507 {
508 return S_.y_[ S_.idx( comp, elem ) ];
509 }
510
512 double
513 get_r_() const
514 {
515 return Time::get_resolution().get_ms() * S_.r_;
516 }
517
518 // Data members ----------------------------------------------------
519
520 Parameters_ P_;
521 State_ S_;
522 Variables_ V_;
523 Buffers_ B_;
524
526 static std::vector< std::string > comp_names_;
527
528 // Dictionary of receptor types, leads to seg fault on exit, see #328
529
531 static RecordablesMap< pp_cond_exp_mc_urbanczik > recordablesMap_;
532};
533
534
535// Inline functions of pp_cond_exp_mc_urbanczik_parameters
536inline double
537pp_cond_exp_mc_urbanczik_parameters::phi( double u ) const
538{
539 return phi_max / ( 1.0 + rate_slope * exp( beta * ( theta - u ) ) );
540}
541
542inline double
543pp_cond_exp_mc_urbanczik_parameters::h( double u ) const
544{
545 return 15.0 * beta / ( 1.0 + ( 1.0 / rate_slope ) * exp( -beta * ( theta - u ) ) );
546}
547
548
549// Inline functions of pp_cond_exp_mc_urbanczik
550inline size_t
551pp_cond_exp_mc_urbanczik::send_test_event( Node& target, size_t receptor_type, synindex, bool )
552{
553 SpikeEvent e;
554 e.set_sender( *this );
555 return target.handles_test_event( e, receptor_type );
556}
557
558inline size_t
559pp_cond_exp_mc_urbanczik::handles_test_event( SpikeEvent&, size_t receptor_type )
560{
561 if ( receptor_type < MIN_SPIKE_RECEPTOR or receptor_type >= SUP_SPIKE_RECEPTOR )
562 {
563 if ( receptor_type >= SUP_CURR_RECEPTOR )
564 {
565 throw UnknownReceptorType( receptor_type, get_name() );
566 }
567 else
568 {
569 throw IncompatibleReceptorType( receptor_type, get_name(), "SpikeEvent" );
570 }
571 }
572 return receptor_type - MIN_SPIKE_RECEPTOR;
573}
574
575inline size_t
576pp_cond_exp_mc_urbanczik::handles_test_event( CurrentEvent&, size_t receptor_type )
577{
578 if ( receptor_type < MIN_CURR_RECEPTOR or receptor_type >= SUP_CURR_RECEPTOR )
579 {
580 if ( receptor_type < MIN_CURR_RECEPTOR )
581 {
582 throw IncompatibleReceptorType( receptor_type, get_name(), "CurrentEvent" );
583 }
584 else
585 {
586 throw UnknownReceptorType( receptor_type, get_name() );
587 }
588 }
589 return receptor_type - MIN_CURR_RECEPTOR;
590}
591
592inline size_t
593pp_cond_exp_mc_urbanczik::handles_test_event( DataLoggingRequest& dlr, size_t receptor_type )
594{
595 if ( receptor_type != 0 )
596 {
597 if ( receptor_type >= SUP_CURR_RECEPTOR )
598 {
599 throw UnknownReceptorType( receptor_type, get_name() );
600 }
601 else
602 {
603 throw IncompatibleReceptorType( receptor_type, get_name(), "DataLoggingRequest" );
604 }
605 }
606 return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
607}
608
609inline void
610pp_cond_exp_mc_urbanczik::get_status( Dictionary& d ) const
611{
612 P_.get( d );
613 S_.get( d );
615
616 d[ names::recordables ] = recordablesMap_.get_list();
617
623 Dictionary receptor_dict_;
624 receptor_dict_[ names::soma_exc ] = static_cast< long >( SOMA_EXC );
625 receptor_dict_[ names::soma_inh ] = static_cast< long >( SOMA_INH );
626 receptor_dict_[ names::soma_curr ] = static_cast< long >( I_SOMA );
627
628 receptor_dict_[ names::dendritic_exc ] = static_cast< long >( DEND_EXC );
629 receptor_dict_[ names::dendritic_inh ] = static_cast< long >( DEND_INH );
630 receptor_dict_[ names::dendritic_curr ] = static_cast< long >( I_DEND );
631
632 d[ names::receptor_types ] = receptor_dict_;
633}
634
635inline void
636pp_cond_exp_mc_urbanczik::set_status( const Dictionary& d )
637{
638 Parameters_ ptmp = P_; // temporary copy in case of errors
639 ptmp.set( d ); // throws if BadProperty
640 State_ stmp = S_; // temporary copy in case of errors
641 stmp.set( d, ptmp ); // throws if BadProperty
642
643 // We now know that (ptmp, stmp) are consistent. We do not
644 // write them back to (P_, S_) before we are also sure that
645 // the properties to be set in the parent class are internally
646 // consistent.
648
649 // if we get here, temporaries contain consistent set of properties
650 P_ = ptmp;
651 S_ = stmp;
652}
653
654} // namespace
655
656
657#endif // HAVE_GSL
658#endif // PP_COND_EXP_MC_URBANCZIK_H
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
void get_status(Dictionary &d) const override
Export properties of the node by setting entries in the status dictionary.
Definition urbanczik_archiving_node_impl.h:47
void set_status(const Dictionary &d) override
Change properties of the node according to the entries in the dictionary.
Definition urbanczik_archiving_node_impl.h:54
const std::string dendritic_exc("dendritic_exc")
const std::string t_ref("t_ref")
const std::string tau_syn_in("tau_syn_in")
const std::string E_L("E_L")
const std::string I_e("I_e")
const std::string dendritic_curr("dendritic_curr")
const std::string phi_max("phi_max")
const std::string recordables("recordables")
const std::string C_m("C_m")
const std::string d("d")
const std::string receptor_types("receptor_types")
const std::string receptor_type("receptor_type")
const std::string rate_slope("rate_slope")
const std::string E_in("E_in")
const std::string soma_exc("soma_exc")
const std::string beta("beta")
const std::string target("target")
const std::string tau_syn_ex("tau_syn_ex")
const std::string dendritic_inh("dendritic_inh")
const std::string soma_curr("soma_curr")
const std::string theta("theta")
const std::string E_ex("E_ex")
const std::string soma_inh("soma_inh")
const std::string h("h")
const std::string g_L("g_L")
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
RandomDistribution< std::poisson_distribution< unsigned long > > poisson_distribution
Definition random_generators.h:60
BaseRandomGenerator * RngPtr
Definition random_generators.h:50
constexpr auto to_underlying(E e) noexcept
Cast enum value to underlying integer type.
Definition nest_types.h:182
size_t synindex
For enumerations of synapse types.
Definition nest_types.h:115
const double e
Definition numerics.cpp:32