psychoWM-A.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/psychoWM-A.C $
00035 // $Id: psychoWM-A.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 #include "Component/ModelManager.H"
00038 #include "Image/Image.H"
00039 #include "Psycho/PsychoDisplay.H"
00040 #include "Psycho/EyeTrackerConfigurator.H"
00041 #include "Psycho/EyeTracker.H"
00042 #include "Psycho/PsychoOpts.H"
00043 #include "Component/EventLog.H"
00044 #include "Component/ComponentOpts.H"
00045 #include "Raster/Raster.H"
00046 #include "Util/MathFunctions.H"
00047 #include "Util/Types.H"
00048 #include "GameBoard/basic-graphics.H"
00049 #include <sys/types.h>
00050 #include <dirent.h>
00051 #include <errno.h>
00052 #include <vector>
00053 #include <string>
00054 #include <iostream>
00055 #include <SDL/SDL.h>
00056 #include <SDL/SDL_image.h>
00057 #include <stdio.h>
00058 #include <stdlib.h>
00059 #include <sstream>
00060 #include <time.h>
00061 #include "Image/DrawOps.H"
00062 #include "GameBoard/resize.h"
00063 #include <iostream>
00064 #include <fstream>
00065 #include <set>
00066 #include <algorithm>
00067 #include <ctime>
00068 #include "Devices/SimpleMotor.H"
00069 #include <SDL/SDL_mixer.h>
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 //nub::soft_ref<SimpleMotor> motor(new SimpleMotor(manager));
00090 map<uint,uint> testMap ;
00091 map<string,string> argMap ;
00092 Mix_Chunk *audio_chunk = NULL;
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 
00105 
00106 bool itIsInThere(int x , vector<int> bag){
00107         for( uint i=0 ; i < bag.size(); i++ ){
00108                 if(x == bag[i]) return true ;
00109         }
00110         return false ;
00111 }
00112 
00113 
00114 double getAvarage(vector<long> v){
00115         double f = 0.0 ;
00116         for( uint i = 0 ; i <  v.size() ; i++ ){
00117                 f += v[i] ;
00118         }
00119         if (v.size()!=0) return f/v.size() ;
00120         return -1 ;
00121 }
00122 
00123 double getVariance(vector<long> v){
00124         double m = getAvarage(v);
00125         double var = 0.0 ;
00126         for( uint i = 0 ; i < v.size(); i++ ){
00127                 var += (v[i]-m)*(v[i]-m) ;
00128         }
00129         if (v.size()!=0) return var/v.size() ;
00130         return -1 ;
00131 }
00132 
00133 
00134 //pushes back the name of files in the directory into the given vector
00135 int getdir (string dir, vector<string> &files)
00136 {
00137         DIR *dp;
00138         struct dirent *dirp;
00139         if((dp  = opendir(dir.c_str())) == NULL) {
00140                 cout << "Error(" << errno << ") opening " << dir << endl;
00141                 return errno;
00142         }
00143         string fn = "" ;
00144         size_t found;
00145         string extension = "" ;
00146         while ((dirp = readdir(dp)) != NULL) {
00147                 fn = string(dirp->d_name) ;
00148                 found = fn.find_last_of(".");
00149                 if(found > 0 && found <1000){
00150                         extension = fn.substr(found) ;
00151                         if(extension.compare(".png")== 0 || extension.compare(".jpg")==0 )
00152                                 files.push_back(dir+"/"+fn);
00153                 }
00154         }
00155         closedir(dp);
00156         return 0;
00157 }
00158 
00159 
00160 
00161 ////////////////////////////////////////////////////////////////////
00162 //// gets a string as the argument and returns a string composed of
00163 //// characters of the first string sorted in the ascending order
00164 ///////////////////////////////////////////////////////////////////
00165 string ascSort(string st)
00166 {
00167         string res = "" ;
00168         vector<string> v = vector<string>();
00169         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00170 
00171         std::sort(v.begin(), v.end());
00172 
00173         for ( uint i = 0 ; i < v.size() ; i++ ){
00174                 res += v[i] ;
00175         }
00176         return res;
00177 }
00178 
00179 
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //// gets a string as the argument and returns a string composed of
00183 //// characters of the first string sorted in the descending order
00184 ///////////////////////////////////////////////////////////////////
00185 string desSort(string st)
00186 {
00187         string res = "" ;
00188         vector<string> v = vector<string>();
00189         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00190         std::sort(v.begin(), v.end());
00191         std::reverse(v.begin(), v.end());
00192         for ( uint i = 0 ; i < v.size() ; i++ ){
00193                 res += v[i] ;
00194         }
00195         return res;
00196 }
00197 
00198 
00199 /////////////////////////////////////////////////////////////
00200 //this function checks how many subblocks of the sorted string can be found in
00201 //original string, the bigger chunks found the bigger number will be return
00202 ////////////////////////////////////////////////////////////
00203 
00204 int mydist(string str , string sorted){
00205         size_t found;
00206         int m = 0 ;
00207         for(uint i = 2 ; i <= sorted.size() ; i++ ){
00208                 for(uint j = 0 ; j <= sorted.size()-i  ; j++ ) {
00209                         found = str.find(sorted.substr(j,i));
00210                         if (found!=string::npos) m += i ;
00211                 }
00212         }
00213         return m ;
00214 }
00215 
00216 /////////////////////////////////////////////////////////////
00217 //this function checks out the difficulty of sorting the string assigns a number which
00218 //reflects how many moves are needed for sorting,
00219 ////////////////////////////////////////////////////////////
00220 
00221 int getDisMetric(string st){
00222         int m = 0 ;
00223         size_t found;
00224         string asString = ascSort(st) ;
00225         for(uint i = 0 ; i < st.size() ; i++ ){
00226                 found = asString.find(st.substr(i,1));
00227                 m += abs((int)i-int(found)) ;
00228         }
00229 
00230         return m- 2*mydist(st,asString) ;
00231 }
00232 
00233 
00234 
00235 ////////////////////////////////////////////////////////
00236 ///// 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
00237 //highest metric value in 1000000 times try will be returned
00238 ////////////////////////////////////////////////////////
00239 
00240 string getARandomString(uint l, string alphabet="0123456789" , int thresh=0){
00241 
00242         string test = string("") ;
00243         string retString ;
00244         int maxDist = -1000000;
00245         int it = 0 ;
00246         int d = 0 ;
00247         do{
00248                 test = "" ;
00249                 string tp = string("") ;
00250                 vector<int> pickedones = vector<int>() ;
00251                 for(uint i = 0 ; i < l ; i++){
00252                         int nd;
00253                         do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00254                         pickedones.push_back(nd);
00255                         tp = alphabet.substr(nd,1) ;
00256                         test += tp ;
00257                 }
00258                 it++ ;
00259                 d = getDisMetric(test);
00260                 maxDist=max(maxDist,d) ;
00261                 if (d==maxDist) retString = test ;
00262 
00263         }while( maxDist<thresh && it < 1000000);
00264 
00265         return retString ;
00266 }
00267 
00268 ///////////////////////////////////////////////////////
00269 //this function is not called in this program, but it generates a random string and it will show it in
00270 //a random place on the screen.
00271 //////////////////////////////////////////////////////
00272 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10  ){
00273         d->clearScreen() ;
00274         vector<int> pickedones = vector<int>() ;
00275         string test = string("") ;
00276         string tp = string("") ;
00277         for(uint i = 0 ; i < l ; i++){
00278                 int nd;
00279                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00280                 pickedones.push_back(nd);
00281                 tp = alphabet.substr(nd,1) ;
00282                 test += tp ;
00283         }
00284         d->displayText(test,true,0) ;
00285         d->waitFrames(displayFrame) ;
00286         d->clearScreen() ;
00287         return test ;
00288 }
00289 
00290 
00291 ////////////////////////////////////////////////////////
00292 ///////this will change the order of elements in a vector to a random order
00293 ////////////////////////////////////////////////////////
00294 void scramble(vector<string>& v){
00295         vector<string> tv = vector<string>() ;
00296         while(v.size()>0){
00297                 tv.push_back(v[0]);
00298                 v.erase(v.begin());
00299         }
00300         int i = 0 ;
00301         while(tv.size()>0){
00302                 i = rand()%tv.size() ;
00303                 v.push_back(tv[i]);
00304                 tv.erase(tv.begin()+i);
00305         }
00306 }
00307 
00308 
00309 ////////////////////////////////////////////////////////////////
00310 ////This is our button factory
00311 ////////////////////////////////////////////////////////////////
00312 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){
00313         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00314         textIm.clear(bgcolor);
00315         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00316         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00317         Uint32 bc = d->getUint32color(bordercolor);
00318         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00319         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00320         SDL_Rect clip;
00321         clip.x = 0 ;
00322         clip.y = 0 ;
00323         clip.w = size.i ;
00324         clip.h = size.j ;
00325         apply_surface(0,0,*surf,*blank,clip);
00326         dumpSurface(surf) ;
00327         return blank ;
00328 }
00329 
00330 ////////////////////////////////////////////////////////////////////////
00331 ////This is the function for creating the keypad, in fact it generates
00332 ////12 buttons and associates the actions to the region for each button
00333 ////////////////////////////////////////////////////////////////////////
00334 
00335 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00336         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00337         SDL_Rect clip;
00338         clip.x=0;
00339         clip.y=0;
00340         int numofrows = alphabet.size()/3 +1;
00341         if(alphabet.size()%3 != 0 ) numofrows++ ;
00342         int numofcolumns = 3 ;
00343         clip.w= pad->w / numofcolumns ;
00344         clip.h = pad->h / numofrows ;
00345 
00346   //keys for 1 to 9
00347         for( int i = 0 ; i < numofrows*3 ; i++){
00348                 SDL_Surface* but ;
00349                 if((uint)i < alphabet.size()){
00350                         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);
00351                 }else{
00352                         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);
00353                 }
00354 
00355                 SDL_Rect cl ;
00356                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00357                 cl.w = clip.w ;
00358                 cl.h = clip.h ;
00359                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00360                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00361                 dumpSurface(but);
00362         }
00363         SDL_Rect cl1 ;
00364         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00365         cl1.w = clip.w ;
00366         cl1.h = clip.h ;
00367         buttmap["!"] = cl1 ;
00368         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);
00369         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00370         dumpSurface(but);
00371         SDL_Rect cl2 ;
00372         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00373         cl2.w = clip.w ;
00374         cl2.h = clip.h ;
00375         buttmap[" "] = cl2 ;
00376         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);
00377         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00378         dumpSurface(but);
00379         SDL_Rect cl3 ;
00380         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00381         cl3.w = clip.w ;
00382         cl3.h = clip.h ;
00383         buttmap["*"] = cl3 ;
00384         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);
00385         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00386         dumpSurface(but);
00387         return pad ;
00388 }
00389 
00390 
00391 
00392 
00393 ///////////////////////////////////////////////////////////////////////////
00394 /////this function listens to mouse clicks and then finds the region of the screen
00395 /////associated with the action, buttmap is the map of the region, offset is the offset of
00396 /////buttons
00397 ///////////////////////////////////////////////////////////////////////////
00398 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00399         int quit = 0 ;
00400         string s ;
00401         SDL_Event event ;
00402         while( quit!=2 ){
00403                 while( SDL_PollEvent( &event ) ) {
00404                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00405                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00406                                         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) {
00407                                                 quit = 2 ;
00408                                                 s = it->first ;
00409                                                 break;
00410                                         }
00411 
00412                                 }
00413                         }
00414 
00415                 }
00416         }
00417         return s ;
00418 
00419 }
00420 
00421 
00422 ////////////////////////////////////////////////////
00423 ////This function creates a virtual keypad, creates a map of buttons
00424 ////and their representation area and listens to the button press and at
00425 ////the end returns the keyed digits
00426 ////////////////////////////////////////////////////
00427 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 ){
00428         d->showCursor(true) ;
00429         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00430         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00431         //now let's get the keypad surface while we get the actions map to regions
00432         SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00433         //this will be the offset of displaying the keypad on the screen
00434         SDL_Rect offset ;
00435         offset.x = (d->getWidth() - keypad->w) /2;
00436         offset.y = (d-> getHeight() - keypad->h) /2;
00437         //now let's display the keypad
00438         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00439         //this will hold the final string keyed be the subject
00440         string p = string("") ;
00441         //this is a temporary string holding the last action related to the pressed key
00442         string tp = string("");
00443         //now let's record subject's key press
00444         while( tp.compare("*")!=0 ){
00445                 //this button is actually the display for the current string
00446                 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) ;
00447                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00448                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00449                 //now let's listen to button events
00450                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00451                 dumpSurface(dp) ;
00452                 if(tp.compare("!")==0 && p.size()>=0 ) {
00453                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00454                 }else{
00455                         if(p.size() < maxl && tp.compare("*")!=0) {
00456                                 p +=tp ;
00457                         }
00458 
00459                 }
00460 
00461         }
00462         buttmap = 0 ;
00463         dumpSurface(keypad) ;
00464         d->clearScreen() ;
00465         return p ;
00466 
00467 }
00468 
00469 //and this is the function which creates and displays a mask of randomly positioned numbers
00470 void showMask(int frames, string alphabet="0123456789"){
00471         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00472         PixRGB<byte> bgcolor = PixRGB<byte>(128,128,128);
00473         PixRGB<byte> txtcolor = PixRGB<byte>(0,0,0);
00474         textIm.clear(bgcolor);
00475         for(int i = 0 ;  i < 200 ; i++)
00476                 writeText(textIm, Point2D<int>((int)random()%(d->getWidth()),(int)random()%(d->getHeight())),alphabet.substr(random()%(int)alphabet.size(),1).c_str(),txtcolor,bgcolor);
00477         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00478         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00479         d->displaySDLSurfacePatch(surf , &offs , NULL , -2 , false ,true ) ;
00480         d->waitFrames(frames) ;
00481         d->clearScreen();
00482         dumpSurface(surf) ;
00483 }
00484 ///////////////////////////////////////////////////////////////
00485 //////gets the test string, answer and the mode and identifies if
00486 //////the answer matches the thing it should be, mode=0 checks if
00487 //////if the answer and test string simply the same, mode=1 matches
00488 //////the answer against the ascending sorted string of the test string
00489 //////mode=2 compares the answer against the descending sorted of
00490 //////the test string
00491 ///////////////////////////////////////////////////////////////
00492 bool isAnswerCorrect(string test , string answer , int mode){
00493 
00494         if(mode == 0 && answer.compare(test)==0) return true ;
00495 
00496         if(mode == 1 && answer.compare(ascSort(test))==0) return true ;
00497 
00498         if(mode == 2 && answer.compare(desSort(test))==0) return true ;
00499 
00500         return false;
00501 }
00502 
00503 
00504 
00505 int addArgument(const string st,const string delim="="){
00506         int i = st.find(delim) ;
00507         argMap[st.substr(0,i)] = st.substr(i+1);
00508 
00509         return 0 ;
00510 }
00511 
00512 std::string getArgumentValue(string arg){
00513         return argMap[arg] ;
00514 }
00515 
00516 std::string getUsageComment(){
00517 
00518         string com = string("\nlist of arguments : \n");
00519         com += "\nlogfile=[logfilename.psy] {default = psycho-wm-a.psy}\n" ;
00520         com += "\nmemo=[a_string_without_white_space]\n";
00521         com += "\nstring-size=[>0](the size of string){default=5} \n";
00522         com += "\nsubject=[subject_name] \n" ;
00523         com += "\ntest-rounds=[>1] (number of tests ) {default=10}\n";
00524         com += "\ndigit-onset=[>1] (number of frames that the string will remain onset ){default=10}\n";
00525         com += "\nalphabet=[a string of characters](a string of characters){default=0123456789}\n";
00526         com += "\nmetric-thresholdt=[>-30 for string of lenght of 5](a string of characters){default=10}\n";
00527         com += "\nmaintain-prb=[a number between 0 to 1], probability of challenging the subject with a memorization task, default=0.2\n"  ;
00528         com += "\nmin-reaction-time=[>0](minimum value for avarage reaction time in microsecond in order to consider a trial valid){default=1000000}\n" ;
00529         com += "\nmax-miss=[>0](maximum misses in a trial in order to be  considered as a valid one){default=0}";
00530         com += "\nmax-false-click=[>0](maximum false clicks in a trial in order to be  considered as a valid one){default=0}";
00531         com += "\ninterrupt-time-range=[x-y](this defines a range of uniform radom distribution by which the perceptual interruption happens){default=500000-5000000}\n" ;
00532         com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n";
00533         com += "\ncue-onset-frames=[<0](number of frames to show the cue onset){default=3}\n";
00534         com += "\nmask=[y/n](whether present a mask after presentation, n for no, y  for yes ){default=n}\n" ;
00535         com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n";
00536         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00537         com += "\audio-file=[white noise file]{default=audio.wav}\n";
00538         com += "\npuase-frames=[number of frames for stopping the the audio playback]{default=5}\n";
00539         return com ;
00540 }
00541 
00542 int myCheckForMouseClick()
00543 {
00544         SDL_Event event;
00545 
00546         while(SDL_PollEvent(&event))
00547         {
00548                 if (event.type == SDL_MOUSEBUTTONDOWN)
00549                 {
00550                         if(event.button.button == SDL_BUTTON_LEFT) {
00551                                 return 1 ;
00552                         }
00553                         if(event.button.button == SDL_BUTTON_RIGHT) {
00554                                 return 2 ;
00555                         }
00556 
00557                 }
00558       // ignore other events
00559         }
00560 
00561   // there was no event in the event queue:
00562         return -1;
00563 }
00564 
00565 
00566 int getClick(){
00567     // while (myCheckForMouseClick() != -1) ;
00568         SDL_Event event;
00569         bool report = false ;
00570         int i = 0;  // will be returned if any other button than left or right
00571         do {
00572                 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN);
00573                 if (event.button.button == SDL_BUTTON_LEFT) {
00574                         i = 0 ;
00575                         report = true ;
00576                 }
00577                 if (event.button.button == SDL_BUTTON_RIGHT) {
00578                         i = 1 ;
00579                         report = true ;
00580                 }
00581 
00582         }while(!report) ;
00583 
00584         return i ;
00585 }
00586 
00587 int getAllKindOfClick(){
00588     // while (myCheckForMouseClick() != -1) ;
00589         SDL_Event event;
00590         bool report = false ;
00591         int i = 0;  // will be returned if any other button than left or right
00592         do {
00593                 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN);
00594                 long st = d->getTimerValue();
00595                 long et = st ;
00596 
00597                 if (event.button.button == SDL_BUTTON_LEFT) {
00598                         i = 0 ;
00599                         report = true ;
00600                         while( et-st < 300000){
00601                                 et = d->getTimerValue() ;
00602                                 if(myCheckForMouseClick()==1) return 2 ;
00603                         }
00604                 }
00605                 if (event.button.button == SDL_BUTTON_RIGHT) {
00606                         i = 1 ;
00607                         report = true ;
00608                 }
00609 
00610         }while(!report) ;
00611 
00612         return i ;
00613 
00614 }
00615 
00616 int getNext(int i){
00617 
00618         int r = 1 ;
00619         if(i == 0 || i == 2) return 1 ;
00620         r = random()%2 ;
00621         if(r == 0) return 0 ;
00622         if(r == 1 ) return 2 ;
00623         return r ;
00624 }
00625 extern "C" int main(const int argc, char** argv)
00626 {
00627 
00628         MYLOGVERB = LOG_INFO;  // suppress debug messages
00629         //let's push the initial value for the parameters
00630         argMap["experiment"]="sorting_strings_in_working_memory-with-audio-presentation";
00631         argMap["logfile"]="psycho-wm-a.psy" ;
00632         argMap["string-size"]="5" ;
00633         argMap["test-rounds"]="10";
00634         argMap["subject"]="" ;
00635         argMap["memo"]="" ;
00636         argMap["digit-onset"]="10" ;
00637         argMap["alphabet"]="0123456789";
00638         argMap["metric-threshold"]="10" ;
00639         argMap["maintain-prb"]="0.2" ;
00640         argMap["min-reaction-time"]="1000000" ;
00641         argMap["max-miss"]="0" ;
00642         argMap["interrupt-time-range"]= "500000-5000000";
00643         argMap["cue-wait-frames"]="0" ;
00644         argMap["mask"]="n" ;
00645         argMap["mask-onset-frames"]="0";
00646         argMap["cue-onset-frames"] = "3" ;
00647         argMap["sound-dir"]="..";
00648         argMap["audio-file"]="audio.wav";
00649         argMap["pause-frames"]="5" ;
00650         argMap["max-false-click"]="0";
00651         manager.addSubComponent(d);
00652         //manager.addSubComponent(motor) ;
00653         nub::soft_ref<EventLog> el(new EventLog(manager));
00654         manager.addSubComponent(el);
00655         d->setEventLog(el);
00656         //mmanager.parseCommandLine(argc, argv, "", 0,0);
00657         //mmanager.start();
00658 
00659         if (manager.parseCommandLine(argc, argv,
00660             "at least one argument needed", 1, -1)==false){
00661                     cout<<getUsageComment()<<endl;
00662                     return(1);
00663             }
00664 
00665             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00666                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00667             }
00668 
00669             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00670             if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00671                     LINFO( "did not open the mix-audio") ;
00672                     return -1 ;
00673             }
00674             string noisestr = argMap["sound-dir"] + "/" + argMap["audio-file"];
00675             audio_chunk = Mix_LoadWAV(noisestr.c_str());
00676             if( audio_chunk == NULL  )
00677             {
00678                     LINFO("did not find the indicated wav files!");
00679                     return -1;
00680             }
00681 
00682 
00683   // let's get all our ModelComponent instances started:
00684             manager.start();
00685             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00686             SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00687 
00688   // let's display an ISCAN calibration grid:
00689             d->clearScreen();
00690             d->displayISCANcalib();
00691             d->waitForMouseClick();
00692             d->displayText("Here the experiment starts! click to start!");
00693             d->waitForMouseClick();
00694             d->clearScreen();
00695         //let's see in what mode the user like to run the program
00696 
00697             int numOfTests = atoi(argMap["test-rounds"].c_str()) ;
00698             int stringSize = atoi(argMap["string-size"].c_str());
00699             int meticThreshold = atoi(argMap["metric-threshold"].c_str()) ;
00700             int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00701             float memPrb = atof(argMap["maintain-prb"].c_str()) ;
00702             int max_miss = atoi(argMap["max-miss"].c_str());
00703             int max_wrong = atoi(argMap["max-false-click"].c_str()) ;
00704             int in  = argMap["interrupt-time-range"].find("-") ;
00705             long iub = atol(argMap["interrupt-time-range"].substr(in+1).c_str());
00706             long ilb = atol(argMap["interrupt-time-range"].substr(0,in).c_str()) ;
00707             long min_reaction_time = atol(argMap["min-reaction-time"].c_str()) ;
00708             int cue_onset_frames = atoi(argMap["cue-onset-frames"].c_str()) ;
00709             int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ;
00710             int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ;
00711             int pause_frames = atoi(argMap["pause-frames"].c_str());
00712         //let's count the rounds
00713             int cr = 0 ;
00714             int fm =0 ; //keeps number of failed memory tests
00715             int sm = 0 ; //keeps number of successful memory tests
00716             int ssfr=0 ; //keeps number of successful sorts but failed reactions
00717             int fssr=0 ; //keeps number of failed sorting and suuccessful reaction
00718             int sssr=0 ; //keeps number of successful sorting and successful reaction
00719             int fsfr=0 ; //keeps number of failed sorting and failed reactions
00720             vector<long> correctAnswersTiming;
00721             vector<long> incorrectAnswersTiming;
00722             vector<long> allTiming ;
00723             Mix_PlayChannel( -1, audio_chunk , 500 ) ;Mix_Pause(-1);
00724             while( cr <numOfTests ){
00725                     float mP = (float) rand()/RAND_MAX  ;
00726                     if(mP > memPrb){
00727 
00728                             d->pushEvent("**************************************") ;
00729                             d->showCursor(true);
00730                             d->displayText("click one of the  mouse buttons to start!");
00731                             d->waitForMouseClick() ;
00732                             d->showCursor(false) ;
00733                             string testString ;
00734                             vector<long> reactionTimes ;
00735                             testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ;
00736                             d->clearScreen() ;
00737                             d->displayFixationBlink();
00738                             d->displayText(testString,true,0) ;
00739                             d->waitFrames(onsetDel) ;
00740                             d->clearScreen() ;
00741                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00742                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00743                             d->displayRedDotFixation();
00744                             d->waitFrames(cue_onset_frames);
00745 
00746                             long st = d->getTimerValue() ;
00747                             d->clearScreen() ;
00748                             d->pushEvent("manipulation starts");
00749                             d->pushEvent("the sequence for manipulation is : "+testString) ;
00750                             Mix_Resume(-1) ;
00751                             long tst =0 ;
00752                             long tet =0 ;
00753                             long dst = 0 ;
00754                             long det = 0 ;
00755                             long dl = 0 ;
00756                             dl = ilb+ random() % (iub-ilb);//we get a value for next stop
00757                             dst = d->getTimerValue() ;
00758                             det = dst ;
00759                             int missed = 0 ;
00760                             bool exitFlag = false ;
00761                             bool clickFlag = false ;
00762                             int ms = -1 ;//holds  mouseclick status
00763                             int wrongclick = 0 ;
00764                             while( !exitFlag ){
00765 
00766                                     if (det - dst > dl ){
00767                                             Mix_Pause(-1);
00768                                             d->waitFrames(pause_frames);
00769                                             Mix_Resume(-1) ;
00770                                             tst = d->getTimerValue() ;
00771                                             det=tst ;
00772                                             if(clickFlag){
00773                                                     missed++ ;
00774                                                     d->pushEvent("missed one change");
00775                                             }
00776                                             clickFlag=true ;
00777                                             dst = det ;
00778                                             dl = ilb+ random() % (iub-ilb);//we get a value for next stop
00779                                     }
00780                                     ms = myCheckForMouseClick() ;
00781                                     if(ms==2) exitFlag = true ;
00782                                     det = d->getTimerValue() ;
00783 
00784                                     if(clickFlag && ms==1){
00785                                             clickFlag = false ;
00786                                             tet = d->getTimerValue() ;
00787                                             reactionTimes.push_back(tet-tst);
00788                                             d->pushEvent("reaction time :" + stringify(tet-tst));
00789                                     }else{if(ms==1) wrongclick++ ;}
00790                             }
00791                             Mix_Pause(-1);
00792                             long et = d->getTimerValue();
00793                             d->pushEvent("manipulation ends") ;
00794                             d->pushEvent("maniupulation time : "+stringify(et-st)) ;allTiming.push_back(et-st);
00795                             d->clearScreen();
00796                             string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00797 
00798                             bool af = false ;
00799                             af = isAnswerCorrect(testString,answer,1);
00800                             d->pushEvent("subject keyed : "+answer);
00801                             d->pushEvent("avarage reaction time : "+ stringify(getAvarage(reactionTimes))) ;
00802                             d->pushEvent("number of missed events : "+stringify(missed));
00803                             d->pushEvent("number of caught events : "+stringify(reactionTimes.size())) ;
00804                             if(missed <= max_miss && getAvarage(reactionTimes)<= min_reaction_time && wrongclick<=max_wrong){
00805                                     cr++;
00806                                     d->pushEvent("valid trial");
00807                                     if(af){
00808                                             d->pushEvent("answer was correct");sssr++;correctAnswersTiming.push_back(et-st) ;
00809                                     }else{
00810                                             d->pushEvent("answer was incorrect");fssr++;
00811                                     }
00812                             }else{
00813                                     if(wrongclick > max_wrong) {
00814                                                 d->displayText("Trial failed, too many FALSE REPORT! Click to start over!");
00815                                                 d->waitForMouseClick();
00816                                         }
00817                                     if(missed > max_miss) {
00818                                             d->displayText("Trial failed, too many events missed! Click to start over!");
00819                                             d->waitForMouseClick();
00820                                     }
00821                                     if(getAvarage(reactionTimes) > min_reaction_time){
00822                                             d->displayText("Trial failed, reaction slower than limit! Click to start over!");
00823                                             d->waitForMouseClick();
00824                                     }
00825                                     if(af){
00826                                             d->pushEvent("answer was correct");ssfr++;
00827                                     }else{
00828                                             d->pushEvent("answer was incorrect");fsfr++;
00829                                     }
00830                                     d->pushEvent("invalid trial");
00831                             }
00832 
00833                     }else{
00834                             d->pushEvent("+++++++++++++++++++++++++++++++++++++++") ;
00835                             d->showCursor(true);
00836                             d->displayText("click one of the  mouse buttons to start!");
00837                             d->waitForMouseClick() ;
00838                             d->showCursor(false) ;
00839                             string testString ;
00840                             testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ;
00841                             d->clearScreen() ;
00842                             d->displayFixationBlink();
00843                             d->displayText(testString,true,0) ;
00844                             d->waitFrames(onsetDel) ;
00845                             d->clearScreen() ;
00846                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00847                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00848                             d->displayFixationBlink(d->getWidth()/2,d->getHeight()/2,1,3);
00849                             d->pushEvent("the memorization sequence is : "+testString) ;
00850 
00851                             d->pushEvent("subject is being challenged for simple momorization");
00852                             d->clearScreen();
00853 
00854                             string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00855 
00856                             bool af = false ;
00857                             af = isAnswerCorrect(testString,answer,0);
00858                             d->pushEvent("subject keyed : "+answer);
00859                             if(af){
00860                                     d->pushEvent("correct answer");
00861                                     sm++;
00862                             }else{
00863                                     d->pushEvent("incorrect answer");
00864                                     fm++ ;
00865                             }
00866 
00867                     }
00868             }
00869 
00870             d->pushEvent("number of successful memory tests :" + stringify(sm));
00871             d->pushEvent("number of failed memory tests :" + stringify(fm)) ;
00872             d->pushEvent("number of successful sorting and successful reaction trials :"+stringify(sssr));
00873             d->pushEvent("number of successful sorting and failed reaction trials :"+stringify(ssfr));
00874             d->pushEvent("number of failed sorting and successful reaction trials :"+stringify(fssr));
00875             d->pushEvent("number of failed sorting and failed reaction trials :"+stringify(fsfr));
00876             d->pushEvent("avarage time for respond :"+ stringify(getAvarage(allTiming)));
00877             d->pushEvent("variance of respond :"+ stringify(getVariance(allTiming)));
00878             d->pushEvent("avarage time for correct answers "+stringify(getAvarage(correctAnswersTiming))) ;
00879             d->pushEvent("variance of correct responds :"+ stringify(getVariance(correctAnswersTiming)));
00880             d->clearScreen();
00881             d->displayText("Experiment complete. Thank you!");
00882             d->waitForMouseClick();
00883             Mix_FreeChunk( audio_chunk );
00884             Mix_CloseAudio();
00885         // stop all our ModelComponents
00886             manager.stop();
00887 
00888 
00889         // all done!
00890             return 0;
00891 }
00892 
00893 #endif // INVT_HAVE_LIBSDL_IMAGE
00894 
Generated on Sun May 8 08:04:21 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3