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/psychoWM.C $ 00035 // $Id: psychoWM.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 bool itIsInThere(int x , vector<int> bag){ 00123 for( uint i=0 ; i < bag.size(); i++ ){ 00124 if(x == bag[i]) return true ; 00125 } 00126 return false ; 00127 } 00128 00129 00130 //////////////////////////////////////////////////////////////////// 00131 //// gets a string as the argument and returns a string composed of 00132 //// characters of the first string sorted in the ascending order 00133 /////////////////////////////////////////////////////////////////// 00134 string ascSort(string st) 00135 { 00136 string res = "" ; 00137 vector<string> v = vector<string>(); 00138 for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ; 00139 00140 std::sort(v.begin(), v.end()); 00141 00142 for ( uint i = 0 ; i < v.size() ; i++ ){ 00143 res += v[i] ; 00144 } 00145 return res; 00146 } 00147 00148 00149 00150 //////////////////////////////////////////////////////////////////// 00151 //// gets a string as the argument and returns a string composed of 00152 //// characters of the first string sorted in the descending order 00153 /////////////////////////////////////////////////////////////////// 00154 string desSort(string st) 00155 { 00156 string res = "" ; 00157 vector<string> v = vector<string>(); 00158 for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ; 00159 std::sort(v.begin(), v.end()); 00160 std::reverse(v.begin(), v.end()); 00161 for ( uint i = 0 ; i < v.size() ; i++ ){ 00162 res += v[i] ; 00163 } 00164 return res; 00165 } 00166 00167 00168 ///////////////////////////////////////////////////////////// 00169 //this function checks how many subblocks of the sorted string can be found in 00170 //original string, the bigger chunks found the bigger number will be return 00171 //////////////////////////////////////////////////////////// 00172 00173 int mydist(string str , string sorted){ 00174 size_t found; 00175 int m = 0 ; 00176 for(uint i = 2 ; i <= sorted.size() ; i++ ){ 00177 for(uint j = 0 ; j <= sorted.size()-i ; j++ ) { 00178 found = str.find(sorted.substr(j,i)); 00179 if (found!=string::npos) m += i ; 00180 } 00181 } 00182 return m ; 00183 } 00184 00185 ///////////////////////////////////////////////////////////// 00186 //this function checks out the difficulty of sorting the string assigns a number which 00187 //reflects how many moves are needed for sorting, 00188 //////////////////////////////////////////////////////////// 00189 00190 int getDisMetric(string st){ 00191 int m = 0 ; 00192 size_t found; 00193 string asString = ascSort(st) ; 00194 for(uint i = 0 ; i < st.size() ; i++ ){ 00195 found = asString.find(st.substr(i,1)); 00196 m += abs((int)i-int(found)) ; 00197 } 00198 00199 return m- 2*mydist(st,asString) ; 00200 } 00201 00202 00203 00204 //////////////////////////////////////////////////////// 00205 ///// simply generates a sequence of digits with given alphabet with length of l with given threshold, if the given threshold is not achieved the best answer with 00206 //highest metric value in 1000000 times try will be returned 00207 //////////////////////////////////////////////////////// 00208 00209 string getARandomString(uint l, string alphabet="0123456789" , int thresh=0){ 00210 00211 string test = string("") ; 00212 string retString ; 00213 int maxDist = -1000000; 00214 int it = 0 ; 00215 int d = 0 ; 00216 do{ 00217 test = "" ; 00218 string tp = string("") ; 00219 vector<int> pickedones = vector<int>() ; 00220 for(uint i = 0 ; i < l ; i++){ 00221 int nd; 00222 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ; 00223 pickedones.push_back(nd); 00224 tp = alphabet.substr(nd,1) ; 00225 test += tp ; 00226 } 00227 it++ ; 00228 d = getDisMetric(test); 00229 maxDist=max(maxDist,d) ; 00230 if (d==maxDist) retString = test ; 00231 00232 }while( maxDist<thresh && it < 1000000); 00233 00234 return retString ; 00235 } 00236 00237 /////////////////////////////////////////////////////// 00238 //this function is not called in this program, but it generates a random string and it will show it in 00239 //a random place on the screen. 00240 ////////////////////////////////////////////////////// 00241 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10 ){ 00242 d->clearScreen() ; 00243 vector<int> pickedones = vector<int>() ; 00244 string test = string("") ; 00245 string tp = string("") ; 00246 for(uint i = 0 ; i < l ; i++){ 00247 int nd; 00248 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ; 00249 pickedones.push_back(nd); 00250 tp = alphabet.substr(nd,1) ; 00251 test += tp ; 00252 } 00253 d->displayText(test,true,0) ; 00254 d->waitFrames(displayFrame) ; 00255 d->clearScreen() ; 00256 return test ; 00257 } 00258 00259 00260 //////////////////////////////////////////////////////// 00261 ///////this will change the order of elements in a vector to a random order 00262 //////////////////////////////////////////////////////// 00263 void scramble(vector<string>& v){ 00264 vector<string> tv = vector<string>() ; 00265 while(v.size()>0){ 00266 tv.push_back(v[0]); 00267 v.erase(v.begin()); 00268 } 00269 int i = 0 ; 00270 while(tv.size()>0){ 00271 i = rand()%tv.size() ; 00272 v.push_back(tv[i]); 00273 tv.erase(tv.begin()+i); 00274 } 00275 } 00276 00277 00278 //////////////////////////////////////////////////////////////// 00279 ////This is our button factory 00280 //////////////////////////////////////////////////////////////// 00281 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){ 00282 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00283 textIm.clear(bgcolor); 00284 writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor); 00285 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00286 Uint32 bc = d->getUint32color(bordercolor); 00287 drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border); 00288 SDL_Surface* blank =getABlankSurface(size.i , size.j); 00289 SDL_Rect clip; 00290 clip.x = 0 ; 00291 clip.y = 0 ; 00292 clip.w = size.i ; 00293 clip.h = size.j ; 00294 apply_surface(0,0,*surf,*blank,clip); 00295 dumpSurface(surf) ; 00296 return blank ; 00297 } 00298 00299 //////////////////////////////////////////////////////////////////////// 00300 ////This is the function for creating the keypad, in fact it generates 00301 ////12 buttons and associates the actions to the region for each button 00302 //////////////////////////////////////////////////////////////////////// 00303 00304 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){ 00305 SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3); 00306 SDL_Rect clip; 00307 clip.x=0; 00308 clip.y=0; 00309 int numofrows = alphabet.size()/3 +1; 00310 if(alphabet.size()%3 != 0 ) numofrows++ ; 00311 int numofcolumns = 3 ; 00312 clip.w= pad->w / numofcolumns ; 00313 clip.h = pad->h / numofrows ; 00314 00315 //keys for 1 to 9 00316 for( int i = 0 ; i < numofrows*3 ; i++){ 00317 SDL_Surface* but ; 00318 if((uint)i < alphabet.size()){ 00319 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); 00320 }else{ 00321 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); 00322 } 00323 00324 SDL_Rect cl ; 00325 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ; 00326 cl.w = clip.w ; 00327 cl.h = clip.h ; 00328 apply_surface( cl.x , cl.y ,*but,*pad,clip); 00329 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ; 00330 dumpSurface(but); 00331 } 00332 SDL_Rect cl1 ; 00333 cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ; 00334 cl1.w = clip.w ; 00335 cl1.h = clip.h ; 00336 buttmap["!"] = cl1 ; 00337 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); 00338 apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00339 dumpSurface(but); 00340 SDL_Rect cl2 ; 00341 cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ; 00342 cl2.w = clip.w ; 00343 cl2.h = clip.h ; 00344 buttmap[" "] = cl2 ; 00345 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); 00346 apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00347 dumpSurface(but); 00348 SDL_Rect cl3 ; 00349 cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ; 00350 cl3.w = clip.w ; 00351 cl3.h = clip.h ; 00352 buttmap["*"] = cl3 ; 00353 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); 00354 apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip); 00355 dumpSurface(but); 00356 return pad ; 00357 } 00358 00359 00360 00361 00362 /////////////////////////////////////////////////////////////////////////// 00363 /////this function listens to mouse clicks and then finds the region of the screen 00364 /////associated with the action, buttmap is the map of the region, offset is the offset of 00365 /////buttons 00366 /////////////////////////////////////////////////////////////////////////// 00367 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){ 00368 int quit = 0 ; 00369 string s ; 00370 SDL_Event event ; 00371 while( quit!=2 ){ 00372 while( SDL_PollEvent( &event ) ) { 00373 if(event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT ){ 00374 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){ 00375 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) { 00376 quit = 2 ; 00377 s = it->first ; 00378 break; 00379 } 00380 00381 } 00382 } 00383 00384 } 00385 } 00386 return s ; 00387 00388 } 00389 00390 00391 //////////////////////////////////////////////////// 00392 ////This function creates a virtual keypad, creates a map of buttons 00393 ////and their representation area and listens to the button press and at 00394 ////the end returns the keyed digits 00395 //////////////////////////////////////////////////// 00396 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){ 00397 d->showCursor(true) ; 00398 //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect 00399 map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>(); 00400 //now let's get the keypad surface while we get the actions map to regions 00401 SDL_Surface * keypad = getKeyPad(alphabet,*buttmap); 00402 //this will be the offset of displaying the keypad on the screen 00403 SDL_Rect offset ; 00404 offset.x = (d->getWidth() - keypad->w) /2; 00405 offset.y = (d-> getHeight() - keypad->h) /2; 00406 //now let's display the keypad 00407 d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true); 00408 //this will hold the final string keyed be the subject 00409 string p = string("") ; 00410 //this is a temporary string holding the last action related to the pressed key 00411 string tp = string(""); 00412 //now let's record subject's key press 00413 while( tp.compare("*")!=0 ){ 00414 //this button is actually the display for the current string 00415 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) ; 00416 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ; 00417 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ; 00418 //now let's listen to button events 00419 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ; 00420 dumpSurface(dp) ; 00421 if(tp.compare("!")==0 && p.size()>=0 ) { 00422 if (p.size()>0) p = p.substr(0,p.size()-1) ; 00423 }else{ 00424 if(p.size() < maxl && tp.compare("*")!=0) { 00425 p +=tp ; 00426 } 00427 00428 } 00429 00430 } 00431 buttmap = 0 ; 00432 dumpSurface(keypad) ; 00433 d->clearScreen() ; 00434 return p ; 00435 00436 } 00437 00438 //and this is the function which creates and displays a mask of randomly positioned numbers 00439 void showMask(int frames, string alphabet="0123456789"){ 00440 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00441 PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128); 00442 PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0); 00443 textIm.clear(bgcolor); 00444 for(int i = 0 ; i < 200 ; i++) 00445 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor); 00446 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00447 SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ; 00448 d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ; 00449 d->waitFrames(frames) ; 00450 d->clearScreen(); 00451 dumpSurface(surf) ; 00452 } 00453 00454 /////////////////////////////////////////////////////////////// 00455 //////gets the test string, answer and the mode and identifies if 00456 //////the answer matches the thing it should be, mode=0 checks if 00457 //////if the answer and test string simply the same, mode=1 matches 00458 //////the answer against the ascending sorted string of the test string 00459 //////mode=2 compares the answer against the descending sorted of 00460 //////the test string 00461 /////////////////////////////////////////////////////////////// 00462 bool isAnswerCorrect(string test , string answer , int mode){ 00463 00464 if(mode == 0 && answer.compare(test)==0) return true ; 00465 00466 if(mode == 1 && answer.compare(ascSort(test))==0) return true ; 00467 00468 if(mode == 2 && answer.compare(desSort(test))==0) return true ; 00469 00470 return false; 00471 } 00472 00473 00474 00475 int addArgument(const string st,const string delim="="){ 00476 int i = st.find(delim) ; 00477 argMap[st.substr(0,i)] = st.substr(i+1); 00478 00479 return 0 ; 00480 } 00481 00482 std::string getArgumentValue(string arg){ 00483 return argMap[arg] ; 00484 } 00485 00486 std::string getUsageComment(){ 00487 00488 string com = string("\nlist of arguments : \n"); 00489 00490 com += "\nlogfile=[logfilename.psy] {default = psycho-stroop-concurrent.psy}\n" ; 00491 com += "\nmemo=[a_string_without_white_space]\n"; 00492 com += "\nstring-size=[>0](the size of string){default=5} \n"; 00493 com += "\nsubject=[subject_name] \n" ; 00494 com += "\ntest-rounds=[>1] (number of tests ) {default=10}\n"; 00495 com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n"; 00496 com += "\nalphabet=[a string of characters](a string of characters){default=0123456789}\n"; 00497 com += "\nmetric-threshold=[>-30 for string of lenght of 5](a string of characters){default=10}\n"; 00498 com += "\nmaintain-prb=[a number between 0 to 1], probability of challenging the subject with a memorization task, default=0.2\n" ; 00499 com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n"; 00500 com += "\ncue-onset-frames=[<0](number of frames to show the cue onset){default=3}\n"; 00501 com += "\nmask=[y/n](whether present a mask after presentation, n for no, y for yes ){default=n}\n" ; 00502 com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n"; 00503 return com ; 00504 } 00505 00506 00507 extern "C" int main(const int argc, char** argv) 00508 { 00509 00510 MYLOGVERB = LOG_INFO; // suppress debug messages 00511 //let's push the initial value for the parameters 00512 argMap["experiment"]="working memory single task - sorting"; 00513 argMap["logfile"]="psycho-wm.psy" ; 00514 argMap["string-size"]="5" ; 00515 argMap["test-rounds"]="10"; 00516 argMap["subject"]="" ; 00517 argMap["memo"]="" ; 00518 argMap["digit-onset"]="10" ; 00519 argMap["alphabet"]="0123456789"; 00520 argMap["metric-threshold"]="10" ; 00521 argMap["maintain-prb"]="0.2" ; 00522 argMap["cue-wait-frames"]="0" ; 00523 argMap["mask"]="n" ; 00524 argMap["mask-onset-frames"]="0"; 00525 argMap["cue-onset-frames"] = "3" ; 00526 00527 manager.addSubComponent(d); 00528 nub::soft_ref<EventLog> el(new EventLog(manager)); 00529 manager.addSubComponent(el); 00530 d->setEventLog(el); 00531 00532 vector<long> correctAnswersTiming; 00533 vector<long> incorrectAnswersTiming; 00534 vector<long> allTiming ; 00535 int correctMemory = 0 ; 00536 int incorrectMemory = 0 ; 00537 if (manager.parseCommandLine(argc, argv, 00538 "at least one argument needed", 1, -1)==false){ 00539 cout<<getUsageComment()<<endl; 00540 return(1); 00541 } 00542 00543 for(uint i = 0 ; i < manager.numExtraArgs() ; i++){ 00544 addArgument(manager.getExtraArg(i),std::string("=")) ; 00545 } 00546 00547 manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]); 00548 00549 00550 00551 // let's get all our ModelComponent instances started: 00552 manager.start(); 00553 for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ; 00554 // let's display an ISCAN calibration grid: 00555 d->clearScreen(); 00556 d->displayISCANcalib(); 00557 d->waitForMouseClick(); 00558 d->displayText("Here the experiment starts! click to start!"); 00559 d->waitForMouseClick(); 00560 d->clearScreen(); 00561 //let's see in what mode the user like to run the program 00562 00563 int numOfTests = atoi(argMap["test-rounds"].c_str()) ; 00564 int stringSize = atoi(argMap["string-size"].c_str()); 00565 int meticThreshold = atoi(argMap["metric-threshold"].c_str()) ; 00566 int onsetDel = atoi(argMap["digit-onset"].c_str()) ; 00567 float memPrb = atof(argMap["maintain-prb"].c_str()) ; 00568 int cue_onset_frames = atoi(argMap["cue-onset-frames"].c_str()) ; 00569 int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ; 00570 int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ; 00571 //let's count the rounds 00572 int cr = 0 ; 00573 while( cr <numOfTests ){ 00574 float mP = (float) rand()/RAND_MAX ; 00575 if(mP > memPrb){ 00576 cr++; 00577 d->pushEvent("**************************************") ; 00578 d->showCursor(true); 00579 d->displayText("click one of the mouse buttons to start!"); 00580 d->waitForMouseClick() ; 00581 d->showCursor(false) ; 00582 string testString ; 00583 testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ; 00584 d->clearScreen() ; 00585 d->displayFixationBlink(); 00586 d->displayText(testString,true,0) ; 00587 d->waitFrames(onsetDel) ; 00588 d->clearScreen() ; 00589 if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]); 00590 if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ; 00591 d->displayRedDotFixation(); 00592 d->waitFrames(cue_onset_frames); 00593 long st = d->getTimerValue() ;//we take this time as the start time of the operation, right after the signal for sorting 00594 d->clearScreen() ; 00595 d->pushEvent("manipulation starts"); 00596 d->pushEvent("the sequence for manipulation is : "+testString) ; 00597 d->waitForMouseClick() ; 00598 long et = d->getTimerValue();//we take this time as the end time of the operation, right after recieving the mouse click 00599 d->pushEvent("manipulation ends") ; 00600 d->pushEvent("manipulation time:"+stringify(et-st)); 00601 allTiming.push_back(et-st); 00602 //let's register subject's answer 00603 string answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size()); 00604 d->pushEvent("subject keyed : "+answer); 00605 //and let's see if the suject was correct 00606 bool af = false ; 00607 af = isAnswerCorrect(testString,answer,1); 00608 if(af){ 00609 d->pushEvent("answer was correct"); 00610 correctAnswersTiming.push_back(et-st) ; 00611 }else{ 00612 d->pushEvent("answer was incorrect"); 00613 incorrectAnswersTiming.push_back(et-st); 00614 } 00615 00616 }else{ 00617 d->pushEvent("+++++++++++++++++++++++++++++++++++++++") ; 00618 d->showCursor(true); 00619 d->displayText("click one of the mouse buttons to start!"); 00620 d->waitForMouseClick() ; 00621 d->showCursor(false) ; 00622 string testString ; 00623 testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ; 00624 d->clearScreen() ; 00625 d->displayFixationBlink(); 00626 d->displayText(testString,true,0) ; 00627 // int x = 9*d->getWidth()/20 + rand()%(d->getWidth()/10); 00628 // int y = 9*d->getHeight()/20 + rand()%(d->getHeight()/10) ; 00629 // d->displayText(testString,Point2D<int>(x,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ; 00630 d->waitFrames(onsetDel) ; 00631 d->clearScreen() ; 00632 if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]); 00633 if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ; 00634 d->displayFixationBlink(d->getWidth()/2,d->getHeight()/2,1,3); 00635 d->pushEvent("the memorization sequence is : "+testString) ; 00636 00637 d->pushEvent("subject is being challenged for simple momorization"); 00638 string answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size()); 00639 00640 bool af = false ; 00641 af = isAnswerCorrect(testString,answer,0); 00642 d->pushEvent("subject keyed : "+answer); 00643 if(af){ 00644 d->pushEvent("correct answer"); 00645 correctMemory++ ; 00646 }else{ 00647 d->pushEvent("incorrect answer"); 00648 incorrectMemory++ ; 00649 } 00650 00651 } 00652 } 00653 d->pushEvent("total number of memory trials :"+stringify(correctMemory+incorrectMemory)) ; 00654 d->pushEvent("number of correct memory recall : "+ stringify(correctMemory)) ; 00655 d->pushEvent("total number of trials :"+ stringify(allTiming.size())) ; 00656 d->pushEvent("number of correct answers :" + stringify(correctAnswersTiming.size())); 00657 d->pushEvent("number of incorrect answers :"+ stringify(incorrectAnswersTiming.size())) ; 00658 d->pushEvent("avarage time for respond :"+ stringify(getAvarage(allTiming))); 00659 d->pushEvent("variance of respond :"+ stringify(getVariance(allTiming))); 00660 d->pushEvent("avarage time for correct answers "+stringify(getAvarage(correctAnswersTiming))) ; 00661 d->pushEvent("variance of correct responds :"+ stringify(getVariance(correctAnswersTiming))); 00662 d->clearScreen(); 00663 d->displayText("Experiment complete. Thank you!"); 00664 d->waitForMouseClick(); 00665 00666 // stop all our ModelComponents 00667 manager.stop(); 00668 00669 00670 // all done! 00671 return 0; 00672 } 00673 00674 #endif // INVT_HAVE_LIBSDL_IMAGE 00675