psycho-spatial-memory-num-counting.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-spatial-memory-num-counting.C Psychophysics test to measure the effect of executive tasks on spatial memory */
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-spatial-memory-num-counting.C $
00035 // $Id: psycho-spatial-memory-num-counting.C 13059 2010-03-26 08:14:32Z itti $
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-Spatial-Memory");
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 //////////////////////////////////////////////
00095 // a functionf for stringigying things
00096 //////////////////////////////////////////////
00097 template <class T> std::string stringify(T i)
00098 {
00099         ostringstream o ;
00100         o << i ;
00101         return o.str();
00102 }
00103 
00104 
00105 double getAvarage(vector<long> v){
00106         double f = 0.0 ;
00107         for( uint i = 0 ; i <  v.size() ; i++ ){
00108                 f += v[i] ;
00109         }
00110         if (v.size()!=0) return f/v.size() ;
00111         return -1 ;
00112 }
00113 
00114 double getVariance(vector<long> v){
00115         double m = getAvarage(v);
00116         double var = 0.0 ;
00117         for( uint i = 0 ; i < v.size(); i++ ){
00118                 var += (v[i]-m)*(v[i]-m) ;
00119         }
00120         if (v.size()!=0) return var/v.size() ;
00121         return -1 ;
00122 }
00123 
00124 bool itIsInThere(int x , vector<int> bag){
00125         for( uint i=0 ; i < bag.size(); i++ ){
00126                 if(x == bag[i]) return true ;
00127         }
00128         return false ;
00129 }
00130 
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //// gets a string as the argument and returns a string composed of
00134 //// characters of the first string sorted in the ascending order
00135 ///////////////////////////////////////////////////////////////////
00136 string ascSort(string st)
00137 {
00138         string res = "" ;
00139         vector<string> v = vector<string>();
00140         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00141 
00142         std::sort(v.begin(), v.end());
00143 
00144         for ( uint i = 0 ; i < v.size() ; i++ ){
00145                 res += v[i] ;
00146         }
00147         return res;
00148 }
00149 
00150 
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //// gets a string as the argument and returns a string composed of
00154 //// characters of the first string sorted in the descending order
00155 ///////////////////////////////////////////////////////////////////
00156 string desSort(string st)
00157 {
00158         string res = "" ;
00159         vector<string> v = vector<string>();
00160         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00161         std::sort(v.begin(), v.end());
00162         std::reverse(v.begin(), v.end());
00163         for ( uint i = 0 ; i < v.size() ; i++ ){
00164                 res += v[i] ;
00165         }
00166         return res;
00167 }
00168 
00169 
00170 ////////////////////////////////////////////////////////
00171 ///// simply generates a sequence of characters out of master string
00172 ////////////////////////////////////////////////////////
00173 
00174 string getARandomString(uint l, string alphabet="0123456789" ){
00175 
00176         string test = string("") ;
00177         string retString ;
00178         test = "" ;
00179         string tp = string("") ;
00180         vector<int> pickedones = vector<int>() ;
00181         for(uint i = 0 ; i < l ; i++){
00182                         int nd;
00183                         do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones)) ;
00184                         pickedones.push_back(nd);
00185                         tp = alphabet.substr(nd,1) ;
00186                         test += tp ;
00187         }
00188         retString = test ;
00189         return retString ;
00190 }
00191 
00192 ///////////////////////////////////////////////////////
00193 //this function is not called in this program, but it generates a random string and it will show it in
00194 //a random place on the screen.
00195 //////////////////////////////////////////////////////
00196 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10  ){
00197         d->clearScreen() ;
00198         vector<int> pickedones = vector<int>() ;
00199         string test = string("") ;
00200         string tp = string("") ;
00201         for(uint i = 0 ; i < l ; i++){
00202                 int nd;
00203                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00204                 pickedones.push_back(nd);
00205                 tp = alphabet.substr(nd,1) ;
00206                 test += tp ;
00207         }
00208         d->displayText(test,true,0) ;
00209         d->waitFrames(displayFrame) ;
00210         d->clearScreen() ;
00211         return test ;
00212 }
00213 
00214 
00215 ////////////////////////////////////////////////////////
00216 ///////this will change the order of elements in a vector to a random order
00217 ////////////////////////////////////////////////////////
00218 void scramble(vector<string>& v){
00219         vector<string> tv = vector<string>() ;
00220         while(v.size()>0){
00221                 tv.push_back(v[0]);
00222                 v.erase(v.begin());
00223         }
00224         int i = 0 ;
00225         while(tv.size()>0){
00226                 i = rand()%tv.size() ;
00227                 v.push_back(tv[i]);
00228                 tv.erase(tv.begin()+i);
00229         }
00230 }
00231 
00232 void scramble(vector<int>& v){
00233         vector<int> tv = vector<int>() ;
00234         while(v.size()>0){
00235                 tv.push_back(v[0]);
00236                 v.erase(v.begin());
00237         }
00238         int i = 0 ;
00239         while(tv.size()>0){
00240                 i = rand()%tv.size() ;
00241                 v.push_back(tv[i]);
00242                 tv.erase(tv.begin()+i);
00243         }
00244 }
00245 
00246 ////////////////////////////////////////////////////////////////
00247 ////This is our button factory
00248 ////////////////////////////////////////////////////////////////
00249 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){
00250         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00251         textIm.clear(bgcolor);
00252         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00253         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00254         Uint32 bc = d->getUint32color(bordercolor);
00255         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00256         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00257         SDL_Rect clip;
00258         clip.x = 0 ;
00259         clip.y = 0 ;
00260         clip.w = size.i ;
00261         clip.h = size.j ;
00262         apply_surface(0,0,*surf,*blank,clip);
00263         dumpSurface(surf) ;
00264         return blank ;
00265 }
00266 
00267 ////////////////////////////////////////////////////////////////////////
00268 ////This is the function for creating the keypad, in fact it generates
00269 ////12 buttons and associates the actions to the region for each button
00270 ////////////////////////////////////////////////////////////////////////
00271 
00272 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00273         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00274         SDL_Rect clip;
00275         clip.x=0;
00276         clip.y=0;
00277         int numofrows = alphabet.size()/3 +1;
00278         if(alphabet.size()%3 != 0 ) numofrows++ ;
00279         int numofcolumns = 3 ;
00280         clip.w= pad->w / numofcolumns ;
00281         clip.h = pad->h / numofrows ;
00282 
00283   //keys for 1 to 9
00284         for( int i = 0 ; i < numofrows*3 ; i++){
00285                 SDL_Surface* but ;
00286                 if((uint)i < alphabet.size()){
00287                         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);
00288                 }else{
00289                         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);
00290                 }
00291 
00292                 SDL_Rect cl ;
00293                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00294                 cl.w = clip.w ;
00295                 cl.h = clip.h ;
00296                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00297                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00298                 dumpSurface(but);
00299         }
00300         SDL_Rect cl1 ;
00301         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00302         cl1.w = clip.w ;
00303         cl1.h = clip.h ;
00304         buttmap["!"] = cl1 ;
00305         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);
00306         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00307         dumpSurface(but);
00308         SDL_Rect cl2 ;
00309         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00310         cl2.w = clip.w ;
00311         cl2.h = clip.h ;
00312         buttmap[" "] = cl2 ;
00313         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);
00314         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00315         dumpSurface(but);
00316         SDL_Rect cl3 ;
00317         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00318         cl3.w = clip.w ;
00319         cl3.h = clip.h ;
00320         buttmap["*"] = cl3 ;
00321         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);
00322         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00323         dumpSurface(but);
00324         return pad ;
00325 }
00326 
00327 
00328 
00329 
00330 ///////////////////////////////////////////////////////////////////////////
00331 /////this function listens to mouse clicks and then finds the region of the screen
00332 /////associated with the action, buttmap is the map of the region, offset is the offset of
00333 /////buttons
00334 ///////////////////////////////////////////////////////////////////////////
00335 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00336         int quit = 0 ;
00337         string s ;
00338         SDL_Event event ;
00339         while( quit!=2 ){
00340                 while( SDL_PollEvent( &event ) ) {
00341                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00342                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00343                                         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) {
00344                                                 quit = 2 ;
00345                                                 s = it->first ;
00346                                                 break;
00347                                         }
00348 
00349                                 }
00350                         }
00351 
00352                 }
00353         }
00354         return s ;
00355 
00356 }
00357 
00358 
00359 ////////////////////////////////////////////////////
00360 ////This function creates a virtual keypad, creates a map of buttons
00361 ////and their representation area and listens to the button press and at
00362 ////the end returns the keyed digits
00363 ////////////////////////////////////////////////////
00364 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 , string message=""){
00365         d->showCursor(true) ;
00366         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00367         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00368         //now let's get the keypad surface while we get the actions map to regions
00369         SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00370         //this will be the offset of displaying the keypad on the screen
00371         SDL_Rect offset ;
00372         offset.x = (d->getWidth() - keypad->w) /2;
00373         offset.y = (d-> getHeight() - keypad->h) /2;
00374         //d->displayText(message, Point2D<int>(d->getWidth()/3,d->getHeight()*2 /16) , PixRGB<byte>(0,0,0) ,PixRGB<byte>(127,127,127)) ;
00375         SDL_Surface* msgp = getButtonImage(message ,PixRGB<byte>(195,60,12) ,PixRGB<byte>(127,127,127) ,Point2D<int>(d->getWidth()/6,d->getHeight() /15) ,PixRGB<byte>(127,127,127) , 4) ;
00376         SDL_Rect msgoffs ; msgoffs.x = (d->getWidth() - msgp->w) /2 ; msgoffs.y = 2*d->getHeight()/9 ;
00377         d->displaySDLSurfacePatch(msgp , &msgoffs , NULL , -2 , false ,true ) ;
00378         dumpSurface(msgp) ;
00379         //now let's display the keypad
00380         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00381         //this will hold the final string keyed be the subject
00382         string p = string("") ;
00383         //this is a temporary string holding the last action related to the pressed key
00384         string tp = string("");
00385         //now let's record subject's key press
00386         while( tp.compare("*")!=0 ){
00387                 //this button is actually the display for the current string
00388                 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) ;
00389                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00390                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00391                 //now let's listen to button events
00392                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00393                 dumpSurface(dp) ;
00394                 if(tp.compare("!")==0 && p.size()>=0 ) {
00395                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00396                 }else{
00397                         if(p.size() < maxl && tp.compare("*")!=0) {
00398                                 p +=tp ;
00399                         }
00400 
00401                 }
00402 
00403         }
00404         
00405         buttmap = 0 ;
00406         dumpSurface(keypad) ;
00407         d->clearScreen() ;
00408         return p ;
00409 
00410 }
00411 
00412 
00413 
00414 ///////////////////////////////////////////////////////////////
00415 //////gets the test string, answer and the mode and identifies if
00416 //////the answer matches the thing it should be, mode=0 checks if
00417 //////if the answer and test string simply the same, mode=1 matches
00418 //////the answer against the ascending sorted string of the test string
00419 //////mode=2 compares the answer against the descending sorted of
00420 //////the test string
00421 ///////////////////////////////////////////////////////////////
00422 bool isAnswerCorrect(string test , string answer , int mode){
00423 
00424         if(mode == 0 && answer.compare(test)==0) return true ;
00425 
00426         if(mode == 1 && answer.compare(ascSort(test))==0) return true ;
00427 
00428         if(mode == 2 && answer.compare(desSort(test))==0) return true ;
00429 
00430         return false;
00431 }
00432 
00433 
00434 
00435 int addArgument(const string st,const string delim="="){
00436         int i = st.find(delim) ;
00437         argMap[st.substr(0,i)] = st.substr(i+1);
00438 
00439         return 0 ;
00440 }
00441 
00442 std::string getArgumentValue(string arg){
00443         return argMap[arg] ;
00444 }
00445 
00446 
00447 void displayWholeNumber(string s , int onsetTime , int wsd){
00448         int x = (d->getWidth()-s.size()*wsd)/2 ;
00449         int y = (d->getHeight())/2 -10;
00450         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00451         textIm.clear(PixRGB<byte>(128,128,128));
00452         for( uint k = 0 ; k < s.size() ; k++ ){
00453                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ; 
00454                 writeText(textIm, Point2D<int>(x+k*wsd,y),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00455         }
00456         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00457         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00458         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00459         dumpSurface(surf);
00460         d->waitFrames(onsetTime);
00461         d->clearScreen() ;
00462 }
00463 
00464 void displayWholeNumberVertically(string s , int onsetTime , int wsd){
00465         int x = (d->getWidth())/2 ;
00466         int y = (d->getHeight()-s.size()*wsd)/2 ;
00467         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00468         textIm.clear(PixRGB<byte>(128,128,128));
00469         for( uint k = 0 ; k < s.size() ; k++ ){
00470                // d->displayText(s.substr(k,1),Point2D<int>(x,y+k*10),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ; 
00471                 writeText(textIm, Point2D<int>(x,y+k*wsd),s.substr(k,1).c_str(),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128));
00472         }
00473         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00474         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00475         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00476         dumpSurface(surf);
00477         d->waitFrames(onsetTime);
00478         d->clearScreen() ;
00479 }
00480 
00481 void displayRandom(string s , int onsetTime){
00482         for( uint k = 0 ; k < s.size() ; k++ ){
00483                 int x = 9*d->getWidth()/20 + rand()%(d->getWidth()/10);
00484                 int y = 9*d->getHeight()/20 + rand()%(d->getHeight()/10) ;
00485                 d->displayText(s.substr(k,1),Point2D<int>(x,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00486                 d->waitFrames(onsetTime);
00487                 d->clearScreen() ;
00488         }
00489 }
00490 
00491 void displayLinear(string s , int onsetTime){
00492         int x = (d->getWidth()-s.size()*10)/2 ;
00493         int y = d->getHeight()/2 - 10;
00494         for( uint k = 0 ; k < s.size() ; k++ ){
00495                 d->displayText(s.substr(k,1),Point2D<int>(x+k*10,y),PixRGB<byte>(0,0,0),PixRGB<byte>(128,128,128),true) ;
00496                 d->waitFrames(onsetTime);
00497                 d->clearScreen() ;
00498         }
00499 }
00500 
00501 void displayLinearReverse(string s , int onsetTime){
00502         int x = (d->getWidth()-s.size()*10)/2 ;
00503         int y = d->getHeight()/2 - 10;
00504         for( uint k = 0 ; k < s.size() ; k++ ){
00505                 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) ;
00506                 d->waitFrames(onsetTime);
00507                 d->clearScreen() ;
00508         }
00509 }
00510 void displayLinearRandom(string s , int onsetTime){
00511         int x = (d->getWidth()-s.size()*10)/2 ;
00512         int y = d->getHeight()/2 - 10;
00513         for( uint k = 0 ; k < s.size() ; k++ ){
00514                 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) ;
00515                 d->waitFrames(onsetTime);
00516                 d->clearScreen() ;
00517         }
00518 }
00519 
00520 void displayLinearRandomVertically(string s , int onsetTime){
00521         int x = (d->getWidth())/2 ;
00522         int y = (d->getHeight()-s.size()*10)/2 - 10;
00523         for( uint k = 0 ; k < s.size() ; k++ ){
00524                 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) ;
00525                 d->waitFrames(onsetTime);
00526                 d->clearScreen() ;
00527         }
00528 }
00529 
00530 void displayLinearRandomNoRepeating(string s , int onsetTime){
00531         int x = (d->getWidth()-s.size()*10)/2 ;
00532         int y = d->getHeight()/2 - 10;
00533         for( uint k = 0 ; k < s.size() ; k++ ){
00534                 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) ;
00535                 d->waitFrames(onsetTime);
00536                 d->clearScreen() ;
00537         }
00538 }
00539 
00540 //and this is the function which creates and displays a mask of randomly positioned numbers
00541 void showMask(int frames, string alphabet="0123456789"){
00542         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00543         PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128);
00544         PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0);
00545         textIm.clear(bgcolor);
00546         for(int i = 0 ;  i < 200 ; i++) 
00547                 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor);
00548         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00549         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00550         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00551         d->waitFrames(frames) ;
00552         d->clearScreen();
00553         dumpSurface(surf) ;
00554 }
00555 
00556 vector<int> spatial_memory_task(int onsetTime, int isd ,int rad=100 ,  int ma=45 ,int Ma=90){
00557 
00558     int w = d->getWidth();
00559     int h = d->getHeight();
00560     int a1 = rand() % 360 ;
00561     int direction = (int)(((rand()%2)-0.5)/0.5);
00562     int a2 =a1 +direction*((rand() % (Ma-ma))+ma);
00563     //d->displayFixation();
00564     d->displayRedDotFixation(w/2+rad*cos(a1*3.1415/180),h/2 + rad*sin(a1*3.1415/180));
00565     d->waitFrames(onsetTime);
00566     d->clearScreen();
00567     //d->displayFixation();
00568     d->waitFrames(isd);
00569     d->displayRedDotFixation(w/2+rad*cos(a2*3.1415/180),h/2 + rad*sin(a2*3.1415/180));
00570     d->waitFrames(onsetTime);
00571     d->clearScreen();
00572     vector<int> angles;
00573     angles.push_back(a1);
00574     angles.push_back(a2);
00575     return angles ;
00576 }
00577 
00578 int spatial_memory_retrival(vector<int> angles ,int rad = 100 ){
00579         int res=0 ;
00580         int flip = rand()%2;
00581         int w = d->getWidth();
00582         int h = d->getHeight();
00583         if(flip==0){
00584                 d->displayRedDotFixation(w/2+rad*cos(angles.at(0)*3.1415/180),h/2 + rad*sin(angles.at(0)*3.1415/180));
00585                 d->displayRedDotFixation(w/2+rad*cos(angles.at(1)*3.1415/180),h/2 + rad*sin(angles.at(1)*3.1415/180));
00586         }else{
00587                 int a1=angles.at(0) % 360;
00588                 int a2=angles.at(1) % 360;
00589                 if (a2<a1) {
00590                         int tmp = a2 ;
00591                         a2=a1;
00592                         a1=tmp;
00593                 }
00594                 int sflip=rand()%2;
00595                 int del = ((rand()%15) + 30);
00596                 if(sflip==0){
00597                         a1=a1-del;
00598                 }else{
00599                         a2=a2+del;
00600                 }
00601                 d->displayRedDotFixation(w/2+rad*cos(a1*3.1415/180),h/2 + rad*sin(a1*3.1415/180));
00602                 d->displayRedDotFixation(w/2+rad*cos(a2*3.1415/180),h/2 + rad*sin(a2*3.1415/180));
00603         }
00604         d->waitFrames(20);
00605         d->clearScreen();
00606         string ans = getDigitSequenceFromSubject("yn",1);
00607         if(flip==0){
00608                 res = 0 ;
00609                 if(ans.compare("y")==0) res=1;
00610         }else{
00611                 res = 0 ;
00612                 if(ans.compare("n")==0) res=1;
00613         }
00614         return res ;
00615 }
00616 
00617 vector<int> executive_memory_task(Mix_Music* tone1 , Mix_Music* tone2 ,string initial_string,int counter_length, int min_tone_wait, int max_tone_wait ){
00618         int t1c = 0 ;
00619         int t2c = 0 ;
00620         vector<int> wFrames;
00621         vector<int> toneSequence ;
00622         vector<int> retVector ;
00623         map<int,string> strMap;
00624 
00625         int flag=0;
00626         float milisum=0;
00627         do{
00628             int rtmp = rand()%(max_tone_wait - min_tone_wait) + min_tone_wait;
00629             milisum += rtmp*33.33 + 240;
00630             if(milisum > counter_length*33.33) {
00631                 milisum = milisum -rtmp*33.33 - 240; 
00632                 flag=1;
00633             }else{
00634                 wFrames.push_back(rtmp);
00635                 toneSequence.push_back(rand()%2);
00636             }
00637         }while(flag==0);
00638         int lagFrames = (int)((counter_length - milisum)/33.33);
00639 
00640         for(uint i = 0 ; i < wFrames.size() ; i++){
00641             d->pushEvent("will wait for "+stringify(wFrames[i]));
00642             if(toneSequence[i]==0){
00643                 d->pushEvent("tone1 playing");
00644                 t1c++;
00645                 if(Mix_PlayMusic(tone1,0)==-1){return retVector;}
00646                 while(Mix_PlayingMusic()==1){} ;
00647             }else{
00648                 d->pushEvent("tone2 playing");
00649                 t2c++ ;
00650                 if(Mix_PlayMusic(tone2,0)==-1){return retVector;}
00651                 while(Mix_PlayingMusic()==1){} ;
00652             }
00653             d->waitFrames(wFrames[i]);
00654         }
00655         d->waitFrames(lagFrames);
00656         retVector.push_back(t1c);
00657         retVector.push_back(t2c);
00658         d->clearScreen();
00659         d->displayFixation();
00660         return retVector ;
00661         
00662 }
00663 
00664 
00665 
00666 std::string getUsageComment(){
00667 
00668         string com = string("\nlist of arguments : \n");
00669 
00670         com += "\nlogfile=[logfilename.psy] {default = psycho-sm.psy}\n" ;
00671         com += "\nmemo=[a_string_without_white_space]\n";
00672         com += "\nstring-size=[>0](the size of counter string){default=4} \n";
00673         com += "\nsubject=[subject_name] \n" ;
00674         com += "\nnum-of-trials=[>1] (number of trials ) {default=10}\n";
00675         com += "\nalphabet=[a string of characters](a string of characters){default=abcdefghijklmnopqrstuvwxyz}\n";
00676         com += "\nmode=[1,2,3](1 for spatial memory task 2 for single counter task, 2 for concurrent task){default=1}\n";
00677         com += "\nsingle-dot-onset=[>1](number of frames that the single dot should be presented){default=16}\n";
00678         com += "\ndots_ISI=[>1](number of frames between dots presentations){default=16}\n";
00679         com += "\ndots_radius=[>1](the radius for circle of dots in pixel){default=100}\n";
00680         com += "\ndots_min_angle=[>0](minimum angle between dots on the circle){default=45}\n";
00681         com += "\ndots_max_angle=[>0] (maximum angle between dots on the circle){default=90}\n";
00682         com += "\nspatial-delay=[>0](number of frames for spatial memory task ){default=180}\n";
00683         com += "\n spatial-counter-ISI=[>1](numer of frames between last dot presentation and start of counter task){default=16}\n";
00684         com += "\n counter-length=[>1](total lenght of counter experiment in frames){default=460}\n";
00685         com += "\n counter-spatial-query-ISI=[>1](the delay between end of counter trail and start of spatial memory query in number of frames){default=16}\n";
00686         com += "\n spatial-query-length=[>1](the total length for showing the spatial memory test in number of frames){default=60}\n";
00687         com += "\n spatial-query-counter-query-ISI=[>1](number of frames between the unspeeded spatial memory query and showing the counter query){default=30}\n";
00688         com += "\n counter-query-length=[>1](number of frames for presenting the counter query){default=60}\n";
00689         com += "\n cue-onset-frames=[>1](){default=3}\n";;
00690         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00691         com += "\ntone1=[a valid file name](name of wav file without extension for tone 1){default=sin}\n";
00692         com += "\ntone2=[a valid file name](name of wav file without extension for tone 2){default=square}\n";
00693         com += "\ncue-file=[a valid file name](name of a wav file without extension for the audio cue){default=cue1}\n";
00694         com += "\nmin-tone-wait=[>1](minimum number of frames waiting on each tone){default=60}\n";
00695         com += "\nmax-tone-wait=[>1](maximum number of frames waiting on each tone){default=90}\n";
00696         return com ;
00697 }
00698 
00699 extern "C" int main(const int argc, char** argv)
00700 {
00701 
00702         MYLOGVERB = LOG_INFO;  // suppress debug messages
00703         //let's push the initial value for the parameters
00704         argMap["experiment"]="spatial-memory-test";
00705         argMap["logfile"]="psycho-sm.psy" ;
00706         argMap["string-size"]="3" ;
00707         argMap["num-of-trials"]="10";
00708         argMap["subject"]="" ;
00709         argMap["memo"]="" ;
00710         argMap["single-dot-onset"]="16" ;
00711             argMap["dots-ISI"]="16";
00712             argMap["spatial-delay"]="180";
00713             argMap["spatial-counter-ISI"]="16";
00714             argMap["counter-length"]="460";
00715             argMap["counter-spatial-query-ISI"]="16";
00716             argMap["spatial-query-length"]="60";
00717             argMap["spatial-query-counter-query-ISI"]="30";
00718             argMap["counter-query-length"]="60";
00719         argMap["alphabet"]="0123456789";
00720         argMap["mode"]="1" ;
00721         argMap["cue-onset-frames"] = "3" ;
00722         argMap["sound-dir"]="..";
00723             argMap["tone1"]="sine";
00724             argMap["tone2"]="square";
00725             argMap["cue-file"]="cue1";
00726             argMap["min-tone-wait-1"]="40";
00727             argMap["max-tone-wait-1"]="60";
00728             argMap["min-tone-wait-2"]="90";
00729             argMap["max-tone-wait-2"]="110";
00730             argMap["dots_radius"]="100";
00731             argMap["dots_min_angle"]="45";
00732             argMap["dots_max_angle"]="90";
00733         manager.addSubComponent(d);
00734         nub::soft_ref<EventLog> el(new EventLog(manager));
00735         manager.addSubComponent(el);
00736         d->setEventLog(el);
00737         nub::soft_ref<EyeTrackerConfigurator>
00738                         etc(new EyeTrackerConfigurator(manager));
00739           manager.addSubComponent(etc);
00740 
00741         if (manager.parseCommandLine(argc, argv,
00742             "at least one argument needed", 1, -1)==false){
00743                     cout<<getUsageComment()<<endl;
00744                     return(1);
00745             }
00746 
00747             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00748                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00749             }
00750 
00751             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00752                 //+manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00753                 //+nub::soft_ref<EyeTracker> eyet = etc->getET();
00754                 //+d->setEyeTracker(eyet);
00755                 //+eyet->setEventLog(el);
00756 
00757 
00758   // let's get all our ModelComponent instances started:
00759             manager.start();
00760             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00761   // let's display an ISCAN calibration grid:
00762             d->clearScreen();
00763             d->displayISCANcalib();
00764             d->waitForMouseClick();
00765             d->displayText("Here the experiment starts! click to start!");
00766             d->waitForMouseClick();
00767             d->clearScreen();
00768         //let's see in what mode the user like to run the program
00769             //int mode = atoi(argMap["mode"].c_str());
00770             string masterString=argMap["alphabet"];
00771             
00772             
00773             int numOfTests = atoi(argMap["num-of-trials"].c_str()) ;
00774             int stringSize = atoi(argMap["string-size"].c_str());
00775             int dots_ISI = atoi(argMap["dots-ISI"].c_str()) ;
00776             int dot_onset = atoi(argMap["single-dot-onset"].c_str());
00777             int dots_radius = atoi(argMap["dots_radius"].c_str());
00778             int dots_min_angle = atoi(argMap["dots_min_angle"].c_str());
00779             int dots_max_angle = atoi(argMap["dots_max_angle"].c_str());
00780             int mode = atoi(argMap["mode"].c_str());
00781             int counter_length = atoi(argMap["counter-length"].c_str());
00782             int min_tone_wait_1 = atoi(argMap["min-tone-wait-1"].c_str());
00783             int max_tone_wait_1 = atoi(argMap["max-tone-wait-1"].c_str());
00784             int min_tone_wait_2 = atoi(argMap["min-tone-wait-2"].c_str());
00785             int max_tone_wait_2 = atoi(argMap["max-tone-wait-2"].c_str());
00786             //let's do calibration        
00787             d->displayText("CLICK LEFT button to calibrate; RIGHT to skip");
00788             int cl = d->waitForMouseClick();
00789             if (cl == 1) d->displayEyeTrackerCalibration(3,5,1 , true);
00790             d->clearScreen();
00791             
00792             
00793             Mix_Music* cueMusic = NULL;//this is the cue for the start of trial 
00794                         Mix_Music* tone1 = NULL;//tone 1
00795                         Mix_Music* tone2 = NULL;//tone 2
00796             map<int,Mix_Music*>  audio_map ;//we will have access to the audios for stimulus presentation using this map
00797                         map<string,int>  charmap ;
00798                         map<int,string>  charinvmap ;
00799                         //now let's open the audio channel
00800                 if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00801                   LINFO( "did not open the mix-audio") ;
00802                   return -1 ;
00803                         }
00804                         //now that everyting is ok, let's load the main string audio files and push them in a map
00805                 for(uint i = 0; i < masterString.size() ; i++){
00806                                 string str = argMap["sound-dir"]+"/"+masterString.substr(i,1)+".wav";
00807                                 audio_map[i]=Mix_LoadMUS(str.c_str());
00808                                 charmap[masterString.substr(i,1)]=i;
00809                                 charinvmap[i]=masterString.substr(i,1) ;
00810                         }
00811 
00812             for( uint i=10;i<100 ;i++ ){
00813                 charmap[stringify(i)]=i;
00814                 charinvmap[i]=stringify(i);
00815             }
00816                         
00817             if(argMap["cue-type"].compare("a")==0){
00818                         string str = argMap["sound-dir"]+"/"+argMap["cue-file"]+".wav" ;
00819                         cueMusic = Mix_LoadMUS(str.c_str());
00820             }
00821                         
00822                         string tmpstr = argMap["sound-dir"]+"/"+argMap["tone1"]+".wav";
00823                         tone1 = Mix_LoadMUS(tmpstr.c_str());
00824                         tmpstr = argMap["sound-dir"]+"/"+argMap["tone2"]+".wav";
00825                         tone2 = Mix_LoadMUS(tmpstr.c_str());
00826                         
00827             int cr = numOfTests ;//this is the counter for number of rounds
00828                         d->showCursor(true);
00829                         d->displayText("click one of the  mouse buttons to start!");
00830             d->waitForMouseClick() ;
00831                         d->showCursor(false);
00832            
00833         int correctSpatialMemory_1=0;
00834         int incorrectSpatialMemory_1=0;
00835         int correctSpatialMemory_2=0;
00836         int incorrectSpatialMemory_2=0;
00837         int correctCounting=0;
00838         int incorrectCounting=0;
00839     int missCounting=0;
00840         vector<int> tempoVector;
00841         for( int i = 0 ; i < numOfTests /2 ;i++ ){
00842                 tempoVector.push_back(0);
00843         }
00844         for( int i = numOfTests /2 ; i < numOfTests ;i++ ){
00845                 tempoVector.push_back(1);
00846         }
00847         scramble(tempoVector);
00848             cr=0;
00849             while( cr < numOfTests ){
00850                 string inStr = getARandomString(stringSize,"234567");
00851                 d->showCursor(false);
00852                 d->clearScreen() ;
00853                 d->pushEvent("**************************************") ;
00854                 if(tempoVector.at(cr)==0) d->pushEvent("fast tempo");
00855                 if(tempoVector.at(cr)==1) d->pushEvent("slow tempo");
00856                 d->pushEvent("initial string :" + inStr);
00857                 for(uint i = 0 ;  i < inStr.size(); i++){
00858                     d->pushEvent("playing character "+inStr.substr(i,1));
00859                     if(Mix_PlayMusic(audio_map[charmap[inStr.substr(i,1)]],0)==-1){return 1;}
00860                     while(Mix_PlayingMusic()==1){} ;
00861                     d->pushEvent("ended playing character "+inStr.substr(i,1));
00862                 }
00863                 d->waitFrames(60);
00864                 d->displayFixation();
00865                 d->waitFrames(10);
00866                 d->clearScreen() ;
00867                 vector<int> angles = spatial_memory_task(dot_onset,dots_ISI,dots_radius,dots_min_angle,dots_max_angle);
00868                 d->pushEvent("dots showed at these angles :"+ stringify(angles.at(0))+" and " + stringify(angles.at(1)));
00869                 d->waitFrames(10);
00870                 d->displayFixation();
00871                 vector<int> tonesVector;
00872                 if(tempoVector.at(cr)==0)
00873                  tonesVector = executive_memory_task( tone1 , tone2 , inStr, counter_length, min_tone_wait_1, max_tone_wait_1 );
00874                 if(tempoVector.at(cr)==1)
00875                  tonesVector = executive_memory_task( tone1 , tone2 , inStr, counter_length, min_tone_wait_2, max_tone_wait_2 );
00876                 string  newStr ;
00877                 if (stringSize == 2)
00878                 newStr = charinvmap[charmap[inStr.substr(0,1)]+tonesVector.at(0)]+charinvmap[charmap[inStr.substr(inStr.size()-1,1)]+tonesVector.at(1)];
00879                 if (stringSize>2)
00880                         newStr = charinvmap[charmap[inStr.substr(0,1)]+tonesVector.at(0)]+inStr.substr(1,inStr.size()-2)+charinvmap[charmap[inStr.substr(inStr.size()-1,1)]+tonesVector.at(1)];
00881                 if(mode==1 || mode==3){
00882                         int spMemAns = spatial_memory_retrival(angles,dots_radius);
00883                         if(tempoVector.at(cr)==0){
00884                                 switch( spMemAns ){
00885                                         case 0 : incorrectSpatialMemory_1++;d->pushEvent("incorrect spatial memory recall");break;
00886                                         case 1 : correctSpatialMemory_1++;d->pushEvent("correct spatial memory recall");break;
00887                                 }
00888                         }
00889                         
00890                         if(tempoVector.at(cr)==1){
00891                                 switch( spMemAns ){
00892                                         case 0 : incorrectSpatialMemory_2++;d->pushEvent("incorrect spatial memory recall");break;
00893                                         case 1 : correctSpatialMemory_2++;d->pushEvent("correct spatial memory recall");break;
00894                                 }
00895                         }
00896                 }
00897                 
00898                 
00899                 if(mode ==1){
00900                 //string ans = getDigitSequenceFromSubject(masterString,3," 3 digits");
00901                 string ans1 = getDigitSequenceFromSubject(masterString,1,"first digit");
00902             d->pushEvent("subject keyed:" + ans1 + " for first digit"); 
00903             string ans2 = getDigitSequenceFromSubject(masterString,1,"second digit");
00904             d->pushEvent("subject keyed:" + ans2 + " for second digit");
00905                 //d->pushEvent("subject keyed:" + ans);
00906                         if(ans1.compare(inStr.substr(0,1))==0 && ans2.compare(inStr.substr(inStr.size()-1,1))==0 ) {
00907                                 correctCounting++;
00908                         }else{
00909                                 incorrectCounting++ ;
00910                         }
00911                         
00912                 }
00913                 
00914                 if(mode ==2 || mode==3){
00915             int sineCounter = tonesVector.at(0)+atoi(inStr.substr(0,1).c_str());
00916             int squareCounter = tonesVector.at(1)+atoi(inStr.substr(inStr.size()-1,1).c_str());
00917             d->pushEvent("sine signal counter is :"+stringify(sineCounter));
00918             d->pushEvent("square signal counter is :"+stringify(squareCounter));
00919             string ans1 = getDigitSequenceFromSubject(masterString,2,"soft tone counter");
00920             d->pushEvent("subject keyed:" + ans1 + " for sine counter");
00921             string ans2 = getDigitSequenceFromSubject(masterString,2,"rough tone counter");
00922             d->pushEvent("subject keyed:" + ans2 + " for square counter");
00923             d->pushEvent("trial misscounting: " + stringify(abs(atoi(ans1.c_str()) - sineCounter) + abs(atoi(ans2.c_str()) - squareCounter)));
00924             missCounting += abs(atoi(ans1.c_str()) - sineCounter) + abs(atoi(ans2.c_str()) - squareCounter);
00925                         
00926                 }       
00927                 cr++;
00928             }
00929             d->pushEvent("correct spatial memory (fast tempo): " +stringify(correctSpatialMemory_1));
00930             d->pushEvent("incorrect spatial memory (fast tempo): " +stringify(incorrectSpatialMemory_1));
00931             d->pushEvent("correct spatial memory (slow tempo): " +stringify(correctSpatialMemory_2));
00932             d->pushEvent("incorrect spatial memory (slow tempo): " +stringify(incorrectSpatialMemory_2));
00933             d->pushEvent("correct counting: " +stringify(correctCounting));
00934             d->pushEvent("incorrect counting: " +stringify(incorrectCounting));
00935         d->pushEvent("total misscounting: "+stringify(missCounting));
00936             d->displayText("Experiment complete. Thank you!");
00937             d->waitForMouseClick();
00938 
00939           // stop all our ModelComponents
00940             manager.stop();
00941 
00942 
00943           // all done!
00944             return 0;
00945 }
00946 
00947 #endif // INVT_HAVE_LIBSDL_IMAGE
00948 
Generated on Sun May 8 08:40:10 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3