00001 /*!@file AppPsycho/psychoWM.C Psychophysics test to measure the influence of eyemovement on memory task performance */ 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/psychoWMS-C.C $ 00035 // $Id: psychoWMS-C.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 "GameBoard/basic-graphics.H" 00050 #include <sys/types.h> 00051 #include <dirent.h> 00052 #include <errno.h> 00053 #include <vector> 00054 #include <string> 00055 #include <iostream> 00056 #include <SDL/SDL.h> 00057 #include <SDL/SDL_image.h> 00058 #include <stdio.h> 00059 #include <stdlib.h> 00060 #include <sstream> 00061 #include <time.h> 00062 #include "Image/DrawOps.H" 00063 #include "GameBoard/resize.h" 00064 #include <iostream> 00065 #include <fstream> 00066 #include <set> 00067 #include <algorithm> 00068 #include <ctime> 00069 00070 #ifndef INVT_HAVE_LIBSDL_IMAGE 00071 #include <cstdio> 00072 int main() 00073 { 00074 fprintf(stderr, "The SDL_image library must be installed to use this program\n"); 00075 return 1; 00076 } 00077 00078 #else 00079 00080 00081 00082 using namespace std; 00083 00084 // ###################################################################### 00085 00086 ModelManager manager("Psycho-Concurrent-Digit"); 00087 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager)); 00088 map<uint,uint> testMap ; 00089 map<string,string> argMap ; 00090 map<string,vector<SDL_Rect*>*> clipsmap; 00091 00092 ////////////////////////////////////////////// 00093 // a functionf for stringigying things 00094 ////////////////////////////////////////////// 00095 template <class T> std::string stringify(T i) 00096 { 00097 ostringstream o ; 00098 o << i ; 00099 return o.str(); 00100 } 00101 00102 00103 double getAvarage(vector<long> v){ 00104 double f = 0.0 ; 00105 for( uint i = 0 ; i < v.size() ; i++ ){ 00106 f += v[i] ; 00107 } 00108 if (v.size()!=0) return f/v.size() ; 00109 return -1 ; 00110 } 00111 00112 double getVariance(vector<long> v){ 00113 double m = getAvarage(v); 00114 double var = 0.0 ; 00115 for( uint i = 0 ; i < v.size(); i++ ){ 00116 var += (v[i]-m)*(v[i]-m) ; 00117 } 00118 if (v.size()!=0) return var/v.size() ; 00119 return -1 ; 00120 } 00121 00122 00123 00124 00125 //////////////////////////////////////////////////////////////// 00126 ////This is our button factory 00127 //////////////////////////////////////////////////////////////// 00128 SDL_Surface* getButtonImage(string label , PixRGB<byte> txtcolor=PixRGB<byte>(0,0,0) , PixRGB<byte> bgcolor=PixRGB<byte>(255,255,255) ,Point2D<int> size = Point2D<int>(100,100) ,PixRGB<byte> bordercolor=PixRGB<byte>(0,0,0) , int border=3){ 00129 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00130 textIm.clear(bgcolor); 00131 writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor); 00132 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00133 Uint32 bc = d->getUint32color(bordercolor); 00134 drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border); 00135 SDL_Surface* blank =getABlankSurface(size.i , size.j); 00136 SDL_Rect clip; 00137 clip.x = 0 ; 00138 clip.y = 0 ; 00139 clip.w = size.i ; 00140 clip.h = size.j ; 00141 apply_surface(0,0,*surf,*blank,clip); 00142 dumpSurface(surf) ; 00143 return blank ; 00144 } 00145 00146 //////////////////////////////////////////////////////////////////////// 00147 ////This is the function for creating the keypad, in fact it generates 00148 ////12 buttons and associates the actions to the region for each button 00149 //////////////////////////////////////////////////////////////////////// 00150 00151 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){ 00152 SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3); 00153 SDL_Rect clip; 00154 clip.x=0; 00155 clip.y=0; 00156 int numofrows = alphabet.size()/3 +1; 00157 if(alphabet.size()%3 != 0 ) numofrows++ ; 00158 int numofcolumns = 3 ; 00159 clip.w= pad->w / numofcolumns ; 00160 clip.h = pad->h / numofrows ; 00161 00162 //keys for 1 to 9 00163 for( int i = 0 ; i < numofrows*3 ; i++){ 00164 SDL_Surface* but ; 00165 if((uint)i < alphabet.size()){ 00166 but = getButtonImage(alphabet.substr(i,1),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3); 00167 }else{ 00168 but = getButtonImage(" ",PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3); 00169 } 00170 00171 SDL_Rect cl ; 00172 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ; 00173 cl.w = clip.w ; 00174 cl.h = clip.h ; 00175 apply_surface( cl.x , cl.y ,*but,*pad,clip); 00176 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ; 00177 dumpSurface(but); 00178 } 00179 SDL_Rect cl1 ; 00180 cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ; 00181 cl1.w = clip.w ; 00182 cl1.h = clip.h ; 00183 buttmap["!"] = cl1 ; 00184 SDL_Surface* but = getButtonImage(string("<-"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3); 00185 apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00186 dumpSurface(but); 00187 SDL_Rect cl2 ; 00188 cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ; 00189 cl2.w = clip.w ; 00190 cl2.h = clip.h ; 00191 buttmap[" "] = cl2 ; 00192 but = getButtonImage(string("spc"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3); 00193 apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00194 dumpSurface(but); 00195 SDL_Rect cl3 ; 00196 cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ; 00197 cl3.w = clip.w ; 00198 cl3.h = clip.h ; 00199 buttmap["*"] = cl3 ; 00200 but = getButtonImage(string("Ok"),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3); 00201 apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00202 dumpSurface(but); 00203 return pad ; 00204 } 00205 00206 00207 00208 00209 /////////////////////////////////////////////////////////////////////////// 00210 /////this function listens to mouse clicks and then finds the region of the screen 00211 /////associated with the action, buttmap is the map of the region, offset is the offset of 00212 /////buttons 00213 /////////////////////////////////////////////////////////////////////////// 00214 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){ 00215 int quit = 0 ; 00216 string s ; 00217 SDL_Event event ; 00218 while( quit!=2 ){ 00219 while( SDL_PollEvent( &event ) ) { 00220 if(event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT ){ 00221 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){ 00222 if(event.button.x >= (it->second).x + offset.i && event.button.x <= (it->second).x + (it->second).w + offset.i && event.button.y >= (it->second).y+ offset.j && event.button.y <= (it->second).y + (it->second).h + offset.j) { 00223 quit = 2 ; 00224 s = it->first ; 00225 break; 00226 } 00227 00228 } 00229 } 00230 00231 } 00232 } 00233 return s ; 00234 00235 } 00236 00237 00238 //////////////////////////////////////////////////// 00239 ////This function creates a virtual keypad, creates a map of buttons 00240 ////and their representation area and listens to the button press and at 00241 ////the end returns the keyed digits 00242 //////////////////////////////////////////////////// 00243 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){ 00244 d->showCursor(true) ; 00245 //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect 00246 map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>(); 00247 //now let's get the keypad surface while we get the actions map to regions 00248 SDL_Surface * keypad = getKeyPad(alphabet,*buttmap); 00249 //this will be the offset of displaying the keypad on the screen 00250 SDL_Rect offset ; 00251 offset.x = (d->getWidth() - keypad->w) /2; 00252 offset.y = (d-> getHeight() - keypad->h) /2; 00253 //now let's display the keypad 00254 d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true); 00255 //this will hold the final string keyed be the subject 00256 string p = string("") ; 00257 //this is a temporary string holding the last action related to the pressed key 00258 string tp = string(""); 00259 //now let's record subject's key press 00260 while( tp.compare("*")!=0 ){ 00261 //this button is actually the display for the current string 00262 SDL_Surface* dp = getButtonImage(p ,PixRGB<byte>(195,60,12) ,PixRGB<byte>(255,255,255) ,Point2D<int>(d->getWidth()/6,d->getHeight() /15) ,PixRGB<byte>(0,25,180) , 4) ; 00263 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ; 00264 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ; 00265 //now let's listen to button events 00266 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ; 00267 dumpSurface(dp) ; 00268 if(tp.compare("!")==0 && p.size()>=0 ) { 00269 if (p.size()>0) p = p.substr(0,p.size()-1) ; 00270 }else{ 00271 if(p.size() < maxl && tp.compare("*")!=0) { 00272 p +=tp ; 00273 } 00274 00275 } 00276 00277 } 00278 buttmap = 0 ; 00279 dumpSurface(keypad) ; 00280 d->clearScreen() ; 00281 return p ; 00282 00283 } 00284 00285 00286 00287 00288 int addArgument(const string st,const string delim="="){ 00289 int i = st.find(delim) ; 00290 argMap[st.substr(0,i)] = st.substr(i+1); 00291 00292 return 0 ; 00293 } 00294 00295 std::string getArgumentValue(string arg){ 00296 return argMap[arg] ; 00297 } 00298 00299 std::string getUsageComment(){ 00300 00301 string com = string("\nlist of arguments : \n"); 00302 00303 com += "\nlogfile=[logfilename.psy] {default = psycho-stroop-concurrent.psy}\n" ; 00304 com += "\nmemo=[a_string_without_white_space]\n"; 00305 com += "\number-range=[x-y](the size of string){default=200-500} \n"; 00306 com += "\nsubject=[subject_name] \n" ; 00307 com += "\ndelay=[>0] (number of micro seconds){default=30000000}\n"; 00308 com += "\ntest-rounds=[>1] (number of tests ) {default=5}\n"; 00309 com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n"; 00310 com += "\nsubtraction-step=[>0] (the subtraction number){default=3} "; 00311 com += "\nball-radius={0>}(radius of the ball){default=-1 which means the ball will be positioned in the given place with the given aspect ration}\n" ; 00312 com += "\nball-position=[x-y](x and y are position of the center of the ball){default is x=w/2 and y=h/2}\n" ; 00313 com += "\nmin-reaction-time=[>0](minimum value for avarage reaction time in microsecond in order to consider a trial valid){default=1000000}\n" ; 00314 com += "\nmax-miss=[>0](maximum misses in a trial in order to be considered as a valid one){default=10}"; 00315 com += "\ninterrupt-time-range=[x-y](this defines a range of uniform radom distribution by which the perceptual interruption happens){default=500000-5000000}\n" ; 00316 com += "\nrgb1=[r-g-b]{default=50-91-255}\n"; 00317 com += "\nrgb2=[r-g-b]{default=89-122-255}\n"; 00318 com += "\nrgb3=[r-g-b]{default=138-159-255}\n"; 00319 return com ; 00320 } 00321 00322 int myCheckForMouseClick() 00323 { 00324 SDL_Event event; 00325 00326 while(SDL_PollEvent(&event)) 00327 { 00328 if (event.type == SDL_MOUSEBUTTONDOWN) 00329 { 00330 if(event.button.button == SDL_BUTTON_LEFT) { 00331 return 1 ; 00332 } 00333 if(event.button.button == SDL_BUTTON_RIGHT) { 00334 return 2 ; 00335 } 00336 00337 } 00338 // ignore other events 00339 } 00340 00341 // there was no event in the event queue: 00342 return -1; 00343 } 00344 00345 00346 00347 int getClick(){ 00348 // while (myCheckForMouseClick() != -1) ; 00349 SDL_Event event; 00350 bool report = false ; 00351 int i = 0; // will be returned if any other button than left or right 00352 do { 00353 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN); 00354 if (event.button.button == SDL_BUTTON_LEFT) { 00355 i = 0 ; 00356 report = true ; 00357 } 00358 if (event.button.button == SDL_BUTTON_RIGHT) { 00359 i = 1 ; 00360 report = true ; 00361 } 00362 00363 }while(!report) ; 00364 00365 return i ; 00366 00367 } 00368 00369 int getAllKindOfClick(){ 00370 // while (myCheckForMouseClick() != -1) ; 00371 SDL_Event event; 00372 bool report = false ; 00373 int i = 0; // will be returned if any other button than left or right 00374 do { 00375 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN); 00376 long st = d->getTimerValue(); 00377 long et = st ; 00378 00379 if (event.button.button == SDL_BUTTON_LEFT) { 00380 i = 0 ; 00381 report = true ; 00382 while( et-st < 300000){ 00383 et = d->getTimerValue() ; 00384 if(myCheckForMouseClick()==1) return 2 ; 00385 } 00386 } 00387 if (event.button.button == SDL_BUTTON_RIGHT) { 00388 i = 1 ; 00389 report = true ; 00390 } 00391 00392 }while(!report) ; 00393 00394 return i ; 00395 00396 } 00397 00398 int getNext(int i){ 00399 00400 int r = 1 ; 00401 if(i == 0 || i == 2) return 1 ; 00402 r = random()%2 ; 00403 if(r == 0) return 0 ; 00404 if(r == 1 ) return 2 ; 00405 return r ; 00406 } 00407 00408 extern "C" int main(const int argc, char** argv) 00409 { 00410 00411 MYLOGVERB = LOG_INFO; // suppress debug messages 00412 //let's push the initial value for the parameters 00413 argMap["experiment"]="subtraction-working-memory"; 00414 argMap["logfile"]="psycho-wm-s-c.psy" ; 00415 argMap["string-size"]="5" ; 00416 argMap["test-rounds"]="5"; 00417 argMap["subject"]="" ; 00418 argMap["memo"]="" ; 00419 argMap["digit-onset"]="10" ; 00420 argMap["number-range"]="200-500"; 00421 argMap["delay"]="30000000" ; 00422 argMap["subtraction-step"]="3" ; 00423 argMap["ball-radius"] = "-1" ; 00424 argMap["ball-position"]="0" ; 00425 argMap["min-reaction-time"]="1000000" ; 00426 argMap["max-miss"]="10" ; 00427 argMap["interrupt-time-range"]= "500000-5000000"; 00428 argMap["mode"]="1"; 00429 argMap["rgb1"]="50-91-255" ; 00430 argMap["rgb2"]="89-122-255" ; 00431 argMap["rgb3"]="138-159-255" ; 00432 00433 manager.addSubComponent(d); 00434 nub::soft_ref<EventLog> el(new EventLog(manager)); 00435 manager.addSubComponent(el); 00436 d->setEventLog(el); 00437 00438 if (manager.parseCommandLine(argc, argv, 00439 "at least one argument needed", 1, -1)==false){ 00440 cout<<getUsageComment()<<endl; 00441 return(1); 00442 } 00443 00444 for(uint i = 0 ; i < manager.numExtraArgs() ; i++){ 00445 addArgument(manager.getExtraArg(i),std::string("=")) ; 00446 } 00447 00448 manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]); 00449 00450 00451 00452 // let's get all our ModelComponent instances started: 00453 manager.start(); 00454 for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ; 00455 // let's display an ISCAN calibration grid: 00456 d->clearScreen(); 00457 d->displayISCANcalib(); 00458 d->waitForMouseClick(); 00459 d->displayText("Here the experiment starts! click to start!"); 00460 d->waitForMouseClick(); 00461 d->clearScreen(); 00462 //let's see in what mode the user like to run the program 00463 00464 int numOfTests = atoi(argMap["test-rounds"].c_str()) ; 00465 int onsetDel = atoi(argMap["digit-onset"].c_str()) ; 00466 long opDelay = atol(argMap["delay"].c_str()); 00467 long min_reaction_time = atol(argMap["min-reaction-time"].c_str()) ; 00468 int in = argMap["number-range"].find("-") ; 00469 int rangeU = atoi( argMap["number-range"].substr(in+1).c_str()) ; 00470 int rangeL = atoi(argMap["number-range"].substr(0,in).c_str()) ; 00471 int step = atoi(argMap["subtraction-step"].c_str()); 00472 int max_miss = atoi(argMap["max-miss"].c_str()); 00473 in = argMap["interrupt-time-range"].find("-") ; 00474 long iub = atol(argMap["interrupt-time-range"].substr(in+1).c_str()); 00475 long ilb = atol(argMap["interrupt-time-range"].substr(0,in).c_str()) ; 00476 //let's count the rounds 00477 int cr = 0 ; 00478 int x = 0 ; int y = 0 ; int rad = 0 ; 00479 if(argMap["ball-position"].compare("0")==0){ 00480 x = d->getWidth()/2 ; 00481 y = d->getHeight() /2 ; 00482 }else{ 00483 int in = argMap["ball-position"].find("-") ; 00484 x = atoi( argMap["ball-position"].substr(in+1).c_str()) ; 00485 y = atoi(argMap["ball-position"].substr(0,in).c_str()) ; 00486 } 00487 00488 if(argMap["ball-radius"].compare("-1") == 0){ 00489 rad = min(min(y-1,d->getHeight()-y-1),min(x,d->getWidth()-x-1)) ; 00490 }else{ 00491 rad = atoi(argMap["ball-radius"].c_str()) ; 00492 rad = min(rad, min(min(y-1,d->getHeight()-y-1),min(x,d->getWidth()-x-1))) ; 00493 } 00494 00495 SDL_Surface* surf1 = getABlankSurface(d->getWidth(),d->getHeight()); 00496 SDL_Surface* surf2 = getABlankSurface(d->getWidth(),d->getHeight()); 00497 SDL_Surface* surf3 = getABlankSurface(d->getWidth(),d->getHeight()); 00498 SDL_Surface* black = getABlankSurface(d->getWidth(),d->getHeight()); 00499 string rgb1 = argMap["rgb1"] ; 00500 string rgb2 = argMap["rgb2"] ; 00501 string rgb3 = argMap["rgb3"] ; 00502 Uint32 color1 = d->getUint32color(PixRGB<byte>(atoi(rgb1.substr(0,rgb1.find_first_of("-")).c_str()), atoi(rgb1.substr(rgb1.find_first_of("-")+1,rgb1.find_last_of("-")-rgb1.find_first_of("-")-1).c_str()), atoi(rgb1.substr(rgb1.find_last_of("-")+1).c_str()))); 00503 Uint32 color2 = d->getUint32color(PixRGB<byte>(atoi(rgb2.substr(0,rgb2.find_first_of("-")).c_str()), atoi(rgb2.substr(rgb2.find_first_of("-")+1,rgb2.find_last_of("-")-rgb2.find_first_of("-")-1).c_str()), atoi(rgb2.substr(rgb2.find_last_of("-")+1).c_str()))); 00504 Uint32 color3 = d->getUint32color(PixRGB<byte>(atoi(rgb3.substr(0,rgb3.find_first_of("-")).c_str()), atoi(rgb3.substr(rgb3.find_first_of("-")+1,rgb3.find_last_of("-")-rgb3.find_first_of("-")-1).c_str()), atoi(rgb3.substr(rgb3.find_last_of("-")+1).c_str()))); 00505 fillCubicRadiant(surf1,color1,x,y,rad) ; 00506 fillCubicRadiant(surf2,color2,x,y,rad) ; 00507 fillCubicRadiant(surf3,color3,x,y,rad) ; 00508 vector<SDL_Surface*> surfVector; 00509 surfVector.push_back(surf1) ; 00510 surfVector.push_back(surf2) ; 00511 surfVector.push_back(surf3) ; 00512 SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ; 00513 if(argMap["mode"].compare("2")==0){ 00514 while( cr <numOfTests ){ 00515 00516 vector<long> reactionTimes ; 00517 int missed = 0 ; 00518 d->pushEvent("**************************************") ; 00519 d->showCursor(true); 00520 d->displayText("click one of the mouse buttons to start!"); 00521 d->waitForMouseClick() ; 00522 d->showCursor(false) ; 00523 int initialNum = rangeL+ random()%(rangeU-rangeL) ; 00524 d->clearScreen() ; 00525 d->displayFixationBlink(); 00526 d->pushEvent("the initial number is: "+stringify(initialNum)) ; 00527 d->displayText(stringify(initialNum),true,0) ; 00528 d->pushEvent("manupulation starts") ; 00529 d->waitFrames(onsetDel) ; 00530 d->clearScreen() ; 00531 long dst = 0 ;//keeps the start of each color set 00532 long det = 0 ;//keeps the current time to be compared with dl 00533 long dl = 0 ;//this is the number of microseconds for a color display 00534 int cs = 0 ;//this is the index of the color presented initially starts from 0 00535 d->displaySDLSurfacePatch(surfVector[cs] , &offs , NULL , -2 , false ,true ) ;//here the first color is set up 00536 dl = ilb+ random() % (iub-ilb);//let's get a value for the the first color display 00537 dst = d->getTimerValue() ;//this is the initial time of display of the first color 00538 det = dst ; 00539 long tst = 0 ;//tst keeps track of the time new color is presented 00540 long tet = 0 ;//after tst tet is sampled from clock to see how long it will take for the subject to respond 00541 long st = d->getTimerValue(); //this will be a sample of clock at the start of the test round 00542 long et = st ;//this is the current time of process if et-st becomes more than opDelay then we should challenge the subject 00543 bool clickFlag = false ; 00544 00545 while( et - st < opDelay ){ 00546 00547 if (det - dst > dl ){//if we get to a point that the color should change 00548 cs = getNext(cs) ;//choose the index of next color 00549 d->displaySDLSurfacePatch(surfVector[cs] , &offs , NULL , -2 , false ,true ) ;//put up the next color 00550 tst = d->getTimerValue() ;//start keeping track of the timer to see how fast the subject will respond 00551 if(clickFlag){ 00552 missed++ ; 00553 d->pushEvent("missed one change"); 00554 } 00555 clickFlag = true ; 00556 dst = tst ; 00557 det = dst ; //let's make sure that a new round is set 00558 dl = ilb+ random() % (iub-ilb);//we get a value for next stop 00559 et= tst ; 00560 } 00561 det = d->getTimerValue() ; 00562 et = det ; 00563 if(clickFlag){// && (myCheckForMouseClick()==1 || myCheckForMouseClick()==2)){ 00564 int c = myCheckForMouseClick() ; 00565 if(c==1 || c==2){ 00566 clickFlag = false ; 00567 tet = d->getTimerValue() ; 00568 d->pushEvent("reaction time :" + stringify(tet-tst)); 00569 reactionTimes.push_back(tet-tst) ; 00570 } 00571 00572 }else{ 00573 myCheckForMouseClick() ;//let's get rid of the queue of the non-related events including the wrong clicks 00574 } 00575 00576 } 00577 d->pushEvent("manipulation ends") ; 00578 d->clearScreen(); 00579 string answer = getDigitSequenceFromSubject("0123456789" , 3); 00580 d->pushEvent("the reported number: "+answer); 00581 int finalNum = atoi(answer.c_str()) ; 00582 d->pushEvent("number of operations: "+stringify((initialNum-finalNum)/step)); 00583 d->pushEvent("avarage reaction time : "+ stringify(getAvarage(reactionTimes))) ; 00584 d->pushEvent("number of missed events : "+stringify(missed)); 00585 d->pushEvent("number of caught events : "+stringify(reactionTimes.size())) ; 00586 if(missed < max_miss && getAvarage(reactionTimes)<= min_reaction_time ){ 00587 cr++; 00588 d->pushEvent("valid trial"); 00589 }else{ 00590 if(missed >= max_miss) { 00591 d->displayText("Trial failed, too many events missed! Click to start over!"); 00592 d->waitForMouseClick(); 00593 } 00594 if(getAvarage(reactionTimes) > min_reaction_time){ 00595 d->displayText("Trial failed, reaction slower than limit! Click to start over!"); 00596 d->waitForMouseClick(); 00597 } 00598 d->pushEvent("invalid trial"); 00599 } 00600 } 00601 } 00602 00603 if(argMap["mode"].compare("1")==0){ 00604 while( cr <numOfTests ){ 00605 00606 vector<long> reactionTimes ; 00607 int missed = 0 ; 00608 d->pushEvent("**************************************") ; 00609 d->showCursor(true); 00610 d->displayText("click one of the mouse buttons to start!"); 00611 d->waitForMouseClick() ; 00612 d->showCursor(false) ; 00613 d->clearScreen() ; 00614 d->displayFixationBlink(); 00615 d->pushEvent("manupulation starts") ; 00616 //d->waitFrames(onsetDel) ; 00617 d->clearScreen() ; 00618 long dst = 0 ;//keeps the start of each color set 00619 long det = 0 ;//keeps the current time to be compared with dl 00620 long dl = 0 ;//this is the number of microseconds for a color display 00621 int cs = 0 ;//this is the index of the color presented initially starts from 0 00622 d->displaySDLSurfacePatch(surfVector[cs] , &offs , NULL , -2 , false ,true ) ;//here the first color is set up 00623 dl = ilb+ random() % (iub-ilb);//let's get a value for the the first color display 00624 dst = d->getTimerValue() ;//this is the initial time of display of the first color 00625 det = dst ; 00626 long tst = 0 ;//tst keeps track of the time new color is presented 00627 long tet = 0 ;//after tst tet is sampled from clock to see how long it will take for the subject to respond 00628 long st = d->getTimerValue(); //this will be a sample of clock at the start of the test round 00629 long et = st ;//this is the current time of process if et-st becomes more than opDelay then we should challenge the subject 00630 bool clickFlag = false ; 00631 00632 while( et - st < opDelay ){ 00633 00634 if (det - dst > dl ){//if we get to a point that the color should change 00635 cs = getNext(cs) ;//choose the index of next color 00636 d->displaySDLSurfacePatch(surfVector[cs] , &offs , NULL , -2 , false ,true ) ;//put up the next color 00637 tst = d->getTimerValue() ;//start keeping track of the timer to see how fast the subject will respond 00638 if(clickFlag){ 00639 missed++ ; 00640 d->pushEvent("missed one change"); 00641 } 00642 clickFlag = true ; 00643 dst = tst ; 00644 det = dst ; //let's make sure that a new round is set 00645 dl = ilb+ random() % (iub-ilb);//we get a value for next stop 00646 et= tst ; 00647 } 00648 det = d->getTimerValue() ; 00649 et = det ; 00650 if(clickFlag){// && (myCheckForMouseClick()==1 || myCheckForMouseClick()==2)){ 00651 int c = myCheckForMouseClick() ; 00652 if(c==1 || c==2){ 00653 clickFlag = false ; 00654 tet = d->getTimerValue() ; 00655 d->pushEvent("reaction time :" + stringify(tet-tst)); 00656 reactionTimes.push_back(tet-tst) ; 00657 } 00658 00659 }else{ 00660 myCheckForMouseClick() ;//let's get rid of the queue of the non-related events including the wrong clicks 00661 } 00662 00663 } 00664 d->pushEvent("manipulation ends") ; 00665 d->clearScreen(); 00666 d->pushEvent("avarage reaction time : "+ stringify(getAvarage(reactionTimes))) ; 00667 d->pushEvent("number of missed events : "+stringify(missed)); 00668 d->pushEvent("number of caught events : "+stringify(reactionTimes.size())) ; 00669 if(missed < max_miss && getAvarage(reactionTimes)<= min_reaction_time ){ 00670 cr++; 00671 d->pushEvent("valid trial"); 00672 }else{ 00673 if(missed >= max_miss) { 00674 d->displayText("Trial failed, too many events missed! Click to start over!"); 00675 d->waitForMouseClick(); 00676 } 00677 if(getAvarage(reactionTimes) > min_reaction_time){ 00678 d->displayText("Trial failed, reaction slower than limit! Click to start over!"); 00679 d->waitForMouseClick(); 00680 } 00681 d->pushEvent("invalid trial"); 00682 } 00683 00684 } 00685 } 00686 dumpSurface(surf1) ; 00687 dumpSurface(surf2) ; 00688 dumpSurface(surf3) ; 00689 dumpSurface(black) ; 00690 d->clearScreen(); 00691 d->displayText("Experiment complete. Thank you!"); 00692 d->waitForMouseClick(); 00693 00694 // stop all our ModelComponents 00695 manager.stop(); 00696 00697 00698 // all done! 00699 return 0; 00700 } 00701 00702 #endif // INVT_HAVE_LIBSDL_IMAGE 00703