00001 /*!@file ModelNeuron/Structure.H Class declarations for partial 00002 implementations of SimStruture for 2-D simulation units. */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David J Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/Structure.H $ 00036 00037 #ifndef MODELNEURON_STRUCTURE_H_DEFINED 00038 #define MODELNEURON_STRUCTURE_H_DEFINED 00039 00040 #include "Util/SimTime.H" 00041 #include "Image/ImageSet.H" 00042 #include "Image/ImageSetOps.H" 00043 #include "ModelNeuron/SimStructure.H" 00044 #include "ModelNeuron/SimUnit.H" 00045 #include "ModelNeuron/NeuralSimUtils.H" 00046 00047 class StructurePlot; 00048 class Location; 00049 // ###################################################################### 00050 // Structure 00051 // ###################################################################### 00052 // A SimStructure which is a collection of SimStructures. Derive from this 00053 // class and use addmodule to set up the structure and and override interact to 00054 // implement interactions between sub modules. 00055 // 00056 // when using the getSimUnit and editSimUnit functions, the N-D location 00057 // argument is interpreted as the position in a 3-D volume, where the 00058 // third dimensions is the sub module number. This recursivly dives down 00059 // sub modules so the return vector may have many units if the structure's 00060 // sub modules have sub modules. 00061 // 00062 // if not all the layers of the exact same type, then derive from or use 00063 // Structure<SimStructure*> which will inact the virtual mode 00064 // 00065 // The second template paramter is the return type fo the access functions, this 00066 // could be the same type as T, or any base class of T, or SimStruture base. 00067 // ###################################################################### 00068 template <class T> 00069 class Structure : public SimStructure 00070 { 00071 public: 00072 //! constructor 00073 Structure(const SimTime& timeStep, const uint w = 40, const uint h = 30, 00074 const std::string name = "", const std::string units = ""); 00075 00076 //!default assignment and copy constructor OK 00077 00078 virtual ~Structure() { }; 00079 00080 //!set the input 00081 void input(const Image<double>& in, const int pos = -1); 00082 00083 //!set the input 00084 void inputExc(const Image<double>& in, const int pos = -1); 00085 00086 //!set the input 00087 void inputInh(const Image<double>& in, const int pos = -1); 00088 00089 //!get the current output 00090 virtual Image<double> getOutput(const int pos = -1) const; 00091 00092 //!get the current display output 00093 virtual Image<double> getDisplayOutput(const int pos = -1) const; 00094 00095 //!set the default input and output modules 00096 void setDefaultIO(const uint input_pos, const uint output_pos); 00097 00098 //!evolve up to specified time 00099 void evolve(const SimTime& simtime); 00100 00101 //!reset/initialize 00102 void initialize(); 00103 00104 //!get unit(s) at desired location 00105 void getSimUnit(const Location& loc, std::vector<const SimUnit*>& units); 00106 00107 //!edit unit(s) at the desired output position 00108 void editSimUnit(const Location& loc, std::vector<SimUnit*>& units); 00109 00110 //set the current time 00111 void setTime(const SimTime& time, const bool recursive = true); 00112 00113 //get the number of sub modules 00114 const uint numSubs() const; 00115 00116 //get a referene to a sub module const version 00117 const typename nsu::TypeTraits<T>::PointeeType& getSub(const uint sub) const; 00118 00119 //!get the unit at desired position mutable version 00120 typename nsu::TypeTraits<T>::PointeeType& editSub(const uint pos); 00121 00122 //get the simulation time 00123 const SimTime getTime() const; 00124 00125 //get the simulation time step 00126 const SimTime getTimeStep() const; 00127 00128 //!clone the module 00129 virtual Structure* clone() const = 0; 00130 00131 protected: 00132 //protect copy and asignment, use clone 00133 Structure(const Structure<T>& nlc); 00134 Structure<T>& operator=(const Structure<T>& nlc); 00135 00136 //!add a sub module 00137 void addSub(const typename nsu::TypeTraits<T>::PointeeType& structure); 00138 00139 private: 00140 //do our class specific interactions 00141 virtual void interact() = 0; 00142 00143 //do any class specific inititialization; 00144 virtual void doInit() { }; 00145 00146 int itsInpPos, itsOutPos; 00147 nsu::vector<T> itsSubs; 00148 ImageSet<double> itsInpExc, itsInpInh; 00149 SimTime itsTimeStep, itsT; 00150 uint itsSampleScale; 00151 bool isSet; 00152 }; 00153 00154 // ###################################################################### 00155 //!A class to derive from to create new Structures. New 00156 //Structure derived types can derive from this class to 00157 //inherit the doClone() function if desired. 00158 /* 00159 Programmer Note: This class uses the 'quriously recursive template 00160 pattern' to simplify creation of new classes for the programmer. As 00161 such, to create a new simulation module, classes should adhear the 00162 following convention: 00163 00164 class mymodule : public StructureDerived<mymodule> 00165 { 00166 mymodule(//params//) : Structure<mymodule>(//params//) { }; 00167 //...rest of functions 00168 } 00169 */ 00170 // ###################################################################### 00171 template <class T, class Derived> 00172 class StructureDerived : public Structure<T> 00173 { 00174 protected: 00175 StructureDerived(const SimTime& timestep, const uint width, const uint height, 00176 const std::string name = "", const std::string units = "") : 00177 Structure<T>(timestep, width, height, name, units) { }; 00178 00179 virtual ~StructureDerived() { }; 00180 00181 private: 00182 Derived* clone() const { return new Derived(dynamic_cast<const Derived&>(*this)); } 00183 }; 00184 00185 // ###################################################################### 00186 // Structure implementation 00187 // ###################################################################### 00188 template <class T> 00189 Structure<T>::Structure(const SimTime& timestep,const uint w, const uint h, 00190 const std::string name, const std::string units) : 00191 SimStructure(w, h, name, units), itsInpPos(-1), itsOutPos(-1), itsSubs(), 00192 itsInpExc(), itsInpInh(), 00193 itsTimeStep(timestep), itsT(SimTime::ZERO()), itsSampleScale(1), isSet(false) 00194 { } 00195 00196 // ###################################################################### 00197 template <class T> 00198 Structure<T>::Structure(const Structure<T>& rhs) : SimStructure(rhs), itsInpPos(rhs.itsInpPos), 00199 itsOutPos(rhs.itsOutPos), itsSubs(rhs.itsSubs), 00200 itsInpExc(rhs.itsInpExc), itsInpInh(rhs.itsInpInh), 00201 itsTimeStep(rhs.itsTimeStep), itsT(rhs.itsT), 00202 itsSampleScale(rhs.itsSampleScale), isSet(rhs.isSet) 00203 { } 00204 00205 // ###################################################################### 00206 template <class T> 00207 Structure<T>& Structure<T>::operator=(const Structure<T>& rhs) 00208 { 00209 if (this != &rhs) 00210 { 00211 SimStructure::operator=(rhs); 00212 itsInpPos = rhs.itsInpPos; 00213 itsOutPos = rhs.itsOutPos; 00214 itsSubs = rhs.itsSubs; 00215 itsInpExc = rhs.itsInpExc; 00216 itsInpInh = rhs.itsInpInh; 00217 itsTimeStep = rhs.itsTimeStep; 00218 itsT = rhs.itsT; 00219 itsSampleScale = rhs.itsSampleScale; 00220 isSet = rhs.isSet; 00221 } 00222 return *this; 00223 } 00224 00225 // ###################################################################### 00226 template <class T> 00227 void Structure<T>::input(const Image<double>& in, const int pos) 00228 { 00229 int p = (pos >= 0) ? pos : itsInpPos; 00230 00231 if (p < (int)itsInpExc.size()) 00232 SimStructure::splitExcInh(in, itsInpExc[p], itsInpInh[p]); 00233 else 00234 LFATAL("This Structure has no %d'th sub module", p); 00235 } 00236 00237 // ###################################################################### 00238 template <class T> 00239 void Structure<T>::inputExc(const Image<double>& in, const int pos) 00240 { 00241 int p = (pos >= 0) ? pos : itsInpPos; 00242 00243 if (p < (int)itsInpExc.size()) 00244 itsInpExc[p] = in; 00245 else 00246 LFATAL("This Structure has no %d'th sub module", p); 00247 } 00248 00249 // ###################################################################### 00250 template <class T> 00251 void Structure<T>::inputInh(const Image<double>& in, const int pos) 00252 { 00253 int p = (pos >= 0) ? pos : itsInpPos; 00254 00255 if (p < (int)itsInpInh.size()) 00256 itsInpInh[p] = in; 00257 else 00258 LFATAL("This Structure has no %d'th sub module", p); 00259 } 00260 00261 // ###################################################################### 00262 template <class T> 00263 Image<double> Structure<T>::getOutput(const int pos) const 00264 { 00265 int p = (pos >= 0) ? pos : itsInpPos; 00266 00267 if (p >= (int)numSubs()) 00268 LFATAL("This Structure has no %d'th sub module", p); 00269 00270 return itsSubs[p].getOutput(); 00271 } 00272 00273 // ###################################################################### 00274 template <class T> 00275 Image<double> Structure<T>::getDisplayOutput(const int pos) const 00276 { 00277 int p = (pos >= 0) ? pos : itsInpPos; 00278 00279 if (p >= (int)numSubs()) 00280 LFATAL("This Structure has no %d'th sub module", p); 00281 00282 return itsSubs[p].getDisplayOutput(); 00283 } 00284 00285 // ###################################################################### 00286 template <class T> 00287 void Structure<T>::setDefaultIO(const uint input_pos, const uint output_pos) 00288 { 00289 itsInpPos = input_pos; 00290 itsOutPos = output_pos; 00291 if (getUnits().empty()) 00292 setUnits(itsSubs[itsOutPos].getUnits()); 00293 isSet = true; 00294 } 00295 00296 // ###################################################################### 00297 template <class T> 00298 void Structure<T>::evolve(const SimTime& t) 00299 { 00300 const SimTime interval(t - itsT); 00301 const int64 nsteps = interval.nsecs() / itsTimeStep.nsecs(); 00302 const int steps = (int)nsteps; 00303 SimTime currTimeStep; 00304 00305 if (steps <= 0) 00306 ++itsSampleScale;//keep track of how many times we don't integrate 00307 else 00308 { 00309 //set our current time step 00310 currTimeStep = SimTime::NSECS(interval.nsecs() / nsteps); 00311 00312 if (itsSampleScale > 1) 00313 { 00314 //rescale our inputs 00315 itsInpExc /= (double)itsSampleScale; 00316 itsInpInh /= (double)itsSampleScale; 00317 itsSampleScale = 1; 00318 } 00319 00320 for (int ii = 0; ii < steps; ++ii) 00321 { 00322 //update our current time 00323 itsT += currTimeStep; 00324 00325 //do sub interactions 00326 interact(); 00327 00328 //pass the input around and evolve 00329 for (uint ii = 0; ii < numSubs(); ++ii) 00330 { 00331 itsSubs[ii].inputExc(itsInpExc[ii]); 00332 itsSubs[ii].inputInh(itsInpInh[ii]); 00333 itsSubs[ii].evolve(itsT); 00334 } 00335 } 00336 00337 //reset our input after we evolve to the current time step 00338 for (uint ii = 0; ii < numSubs(); ++ii) 00339 { 00340 itsInpExc[ii].clear(); 00341 itsInpInh[ii].clear(); 00342 } 00343 } 00344 } 00345 00346 // ###################################################################### 00347 template <class T> 00348 void Structure<T>::initialize() 00349 { 00350 itsT = SimTime::ZERO(); 00351 00352 typename nsu::vector<T>::iterator iter(itsSubs.begin()); 00353 while (iter != itsSubs.end()) 00354 (iter++)->initialize(); 00355 00356 doInit(); 00357 } 00358 00359 // ###################################################################### 00360 template <class T> 00361 void Structure<T>::setTime(const SimTime& time, const bool recursive) 00362 { 00363 itsT = time; 00364 for (uint ii = 0; ii < numSubs(); ++ii) 00365 editSub(ii).setTime(time); 00366 } 00367 00368 // ###################################################################### 00369 template <class T> 00370 void Structure<T>::getSimUnit(const Location& loc, std::vector<const SimUnit*>& units) 00371 { 00372 //recurse through the subs, eventually someone will deal with it 00373 for (uint ii = 0; ii < numSubs(); ++ii) 00374 editSub(ii).getSimUnit(loc, units); 00375 } 00376 00377 // ###################################################################### 00378 template <class T> 00379 void Structure<T>::editSimUnit(const Location& loc, std::vector<SimUnit*>& units) 00380 { 00381 //recurse through the subs, eventually someone will deal with it 00382 for (uint ii = 0; ii < numSubs(); ++ii) 00383 editSub(ii).editSimUnit(loc, units); 00384 } 00385 00386 // ###################################################################### 00387 template <class T> 00388 const uint Structure<T>::numSubs() const 00389 { 00390 return (uint)itsSubs.size(); 00391 } 00392 00393 // ###################################################################### 00394 template <class T> 00395 const typename nsu::TypeTraits<T>::PointeeType& Structure<T>::getSub(const uint sub) const 00396 { 00397 return itsSubs[sub]; 00398 } 00399 00400 // ###################################################################### 00401 template <class T> 00402 typename nsu::TypeTraits<T>::PointeeType& Structure<T>::editSub(const uint pos) 00403 { 00404 return itsSubs[pos]; 00405 } 00406 00407 // ###################################################################### 00408 template <class T> 00409 const SimTime Structure<T>::getTime() const 00410 { 00411 return itsT; 00412 } 00413 00414 // ###################################################################### 00415 template <class T> 00416 const SimTime Structure<T>::getTimeStep() const 00417 { 00418 return itsTimeStep; 00419 } 00420 00421 // ###################################################################### 00422 template <class T> 00423 void Structure<T>::addSub(const typename nsu::TypeTraits<T>::PointeeType& structure) 00424 { 00425 itsSubs.push_back(structure); 00426 itsInpExc.push_back(Image<double>(structure.getOutDims(), ZEROS)); 00427 itsInpInh.push_back(Image<double>(structure.getOutDims(), ZEROS)); 00428 00429 if (~isSet) 00430 { 00431 itsInpPos = 0; 00432 ++itsOutPos; 00433 if (getUnits().empty()) 00434 setUnits(itsSubs[itsOutPos].getUnits()); 00435 } 00436 } 00437 00438 #endif 00439 // ###################################################################### 00440 /* So things look consistent in everyone's emacs... */ 00441 /* Local Variables: */ 00442 /* indent-tabs-mode: nil */ 00443 /* End: */