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