00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include "Neuro/SimulationViewerStats.H"
00039 #include "Channels/ChannelMaps.H"
00040 #include "Channels/ChannelOpts.H"
00041 #include "Image/colorDefs.H"
00042 #include "Image/CutPaste.H"
00043 #include "Image/ColorOps.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/fancynorm.H"
00046 #include "Image/FFTWWrapper.H"
00047 #include "Image/ImageSet.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/ShapeOps.H"
00050 #include "Image/NamedImage.H"
00051 #include "Media/MediaSimEvents.H"
00052 #include "Neuro/Brain.H"
00053 #include "Neuro/NeuroOpts.H"
00054 #include "Neuro/NeuroSimEvents.H"
00055 #include "Neuro/VisualCortex.H"
00056 #include "Transport/FrameInfo.H"
00057 #include "Transport/FrameOstream.H"
00058 #include <fcntl.h> 
00059 #include <cerrno> 
00060 
00061 
00062 
00063 SimulationViewerStats::SimulationViewerStats(OptionManager& mgr,
00064                                          const std::string& descrName,
00065                                          const std::string& tagName) :
00066   SimulationViewer(mgr, descrName, tagName),
00067   SIMCALLBACK_INIT(SimEventSaveOutput),
00068   itsStatsFname(&OPT_SVstatsFname, this),
00069   itsSaveXcombo(&OPT_SVsaveXcombo, this),
00070   itsSaveYcombo(&OPT_SVsaveYcombo, this),
00071   itsComputeAGStats(&OPT_ComputeAGStats, this),
00072   itsAGTargetFrame(&OPT_AGTargetFrame, this),
00073   itsAGMaskFile(&OPT_AGMaskFile, this),
00074   itsAGStatsSaveFile(&OPT_AGStatsSaveFile, this),
00075   itsGetSingleChannelStats(&OPT_GetSingleChannelStats, this),
00076   itsGetSingleChannelStatsFile(&OPT_GetSingleChannelStatsFile, this),
00077   itsSaveStatsPerChannelFreq(&OPT_SaveStatsPerChannelFreq, this),
00078   itsStatsFile(NULL)
00079 { }
00080 
00081 
00082 SimulationViewerStats::~SimulationViewerStats()
00083 { }
00084 
00085 
00086 void SimulationViewerStats::start2()
00087 {
00088   
00089   itsFrameIdx = 0;
00090 
00091   
00092   itsMaskCount = 0; itsLamCount = 0; itsOverlapCount = 0;
00093 }
00094 
00095 
00096 void SimulationViewerStats::stop2()
00097 {
00098   
00099   if (itsStatsFile)
00100     {
00101       itsStatsFile->flush();
00102       itsStatsFile->close();
00103       delete itsStatsFile;
00104       itsStatsFile = NULL;
00105     }
00106 }
00107 
00108 
00109 void SimulationViewerStats::lockFile(const std::string fileName,
00110                                      int &fd,
00111                                      struct flock &fl) const
00112 {
00113   
00114   fd = open(fileName.c_str(), O_RDWR);
00115   if (fd < 0)
00116   {
00117         LINFO("lockFile: Open failure on file %s",fileName.c_str());
00118   }
00119   else
00120   {
00121     fl.l_type   = F_WRLCK;
00122     fl.l_whence = SEEK_SET;
00123     fl.l_start  = 0;
00124     fl.l_len    = 0;
00125     if (fcntl(fd, F_SETLK, &fl) == -1)
00126     {
00127       if (errno == EACCES || errno == EAGAIN)
00128         LINFO("'%s' Already locked by another process",fileName.c_str());
00129       else if(errno == EBADF)
00130         LINFO("'%s' not a valid open file descriptor",fileName.c_str());
00131       else if(errno == EINVAL)
00132         LINFO("'%s In a locking operation, fildes refers to a file with a type that does not support locking, or the struct flock pointed to by the third argument has an incorrect form",fileName.c_str());
00133       else if(errno == EMFILE)
00134         LINFO("'%s' process has already reached its maximum number of file descriptors",fileName.c_str());
00135       else
00136       LINFO("Cannot lock file '%s' Error code '%d' \(Is this an NFS mount?)",fileName.c_str(),errno);
00137     }
00138   }
00139 }
00140 
00141 
00142 void SimulationViewerStats::unlockFile(const std::string fileName,
00143                                        const  int fd,
00144                                        struct flock &fl) const
00145 {
00146   
00147   fl.l_type   = F_UNLCK;
00148   fl.l_whence = SEEK_SET;
00149   fl.l_start  = 0;
00150   fl.l_len    = 0;
00151   if (fcntl(fd, F_SETLK, &fl) == -1)
00152   {
00153     LINFO("Cannot unlock file '%s'",fileName.c_str());
00154   }
00155   close(fd);
00156 }
00157 
00158 
00159 void SimulationViewerStats::
00160 onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00161 {
00162   this->save1(e->sinfo());
00163 }
00164 
00165 
00166 void SimulationViewerStats::save1(const ModelComponentSaveInfo& sinfo)
00167 {
00168   
00169   
00170   LINFO("SAVING STATS TO %s",itsStatsFname.getVal().c_str());
00171 
00172   
00173   
00174   struct flock fl; int fd;
00175   lockFile(itsStatsFname.getVal().c_str(),fd,fl);
00176 
00177   
00178   
00179   std::ofstream statsFile;
00180   statsFile.open(itsStatsFname.getVal().c_str(),std::ios_base::app);
00181 
00182   
00183   
00184   nub::ref<FrameOstream> ofs =
00185     dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs;
00186 
00187   
00188   SimEventQueue *q    = dynamic_cast<const SimModuleSaveInfo&>(sinfo).q;
00189 
00190   
00191   if(itsFrameIdx == 0)
00192   {
00193     rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
00194     q->request(vcxm); 
00195 
00196     if (itsStatsFname.getVal().size())
00197     {
00198       itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str());
00199       if (itsStatsFile->is_open() == false)
00200         LFATAL("Failed to open '%s' for writing.",
00201                itsStatsFname.getVal().c_str());
00202 
00203       
00204       getRootObject()->printout(*itsStatsFile, "# ");
00205 
00206       
00207       
00208       
00209 
00210       rutz::shared_ptr<ChannelMaps> chm        = vcxm->channelmaps();
00211       uint                          numSubmaps = chm->numSubmaps();
00212 
00213       *itsStatsFile << "# CHANNELS: ";
00214 
00215       for(uint i = 0; i < numSubmaps; i++)
00216       {
00217         NamedImage<float> smap = chm->getRawCSmap(i);
00218         *itsStatsFile << smap.name() << ", ";
00219       }
00220       *itsStatsFile << std::endl;
00221     }
00222   }
00223 
00224   
00225   
00226   
00227   (*itsStatsFile).flush();
00228   (*itsStatsFile).close();
00229 
00230   
00231   if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this))
00232   {
00233     itsSizeX       = e->frame().getWidth();
00234     itsSizeY       = e->frame().getHeight();
00235     itsFrameNumber = (unsigned int)e->frameNum();
00236     itsFrameIdx    = itsFrameNumber;
00237   }
00238   else
00239   {
00240     itsFrameNumber = itsFrameIdx;
00241     itsFrameIdx++;
00242   }
00243 
00244   
00245   
00246   
00247   Image< PixRGB<byte> > input;
00248   if (SeC<SimEventRetinaImage> e = q->check<SimEventRetinaImage>(this,SEQ_ANY))
00249     input = e->frame().colorByte();
00250   else
00251     LINFO("No input? Check the SimEventCue.");
00252 
00253   
00254   
00255 
00256 
00257 
00258 
00259 
00260 
00261   
00262   Image<float> agm;
00263   if (SeC<SimEventAttentionGuidanceMapOutput> e =
00264       q->check<SimEventAttentionGuidanceMapOutput>(this))
00265     agm = e->agm(1.0F);
00266   else
00267     LINFO("No AGM? Check the SimEventCue.");
00268 
00269   
00270   
00271   bool quit = false;
00272   if (input.initialized() == false)
00273     {
00274       LINFO("WARNING!!! Input seems not to be initialized, so detailed stats cannot be saved.");
00275       quit = true;
00276     }
00277   if(agm.initialized() == false)
00278     {
00279       LINFO("WARNING!!! NO Attention Guidance MAP \"AGM\" so detailed stats cannot be saved.");
00280       quit = true;
00281     }
00282 
00283   if(quit == true) return;
00284 
00285   
00286   Image< PixRGB<byte> > res;
00287   const int w = input.getWidth();
00288 
00289   
00290   if (itsSaveXcombo.getVal() || itsSaveYcombo.getVal())
00291     {
00292       Image<float> nagm = getMap(*q);
00293       res = colGreyCombo(input, nagm, itsSaveXcombo.getVal(),
00294                          itsDisplayInterp.getVal());
00295     }
00296 
00297   
00298   
00299   if (itsGetSingleChannelStats.getVal())
00300     saveCompat(agm);
00301 
00302   
00303   if (statsFile)
00304     {
00305       
00306        statsFile <<std::endl<<"= "<<q->now().msecs()
00307                      <<" # time of frame in ms"<<std::endl;
00308 
00309       
00310       float mi, ma, av; getMinMaxAvg(agm, mi, ma, av);
00311       double sdev = stdev(agm);
00312       double peaksum; int npeaks = findPeaks(agm, 0.0f, 255.0f, peaksum);
00313 
00314       
00315       float maxval; Point2D<int> maxloc;
00316       findMax(agm, maxloc, maxval);
00317       float scale = float(w) / float(agm.getWidth());
00318       maxloc.i = int(maxloc.i * scale + 0.4999F);
00319       maxloc.j = int(maxloc.j * scale + 0.4999F);
00320       if (res.initialized())
00321         {
00322           drawPatch(res, maxloc, 4, COL_YELLOW);
00323           drawPatch(res, maxloc + Point2D<int>(w, 0), 4, COL_YELLOW);
00324         }
00325 
00326       
00327       float minval; Point2D<int> minloc;
00328       findMin(agm, minloc, minval);
00329       minloc.i = int(minloc.i * scale + 0.4999F);
00330       minloc.j = int(minloc.j * scale + 0.4999F);
00331       if (res.initialized())
00332         {
00333           drawPatch(res, minloc, 4, COL_GREEN);
00334           drawPatch(res, minloc + Point2D<int>(w, 0), 4, COL_GREEN);
00335         }
00336 
00337       
00338        statsFile  <<maxloc.i<<' '<<maxloc.j<<' '<<minloc.i<<' '
00339                   <<minloc.j<<' '<<ma<<' '<<mi<<' '<<av<<' '<<sdev
00340                   <<' '<<npeaks<<' '<<peaksum
00341                   <<" # Xmax Ymax Xmin Ymin max min avg std npeaks peaksum"
00342                   <<std::endl;
00343 
00344       
00345       
00346       std::vector<Point2D<int> > loc;
00347       loc.push_back(maxloc);
00348       loc.push_back(minloc);
00349       for (uint n = 0; n < 100; n ++)
00350         loc.push_back(Point2D<int>(randomUpToNotIncluding(input.getWidth()),
00351                               randomUpToNotIncluding(input.getHeight())));
00352 
00353       
00354       ImageSet<float> cmap;
00355       
00356       rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
00357       q->request(vcxm); 
00358       rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps();
00359       uint numSubmaps = chm->numSubmaps();
00360       for(uint i=0;i < numSubmaps; i++)
00361       {
00362         NamedImage<float> tempMap = chm->getRawCSmap(i);
00363         Image<float> m = tempMap;
00364         cmap.push_back(m);
00365 
00366         
00367         Point2D<int> p; float v;
00368         findMax(m, p, v); loc.push_back(p);
00369         findMin(m, p, v); loc.push_back(p);
00370       }
00371       
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384       
00385       
00386       for (uint i = 0; i < loc.size(); i ++)
00387         {
00388           Point2D<int> p = loc[i];
00389           Point2D<int> pp(int(p.i / scale), int(p.j / scale));
00390 
00391            statsFile <<p.i<<' '<<p.j<<"     ";
00392 
00393           
00394           
00395           for (uint j = 0; j < cmap.size(); j ++)
00396           {
00397             if((int(p.i / scale) < agm.getWidth()) &&
00398                (int(p.j / scale) < agm.getHeight()))
00399             {
00400               (statsFile)<<cmap[j].getVal(pp)<<' ';
00401               (statsFile)<<"    ";
00402             }
00403             else
00404             {
00405               (statsFile)<<"-1"<<' ';
00406               (statsFile)<<"    ";
00407             }
00408           }
00409 
00410           
00411           
00412 
00413 
00414 
00415 
00416 
00417            statsFile  <<"# features "<<i<<" at ("<<p.i
00418                          <<", "<<p.j<<')'<<std::endl;
00419         }
00420   }
00421 
00422   statsFile.flush();
00423   statsFile.close();
00424   unlockFile(itsStatsFname.getVal().c_str(),fd,fl);
00425   
00426   if (res.initialized())
00427     ofs->writeRGB(res, "T",
00428                   FrameInfo("SimulationViewerStats trajectory", SRC_POS));
00429 
00430   
00431   
00432   if(itsComputeAGStats.getVal())
00433     computeAGStats(*q);
00434   else if (SeC<SimEventAttentionGateOutput> ag =
00435            q->check<SimEventAttentionGateOutput>(this))
00436     computeLAMStats(ag->lam());
00437 
00438 
00439   if(itsOverlap.initialized())
00440     ofs->writeRGB(itsOverlap, "AG-STAT-MASK",
00441                   FrameInfo("Stats mask overlap", SRC_POS));
00442 
00443   if(itsVisualSegments.initialized())
00444     ofs->writeRGB(itsVisualSegments, "AG-STAT-SEGS",
00445                   FrameInfo("Stats segments", SRC_POS));
00446 
00447   if(itsVisualCandidates.initialized())
00448     ofs->writeGray(itsVisualCandidates, "AG-STAT-CAND",
00449                    FrameInfo("Stats candidates", SRC_POS));
00450 
00451 }
00452 
00453 
00454 void SimulationViewerStats::computeLAMStats(const Image<float> &img)
00455 {
00456 
00457   saveCompat(img,".final-lam.txt",-1);
00458 
00459   Image<float> lamr = rescale(img,itsSizeX,itsSizeY);
00460 
00461   itsMaskCount  = 0; itsLamCount = 0; itsOverlapCount = 0;
00462   itsTotalCount = 0;
00463 
00464   
00465   for(Image<float>::iterator litr = lamr.beginw();
00466       litr != lamr.endw(); litr++)
00467   {
00468     if(*litr > 32) itsLamCount++;
00469     itsTotalCount++;
00470   }
00471   saveAGMaskStats(lamr,"LAM");
00472 
00473 }
00474 
00475 
00476 void SimulationViewerStats::computeAGStats(SimEventQueue& q)
00477 {
00478   
00479   if (SeC<SimEventAttentionGateOutput> ag =
00480       q.check<SimEventAttentionGateOutput>(this))
00481   {
00482     Image<float> lam = ag->lam();
00483     saveCompat(lam,".final-lam.txt",-1);
00484     
00485 
00486     
00487     
00488     if(!itsMask.initialized())
00489     {
00490       
00491       const Image< PixRGB<byte> > cmask =
00492         Raster::ReadRGB(itsAGMaskFile.getVal());
00493 
00494       LINFO("Target Mask File Read %s",itsAGMaskFile.getVal().c_str());
00495 
00496       
00497       itsMask.resize(cmask.getWidth(),cmask.getHeight());
00498       Image<bool>::iterator mitr = itsMask.beginw();
00499       
00500       for(Image<PixRGB<byte> >::const_iterator citr = cmask.begin();
00501           citr != cmask.end(); citr++)
00502       {
00503         
00504         if(citr->p[0] < 230) *mitr++ = true;
00505         else                 *mitr++ = false;
00506       }
00507 
00508       itsLamMask.resize(itsMask.getWidth(),itsMask.getHeight(),true);
00509       itsOverlap.resize(itsMask.getWidth(),itsMask.getHeight(),true);
00510     }
00511 
00512 
00513     
00514     
00515     if(itsMask.initialized())
00516     {
00517       LINFO("FRAME %d",itsFrameNumber);
00518       
00519       
00520       if((itsFrameNumber == (unsigned int)(itsAGTargetFrame.getVal() + 1)) ||
00521          ((itsAGTargetFrame.getVal() == 0) && (itsFrameIdx > 0)))
00522       {
00523 
00524         LINFO("Checking Mask file to target Attention Gate Frame %d",
00525               (itsFrameNumber + 1));
00526         
00527         
00528 
00529         
00530         
00531         
00532         
00533 
00534         
00535         Image<float> lamr          = rescale(lam,itsMask.getWidth(),
00536                                              itsMask.getHeight());
00537         Image<bool>::iterator mitr = itsLamMask.beginw();
00538 
00539         
00540         for(Image<float>::iterator litr = lamr.beginw();
00541             litr != lamr.endw();
00542             litr++)
00543         {
00544           
00545           if(*litr > 32) *mitr++ = true;
00546           else           *mitr++ = false;
00547         }
00548 
00549         itsMaskCount  = 0; itsLamCount = 0; itsOverlapCount = 0;
00550         itsTotalCount = 0;
00551 
00552         Image<bool>::iterator aitr          = itsMask.beginw();
00553         Image<bool>::iterator litr          = itsLamMask.beginw();
00554         Image<PixRGB<byte> >::iterator oitr = itsOverlap.beginw();
00555 
00556         
00557         
00558         while(litr != itsLamMask.endw())
00559         {
00560           if(*aitr++)
00561           {
00562             itsMaskCount++;
00563             if(*litr++)
00564             {
00565               itsLamCount++;
00566               itsOverlapCount++;
00567               *oitr++ = PixRGB<byte>(0,0,0);      
00568             }
00569             else *oitr++ = PixRGB<byte>(255,0,0); 
00570           }
00571           else if(*litr++)
00572           {
00573             itsLamCount++;
00574             *oitr++ = PixRGB<byte>(0,0,255);      
00575           }
00576           else
00577           {
00578             *oitr++ = PixRGB<byte>(255,255,255); 
00579           }
00580           itsTotalCount++;
00581         }
00582 
00583         
00584         
00585         
00586 
00587         
00588         if(itsMaskCount      == itsTotalCount)
00589           LFATAL("Constancy Check failed for mask - Too Large!");
00590         else if(itsMaskCount == 0)
00591           LFATAL("Constancy Check failed for mask - Too Small!");
00592 
00593         saveAGMaskStats(lamr,"AG-MASK");
00594       }
00595     }
00596 
00597     
00598     if (SeC<SimEventAttentionGateStageTwoSegments> agst =
00599         q.check<SimEventAttentionGateStageTwoSegments>(this))
00600     {
00601       LINFO("Getting Segments Image");
00602       const Image<int> segments = agst->obj().segments;
00603       Image<float> newSegments  = static_cast<Image<float> >(segments);
00604 
00605       float min,max,avg;
00606 
00607       getMinMaxAvg(newSegments,min,max,avg);
00608 
00609       LINFO("Segments min %f max %f",min,max);
00610 
00611       Image<PixHSV<float> > classImage;
00612 
00613       classImage.resize(segments.getWidth(),segments.getHeight());
00614 
00615       if((max-min) > 0.0f)
00616       {
00617         
00618         
00619         newSegments = ((newSegments - min) / (max - min)) * 300.0f;
00620 
00621         Image<PixHSV<float> >::iterator classImageItr = classImage.beginw();
00622 
00623         for(Image<float>::iterator segmentsItr = newSegments.beginw();
00624             segmentsItr != newSegments.endw(); ++segmentsItr)
00625        {
00626          classImageItr->p[0] = *segmentsItr;
00627          
00628          classImageItr->p[1] = 100.0f;
00629          classImageItr->p[2] = 255.0f;
00630          ++classImageItr;
00631        }
00632 
00633         
00634         Image<PixRGB<float> > temp =
00635           static_cast<Image<PixRGB<float> > >(classImage);
00636 
00637         itsVisualSegments = temp;
00638       }
00639 
00640       const Image<bool> cand = agst->candidates();
00641       Image<float> newCand   = static_cast<Image<float> >(cand);
00642 
00643       newCand = newCand * 255.0f;
00644 
00645       itsVisualCandidates = newCand;
00646 
00647     }
00648   }
00649 }
00650 
00651 
00652 
00653 void SimulationViewerStats::saveCompat(const Image<float>& img,
00654                                        const std::string suffix,
00655                                        const int frameOffset)
00656 {
00657 
00658 
00659   unsigned int frameIdx = (unsigned int)((int)itsFrameNumber + frameOffset);
00660 
00661   std::string fileName;
00662   std::string txt = suffix;
00663   fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00664 
00665   ushort minx = 0, miny = 0, maxx = 0, maxy = 0;
00666   float  min,  max,  avg,  std;
00667   uint   N;
00668   
00669   getMinMaxAvgEtc(img, min, max, avg, std, minx, miny, maxx, maxy, N);
00670 
00671   LINFO("SAVING COMPAT STATS TO %s",fileName.c_str());
00672 
00673   std::ofstream statsFile(fileName.c_str(), std::ios::app);
00674 
00675   statsFile << "final" << "\t";
00676 
00677   statsFile << frameIdx << "\t";
00678 
00679   
00680   
00681 
00682   statsFile << "COMBINED\t-1\t";
00683   
00684 
00685   statsFile << "final" << "\t" << "FINAL" << "\t";
00686   statsFile << min  << "\t" << max  << "\t" << avg  << "\t" << std  << "\t"
00687             << minx << "\t" << miny << "\t" << maxx << "\t" << maxy << "\t"
00688             << N    << "\n";
00689   statsFile.close();
00690 
00691   if(itsSaveStatsPerChannelFreq.getVal())
00692     {
00693       std::string txt = ".final.freq.txt";
00694       fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00695 
00696       FFTWWrapper fft(img.getWidth(), img.getHeight());
00697       double dimg[img.getHeight() * img.getWidth()];
00698       Image<float>::const_iterator itr = img.begin();
00699       double *ditr = &dimg[0];
00700       while(itr != img.end()) *ditr++ = double(*itr++);
00701       fft.init(dimg);
00702       double mag[img.getHeight() * (img.getWidth()/2 + 1)];
00703       fft.compute(mag);
00704 
00705       std::ofstream freqFile(fileName.c_str(), std::ios::app);
00706       freqFile << "final" << "\t";
00707       freqFile << frameIdx << "\t";
00708 
00709       freqFile << "COMBINED\t-1\t";
00710 
00711       freqFile << "SIZE\t" << img.getWidth() <<"\t"<< img.getHeight() << "\n";
00712 
00713       for(int i = 0; i < img.getHeight(); i++)
00714         {
00715           for(int j = 0; j < (img.getWidth()/2 + 1); j++)
00716             freqFile << mag[i * (img.getWidth()/2 + 1) + j] << "\t";
00717           freqFile << "\n";
00718         }
00719       freqFile.close();
00720     }
00721 }
00722 
00723 
00724 void SimulationViewerStats::saveAGMaskStats(const Image<float> &img,
00725                                             const std::string caller,
00726                                             const std::string suffix)
00727 {
00728 
00729   ushort minx = 0, miny = 0, maxx = 0, maxy = 0;
00730   float  min,  max,  avg,  std;
00731   uint   N;
00732   
00733   getMinMaxAvgEtc(img, min, max, avg, std, minx, miny, maxx, maxy, N);
00734 
00735   std::string fileName;
00736   std::string txt = suffix;
00737   fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00738 
00739   LINFO("SAVING AG STATS TO %s",fileName.c_str());
00740 
00741   std::ofstream statsFile(fileName.c_str(), std::ios::app);
00742 
00743   statsFile << "AGstats" << "\t";
00744 
00745   statsFile << (itsFrameNumber - 1) << "\t";
00746 
00747   
00748   
00749 
00750   statsFile << "COMBINED\t" << caller << "\t";
00751   
00752 
00753   statsFile << "final" << "\t" << "FINAL" << "\t";
00754   statsFile << itsTotalCount   << "\t"
00755             << itsMaskCount    << "\t"
00756             << itsLamCount     << "\t"
00757             << itsOverlapCount << "\t";
00758   statsFile << min  << "\t" << max  << "\t" << avg  << "\t" << std  << "\t"
00759             << minx << "\t" << miny << "\t" << maxx << "\t" << maxy << "\t"
00760             << N    << "\n";
00761 
00762   statsFile.close();
00763 }
00764 
00765 
00766 
00767 
00768 
00769 
00770