00001 /*!@file AppPsycho/psycho-searchArray.C Psychophysics display of still search arrays */ 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://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-searchArray.C $ 00035 // 00036 00037 #include "Component/ModelManager.H" 00038 #include "Component/ModelOptionDef.H" 00039 #include "Image/Image.H" 00040 #include "Image/Range.H" 00041 #include "Image/DrawOps.H" 00042 #include "Psycho/PsychoDisplay.H" 00043 #include "Psycho/EyeTrackerConfigurator.H" 00044 #include "Psycho/EyeTracker.H" 00045 #include "Psycho/PsychoOpts.H" 00046 #include "Psycho/ArrayCreator.H" 00047 #include "Component/EventLog.H" 00048 #include "Component/ComponentOpts.H" 00049 #include "Raster/Raster.H" 00050 #include "Util/MathFunctions.H" 00051 #include "Util/Types.H" 00052 #include "Util/SimTime.H" 00053 #include "Util/Timer.H" 00054 #include "rutz/rand.h" 00055 00056 #include <vector> 00057 00058 //option for number of trials 00059 static const ModelOptionDef OPT_ACTrials = 00060 { MODOPT_ARG(int), "ACTrials", &MOC_PSYCHOARRAYCREATOR, 00061 OPTEXP_CORE, "number of times to repeat the sequnce", 00062 "trials", '\0', "<int>", "1" }; 00063 00064 // ###################################################################### 00065 extern "C" int main(const int argc, char** argv) 00066 { 00067 MYLOGVERB = LOG_INFO; // suppress debug messages 00068 00069 // Instantiate a ModelManager: 00070 ModelManager manager("Psycho Search Array"); 00071 OModelParam<std::string> itsConfigFile(&OPT_ACFileName, &manager); 00072 OModelParam<uint> itsItemRadius(&OPT_ACItemRadius, &manager); 00073 OModelParam<float> itsJitter(&OPT_ACJitterLevel, &manager); 00074 OModelParam<float> itsPpdx(&OPT_ACPpdX, &manager); 00075 OModelParam<float> itsPpdy(&OPT_ACPpdY, &manager); 00076 OModelParam<PixRGB<byte> > itsBgCol(&OPT_ACBackgroundColor, &manager); 00077 OModelParam<SimTime> itsDur(&OPT_DisplayTime, &manager); 00078 OModelParam<float> itsFixSize(&OPT_FixSize, &manager); 00079 OModelParam<bool> itsKeepFix(&OPT_KeepFix, &manager); 00080 OModelParam<int> itsTrials(&OPT_ACTrials, &manager); 00081 OModelParam<Range<int> > itsWait(&OPT_TrialWait, &manager); 00082 OModelParam<bool> itsPermTargs(&OPT_ACPermuteTargs, &manager); 00083 OModelParam<bool> testrun(&OPT_Testrun, &manager); 00084 00085 // Instantiate our various ModelComponents: 00086 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager)); 00087 manager.addSubComponent(d); 00088 00089 nub::soft_ref<EyeTrackerConfigurator> 00090 etc(new EyeTrackerConfigurator(manager)); 00091 manager.addSubComponent(etc); 00092 00093 nub::soft_ref<EventLog> el(new EventLog(manager)); 00094 manager.addSubComponent(el); 00095 00096 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy"); 00097 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN"); 00098 00099 // Parse command-line: 00100 if (manager.parseCommandLine(argc, argv,"", 0, 0)==false) 00101 return(1); 00102 00103 //create search array 00104 ArrayCreator ac(itsConfigFile.getVal(), 00105 itsItemRadius.getVal(), itsJitter.getVal(), 00106 d->getDims(), itsPpdx.getVal(),itsPpdy.getVal(), 00107 itsBgCol.getVal(), 00108 int(itsKeepFix.getVal())*itsFixSize.getVal(), 00109 itsPermTargs.getVal()); 00110 00111 LINFO("Array list created with %d trials", ac.size()); 00112 00113 // hook our various babies up and do post-command-line configs: 00114 nub::soft_ref<EyeTracker> et = etc->getET(); 00115 d->setEyeTracker(et); 00116 d->setEventLog(el); 00117 et->setEventLog(el); 00118 00119 initRandomNumbers(); 00120 00121 // let's get all our ModelComponent instances started: 00122 manager.start(); 00123 00124 d->SDLdisplay::clearScreen(itsBgCol.getVal()); 00125 00126 //determine size of fixation point, set sdl fixation point 00127 const float ppd = sqrt(itsPpdx.getVal()*itsPpdx.getVal() + 00128 itsPpdy.getVal()*itsPpdy.getVal()); 00129 const int size = int(ppd * itsFixSize.getVal()); 00130 d->setFixationSize(size*2); 00131 00132 // setup array of search array indices: 00133 uint nbimgs = ac.size()*itsTrials.getVal(); int index[nbimgs]; 00134 for (uint i = 0; i < nbimgs; ++i) index[i] = i % ac.size(); 00135 randShuffle(index, nbimgs); 00136 std::vector<int> vindex(index, index + nbimgs); 00137 00138 try { 00139 // main loop: 00140 for (uint i = 0; i < vindex.size(); i ++) 00141 { 00142 // load up the frame and show a fixation cross on a blank screen: 00143 d->SDLdisplay::clearScreen(itsBgCol.getVal()); 00144 Image< PixRGB<byte> > image = ac.draw(vindex[i]); 00145 00146 SDL_Surface *surf = d->makeBlittableSurface(image, true); 00147 LINFO("Array ready. %d trial", i); 00148 00149 // give a chance to other processes (useful on single-CPU machines): 00150 sleep(1); if (system("/bin/sync")) LERROR("error in sync"); 00151 LINFO("sync command complete"); 00152 00153 // eat up any extra fixations, saccades, or keys before we start 00154 // the next fixation round: 00155 et->clearEyeStatus(); 00156 while (d->checkForKey() != -1) ; 00157 00158 // display fixation to indicate that we are ready: 00159 d->displayWhiteDotFixation(); 00160 00161 // give us a chance to abort 00162 d->checkForKey(); 00163 00164 // ready to go whenever the monkey is ready (pulse on parallel port): 00165 if (!testrun.getVal()) 00166 while(true) 00167 { 00168 if (et->isFixating()) break; 00169 if (d->checkForKey() != -1) break; // allow force start by key 00170 } 00171 00172 //eat up any eye fixations or saccades, in case both were triggered 00173 et->clearEyeStatus(); 00174 00175 //store stimulus data to log file 00176 d->pushEvent(std::string("===== Showing Array: ") + 00177 ac.toString(index[i]) + " ====="); 00178 00179 //wait for the next refresh 00180 d->waitNextRequestedVsync(false, true); 00181 00182 // start the eye tracker: 00183 et->track(true); 00184 00185 // show the image: 00186 d->displaySurface(surf, -2); 00187 00188 //time starts when display is visible 00189 Timer itsTimer; 00190 00191 //wait for the required time, or break if we recieve a signal. 00192 while ( itsTimer.getSimTime() < itsDur.getVal() ) 00193 { 00194 if (itsKeepFix.getVal()) 00195 if (et->isSaccade()) 00196 { 00197 LINFO("Trial Aborted: Broke fixation"); 00198 d->pushEvent("Trial Aborted: Broke fixation"); 00199 00200 //put the stimulus back into the queue 00201 int temp = vindex[i]; 00202 vindex.push_back(temp); 00203 break; 00204 } 00205 } 00206 00207 // free the image: 00208 SDL_FreeSurface(surf); 00209 00210 // make sure display if off before we stop the tracker: 00211 d->SDLdisplay::clearScreen(itsBgCol.getVal()); 00212 00213 // stop the eye tracker: 00214 usleep(50000); 00215 et->track(false); 00216 00217 //wait for requested time till next trial 00218 usleep(rutz::rand_range<int>(itsWait.getVal().min(), 00219 itsWait.getVal().max()) * 1000); 00220 } 00221 00222 d->SDLdisplay::clearScreen(itsBgCol.getVal());; 00223 LINFO("Experiment complete"); 00224 } 00225 catch(...) 00226 { 00227 REPORT_CURRENT_EXCEPTION; 00228 } 00229 00230 // stop all our ModelComponents 00231 manager.stop(); 00232 00233 // all done! 00234 return 0; 00235 } 00236 00237 // ###################################################################### 00238 /* So things look consistent in everyone's emacs... */ 00239 /* Local Variables: */ 00240 /* indent-tabs-mode: nil */ 00241 /* End: */