psycho-sorting-cost-two-way.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-sorting-cost-two-way.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-sorting-cost-two-way.C $
00035 // $Id: psycho-sorting-cost-two-way.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-a-sorting-trials=[>1](number of ascending trials){default=2}\n";
00487         com += "\nnum-of-d-sorting-trials=[>1](number of descending trials){default=2}\n";
00488         com += "\nnum-of-mem-trials=[>1](number of trials){default=10}\n";
00489         com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n";
00490         com += "\nalphabet=[a string of characters](a string of characters){default=0123456789}\n";
00491         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";
00492         com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n";
00493         com += "\nmask=[y/n](whether present a mask after presentation, n for no, y  for yes ){default=n}\n" ;
00494         com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n";
00495         com += "\nwhite-space=[>0](the distance between digits in display){default=20}\n" ;
00496         com += "\ncue-type=[a/v](a for audio v for visual){default=v}\n";
00497         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00498         com += "\nfirst-stop=[a number](number of trials before the first recalibration){defalut=20}\n";
00499         com += "\nsecond-stop=[a number](number of trials before the second recalibration){defalut=40}\n";
00500         com += "\nthird-stop=[a number](number of trials before the third recalibration){defalut=60}\n";
00501         com += "\nasc-cue-sound-file=[file name for ascending cue operation]{defualt=sine.wav}\n";
00502         com += "\ndesc-cue-sound-file=[file name for ascending cue operation]{defualt=square.wav}\n";
00503         return com ;
00504 }
00505 
00506 
00507 void displayWholeNumber(string s , int onsetTime , int wsd){
00508         int x = (d->getWidth()-s.size()*wsd)/2 ;
00509         int y = (d->getHeight())/2 -10;
00510         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00511         textIm.clear(PixRGB<byte>(128,128,128));
00512         for( uint k = 0 ; k < s.size() ; k++ ){
00513                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00514                 writeText(textIm, Point2D<int>(x+k*wsd,y),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00515         }
00516         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00517         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00518         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00519         dumpSurface(surf);
00520         d->waitFrames(onsetTime);
00521         d->clearScreen() ;
00522 }
00523 
00524 void displayWholeNumberVertically(string s , int onsetTime , int wsd){
00525         int x = (d->getWidth())/2 ;
00526         int y = (d->getHeight()-s.size()*wsd)/2 ;
00527         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00528         textIm.clear(PixRGB<byte>(128,128,128));
00529         for( uint k = 0 ; k < s.size() ; k++ ){
00530                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00531                 writeText(textIm, Point2D<int>(x,y+k*wsd),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00532         }
00533         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00534         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00535         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00536         dumpSurface(surf);
00537         d->waitFrames(onsetTime);
00538         d->clearScreen() ;
00539 }
00540 
00541 void displayRandom(string s , int onsetTime){
00542         for( uint k = 0 ; k < s.size() ; k++ ){
00543                 int x = 9*d->getWidth()/20 + rand()%(d->getWidth()/10);
00544                 int y = 9*d->getHeight()/20 + rand()%(d->getHeight()/10) ;
00545                 d->displayText(s.substr(k,1),Point2D<int>(x,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00546                 d->waitFrames(onsetTime);
00547                 d->clearScreen() ;
00548         }
00549 }
00550 
00551 void displayLinear(string s , int onsetTime){
00552         int x = (d->getWidth()-s.size()*10)/2 ;
00553         int y = d->getHeight()/2 - 10;
00554         for( uint k = 0 ; k < s.size() ; k++ ){
00555                 d->displayText(s.substr(k,1),Point2D<int>(x+k*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00556                 d->waitFrames(onsetTime);
00557                 d->clearScreen() ;
00558         }
00559 }
00560 
00561 void displayLinearReverse(string s , int onsetTime){
00562         int x = (d->getWidth()-s.size()*10)/2 ;
00563         int y = d->getHeight()/2 - 10;
00564         for( uint k = 0 ; k < s.size() ; k++ ){
00565                 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) ;
00566                 d->waitFrames(onsetTime);
00567                 d->clearScreen() ;
00568         }
00569 }
00570 void displayLinearRandom(string s , int onsetTime){
00571         int x = (d->getWidth()-s.size()*10)/2 ;
00572         int y = d->getHeight()/2 - 10;
00573         for( uint k = 0 ; k < s.size() ; k++ ){
00574                 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) ;
00575                 d->waitFrames(onsetTime);
00576                 d->clearScreen() ;
00577         }
00578 }
00579 
00580 void displayLinearRandomVertically(string s , int onsetTime){
00581         int x = (d->getWidth())/2 ;
00582         int y = (d->getHeight()-s.size()*10)/2 - 10;
00583         for( uint k = 0 ; k < s.size() ; k++ ){
00584                 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) ;
00585                 d->waitFrames(onsetTime);
00586                 d->clearScreen() ;
00587         }
00588 }
00589 
00590 void displayLinearRandomNoRepeating(string s , int onsetTime){
00591         int x = (d->getWidth()-s.size()*10)/2 ;
00592         int y = d->getHeight()/2 - 10;
00593         for( uint k = 0 ; k < s.size() ; k++ ){
00594                 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) ;
00595                 d->waitFrames(onsetTime);
00596                 d->clearScreen() ;
00597         }
00598 }
00599 
00600 //and this is the function which creates and displays a mask of randomly positioned numbers
00601 void showMask(int frames, string alphabet="0123456789"){
00602         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00603         PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128);
00604         PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0);
00605         textIm.clear(bgcolor);
00606         for(int i = 0 ;  i < 800 ; i++)
00607                 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor);
00608         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00609         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00610         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00611         d->waitFrames(frames) ;
00612         d->clearScreen();
00613         dumpSurface(surf) ;
00614 }
00615 
00616 
00617 vector<string> getAll_34012(string al="0123456789"){
00618             string tmp;
00619             vector<string> outVector ;
00620             for(int i0=0 ;i0<10 ;i0++ ){
00621                 for( int i1=i0+2;i1<10 ; i1++ ){
00622                     for( int i2=i1+2 ;i2<10 ; i2++){
00623                         for( int i3=i2+1  ; i3 <10 ; i3++ ){
00624                             for( int i4=i3+2; i4 < 10 ; i4++){
00625                                 tmp = al.substr(i3,1)+al.substr(i4,1)+al.substr(i0,1)+al.substr(i1,1)+al.substr(i2,1);
00626                                 outVector.push_back(tmp);
00627                             }
00628                         }
00629                     }
00630                 }
00631             }
00632 return outVector ;
00633         }
00634 
00635 vector<string> getAll_21043(string al="0123456789"){
00636             string tmp;
00637             vector<string> outVector ;
00638             for(int i0=0 ;i0<10 ;i0++ ){
00639                 for( int i1=i0+2;i1<10 ; i1++ ){
00640                     for( int i2=i1+2 ;i2<10 ; i2++){
00641                         for( int i3=i2+1  ; i3 <10 ; i3++ ){
00642                             for( int i4=i3+2; i4 < 10 ; i4++){
00643                                 tmp = al.substr(i2,1)+al.substr(i1,1)+al.substr(i0,1)+al.substr(i4,1)+al.substr(i3,1);
00644                                 outVector.push_back(tmp);
00645                             }
00646                         }
00647                     }
00648                 }
00649             }
00650 return outVector ;
00651         }
00652 vector<string> getAll_41230(string al="0123456789"){
00653             string tmp;
00654             vector<string> outVector ;
00655             for(uint i0=0 ;i0<al.size() ;i0++ ){
00656                 for( uint i1=i0+1;i1<al.size() ; i1++ ){
00657                     for( uint i2=i1+2 ;i2<al.size() ; i2++){
00658                         for( uint i3=i2+2  ; i3 <al.size() ; i3++ ){
00659                             for( uint i4=i3+1; i4 < al.size() ; i4++){
00660                                 tmp = al.substr(i4,1)+al.substr(i1,1)+al.substr(i2,1)+al.substr(i3,1)+al.substr(i0,1);
00661                                 outVector.push_back(tmp);
00662                             }
00663                         }
00664                     }
00665                 }
00666             }
00667 return outVector ;
00668         }
00669 
00670 vector<string> getAll_03214(string al="0123456789"){
00671             string tmp;
00672             vector<string> outVector ;
00673             for(uint i0=0 ;i0<al.size() ;i0++ ){
00674                 for( uint i1=i0+1;i1<al.size() ; i1++ ){
00675                     for( uint i2=i1+2 ;i2<al.size() ; i2++){
00676                         for( uint i3=i2+2  ; i3 <al.size() ; i3++ ){
00677                             for( uint i4=i3+1; i4 < al.size() ; i4++){
00678                                 tmp = al.substr(i0,1)+al.substr(i3,1)+al.substr(i2,1)+al.substr(i1,1)+al.substr(i4,1);
00679                                 outVector.push_back(tmp);
00680                             }
00681                         }
00682                     }
00683                 }
00684             }
00685 return outVector ;
00686         }
00687 
00688 extern "C" int main(const int argc, char** argv)
00689 {
00690 
00691         MYLOGVERB = LOG_INFO;  // suppress debug messages
00692         //let's push the initial value for the parameters
00693         argMap["experiment"]="working memory single task - sorting";
00694         argMap["logfile"]="psycho-sorting-const.psy" ;
00695         argMap["string-size"]="5" ;
00696         argMap["subject"]="" ;
00697         argMap["memo"]="" ;
00698         argMap["digit-onset"]="10" ;
00699         argMap["alphabet"]="0123456789";
00700         argMap["mode"]="1" ;
00701         argMap["cue-wait-frames"]="0" ;
00702         argMap["mask"]="n" ;
00703         argMap["cue-onset-frames"] = "3" ;
00704         argMap["white-space"] = "20" ;
00705         argMap["cue-type"] = "v" ;
00706         argMap["sound-dir"]="..";
00707             argMap["num-of-a-sorting-trials"] = "2" ;
00708         argMap["num-of-d-sorting-trials"] = "2" ;
00709         argMap["num-of-mem-trials"] = "2" ;
00710         argMap["first-stop"]="20";
00711         argMap["second-stop"]="40";
00712         argMap["third-stop"] = "60";
00713         argMap["asc-cue-sound-file"]="sine.wav";
00714         argMap["desc-cue-sound-file"]="square.wav";
00715         manager.addSubComponent(d);
00716         nub::soft_ref<EventLog> el(new EventLog(manager));
00717         manager.addSubComponent(el);
00718         d->setEventLog(el);
00719         nub::soft_ref<EyeTrackerConfigurator>
00720                         etc(new EyeTrackerConfigurator(manager));
00721           manager.addSubComponent(etc);
00722 
00723         if (manager.parseCommandLine(argc, argv,
00724             "at least one argument needed", 1, -1)==false){
00725                     cout<<getUsageComment()<<endl;
00726                     return(1);
00727             }
00728 
00729             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00730                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00731             }
00732 
00733             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00734         manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00735         nub::soft_ref<EyeTracker> eyet = etc->getET();
00736         d->setEyeTracker(eyet);
00737         eyet->setEventLog(el);
00738 
00739 
00740   // let's get all our ModelComponent instances started:
00741             manager.start();
00742             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00743   // let's display an ISCAN calibration grid:
00744             d->clearScreen();
00745             d->displayISCANcalib();
00746             d->waitForMouseClick();
00747             d->displayText("Here the experiment starts! click to start!");
00748             d->waitForMouseClick();
00749             d->clearScreen();
00750         //let's see in what mode the user like to run the program
00751             int mode = atoi(argMap["mode"].c_str());
00752             vector<long> correctAnswersTiming;
00753             vector<long> incorrectAnswersTiming;
00754             vector<long> allTiming ;
00755             int correctMemory = 0 ;
00756             int incorrectMemory = 0 ;
00757             int correctAsc = 0 ;
00758             int incorrectAsc = 0 ;
00759             int correctDes = 0 ;
00760             int incorrectDes = 0 ;
00761             int stringSize = atoi(argMap["string-size"].c_str());
00762             int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00763             int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ;
00764             int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ;
00765             int white_sapece_distance = atoi(argMap["white-space"].c_str());
00766             int num_of_a_sorting_task = atoi(argMap["num-of-a-sorting-trials"].c_str()) ;
00767             int num_of_d_sorting_task = atoi(argMap["num-of-d-sorting-trials"].c_str()) ;
00768             int num_of_mem_task = atoi(argMap["num-of-mem-trials"].c_str()) ;
00769             int first_stop = atoi(argMap["first-stop"].c_str());
00770             int second_stop = atoi(argMap["second-stop"].c_str());
00771             int third_stop = atoi(argMap["third-stop"].c_str());
00772             string alphabet = argMap["alphabet"];
00773             //let's do calibration
00774             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00775             int cl = d->waitForMouseClick();
00776             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00777             d->clearScreen() ;
00778 
00779             map<int,Mix_Music*>  audio_map ;//we will have access to the audios for stimulus presentation using this map
00780                         map<string,int>  charmap ;
00781                         map<int,string>  charinvmap ;
00782             Mix_Music* recallCueMusic = NULL;
00783             Mix_Music* sortCueMusic = NULL;
00784             if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00785                             LINFO( "did not open the mix-audio") ;
00786                             return -1 ;
00787             }
00788             string str = argMap["sound-dir"]+"/"+argMap["asc-cue-sound-file"] ;
00789             recallCueMusic = Mix_LoadMUS(str.c_str());
00790             if(recallCueMusic==NULL) cout<<"not a 16 bit wav file  "<<str<<endl;
00791             str = argMap["sound-dir"]+"/"+argMap["desc-cue-sound-file"] ;
00792             sortCueMusic = Mix_LoadMUS(str.c_str());
00793             if(sortCueMusic==NULL) cout<<"not a 16 bit wav file  "<<str<<endl;
00794             if(argMap["cue-type"].compare("a")==0){
00795                      //now let's open the audio channel
00796                                                 for(uint i = 0; i < alphabet.size() ; i++){
00797                                                         string str = argMap["sound-dir"]+"/"+alphabet.substr(i,1)+".wav";
00798                                                         audio_map[i]=Mix_LoadMUS(str.c_str());
00799                                                         if(audio_map[i]==NULL) cout<<"not a 16 bit wav file  "<<str<<endl;
00800                                                         charmap[alphabet.substr(i,1)]=i;
00801                                                         charinvmap[i]=alphabet.substr(i,1) ;
00802                                                 }
00803             }
00804             vector<int>* taskVector = new vector<int>();
00805             for(int i = 0 ; i < (int)(num_of_a_sorting_task/2) ; i++) {
00806                     taskVector->push_back(1);
00807                     taskVector->push_back(2);
00808                 }
00809             for(int i = 0 ; i < (int)(num_of_d_sorting_task/2) ; i++) {
00810             taskVector->push_back(3);
00811             taskVector->push_back(4);
00812             }
00813             vector<string> a_41230 = getAll_41230(alphabet);
00814             vector<string> a_03214 = getAll_03214(alphabet);
00815             vector<string> d_41230 = getAll_41230(alphabet);
00816             vector<string> d_03214 = getAll_03214(alphabet);
00817             scramble(a_41230);
00818             scramble(a_03214);
00819             scramble(d_41230);
00820             scramble(d_03214);
00821             int ind1 = 0 ; int ind2 = 0 ; int ind3 = 0 ;int ind4 = 0 ;
00822             for(int i = 0 ; i < num_of_mem_task ; i++)  taskVector->push_back(0);
00823             scramble(*taskVector);
00824             for( int r = 0 ; (int)r < (int)taskVector->size() ; r++ ){
00825 
00826                             if(r==first_stop || r==second_stop || r==third_stop){
00827                                 d->displayText("YOU MAY STOP HERE TO TAKE A SHORT BRAKE!");
00828                                 d->waitForMouseClick();
00829                                 d->displayText("incorrect memory recalls="+stringify(incorrectMemory)+"    incorrect ascending sorting:"+stringify(incorrectAsc) + "  incorrect descencing sorting"+ stringify(incorrectDes) );
00830                                 d->waitForMouseClick();
00831                                 d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00832                                 int cl = d->waitForMouseClick();
00833                                 if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00834                                 d->clearScreen() ;
00835                             }
00836 
00837                             int task = taskVector->at(r) ;
00838                             d->pushEvent("**************************************") ;
00839                             d->showCursor(true);
00840                             d->displayText("click one of the  mouse buttons to start!");
00841                             d->waitForMouseClick() ;
00842                             string testString ;
00843                             testString = getARandomString(stringSize,alphabet);
00844                             switch( task ){
00845                                 case 1 : testString = a_41230.at(ind1);ind1++;break ;
00846                                 case 2 : testString = a_03214.at(ind2);ind2++;break ;
00847                                 case 3 : testString = d_41230.at(ind3);ind3++;break ;
00848                                 case 4 : testString = d_03214.at(ind4);ind4++;break ;
00849                             }
00850                             d->clearScreen() ;
00851                             d->displayFixationBlink();
00852                                                         if(argMap["cue-type"].compare("a")==0){
00853                                                                         for(int i = 0 ; i < (int)testString.size(); i++){
00854                                                                                 if( Mix_PlayMusic( audio_map[charmap[testString.substr(i,1)]], 0 ) == -1 ) { return 1; }
00855                                             while( Mix_PlayingMusic() == 1 ){}
00856                                         d->waitFrames(onsetDel);
00857                                                                         }
00858                                                         }else{
00859                             switch( mode ){
00860                                     case 1 : displayWholeNumber(testString,onsetDel,white_sapece_distance);break ;
00861                                     case 2 : displayRandom(testString,onsetDel) ; break ;
00862                                     case 3 : displayLinear(testString,onsetDel) ; break ;
00863                                     case 4 : displayLinearRandom(testString,onsetDel) ; break ;
00864                                     case 5 : displayLinearReverse(testString,onsetDel) ; break ;
00865                                     case 6 : displayLinearRandomVertically(testString,onsetDel) ; break ;
00866                                     case 7 : displayWholeNumberVertically(testString,onsetDel,white_sapece_distance) ; break ;
00867                             }
00868                                                         }
00869                                 d->displayFixation() ;
00870 
00871                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00872                            if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00873                             d->displayFixation() ;
00874 
00875 
00876                                 if(task == 0 ) {d->displayRedDotFixation();d->waitFrames(10);}
00877                                 if(task == 1 || task ==2 ){if( Mix_PlayMusic( recallCueMusic, 0 ) == -1 ) { return 1; }
00878                                     while( Mix_PlayingMusic() == 1 ){}
00879                                 }
00880                                 if(task==3 || task==4){
00881                                     if( Mix_PlayMusic( sortCueMusic, 0 ) == -1 ) { return 1; }
00882                                     while( Mix_PlayingMusic() == 1 ){}
00883                                 }
00884 
00885 
00886 
00887                             //d->clearScreen() ;
00888                             string imst ;
00889                             if(task!=0){
00890                                 imst= "===== Showing image: def_"+stringify(task)+"_"+stringify(r)+"_"+testString+".png =====";
00891                                 d->pushEvent("the sequence for operation is : "+testString) ;
00892                                 d->pushEvent(imst);
00893                                 eyet->track(true);
00894                                 d->waitForMouseClick();
00895                                 eyet->track(false);
00896                                 d->pushEvent("task ends") ;
00897                                 string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00898                                 d->pushEvent("subject keyed : "+answer);
00899                                 if((task==1 || task==2) && answer.compare(ascSort(testString))==0){
00900                                     d->pushEvent("answer was correct");
00901                                     correctAsc++ ;
00902                                 }
00903                                 if((task==1 || task==2) && answer.compare(ascSort(testString))!=0){
00904                                     d->pushEvent("answer was incorrect");
00905                                     incorrectAsc++ ;
00906                                     d->displayText("!!!!");
00907                                     d->waitFrames(20);
00908                                 }
00909 
00910                                 if((task==3 || task==4) && answer.compare(desSort(testString))==0){
00911                                     d->pushEvent("answer was correct");
00912                                     correctDes++;
00913                                 }
00914                                 if((task==3 || task==4) && answer.compare(desSort(testString))!=0){
00915                                     d->pushEvent("answer was incorrect");
00916                                     incorrectDes++;
00917                                     d->displayText("!!!!");
00918                                     d->waitFrames(20);
00919                                 }
00920 
00921                             }else{
00922                                  string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00923                                 d->pushEvent("subject keyed : "+answer);
00924                                 if(answer.compare(testString)==0){
00925                                     d->pushEvent("recall was correct");
00926                                     correctMemory++ ;
00927                                 }else{
00928                                     d->pushEvent("recall was incorrect");
00929                                                     incorrectMemory++ ;
00930                                     d->displayText("!!!!");
00931                                     d->waitFrames(20);
00932                                 }
00933                             }
00934 
00935             }
00936             d->pushEvent("number of correct memory recall : "+ stringify(correctMemory)) ;
00937                 d->pushEvent("number of incorrect memory recall : "+ stringify(incorrectMemory)) ;
00938             d->pushEvent("number of correct ascending sorting :"+stringify(correctAsc));
00939             d->pushEvent("number of incorrect ascending sorting :"+stringify(incorrectAsc));
00940             d->pushEvent("number of correct descending sorting :"+stringify(correctDes));
00941             d->pushEvent("number of incorrect descending sorting :"+stringify(incorrectDes));
00942             d->clearScreen();
00943             d->displayText("Experiment complete. Thank you!");
00944             d->waitForMouseClick();
00945             taskVector = 0 ;
00946           // stop all our ModelComponents
00947             manager.stop();
00948 
00949 
00950           // all done!
00951             return 0;
00952 }
00953 
00954 #endif // INVT_HAVE_LIBSDL_IMAGE
00955 
Generated on Sun May 8 08:40:10 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3