/*
* ht_neuron.h
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see .
*
*/
#ifndef HT_NEURON_H
#define HT_NEURON_H
// Generated includes:
#include "config.h"
#ifdef HAVE_GSL
// C++ includes:
#include
#include
// C includes:
#include
#include
#include
// Includes from nestkernel:
#include "archiving_node.h"
#include "connection.h"
#include "recordables_map.h"
#include "ring_buffer.h"
#include "universal_data_logger.h"
// Includes from
// Includes from sli:
#include "stringdatum.h"
namespace nest
{
/**
* Function computing right-hand side of ODE for GSL solver.
* @note Must be declared here so we can befriend it in class.
* @note Must have C-linkage for passing to GSL. Internally, it is
* a first-class C++ function, but cannot be a member function
* because of the C-linkage.
* @note No point in declaring it inline, since it is called
* through a function pointer.
* @param void* Pointer to model neuron instance.
*/
extern "C" int ht_neuron_dynamics( double, const double*, double*, void* );
/* BeginUserDocs: neuron, Hill-Tononi plasticity
Short description
+++++++++++++++++
Neuron model after Hill & Tononi (2005)
Description
+++++++++++
This model neuron implements a slightly modified version of the
neuron model described in [1]_. The most important properties are:
- Integrate-and-fire with threshold adaptive threshold.
- Repolarizing potassium current instead of hard reset.
- AMPA, NMDA, GABA_A, and GABA_B conductance-based synapses with
beta-function (difference of exponentials) time course.
- Voltage-dependent NMDA with instantaneous or two-stage unblocking [1]_, [2]_.
- Intrinsic currents I_h, I_T, I_Na(p), and I_KNa.
- Synaptic "minis" are not implemented.
For implementation details see:
- `HillTononi_model <../model_details/HillTononiModels.ipynb>`_
For examples, see:
- :doc:`../auto_examples/intrinsic_currents_spiking`
- :doc:`../auto_examples/intrinsic_currents_subthreshold`
For an example network model using ``ht_neuron`` (based on [1]_), see:
- `Multiarea Hill-Tononi thalamocortical network model
`_
Parameters
++++++++++
=============== ======= =========================================================
V_m mV Membrane potential
tau_m ms Membrane time constant applying to all currents except
repolarizing K-current (see [1]_, p 1677)
t_ref ms Refractory time and duration of post-spike repolarizing
potassium current (t_spike in [1]_)
tau_spike ms Membrane time constant for post-spike repolarizing
potassium current
voltage_clamp boolean If true, clamp voltage to value at beginning of
simulation
(default: false, mainly for testing)
theta mV Threshold
theta_eq mV Equilibrium value
tau_theta ms Time constant
g_KL nS Conductance for potassium leak current
E_K mV Reversal potential for potassium leak currents
g_NaL nS Conductance for sodium leak currents
E_Na mV Reversal potential for Na leak currents
tau_D_KNa ms Relaxation time constant for I_KNa
receptor_types Dictionary mapping synapse names to ports on neuron model
recordables List of recordable quantities
=============== ======= =========================================================
+------------------------------------------------------------+
|{E_rev,g_peak,tau_rise,tau_decay}_{AMPA,NMDA,GABA_A,GABA_B} |
+------------------------------------------------------------+
| Reversal potentials, peak conductances and time constants |
| for synapses (tau_rise/tau_decay correspond to tau_1/tau_2 |
| in the paper) |
+------------------------------------------------------------+
+------------------------+------------------------------------------------+
|V_act_NMDA, S_act_NMDA, | Parameters for voltage dependence of NMDA- |
|tau_Mg_{fast, slow}_NMDA| conductance, see above |
+------------------------+------------------------------------------------+
============================ =================================================
instant_unblock_NMDA Instantaneous NMDA unblocking (default: false)
{E_rev,g_peak}_{h,T,NaP,KNa} Reversal potential and peak conductance for
intrinsic currents
{N}_{T,NaP} Exponent activation term m_inf, corresponding to
number of activation particles
equilibrate If given and true, time-dependent activation
and inactivation state variables (h, m) of
intrinsic currents and NMDA channels are set
to their equilibrium values during this
SetStatus call; otherwise they retain their
present values.
============================ =================================================
.. note::
Conductances are unitless in this model and currents are in mV.
Sends
+++++
SpikeEvent
Receives
++++++++
SpikeEvent, CurrentEvent, DataLoggingRequest
References
++++++++++
.. [1] Hill S, Tononi G (2005). Modeling sleep and wakefulness in the
thalamocortical system. Journal of Neurophysiology. 93:1671-1698.
DOI: https://doi.org/10.1152/jn.00915.2004
.. [2] Vargas-Caballero M, Robinson HPC (2003). A slow fraction of Mg2+
unblock of NMDA receptors limits their contribution to spike generation
in cortical pyramidal neurons. Journal of Neurophysiology 89:2778-2783.
DOI: https://doi.org/10.1152/jn.01038.2002
See also
++++++++
ht_synapse
EndUserDocs */
class ht_neuron : public ArchivingNode
{
public:
ht_neuron();
ht_neuron( const ht_neuron& );
~ht_neuron();
/**
* Import sets of overloaded virtual functions.
* @see Technical Issues / Virtual Functions: Overriding, Overloading, and
* Hiding
*/
using Node::handle;
using Node::handles_test_event;
port send_test_event( Node&, rport, synindex, bool );
void handle( SpikeEvent& e );
void handle( CurrentEvent& e );
void handle( DataLoggingRequest& );
port handles_test_event( SpikeEvent&, rport );
port handles_test_event( CurrentEvent&, rport );
port handles_test_event( DataLoggingRequest&, rport );
void get_status( DictionaryDatum& ) const;
void set_status( const DictionaryDatum& );
private:
/**
* Synapse types to connect to
* @note Excluded upper and lower bounds are defined as INF_, SUP_.
* Excluding port 0 avoids accidental connections.
*/
enum SynapseTypes
{
INF_SPIKE_RECEPTOR = 0,
AMPA,
NMDA,
GABA_A,
GABA_B,
SUP_SPIKE_RECEPTOR
};
void init_buffers_();
void calibrate();
void update( Time const&, const long, const long );
double get_synapse_constant( double, double, double );
// END Boilerplate function declarations ----------------------------
// Friends --------------------------------------------------------
// make dynamics function quasi-member
friend int ht_neuron_dynamics( double, const double*, double*, void* );
// ----------------------------------------------------------------
/**
* Independent parameters of the model.
*/
struct Parameters_
{
Parameters_();
void get( DictionaryDatum& ) const; //!< Store current values in dictionary
void set( const DictionaryDatum&, Node* node ); //!< Set values from dicitonary
// Note: Conductances are unitless
// Leaks
double E_Na; // mV
double E_K; // mV
double g_NaL;
double g_KL;
double tau_m; // ms
// Dynamic threshold
double theta_eq; // mV
double tau_theta; // ms
// Post-spike potassium current
double tau_spike; // ms, membrane time constant for this current
double t_ref; // ms, refractory time
// Parameters for synapse of type AMPA, GABA_A, GABA_B and NMDA
double g_peak_AMPA;
double tau_rise_AMPA; // ms
double tau_decay_AMPA; // ms
double E_rev_AMPA; // mV
double g_peak_NMDA;
double tau_rise_NMDA; // ms
double tau_decay_NMDA; // ms
double E_rev_NMDA; // mV
double V_act_NMDA; // mV, inactive for V << Vact, inflection of sigmoid
double S_act_NMDA; // mV, scale of inactivation
double tau_Mg_slow_NMDA; // ms
double tau_Mg_fast_NMDA; // ms
bool instant_unblock_NMDA;
double g_peak_GABA_A;
double tau_rise_GABA_A; // ms
double tau_decay_GABA_A; // ms
double E_rev_GABA_A; // mV
double g_peak_GABA_B;
double tau_rise_GABA_B; // ms
double tau_decay_GABA_B; // ms
double E_rev_GABA_B; // mV
// parameters for intrinsic currents
double g_peak_NaP;
double E_rev_NaP; // mV
double N_NaP;
double g_peak_KNa;
double E_rev_KNa; // mV
double tau_D_KNa; // ms
double g_peak_T;
double E_rev_T; // mV
double N_T;
double g_peak_h;
double E_rev_h; // mV
bool voltage_clamp;
};
// ----------------------------------------------------------------
/**
* State variables of the model.
*/
public:
struct State_
{
// y_ = [V, theta, Synapses]
enum StateVecElems_
{
V_M = 0,
THETA,
DG_AMPA,
G_AMPA,
DG_NMDA_TIMECOURSE,
G_NMDA_TIMECOURSE,
DG_GABA_A,
G_GABA_A,
DG_GABA_B,
G_GABA_B, // DO NOT INSERT ANYTHING UP TO HERE, WILL MIX UP
// SPIKE DELIVERY
m_fast_NMDA,
m_slow_NMDA,
m_Ih,
D_IKNa,
m_IT,
h_IT,
STATE_VEC_SIZE
};
//! neuron state, must be C-array for GSL solver
double y_[ STATE_VEC_SIZE ];
/** Timer (counter) for spike-activated repolarizing potassium current.
* Neuron is absolutely refractory during this period.
*/
long ref_steps_;
double I_NaP_; //!< Persistent Na current; member only to allow recording
double I_KNa_; //!< Depol act. K current; member only to allow recording
double I_T_; //!< Low-thresh Ca current; member only to allow recording
double I_h_; //!< Pacemaker current; member only to allow recording
State_( const ht_neuron&, const Parameters_& p );
State_( const State_& s );
State_& operator=( const State_& s );
~State_();
void get( DictionaryDatum& ) const;
void set( const DictionaryDatum&, const ht_neuron&, Node* node );
};
private:
// These friend declarations must be precisely here.
friend class RecordablesMap< ht_neuron >;
friend class UniversalDataLogger< ht_neuron >;
// ----------------------------------------------------------------
/**
* Buffers of the model.
*/
struct Buffers_
{
Buffers_( ht_neuron& );
Buffers_( const Buffers_&, ht_neuron& );
UniversalDataLogger< ht_neuron > logger_;
/** buffers and sums up incoming spikes/currents */
std::vector< RingBuffer > spike_inputs_;
RingBuffer currents_;
/** GSL ODE stuff */
gsl_odeiv_step* s_; //!< stepping function
gsl_odeiv_control* c_; //!< adaptive stepsize control function
gsl_odeiv_evolve* e_; //!< evolution function
gsl_odeiv_system sys_; //!< struct describing system
// Since IntergrationStep_ is initialized with step_, and the resolution
// cannot change after nodes have been created, it is safe to place both
// here.
double step_; //!< step size in ms
double integration_step_; //!< current integration time step, updated by GSL
/**
* Input current injected by CurrentEvent.
* This variable is used to transport the current applied into the
* _dynamics function computing the derivative of the state vector.
* It must be a part of Buffers_, since it is initialized once before
* the first simulation, but not modified before later Simulate calls.
*/
double I_stim_;
};
// ----------------------------------------------------------------
/**
* Internal variables of the model.
*/
struct Variables_
{
//! size of conductance steps for arriving spikes
std::vector< double > cond_steps_;
//! Duration of potassium current.
int PotassiumRefractoryCounts_;
//! Voltage at beginning of simulation, for clamping
double V_clamp_;
};
// readout functions, can use template for vector elements
template < State_::StateVecElems_ elem >
double
get_y_elem_() const
{
return S_.y_[ elem ];
}
double
get_I_NaP_() const
{
return S_.I_NaP_;
}
double
get_I_KNa_() const
{
return S_.I_KNa_;
}
double
get_I_T_() const
{
return S_.I_T_;
}
double
get_I_h_() const
{
return S_.I_h_;
}
double get_g_NMDA_() const;
/**
* NMDA activation for given parameters
* Needs to take parameter values explicitly since it is called from
* _dynamics.
*/
double m_NMDA_( double V, double m_eq, double m_fast, double m_slow ) const;
/**
* Return equilibrium value of I_h activation
*
* @param V Membrane potential for which to evaluate
* (may differ from y_[V_M] when clamping)
*/
double m_eq_h_( double V ) const;
/**
* Return equilibrium value of I_T activation
*
* @param V Membrane potential for which to evaluate
* (may differ from y_[V_M] when clamping)
*/
double m_eq_T_( double V ) const;
/**
* Return equilibrium value of I_T inactivation
*
* @param V Membrane potential for which to evaluate
* (may differ from y_[V_M] when clamping)
*/
double h_eq_T_( double V ) const;
/**
* Return steady-state magnesium unblock ratio.
*
* Receives V_m as argument since it is called from ht_neuron_dyamics
* with temporary state values.
*/
double m_eq_NMDA_( double V ) const;
/**
* Steady-state "D" value for given voltage.
*/
double D_eq_KNa_( double V ) const;
static RecordablesMap< ht_neuron > recordablesMap_;
Parameters_ P_;
State_ S_;
Variables_ V_;
Buffers_ B_;
};
inline port
ht_neuron::send_test_event( Node& target, rport receptor_type, synindex, bool )
{
SpikeEvent e;
e.set_sender( *this );
return target.handles_test_event( e, receptor_type );
}
inline port
ht_neuron::handles_test_event( SpikeEvent&, rport receptor_type )
{
assert( B_.spike_inputs_.size() == 4 );
if ( not( INF_SPIKE_RECEPTOR < receptor_type && receptor_type < SUP_SPIKE_RECEPTOR ) )
{
throw UnknownReceptorType( receptor_type, get_name() );
return 0;
}
else
{
return receptor_type - 1;
}
/*
if (receptor_type != 0)
{
throw UnknownReceptorType(receptor_type, get_name());
}
return 0;*/
}
inline port
ht_neuron::handles_test_event( CurrentEvent&, rport receptor_type )
{
if ( receptor_type != 0 )
{
throw UnknownReceptorType( receptor_type, get_name() );
}
return 0;
}
inline port
ht_neuron::handles_test_event( DataLoggingRequest& dlr, rport receptor_type )
{
if ( receptor_type != 0 )
{
throw UnknownReceptorType( receptor_type, get_name() );
}
return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
}
}
#endif // HAVE_GSL
#endif // HT_NEURON_H