pychoWM-dp.C

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