00001 /*!@file ModelNeuron/IZNeuron.C Class declarations for an izhikevich neuron */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/IZNeuron.C $ 00035 00036 #include "ModelNeuron/IZNeuron.H" 00037 00038 // ###################################################################### 00039 // ##### functions for IZNeuronFunc: 00040 // ###################################################################### 00041 void IZNeuronFunc::integrate() 00042 { 00043 //lets just run our difference equation one time step, dt. 00044 //Integrate V 00045 double temp = itsk * (itsV - itsVr) * (itsV - itsVth) - itsU + itsI; 00046 00047 //multiply timestep converted to ms, and devide capacitance 00048 itsV += (temp / itsCm); 00049 00050 //Integrate U 00051 itsU += itsa * (itsb * (itsV-itsVr) - itsU); 00052 00053 // Check if voltage has exceeded threshold -> if so, then fire: 00054 if (itsV > itsVp) 00055 { 00056 itsSpike = true; 00057 reset(); 00058 } 00059 else 00060 itsSpike = false; 00061 } 00062 00063 // ###################################################################### 00064 void IZNeuronFunc::initialize() { 00065 itsSpike = false; 00066 itsV = itsVr; 00067 itsI = 0.0; 00068 itsU = 0.0; 00069 } 00070 00071 // ###################################################################### 00072 void IZNeuronFunc::reset() 00073 { 00074 itsV = itsc; 00075 itsU += itsd; 00076 } 00077 00078 // ###################################################################### 00079 void IZNeuronFunc::setup(const std::string& name, const bool use_random) 00080 { 00081 if (name.compare("RS") == 0) 00082 { 00083 itsa = 0.01; // timescale of recovery variable 00084 itsb = 5.0; // sensitivity of u to voltage 00085 itsc = -60.0; // after-spike reset value of v 00086 itsd = 400.0; // after-spike reset value of u 00087 itsk = 3.0; // current voltage relationship 00088 itsCm = 100.0; // in microfarads 00089 itsVr = -60.0; // in millivolts 00090 itsVth = -50.0; // in millivolts 00091 itsVp = 50.0; // in millivolts 00092 } 00093 else if (name.compare("FS") == 0) 00094 { 00095 itsa = 0.15; // timescale of recovery variable 00096 itsb = 8.0; // sensitivity of u to voltage 00097 itsc = -55.0; // after-spike reset value of v 00098 itsd = 200.0; // after-spike reset value of u 00099 itsk = 1.0; // current voltage relationship 00100 itsCm = 20.0; // in microfarads 00101 itsVr = -55.0; // in millivolts 00102 itsVth = -40.0; // in millivolts 00103 itsVp = 25.0; // in millivolts 00104 } 00105 else if (name.compare("EB") == 0) 00106 { 00107 itsa = 0.01; // timescale of recovery variable 00108 itsb = 17.0; // sensitivity of u to voltage 00109 itsc = -42.0; // after-spike reset value of v 00110 itsd = 1.5; // after-spike reset value of u 00111 itsk = 1.4; // current voltage relationship 00112 itsCm = 20.0; // in microfarads 00113 itsVr = -55.0; // in millivolts 00114 itsVth = -50.0; // in millivolts 00115 itsVp = 25.0; // in millivolts 00116 } 00117 00118 if (use_random) 00119 { 00120 //perterbate the parameters a little bit 00121 } 00122 } 00123 00124 // ###################################################################### 00125 // ##### Functions for IZNeuron: 00126 // ###################################################################### 00127 IZNeuron::IZNeuron(const double& a, const double& b, 00128 const double& c, const double& d, const double& k, 00129 const double& Cm, const double& V_rest, 00130 const double& V_thresh, const double& V_peak, 00131 const std::string& name, const std::string& units) : 00132 SimUnit(SimTime::MSECS(1.0), SimUnit::STRICT, name, units), 00133 itsI(0.0), itsN(a,b,c,d,k,Cm,V_rest,V_thresh,V_peak), 00134 ampa(SimTime::MSECS(1.0)), nmda(SimTime::MSECS(1.0)), 00135 gabaa(SimTime::MSECS(1.0)), gabab(SimTime::MSECS(1.0)) 00136 { 00137 } 00138 00139 // ###################################################################### 00140 void IZNeuron::setV(const double& v) 00141 { 00142 itsN.setV(v); 00143 } 00144 00145 // ###################################################################### 00146 const double IZNeuron::getDisplayOutput() const 00147 { 00148 return getV(); 00149 } 00150 00151 // ###################################################################### 00152 const uint IZNeuron::numSubs() const 00153 { 00154 return 4; 00155 } 00156 00157 // ###################################################################### 00158 const SimUnit& IZNeuron::getSub(const uint i) const 00159 { 00160 switch (i) 00161 { 00162 case 0: 00163 return ampa; 00164 case 1: 00165 return nmda; 00166 case 2: 00167 return gabaa; 00168 case 3: 00169 return gabab; 00170 default: 00171 LFATAL("Sub module position out of range."); 00172 return ampa;//will never execute; 00173 } 00174 } 00175 00176 // ###################################################################### 00177 SimUnit& IZNeuron::editSub(const uint i) 00178 { 00179 switch (i) 00180 { 00181 case 0: 00182 return ampa; 00183 case 1: 00184 return nmda; 00185 case 2: 00186 return gabaa; 00187 case 3: 00188 return gabab; 00189 default: 00190 LFATAL("Sub module position out of range."); 00191 return ampa;//will never execute; 00192 } 00193 } 00194 00195 // ###################################################################### 00196 const double IZNeuron::getV() const 00197 { 00198 return itsN.getV(); 00199 } 00200 00201 // ###################################################################### 00202 const double IZNeuron::getI() const 00203 { 00204 return itsN.getCurrent(); 00205 } 00206 00207 // ###################################################################### 00208 void IZNeuron::setI(const double& current) 00209 { 00210 itsI = current; 00211 } 00212 00213 // ###################################################################### 00214 const IZNeuron& IZNeuron::setup(const std::string& name, const bool use_random) 00215 { 00216 itsN.setup(name, false); 00217 setName(name + getName()); 00218 return *this; 00219 } 00220 00221 // ###################################################################### 00222 const double IZNeuron::doIntegrate(const SimTime& dt, 00223 const double& exc, const double& inh) 00224 { 00225 //input to synapses 00226 const double inh1 = inh * -1.0; 00227 ampa.input(exc); 00228 nmda.input(exc); 00229 gabaa.input(inh1); 00230 gabab.input(inh1); 00231 00232 //set the synapse voltage to cells membrane voltage 00233 ampa.setV(getV()); 00234 nmda.setV(getV()); 00235 gabaa.setV(getV()); 00236 gabab.setV(getV()); 00237 00238 //evolve our synapse to current time 00239 ampa.evolve(getTime()); 00240 nmda.evolve(getTime()); 00241 gabaa.evolve(getTime()); 00242 gabab.evolve(getTime()); 00243 00244 const double synCurr = ampa.getOutput() + nmda.getOutput() + 00245 gabaa.getOutput() + gabab.getOutput(); 00246 00247 const double inp = itsI - synCurr; 00248 itsN.setCurrent(inp); //set the current level 00249 itsN.integrate(); //integrate 1ms in the future 00250 00251 return (double)itsN.getSpike(); //return any spikes 00252 } 00253 00254 // ###################################################################### 00255 void IZNeuron::doInit() 00256 { 00257 itsI = 0.0; 00258 itsN.initialize(); 00259 ampa.initialize(); 00260 nmda.initialize(); 00261 gabaa.initialize(); 00262 gabab.initialize(); 00263 } 00264 00265 // ###################################################################### 00266 IZNeuron* IZNeuron::doClone() const 00267 { return new IZNeuron(*this); }; 00268 00269 /* 00270 // ###################################################################### 00271 // ##### Functions for IZNeuronSyn: 00272 // ###################################################################### 00273 //! Constructor with default params 00274 IZNeuronSyn::IZNeuronSyn(const double& a, const double& b, 00275 const double& c, const double& d, const double& k, 00276 const double& Cm, const double& V_rest, 00277 const double& V_thresh, const double& V_peak, 00278 const std::string& name, const std::string& units) : 00279 SimUnit(SimTime::MSECS(1.0), SimUnit::STRICT, name, units), 00280 itsI(0.0), itsN(a, b, c, d, k, Cm, V_rest, V_thresh, V_peak), itsS() 00281 { 00282 } 00283 00284 // ###################################################################### 00285 IZNeuronSyn::IZNeuronSyn(const IZNeuronSyn& rhs) : 00286 SimUnit(rhs), itsI(rhs.itsI), itsN(rhs.itsN), itsS() 00287 { 00288 map::const_iterator i(rhs.itsS.begin()), end(rhs.itsS.begin()); 00289 while (i != end) 00290 { 00291 itsS[i->first] = pair(i->second.first, 00292 i->second.second->clone()); 00293 ++i; 00294 } 00295 } 00296 00297 // ###################################################################### 00298 IZNeuronSyn& IZNeuronSyn::operator=(const IZNeuronSyn& rhs) 00299 { 00300 if (this != &rhs) 00301 { 00302 SimUnit::operator=(rhs); 00303 00304 itsI = rhs.itsI; 00305 itsN = rhs.itsN; 00306 map::const_iterator i(rhs.itsS.begin()), end(rhs.itsS.begin()); 00307 while (i != end) 00308 { 00309 itsS[i->first] = pair(i->second.first, 00310 i->second.second->clone()); 00311 ++i; 00312 } 00313 } 00314 return *this; 00315 } 00316 00317 // ###################################################################### 00318 IZNeuronSyn::~IZNeuronSyn() 00319 { 00320 cleanup(); 00321 } 00322 00323 // ###################################################################### 00324 void IZNeuronSyn::setV(const double& v) 00325 { 00326 itsN.setV(v); 00327 } 00328 00329 // ###################################################################### 00330 const double IZNeuronSyn::getDisplayOutput() const 00331 { 00332 return getV(); 00333 } 00334 00335 // ###################################################################### 00336 const uint IZNeuronSyn::numSubs() const 00337 { 00338 return (uint)itsS.size(); 00339 } 00340 00341 // ###################################################################### 00342 const SimUnit& IZNeuronSyn::getSub(const uint pos) const 00343 { 00344 if (pos >= (uint)itsS.size() ) 00345 LFATAL("You have not added %d synapses", pos); 00346 map::const_iterator i(itsS.begin()); 00347 for (uint j = 0; j < pos; ++j) 00348 ++i; 00349 SimUnit* tmp = i->second.second; 00350 return *tmp; 00351 } 00352 00353 // ###################################################################### 00354 SimUnit& IZNeuronSyn::editSub(const uint pos) 00355 { 00356 if (pos >= (uint)itsS.size() ) 00357 LFATAL("You have not added %d synapses", pos); 00358 map::iterator i(itsS.begin()); 00359 for (uint j = 0; j < pos; ++j) 00360 ++i; 00361 SimUnit* tmp = i->second.second; 00362 return *tmp; 00363 } 00364 00365 // ###################################################################### 00366 const double IZNeuronSyn::getV() const 00367 { 00368 return itsN.getV(); 00369 } 00370 00371 // ###################################################################### 00372 const double IZNeuronSyn::getI() const 00373 { 00374 return itsN.getCurrent(); 00375 } 00376 00377 // ###################################################################### 00378 void IZNeuronSyn::setI(const double& current) 00379 { 00380 itsI = current; 00381 } 00382 00383 // ###################################################################### 00384 const IZNeuronSyn& IZNeuronSyn::setup(const std::string& name, 00385 const bool use_random) 00386 { 00387 itsN.setup(name, false); 00388 setName(name + getName()); 00389 return *this; 00390 } 00391 00392 // ###################################################################### 00393 template <class S, class I> 00394 void IZNeuronSyn::addSynapse(const Synapse<S, I>& synapse, const double& ratio) 00395 { 00396 //make sure we dont already have it 00397 map::const_iterator i(itsS.find(S::id)); 00398 if (i != itsS.end()) 00399 LFATAL("Synapse %s of type already added", synapse.getName().c_str()); 00400 else 00401 itsS[S::id] = pair(ratio, synapse.clone()); 00402 } 00403 00404 // ###################################################################### 00405 void IZNeuronSyn::inputSynapse(const double& input, 00406 const Receptor::Type receptor) 00407 { 00408 map::const_iterator i(itsS.find(receptor)); 00409 if (i != itsS.end()) 00410 { 00411 i->second.second->input(i->second.first * input); 00412 ++i; 00413 } 00414 } 00415 00416 // ###################################################################### 00417 void IZNeuronSyn::cleanup() 00418 { 00419 map::iterator i(itsS.begin()), end(itsS.begin()); 00420 while (i != end) 00421 { 00422 delete i->second.second; 00423 i->second.second = NULL; 00424 ++i; 00425 } 00426 } 00427 00428 // ###################################################################### 00429 const double IZNeuronSyn::doIntegrate(const SimTime& dt, 00430 const double& exc, const double& inh) 00431 { 00432 double synCurr = 0.0; 00433 map::const_iterator i(itsS.begin()), end(itsS.end()); 00434 while (i != end) 00435 { 00436 i->second.second->setV(getV());//set starting voltage 00437 i->second.second->evolve(getTime());//evolve our synapse to current time 00438 synCurr += i->second.second->getOutput(); //add synaptic currents 00439 ++i; 00440 } 00441 00442 const double inp = itsI - synCurr; 00443 itsN.setCurrent(inp); //set the current level 00444 itsN.integrate(); //integrate 00445 00446 return (double)itsN.getSpike(); //return any spikes 00447 } 00448 00449 // ###################################################################### 00450 void IZNeuronSyn::doInit() 00451 { 00452 map::const_iterator i(itsS.begin()), end(itsS.end()); 00453 while (i != end) 00454 (i++)->second.second->initialize(); 00455 00456 itsN.initialize(); 00457 } 00458 00459 // ###################################################################### 00460 IZNeuronSyn* IZNeuronSyn::doClone() const 00461 { return new IZNeuronSyn(*this); }; 00462 00463 // ###################################################################### 00464 // specific instantiation for addSynapse 00465 // ###################################################################### 00466 template 00467 void IZNeuronSyn::addSynapse(Synapse<Receptor::AMPA, LowPassExpEuler> const&, 00468 double const&); 00469 template 00470 void IZNeuronSyn::addSynapse(Synapse<Receptor::NMDA, LowPassExpEuler> const&, 00471 double const&); 00472 template 00473 void IZNeuronSyn::addSynapse(Synapse<Receptor::GABAA, LowPassExpEuler> const&, 00474 double const&); 00475 template 00476 void IZNeuronSyn::addSynapse(Synapse<Receptor::GABAB, LowPassExpEuler> const&, 00477 double const&); 00478 00479 */ 00480 // ###################################################################### 00481 /* So things look consistent in everyone's emacs... */ 00482 /* Local Variables: */ 00483 /* indent-tabs-mode: nil */ 00484 /* End: */