psychoWMS.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psychoWMS.C Psychophysics test to measure the influence of eyemovement on memory task performance */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psychoWMS.C $
00035 // $Id: psychoWMS.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-WM");
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 
00104 
00105 
00106 
00107 
00108 ////////////////////////////////////////////////////////////////
00109 ////This is our button factory
00110 ////////////////////////////////////////////////////////////////
00111 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){
00112         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00113         textIm.clear(bgcolor);
00114         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00115         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00116         Uint32 bc = d->getUint32color(bordercolor);
00117         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00118         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00119         SDL_Rect clip;
00120         clip.x = 0 ;
00121         clip.y = 0 ;
00122         clip.w = size.i ;
00123         clip.h = size.j ;
00124         apply_surface(0,0,*surf,*blank,clip);
00125         dumpSurface(surf) ;
00126         return blank ;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////////
00130 ////This is the function for creating the keypad, in fact it generates
00131 ////12 buttons and associates the actions to the region for each button
00132 ////////////////////////////////////////////////////////////////////////
00133 
00134 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00135         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00136         SDL_Rect clip;
00137         clip.x=0;
00138         clip.y=0;
00139         int numofrows = alphabet.size()/3 +1;
00140         if(alphabet.size()%3 != 0 ) numofrows++ ;
00141         int numofcolumns = 3 ;
00142         clip.w= pad->w / numofcolumns ;
00143         clip.h = pad->h / numofrows ;
00144 
00145   //keys for 1 to 9
00146         for( int i = 0 ; i < numofrows*3 ; i++){
00147                 SDL_Surface* but ;
00148                 if((uint)i < alphabet.size()){
00149                         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);
00150                 }else{
00151                         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);
00152                 }
00153 
00154                 SDL_Rect cl ;
00155                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00156                 cl.w = clip.w ;
00157                 cl.h = clip.h ;
00158                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00159                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00160                 dumpSurface(but);
00161         }
00162         SDL_Rect cl1 ;
00163         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00164         cl1.w = clip.w ;
00165         cl1.h = clip.h ;
00166         buttmap["!"] = cl1 ;
00167         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);
00168         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00169         dumpSurface(but);
00170         SDL_Rect cl2 ;
00171         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00172         cl2.w = clip.w ;
00173         cl2.h = clip.h ;
00174         buttmap[" "] = cl2 ;
00175         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);
00176         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00177         dumpSurface(but);
00178         SDL_Rect cl3 ;
00179         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00180         cl3.w = clip.w ;
00181         cl3.h = clip.h ;
00182         buttmap["*"] = cl3 ;
00183         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);
00184         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00185         dumpSurface(but);
00186         return pad ;
00187 }
00188 
00189 
00190 
00191 
00192 ///////////////////////////////////////////////////////////////////////////
00193 /////this function listens to mouse clicks and then finds the region of the screen
00194 /////associated with the action, buttmap is the map of the region, offset is the offset of
00195 /////buttons
00196 ///////////////////////////////////////////////////////////////////////////
00197 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00198         int quit = 0 ;
00199         string s ;
00200         SDL_Event event ;
00201         while( quit!=2 ){
00202                 while( SDL_PollEvent( &event ) ) {
00203                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00204                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00205                                         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) {
00206                                                 quit = 2 ;
00207                                                 s = it->first ;
00208                                                 break;
00209                                         }
00210 
00211                                 }
00212                         }
00213 
00214                 }
00215         }
00216         return s ;
00217 
00218 }
00219 
00220 
00221 ////////////////////////////////////////////////////
00222 ////This function creates a virtual keypad, creates a map of buttons
00223 ////and their representation area and listens to the button press and at
00224 ////the end returns the keyed digits
00225 ////////////////////////////////////////////////////
00226 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){
00227         d->showCursor(true) ;
00228         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00229         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00230         //now let's get the keypad surface while we get the actions map to regions
00231         SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00232         //this will be the offset of displaying the keypad on the screen
00233         SDL_Rect offset ;
00234         offset.x = (d->getWidth() - keypad->w) /2;
00235         offset.y = (d-> getHeight() - keypad->h) /2;
00236         //now let's display the keypad
00237         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00238         //this will hold the final string keyed be the subject
00239         string p = string("") ;
00240         //this is a temporary string holding the last action related to the pressed key
00241         string tp = string("");
00242         //now let's record subject's key press
00243         while( tp.compare("*")!=0 ){
00244                 //this button is actually the display for the current string
00245                 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) ;
00246                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00247                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00248                 //now let's listen to button events
00249                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00250                 dumpSurface(dp) ;
00251                 if(tp.compare("!")==0 && p.size()>=0 ) {
00252                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00253                 }else{
00254                         if(p.size() < maxl && tp.compare("*")!=0) {
00255                                 p +=tp ;
00256                         }
00257 
00258                 }
00259 
00260         }
00261         buttmap = 0 ;
00262         dumpSurface(keypad) ;
00263         d->clearScreen() ;
00264         return p ;
00265 
00266 }
00267 
00268 
00269 
00270 
00271 int addArgument(const string st,const string delim="="){
00272         int i = st.find(delim) ;
00273         argMap[st.substr(0,i)] = st.substr(i+1);
00274 
00275         return 0 ;
00276 }
00277 
00278 std::string getArgumentValue(string arg){
00279         return argMap[arg] ;
00280 }
00281 
00282 std::string getUsageComment(){
00283 
00284         string com = string("\nlist of arguments : \n");
00285 
00286         com += "\nlogfile=[logfilename.psy] {default = psycho-wm-subtraction.psy}\n" ;
00287         com += "\nmemo=[a_string_without_white_space]\n";
00288         com += "\nrange=[x-y](the size of string){default=200-500} \n";
00289         com += "\nsubject=[subject_name] \n" ;
00290         com += "\ndelay=[>0] (number of micro seconds){default=30000000}\n";
00291         com += "\ntest-rounds=[>1] (number of tests ) {default=5}\n";
00292         com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n";
00293         com += "\nsubtraction-step=[>0] (the subtraction number){default=3} ";
00294         return com ;
00295 }
00296 
00297 
00298 extern "C" int main(const int argc, char** argv)
00299 {
00300 
00301         MYLOGVERB = LOG_INFO;  // suppress debug messages
00302         //let's push the initial value for the parameters
00303         argMap["experiment"]="subtraction-working-memory";
00304         argMap["logfile"]="psycho-wm-subtraction.psy" ;
00305         argMap["string-size"]="5" ;
00306         argMap["test-rounds"]="5";
00307         argMap["subject"]="" ;
00308         argMap["memo"]="" ;
00309         argMap["digit-onset"]="10" ;
00310         argMap["range"]="200-500";
00311         argMap["delay"]="30000000" ;
00312         argMap["subtraction-step"]="3" ;
00313         manager.addSubComponent(d);
00314         nub::soft_ref<EventLog> el(new EventLog(manager));
00315         manager.addSubComponent(el);
00316         d->setEventLog(el);
00317         nub::soft_ref<EyeTrackerConfigurator>
00318                         etc(new EyeTrackerConfigurator(manager));
00319           manager.addSubComponent(etc);
00320 
00321         if (manager.parseCommandLine(argc, argv,
00322             "at least one argument needed", 1, -1)==false){
00323                     cout<<getUsageComment()<<endl;
00324                     return(1);
00325             }
00326 
00327             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00328                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00329             }
00330 
00331             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00332             manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00333             nub::soft_ref<EyeTracker> eyet = etc->getET();
00334             d->setEyeTracker(eyet);
00335             eyet->setEventLog(el);
00336 
00337 
00338   // let's get all our ModelComponent instances started:
00339             manager.start();
00340             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00341   // let's display an ISCAN calibration grid:
00342             d->clearScreen();
00343             d->displayISCANcalib();
00344             d->waitForMouseClick();
00345             d->displayText("Here the experiment starts! click to start!");
00346             d->waitForMouseClick();
00347             d->clearScreen();
00348         //let's see in what mode the user like to run the program
00349 
00350             int numOfTests = atoi(argMap["test-rounds"].c_str()) ;
00351             int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00352             long opDelay = atol(argMap["delay"].c_str());
00353             int in = argMap["range"].find("-") ;
00354             int rangeU = atoi( argMap["range"].substr(in+1).c_str()) ;
00355             int rangeL = atoi(argMap["range"].substr(0,in).c_str()) ;
00356             int step = atoi(argMap["subtraction-step"].c_str());
00357         //let's count the rounds
00358             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00359             int cl = d->waitForMouseClick();
00360             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00361             d->clearScreen();
00362             int cr = 0 ;
00363             while( cr <numOfTests ){
00364 
00365                             cr++;
00366                             d->pushEvent("**************************************") ;
00367                             d->showCursor(true);
00368                             d->displayText("click one of the  mouse buttons to start!");
00369                             d->waitForMouseClick() ;
00370                             d->showCursor(false) ;
00371                             int initialNum = rangeL+ random()%(rangeU-rangeL) ;
00372                             d->clearScreen() ;
00373                             d->pushEvent("the initial number is: "+stringify(initialNum)) ;
00374                             d->displayFixationBlink();
00375                             d->displayText(stringify(initialNum),true,0) ;
00376                             d->waitFrames(onsetDel) ;
00377                             d->clearScreen() ;
00378                             d->displayFixationBlink(d->getWidth()/2,d->getHeight()/2,2,3);
00379                             d->pushEvent(std::string("===== Showing image: def.mpg ====="));
00380                             eyet->track(true);
00381                             d->pushEvent("manupulation starts") ;
00382                             long st = d->getTimerValue();
00383                             long et = st ;
00384                             while( et - st < opDelay ){
00385                                 et = d->getTimerValue();
00386                             }
00387                             usleep(50000);
00388                             eyet->track(false);
00389                             d->pushEvent("manipulation ends") ;
00390                             string  answer = getDigitSequenceFromSubject("0123456789" , 3);
00391                             d->pushEvent("the reported number: "+answer);
00392                             int finalNum = atoi(answer.c_str()) ;
00393                             d->pushEvent("number of operations: "+stringify((initialNum-finalNum)/step));
00394             }
00395 
00396             d->clearScreen();
00397             d->displayText("Experiment complete. Thank you!");
00398             d->waitForMouseClick();
00399 
00400         // stop all our ModelComponents
00401             manager.stop();
00402 
00403 
00404         // all done!
00405             return 0;
00406 }
00407 
00408 #endif // INVT_HAVE_LIBSDL_IMAGE
00409 
Generated on Sun May 8 08:40:10 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3