00001 /*!@file AppPsycho/psycho-geon-relations.C Psychophysics display of geon images of Marks relations experiment */ 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-geon-relations.c $ 00035 // $Id: psycho-geon-relations.c 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 #include "Component/ModelManager.H" 00039 #include "Image/Image.H" 00040 #include "Psycho/PsychoDisplay.H" 00041 #include "Psycho/EyeTrackerConfigurator.H" 00042 #include "Psycho/EyeTracker.H" 00043 #include "Psycho/PsychoOpts.H" 00044 #include "Component/EventLog.H" 00045 #include "Component/ComponentOpts.H" 00046 #include "Raster/Raster.H" 00047 #include "Util/MathFunctions.H" 00048 #include "Util/Types.H" 00049 #include <fstream> 00050 #include <ctime> 00051 #include <SDL/SDL_mixer.h> //for playing sounds 00052 #include <stdio.h> 00053 00054 using namespace std; 00055 00056 char waitForResp(double WaitTime, double StartMeasure, *char keys, int NumOfKeys); 00057 int WrightResults2File(string FileName,int* IsCorrect, double* RT,char* SubResp, char* CorrectResp, int NumOfTrials); 00058 00059 00060 // ###################################################################### 00061 extern "C" int main(const int argc, char** argv) 00062 { 00063 MYLOGVERB = LOG_INFO; // suppress debug messages 00064 00065 // Instantiate a ModelManager: 00066 ModelManager manager("Psycho Still"); 00067 00068 // Instantiate our various ModelComponents: 00069 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager)); 00070 manager.addSubComponent(d); 00071 00072 nub::soft_ref<EyeTrackerConfigurator> 00073 etc(new EyeTrackerConfigurator(manager)); 00074 manager.addSubComponent(etc); 00075 00076 nub::soft_ref<EventLog> el(new EventLog(manager)); 00077 manager.addSubComponent(el); 00078 00079 int NumOfKeys=3; 00080 char keys[NumOfKeys]={'z', ',', '.'}; //from left to right, the key specified means object 1,2,3 00081 00082 00083 00084 00085 // Parse command-line: 00086 // Subject Run isAdapt(1or0) MaleOrFemale 00087 if (manager.parseCommandLine(argc, argv, 00088 "<img1.ppm> ... <imgN.ppm>", 1, -1)==false){ 00089 cout<<"please give the following arguments:\n Subject-Initials Run-Number PresentationFrames(1 sec is 30 frames) MaleOrFemale(M for Male, F you guessed it...) Handedness(R L)"<< endl; 00090 cout<<"the keys for objects 1,2,3 are, respectively the keys:"<< keys[0]<< ", "<<keys[1] <<", "<< keys[2]<<endl; 00091 return(1); 00092 } 00093 00094 string Sub=manager.getExtraArg(0); 00095 string Run=manager.getExtraArg(1); 00096 string PT=manager.getExtraArg(2); 00097 const char *pp; 00098 pp=PT.c_str(); 00099 int PresentationFrames=atoi(pp); 00100 //int PresentationTime=(int)PT[0]-48;//atoi(PT[0].c_str()); 00101 cout<<"presentation time is:"<<(PresentationFrames/30)<<" seconds"<<endl; 00102 string Gender=manager.getExtraArg(3); 00103 string Handedness=manager.getExtraArg(4); 00104 00105 string DataDir="/lab/ilab19/geonexp/GRET/Data/"; 00106 string psyFileName=DataDir + "GRET_Run" + Run + "_"+ Sub+"_StimONFrames-"+PT+"_"+Gender+"_"+Handedness+".psy"; 00107 manager.setOptionValString(&OPT_EventLogFileName, psyFileName); 00108 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN"); 00109 00110 d->pushEvent(std::string("Run=") + Run + "\n" + Sub +"\nGender="+ Gender); 00111 00112 00113 00114 00115 // hook our various babies up and do post-command-line configs: 00116 nub::soft_ref<EyeTracker> et = etc->getET(); 00117 d->setEyeTracker(et); 00118 d->setEventLog(el); 00119 et->setEventLog(el); 00120 00121 // let's get all our ModelComponent instances started: 00122 manager.start(); 00123 00124 // let's do an eye tracker calibration: 00125 et->calibrate(d); 00126 00127 d->clearScreen(); 00128 d->displayText("<SPACE> for random play; other key for ordered"); 00129 //int c = d->waitForKey(); 00130 00131 // setup array of movie indices: 00132 //uint nbimgs = manager.numExtraArgs(); int index[nbimgs]; 00133 //for (uint i = 0; i < nbimgs; i ++) index[i] = i; 00134 //if (c == ' ') { LINFO("Randomizing images..."); randShuffle(index, nbimgs); } 00135 00136 //Reads the Images sequence text file: 00137 string FileName; 00138 00139 string ExpDir="/lab/ilab19/geonexp/GRET/sequences/"; 00140 string ImgDir="/lab/ilab19/geonexp/GRET/images/"; 00141 00142 00143 FileName=ExpDir+"GeonRelationsET_Run"+Run+".txt"; 00144 00145 00146 cout<<FileName<<endl; 00147 const char *FileNameP=FileName.c_str(); 00148 00149 00150 ifstream RunFile (FileNameP); 00151 string u; 00152 00153 int NumOfTrials, j; 00154 00155 getline(RunFile, u); 00156 cout<<u; 00157 const char *p; 00158 p=u.c_str(); 00159 NumOfTrials=atoi(p); 00160 string ImageSequence[NumOfTrials]; 00161 double RT[NumOfTrials]; //The reaction time for each trial 00162 char SubResp[NumOfTrials];//The actual response in each trial 00163 int IsCorrect[NumOfTrials]; // whether the response was correct (=1) incorrect (=0) or no response recorded (=-1) 00164 char Correct_Response[NumOfTrials]; //The key that the subject should have pressed 00165 00166 for(j=0; j<NumOfTrials; j++){ 00167 getline(RunFile, ImageSequence[j]); 00168 ImageSequence[j]= ImgDir +ImageSequence[j]; 00169 cout <<ImageSequence[j]<<endl; 00170 } 00171 00172 RunFile.close(); 00173 00174 double StartMeasure; 00175 double Now; 00176 char Response; 00177 00178 //setting up the audio (for the error-feedback) 00179 Mix_Music* recallCueMusic = NULL; 00180 //now let's open the audio channel 00181 if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){ 00182 LINFO( "did not open the mix-audio") ; 00183 return -1 ; 00184 } 00185 SoundFile='/lab/ilab19/geonexp/GRET/images/beep-2.wav'; 00186 BipSound = Mix_LoadMUS(SoundFile); 00187 00188 00189 00190 00191 00192 LINFO("Ready to go"); 00193 00194 // main loop: 00195 for (int i = 0; i < NumOfTrials; i ++) 00196 { 00197 // load up the frame and show a fixation cross on a blank screen: 00198 d->clearScreen(); 00199 LINFO("Loading '%s'...", ImageSequence[i].c_str()); 00200 Image< PixRGB<byte> > image = 00201 Raster::ReadRGB(ImageSequence[i]); 00202 00203 SDL_Surface *surf = d->makeBlittableSurface(image, true); 00204 00205 LINFO("'%s' ready.", ImageSequence[i].c_str()); 00206 d->displayFixation(); 00207 00208 // ready to go whenever the user is ready: 00209 d->waitForKey(); 00210 d->waitNextRequestedVsync(false, true); 00211 d->pushEvent(std::string("===== Showing image: ") + 00212 ImageSequence[i] + " ====="); 00213 00214 //Finding out what object it is 00215 Current_Obj=ImageSequence[i][3]; 00216 Correct_Response[i]=keys[ImageSequence[i][3]-1]; 00217 00218 // start the eye tracker: 00219 et->track(true); 00220 00221 // blink the fixation: 00222 d->displayFixationBlink(); 00223 00224 // show the image: 00225 d->displaySurface(surf, -2); 00226 00227 // Recording response: 00228 StartMeasure=d->getTimerValue(); 00229 Response=waitForResp((PresentationFrames/30), StartMeasure, keys, NumOfKeys); //see function bellow 00230 if (Response!='0'){RT[i]=((d->getTimerValue())-StartMeasure);}; 00231 cout<<Response<<endl; 00232 00233 //continues to present the image for the time specified 00234 Now = d->getTimerValue(); 00235 while ((Now-StartMeasure)<(PresentationFrames/30)) { d->waitFrames(1);}; 00236 00237 // free the image: 00238 SDL_FreeSurface(surf); 00239 00240 // make sure display if off before we stop the tracker: 00241 d->clearScreen(); 00242 00243 // stop the eye tracker: 00244 usleep(50000); 00245 et->track(false); 00246 00247 //recording response if it wasn't yet recorded 00248 if (Response=='0') {Response=waitForResp(((PresentationFrames/30)+1), StartMeasure, keys, NumOfKeys);} 00249 if (Response!='0'){RT[i]=((d->getTimerValue())-StartMeasure);}else{RT[i]=-1;}; 00250 SubResp[i]=Response; 00251 00252 00253 //feedback if error 00254 if (Response!=Correct_Response){ 00255 IsCorrect[i]=0; 00256 if(task == 0){if( Mix_PlayMusic( BipSound, 0 ) == -1 ) { return 1; } 00257 while( Mix_PlayingMusic() == 1 ){} 00258 }else{ 00259 IsCorrect[i]=1; 00260 } 00261 } 00262 string BehaveFileName=DataDir + "Behav_GRET_Run" + Run + "_"+ Sub+"_StimONFrames-"+PT+"_"+Gender+"_"+Handedness+".bhv"; 00263 WrightResults2File(BehaveFileName,IsCorrect, RT, SubResp, Correct_Response, NumOfTrials); 00264 00265 d->clearScreen(); 00266 d->displayText("Experiment complete. Thank you!"); 00267 d->waitForKey(); 00268 00269 // stop all our ModelComponents 00270 manager.stop(); 00271 00272 // all done! 00273 return 0; 00274 00275 } 00276 00277 00278 // ###################################################################### 00279 /* So things look consistent in everyone's emacs... */ 00280 /* Local Variables: */ 00281 /* indent-tabs-mode: nil */ 00282 /* End: */ 00283 00284 // ###################################################################### 00285 char waitForResp(double WaitTime, double StartMeasure, *char keys, int NumOfKeys) 00286 { 00287 // clear the input buffer before we get started if doWait is set to true 00288 while (checkForKey() != -1) ; 00289 00290 double Now=StartMeasure; 00291 pushEventBegin("waitForResp"); 00292 SDL_Event event; 00293 int Stop=0; 00294 00295 do { 00296 00297 Now = d->getTimerValue() ; 00298 SDL_PollEvent(&event); 00299 if (event.type == SDL_KEYDOWN){ 00300 00301 for (aa=0; aa<NumOfKeys; aa ++){ if ((char(event.key.keysym.unicode))==keys[aa]) {Stop=1}} 00302 } 00303 00304 } while (!Stop && (Now-StartMeasure)<WaitTime); 00305 00306 if event.type==SDL_KEYDOWN{ 00307 00308 int key = event.key.keysym.unicode; 00309 char c; if (key >= 32 && key < 128) c = char(key); else c = '?'; 00310 pushEventEnd(sformat("waitForResp - got %d (%c)", key, c)); 00311 00312 // abort if it was ESC: 00313 if (key == 27) LFATAL("Aborting on [ESC] key"); 00314 00315 return c; 00316 00317 }else{ return '0';} 00318 00319 } 00320 00321 int WrightResults2File(string FileName,int* IsCorrect, double* RT,char* SubResp, char* CorrectResp, int NumOfTrials){ 00322 /* function wrights the behavioral results of Mark's Geon Relations ET 00323 * experimnt into a text file */ 00324 00325 string ExpDir="/lab/ilab19/geonexp/GRET/Data/"; 00326 FileName=ExpDir+FileName; 00327 const char *FileNameP=FileName.c_str(); 00328 FILE * pFile; 00329 pFile = fopen (FileNameP,"w"); 00330 00331 00332 00333 00334 int ii; 00335 00336 for (ii=0; ii<NumOfTrials; ii ++){ 00337 fprintf(pFile, "%i %f %c %c \n", IsCorrect[ii], RT[ii], SubResp[ii], CorrectResp[ii]); 00338 00339 } 00340 00341 fclose (pFile); 00342 00343 return 0; 00344 00345 00346 00347 00348 00349 00350 }