psycho-sc.C

00001 /*!@file AppPsycho/psycho-sorting-cost.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/psycho-sc.C $
00035 // $Id: psycho-sc.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 <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 #include <iostream>
00066 #include <fstream>
00067 #include <set>
00068 #include <algorithm>
00069 #include <ctime>
00070 
00071 #ifndef INVT_HAVE_LIBSDL_IMAGE
00072 #include <cstdio>
00073 int main()
00074 {
00075         fprintf(stderr, "The SDL_image library must be installed to use this program\n");
00076         return 1;
00077 }
00078 
00079 #else
00080 
00081 
00082 
00083 using namespace std;
00084 
00085 // ######################################################################
00086 
00087 ModelManager manager("Psycho-Concurrent-Digit");
00088 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00089 map<uint,uint> testMap ;
00090 map<string,string> argMap ;
00091 map<string,vector<SDL_Rect*>*> clipsmap;
00092 
00093 //////////////////////////////////////////////
00094 // a functionf for stringigying things
00095 //////////////////////////////////////////////
00096 template <class T> std::string stringify(T i)
00097 {
00098         ostringstream o ;
00099         o << i ;
00100         return o.str();
00101 }
00102 
00103 
00104 double getAvarage(vector<long> v){
00105         double f = 0.0 ;
00106         for( uint i = 0 ; i <  v.size() ; i++ ){
00107                 f += v[i] ;
00108         }
00109         if (v.size()!=0) return f/v.size() ;
00110         return -1 ;
00111 }
00112 
00113 double getVariance(vector<long> v){
00114         double m = getAvarage(v);
00115         double var = 0.0 ;
00116         for( uint i = 0 ; i < v.size(); i++ ){
00117                 var += (v[i]-m)*(v[i]-m) ;
00118         }
00119         if (v.size()!=0) return var/v.size() ;
00120         return -1 ;
00121 }
00122 
00123 bool itIsInThere(int x , vector<int> bag){
00124         for( uint i=0 ; i < bag.size(); i++ ){
00125                 if(x == bag[i]) return true ;
00126         }
00127         return false ;
00128 }
00129 
00130 
00131 string get34012(string s){
00132         string t = "";
00133         t = s.substr(3,1)+s.substr(4,1)+s.substr(0,1)+s.substr(1,1)+s.substr(2,1);
00134         return t ;
00135 }
00136 
00137 string get21043(string s){
00138         string t = "";
00139         t = s.substr(2,1)+s.substr(1,1)+s.substr(0,1)+s.substr(4,1)+s.substr(3,1);
00140         return t ;
00141 }
00142 
00143 string get41230(string s){
00144         string t = "";
00145         t = s.substr(4,1)+s.substr(1,1)+s.substr(2,1)+s.substr(3,1)+s.substr(0,1);
00146         return t ;
00147 }
00148 
00149 string get03214(string s){
00150         string t = "";
00151         t = s.substr(0,1)+s.substr(3,1)+s.substr(2,1)+s.substr(1,1)+s.substr(4,1);
00152         return t ;
00153 }
00154 
00155 string get42130(string s){
00156         string t="";
00157         t = s.substr(4,1)+s.substr(2,1)+s.substr(1,1)+s.substr(3,1)+s.substr(0,1);
00158         return t ;
00159 }
00160 
00161 
00162 string get03124(string s){
00163         string t = "" ;
00164         t = s.substr(0,1)+s.substr(3,1)+s.substr(1,2)+s.substr(2,1)+s.substr(4,1);
00165         return t ;
00166 }
00167 ////////////////////////////////////////////////////////////////////
00168 //// gets a string as the argument and returns a string composed of
00169 //// characters of the first string sorted in the ascending order
00170 ///////////////////////////////////////////////////////////////////
00171 string ascSort(string st)
00172 {
00173         string res = "" ;
00174         vector<string> v = vector<string>();
00175         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00176 
00177         std::sort(v.begin(), v.end());
00178 
00179         for ( uint i = 0 ; i < v.size() ; i++ ){
00180                 res += v[i] ;
00181         }
00182         return res;
00183 }
00184 
00185 
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //// gets a string as the argument and returns a string composed of
00189 //// characters of the first string sorted in the descending order
00190 ///////////////////////////////////////////////////////////////////
00191 string desSort(string st)
00192 {
00193         string res = "" ;
00194         vector<string> v = vector<string>();
00195         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00196         std::sort(v.begin(), v.end());
00197         std::reverse(v.begin(), v.end());
00198         for ( uint i = 0 ; i < v.size() ; i++ ){
00199                 res += v[i] ;
00200         }
00201         return res;
00202 }
00203 
00204 
00205 
00206 
00207 
00208 ////////////////////////////////////////////////////////
00209 ///// 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
00210 //highest metric value in 1000000 times try will be returned
00211 ////////////////////////////////////////////////////////
00212 
00213 string getARandomString(uint l, string alphabet="0123456789"){
00214 
00215         string test = string("") ;
00216         test = "" ;
00217         string tp = string("") ;
00218         vector<int> pickedones = vector<int>() ;
00219         for(uint i = 0 ; i < l ; i++){
00220                 int nd;
00221                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00222                 pickedones.push_back(nd);
00223                 tp = alphabet.substr(nd,1) ;
00224                 test += tp ;
00225         }
00226 
00227         return test ;
00228 }
00229 
00230 ///////////////////////////////////////////////////////
00231 //this function is not called in this program, but it generates a random string and it will show it in
00232 //a random place on the screen.
00233 //////////////////////////////////////////////////////
00234 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10  ){
00235         d->clearScreen() ;
00236         vector<int> pickedones = vector<int>() ;
00237         string test = string("") ;
00238         string tp = string("") ;
00239         for(uint i = 0 ; i < l ; i++){
00240                 int nd;
00241                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00242                 pickedones.push_back(nd);
00243                 tp = alphabet.substr(nd,1) ;
00244                 test += tp ;
00245         }
00246         d->displayText(test,true,0) ;
00247         d->waitFrames(displayFrame) ;
00248         d->clearScreen() ;
00249         return test ;
00250 }
00251 
00252 
00253 ////////////////////////////////////////////////////////
00254 ///////this will change the order of elements in a vector to a random order
00255 ////////////////////////////////////////////////////////
00256 void scramble(vector<string>& v){
00257         vector<string> tv = vector<string>() ;
00258         while(v.size()>0){
00259                 tv.push_back(v[0]);
00260                 v.erase(v.begin());
00261         }
00262         int i = 0 ;
00263         while(tv.size()>0){
00264                 i = rand()%tv.size() ;
00265                 v.push_back(tv[i]);
00266                 tv.erase(tv.begin()+i);
00267         }
00268 }
00269 
00270 void scramble(vector<int>& v){
00271         vector<int> tv = vector<int>() ;
00272         while(v.size()>0){
00273                 tv.push_back(v[0]);
00274                 v.erase(v.begin());
00275         }
00276         int i = 0 ;
00277         while(tv.size()>0){
00278                 i = rand()%tv.size() ;
00279                 v.push_back(tv[i]);
00280                 tv.erase(tv.begin()+i);
00281         }
00282 }
00283 
00284 ////////////////////////////////////////////////////////////////
00285 ////This is our button factory
00286 ////////////////////////////////////////////////////////////////
00287 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){
00288         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00289         textIm.clear(bgcolor);
00290         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00291         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00292         Uint32 bc = d->getUint32color(bordercolor);
00293         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00294         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00295         SDL_Rect clip;
00296         clip.x = 0 ;
00297         clip.y = 0 ;
00298         clip.w = size.i ;
00299         clip.h = size.j ;
00300         apply_surface(0,0,*surf,*blank,clip);
00301         dumpSurface(surf) ;
00302         return blank ;
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////////
00306 ////This is the function for creating the keypad, in fact it generates
00307 ////12 buttons and associates the actions to the region for each button
00308 ////////////////////////////////////////////////////////////////////////
00309 
00310 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00311         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00312         SDL_Rect clip;
00313         clip.x=0;
00314         clip.y=0;
00315         int numofrows = alphabet.size()/3 +1;
00316         if(alphabet.size()%3 != 0 ) numofrows++ ;
00317         int numofcolumns = 3 ;
00318         clip.w= pad->w / numofcolumns ;
00319         clip.h = pad->h / numofrows ;
00320 
00321   //keys for 1 to 9
00322         for( int i = 0 ; i < numofrows*3 ; i++){
00323                 SDL_Surface* but ;
00324                 if((uint)i < alphabet.size()){
00325                         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);
00326                 }else{
00327                         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);
00328                 }
00329 
00330                 SDL_Rect cl ;
00331                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00332                 cl.w = clip.w ;
00333                 cl.h = clip.h ;
00334                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00335                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00336                 dumpSurface(but);
00337         }
00338         SDL_Rect cl1 ;
00339         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00340         cl1.w = clip.w ;
00341         cl1.h = clip.h ;
00342         buttmap["!"] = cl1 ;
00343         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);
00344         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00345         dumpSurface(but);
00346         SDL_Rect cl2 ;
00347         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00348         cl2.w = clip.w ;
00349         cl2.h = clip.h ;
00350         buttmap[" "] = cl2 ;
00351         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);
00352         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00353         dumpSurface(but);
00354         SDL_Rect cl3 ;
00355         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00356         cl3.w = clip.w ;
00357         cl3.h = clip.h ;
00358         buttmap["*"] = cl3 ;
00359         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);
00360         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00361         dumpSurface(but);
00362         return pad ;
00363 }
00364 
00365 
00366 
00367 
00368 ///////////////////////////////////////////////////////////////////////////
00369 /////this function listens to mouse clicks and then finds the region of the screen
00370 /////associated with the action, buttmap is the map of the region, offset is the offset of
00371 /////buttons
00372 ///////////////////////////////////////////////////////////////////////////
00373 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00374         int quit = 0 ;
00375         string s ;
00376         SDL_Event event ;
00377         while( quit!=2 ){
00378                 while( SDL_PollEvent( &event ) ) {
00379                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00380                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00381                                         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) {
00382                                                 quit = 2 ;
00383                                                 s = it->first ;
00384                                                 break;
00385                                         }
00386 
00387                                 }
00388                         }
00389 
00390                 }
00391         }
00392         return s ;
00393 
00394 }
00395 
00396 
00397 ////////////////////////////////////////////////////
00398 ////This function creates a virtual keypad, creates a map of buttons
00399 ////and their representation area and listens to the button press and at
00400 ////the end returns the keyed digits
00401 ////////////////////////////////////////////////////
00402 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){
00403         d->showCursor(true) ;
00404         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00405         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00406         //now let's get the keypad surface while we get the actions map to regions
00407         SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00408         //this will be the offset of displaying the keypad on the screen
00409         SDL_Rect offset ;
00410         offset.x = (d->getWidth() - keypad->w) /2;
00411         offset.y = (d-> getHeight() - keypad->h) /2;
00412         //now let's display the keypad
00413         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00414         //this will hold the final string keyed be the subject
00415         string p = string("") ;
00416         //this is a temporary string holding the last action related to the pressed key
00417         string tp = string("");
00418         //now let's record subject's key press
00419         while( tp.compare("*")!=0 ){
00420                 //this button is actually the display for the current string
00421                 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) ;
00422                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00423                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00424                 //now let's listen to button events
00425                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00426                 dumpSurface(dp) ;
00427                 if(tp.compare("!")==0 && p.size()>=0 ) {
00428                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00429                 }else{
00430                         if(p.size() < maxl && tp.compare("*")!=0) {
00431                                 p +=tp ;
00432                         }
00433 
00434                 }
00435 
00436         }
00437         buttmap = 0 ;
00438         dumpSurface(keypad) ;
00439         d->clearScreen() ;
00440         return p ;
00441 
00442 }
00443 
00444 
00445 
00446 ///////////////////////////////////////////////////////////////
00447 //////gets the test string, answer and the mode and identifies if
00448 //////the answer matches the thing it should be, mode=0 checks if
00449 //////if the answer and test string simply the same, mode=1 matches
00450 //////the answer against the ascending sorted string of the test string
00451 //////mode=2 compares the answer against the descending sorted of
00452 //////the test string
00453 ///////////////////////////////////////////////////////////////
00454 bool isAnswerCorrect(string test , string answer , int mode){
00455 
00456         if(mode == 0 && answer.compare(test)==0) return true ;
00457 
00458         if(mode == 1 && answer.compare(ascSort(test))==0) return true ;
00459 
00460         if(mode == 2 && answer.compare(desSort(test))==0) return true ;
00461 
00462         return false;
00463 }
00464 
00465 
00466 
00467 int addArgument(const string st,const string delim="="){
00468         int i = st.find(delim) ;
00469         argMap[st.substr(0,i)] = st.substr(i+1);
00470 
00471         return 0 ;
00472 }
00473 
00474 std::string getArgumentValue(string arg){
00475         return argMap[arg] ;
00476 }
00477 
00478 std::string getUsageComment(){
00479 
00480         string com = string("\nlist of arguments : \n");
00481 
00482         com += "\nlogfile=[logfilename.psy] {default = psycho-stroop-concurrent.psy}\n" ;
00483         com += "\nmemo=[a_string_without_white_space]\n";
00484         com += "\nstring-size=[>0](the size of string){default=5} \n";
00485         com += "\nsubject=[subject_name] \n" ;
00486         com += "\nnum-of-sorting-trials=[>1](number of trials){default=10}\n";
00487         com += "\nnum-of-mem-trials=[>1](number of trials){default=10}\n";
00488         com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n";
00489         com += "\nalphabet=[a string of characters](a string of characters){default=0123456789}\n";
00490         com += "\nmode=[1,2,3,4](1 for displaying the whole number, 2 for random display , 3 for linear flashing disply , 4 for linear reverse flashing){default=1}\n";
00491         com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n";
00492         com += "\nmask=[y/n](whether present a mask after presentation, n for no, y  for yes ){default=n}\n" ;
00493         com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n";
00494         com += "\nwhite-space=[>0](the distance between digits in display){default=20}\n" ;
00495         com += "\ncue-type=[a/v](a for audio v for visual){default=v}\n";
00496         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00497 
00498         return com ;
00499 }
00500 
00501 
00502 void displayWholeNumber(string s , int onsetTime , int wsd){
00503         int x = (d->getWidth()-s.size()*wsd)/2 ;
00504         int y = (d->getHeight())/2 -10;
00505         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00506         textIm.clear(PixRGB<byte>(128,128,128));
00507         for( uint k = 0 ; k < s.size() ; k++ ){
00508                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00509                 writeText(textIm, Point2D<int>(x+k*wsd,y),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00510         }
00511         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00512         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00513         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00514         dumpSurface(surf);
00515         d->waitFrames(onsetTime);
00516         d->clearScreen() ;
00517 }
00518 
00519 void displayWholeNumberVertically(string s , int onsetTime , int wsd){
00520         int x = (d->getWidth())/2 ;
00521         int y = (d->getHeight()-s.size()*wsd)/2 ;
00522         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00523         textIm.clear(PixRGB<byte>(128,128,128));
00524         for( uint k = 0 ; k < s.size() ; k++ ){
00525                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00526                 writeText(textIm, Point2D<int>(x,y+k*wsd),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00527         }
00528         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00529         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00530         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00531         dumpSurface(surf);
00532         d->waitFrames(onsetTime);
00533         d->clearScreen() ;
00534 }
00535 
00536 void displayRandom(string s , int onsetTime){
00537         for( uint k = 0 ; k < s.size() ; k++ ){
00538                 int x = 9*d->getWidth()/20 + rand()%(d->getWidth()/10);
00539                 int y = 9*d->getHeight()/20 + rand()%(d->getHeight()/10) ;
00540                 d->displayText(s.substr(k,1),Point2D<int>(x,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00541                 d->waitFrames(onsetTime);
00542                 d->clearScreen() ;
00543         }
00544 }
00545 
00546 void displayLinear(string s , int onsetTime){
00547         int x = (d->getWidth()-s.size()*10)/2 ;
00548         int y = d->getHeight()/2 - 10;
00549         for( uint k = 0 ; k < s.size() ; k++ ){
00550                 d->displayText(s.substr(k,1),Point2D<int>(x+k*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00551                 d->waitFrames(onsetTime);
00552                 d->clearScreen() ;
00553         }
00554 }
00555 
00556 void displayLinearReverse(string s , int onsetTime){
00557         int x = (d->getWidth()-s.size()*10)/2 ;
00558         int y = d->getHeight()/2 - 10;
00559         for( uint k = 0 ; k < s.size() ; k++ ){
00560                 d->displayText(s.substr(k,1),Point2D<int>(x+(s.size()-k)*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00561                 d->waitFrames(onsetTime);
00562                 d->clearScreen() ;
00563         }
00564 }
00565 void displayLinearRandom(string s , int onsetTime){
00566         int x = (d->getWidth()-s.size()*10)/2 ;
00567         int y = d->getHeight()/2 - 10;
00568         for( uint k = 0 ; k < s.size() ; k++ ){
00569                 d->displayText(s.substr(k,1),Point2D<int>(x+ (random()%s.size())*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00570                 d->waitFrames(onsetTime);
00571                 d->clearScreen() ;
00572         }
00573 }
00574 
00575 void displayLinearRandomVertically(string s , int onsetTime){
00576         int x = (d->getWidth())/2 ;
00577         int y = (d->getHeight()-s.size()*10)/2 - 10;
00578         for( uint k = 0 ; k < s.size() ; k++ ){
00579                 d->displayText(s.substr(k,1),Point2D<int>(x, (random()%s.size())*10+y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00580                 d->waitFrames(onsetTime);
00581                 d->clearScreen() ;
00582         }
00583 }
00584 
00585 void displayLinearRandomNoRepeating(string s , int onsetTime){
00586         int x = (d->getWidth()-s.size()*10)/2 ;
00587         int y = d->getHeight()/2 - 10;
00588         for( uint k = 0 ; k < s.size() ; k++ ){
00589                 d->displayText(s.substr(k,1),Point2D<int>(x+ (random()%s.size())*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00590                 d->waitFrames(onsetTime);
00591                 d->clearScreen() ;
00592         }
00593 }
00594 
00595 //and this is the function which creates and displays a mask of randomly positioned numbers
00596 void showMask(int frames, string alphabet="0123456789"){
00597         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00598         PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128);
00599         PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0);
00600         textIm.clear(bgcolor);
00601         for(int i = 0 ;  i < 800 ; i++)
00602                 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor);
00603         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00604         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00605         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00606         d->waitFrames(frames) ;
00607         d->clearScreen();
00608         dumpSurface(surf) ;
00609 }
00610 
00611 extern "C" int main(const int argc, char** argv)
00612 {
00613 
00614         MYLOGVERB = LOG_INFO;  // suppress debug messages
00615         //let's push the initial value for the parameters
00616         argMap["experiment"]="working memory single task - sorting";
00617         argMap["logfile"]="psycho-sorting-const.psy" ;
00618         argMap["string-size"]="5" ;
00619         argMap["subject"]="" ;
00620         argMap["memo"]="" ;
00621         argMap["digit-onset"]="10" ;
00622         argMap["alphabet"]="0123456789";
00623         argMap["mode"]="1" ;
00624         argMap["cue-wait-frames"]="0" ;
00625         argMap["mask"]="n" ;
00626         argMap["cue-onset-frames"] = "3" ;
00627         argMap["white-space"] = "20" ;
00628         argMap["cue-type"] = "v" ;
00629         argMap["sound-dir"]="..";
00630         argMap["num-of-sorting-trials"] = "10" ;
00631         argMap["num-of-mem-trials"] = "10" ;
00632         manager.addSubComponent(d);
00633         nub::soft_ref<EventLog> el(new EventLog(manager));
00634         manager.addSubComponent(el);
00635         d->setEventLog(el);
00636         nub::soft_ref<EyeTrackerConfigurator>
00637                         etc(new EyeTrackerConfigurator(manager));
00638           manager.addSubComponent(etc);
00639 
00640         if (manager.parseCommandLine(argc, argv,
00641             "at least one argument needed", 1, -1)==false){
00642                     cout<<getUsageComment()<<endl;
00643                     return(1);
00644             }
00645 
00646             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00647                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00648             }
00649 
00650             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00651         manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00652         nub::soft_ref<EyeTracker> eyet = etc->getET();
00653         d->setEyeTracker(eyet);
00654         eyet->setEventLog(el);
00655 
00656 
00657   // let's get all our ModelComponent instances started:
00658             manager.start();
00659             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00660   // let's display an ISCAN calibration grid:
00661             d->clearScreen();
00662             d->displayISCANcalib();
00663             d->waitForMouseClick();
00664             d->displayText("Here the experiment starts! click to start!");
00665             d->waitForMouseClick();
00666             d->clearScreen();
00667         //let's see in what mode the user like to run the program
00668             int mode = atoi(argMap["mode"].c_str());
00669             vector<long> correctAnswersTiming;
00670             vector<long> incorrectAnswersTiming;
00671             vector<long> allTiming ;
00672             int correctMemory = 0 ;
00673             int incorrectMemory = 0 ;
00674             int stringSize = atoi(argMap["string-size"].c_str());
00675             int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00676             int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ;
00677             int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ;
00678             int white_sapece_distance = atoi(argMap["white-space"].c_str());
00679             int num_of_sorting_task = atoi(argMap["num-of-sorting-trials"].c_str()) ;
00680             int num_of_mem_task = atoi(argMap["num-of-mem-trials"].c_str()) ;
00681             //let's do calibration
00682             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00683             int cl = d->waitForMouseClick();
00684             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00685             d->clearScreen() ;
00686 
00687             Mix_Music* recallCueMusic = NULL;
00688             Mix_Music* sortCueMusic = NULL;
00689             if(argMap["cue-type"].compare("a")==0){
00690                      //now let's open the audio channel
00691                     if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00692                             LINFO( "did not open the mix-audio") ;
00693                             return -1 ;
00694                     }
00695 
00696                         string str = argMap["sound-dir"]+"/recall.wav" ;
00697                         recallCueMusic = Mix_LoadMUS(str.c_str());
00698                         str = argMap["sound-dir"]+"/sort.wav" ;
00699                         sortCueMusic = Mix_LoadMUS(str.c_str());
00700             }
00701             vector<int>* taskVector = new vector<int>();
00702             for(int i = 0 ; i < (int)(num_of_sorting_task/4) ; i++) {
00703                     taskVector->push_back(1);
00704                     taskVector->push_back(2);
00705                     taskVector->push_back(3);
00706                     taskVector->push_back(4);
00707                     //taskVector->push_back(5);
00708                     //taskVector->push_back(6);
00709 
00710             }
00711             for(int i = 0 ; i < num_of_mem_task ; i++)  taskVector->push_back(0);
00712             scramble(*taskVector);
00713             for( int r = 0 ; (int)r < (int)taskVector->size() ; r++ ){
00714 
00715                             int task = taskVector->at(r) ;
00716                             d->pushEvent("**************************************") ;
00717                             d->showCursor(true);
00718                             d->displayText("click one of the  mouse buttons to start!");
00719                             d->waitForMouseClick() ;
00720                             d->showCursor(false) ;
00721                             string testString ;
00722                             testString = getARandomString(stringSize, argMap["alphabet"]);
00723                             switch( task ){
00724                                 case 1 : testString = get34012(ascSort(testString));break ;
00725                                 case 2 : testString = get21043(ascSort(testString));break ;
00726                                 case 3 : testString = get41230(ascSort(testString));break ;
00727                                 case 4 : testString = get03214(ascSort(testString));break ;
00728                                 case 5 : testString = get42130(ascSort(testString));break ;
00729                                 case 6 : testString = get03124(ascSort(testString));break ;
00730                             }
00731                             d->clearScreen() ;
00732                             d->displayFixationBlink();
00733                             switch( mode ){
00734                                     case 1 : displayWholeNumber(testString,onsetDel,white_sapece_distance);break ;
00735                                     case 2 : displayRandom(testString,onsetDel) ; break ;
00736                                     case 3 : displayLinear(testString,onsetDel) ; break ;
00737                                     case 4 : displayLinearRandom(testString,onsetDel) ; break ;
00738                                     case 5 : displayLinearReverse(testString,onsetDel) ; break ;
00739                                     case 6 : displayLinearRandomVertically(testString,onsetDel) ; break ;
00740                                     case 7 : displayWholeNumberVertically(testString,onsetDel,white_sapece_distance) ; break ;
00741                             }
00742                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00743                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00744                             d->displayFixation() ;
00745                             if(argMap["cue-type"].compare("v")==0){
00746                                     d->displayRedDotFixation();
00747                             }else{
00748                                 if(task == 0){if( Mix_PlayMusic( recallCueMusic, 0 ) == -1 ) { return 1; }
00749                                     while( Mix_PlayingMusic() == 1 ){}
00750                                 }else{
00751                                     if( Mix_PlayMusic( sortCueMusic, 0 ) == -1 ) { return 1; }
00752                                     while( Mix_PlayingMusic() == 1 ){}
00753                                 }
00754 
00755                             }
00756 
00757 
00758                             d->clearScreen() ;
00759                             string imst ;
00760                             if(task!=0){
00761                                 imst= "===== Showing image: def_"+stringify(task)+"_"+testString+".png =====";
00762                                 d->pushEvent("the sequence for operation is : "+testString) ;
00763                                 d->pushEvent(imst);
00764                                 eyet->track(true);
00765                                 d->waitForMouseClick();
00766                                 eyet->track(false);
00767                                 d->pushEvent("task ends") ;
00768                                 string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00769                                 d->pushEvent("subject keyed : "+answer);
00770                                 if(answer.compare(ascSort(testString))==0){
00771                                     d->pushEvent("answer was correct");
00772                                 }else{
00773                                     d->pushEvent("answer was incorrect");
00774                                 }
00775                             }else{
00776                                  string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00777                                 d->pushEvent("subject keyed : "+answer);
00778                                 if(answer.compare(testString)==0){
00779                                     d->pushEvent("recall was correct");
00780                                     correctMemory++ ;
00781                                 }else{
00782                                     d->pushEvent("recall was incorrect");
00783                                     incorrectMemory++ ;
00784                                 }
00785                             }
00786 
00787             }
00788             d->pushEvent("number of correct memory recall : "+ stringify(correctMemory)) ;
00789             d->pushEvent("number of incorrect memory recall : "+ stringify(incorrectMemory)) ;
00790             d->clearScreen();
00791             d->displayText("Experiment complete. Thank you!");
00792             d->waitForMouseClick();
00793             taskVector = 0 ;
00794           // stop all our ModelComponents
00795             manager.stop();
00796 
00797 
00798           // all done!
00799             return 0;
00800 }
00801 
00802 #endif // INVT_HAVE_LIBSDL_IMAGE
00803 
Generated on Sun May 8 08:40:09 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3