psycho-msc.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-msc.C Psychophysics test to measure the influence of eyemovement on memory task performance
00002 this is an new version of psycho-sc.C which supports words instead of characters for the memory task */
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00006 // University of Southern California (USC) and the iLab at USC.         //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-msc.C $
00036 // $Id: psycho-msc.C 12962 2010-03-06 02:13:53Z irock $
00037 //
00038 
00039 #include "Component/ModelManager.H"
00040 #include "Image/Image.H"
00041 #include "Psycho/PsychoDisplay.H"
00042 #include "Psycho/EyeTrackerConfigurator.H"
00043 #include "Psycho/EyeTracker.H"
00044 #include "Psycho/PsychoOpts.H"
00045 #include "Component/EventLog.H"
00046 #include "Component/ComponentOpts.H"
00047 #include "Raster/Raster.H"
00048 #include "Util/MathFunctions.H"
00049 #include "Util/Types.H"
00050 #include "GameBoard/basic-graphics.H"
00051 #include <sys/types.h>
00052 #include <dirent.h>
00053 #include <errno.h>
00054 #include <vector>
00055 #include <string>
00056 #include <iostream>
00057 #include <SDL/SDL.h>
00058 #include <SDL/SDL_image.h>
00059 #include <SDL/SDL_mixer.h>
00060 #include <stdio.h>
00061 #include <stdlib.h>
00062 #include <sstream>
00063 #include <time.h>
00064 #include "Image/DrawOps.H"
00065 #include "GameBoard/resize.h"
00066 #include <iostream>
00067 #include <fstream>
00068 #include <set>
00069 #include <algorithm>
00070 #include <ctime>
00071 
00072 #ifndef INVT_HAVE_LIBSDL_IMAGE
00073 #include <cstdio>
00074 int main()
00075 {
00076         fprintf(stderr, "The SDL_image library must be installed to use this program\n");
00077         return 1;
00078 }
00079 
00080 #else
00081 
00082 
00083 
00084 using namespace std;
00085 
00086 // ######################################################################
00087 
00088 ModelManager manager("Psycho-Concurrent-Digit");
00089 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00090 map<uint,uint> testMap ;
00091 map<string,string> argMap ;
00092 map<string,vector<SDL_Rect*>*> clipsmap;
00093 
00094 //////////////////////////////////////////////
00095 // a functionf for stringigying things
00096 //////////////////////////////////////////////
00097 template <class T> std::string stringify(T i)
00098 {
00099         ostringstream o ;
00100         o << i ;
00101         return o.str();
00102 }
00103 
00104 
00105 double getAvarage(vector<long> v){
00106         double f = 0.0 ;
00107         for( uint i = 0 ; i <  v.size() ; i++ ){
00108                 f += v[i] ;
00109         }
00110         if (v.size()!=0) return f/v.size() ;
00111         return -1 ;
00112 }
00113 
00114 double getVariance(vector<long> v){
00115         double m = getAvarage(v);
00116         double var = 0.0 ;
00117         for( uint i = 0 ; i < v.size(); i++ ){
00118                 var += (v[i]-m)*(v[i]-m) ;
00119         }
00120         if (v.size()!=0) return var/v.size() ;
00121         return -1 ;
00122 }
00123 
00124 bool itIsInThere(int x , vector<int> bag){
00125         for( uint i=0 ; i < bag.size(); i++ ){
00126                 if(x == bag[i]) return true ;
00127         }
00128         return false ;
00129 }
00130 
00131 
00132 string get0321(string s){
00133         string t = "";
00134         t = s.substr(0,1)+s.substr(3,1)+s.substr(2,1)+s.substr(1,1);
00135         return t ;
00136 }
00137 
00138 string get1230(string s){
00139         string t = "";
00140         t = s.substr(1,1)+s.substr(2,1)+s.substr(3,1)+s.substr(0,1);
00141         return t ;
00142 }
00143 
00144 string get3012(string s){
00145         string t = "";
00146         t = s.substr(3,1)+s.substr(0,1)+s.substr(1,1)+s.substr(2,1);
00147         return t ;
00148 }
00149 
00150 string get2103(string s){
00151         string t = "";
00152         t = s.substr(2,1)+s.substr(1,1)+s.substr(0,1)+s.substr(3,1);
00153         return t ;
00154 }
00155 
00156 string get34012(string s){
00157         string t = "";
00158         t = s.substr(3,1)+s.substr(4,1)+s.substr(0,1)+s.substr(1,1)+s.substr(2,1);
00159         return t ;
00160 }
00161 
00162 string get21043(string s){
00163         string t = "";
00164         t = s.substr(2,1)+s.substr(1,1)+s.substr(0,1)+s.substr(4,1)+s.substr(3,1);
00165         return t ;
00166 }
00167 
00168 string get41230(string s){
00169         string t = "";
00170         t = s.substr(4,1)+s.substr(1,1)+s.substr(2,1)+s.substr(3,1)+s.substr(0,1);
00171         return t ;
00172 }
00173 
00174 string get03214(string s){
00175         string t = "";
00176         t = s.substr(0,1)+s.substr(3,1)+s.substr(2,1)+s.substr(1,1)+s.substr(4,1);
00177         return t ;
00178 }
00179 
00180 string get42130(string s){
00181         string t="";
00182         t = s.substr(4,1)+s.substr(2,1)+s.substr(1,1)+s.substr(3,1)+s.substr(0,1);
00183         return t ;
00184 }
00185 
00186 
00187 string get03124(string s){
00188         string t = "" ;
00189         t = s.substr(0,1)+s.substr(3,1)+s.substr(1,2)+s.substr(2,1)+s.substr(4,1);
00190         return t ;
00191 }
00192 ////////////////////////////////////////////////////////////////////
00193 //// gets a string as the argument and returns a string composed of
00194 //// characters of the first string sorted in the ascending order
00195 ///////////////////////////////////////////////////////////////////
00196 string ascSort(string st)
00197 {
00198         string res = "" ;
00199         vector<string> v = vector<string>();
00200         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00201 
00202         std::sort(v.begin(), v.end());
00203 
00204         for ( uint i = 0 ; i < v.size() ; i++ ){
00205                 res += v[i] ;
00206         }
00207         return res;
00208 }
00209 
00210 
00211 
00212 ////////////////////////////////////////////////////////////////////
00213 //// gets a string as the argument and returns a string composed of
00214 //// characters of the first string sorted in the descending order
00215 ///////////////////////////////////////////////////////////////////
00216 string desSort(string st)
00217 {
00218         string res = "" ;
00219         vector<string> v = vector<string>();
00220         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00221         std::sort(v.begin(), v.end());
00222         std::reverse(v.begin(), v.end());
00223         for ( uint i = 0 ; i < v.size() ; i++ ){
00224                 res += v[i] ;
00225         }
00226         return res;
00227 }
00228 
00229 
00230 
00231 
00232 
00233 ////////////////////////////////////////////////////////
00234 ///// simply generates a sequence of digits with given alphabet with length of l with given threshold, if the given threshold is not achieved the best answer with
00235 //highest metric value in 1000000 times try will be returned
00236 ////////////////////////////////////////////////////////
00237 
00238 string getARandomString(uint l, string alphabet="0123456789"){
00239 
00240         string test = string("") ;
00241         test = "" ;
00242         string tp = string("") ;
00243         vector<int> pickedones = vector<int>() ;
00244         for(uint i = 0 ; i < l ; i++){
00245                 int nd;
00246                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00247                 pickedones.push_back(nd);
00248                 tp = alphabet.substr(nd,1) ;
00249                 test += tp ;
00250         }
00251 
00252         return test ;
00253 }
00254 
00255 ///////////////////////////////////////////////////////
00256 //this function is not called in this program, but it generates a random string and it will show it in
00257 //a random place on the screen.
00258 //////////////////////////////////////////////////////
00259 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10  ){
00260         d->clearScreen() ;
00261         vector<int> pickedones = vector<int>() ;
00262         string test = string("") ;
00263         string tp = string("") ;
00264         for(uint i = 0 ; i < l ; i++){
00265                 int nd;
00266                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00267                 pickedones.push_back(nd);
00268                 tp = alphabet.substr(nd,1) ;
00269                 test += tp ;
00270         }
00271         d->displayText(test,true,0) ;
00272         d->waitFrames(displayFrame) ;
00273         d->clearScreen() ;
00274         return test ;
00275 }
00276 
00277 
00278 ////////////////////////////////////////////////////////
00279 ///////this will change the order of elements in a vector to a random order
00280 ////////////////////////////////////////////////////////
00281 void scramble(vector<string>& v){
00282         vector<string> tv = vector<string>() ;
00283         while(v.size()>0){
00284                 tv.push_back(v[0]);
00285                 v.erase(v.begin());
00286         }
00287         int i = 0 ;
00288         while(tv.size()>0){
00289                 i = rand()%tv.size() ;
00290                 v.push_back(tv[i]);
00291                 tv.erase(tv.begin()+i);
00292         }
00293 }
00294 
00295 void scramble(vector<int>& v){
00296         vector<int> tv = vector<int>() ;
00297         while(v.size()>0){
00298                 tv.push_back(v[0]);
00299                 v.erase(v.begin());
00300         }
00301         int i = 0 ;
00302         while(tv.size()>0){
00303                 i = rand()%tv.size() ;
00304                 v.push_back(tv[i]);
00305                 tv.erase(tv.begin()+i);
00306         }
00307 }
00308 
00309 string transformString(string pattern , vector<string>* wl, int white_space_distance){
00310         string st;
00311         for( uint i = 0 ; i < pattern.size() ; i++ ){
00312                 int ind = atoi(pattern.substr(i,1).c_str());
00313                 st += wl->at(ind);
00314                 if(i != pattern.size()-1){
00315                         for( int j = 0 ; j< white_space_distance ; j++){
00316                                 st += " ";
00317                         }
00318                 }
00319 
00320         }
00321         return st ;
00322 }
00323 
00324 
00325 ////////////////////////////////////////////////////////////////
00326 ////This is our button factory
00327 ////////////////////////////////////////////////////////////////
00328 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){
00329         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00330         textIm.clear(bgcolor);
00331         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00332         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00333         Uint32 bc = d->getUint32color(bordercolor);
00334         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00335         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00336         SDL_Rect clip;
00337         clip.x = 0 ;
00338         clip.y = 0 ;
00339         clip.w = size.i ;
00340         clip.h = size.j ;
00341         apply_surface(0,0,*surf,*blank,clip);
00342         dumpSurface(surf) ;
00343         return blank ;
00344 }
00345 
00346 ////////////////////////////////////////////////////////////////////////
00347 ////This is the function for creating the keypad, in fact it generates
00348 ////12 buttons and associates the actions to the region for each button
00349 ////////////////////////////////////////////////////////////////////////
00350 
00351 SDL_Surface* getKeyPad(string alphabet,vector<string>* wl ,map<string , SDL_Rect>& buttmap){
00352         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00353         SDL_Rect clip;
00354         clip.x=0;
00355         clip.y=0;
00356         int numofrows = alphabet.size()/3 +1;
00357         if(alphabet.size()%3 != 0 ) numofrows++ ;
00358         int numofcolumns = 3 ;
00359         clip.w= pad->w / numofcolumns ;
00360         clip.h = pad->h / numofrows ;
00361 
00362   //keys for 1 to 9
00363         for( int i = 0 ; i < numofrows*3 ; i++){
00364                 SDL_Surface* but ;
00365                 if((uint)i < alphabet.size()){
00366                         but = getButtonImage(wl->at(i),PixRGB<byte>(0,0,0),PixRGB<byte>(255,255,255),Point2D<int>(pad->w / numofcolumns , pad->h / numofrows),PixRGB<byte>(255, 98 , 25),3);
00367                 }else{
00368                         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);
00369                 }
00370 
00371                 SDL_Rect cl ;
00372                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00373                 cl.w = clip.w ;
00374                 cl.h = clip.h ;
00375                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00376                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00377                 dumpSurface(but);
00378         }
00379         SDL_Rect cl1 ;
00380         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00381         cl1.w = clip.w ;
00382         cl1.h = clip.h ;
00383         buttmap["!"] = cl1 ;
00384         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);
00385         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00386         dumpSurface(but);
00387         SDL_Rect cl2 ;
00388         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00389         cl2.w = clip.w ;
00390         cl2.h = clip.h ;
00391         buttmap[" "] = cl2 ;
00392         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);
00393         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00394         dumpSurface(but);
00395         SDL_Rect cl3 ;
00396         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00397         cl3.w = clip.w ;
00398         cl3.h = clip.h ;
00399         buttmap["*"] = cl3 ;
00400         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);
00401         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00402         dumpSurface(but);
00403         return pad ;
00404 }
00405 
00406 
00407 
00408 
00409 ///////////////////////////////////////////////////////////////////////////
00410 /////this function listens to mouse clicks and then finds the region of the screen
00411 /////associated with the action, buttmap is the map of the region, offset is the offset of
00412 /////buttons
00413 ///////////////////////////////////////////////////////////////////////////
00414 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00415         int quit = 0 ;
00416         string s ;
00417         SDL_Event event ;
00418         while( quit!=2 ){
00419                 while( SDL_PollEvent( &event ) ) {
00420                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00421                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00422                                         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) {
00423                                                 quit = 2 ;
00424                                                 s = it->first ;
00425                                                 break;
00426                                         }
00427 
00428                                 }
00429                         }
00430 
00431                 }
00432         }
00433         return s ;
00434 
00435 }
00436 
00437 
00438 ////////////////////////////////////////////////////
00439 ////This function creates a virtual keypad, creates a map of buttons
00440 ////and their representation area and listens to the button press and at
00441 ////the end returns the keyed digits
00442 ////////////////////////////////////////////////////
00443 string getDigitSequenceFromSubject(string alphabet,vector<string>* wl , uint maxl  ){
00444         d->showCursor(true) ;
00445         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00446         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00447         //now let's get the keypad surface while we get the actions map to regions
00448         SDL_Surface * keypad = getKeyPad(alphabet,wl,*buttmap);
00449         //this will be the offset of displaying the keypad on the screen
00450         SDL_Rect offset ;
00451         offset.x = (d->getWidth() - keypad->w) /2;
00452         offset.y = (d-> getHeight() - keypad->h) /2;
00453         //now let's display the keypad
00454         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00455         //this will hold the final string keyed be the subject
00456         string p = string("") ;
00457         //this is a temporary string holding the last action related to the pressed key
00458         string tp = string("");
00459         //now let's record subject's key press
00460         while( tp.compare("*")!=0 ){
00461                 //this button is actually the display for the current string
00462                 SDL_Surface* dp = getButtonImage(transformString(p,wl,1) ,PixRGB<byte>(195,60,12) ,PixRGB<byte>(255,255,255) ,Point2D<int>(d->getWidth()/2,d->getHeight() /15) ,PixRGB<byte>(0,25,180) , 4) ;
00463                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00464                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00465                 //now let's listen to button events
00466                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00467                 dumpSurface(dp) ;
00468                 if(tp.compare("!")==0 && p.size()>=0 ) {
00469                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00470                 }else{
00471                         if(p.size() < maxl && tp.compare("*")!=0) {
00472                                 p +=tp ;
00473                         }
00474 
00475                 }
00476 
00477         }
00478         buttmap = 0 ;
00479         dumpSurface(keypad) ;
00480         d->clearScreen() ;
00481         return p ;
00482 
00483 }
00484 
00485 
00486 
00487 ///////////////////////////////////////////////////////////////
00488 //////gets the test string, answer and the mode and identifies if
00489 //////the answer matches the thing it should be, mode=0 checks if
00490 //////if the answer and test string simply the same, mode=1 matches
00491 //////the answer against the ascending sorted string of the test string
00492 //////mode=2 compares the answer against the descending sorted of
00493 //////the test string
00494 ///////////////////////////////////////////////////////////////
00495 bool isAnswerCorrect(string test , string answer , int mode){
00496 
00497         if(mode == 0 && answer.compare(test)==0) return true ;
00498 
00499         if(mode == 1 && answer.compare(ascSort(test))==0) return true ;
00500 
00501         if(mode == 2 && answer.compare(desSort(test))==0) return true ;
00502 
00503         return false;
00504 }
00505 
00506 
00507 
00508 int addArgument(const string st,const string delim="="){
00509         int i = st.find(delim) ;
00510         argMap[st.substr(0,i)] = st.substr(i+1);
00511 
00512         return 0 ;
00513 }
00514 
00515 std::string getArgumentValue(string arg){
00516         return argMap[arg] ;
00517 }
00518 
00519 std::string getUsageComment(){
00520 
00521         string com = string("\nlist of arguments : \n");
00522 
00523         com += "\nlogfile=[logfilename.psy] {default = psycho-stroop-concurrent.psy}\n" ;
00524         com += "\nmemo=[a_string_without_white_space]\n";
00525         com += "\nstring-size=[>0](the size of string){default=4} \n";
00526         com += "\nsubject=[subject_name] \n" ;
00527         com += "\nnum-of-sorting-trials=[>1](number of trials){default=10}\n";
00528         com += "\nnum-of-mem-trials=[>1](number of trials){default=10}\n";
00529         com += "\nstimulus-onset=[>1] (number of frames that the string will remain onset ){default=60}\n";
00530         com += "\nalphabet=[a string of characters](a string of characters){default=0123456789}\n";
00531         com += "\nmode=[1,2](1 for displaying the whole string, 2 displaying one character at a time ){default=1}\n";
00532         com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n";
00533         com += "\nmask=[y/n](whether present a mask after presentation, n for no, y  for yes ){default=n}\n" ;
00534         com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n";
00535         com += "\nwhite-space=[>0](the distance between digits in number of space characters){default=5}\n" ;
00536         com += "\ncue-type=[a/v](a for audio v for visual){default=v}\n";
00537         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00538         com += "\nwords-file=[path to a text file that has words one in each line]{default=./words1.txt}\n";
00539         com += "\nrefresh-calibration=[y/n] {default=n}\n";
00540 
00541         return com ;
00542 }
00543 
00544 
00545 void displayWholeNumber(string s , int onsetTime , int wsd){
00546         int x = (d->getWidth()-s.size()*wsd)/2 ;
00547         int y = (d->getHeight())/2 -10;
00548         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00549         textIm.clear(PixRGB<byte>(128,128,128));
00550         for( uint k = 0 ; k < s.size() ; k++ ){
00551                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00552                 writeText(textIm, Point2D<int>(x+k*wsd,y),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00553         }
00554         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00555         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00556         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00557         dumpSurface(surf);
00558         d->waitFrames(onsetTime);
00559         d->clearScreen() ;
00560 }
00561 
00562 void displayHorizontal(string s , int onsetTime){
00563         int wsd=10 ;
00564         int x = (d->getWidth()-s.size()*wsd)/2 ;
00565         int y = (d->getHeight())/2 -10;
00566         d->displayText(s,Point2D<int>(x,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00567         d->waitFrames(onsetTime);
00568         d->clearScreen() ;
00569 }
00570 
00571 
00572 
00573 
00574 
00575 
00576 void displayLinear(string s , int onsetTime){
00577         int x = (d->getWidth()-s.size()*10)/2 ;
00578         int y = d->getHeight()/2 - 10;
00579         for( uint k = 0 ; k < s.size() ; k++ ){
00580                 d->displayText(s.substr(k,1),Point2D<int>(x+k*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00581                 d->waitFrames(onsetTime);
00582                 d->clearScreen() ;
00583         }
00584 }
00585 
00586 
00587 
00588 
00589 //and this is the function which creates and displays a mask of randomly positioned numbers
00590 void showMask(int frames, string alphabet){
00591         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00592         PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128);
00593         PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0);
00594         textIm.clear(bgcolor);
00595         for(int i = 0 ;  i < 800 ; i++)
00596                 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor);
00597         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00598         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00599         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00600         d->waitFrames(frames) ;
00601         d->clearScreen();
00602         dumpSurface(surf) ;
00603 }
00604 
00605 vector<string> getARandomArray(uint l, vector<string>* wl){
00606         vector<string> testArray;
00607         vector<int> pickedones = vector<int>() ;
00608         for(uint i = 0 ; i < l ; i++){
00609                 int nd;
00610                 do{ nd= rand()% wl->size() ; }while(itIsInThere(nd,pickedones)) ;
00611                 pickedones.push_back(nd);
00612                 testArray.push_back(wl->at(nd));
00613         }
00614       return   testArray ;
00615 }
00616 
00617 
00618 int readWordFile(const char* filename, vector<string>* wl){
00619         ifstream inFile(filename, ios::in);
00620         if (! inFile)
00621    {
00622       return -1;
00623    }
00624 
00625    char ch[1000];
00626    while (inFile.getline(ch , 500)){
00627            string line = ch;
00628                 LINFO("profile reader reads : '%s'...", line.c_str());
00629                 wl->push_back(line);
00630         }
00631 
00632         return 0 ;
00633 }
00634 
00635 
00636 
00637 string switch_neighbors(string s){
00638         string os ;
00639         uint p = random()%(s.size()-1);
00640         if(p < s.size()-2){
00641                 os = s.substr(0,p)+s.substr(p+1,1)+s.substr(p,1)+s.substr(p+2) ;
00642         }else{
00643                 os = s.substr(0,p)+s.substr(p+1,1)+s.substr(p,1) ;
00644         }
00645 
00646 
00647         return os ;
00648 }
00649 
00650 string replaceOne(string s,string alphabet="0123456789"){
00651         vector<int> pickedones ;
00652         for( uint i = 0 ; i < s.size() ;i++ ){
00653                 pickedones.push_back(atoi(s.substr(i,1).c_str()));
00654         }
00655         int nd;
00656         do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones));
00657         string os;
00658         os = stringify(nd);
00659         os += s.substr(1);
00660         return os ;
00661 }
00662 
00663 extern "C" int main(const int argc, char** argv)
00664 {
00665 
00666         MYLOGVERB = LOG_INFO;  // suppress debug messages
00667         //let's push the initial value for the parameters
00668         argMap["experiment"]="working memory single task - sorting";
00669         argMap["logfile"]="psycho-sorting-const.psy" ;
00670         argMap["string-size"]="4" ;
00671         argMap["subject"]="" ;
00672         argMap["memo"]="" ;
00673         argMap["stimulus-onset"]="60" ;
00674         argMap["challenge-onset"]="20" ;
00675         argMap["alphabet"]="0123456789";
00676         argMap["mode"]="1" ;
00677         argMap["cue-wait-frames"]="0" ;
00678         argMap["mask"]="n" ;
00679         argMap["cue-onset-frames"] = "3" ;
00680         argMap["white-space"] = "5" ;
00681         argMap["cue-type"] = "v" ;
00682         argMap["sound-dir"]="..";
00683         argMap["num-of-sorting-trials"] = "10" ;
00684         argMap["num-of-mem-trials"] = "10" ;
00685         argMap["words-file"]="./words1.txt";
00686         argMap["refresh-calibration"]="n";
00687         manager.addSubComponent(d);
00688         nub::soft_ref<EventLog> el(new EventLog(manager));
00689         manager.addSubComponent(el);
00690         d->setEventLog(el);
00691         nub::soft_ref<EyeTrackerConfigurator>
00692                         etc(new EyeTrackerConfigurator(manager));
00693           manager.addSubComponent(etc);
00694 
00695         if (manager.parseCommandLine(argc, argv,
00696             "at least one argument needed", 1, -1)==false){
00697                     cout<<getUsageComment()<<endl;
00698                     return(1);
00699             }
00700 
00701             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00702                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00703             }
00704 
00705             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00706            manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00707            nub::soft_ref<EyeTracker> eyet = etc->getET();
00708            d->setEyeTracker(eyet);
00709            eyet->setEventLog(el);
00710 
00711 
00712   // let's get all our ModelComponent instances started:
00713             manager.start();
00714             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00715   // let's display an ISCAN calibration grid:
00716             d->clearScreen();
00717             d->displayISCANcalib();
00718             d->waitForMouseClick();
00719             d->displayText("Here the experiment starts! click to start!");
00720             d->waitForMouseClick();
00721             d->clearScreen();
00722         //let's see in what mode the user like to run the program
00723             int mode = atoi(argMap["mode"].c_str());
00724             vector<long> correctAnswersTiming;
00725             vector<long> incorrectAnswersTiming;
00726             vector<long> allTiming ;
00727             vector<string>* wordsList = new vector<string>();
00728             int correctMemory = 0 ;
00729             int incorrectMemory = 0 ;
00730             int stringSize = atoi(argMap["string-size"].c_str());
00731             int onsetDel = atoi(argMap["stimulus-onset"].c_str()) ;
00732             //int ch_onsetDel = atoi(argMap["challenge-onset"].c_str()) ;
00733             int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ;
00734             int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ;
00735             int white_space_distance = atoi(argMap["white-space"].c_str());
00736             int num_of_sorting_task = atoi(argMap["num-of-sorting-trials"].c_str()) ;
00737             int num_of_mem_task = atoi(argMap["num-of-mem-trials"].c_str()) ;
00738             string wordsFile = argMap["words-file"];
00739             if(readWordFile(wordsFile.c_str(),wordsList)==-1) {
00740                         cout<<"can\'t find the words file";
00741                         return(1);
00742                 }
00743 
00744             //let's do calibration
00745             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00746             int cl = d->waitForMouseClick();
00747             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00748             d->clearScreen() ;
00749 
00750             Mix_Music* recallCueMusic = NULL;
00751             Mix_Music* sortCueMusic = NULL;
00752             if(argMap["cue-type"].compare("a")==0){
00753                      //now let's open the audio channel
00754                     if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00755                             LINFO( "did not open the mix-audio") ;
00756                             return -1 ;
00757                     }
00758 
00759                         string str = argMap["sound-dir"]+"/recall.wav" ;
00760                         recallCueMusic = Mix_LoadMUS(str.c_str());
00761                         str = argMap["sound-dir"]+"/sort.wav" ;
00762                         sortCueMusic = Mix_LoadMUS(str.c_str());
00763             }
00764             vector<int>* taskVector = new vector<int>();
00765             for(int i = 0 ; i < (int)(num_of_sorting_task/4) ; i++) {
00766                     taskVector->push_back(1);
00767                     taskVector->push_back(2);
00768                     taskVector->push_back(3);
00769                     taskVector->push_back(4);
00770                     //taskVector->push_back(5);
00771                     //taskVector->push_back(6);
00772 
00773             }
00774             for(int i = 0 ; i < num_of_mem_task ; i++)  taskVector->push_back(0);
00775             scramble(*taskVector);
00776             for( int r = 0 ; (int)r < (int)taskVector->size() ; r++ ){
00777                     if(argMap["refresh-calibration"].compare("y")==0 && r ==(int)taskVector->size()/2){
00778                             d->displayText("STOP HERE AND STRETCH A little BIT!");
00779                             cl = d->waitForMouseClick();
00780                             d->displayText("Click if you are ready.");
00781                             cl = d->waitForMouseClick();
00782                              //let's do calibration
00783                             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00784                             cl = d->waitForMouseClick();
00785                             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00786                             d->clearScreen() ;
00787 
00788                     }
00789 
00790                             int task = taskVector->at(r) ;
00791                             d->pushEvent("**************************************") ;
00792                             d->showCursor(true);
00793                             d->displayText("click one of the  mouse buttons to start!");
00794                             d->waitForMouseClick() ;
00795                             d->showCursor(false) ;
00796                             string testString ;
00797                             testString = getARandomString(stringSize, "0123456789");
00798                             if(stringSize == 5){
00799                                 switch( task ){
00800                                 case 1 : testString = get34012(ascSort(testString));break ;
00801                                 case 2 : testString = get21043(ascSort(testString));break ;
00802                                 case 3 : testString = get41230(ascSort(testString));break ;
00803                                 case 4 : testString = get03214(ascSort(testString));break ;
00804                                 case 5 : testString = get42130(ascSort(testString));break ;
00805                                 case 6 : testString = get03124(ascSort(testString));break ;
00806                                 }
00807                             }
00808                            if(stringSize == 4){
00809                                 switch( task ){
00810                                 case 1 : testString = get0321(ascSort(testString));break ;
00811                                 case 2 : testString = get1230(ascSort(testString));break ;
00812                                 case 3 : testString = get3012(ascSort(testString));break ;
00813                                 case 4 : testString = get2103(ascSort(testString));break ;
00814                                 }
00815                             }
00816 
00817                             d->clearScreen() ;
00818                             d->displayFixationBlink();
00819                             switch( mode ){
00820                                     case 1 : displayHorizontal(transformString(testString,wordsList,white_space_distance),onsetDel);break ;
00821                                     case 2 : displayLinear(transformString(testString,wordsList,white_space_distance),onsetDel) ; break ;
00822                             }
00823                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,"abcdefghijklmnopqrstuvwxyz");
00824                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00825                             d->displayFixation() ;
00826                             if(argMap["cue-type"].compare("v")==0){
00827                                     d->displayRedDotFixation();
00828                             }else{
00829                                 if(task == 0){if( Mix_PlayMusic( recallCueMusic, 0 ) == -1 ) { return 1; }
00830                                     while( Mix_PlayingMusic() == 1 ){}
00831                                 }else{
00832                                     if( Mix_PlayMusic( sortCueMusic, 0 ) == -1 ) { return 1; }
00833                                     while( Mix_PlayingMusic() == 1 ){}
00834                                 }
00835 
00836                             }
00837 
00838 
00839                             d->clearScreen() ;
00840                             string imst ;
00841                             string chstr;
00842                             if(task!=0){
00843                                     imst= "===== Showing image: def_"+stringify(task)+"_"+testString+".png =====";
00844                                     d->pushEvent("the sequence for operation is : "+testString) ;
00845                                     d->pushEvent(imst);
00846                                     eyet->track(true);
00847                                     d->waitForMouseClick();
00848                                     eyet->track(false);
00849                                     d->pushEvent("task ends") ;
00850                                     string  answer = getDigitSequenceFromSubject("0123456789",wordsList , stringSize);
00851                                     d->pushEvent("subject keyed : "+answer);
00852                                     if(answer.compare(ascSort(testString))==0){
00853                                             d->pushEvent("answer was correct");
00854                                     }else{
00855                                             d->pushEvent("answer was incorrect");
00856                                     }
00857                             }else{
00858                                     string  answer = getDigitSequenceFromSubject("0123456789",wordsList , stringSize);
00859                                     d->pushEvent("subject keyed : "+answer);
00860                                     if(answer.compare(testString)==0){
00861                                             d->pushEvent("recall was correct");
00862                                             correctMemory++ ;
00863                                     }else{
00864                                             d->pushEvent("recall was incorrect");
00865                                             incorrectMemory++ ;
00866                                     }
00867                             }
00868                             /*if(task!=0){
00869                                 imst= "===== Showing image: def_"+stringify(task)+"_"+testString+".png =====";
00870                                 d->pushEvent("the sequence for operation is : "+testString) ;
00871                                 d->pushEvent(imst);
00872                                 eyet->track(true);
00873                                 d->waitForMouseClick();
00874                                 eyet->track(false);
00875                                 d->pushEvent("task ends") ;
00876                                 int challenge = random()%2 ;
00877 
00878                                 if(challenge == 0 ) {
00879                                         chstr = ascSort(testString);
00880                                         displayHorizontal(transformString(chstr,wordsList,white_space_distance),ch_onsetDel);
00881                                 }else{
00882                                         chstr = ascSort(replaceOne(testString));
00883                                         displayHorizontal(transformString(chstr,wordsList,white_space_distance),ch_onsetDel);
00884                                 }
00885                                 d->pushEvent("subject was challenged by "+chstr);
00886                                 string  answer = getDigitSequenceFromSubject("0123456789",wordsList , stringSize);
00887                                 d->pushEvent("subject keyed : "+answer);
00888                                 if(answer.compare("Y")==0){
00889                                     if(challenge==0){
00890                                         d->pushEvent("answer was correct");
00891                                     }else{
00892                                         d->pushEvent("answer was incorrect");
00893                                     }
00894                                 }
00895                                 if(answer.compare("N")==0){
00896                                     if(challenge==1){
00897                                         d->pushEvent("answer was correct");
00898                                     }else{
00899                                         d->pushEvent("answer was incorrect");
00900                                     }
00901                                 }
00902                                 if(answer.compare("~")==0){
00903                                     d->pushEvent("confused");
00904                                 }
00905                             }else{
00906                                 d->pushEvent("the sequence for recall task is : "+testString) ;
00907                                 int challenge = random()%2 ;
00908                                 if(challenge == 0 ) {
00909                                         chstr = testString;
00910                                         displayHorizontal(transformString(chstr,wordsList,white_space_distance),ch_onsetDel);
00911                                 }else{
00912                                         chstr = switch_neighbors(testString);
00913                                         displayHorizontal(transformString(chstr,wordsList,white_space_distance),ch_onsetDel);
00914                                 }
00915                                 d->pushEvent("subject was challenged by "+chstr);
00916                                 string  answer = getDigitSequenceFromSubject("0123456789",wordsList , stringSize);
00917                                 d->pushEvent("subject keyed : "+answer);
00918                                 if(answer.compare("Y")==0){
00919                                     if(challenge==0){
00920                                         correctMemory++;
00921                                         d->pushEvent("answer was correct");
00922                                     }else{
00923                                         incorrectMemory++ ;
00924                                         d->pushEvent("answer was incorrect");
00925                                     }
00926                                 }
00927                                 if(answer.compare("N")==0){
00928                                     if(challenge==1){
00929                                         correctMemory++;
00930                                         d->pushEvent("recall was correct");
00931                                     }else{
00932                                         d->pushEvent("recall was incorrect");
00933                                         incorrectMemory++ ;
00934                                     }
00935                                 }
00936                                 if(answer.compare("~")==0){
00937                                     d->pushEvent("confused");
00938                                     incorrectMemory++ ;
00939                                 }
00940                             }*/
00941 
00942             }
00943             d->pushEvent("number of correct memory recall : "+ stringify(correctMemory)) ;
00944             d->pushEvent("number of incorrect memory recall : "+ stringify(incorrectMemory)) ;
00945             d->clearScreen();
00946             d->displayText("Experiment complete. Thank you!");
00947             d->waitForMouseClick();
00948             taskVector = 0 ;
00949           // stop all our ModelComponents
00950             manager.stop();
00951 
00952 
00953           // all done!
00954             return 0;
00955 }
00956 
00957 #endif // INVT_HAVE_LIBSDL_IMAGE
00958 
Generated on Sun May 8 08:40:09 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3