psycho-auditory-concurrent.C

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