00001 /*!@file ModelNeuron/PlotBuffer.C implementation for PlotBuffer*/ 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 J. Berg <dberg@usc.edu> 00034 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/ModelNeuron/PlotBuffer.C$ 00035 00036 #include "ModelNeuron/PlotBuffer.H" 00037 #include "ModelNeuron/SimUnit.H" 00038 #include "Image/DrawOps.H" 00039 #include "Util/StringConversions.H" 00040 00041 // ###################################################################### 00042 // ! implementation of PlotBuffer 00043 // ###################################################################### 00044 PlotBuffer::PlotBuffer() 00045 : itsData(), names(), units(), itsXlabel("Samples"), 00046 itsCount(0), itsChildCount(0), itsTotal(0), itsDepth(0) 00047 { 00048 } 00049 00050 // ###################################################################### 00051 void PlotBuffer::push(const SimUnit& nsm, const uint length, 00052 const uint depth, const bool usedisplayout) 00053 { 00054 //if the depth has changed or we haven't initialized, do it now 00055 if ((itsTotal == 0) || (depth != itsDepth)) 00056 { 00057 reset(); 00058 getSubInfo(nsm, depth); 00059 ++itsTotal; 00060 itsData.resize(itsTotal); 00061 itsDepth = depth; 00062 } 00063 00064 //recursively inspect the objects submodules and store the data 00065 addData(nsm, length, depth, usedisplayout); 00066 } 00067 00068 // ###################################################################### 00069 void PlotBuffer::addData(const SimUnit& nsm, const uint length, 00070 const uint depth, const bool usedisplayout) 00071 { 00072 if (depth > 0) 00073 for (int i = nsm.numSubs()-1; i >=0; --i) 00074 { 00075 const SimUnit& temp = nsm.getSub(i); 00076 ++itsCount; 00077 //recursion hurts your head, but is so nice. 00078 addData(temp, length, depth - 1, usedisplayout); 00079 } 00080 00081 //base case 00082 if ((uint)itsData[itsChildCount].size() < length) 00083 itsData[itsChildCount].resize(length,0); 00084 00085 //save our current value 00086 const double outval = usedisplayout ? nsm.getDisplayOutput() : nsm.getOutput(); 00087 itsData[itsChildCount].push_back(outval); 00088 00089 //chop any extra data off the buffer 00090 while ( ((uint)itsData[itsChildCount].size() > length) && (length != 0) ) 00091 itsData[itsChildCount].pop_front(); 00092 00093 if (itsCount > 0) 00094 { 00095 ++itsChildCount; 00096 --itsCount; 00097 } 00098 else 00099 itsChildCount = 0; 00100 } 00101 00102 // ###################################################################### 00103 void PlotBuffer::reset() 00104 { 00105 itsData.clear(); 00106 itsCount = 0; 00107 itsChildCount = 0; 00108 itsTotal = 0; 00109 itsDepth = 0; 00110 } 00111 00112 // ###################################################################### 00113 void PlotBuffer::draw(Image<PixRGB<byte> >& img, const bool clear, const uint w, const uint h, const Range<double>& range) 00114 { 00115 img = draw(clear, w, h, range).render(); 00116 } 00117 00118 // ###################################################################### 00119 Layout<PixRGB<byte> > PlotBuffer::draw(const bool clear, const uint w, const uint h, const Range<double>& range) 00120 { 00121 Layout<PixRGB<byte> > layout; 00122 if (itsTotal != 0) 00123 { 00124 if (itsData[0].size() > 1) 00125 { 00126 uint height = h / (uint)itsData.size(); 00127 std::vector<std::deque<double> >::reverse_iterator 00128 iter(itsData.rbegin()), end(itsData.rend()); 00129 00130 std::vector<std::string>::const_reverse_iterator 00131 nameiter(names.rbegin()), unititer(units.rbegin()); 00132 00133 while (iter != end) 00134 { 00135 layout = vcat(layout, linePlot(*iter, w, height, range.min(), range.max(), 00136 nameiter->c_str(), unititer->c_str(), itsXlabel.c_str())); 00137 if (clear) 00138 iter->clear(); 00139 00140 ++iter;++nameiter;++unititer; 00141 } 00142 return layout; 00143 } 00144 else 00145 return 00146 Layout<PixRGB<byte> > (Image<PixRGB<byte> >(w,h,ZEROS)); 00147 } 00148 return 00149 Layout<PixRGB<byte> > (Image<PixRGB<byte> >(w,h,ZEROS)); 00150 } 00151 00152 // ###################################################################### 00153 void PlotBuffer::getSubInfo(const SimUnit& nsm, const uint depth) 00154 { 00155 if (depth > 0) 00156 for (int i = nsm.numSubs() - 1; i >= 0; --i) 00157 { 00158 const SimUnit& temp = nsm.getSub(i); 00159 ++itsTotal; 00160 this->getSubInfo(temp, depth - 1); //recursion 00161 } 00162 names.push_back(nsm.getName()); 00163 units.push_back(nsm.getUnits()); 00164 } 00165 00166 // ###################################################################### 00167 void PlotBuffer::setSamplingRate(const SimTime& time) 00168 { 00169 itsXlabel = PlotBuffer::SimTimeToSI(time); 00170 } 00171 00172 // ###################################################################### 00173 const uint PlotBuffer::getTotal() 00174 { 00175 return itsTotal; 00176 } 00177 00178 // ###################################################################### 00179 std::string PlotBuffer::SimTimeToSI(const SimTime& time) 00180 { 00181 std::string t(time.toString()); 00182 int pos,epos; 00183 //for no decimal or exponent 00184 pos = t.find('.'); 00185 epos = t.find('e'); 00186 00187 //for a decimal 00188 int magnitude = 0; 00189 std::string output; 00190 if (pos != (int)std::string::npos) 00191 { 00192 int cnt = pos + 1; 00193 while (t[cnt] == '0') 00194 ++cnt; 00195 output = t.substr(cnt, t.size() - cnt - 1) + " "; 00196 magnitude = cnt - pos; 00197 } 00198 //for exponent 00199 else if (epos != (int)std::string::npos) 00200 { 00201 //get text before exponent 00202 output = t.substr(0,epos) + " "; 00203 std::string str = t.substr(epos+2,t.size() - 3 - epos); 00204 magnitude = fromStr<int>(str); 00205 } 00206 00207 switch (magnitude) 00208 { 00209 case 1 : 00210 if (output.compare("1 ") == 0)//if the multuple is only 1, ignore the text 00211 output = ""; 00212 output += "decisec"; 00213 break; 00214 case 2 : 00215 if (output.compare("1 ") == 0)//if the multuple is only 1, ignore the text 00216 output = ""; 00217 output += "centisec"; 00218 break; 00219 case 3 : 00220 if (output.compare("1 ") == 0)//if the multuple is only 1, ignore the text 00221 output = ""; 00222 output += "ms"; 00223 break; 00224 case 4 : 00225 output = "." + output + "ms"; 00226 break; 00227 case 5 : 00228 output = ".0" + output + "ms"; 00229 break; 00230 case 6 : 00231 if (output.compare("1 ") == 0)//if the multuple is only 1, ignore the text 00232 output = ""; 00233 output += "microsec"; 00234 break; 00235 case 7 : 00236 output = "." + output + "microsec"; 00237 break; 00238 case 8 : 00239 output = ".0" + output + "microsec"; 00240 break; 00241 case 9 : 00242 if (output.compare("1 ") == 0)//if the multuple is only 1, ignore the text 00243 output = ""; 00244 output += "nanosec"; 00245 break; 00246 default: 00247 output = t.substr(0,t.size() - 1) + " sec"; 00248 break; 00249 } 00250 return output; 00251 } 00252 00253 00254 // ###################################################################### 00255 // implementation of PlotBufferList 00256 // ###################################################################### 00257 void PlotBufferList::push(const std::vector<const SimUnit*>& nsm, 00258 const uint length, const uint depth, 00259 const bool usedisplayout) 00260 { 00261 if (nsm.size() != itsPb.size()) 00262 { 00263 itsPb.clear(); 00264 itsPb.resize(nsm.size()); 00265 } 00266 std::vector<const SimUnit*>::const_iterator begin(nsm.begin()); 00267 std::vector<PlotBuffer>::iterator beginPb(itsPb.begin()); 00268 while (begin != nsm.end()) 00269 { 00270 beginPb->push(**begin, length, depth, usedisplayout); 00271 ++beginPb; ++begin; 00272 } 00273 } 00274 00275 // ###################################################################### 00276 void PlotBufferList::clear() 00277 { 00278 itsPb.clear(); 00279 } 00280 00281 // ###################################################################### 00282 Layout<PixRGB<byte> > PlotBufferList::draw(bool clear, const uint w, 00283 const uint h, const Dims& d, const Range<double>& range) 00284 { 00285 if (itsPb.size() < 1) 00286 { 00287 return Layout<PixRGB<byte> >(); 00288 } 00289 00290 Layout<PixRGB<byte> > lay; 00291 if (d == Dims(0,1)) 00292 { 00293 const uint height = h / itsPb.size(); 00294 std::vector<PlotBuffer>::iterator begin(itsPb.begin()); 00295 while (begin != itsPb.end()) 00296 lay = vcat(lay, (begin++)->draw(clear, w, height, range)); 00297 } 00298 else if (d == Dims(1,0)) 00299 { 00300 const uint width = w / itsPb.size(); 00301 std::vector<PlotBuffer>::iterator begin(itsPb.begin()); 00302 while (begin != itsPb.end()) 00303 lay = hcat(lay, (begin++)->draw(clear, width, h, range)); 00304 } 00305 else 00306 { 00307 Layout<PixRGB<byte> > layr; 00308 const uint height = h / d.h(); 00309 const uint width = w / d.w(); 00310 std::vector<PlotBuffer>::iterator begin(itsPb.begin()); 00311 for (int r = 0; (r < d.h()) || (begin == itsPb.end()); ++r) 00312 { 00313 for (int c = 0; (c < d.w()) || (begin == itsPb.end()); ++c) 00314 layr = hcat(layr, (begin++)->draw(clear, width, height, range)); 00315 lay = vcat(lay,layr); 00316 } 00317 } 00318 return lay; 00319 } 00320 00321 // ###################################################################### 00322 void PlotBufferList::draw(Image<PixRGB<byte> >& img, bool clear, 00323 const uint w, const uint h, const Dims& d, const Range<double>& range) 00324 { 00325 img = draw(clear, w, h, d, range).render(); 00326 } 00327 00328 // ###################################################################### 00329 void PlotBufferList::setSamplingRate(const SimTime& time) 00330 { 00331 std::vector<PlotBuffer>::iterator iter(itsPb.begin()); 00332 while (iter != itsPb.end()) 00333 (iter++)->setSamplingRate(time); 00334 } 00335 00336 // ###################################################################### 00337 /* So things look consistent in everyone's emacs... */ 00338 /* Local Variables: */ 00339 /* indent-tabs-mode: nil */ 00340 /* End: */