00001 #ifndef GENERICPLPOISSONNEURON_H_
00002 #define GENERICPLPOISSONNEURON_H_
00003
00004 #include "EvSimObject.h"
00005 #include "ProjectedEventSender.h"
00006 #include "DirectEventSender.h"
00007 #include "SpikeResponse.h"
00008 #include "Synapse.h"
00009 #include "EvSimObjectTypeUtils.h"
00010 #include "RandomDistribution.h"
00011 #include "GenericPoissonNeuron.h"
00012 #include "Neuron.h"
00013
00014 #include <limits>
00015
00016
00017 template <class Base >
00018 class GenericPLPoissNeuronRecalcVm : public Base {
00019 public:
00020
00021 virtual ~GenericPLPoissNeuronRecalcVm() {};
00022
00023 virtual unsigned registerInputSynapse(EvSimObject *input_synapse)
00024 {
00025 post_syn_potentials.push_back(static_cast<double *>(dynamic_cast<EvSimObject *>(input_synapse)->getVariablePtr("psr")));
00026 double * slope_ptr = static_cast<double *>(dynamic_cast<EvSimObject *>(input_synapse)->getVariablePtr("slope"));
00027 if ( slope_ptr )
00028 post_syn_slopes.push_back(slope_ptr);
00029 return post_syn_potentials.size() - 1;
00030 }
00031
00032 virtual void reset(SimContext &sim_ctxt)
00033 {
00034 Base::reset(sim_ctxt);
00035 Base::Vm = 0;
00036 slope = 0;
00037 cur_time = 0;
00038 };
00039
00040 protected:
00041 struct Accum {
00042 Accum() : s(0) {}
00043
00044 inline void operator()(double *p) {s+=*p;}
00045
00046 double s;
00047 };
00048
00049 inline void updateVm(Time time)
00050 {
00051 if (time > cur_time) {
00052 Accum accumulate_vm;
00053 Accum accumulate_slope;
00054 std::for_each(post_syn_potentials.begin(), post_syn_potentials.end(), accumulate_vm);
00055 std::for_each(post_syn_slopes.begin(), post_syn_slopes.end(), accumulate_slope);
00056 Base::Vm = accumulate_vm.s;
00057 slope = accumulate_slope.s;
00058 cur_time = time;
00059 }
00060 }
00061
00062 vector<double *> post_syn_potentials;
00063 vector<double *> post_syn_slopes;
00064 double slope;
00065 Time cur_time;
00066 };
00067
00068
00069 template <class Base >
00070 class GenericPLPoissNeuronFast : public Base {
00071 public:
00072 virtual ~GenericPLPoissNeuronFast() {};
00073
00074 virtual void updatePSR(double psr, double psr_diff, Time time)
00075 {
00076 updateVm(time);
00077 Base::Vm += psr_diff;
00078 }
00079
00080 virtual void updatePSRSlope(double psr_slope, double psr_slope_diff, Time time)
00081 {
00082 updateVm(time);
00083 slope += psr_slope_diff;
00084 }
00085
00086 virtual bool requiresActiveSynapse() {
00087 return true;
00088 }
00089
00090 inline void updateVm(Time time) {
00091 if (time > cur_time) {
00092 Base::Vm += (time-cur_time)*slope;
00093 cur_time = time;
00094 }
00095 };
00096
00097 virtual void reset(SimContext &sim_ctxt)
00098 {
00099 Base::reset(sim_ctxt);
00100 Base::Vm = 0;
00101 slope = 0;
00102 cur_time = 0;
00103 };
00104
00105 protected:
00106 double slope;
00107 Time cur_time;
00108 };
00109
00110
00111 template <class Base >
00112 class GenericPLExpPoissonNeuron : public Base {
00113 public:
00114
00115 virtual ~GenericPLExpPoissonNeuron() {};
00116
00117 float C;
00118
00119 float A;
00120
00121 float bias;
00122
00123 protected:
00124 inline double firingRate()
00125 {
00126 return A*exp(C*(Base::Vm+bias));
00127 };
00128
00129 void recalcNextSpikeTime(SimContext &sim_info, Time time)
00130 {
00131 Time next_spike_time = MAX_TIME;
00132 Base::updateVm(time);
00133 double rate = firingRate();
00134 if (rate > 0) {
00135 ExponentialDistribution exp_dist(1.0);
00136 double exp_dist_sample = exp_dist( *global_sim_random_eng );
00137 double next_time_projected = Base::slope/rate*exp_dist_sample;
00138 if (next_time_projected > (-1 + std::numeric_limits<double>::epsilon()) ) {
00139 if (fabs(next_time_projected) <= std::numeric_limits<double>::epsilon())
00140 next_spike_time = Base::cur_time + exp_dist_sample/rate;
00141 else
00142 next_spike_time = Base::cur_time + (1/Base::slope)*log( next_time_projected + 1 );
00143 }
00144 }
00145 Base::changeProjectedEventTime(sim_info, (port_id_t)0, next_spike_time);
00146 };
00147 };
00148
00149 #endif
00150