LowPass.H

Go to the documentation of this file.
00001 /*!@file ModelNeuron/LowPass.H Class declarations for temporal
00002    low-pass filter implemented as first-order differential with a
00003    possible firing rate function  */
00004 
00005 // //////////////////////////////////////////////////////////////////// //
00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00007 // University of Southern California (USC) and the iLab at USC.         //
00008 // See http://iLab.usc.edu for information about this project.          //
00009 // //////////////////////////////////////////////////////////////////// //
00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00012 // in Visual Environments, and Applications'' by Christof Koch and      //
00013 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00014 // pending; application number 09/912,225 filed July 23, 2001; see      //
00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00016 // //////////////////////////////////////////////////////////////////// //
00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00018 //                                                                      //
00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00020 // redistribute it and/or modify it under the terms of the GNU General  //
00021 // Public License as published by the Free Software Foundation; either  //
00022 // version 2 of the License, or (at your option) any later version.     //
00023 //                                                                      //
00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00027 // PURPOSE.  See the GNU General Public License for more details.       //
00028 //                                                                      //
00029 // You should have received a copy of the GNU General Public License    //
00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00032 // Boston, MA 02111-1307 USA.                                           //
00033 // //////////////////////////////////////////////////////////////////// //
00034 //
00035 // Primary maintainer for this file: David Berg <dberg@usc.edu>
00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/LowPass.H $
00037 
00038 #ifndef MODELNEURON_LOWPASS_H_DEFINED
00039 #define MODELNEURON_LOWPASS_H_DEFINED
00040 
00041 #include "ModelNeuron/SimUnit.H"
00042 
00043 #include<cmath>
00044 // ######################################################################
00045 // ! A set of policies for the integration method to use in our
00046 // lowpass filters. The equation to be solved is:
00047 //
00048 // dg/dt = (-g + H + I) / tau;
00049 // or
00050 // dg/dt = (-g + H) / tau + I;
00051 //
00052 // where g is the state variable, tau is a decay factor, H is the
00053 // steady state and I is the input.
00054 
00055 //All integration policy classes should implement three functions:
00056 //
00057 // MyPolicy(const double& timestep, const double& steadystate, 
00058 //          const double& tau);
00059 // const double update(const double& in, const double& g) const;
00060 // const double update_nodecay_input(const double& in, const double& g) const;
00061 //
00062 // where MyPolicy is a constructor that takes the time step in ms, the
00063 // steady state value and the decay factor (in ms) as arguments. The
00064 // 'update' and 'update_nodecay_input' functions takes the current
00065 // input and value of the state variable to compute and return the
00066 // state at the next time step.
00067 // ######################################################################
00068 // ! policy for the forward Euler method
00069 // ######################################################################
00070 class LowPassFwdEuler
00071 { 
00072 public:
00073   static const SimUnit::RateType RateType = SimUnit::NORMAL;
00074 
00075   LowPassFwdEuler(const double& timestep, const double& h, const double& tau) : 
00076     H(h), Tau(tau), itsTimeStep(timestep) { };
00077   
00078   ~LowPassFwdEuler() { };
00079   
00080   //! update using fwd euler
00081   void update(const double& in, double& g) const
00082   { g = g + itsTimeStep * (-1.0 * g + in + H) / Tau; };
00083 
00084   //! update without applying the decay factor to the input using fwd euler
00085   void update_nodecay_input(const double& in, double& g) const
00086   { g = g + itsTimeStep * (-1.0 * g + H) / Tau + in; };
00087 
00088   //timestep in ms, steady state value, kinetic time constant (msecs) 
00089   double H, Tau;
00090   
00091 private:
00092   double itsTimeStep;
00093 };
00094 
00095 // ######################################################################
00096 // ! policy for the exponential Euler method
00097 // ######################################################################
00098 class LowPassExpEuler 
00099 {
00100 public:
00101   static const SimUnit::RateType RateType = SimUnit::STRICT;
00102   
00103   LowPassExpEuler(const double& timestep, const double& h, const double& tau) : 
00104     H(h), Tau(tau), B(1.0/Tau), E(exp(-1.0 * B * timestep)), E1(1 - E) { };
00105   
00106   ~LowPassExpEuler() { };
00107   
00108   //! update using exp euler
00109   void update(const double& in, double& g) const
00110   { 
00111     double A = (H + in) / Tau;
00112     g = g * E + (A / B) * E1;  
00113   };
00114 
00115   //! update without applying the decay factor to the input using fwd euler
00116   void update_nodecay_input(const double& in, double& g) const
00117   { 
00118     double A = H / Tau + in;
00119     g =  g * E + (A / B) * E1;  
00120   };
00121 
00122   //timestep in ms, steady state value, kinetic time constant (msecs) 
00123   double H, Tau;                       
00124   
00125 private:
00126   double B;   //steady state + input / tau
00127   double E;   //exp (-1 * B * dt)
00128   double E1;  //1 - E
00129 };
00130 
00131 // ######################################################################
00132 // ! Functors that can serve as firing rate functions. Operator() must
00133 // take a double and return a double.
00134 // ######################################################################
00135 namespace RateFunctions
00136 {
00137   // ######################################################################
00138   // an empty rate function
00139   // ######################################################################
00140   struct EmptyFunction
00141   {
00142     //constructor
00143     EmptyFunction() { };
00144     //destructor
00145     ~EmptyFunction() { };
00146     //get the name
00147     static const char* name() { return ""; };
00148     //overload function call operator
00149     const double operator()(const double& in) const { return in; }
00150   };
00151   
00152   // ######################################################################
00153   // full wave rectification firing rate function:
00154   // 
00155   // f(x) = -x : x < 0
00156   // f(x) =  x : x > 0
00157   // ######################################################################
00158   struct FullRectifyFunction
00159   {
00160     //constructor
00161     FullRectifyFunction() { };
00162     //destructor
00163     ~FullRectifyFunction() { };
00164     //get the name
00165     static const char* name() { return "FullRectify"; };
00166     //overload function call operator
00167     const double operator()(const double& in) const
00168     {
00169       return (in >= 0.0) ? in : -1.0 * in;
00170     }
00171   };
00172 
00173   // ######################################################################
00174   // half wave rectification firing rate function:
00175   // 
00176   // f(x) = 0 : x <= thresh
00177   // f(x) = x : x > thresh 
00178   // ######################################################################
00179   struct RectifyFunction
00180   {
00181     //constructor
00182     RectifyFunction(const double& thresh) : 
00183       Thresh(thresh) { };
00184     //destructor
00185     ~RectifyFunction() { };
00186     //get the name
00187     static const char* name() { return "Rectify"; };
00188     //overload function call operator
00189     const double operator()(const double& in) const
00190     {
00191       return (in > Thresh) ? in : 0.0;
00192     }
00193     //paramters
00194     double Thresh; 
00195   };
00196   
00197   // ######################################################################
00198   // half wave rectification with clipping. Make thresh and max the same 
00199   // values to create a step function:
00200   // 0.0 in <= thresh 
00201   // in if thresh < in < max
00202   // max if in >= max
00203   // ######################################################################
00204   struct MaxRectFunction
00205   {
00206     //constructor
00207     MaxRectFunction(const double& thresh, const double& max) : 
00208       Thresh(thresh), Max(max) { };
00209     //destructor
00210     ~MaxRectFunction() { };
00211     //get the name
00212     static const char* name() { return "MaxRect"; };
00213     //overload function call operator
00214     const double operator()(const double& in) const
00215     {
00216       if (in <= Thresh)
00217         return 0.0;
00218       else if (in > Max)
00219         return Max;
00220       else
00221         return in;
00222     }
00223     //paramters
00224     double Thresh, Max;
00225   };
00226 
00227   // ######################################################################
00228   // Step Function.
00229   // 0.0 in <= thresh 
00230   // max if in > thresh
00231   // ######################################################################
00232   struct StepFunction
00233   {
00234     //constructor
00235     StepFunction(const double& thresh, const double& max) : 
00236       Thresh(thresh), Max(max) { };
00237     //destructor
00238     ~StepFunction() { };
00239     //get the name
00240     static const char* name() { return "Step"; };
00241     //overload function call operator
00242     const double operator()(const double& in) const
00243     {
00244       if (in <= Thresh)
00245         return 0.0;
00246       else
00247         return Max;
00248     }
00249     //paramters
00250     double Thresh, Max;
00251   };
00252   
00253   // ######################################################################
00254   // A version of the lowpass filter module with a firing threshold
00255   // and rate function described by: 
00256   //     R = 0; if I < theta 
00257   //     R = ln(I/theta) if I > theta 
00258   //
00259   // Where R is the output rate, I is the
00260   // integrators current value, and theta is a threshold.
00261   //
00262   // From  Durstewitz et al, 2000, Nature Reviews
00263   // ######################################################################
00264   struct LogThreshFunction
00265   {
00266     //constructor
00267     LogThreshFunction(const double& theta) : Thresh(theta) { };
00268     //destructor
00269     ~LogThreshFunction() { };
00270     //get the name
00271     static const char* name() { return "LogThresh"; };
00272     //overload function call operator
00273     const double operator()(const double& in) const 
00274     {
00275       if (in < Thresh)
00276         return 0.0;
00277       else
00278         return log(in / Thresh); 
00279     }
00280     //paramters
00281     double Thresh;
00282   };
00283   
00284   // ######################################################################
00285   // A version of the lowpass filter module with a sigmoidal firing 
00286   // rate function:
00287   //
00288   // f(x) = 1 / (1 + exp(-beta(u - u_not)))
00289   //
00290   // From Erlhagen & Bicho, 2006, J. Neural Engineering
00291   // ######################################################################
00292   struct SigmoidFunction
00293   {
00294     //constructor
00295     SigmoidFunction(const double& thresh, const double& slope) : 
00296       Thresh(thresh), Slope(slope) { };
00297     //destructor
00298     ~SigmoidFunction() { };
00299     //get the name
00300     static const char* name() { return "Sigmoid"; };
00301     //overload function call operator
00302     const double operator()(const double& in) const
00303     {
00304       return 1 / ( 1 + exp(-1.0 * Slope * (in - Thresh)) ); 
00305     }
00306     //paramters
00307     double Thresh, Slope;
00308   };
00309 }
00310 
00311 // ######################################################################
00312 // lowpass filter: Defines a low pass filter with simple first order
00313 // dynamics:
00314 //
00315 // tau * dg/dt = -g + H + I;
00316 //
00317 // Users can choose between one of the solver types and rate functors
00318 // defined above. See solver and functor definitions for interface
00319 // requirements. Some rate functors constructors take parameters and
00320 // so three constructors are provided that take 0, 1 or 2 extra
00321 // parameters, which are passed to the rate functors. The parameters
00322 // will be assigned in the same order as in the functor
00323 // definition. Several typedefs are defined below for convenience.
00324 // ######################################################################
00325 template <class RateFunc = RateFunctions::EmptyFunction, 
00326           class IntType = LowPassExpEuler>
00327 class LowPassFilter: public SimUnit, public IntType
00328 {
00329 public:  
00330   //! Constructor with default params
00331   LowPassFilter(const double& tau, //time constant msecs
00332                 const double& h, //steady state
00333                 const SimTime& timestep,//simulaton timestep
00334                 const std::string& name = "Lowpass", 
00335                 const std::string& units = "pA");
00336   
00337   //! Constructor with default params, overload for RateFuncs with 1 param
00338   LowPassFilter(const double& tau, //time constant msecs
00339                 const double& h, //steady state
00340                 const double& param1,//param 1 for the rate function
00341                 const SimTime& timestep, //simulaton timestep,
00342                 const std::string& name = "Lowpass", 
00343                 const std::string& units = "pA");
00344   
00345   //! Constructor with default params, overload for RateFuncs with 2 param
00346   LowPassFilter(const double& tau, //time constant msecs
00347                 const double& h, //steady state
00348                 const double& param1,//param 1 for the rate function
00349                 const double& param2,//param 2 for the rate function
00350                 const SimTime& timestep, //simulaton timestep
00351                 const std::string& name = "Lowpass", 
00352                 const std::string& units = "pA");
00353   
00354   //! destructor
00355   ~LowPassFilter() { };
00356   
00357   //! get the display output
00358   const double getDisplayOutput() const;
00359   
00360 private:
00361   //! integrate a time step using exponential euler
00362   const double doIntegrate(const SimTime& dt, 
00363                            const double& ine, const double& inh);
00364   
00365   //!initialize or reset internal variables
00366   void doInit();
00367   
00368   //! clone this object
00369   LowPassFilter<RateFunc, IntType>* doClone() const;
00370 
00371   double itsG; // internal state
00372   RateFunc firingRate; // our firing rate functor
00373 };
00374 
00375 // ######################################################################
00376 // typedefs
00377 // ######################################################################
00378 typedef 
00379 LowPassFilter<RateFunctions::EmptyFunction, LowPassExpEuler> LowPass;
00380 typedef 
00381 LowPassFilter<RateFunctions::RectifyFunction, LowPassExpEuler> LowPassRectify;
00382 typedef 
00383 LowPassFilter<RateFunctions::FullRectifyFunction, LowPassExpEuler> LowPassFullRectify;
00384 typedef 
00385 LowPassFilter<RateFunctions::StepFunction, LowPassExpEuler> LowPassStep;
00386 typedef 
00387 LowPassFilter<RateFunctions::MaxRectFunction, LowPassExpEuler> LowPassMaxRect;
00388 typedef 
00389 LowPassFilter<RateFunctions::LogThreshFunction, LowPassExpEuler> LowPassLog;
00390 typedef 
00391 LowPassFilter<RateFunctions::SigmoidFunction, LowPassExpEuler> LowPassSigmoid;
00392 
00393 // ######################################################################
00394 // register our objects
00395 // ######################################################################
00396 namespace 
00397 {
00398   typedef SimUnit::Factory LPFactory;
00399   typedef SimUnit::Creator LPCreator;
00400   //define creation functions
00401   struct RegisterLowPassFilter
00402   {
00403     RegisterLowPassFilter()
00404     {
00405       const double tau = 50.0;
00406       const SimTime time = SimTime::MSECS(1.0);
00407       LPFactory::instance().add("LowPass", 
00408                                 LPCreator::make<LowPass>(tau, -0.5, time));
00409       LPFactory::instance().add("LowPassRectify", 
00410                                 LPCreator::make<LowPassRectify>(tau, -0.5, 0.0, time));
00411       LPFactory::instance().add("LowPassFullRectify", 
00412                                 LPCreator::make<LowPassFullRectify>(tau, 0.0, time));
00413       LPFactory::instance().add("LowPassStep", 
00414                                 LPCreator::make<LowPassStep>(tau, -0.5, 0.0, 1.0, time));
00415       LPFactory::instance().add("LowPassMaxRect", 
00416                                 LPCreator::make<LowPassMaxRect>(tau, -0.5, 0.0, 1.0, time));
00417       LPFactory::instance().add("LowPassLog", 
00418                                 LPCreator::make<LowPassLog>(tau, 0.0, 0.1, time));
00419       LPFactory::instance().add("LowPassSigmoid",
00420                                 LPCreator::make<LowPassSigmoid>(tau, -0.5, 0.55, 12.0, time));
00421     }
00422   };
00423   static RegisterLowPassFilter registerlpf;  
00424 }
00425 
00426 
00427 // ######################################################################
00428 // ##### implementation for LowPassFilter
00429 // ######################################################################
00430 // default case rate function takes 0 params
00431 // ######################################################################
00432 template <class RateFunc, class IntType> inline
00433 LowPassFilter<RateFunc, IntType>::LowPassFilter(const double& tau, 
00434                                                 const double& h,
00435                                                 const SimTime& timestep,
00436                                                 const std::string& name, 
00437                                                 const std::string& units) : 
00438   SimUnit(timestep, IntType::RateType, name+RateFunc::name(), units), 
00439   IntType(timestep.msecs(), h, tau), itsG(h), firingRate() { };
00440 
00441 // ######################################################################
00442 // default case rate function takes 1 params
00443 // ######################################################################
00444 template <class RateFunc, class IntType> inline
00445 LowPassFilter<RateFunc, IntType>::LowPassFilter(const double& tau, 
00446                                                 const double& h,
00447                                                 const double& param1, 
00448                                                 const SimTime& timestep,
00449                                                 const std::string& name, 
00450                                                 const std::string& units) : 
00451   SimUnit(timestep, IntType::RateType, name+RateFunc::name(), units), 
00452   IntType(timestep.msecs(), h, tau), itsG(h), firingRate(param1) { };
00453 
00454 // ######################################################################
00455 // default case rate function takes 2 params
00456 // ######################################################################
00457 template <class RateFunc, class IntType> inline
00458 LowPassFilter<RateFunc, IntType>::LowPassFilter(const double& tau, 
00459                                                 const double& h,
00460                                                 const double& param1, 
00461                                                 const double& param2, 
00462                                                 const SimTime& timestep,
00463                                                 const std::string& name, 
00464                                                 const std::string& units) : 
00465   SimUnit(timestep, IntType::RateType, name+RateFunc::name(), units), 
00466   IntType(timestep.msecs(), h, tau), itsG(h), firingRate(param1, param2) { };
00467 
00468 // ######################################################################
00469 template <class RateFunc, class IntType> inline 
00470 const double LowPassFilter<RateFunc, IntType>::getDisplayOutput() const
00471 {
00472   return itsG;
00473 }
00474 
00475 // ######################################################################
00476 template <class RateFunc, class IntType> inline
00477 const double LowPassFilter<RateFunc, IntType>::doIntegrate(const SimTime& dt, 
00478                                                            const double& ine,
00479                                                            const double& inh)
00480 {
00481   IntType::update(ine + inh, itsG);//update inherited from template parameter
00482   return firingRate(itsG);
00483 }
00484 
00485 // ######################################################################
00486 template <class RateFunc, class IntType> inline
00487 void LowPassFilter<RateFunc, IntType>::doInit()
00488 {
00489   itsG = IntType::H;
00490 }
00491 
00492 // ######################################################################
00493 template <class RateFunc, class IntType> inline 
00494 LowPassFilter<RateFunc, IntType>* 
00495 LowPassFilter<RateFunc, IntType>::doClone() const
00496 {
00497   return new LowPassFilter<RateFunc, IntType>(*this);
00498 }
00499 
00500 #endif
00501 // ######################################################################
00502 /* So things look consistent in everyone's emacs... */
00503 /* Local Variables: */
00504 /* indent-tabs-mode: nil */
00505 /* End: */
Generated on Sun May 8 08:05:14 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3