00001 /*!@file ModelNeuron/NeuralDecoder.H Class declaration for neural 00002 decoders, which expect as input a spike train, and outputs a 00003 decoded signal such as a spike density function, inter spike 00004 interval etc...*/ 00005 00006 // //////////////////////////////////////////////////////////////////// // 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00008 // University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 // //////////////////////////////////////////////////////////////////// // 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 // //////////////////////////////////////////////////////////////////// // 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 // //////////////////////////////////////////////////////////////////// // 00035 // 00036 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00037 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/ModelNeuron/NeuralDecoder.H$ 00038 00039 #ifndef MODELNEURON_NEURALDECODER_H_DEFINED 00040 #define MODELNEURON_NEURALDECODER_H_DEFINED 00041 00042 #include "Util/SimTime.H" 00043 #include "GenericUtils/GenericFactory.H" 00044 #include "GenericUtils/CreateFunctor.H" 00045 00046 // ###################################################################### 00047 //! An abstract class for a neural decoder. Neural decoders transform 00048 //! input and output of SimUnit's, possibly with a delay. 00049 // ###################################################################### 00050 class NeuralDecoder 00051 { 00052 public: 00053 //typedef for registering decoders 00054 typedef CreateFunctor<NeuralDecoder, ParamList<SimTime> > Creator; 00055 typedef GenericFactory<NeuralDecoder, std::string, Creator> Factory; 00056 00057 //!constructor 00058 NeuralDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00059 const SimTime& windowSize = SimTime::MSECS(100.0)) : 00060 itsWindowSize(windowSize), 00061 itsSamples( (uint)(itsWindowSize.secs()*timeStep.hertz()) ) { }; 00062 00063 //!desctrctor 00064 virtual ~NeuralDecoder() { }; 00065 00066 //!add some data to the decoder 00067 virtual void push(const double& in) = 0; 00068 00069 //!get the latest (and possibly time delayed) output of the decoder 00070 virtual const double getOutput() const = 0; 00071 00072 //!make a copy of the this object 00073 virtual NeuralDecoder* clone() const = 0; 00074 00075 //! reset the decoder internals to the state after construction 00076 virtual void reset() { }; 00077 00078 protected: 00079 //prohibit copy and assign 00080 NeuralDecoder(const NeuralDecoder& rhs); 00081 NeuralDecoder& operator=(const NeuralDecoder& rhs); 00082 00083 SimTime itsWindowSize; 00084 uint itsSamples; 00085 }; 00086 00087 // ###################################################################### 00088 //! A class to derive from to create new NeuralDecoders. New 00089 //! NeuralDecoder derived types can derive from this class to inherit 00090 //! the clone() function if desired. 00091 /* 00092 Programmer Note: This class uses the 'quriously recursive template 00093 pattern' to simplify creation of new classes for the programmer. As 00094 such, to create a new simulation module, classes should adhear the 00095 following convention: 00096 00097 class mymodule : public NeuralDecoderDerived<mymodule> 00098 { 00099 mymodule(//params//) : NeuralDecoder<mymodule>(//params//) { }; 00100 //...rest of functions 00101 }; 00102 */ 00103 // ###################################################################### 00104 template <class Derived> 00105 class NeuralDecoderDerived : public NeuralDecoder 00106 { 00107 public: 00108 NeuralDecoder* clone() const 00109 { return new Derived(dynamic_cast<const Derived&>(*this)); }; 00110 00111 protected: 00112 NeuralDecoderDerived(const SimTime& timeStep = SimTime::MSECS(1.0), 00113 const SimTime& windowSize = SimTime::MSECS(100.0)) : 00114 NeuralDecoder(timeStep, windowSize) { }; 00115 00116 ~NeuralDecoderDerived() { }; 00117 }; 00118 00119 // ###################################################################### 00120 //! A decoder that just passes through the data, possibly with a delay 00121 // ###################################################################### 00122 class HoldDecoder: public NeuralDecoderDerived<HoldDecoder> 00123 { 00124 public: 00125 //!constructor 00126 HoldDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00127 const SimTime& windowSize = SimTime::ZERO()) : 00128 NeuralDecoderDerived<HoldDecoder>(timeStep, windowSize), itsLastSpike(0.0), 00129 itsSignal(itsSamples, 0.0) { }; 00130 00131 //!desctructor 00132 ~HoldDecoder() { }; 00133 00134 //!add some data to the decoder 00135 void push(const double& in); 00136 00137 //!get the instantaneous Spikes/Second 00138 const double getOutput() const; 00139 00140 //! reset decoder internals 00141 void reset(); 00142 00143 private: 00144 double itsLastSpike; 00145 std::deque<double> itsSignal; 00146 }; 00147 00148 // ###################################################################### 00149 //! A histogram (non overlapping) decoder, spike count 00150 // ###################################################################### 00151 class HistDecoder: public NeuralDecoderDerived<HistDecoder> 00152 { 00153 public: 00154 //!constructor 00155 HistDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00156 const SimTime& windowSize = SimTime::MSECS(100.0)) : 00157 NeuralDecoderDerived<HistDecoder>(timeStep,windowSize), itsSpikeCount(0), 00158 itsLastCount(0.0), itsSampleCount(0) { }; 00159 00160 //!desctructor 00161 ~HistDecoder() { }; 00162 00163 //!add some data to the decoder 00164 void push(const double& in); 00165 00166 //!get the instantaneous Spikes/Second 00167 const double getOutput() const; 00168 00169 //! reset decoder internals 00170 void reset(); 00171 00172 private: 00173 double itsSpikeCount, itsLastCount; 00174 uint itsSampleCount; 00175 }; 00176 00177 // ###################################################################### 00178 //!A decoder using a sliding rectangular window, or moving average 00179 //###################################################################### 00180 class RectDecoder: public NeuralDecoderDerived<RectDecoder> 00181 { 00182 public: 00183 //!constructor 00184 RectDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00185 const SimTime& windowSize = SimTime::MSECS(100.0)) : 00186 NeuralDecoderDerived<RectDecoder>(timeStep, windowSize), 00187 itsSpikeRate(0.0), itsSignal(itsSamples, 0.0) { }; 00188 00189 //!desctructor 00190 ~RectDecoder() { }; 00191 00192 //!add some data to the decoder 00193 void push(const double& in); 00194 00195 //!get the instantaneous Spikes/Second 00196 const double getOutput() const; 00197 00198 //! reset decoder internals 00199 void reset(); 00200 00201 private: 00202 double itsSpikeRate; 00203 std::deque<double> itsSignal; 00204 }; 00205 00206 // ###################################################################### 00207 //! A Exponential rate decoder 00208 // ###################################################################### 00209 class ExpDecoder: public NeuralDecoderDerived<ExpDecoder> 00210 { 00211 public: 00212 //!constructor 00213 ExpDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00214 const SimTime& windowSize = SimTime::MSECS(100.0), 00215 const double& alpha = 0.99) : 00216 NeuralDecoderDerived<ExpDecoder>(timeStep,windowSize), itsSpikeRate(0.0), 00217 itsAlpha(alpha) { }; 00218 00219 //!desctructor 00220 ~ExpDecoder() { }; 00221 00222 //!add some data to the decoder 00223 void push(const double& in); 00224 00225 //!get the instantaneous Spikes/Second 00226 const double getOutput() const; 00227 00228 //! reset decoder internals 00229 void reset(); 00230 00231 private: 00232 double itsSpikeRate; 00233 double itsAlpha; 00234 }; 00235 00236 // ###################################################################### 00237 //! A Rate decoder using an alpha function 00238 // ###################################################################### 00239 class AlphaDecoder: public NeuralDecoderDerived<AlphaDecoder> 00240 { 00241 public: 00242 //!constructor: in this case windowSize is the alpha parameter of 00243 //!the kernel function 1/alpha^2 * t * exp(-1/alpha * t), the actual 00244 //!length of the kernel is determined automatically 00245 AlphaDecoder(const SimTime& timeStep = SimTime::MSECS(1.0), 00246 const SimTime& windowSize = SimTime::MSECS(15.0)); 00247 //!destructor 00248 ~AlphaDecoder() { }; 00249 00250 //!add some data to the decoder 00251 void push(const double& in); 00252 00253 //!get the instantaneous Spikes/Second 00254 const double getOutput() const; 00255 00256 //! reset decoder internals 00257 void reset(); 00258 00259 private: 00260 std::deque<double> itsSignal; 00261 std::vector<double> itsKernel; 00262 }; 00263 00264 // ###################################################################### 00265 // register or types with a factory 00266 // ###################################################################### 00267 namespace 00268 { 00269 typedef NeuralDecoder::Factory NDFactory; 00270 typedef NeuralDecoder::Creator NDCreator; 00271 //define creation functions 00272 struct RegisterNeuralDecoder 00273 { 00274 RegisterNeuralDecoder() 00275 { 00276 const SimTime time = SimTime::MSECS(1.0); 00277 NDFactory::instance().add("HoldDecoder", NDCreator::make<HoldDecoder>(time)); 00278 NDFactory::instance().add("HistDecoder", NDCreator::make<HistDecoder>(time)); 00279 NDFactory::instance().add("RectDecoder", NDCreator::make<RectDecoder>(time)); 00280 NDFactory::instance().add("ExpDecoder", NDCreator::make<ExpDecoder>(time)); 00281 NDFactory::instance().add("AlphaDecoder", NDCreator::make<AlphaDecoder>(time)); 00282 } 00283 }; 00284 static RegisterNeuralDecoder registerneuraldecoder; 00285 } 00286 00287 #endif 00288 00289 // ###################################################################### 00290 /* So things look consistent in everyone's emacs... */ 00291 /* Local Variables: */ 00292 /* indent-tabs-mode: nil */ 00293 /* End: */ 00294 00295 00296