Staircase.C

Go to the documentation of this file.
00001 /*!@file Psycho/Staircase.C A staircase procedure for psychophysical thresholds */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the 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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/Staircase.C $
00035 // $Id: Staircase.C 8264 2007-04-17 21:43:10Z rjpeters $
00036 //
00037 
00038 #include "Psycho/Staircase.H"
00039 
00040 #include "Component/OptionManager.H"
00041 #include "Util/MathFunctions.H"
00042 #include "Util/sformat.H"
00043 
00044 #include <fstream>
00045 
00046 // ######################################################################
00047 Staircase::Staircase(OptionManager& mgr, const std::string& descrName,
00048                      const std::string& tagName) :
00049   ModelComponent(mgr, descrName, tagName),
00050   itsInitial("InitialValue", this, 1.0),
00051   itsDelta("DeltaValue", this, 0.1),
00052   itsMini("MinValue", this, 0.0),
00053   itsMaxi("MaxValue", this, 1.0),
00054   itsNright("Nright", this, 4),
00055   itsNwrong("Nwrong", this, 2),
00056   itsFileName("FileName", this, std::string("staircase-")+tagName+".txt"),
00057   itsTrial(0), itsValue(0.0),
00058   itsTimer(1000000),  // use microsecond resolution
00059   itsEvents(), itsNr(0), itsNw(0), itsExpectedResponse(false)
00060 { }
00061 
00062 // ######################################################################
00063 Staircase::~Staircase()
00064 { }
00065 
00066 // ######################################################################
00067 void Staircase::start2()
00068 {
00069   initRandomNumbers();
00070 
00071   itsValue = itsInitial.getVal(); itsTimer.reset();
00072   time_t ti = time(NULL);
00073   pushEvent(sformat("##### START %s #####", ctime(&ti)));
00074 }
00075 
00076 // ######################################################################
00077 void Staircase::reset1()
00078 {
00079   itsTrial = 0; itsValue = itsInitial.getVal();
00080   itsTimer.reset(); itsNr = 0; itsNw = 0;
00081   time_t ti = time(NULL);
00082   pushEvent(sformat("##### RESET %s #####", ctime(&ti)));
00083 
00084   ModelComponent::reset1();
00085 }
00086 
00087 // ######################################################################
00088 void Staircase::stop1()
00089 {
00090   // let's save the events:
00091   if (itsEvents.empty() == false && itsFileName.getVal().length() > 1)
00092     {
00093       std::ofstream ofs(itsFileName.getVal().c_str());
00094       if (!ofs.is_open())
00095         {
00096           LERROR("Couldn't open file '%s' for writing.",
00097                  itsFileName.getVal().c_str());
00098           return;
00099         }
00100 
00101       std::list<StaircaseEvent>::const_iterator itr = itsEvents.begin();
00102       while (itr != itsEvents.end()) {
00103         int usec = int(itr->tim % 1000ULL);
00104         int msec = int((itr->tim / 1000ULL) % 1000ULL);
00105         int sec = int((itr->tim / 1000000ULL) % 60ULL);
00106         int minu = int((itr->tim / 60000000ULL) % 60ULL);
00107         int hour = int(itr->tim / 3600000000ULL);
00108         char tim[256]; sprintf(tim, "%03d:%02d:%02d.%03d.%03d",
00109                                hour, minu, sec, msec, usec);
00110         ofs << tim << " " << itr->descrip;
00111         if (itr->trial >= 0) {
00112           ofs << " Trial = " << itr->trial << " Value = " << itr->val;
00113           if (itr->descrip.compare("end  ") == 0)
00114             ofs << " Response = " << (itr->response ? "Correct" : "Incorrect");
00115         }
00116         ofs << std::endl;
00117         itr ++;
00118       }
00119       ofs.close();
00120       LINFO("Saved data to '%s'", itsFileName.getVal().c_str());
00121     }
00122 }
00123 
00124 // ######################################################################
00125 void Staircase::getValues(double& value1, double& value2)
00126 {
00127   // randomly pick a trial type
00128   if (randomDouble() < 0.5)
00129     {
00130       // nothing-then-something:
00131       value1 = 0.0; value2 = itsValue; itsExpectedResponse = true;
00132     }
00133   else
00134     {
00135       // something-then-nothing:
00136       value1 = itsValue; value2 = 0.0; itsExpectedResponse = false;
00137     }
00138 
00139   // log the setup:
00140   pushEvent("begin", itsTrial, itsValue, true);
00141 }
00142 
00143 // ######################################################################
00144 void Staircase::setResponse(const bool response)
00145 {
00146   bool correct = (response == itsExpectedResponse);
00147 
00148   // log the current value of the parameter and the corresponding
00149   // response obtained for that value:
00150   pushEvent("end  ", itsTrial, itsValue, correct);
00151 
00152   // compute the next value to use:
00153   if (correct) { itsNr ++; itsNw = 0; }  // correct answer
00154   else { itsNw ++; itsNr = 0; }  // incorrect answer
00155 
00156   if (itsNr >= itsNright.getVal())
00157     { itsValue -= itsDelta.getVal(); itsNr = 0; }
00158   if (itsNw >= itsNwrong.getVal())
00159     { itsValue += itsDelta.getVal(); itsNw = 0; }
00160 
00161   if (itsValue < itsMini.getVal()) itsValue = itsMini.getVal();
00162   if (itsValue > itsMaxi.getVal()) itsValue = itsMaxi.getVal();
00163 
00164   itsTrial ++;
00165 }
00166 
00167 // ######################################################################
00168 void Staircase::pushEvent(const std::string& msg, const int trial,
00169                           const double val, const bool response)
00170 {
00171   StaircaseEvent evt;
00172   evt.descrip = msg; evt.tim = itsTimer.get();
00173   evt.trial = trial; evt.val = val; evt.response = response;
00174   itsEvents.push_back(evt);
00175 }
00176 
00177 // ######################################################################
00178 /* So things look consistent in everyone's emacs... */
00179 /* Local Variables: */
00180 /* indent-tabs-mode: nil */
00181 /* End: */
Generated on Sun May 8 08:41:13 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3