1 /*
2  *  pp_psc_delta.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_PSC_DELTA_H
24 #define PP_PSC_DELTA_H
25 
26 // Includes from nestkernel:
27 #include "archiving_node.h"
28 #include "connection.h"
29 #include "event.h"
30 #include "nest_types.h"
31 #include "random_generators.h"
32 #include "ring_buffer.h"
33 #include "universal_data_logger.h"
34 
35 namespace nest
36 {
37 
38 /* BeginUserDocs: neuron, point process, current-based
39 
40 Short description
41 +++++++++++++++++
42 
43 Point process neuron with leaky integration of delta-shaped PSCs
44 
45 Description
46 +++++++++++
47 
48 pp_psc_delta is an implementation of a leaky integrator, where the potential
49 jumps on each spike arrival. It produces spike stochastically, and supports
50 spike-frequency adaptation, and other optional features.
51 
52 Spikes are generated randomly according to the current value of the
53 transfer function which operates on the membrane potential. Spike
54 generation is followed by an optional dead time. Setting with_reset to
55 true will reset the membrane potential after each spike.
56 
57 The transfer function can be chosen to be linear, exponential or a sum of
58 both by adjusting three parameters:
59 
60 .. math::
61 
62   rate = Rect[ c_1 * V' + c_2 * \exp(c_3 * V') ],
63 
64 where the effective potential :math:`V' = V_m - E_{sfa}` and :math:`E_{sfa}`
65 is called the adaptive threshold. Here Rect means rectifier:
66 :math:`Rect(x) = {x \text{ if } x>=0, 0 \text{ else}}` (this is necessary
67 because
68 negative rates are not possible).
69 
70 By setting c_3 = 0, c_2 can be used as an offset spike rate for an otherwise
71 linear rate model.
72 
73 The dead time enables to include refractoriness. If dead time is 0, the
74 number of spikes in one time step might exceed one and is drawn from the
75 Poisson distribution accordingly. Otherwise, the probability for a spike
76 is given by :math:`1 - \exp(-rate*h)`, where h is the simulation time step. If
77 dead_time is smaller than the simulation resolution (time step), it is
78 internally set to the resolution.
79 
80 Note that, even if non-refractory neurons are to be modeled, a small value
81 of dead_time, like dead_time=1e-8, might be the value of choice since it
82 uses faster uniform random numbers than dead_time=0, which draws Poisson
83 numbers. Only for very large spike rates (> 1 spike/time_step) this will
84 cause errors.
85 
86 The model can optionally include an adaptive firing threshold.
87 If the neuron spikes, the threshold increases and the membrane potential
88 will take longer to reach it.
89 Here this is implemented by subtracting the value of the adaptive threshold
90 E_sfa from the membrane potential V_m before passing the potential to the
91 transfer function, see also above. E_sfa jumps by q_sfa when the neuron
92 fires a spike, and decays exponentially with the time constant tau_sfa
93 after (see [2]_ or [3]_). Thus, the E_sfa corresponds to the convolution of the
94 neuron's spike train with an exponential kernel.
95 This adaptation kernel may also be chosen as the sum of n exponential
96 kernels. To use this feature, q_sfa and tau_sfa have to be given as a list
97 of n values each.
98 
99 The firing of pp_psc_delta is usually not a renewal process. For example,
100 its firing may depend on its past spikes if it has non-zero adaptation terms
101 (q_sfa). But if so, it will depend on all its previous spikes, not just the
102 last one -- so it is not a renewal process model. However, if "with_reset"
103 is True, and all adaptation terms (q_sfa) are 0, then it will reset
104 ("forget") its membrane potential each time a spike is emitted, which makes
105 it a renewal process model (where "rate" above is its hazard function,
106 also known as conditional intensity).
107 
108 pp_psc_delta may also be called a spike-response model with escape-noise [6]_
109 (for vanishing, non-random dead_time). If c_1>0 and c_2==0, the rate is a
110 convolution of the inputs with exponential filters -- which is a model known
111 as a Hawkes point process (see [4]_). If instead c_1==0, then pp_psc_delta is
112 a point process generalized linear model (with the canonical link function,
113 and exponential input filters) (see [5,6]_).
114 
115 This model has been adapted from iaf_psc_delta. The default parameters are
116 set to the mean values given in [2]_, which have been matched to spike-train
117 recordings. Due to the many features of pp_psc_delta and its versatility,
118 parameters should be set carefully and consciously.
119 
120 Parameters
121 ++++++++++
122 
123 The following parameters can be set in the status dictionary.
124 
125 
126 =================  ======= ===================================================
127  V_m               mV      Membrane potential
128  C_m               pF      Capacitance of the membrane
129  tau_m             ms      Membrane time constant
130  q_sfa             mV      Adaptive threshold jump
131  tau_sfa           ms      Adaptive threshold time constant
132  dead_time         ms      Duration of the dead time
133  dead_time_random  boolean Should a random dead time be drawn after each
134                            spike?
135  dead_time_shape   integer Shape parameter of dead time gamma distribution
136  t_ref_remaining   ms      Remaining dead time at simulation start
137  with_reset        boolean Should the membrane potential be reset after a
138                            spike?
139  I_e               pA      Constant input current
140  c_1               Hz/mV   Slope of linear part of transfer function in
141                            Hz/mV
142  c_2               Hz      Prefactor of exponential part of transfer function
143  c_3               1/mV    Coefficient of exponential non-linearity of
144                            transfer function
145 =================  ======= ===================================================
146 
147 
148 References
149 ++++++++++
150 
151 .. [1] Cardanobile S, Rotter S (2010). Multiplicatively interacting point
152        processes and applications to neural modeling. Journal of
153        Computational Neuroscience 28(2):267-284
154        DOI: https://doi.org/10.1007/s10827-009-0204-0
155 .. [2] Jolivet R, Rauch A, Luescher H-R, Gerstner W. (2006). Predicting spike
156        timing of neocortical pyramidal neurons by simple threshold models.
157        Journal of Computational Neuroscience 21:35-49.
158        DOI: https://doi.org/10.1007/s10827-006-7074-5
159 .. [3] Pozzorini C, Naud R, Mensi S, Gerstner W (2013). Temporal whitening by
160        power-law adaptation in neocortical neurons. Nature Neuroscience
161        16:942-948. (Uses a similar model of multi-timescale adaptation)
162        DOI: https://doi.org/10.1038/nn.3431
163 .. [4] Grytskyy D, Tetzlaff T, Diesmann M, Helias M (2013). A unified view
164        on weakly correlated recurrent networks. Frontiers in Computational
165        Neuroscience, 7:131.
166        DOI: https://doi.org/10.3389/fncom.2013.00131
167 .. [5] Deger M, Schwalger T, Naud R, Gerstner W (2014). Fluctuations and
168        information filtering in coupled populations of spiking neurons with
169        adaptation. Physical Review E 90:6, 062704.
170        DOI: https://doi.org/10.1103/PhysRevE.90.062704
171 .. [6] Gerstner W, Kistler WM, Naud R, Paninski L (2014). Neuronal Dynamics:
172        From single neurons to networks and models of cognition.
173        Cambridge University Press
174 
175 
176 Sends
177 +++++
178 
179 SpikeEvent
180 
181 Receives
182 ++++++++
183 
184 SpikeEvent, CurrentEvent, DataLoggingRequest
185 
186 See also
187 ++++++++
188 
189 pp_pop_psc_delta, iaf_psc_delta, iaf_psc_alpha, iaf_psc_exp, iaf_psc_delta_ps
190 
191 EndUserDocs */
192 
193 class pp_psc_delta : public ArchivingNode
194 {
195 
196 public:
197   pp_psc_delta();
198   pp_psc_delta( const pp_psc_delta& );
199 
200   /**
201    * Import sets of overloaded virtual functions.
202    * @see Technical Issues / Virtual Functions: Overriding, Overloading, and
203    * Hiding
204    */
205   using Node::handle;
206   using Node::handles_test_event;
207 
208   port send_test_event( Node&, rport, synindex, bool );
209 
210   void handle( SpikeEvent& );
211   void handle( CurrentEvent& );
212   void handle( DataLoggingRequest& );
213 
214   port handles_test_event( SpikeEvent&, rport );
215   port handles_test_event( CurrentEvent&, rport );
216   port handles_test_event( DataLoggingRequest&, rport );
217 
218 
219   void get_status( DictionaryDatum& ) const;
220   void set_status( const DictionaryDatum& );
221 
222 private:
223   void init_state_();
224   void init_buffers_();
225   void calibrate();
226 
227   void update( Time const&, const long, const long );
228 
229   // The next two classes need to be friends to access the State_ class/member
230   friend class RecordablesMap< pp_psc_delta >;
231   friend class UniversalDataLogger< pp_psc_delta >;
232 
233   // ----------------------------------------------------------------
234 
235   /**
236    * Independent parameters of the model.
237    */
238   struct Parameters_
239   {
240     /** Membrane time constant in ms. */
241     double tau_m_;
242 
243     /** Membrane capacitance in pF. */
244     double c_m_;
245 
246     /** Dead time in ms. */
247     double dead_time_;
248 
249     /** Do we use random dead time? */
250     bool dead_time_random_;
251 
252     /** Shape parameter of random dead time gamma distribution. */
253     unsigned long dead_time_shape_;
254 
255     /** Do we reset the membrane potential after each spike? */
256     bool with_reset_;
257 
258     /** List of adaptive threshold time constant in ms (for multi adaptation
259      * version). */
260     std::vector< double > tau_sfa_;
261 
262     /** Adaptive threshold jump in mV (for multi adaptation version). */
263     std::vector< double > q_sfa_;
264 
265     /** indicates multi parameter adaptation model **/
266     bool multi_param_;
267 
268     /** Slope of the linear part of transfer function. */
269     double c_1_;
270 
271     /** Prefactor of exponential part of transfer function. */
272     double c_2_;
273 
274     /** Coefficient of exponential non-linearity of transfer function. */
275     double c_3_;
276 
277     /** External DC current. */
278     double I_e_;
279 
280     /** Dead time from simulation start. */
281     double t_ref_remaining_;
282 
283     Parameters_(); //!< Sets default parameter values
284 
285     void get( DictionaryDatum& ) const;             //!< Store current values in dictionary
286     void set( const DictionaryDatum&, Node* node ); //!< Set values from dictionary
287   };
288 
289   // ----------------------------------------------------------------
290 
291   /**
292    * State variables of the model.
293    */
294   struct State_
295   {
296     double y0_; //!< This is piecewise constant external current
297     //! This is the membrane potential RELATIVE TO RESTING POTENTIAL.
298     double y3_;
299     double q_; //!< This is the change of the 'threshold' due to adaptation.
300 
301     //! Vector of adaptation parameters. by Hesam
302     std::vector< double > q_elems_;
303 
304     int r_; //!< Number of refractory steps remaining
305 
306     bool initialized_; //!< it is true if the vectors are initialized
307 
308     State_(); //!< Default initialization
309 
310     void get( DictionaryDatum&, const Parameters_& ) const;
311     void set( const DictionaryDatum&, const Parameters_&, Node* );
312   };
313 
314   // ----------------------------------------------------------------
315 
316   /**
317    * Buffers of the model.
318    */
319   struct Buffers_
320   {
321     Buffers_( pp_psc_delta& );
322     Buffers_( const Buffers_&, pp_psc_delta& );
323 
324     /** buffers and sums up incoming spikes/currents */
325     RingBuffer spikes_;
326     RingBuffer currents_;
327 
328     //! Logger for all analog data
329     UniversalDataLogger< pp_psc_delta > logger_;
330   };
331 
332   // ----------------------------------------------------------------
333 
334   /**
335    * Internal variables of the model.
336    */
337   struct Variables_
338   {
339 
340     double P30_;
341     double P33_;
342 
343     std::vector< double > Q33_;
344 
345     double h_;       //!< simulation time step in ms
346     double dt_rate_; //!< rate parameter of dead time distribution
347 
348     RngPtr rng_;                        //!< random number generator of my own thread
349     gamma_distribution gamma_dist_;     //!< gamma distribution
350     poisson_distribution poisson_dist_; //!< poisson distribution
351 
352     int DeadTimeCounts_;
353   };
354 
355   // Access functions for UniversalDataLogger -----------------------
356 
357   //! Read out the real membrane potential
358   double
get_V_m_()359   get_V_m_() const
360   {
361     return S_.y3_;
362   }
363 
364   //! Read out the adaptive threshold potential
365   double
get_E_sfa_()366   get_E_sfa_() const
367   {
368     return S_.q_;
369   }
370 
371   // ----------------------------------------------------------------
372 
373   /**
374    * @defgroup iaf_psc_alpha_data
375    * Instances of private data structures for the different types
376    * of data pertaining to the model.
377    * @note The order of definitions is important for speed.
378    * @{
379    */
380   Parameters_ P_;
381   State_ S_;
382   Variables_ V_;
383   Buffers_ B_;
384   /** @} */
385 
386   //! Mapping of recordables names to access functions
387   static RecordablesMap< pp_psc_delta > recordablesMap_;
388 };
389 
390 inline port
send_test_event(Node & target,rport receptor_type,synindex,bool)391 pp_psc_delta::send_test_event( Node& target, rport receptor_type, synindex, bool )
392 {
393   SpikeEvent e;
394   e.set_sender( *this );
395 
396   return target.handles_test_event( e, receptor_type );
397 }
398 
399 
400 inline port
handles_test_event(SpikeEvent &,rport receptor_type)401 pp_psc_delta::handles_test_event( SpikeEvent&, rport receptor_type )
402 {
403   if ( receptor_type != 0 )
404   {
405     throw UnknownReceptorType( receptor_type, get_name() );
406   }
407   return 0;
408 }
409 
410 inline port
handles_test_event(CurrentEvent &,rport receptor_type)411 pp_psc_delta::handles_test_event( CurrentEvent&, rport receptor_type )
412 {
413   if ( receptor_type != 0 )
414   {
415     throw UnknownReceptorType( receptor_type, get_name() );
416   }
417   return 0;
418 }
419 
420 inline port
handles_test_event(DataLoggingRequest & dlr,rport receptor_type)421 pp_psc_delta::handles_test_event( DataLoggingRequest& dlr, rport receptor_type )
422 {
423   if ( receptor_type != 0 )
424   {
425     throw UnknownReceptorType( receptor_type, get_name() );
426   }
427   return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
428 }
429 
430 inline void
get_status(DictionaryDatum & d)431 pp_psc_delta::get_status( DictionaryDatum& d ) const
432 {
433   P_.get( d );
434   S_.get( d, P_ );
435   ArchivingNode::get_status( d );
436   ( *d )[ names::recordables ] = recordablesMap_.get_list();
437 }
438 
439 inline void
set_status(const DictionaryDatum & d)440 pp_psc_delta::set_status( const DictionaryDatum& d )
441 {
442   Parameters_ ptmp = P_;     // temporary copy in case of errors
443   ptmp.set( d, this );       // throws if BadProperty
444   State_ stmp = S_;          // temporary copy in case of errors
445   stmp.set( d, ptmp, this ); // throws if BadProperty
446 
447   // We now know that (ptmp, stmp) are consistent. We do not
448   // write them back to (P_, S_) before we are also sure that
449   // the properties to be set in the parent class are internally
450   // consistent.
451   ArchivingNode::set_status( d );
452 
453   // if we get here, temporaries contain consistent set of properties
454   P_ = ptmp;
455   S_ = stmp;
456 }
457 
458 } // namespace
459 
460 #endif /* #ifndef PP_PSC_DELTA_H */
461