00001 /*!@file AppPsycho/psycho-concurrent-still.C Psychophysics display of still for concurrent task images */ 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-concurrent-still.C $ 00035 // $Id: psycho-concurrent-still.C 10794 2009-02-08 06:21:09Z itti $ 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 00065 00066 00067 00068 #ifndef INVT_HAVE_LIBSDL_IMAGE 00069 #include <cstdio> 00070 int main() 00071 { 00072 fprintf(stderr, "The SDL_image library must be installed to use this program\n"); 00073 return 1; 00074 } 00075 00076 #else 00077 00078 00079 00080 using namespace std; 00081 // ###################################################################### 00082 ModelManager manager("Psycho-Concurrent"); 00083 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager)); 00084 map<uint,uint> testMap ; 00085 map<string,string> argMap ; 00086 00087 00088 ////////////////////////////////////////////// 00089 00090 // a functionf for stringigying things 00091 template <class T> std::string stringify(T i) 00092 { 00093 ostringstream o ; 00094 o << i ; 00095 return o.str(); 00096 } 00097 00098 ////////////////////////////////////////////// 00099 void getMouseEvent(){ 00100 bool quit = false ; 00101 SDL_Event event ; 00102 while( quit == false ) { 00103 while( SDL_PollEvent( &event ) ) { 00104 if( event.type == SDL_MOUSEBUTTONDOWN ) { quit = true; } 00105 } 00106 } 00107 } 00108 //pushes back the name of files in the directory into the given vector 00109 int getdir (string dir, vector<string> &files) 00110 { 00111 DIR *dp; 00112 struct dirent *dirp; 00113 if((dp = opendir(dir.c_str())) == NULL) { 00114 cout << "Error(" << errno << ") opening " << dir << endl; 00115 return errno; 00116 } 00117 string fn = "" ; 00118 size_t found; 00119 string extension = "" ; 00120 while ((dirp = readdir(dp)) != NULL) { 00121 fn = string(dirp->d_name) ; 00122 found = fn.find_last_of("."); 00123 if(found > 0 && found <1000){ 00124 extension = fn.substr(found) ; 00125 if(extension.compare(".png")== 0 || extension.compare(".jpg")==0 ) 00126 files.push_back(dir+"/"+fn); 00127 } 00128 } 00129 closedir(dp); 00130 return 0; 00131 } 00132 ////////////////////////////////////////////// 00133 //inputs: l ; number of words to be shown (1..5) 00134 // :delay; delay between displaying words in number of frames 00135 00136 void colorStroopTask(const uint l,const int delay = 10){ 00137 //0 stands for white 00138 //1 stands for yellow 00139 //2 stands for red 00140 //3 stands for green 00141 //4 stands for blue 00142 vector<uint> word = vector<uint>() ; 00143 vector<uint> color = vector<uint>() ; 00144 for(uint i = 0 ; i < 5 ; i++){ 00145 word.push_back(i) ; 00146 color.push_back(i) ; 00147 } 00148 for(uint i = 0 ; i < l ; i++){ 00149 int wi = rand() % word.size() ; 00150 int ci = rand() % color.size() ; 00151 //let's make sure that the color word and color are not the same 00152 while( ci==wi ){ 00153 ci = rand() % color.size() ; 00154 } 00155 00156 testMap[word[wi]] = color[ci] ; 00157 word.erase(word.begin()+wi); 00158 color.erase(color.begin()+ci) ; 00159 } 00160 00161 PixRGB<byte> white(255, 255, 255); 00162 PixRGB<byte> yellow(255, 255, 0); 00163 PixRGB<byte> red(255,0,0); 00164 PixRGB<byte> green(0,255,0) ; 00165 PixRGB<byte> blue(0,0,255) ; 00166 SDL_Surface* blank = getABlankSurface(d->getWidth(),d->getHeight()) ; 00167 for(map<uint,uint>:: iterator it = testMap.begin() ; it != testMap.end() ; ++it ){ 00168 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00169 textIm.clear(PixRGB<byte>(0, 0, 0)); 00170 int x = rand()% (d->getWidth()-60) ; 00171 int y = rand() % (d-> getHeight() - 60); 00172 string myword = "" ; 00173 PixRGB<byte> mycolor(0,0,0) ; 00174 switch (it->first){ 00175 case 0 : myword = "white"; break ; 00176 case 1 : myword = "yellow" ; break ; 00177 case 2 : myword = "red" ; break ; 00178 case 3 : myword = "green" ; break ; 00179 case 4 : myword = "blue" ; break ; 00180 } 00181 00182 switch ( it->second){ 00183 case 0 : mycolor = white ; break ; 00184 case 1 : mycolor = yellow ; break ; 00185 case 2 : mycolor = red ; break ; 00186 case 3 : mycolor = green; break ; 00187 case 4 : mycolor = blue ; break ; 00188 } 00189 writeText(textIm, Point2D<int>(x,y), myword.c_str(),mycolor, PixRGB<byte>(0,0,0), SimpleFont::FIXED(10), true); 00190 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00191 d->pushEvent(string("stroop test: ")+stringify(it->first)+" " +stringify(it->second)) ; 00192 d->pushEvent(std::string("image is going up")); 00193 d->displaySurface(surf, -2); 00194 d->waitFrames(delay); 00195 d->pushEvent(std::string("image is going down")); 00196 d->displaySurface(blank, -2); 00197 dumpSurface(surf) ; 00198 } 00199 dumpSurface(blank); 00200 } 00201 ///////////////////////////////////////////// 00202 //this function poses the question based on the testMap previously set,at the end the testMap will be cleared 00203 void colorStroopQuiz(){ 00204 //since the subject is supposed to interact with the mouse we make it appear! 00205 d->showCursor(true); 00206 map<uint,string> abrMap ; 00207 abrMap[2] = "red" ; 00208 abrMap[4] = "blue" ; 00209 abrMap[3] = "green" ; 00210 abrMap[0] = "white" ; 00211 abrMap[1] = "yellow" ; 00212 int rd = rand()%testMap.size() ; 00213 int c = -1 ; 00214 uint word = 0 ; 00215 uint color= 0 ; 00216 00217 for(map<uint,uint>:: iterator it = testMap.begin() ; it != testMap.end() ; ++it ){ 00218 c++ ; 00219 if(c==rd){ 00220 word = it->first; 00221 color = it->second; 00222 } 00223 } 00224 string disWord = abrMap[word] ; 00225 string disColor = abrMap[color] ; 00226 00227 //we toss a coin to see what question to ask; asking the color of a word (rd=0) or the word in a give color (rd=1) 00228 rd = rand()%2 ; 00229 Uint32 white = d->getUint32color(PixRGB<byte>(255, 255, 255)); 00230 Uint32 yellow = d->getUint32color(PixRGB<byte>(255, 255, 0)); 00231 Uint32 red = d->getUint32color(PixRGB<byte>(255,0,0)); 00232 Uint32 green = d->getUint32color(PixRGB<byte>(0,255,0)); 00233 Uint32 blue = d->getUint32color(PixRGB<byte>(0,0,255)); 00234 if(rd == 0){ 00235 //let's ask the question 00236 d->pushEvent("asked "+stringify(word)+":-") ; 00237 d->displayText("'"+disWord+"'",true,1); 00238 //this will serve as the panle for showing the buttons 00239 SDL_Surface* blank =getABlankSurface(d->getWidth()/2 , d->getHeight()/10); 00240 fillRectangle(blank , white , 0 , 0 , blank->w/5 , blank->h ); 00241 fillRectangle(blank , yellow , (blank->w)/5 ,0 , (blank->w)/5 , blank->h ); 00242 fillRectangle(blank , red , 2*(blank->w)/5 ,0 , (blank->w)/5 , blank->h ); 00243 fillRectangle(blank , green , 3*(blank->w)/5 ,0 , (blank->w)/5 , blank->h ); 00244 fillRectangle(blank , blue , 4*(blank->w)/5 ,0 , (blank->w)/5 , blank->h ); 00245 //this is the offset of buttons panel 00246 SDL_Rect offset; 00247 offset.x = (d->getWidth() - blank->w) /2; 00248 offset.y = (d-> getHeight() - blank->h) /2; 00249 d->pushEvent("the answer panel is going up"); 00250 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00251 bool quit = false ; 00252 SDL_Event event ; 00253 int mx = 0 ; //the x location of mouse pointer at click time 00254 int my = 0 ; //the y location of mouse pointer at click time 00255 00256 //in this block we will wait until left burron is down 00257 while( quit == false ) { 00258 while( SDL_PollEvent( &event ) ) { 00259 if( event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT 00260 && event.button.x > offset.x && event.button.x <= offset.x + blank->w 00261 && event.button.y > offset.y && event.button.y <= offset.y + blank->h 00262 ) { 00263 quit = true; 00264 mx = event.button.x ; 00265 my = event.button.y ; 00266 } 00267 } 00268 } 00269 //let's save the answer in the logfile! 00270 d->pushEvent("answered: "+ stringify((mx - offset.x) / ((blank->w)/5)) ) ; 00271 if((mx - offset.x) / ((blank->w)/5) == (int)color) { 00272 d->pushEvent("correct answer") ; 00273 }else{ 00274 d->pushEvent("incorrect answer") ; 00275 } 00276 dumpSurface(blank) ; 00277 00278 }else{ 00279 //let's ask the question 00280 d->pushEvent("asked -:"+stringify(color)) ; 00281 SDL_Surface* cblank =getABlankSurface((d->getWidth())/10 , d->getHeight()/10); 00282 Uint32 cl = 0 ; 00283 switch(color){ 00284 case 0 : cl = white ;break ; 00285 case 1 : cl = yellow ; break ; 00286 case 2 : cl = red ; break ; 00287 case 3 : cl = green ; break ; 00288 case 4 : cl = blue ; break ; 00289 } 00290 fillRectangle(cblank , cl , 0 , 0 , cblank->w , cblank->h ); 00291 SDL_Rect coffset; 00292 coffset.x = (d->getWidth() - cblank->w) /2; 00293 coffset.y = (d-> getHeight() - cblank->h) /6; 00294 d->displaySDLSurfacePatch(cblank , &coffset,NULL , -2,false, true); 00295 //d->displayText("what word was written in '"+disColor+"'? ",true,1); 00296 //this is a panel for the buttons 00297 SDL_Surface* blank =getABlankSurface(3*(d->getWidth())/4 , d->getHeight()/10); 00298 //and this is a scrap image for writing lables of the buttons 00299 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00300 textIm.clear(PixRGB<byte>(255, 255, 255)); 00301 writeText(textIm, Point2D<int>(10,10), "white"); 00302 writeText(textIm, Point2D<int>(10,110), "yellow"); 00303 writeText(textIm, Point2D<int>(10,210), "red"); 00304 writeText(textIm, Point2D<int>(10,310), "green"); 00305 writeText(textIm, Point2D<int>(10,410), "blue"); 00306 //now let's make a SDL_Surface out of our scrap image 00307 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00308 //we will cut out different clips from the scrap image 00309 SDL_Rect clip; 00310 clip.x = 0 ; 00311 clip.y = 0 ; 00312 clip.w = (blank->w)/5 - 2 ; 00313 clip.h =blank->h ; 00314 //and apply it to the button panel 00315 apply_surface(0,0,*surf,*blank,clip); 00316 clip.y = 100 ; 00317 apply_surface(clip.w + 2 ,0,*surf,*blank,clip); 00318 clip.y = 200 ; 00319 apply_surface(2* (clip.w + 2) ,0,*surf,*blank,clip); 00320 clip.y = 300 ; 00321 apply_surface(3* (clip.w + 2) ,0,*surf,*blank,clip); 00322 clip.y = 400 ; 00323 apply_surface(4* (clip.w + 2) ,0,*surf,*blank,clip); 00324 //and this the offset for the button panel 00325 SDL_Rect offset; 00326 offset.x = (d->getWidth() - blank->w) /2; 00327 offset.y = (d-> getHeight() - blank->h) /2; 00328 d->pushEvent("the answer panel is going up"); 00329 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00330 bool quit = false ; 00331 SDL_Event event ; 00332 int mx = 0 ; //the x location of mouse pointer at click time 00333 int my = 0 ; //the y location of mouse pointer at click time 00334 00335 //in this block we will wait until left burron is down 00336 while( quit == false ) { 00337 while( SDL_PollEvent( &event ) ) { 00338 if( event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT 00339 && event.button.x > offset.x && event.button.x <= offset.x + blank->w 00340 && event.button.y > offset.y && event.button.y <= offset.y + blank->h 00341 ) { 00342 quit = true; 00343 mx = event.button.x ; 00344 my = event.button.y ; 00345 } 00346 } 00347 } 00348 d->pushEvent("answered: "+ stringify((mx - offset.x) / ((blank->w)/5)) ) ; 00349 if((mx - offset.x) / ((blank->w)/5) == (int)word) { 00350 d->pushEvent("correct answer") ; 00351 }else{ 00352 d->pushEvent("incorrect answer") ; 00353 } 00354 dumpSurface(blank) ; 00355 dumpSurface(cblank); 00356 dumpSurface(surf) ; 00357 } 00358 //cleaning up the questions and answers 00359 while(testMap.size()>0){ 00360 map<uint,uint>::iterator it=testMap.begin() ; 00361 testMap.erase(it); 00362 } 00363 //we make the mouse pointer disappear again! 00364 d->showCursor(false); 00365 } 00366 00367 00368 void scramble(vector<string>& v){ 00369 vector<string> tv = vector<string>() ; 00370 while(v.size()>0){ 00371 tv.push_back(v[0]); 00372 v.erase(v.begin()); 00373 } 00374 int i = 0 ; 00375 while(tv.size()>0){ 00376 i = rand()%tv.size() ; 00377 v.push_back(tv[i]); 00378 tv.erase(tv.begin()+i); 00379 } 00380 } 00381 //this function is used for the memory task, it takes in two lists of file names, one as the target list and 00382 //the second as test images, then it scramble the aggragated list and displays a random array of images, upon 00383 //click on one image a fram apears around the image and by clicking on the framed image the image is selected 00384 //as subject's choice, the choice and correctness will be logged 00385 bool memoryTest(vector<string>& dil , vector<string>& cil){ 00386 d->showCursor(true); 00387 bool flag = false ; 00388 //here we decide what is size of grid of images, number of rows and columns are equal 00389 int sf = (int)sqrt(dil.size()+cil.size()) ; 00390 if((uint)(sf*sf) < dil.size()+cil.size() ) sf++ ; 00391 float sizefactor = 1.0f/(float)sf ; 00392 //fls is the aggregated list of file names 00393 vector<string>* fls = new vector<string>() ; 00394 //let's put everything in fls 00395 for(uint i = 0 ; i < dil.size() ; i++){ 00396 fls->push_back(dil[i]); 00397 } 00398 for(uint i = 0 ; i < cil.size() ; i++){ 00399 fls->push_back(cil[i]); 00400 } 00401 00402 // and then scramble the list in a random fashion 00403 scramble(*fls) ; 00404 //this surface is used for final display 00405 SDL_Surface* blank = getABlankSurface(d->getWidth(),d->getHeight()) ; 00406 //this surface keeps the original display images in the case that we need to refresh the 00407 //the display with original image this one will be copied to blank 00408 SDL_Surface* oblank = getABlankSurface(d->getWidth(),d->getHeight()) ; 00409 d->displayText("Time for a memory test!",true, 1); 00410 //cout<<cil.size()<< " "<<dil.size()<<" "<<fls->size()<<endl; 00411 00412 //this surface is used as the progress bar 00413 SDL_Surface* pbar = getABlankSurface((d->getWidth())/2,(d->getHeight())/25); 00414 SDL_Rect pbarOffset = SDL_Rect(); 00415 pbarOffset.x = (d->getWidth() - pbar->w )/2 ; 00416 pbarOffset.y = (d->getHeight() - pbar->h)/2 ; 00417 d->displaySDLSurfacePatch(pbar , &pbarOffset,NULL , -2,false, true); 00418 00419 //cframe is a frame on a transparent background put on top of the las choice of the subject 00420 SDL_Surface* cframe = getABlankSurface((d->getWidth())/sf,(d->getHeight())/sf); 00421 Uint32 color = d->getUint32color(PixRGB<byte>(255, 98 , 25)); 00422 drawRectangle(cframe , color , 0 , 0 ,cframe->w -2 , cframe->h -2 , 5) ; 00423 if( cframe != NULL ) 00424 { 00425 //Map the color key 00426 Uint32 colorkey = SDL_MapRGB( cframe->format, 0x00, 0x00, 0x00 ); 00427 00428 //Set all pixels of color R 0, G 0, B 0 to be transparent 00429 SDL_SetColorKey( cframe, SDL_SRCCOLORKEY, colorkey ); 00430 } 00431 00432 //Now let's load up the images, resize them and put them in the right place of the display 00433 int c = 0 ; 00434 for(int i = 0 ; i < sf ; i++){ 00435 for(int j = 0 ; j < sf ; j++){ 00436 if((uint)(j*sf + i) < fls->size()){ 00437 c++ ; 00438 //let's load the image 00439 SDL_Surface* ts = load_image((*fls)[j*sf + i]); 00440 sizefactor = min(((float)(d->getWidth()))/sf/((float)(ts->w)),((float)(d->getHeight()))/sf/((float)(ts->h))); 00441 //here we resize the image 00442 ts = SDL_Resize(ts,sizefactor,5) ; 00443 //cout<<(j*sf + i)<<" " <<(*fls)[j*sf + i]<<endl 00444 SDL_Rect* clip = new SDL_Rect() ; 00445 clip->x = 0 ; 00446 clip->y = 0 ; 00447 clip->w = ts->w ; 00448 clip->h = ts->h ; 00449 SDL_Rect offset; 00450 offset.x = i*(d->getWidth())/sf + ((d->getWidth())/sf - ts->w)/2; 00451 offset.y = j*(d->getHeight())/sf + ((d->getHeight())/sf - ts->h)/2; 00452 00453 //here we apply the surface patch on both copies of the displaying image 00454 apply_surface(offset.x, offset.y,*ts,*blank ,*clip); 00455 apply_surface(offset.x, offset.y,*ts,*oblank ,*clip); 00456 //let's free up the pointers 00457 dumpSurface(ts); 00458 delete clip ; 00459 //let's draw the progress bar 00460 Uint32 color = d->getUint32color(PixRGB<byte>(255, 98 , 25)); 00461 fillRectangle(pbar,color,0,0,(int)((float)((j*sf + i + 1)*(pbar->w))/(float)(fls->size())) , pbar->h); 00462 fillRectangle(pbar,color,0,0,(int)((float)c/float(fls->size())) , pbar->h); 00463 d->displaySDLSurfacePatch(pbar , &pbarOffset,NULL , -2,false, true); 00464 } 00465 00466 00467 } 00468 } 00469 SDL_FreeSurface( pbar ); 00470 //here we are ready for displaying the image so let's ask the subject to continue 00471 d->displayText("Click to start!",true); 00472 SDL_Rect offset; 00473 offset.x = 0; 00474 offset.y = 0; 00475 getMouseEvent() ; 00476 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00477 uint quit = 0 ; 00478 SDL_Event event ; 00479 int fmx = 0 ; 00480 int fmy = 0 ; 00481 int smx = 0 ; 00482 int smy = 0 ; 00483 int choice1 = 0 ; 00484 int choice2 = 0 ; 00485 //here we interact with the subject in order to get the subject's choice 00486 while( quit != 2 ) { 00487 SDL_Rect tempClip = SDL_Rect(); 00488 tempClip.x = 0 ; tempClip.y=0 ; 00489 tempClip.w = 10 ; tempClip.h = 10; 00490 00491 while( SDL_PollEvent( &event ) ) { 00492 00493 00494 if( event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT 00495 && event.button.x > offset.x && event.button.x <= offset.x + blank->w 00496 && event.button.y > offset.y && event.button.y <= offset.y + blank->h 00497 && quit == 1 00498 ) { 00499 smx = event.button.x ; 00500 smy = event.button.y ; 00501 choice2 = (int)(sf*(smx-offset.x)/(d->getWidth())) + sf*(int)(sf*(smy-offset.y)/(d->getHeight())) ; 00502 if(choice1 == choice2){ 00503 if((uint)choice1 < fls->size()){ 00504 quit = 2 ; 00505 d->pushEvent("memory test choice : "+(*fls)[choice1]); 00506 00507 for(uint f = 0 ; f < dil.size() ; f++){ 00508 if((*fls)[choice1].compare(dil[f])==0) { 00509 flag = true ; 00510 break ; 00511 } 00512 } 00513 00514 if (flag==true){ 00515 d->pushEvent("memory test result : correct" ); 00516 }else{ 00517 d->pushEvent("memory test result : incorrect" ); 00518 } 00519 00520 }else{ 00521 quit = 3 ; 00522 SDL_Rect* clip = new SDL_Rect() ; 00523 SDL_Rect* tof = new SDL_Rect ; 00524 tof->x = 0 ; tof->y=0 ; 00525 SDL_BlitSurface( oblank, NULL, blank, tof ); 00526 clip = 0 ; 00527 tof=0; 00528 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00529 00530 } 00531 00532 }else{ 00533 quit = 3 ; 00534 SDL_Rect* clip = new SDL_Rect() ; 00535 clip->x = 0 ; 00536 clip->y = 0 ; 00537 clip->w = d->getWidth() ; 00538 clip->h = d->getHeight() ; 00539 SDL_Rect* tof = new SDL_Rect ; 00540 tof->x = 0 ; tof->y=0 ; 00541 SDL_BlitSurface( oblank, NULL, blank, tof ); 00542 clip = 0 ; 00543 tof=0; 00544 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00545 } 00546 } 00547 00548 if( event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT 00549 && event.button.x > offset.x && event.button.x <= offset.x + blank->w 00550 && event.button.y > offset.y && event.button.y <= offset.y + blank->h 00551 && quit == 0 00552 ) { 00553 SDL_Rect* clip = new SDL_Rect() ; 00554 clip->x = 0 ; 00555 clip->y = 0 ; 00556 clip->w = oblank->w ; 00557 clip->h = oblank->h ; 00558 SDL_Rect* tof = new SDL_Rect ; 00559 tof->x = 0 ; tof->y=0 ; 00560 SDL_BlitSurface( oblank, NULL, blank, tof ); 00561 clip = 0 ; 00562 tof=0; 00563 quit = 1; 00564 fmx = event.button.x ; 00565 fmy = event.button.y ; 00566 int i = sf*(fmx-offset.x)/(d->getWidth()) ; 00567 int j = sf*(fmy-offset.y)/(d->getHeight()); 00568 choice1 = (int)(sf*(fmx-offset.x)/(d->getWidth())) + sf*(int)(sf*(fmy-offset.y)/(d->getHeight())) ; 00569 tempClip.x = i*(d->getWidth())/sf; tempClip.y= j*(d->getHeight())/sf;tempClip.w=(d->getWidth())/sf;tempClip.h=(d->getHeight())/sf; 00570 SDL_BlitSurface(cframe,NULL,blank,&tempClip) ; 00571 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00572 } 00573 00574 if(quit==3) quit=0 ; 00575 00576 } 00577 } 00578 00579 if(oblank != NULL) 00580 SDL_FreeSurface( oblank ); 00581 if(blank != NULL) 00582 SDL_FreeSurface( blank ); 00583 SDL_FreeSurface( cframe ); 00584 fls = 0 ; 00585 d->clearScreen(); 00586 return flag ; 00587 } 00588 void firstTask(const uint l){ 00589 Uint32 green = d->getUint32color(PixRGB<byte>(0, 255, 0)); 00590 Uint32 blue = d->getUint32color(PixRGB<byte>(0, 0, 255)); 00591 Uint32 red = d->getUint32color(PixRGB<byte>(255,0,0)); 00592 Uint32 color = 0 ; 00593 int c = 0 ; 00594 SDL_Rect offset; 00595 d->clearScreen() ; 00596 //Give the offsets to the rectangle 00597 SDL_Surface* blankSurface = getABlankSurface(d->getWidth(),d->getHeight()) ; 00598 offset.x = (d->getWidth() - blankSurface->w) /2; 00599 offset.y = (d-> getHeight() - blankSurface->h) /2; 00600 for (uint i = 0 ; i < l ; i++){ 00601 c = rand()%3 ; 00602 switch(c){ 00603 case 0 : color = red ;break; 00604 case 1 : color = green ; break ; 00605 case 2 : color = blue ; break ; 00606 } 00607 00608 fillQuadricRadiant(blankSurface,color,rand()%(blankSurface->w -100 ) + 50 ,rand()%(blankSurface->h -100)+50,20) ; 00609 d->displaySDLSurfacePatch(blankSurface , &offset,NULL , -2,false, true); 00610 d->waitFrames(10); 00611 } 00612 dumpSurface(blankSurface) ; 00613 } 00614 00615 //displays 0 or 1 in a random place on the screen 00616 void finalTask(const int rndBase = 2 , const uint delay = 10 ){ 00617 int confNum = rand() % rndBase ; 00618 d->pushEvent(std::string("confirmation number : ")+stringify(confNum)); 00619 //let's display the number in a random place 00620 d->displayText(stringify(confNum),true,-2); 00621 d->waitFrames(delay); 00622 d->clearScreen(); 00623 d->pushEvent(std::string("asking for confirmation number")); 00624 d->displayText(std::string("what was the number ? "),true,1); 00625 //we need the subject be able to interact with the mouse 00626 d->showCursor(true); 00627 SDL_Surface* blank =getABlankSurface((d->getWidth())/2 , d->getHeight()/10); 00628 //we make a scrap image to write down the numbers on 00629 Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS); 00630 textIm.clear(PixRGB<byte>(255, 255, 255)); 00631 //here we write the numbers 00632 for(int i = 0 ; i < rndBase ; i ++){ 00633 writeText(textIm, Point2D<int>((blank->w)/(2*rndBase) -2,10+100*i), stringify(i).c_str()); 00634 } 00635 //and here we make a blittabl surface out of that 00636 SDL_Surface *surf = d->makeBlittableSurface(textIm , true); 00637 //and take out differnt clips out of that 00638 SDL_Rect clip; 00639 clip.x = 0 ; 00640 clip.w = (blank->w)/rndBase - 2 ; 00641 clip.h =blank->h ; 00642 for(int i = 0 ; i < rndBase ; i++){ 00643 clip.y = i*100 ; 00644 apply_surface(i*(clip.w + 2),0,*surf,*blank,clip); 00645 } 00646 00647 SDL_Rect offset; 00648 offset.x = (d->getWidth() - blank->w) /2; 00649 offset.y = (d-> getHeight() - blank->h) /2; 00650 d->pushEvent("the button panel is going up"); 00651 d->displaySDLSurfacePatch(blank , &offset,NULL , -2,false, true); 00652 00653 bool quit = false ; 00654 SDL_Event event ; 00655 int mx = 0 ; 00656 int my = 0 ; 00657 while( quit == false ) { 00658 while( SDL_PollEvent( &event ) ) { 00659 if( event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_LEFT 00660 && event.button.x > offset.x && event.button.x <= offset.x + blank->w 00661 && event.button.y > offset.y && event.button.y <= offset.y + blank->h 00662 ) { 00663 quit = true; 00664 mx = event.button.x ; 00665 my = event.button.y ; 00666 } 00667 } 00668 } 00669 00670 d->pushEvent("confirmed: " + stringify((mx - offset.x) / ((blank->w)/rndBase))) ; 00671 if((mx - offset.x) / ((blank->w)/rndBase) == (int)confNum) { 00672 d->pushEvent("correct confirmation") ; 00673 }else{ 00674 d->pushEvent("incorrect confirmation") ; 00675 } 00676 00677 dumpSurface(blank); 00678 dumpSurface(surf) ; 00679 d->showCursor(false); 00680 00681 } 00682 00683 00684 void getARandomScoop(vector<string> mainlist , vector<string>& targetlist , int s){ 00685 //cleaning up the target list 00686 if(targetlist.size()>0) { 00687 while( targetlist.size()!=0 ){ 00688 targetlist.erase(targetlist.begin()) ; 00689 } 00690 } 00691 //let's duplicate the mainlist and make a temporary vector 00692 LINFO("scoop1"); 00693 vector<string> tv = vector<string>() ; 00694 for(uint i = 0 ; i < mainlist.size() ; i++){ 00695 tv.push_back(mainlist[i]); 00696 } 00697 00698 for(int i = 0 ; i < s ; i++){ 00699 int index = rand()%tv.size() ; 00700 targetlist.push_back(tv[index]); 00701 tv.erase(tv.begin()); 00702 } 00703 string st = stringify(targetlist.size()); 00704 LINFO(st.c_str()); 00705 } 00706 00707 00708 00709 int addArgument(const string st,const string delim="="){ 00710 int i = st.find(delim) ; 00711 argMap[st.substr(0,i)] = st.substr(i+1); 00712 00713 return 0 ; 00714 } 00715 00716 std::string getArgumentValue(string arg){ 00717 return argMap[arg] ; 00718 } 00719 00720 std::string getUsageComment(){ 00721 00722 string com = string("\nlist of arguments : \n"); 00723 00724 com += "\nconf-num=[2..10] (random numbers in confirmation task) {default=2} \n" ; 00725 com += "\nconf-delay=[>1] (the delay in showing the confirmation number) {default=10}\n"; 00726 com += "\ndelay-interval=[>1]:[>1] (the interval for random delay after stroop task) {default=10}\n"; 00727 com += "\nfixation-blink=[y/n] (show the blink for fixation after stroop task or no) {defaule y}\n"; 00728 com += "\nimage-dir=[path to image directory] (needed for mode 2 and 3) {default=60:160} \n" ; 00729 com += "\nextra-image-dir=[path to extra images directory](needed for lineup memory test)"; 00730 com += "\nlogfile=[logfilename.psy] {default = psycho-stroop-concurrent.psy}\n" ; 00731 com += "\nstroop-display-delay=[>1] (number of frames to display the stroop word){default=60}\n"; 00732 com += "\nmemo=[a_string_without_white_space]\n"; 00733 com += "\nmode=[1..5] (1 for stroop test only, 2 for stroop test + image display + digit memorizetion" 00734 ", 3 for image display only, 4 for stroop test + image display + image memorizetion, " 00735 "5 for image display + image memorization ) {default=1}\n"; 00736 com += "\nstroop-size=[1..5](number of words in the stroop task){default=3} \n" ; 00737 com += "\nsubject=[subject_name] \n" ; 00738 com += "\ntest-rounds=[>1] (needed for mode1) {default=5}\n"; 00739 00740 00741 return com ; 00742 } 00743 00744 00745 extern "C" int main(const int argc, char** argv) 00746 { 00747 00748 MYLOGVERB = LOG_INFO; // suppress debug messages 00749 //let's push the initial value for the parameters 00750 argMap["mode"] = "1" ; 00751 argMap["logfile"]="psycho-stroop-concurrent.psy" ; 00752 argMap["conf-number"] = "2" ; 00753 argMap["stroop-size"]="3" ; 00754 argMap["image-dir"]=".."; 00755 argMap["extra-image-dir"] = ".." ; 00756 argMap["conf-delay"]="10" ; 00757 argMap["test-rounds"]="5"; 00758 argMap["stroop-display-delay"] = "60" ; 00759 argMap["delay-interval"]="60:160" ; 00760 argMap["subject"]="" ; 00761 argMap["memo"]="" ; 00762 argMap["fixation-blink"]="y" ; 00763 argMap["lineup-size"]="4"; 00764 argMap["image-memory-stack"]="4"; 00765 00766 manager.addSubComponent(d); 00767 nub::soft_ref<EventLog> el(new EventLog(manager)); 00768 manager.addSubComponent(el); 00769 //*nub::soft_ref<EyeTrackerConfigurator> 00770 //* etc(new EyeTrackerConfigurator(manager)); 00771 //*manager.addSubComponent(etc); 00772 00773 if (manager.parseCommandLine(argc, argv, 00774 "at least one argument needed", 1, -1)==false){ 00775 LINFO(getUsageComment().c_str()); 00776 return(1); 00777 } 00778 00779 for(uint i = 0 ; i < manager.numExtraArgs() ; i++){ 00780 addArgument(manager.getExtraArg(i),std::string("=")) ; 00781 } 00782 00783 manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]); 00784 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN"); 00785 // hook our various babies up and do post-command-line configs: 00786 //*nub::soft_ref<EyeTracker> et = etc->getET(); 00787 //*d->setEyeTracker(et); 00788 d->setEventLog(el); 00789 //*et->setEventLog(el); 00790 00791 00792 // let's get all our ModelComponent instances started: 00793 manager.start(); 00794 for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ; 00795 // let's display an ISCAN calibration grid: 00796 d->clearScreen(); 00797 d->displayISCANcalib(); 00798 d->waitForKey(); 00799 00800 // let's do an eye tracker calibration: 00801 d->displayText("<SPACE> to calibrate; other key to skip"); 00802 int c = d->waitForKey(); 00803 if (c == ' ') d->displayEyeTrackerCalibration(3,5); 00804 00805 d->clearScreen(); 00806 d->displayText("<SPACE> for random play; other key for ordered"); 00807 c = d->waitForKey(); 00808 00809 int mode = atoi(argMap["mode"].c_str()) ; 00810 00811 if(mode == 1){ 00812 string::size_type position = argMap["delay-interval"].find(":"); 00813 int minDel = atoi(argMap["delay-interval"].substr(0,position).c_str()) ; 00814 int maxDel = atoi(argMap["delay-interval"].substr(position+1).c_str()) ; 00815 int numOfTests = atoi(argMap["test-rounds"].c_str()) ; 00816 int stroopSize = atoi(argMap["stroop-size"].c_str()) ; 00817 //int confNum = atoi(argMap["conf-number"].c_str()) ; 00818 //int confDelay = atoi(argMap["conf-delay"].c_str()) ; 00819 int stroopDelay = atoi(argMap["stroop-display-delay"].c_str()); 00820 for(int i = 0 ; i < numOfTests ; i++){ 00821 d->pushEvent("**************************************") ; 00822 d->showCursor(true); 00823 d->displayText("click one of the mouse buttons to start!"); 00824 getMouseEvent() ; 00825 d->showCursor(false); 00826 colorStroopTask(stroopSize,stroopDelay); 00827 d->waitFrames((rand()%(maxDel - minDel)) +minDel ); 00828 //finalTask(confNum,confDelay) ; 00829 d->clearScreen() ; 00830 colorStroopQuiz(); 00831 } 00832 } 00833 00834 if(mode == 2 ){ 00835 string::size_type position = argMap["delay-interval"].find(":"); 00836 int minDel = atoi(argMap["delay-interval"].substr(0,position).c_str()) ; 00837 int maxDel = atoi(argMap["delay-interval"].substr(position+1).c_str()) ; 00838 string dir = argMap["image-dir"]; 00839 vector<string> files = vector<string>(); 00840 getdir(dir,files); 00841 int stroopSize = atoi(argMap["stroop-size"].c_str()) ; 00842 int confNum = atoi(argMap["conf-number"].c_str()) ; 00843 int confDelay = atoi(argMap["conf-delay"].c_str()) ; 00844 int stroopDelay = atoi(argMap["stroop-display-delay"].c_str()); 00845 00846 while(files.size()>0){ 00847 int imageIndex = rand()%files.size() ; 00848 SDL_Surface *surf = load_image(files[imageIndex]); 00849 float r1 = (float)d->getWidth()/(float)surf->w ; 00850 float r2 = (float)d->getHeight() / (float)surf->h ; 00851 surf = SDL_Resize(surf ,min(r1,r2) , 5 ); 00852 SDL_Rect offset; 00853 offset.x = (d->getWidth() - surf->w) /2; 00854 offset.y = (d-> getHeight() - surf->h) /2; 00855 d->pushEvent("**************************************") ; 00856 d->showCursor(true); 00857 d->displayText("click a mouse button to start!"); 00858 getMouseEvent() ; 00859 d->showCursor(false); 00860 colorStroopTask(stroopSize,stroopDelay); 00861 d->clearScreen() ; 00862 d->waitNextRequestedVsync(false, true); 00863 d->pushEvent(std::string("===== Showing image: ") + 00864 files[imageIndex] + " ====="); 00865 00866 // start the eye tracker: 00867 //*et->track(true); 00868 //blink the fixation: 00869 if(argMap["fixation-blink"].compare("y")==0) d->displayFixationBlink(); 00870 00871 d->displaySDLSurfacePatch(surf , &offset,NULL , -2,false, true); 00872 d->waitFrames((rand()%(maxDel-minDel)) +minDel ); 00873 dumpSurface(surf); 00874 // stop the eye tracker: 00875 usleep(50000); 00876 //*et->track(false); 00877 //see if the subject was looking at the screen! 00878 finalTask(confNum,confDelay) ; 00879 d->clearScreen() ; 00880 //now quiz time! 00881 colorStroopQuiz(); 00882 d->clearScreen() ; 00883 files.erase(files.begin()+imageIndex); 00884 } 00885 } 00886 00887 if(mode == 3){ 00888 string::size_type position = argMap["delay-interval"].find(":"); 00889 int minDel = atoi(argMap["delay-interval"].substr(0,position).c_str()) ; 00890 int maxDel = atoi(argMap["delay-interval"].substr(position+1).c_str()) ; 00891 string dir = argMap["image-dir"]; 00892 vector<string> files = vector<string>(); 00893 getdir(dir,files); 00894 int c = 0 ; 00895 00896 while(files.size()>0){ 00897 c++ ; 00898 int imageIndex = rand()%files.size() ; 00899 //this block turned out to be buggy! so I decided to switch to working with SDL_Surface instead 00900 //Image< PixRGB<byte> > image = 00901 //Raster::ReadRGB(files[imageIndex]); 00902 00903 //SDL_Surface *surf = d->makeBlittableSurface(image, true); 00904 SDL_Surface *surf = load_image(files[imageIndex]); 00905 float r1 = (float)d->getWidth()/(float)surf->w ; 00906 float r2 = (float)d->getHeight() / (float)surf->h ; 00907 surf = SDL_Resize(surf ,min(r1,r2) , 5 ); 00908 SDL_Rect offset; 00909 offset.x = (d->getWidth() - surf->w) /2; 00910 offset.y = (d-> getHeight() - surf->h) /2; 00911 d->waitFrames(45); 00912 d->waitNextRequestedVsync(false, true); 00913 d->pushEvent(std::string("===== Showing image: ") + 00914 files[imageIndex] + " ====="); 00915 00916 // start the eye tracker: 00917 //*et->track(true); 00918 //blink the fixation: 00919 if(argMap["fixation-blink"].compare("y")==0) d->displayFixationBlink(); 00920 00921 d->displaySDLSurfacePatch(surf , &offset,NULL , -2,false, true); 00922 d->waitFrames((rand()%(maxDel-minDel)) +minDel ); 00923 dumpSurface(surf); 00924 // stop the eye tracker: 00925 usleep(50000); 00926 //*et->track(false); 00927 d->clearScreen() ; 00928 files.erase(files.begin()+imageIndex); 00929 } 00930 00931 } 00932 if(mode==5){ 00933 //let's read the parameters related to this part 00934 string::size_type position = argMap["delay-interval"].find(":"); 00935 int minDel = atoi(argMap["delay-interval"].substr(0,position).c_str()) ; 00936 int maxDel = atoi(argMap["delay-interval"].substr(position+1).c_str()) ; 00937 vector<string> files = vector<string>(); 00938 vector<string> extras = vector<string>(); 00939 vector<string> memoryStack = vector<string>(); 00940 string dir = argMap["image-dir"]; 00941 getdir(dir,files); 00942 dir = argMap["extra-image-dir"]; 00943 getdir(dir,extras); 00944 int stroopSize = atoi(argMap["stroop-size"].c_str()) ; 00945 int stroopDelay = atoi(argMap["stroop-display-delay"].c_str()); 00946 int lineupSize = atoi(argMap["lineup-size"].c_str()) ; 00947 int stackSize = atoi(argMap["image-memory-stack"].c_str()); 00948 while(files.size()>0){ 00949 int imageIndex = rand()%files.size() ; 00950 SDL_Surface *surf = load_image(files[imageIndex]); 00951 float r1 = (float)d->getWidth()/(float)surf->w ; 00952 float r2 = (float)d->getHeight() / (float)surf->h ; 00953 surf = SDL_Resize(surf ,min(r1,r2) , 5 ); 00954 SDL_Rect offset; 00955 offset.x = (d->getWidth() - surf->w) /2; 00956 offset.y = (d-> getHeight() - surf->h) /2; 00957 d->pushEvent("**************************************") ; 00958 d->showCursor(true); 00959 d->displayText("click a mouse button to start!"); 00960 getMouseEvent() ; 00961 d->showCursor(false); 00962 colorStroopTask(stroopSize,stroopDelay); 00963 d->clearScreen() ; 00964 d->waitNextRequestedVsync(false, true); 00965 d->pushEvent(std::string("===== Showing image: ") + 00966 files[imageIndex] + " ====="); 00967 00968 // start the eye tracker: 00969 //*et->track(true); 00970 //blink the fixation: 00971 if(argMap["fixation-blink"].compare("y")==0) d->displayFixationBlink(); 00972 00973 d->displaySDLSurfacePatch(surf , &offset,NULL , -2,false, true); 00974 d->waitFrames((rand()%(maxDel-minDel)) +minDel ); 00975 dumpSurface(surf); 00976 // stop the eye tracker: 00977 usleep(50000); 00978 //*et->track(false); 00979 d->clearScreen() ; 00980 //now quiz time! 00981 colorStroopQuiz(); 00982 d->clearScreen() ; 00983 memoryStack.push_back(files[imageIndex]); 00984 00985 if(memoryStack.size()%stackSize == 0 && memoryStack.size()!=0){ 00986 00987 while( memoryStack.size() != 0 ){ 00988 vector<string> imVector = vector<string>(); 00989 imVector.push_back(memoryStack[0]); 00990 vector<string> distractorsVector = vector<string>() ; 00991 memoryStack.erase(memoryStack.begin()); 00992 vector<string> tv = vector<string>() ; 00993 for(uint i = 0 ; i < extras.size() ; i++){ 00994 tv.push_back(extras[i]); 00995 } 00996 00997 for(int i = 0 ; i < lineupSize -1 ; i++){ 00998 int index = rand()%tv.size() ; 00999 distractorsVector.push_back(tv[index]); 01000 tv.erase(tv.begin()); 01001 } 01002 01003 //getARandomScoop(extras,distractorsVector,lineupSize -1 ) ; 01004 string st = stringify(distractorsVector.size()); 01005 LINFO(st.c_str()) ; 01006 memoryTest(imVector , distractorsVector); 01007 //delete distractorsVector; 01008 } 01009 } 01010 01011 files.erase(files.begin()+imageIndex); 01012 } 01013 01014 } 01015 01016 if(mode==6){ 01017 01018 } 01019 d->clearScreen(); 01020 d->displayText("Experiment complete. Thank you!"); 01021 d->waitForKey(); 01022 //getEvent(); 01023 // stop all our ModelComponents 01024 manager.stop(); 01025 01026 // all done! 01027 return 0; 01028 } 01029 01030 #endif // INVT_HAVE_LIBSDL_IMAGE 01031