psychoWM-S.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-S.C $
00035 // $Id: psychoWM-S.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 
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 += "\nmin-reaction-time=[>0](minimum value for avarage reaction time in microsecond in order to consider a trial valid){default=1000000}\n" ;
00506         com += "\nmax-miss=[>0](maximum misses in a trial in order to be  considered as a valid one){default=0}";
00507         com += "\nmax-false-click=[>0](maximum false clicks in a trial in order to be  considered as a valid one){default=0}";
00508         com += "\ninterrupt-time-range=[x-y](this defines a range of uniform radom distribution by which the perceptual interruption happens){default=500000-5000000}\n" ;
00509         com += "\nrgb1=[r-g-b]{default=50-91-255}\n";
00510         com += "\nrgb2=[r-g-b]{default=89-122-255}\n";
00511         com += "\nrgb3=[r-g-b]{default=138-159-255}\n";
00512         com += "\ncue-wait-frames=[<0](number of frames to show the cue){default=0}\n";
00513         com += "\ncue-onset-frames=[<0](number of frames to show the cue onset){default=3}\n";
00514         com += "\nmask=[y/n](whether present a mask after presentation, n for no, y  for yes ){default=n}\n" ;
00515         com += "\nmask-onset-frames=[<0](number of frames that mask will be onset){default=0}\n";
00516         com += "\nball-radius={0<}(radius of the ball){default=4}\n" ;
00517         return com ;
00518 }
00519 
00520 int myCheckForMouseClick()
00521 {
00522         SDL_Event event;
00523 
00524         while(SDL_PollEvent(&event))
00525         {
00526                 if (event.type == SDL_MOUSEBUTTONDOWN)
00527                 {
00528                         if(event.button.button == SDL_BUTTON_LEFT) {
00529                                 return 1 ;
00530                         }
00531                         if(event.button.button == SDL_BUTTON_RIGHT) {
00532                                 return 2 ;
00533                         }
00534 
00535                 }
00536       // ignore other events
00537         }
00538 
00539   // there was no event in the event queue:
00540         return -1;
00541 }
00542 
00543 
00544 int getClick(){
00545     // while (myCheckForMouseClick() != -1) ;
00546         SDL_Event event;
00547         bool report = false ;
00548         int i = 0;  // will be returned if any other button than left or right
00549         do {
00550                 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN);
00551                 if (event.button.button == SDL_BUTTON_LEFT) {
00552                         i = 0 ;
00553                         report = true ;
00554                 }
00555                 if (event.button.button == SDL_BUTTON_RIGHT) {
00556                         i = 1 ;
00557                         report = true ;
00558                 }
00559 
00560         }while(!report) ;
00561 
00562         return i ;
00563 }
00564 
00565 int getAllKindOfClick(){
00566     // while (myCheckForMouseClick() != -1) ;
00567         SDL_Event event;
00568         bool report = false ;
00569         int i = 0;  // will be returned if any other button than left or right
00570         do {
00571                 do { SDL_WaitEvent(&event); } while (event.type != SDL_MOUSEBUTTONDOWN);
00572                 long st = d->getTimerValue();
00573                 long et = st ;
00574 
00575                 if (event.button.button == SDL_BUTTON_LEFT) {
00576                         i = 0 ;
00577                         report = true ;
00578                         while( et-st < 300000){
00579                                 et = d->getTimerValue() ;
00580                                 if(myCheckForMouseClick()==1) return 2 ;
00581                         }
00582                 }
00583                 if (event.button.button == SDL_BUTTON_RIGHT) {
00584                         i = 1 ;
00585                         report = true ;
00586                 }
00587 
00588         }while(!report) ;
00589 
00590         return i ;
00591 
00592 }
00593 
00594 int getNext(int i){
00595 
00596         int r = 1 ;
00597         if(i == 0 || i == 2) return 1 ;
00598         r = random()%2 ;
00599         if(r == 0) return 0 ;
00600         if(r == 1 ) return 2 ;
00601         return r ;
00602 }
00603 
00604 void drawDot(long t , int r , int c , vector<Uint32> colorVector){
00605         int x = d->getWidth()/2 + (int)((d->getWidth()/3)*cos((double)t/1000000)) ;
00606         int y = d->getHeight()/2 + (int)((d->getHeight()/3 )*sin( 0.2 + (double)t/1000000)) ;
00607         SDL_Surface* black = getABlankSurface(d->getWidth(),d->getHeight());
00608 
00609         fillCubicRadiant(black,colorVector[c],x,y,r) ;
00610         SDL_Rect offs ; offs.x = 0 ; offs.y = 0 ;
00611         d->displaySDLSurfacePatch(black , &offs , NULL , -2 , false ,true ) ;
00612         dumpSurface(black) ;
00613 }
00614 
00615 
00616 extern "C" int main(const int argc, char** argv)
00617 {
00618 
00619         MYLOGVERB = LOG_INFO;  // suppress debug messages
00620         //let's push the initial value for the parameters
00621         argMap["experiment"]="sorting_strings_in_working_memory-with-moving-stimulus";
00622         argMap["logfile"]="psycho-wm-s.psy" ;
00623         argMap["string-size"]="5" ;
00624         argMap["test-rounds"]="10";
00625         argMap["subject"]="" ;
00626         argMap["memo"]="" ;
00627         argMap["digit-onset"]="10" ;
00628         argMap["alphabet"]="0123456789";
00629         argMap["metric-threshold"]="10" ;
00630         argMap["maintain-prb"]="0.2" ;
00631         argMap["ball-radius"] = "4" ;
00632         argMap["min-reaction-time"]="1000000" ;
00633         argMap["max-miss"]="0" ;
00634         argMap["interrupt-time-range"]= "500000-5000000";
00635         argMap["rgb1"]="50-91-255" ;
00636         argMap["rgb2"]="89-122-255" ;
00637         argMap["rgb3"]="138-159-255" ;
00638         argMap["cue-wait-frames"]="0" ;
00639         argMap["mask"]="n" ;
00640         argMap["mask-onset-frames"]="0";
00641         argMap["cue-onset-frames"] = "3" ;
00642         argMap["max-false-click"]="0";
00643         manager.addSubComponent(d);
00644         //manager.addSubComponent(motor) ;
00645         nub::soft_ref<EventLog> el(new EventLog(manager));
00646         manager.addSubComponent(el);
00647         d->setEventLog(el);
00648         //mmanager.parseCommandLine(argc, argv, "", 0,0);
00649         //mmanager.start();
00650 
00651         if (manager.parseCommandLine(argc, argv,
00652             "at least one argument needed", 1, -1)==false){
00653                     cout<<getUsageComment()<<endl;
00654                     return(1);
00655             }
00656 
00657             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00658                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00659             }
00660 
00661             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00662 
00663 
00664 
00665   // let's get all our ModelComponent instances started:
00666             manager.start();
00667             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00668 
00669             int x = 0 ; int y = 0 ; int rad = 0 ;
00670             if(argMap["ball-position"].compare("0")==0){
00671                     x = d->getWidth()/2 ;
00672                     y = d->getHeight() /2 ;
00673             }else{
00674                     int in = argMap["ball-position"].find("-") ;
00675                     x = atoi( argMap["ball-position"].substr(in+1).c_str()) ;
00676                     y = atoi(argMap["ball-position"].substr(0,in).c_str()) ;
00677             }
00678 
00679             if(argMap["ball-radius"].compare("-1") == 0){
00680                     rad = min(min(y-1,d->getHeight()-y-1),min(x,d->getWidth()-x-1)) ;
00681             }else{
00682                     rad = atoi(argMap["ball-radius"].c_str()) ;
00683                     rad = min(rad, min(min(y-1,d->getHeight()-y-1),min(x,d->getWidth()-x-1))) ;
00684             }
00685 
00686             string rgb1 = argMap["rgb1"] ;
00687             string rgb2 = argMap["rgb2"] ;
00688             string rgb3 = argMap["rgb3"] ;
00689             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())));
00690             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())));
00691             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())));
00692             vector<Uint32> colorVector ;
00693             colorVector.push_back(color1) ;
00694             colorVector.push_back(color2) ;
00695             colorVector.push_back(color3) ;
00696 
00697 
00698   // let's display an ISCAN calibration grid:
00699             d->clearScreen();
00700             d->displayISCANcalib();
00701             d->waitForMouseClick();
00702             d->displayText("Here the experiment starts! click to start!");
00703             d->waitForMouseClick();
00704             d->clearScreen();
00705         //let's see in what mode the user like to run the program
00706 
00707             int numOfTests = atoi(argMap["test-rounds"].c_str()) ;
00708             int stringSize = atoi(argMap["string-size"].c_str());
00709             int meticThreshold = atoi(argMap["metric-threshold"].c_str()) ;
00710             int onsetDel = atoi(argMap["digit-onset"].c_str()) ;
00711             float memPrb = atof(argMap["maintain-prb"].c_str()) ;
00712             int max_miss = atoi(argMap["max-miss"].c_str());
00713             int max_wrong = atoi(argMap["max-false-click"].c_str()) ;
00714             int in  = argMap["interrupt-time-range"].find("-") ;
00715             long iub = atol(argMap["interrupt-time-range"].substr(in+1).c_str());
00716             long ilb = atol(argMap["interrupt-time-range"].substr(0,in).c_str()) ;
00717             long min_reaction_time = atol(argMap["min-reaction-time"].c_str()) ;
00718             int cue_onset_frames = atoi(argMap["cue-onset-frames"].c_str()) ;
00719             int cue_wait_frames = atoi(argMap["cue-wait-frames"].c_str()) ;
00720             int mask_onset_frames = atoi(argMap["mask-onset-frames"].c_str()) ;
00721             int br = atoi(argMap["ball-radius"].c_str());
00722         //let's count the rounds
00723             int cr = 0 ;
00724             int fm =0 ; //keeps number of failed memory tests
00725             int sm = 0 ; //keeps number of successful memory tests
00726             int ssfr=0 ; //keeps number of successful sorts but failed reactions
00727             int fssr=0 ; //keeps number of failed sorting and suuccessful reaction
00728             int sssr=0 ; //keeps number of successful sorting and successful reaction
00729             int fsfr=0 ; //keeps number of failed sorting and failed reactions
00730             vector<long> correctAnswersTiming;
00731             vector<long> incorrectAnswersTiming;
00732             vector<long> allTiming ;
00733             while( cr <numOfTests ){
00734                     float mP = (float) rand()/RAND_MAX  ;
00735                     if(mP > memPrb){
00736 
00737                             d->pushEvent("**************************************") ;
00738                             d->showCursor(true);
00739                             d->displayText("click one of the  mouse buttons to start!");
00740                             d->waitForMouseClick() ;
00741                             d->showCursor(false) ;
00742                             string testString ;
00743                             vector<long> reactionTimes ;
00744                             testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ;
00745                             d->clearScreen() ;
00746                             d->displayFixationBlink();
00747                             d->displayText(testString,true,0) ;
00748                             d->waitFrames(onsetDel) ;
00749                             d->clearScreen() ;
00750                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00751                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00752                             d->displayRedDotFixation();
00753                             d->waitFrames(cue_onset_frames);
00754                             long st = d->getTimerValue() ;
00755                             d->clearScreen() ;
00756                             d->pushEvent("manipulation starts");
00757                             d->pushEvent("the sequence for manipulation is : "+testString) ;
00758 
00759                             long tst =0 ;
00760                             long tet =0 ;
00761 
00762                             int cs = 0 ;
00763                             long dst = 0 ;
00764                             long det = 0 ;
00765                             long dl = 0 ;
00766                             dl = ilb+ random() % (iub-ilb);//we get a value for next stop
00767                             dst = d->getTimerValue() ;
00768                             det = dst ;
00769                             int missed = 0 ;
00770                             bool exitFlag = false ;
00771                             bool clickFlag = false ;
00772                             int ms = -1 ;//holds  mouseclick status
00773                             int wrongclick = 0 ;
00774                             while( !exitFlag ){
00775                                     drawDot(d->getTimerValue(), br , cs ,colorVector);
00776                                     if (det - dst > dl ){
00777                                             cs = getNext(cs) ;
00778                                        // d->displaySDLSurfacePatch(surfVector[cs] , &offs , NULL , -2 , false ,true ) ;
00779                                             tst = d->getTimerValue() ;
00780                                             det=tst ;
00781                                             if(clickFlag){
00782                                                     missed++ ;
00783                                                     d->pushEvent("missed one change");
00784                                             }
00785                                             clickFlag=true ;
00786                                             dst = det ;
00787                                             dl = ilb+ random() % (iub-ilb);//we get a value for next stop
00788                                     }
00789                                     ms = myCheckForMouseClick() ;
00790                                     if(ms==2) exitFlag = true ;
00791                                     det = d->getTimerValue() ;
00792 
00793                                     if(clickFlag && ms==1){
00794                                             clickFlag = false ;
00795                                             tet = d->getTimerValue() ;
00796                                             reactionTimes.push_back(tet-tst);
00797                                             d->pushEvent("reaction time :" + stringify(tet-tst));
00798                                     }else{if(ms==1) wrongclick++ ;}
00799                             }
00800 
00801                             long et = d->getTimerValue();
00802                             d->pushEvent("manipulation ends") ;
00803                             d->pushEvent("maniupulation time : "+stringify(et-st)) ;allTiming.push_back(et-st);
00804                             d->clearScreen();
00805                             string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00806 
00807                             bool af = false ;
00808                             af = isAnswerCorrect(testString,answer,1);
00809                             d->pushEvent("subject keyed : "+answer);
00810                             d->pushEvent("avarage reaction time : "+ stringify(getAvarage(reactionTimes))) ;
00811                             d->pushEvent("number of missed events : "+stringify(missed));
00812                             d->pushEvent("number of caught events : "+stringify(reactionTimes.size())) ;
00813                             if(missed <= max_miss && getAvarage(reactionTimes)<= min_reaction_time && wrongclick <= max_wrong){
00814                                     cr++;
00815                                     d->pushEvent("valid trial");
00816                                     if(af){
00817                                             d->pushEvent("answer was correct");sssr++;correctAnswersTiming.push_back(et-st) ;
00818                                     }else{
00819                                             d->pushEvent("answer was incorrect");fssr++;
00820                                     }
00821                             }else{
00822                                         if(wrongclick > max_wrong) {
00823                                                 d->displayText("Trial failed, too many FALSE REPORT! Click to start over!");
00824                                                 d->waitForMouseClick();
00825                                         }
00826                                     if(missed > max_miss) {
00827                                             d->displayText("Trial failed, too many events missed! Click to start over!");
00828                                             d->waitForMouseClick();
00829                                     }
00830                                     if(getAvarage(reactionTimes) > min_reaction_time){
00831                                             d->displayText("Trial failed, reaction slower than limit! Click to start over!");
00832                                             d->waitForMouseClick();
00833                                     }
00834                                     if(af){
00835                                             d->pushEvent("answer was correct");ssfr++;
00836                                     }else{
00837                                             d->pushEvent("answer was incorrect");fsfr++;
00838                                     }
00839                                     d->pushEvent("invalid trial");
00840                             }
00841 
00842                     }else{
00843                             d->pushEvent("+++++++++++++++++++++++++++++++++++++++") ;
00844                             d->showCursor(true);
00845                             d->displayText("click one of the  mouse buttons to start!");
00846                             d->waitForMouseClick() ;
00847                             d->showCursor(false) ;
00848                             string testString ;
00849                             testString = getARandomString(stringSize, argMap["alphabet"] , meticThreshold);// digitMemorizationTask(stringSize, argMap["alphabet"] , wr , hr , onsetDel) ;
00850                             d->clearScreen() ;
00851                             d->displayFixationBlink();
00852                             d->displayText(testString,true,0) ;
00853                             d->waitFrames(onsetDel) ;
00854                             d->clearScreen() ;
00855                             if(argMap["mask"].compare("y")==0) showMask(mask_onset_frames,argMap["alphabet"]);
00856                             if(cue_wait_frames != 0) d->waitFrames(cue_wait_frames) ;
00857                             d->displayFixationBlink(d->getWidth()/2,d->getHeight()/2,1,3);
00858                             d->pushEvent("the memorization sequence is : "+testString) ;
00859 
00860                             d->pushEvent("subject is being challenged for simple momorization");
00861                             d->clearScreen();
00862 
00863                             string  answer = getDigitSequenceFromSubject(argMap["alphabet"] , testString.size());
00864 
00865                             bool af = false ;
00866                             af = isAnswerCorrect(testString,answer,0);
00867                             d->pushEvent("subject keyed : "+answer);
00868                             if(af){
00869                                     d->pushEvent("correct answer");
00870                                     sm++;
00871                             }else{
00872                                     d->pushEvent("incorrect answer");
00873                                     fm++ ;
00874                             }
00875 
00876                     }
00877             }
00878 
00879             d->pushEvent("number of successful memory tests :" + stringify(sm));
00880             d->pushEvent("number of failed memory tests :" + stringify(fm)) ;
00881             d->pushEvent("number of successful sorting and successful reaction trials :"+stringify(sssr));
00882             d->pushEvent("number of successful sorting and failed reaction trials :"+stringify(ssfr));
00883             d->pushEvent("number of failed sorting and successful reaction trials :"+stringify(fssr));
00884             d->pushEvent("number of failed sorting and failed reaction trials :"+stringify(fsfr));
00885             d->pushEvent("avarage time for respond :"+ stringify(getAvarage(allTiming)));
00886             d->pushEvent("variance of respond :"+ stringify(getVariance(allTiming)));
00887             d->pushEvent("avarage time for correct answers "+stringify(getAvarage(correctAnswersTiming))) ;
00888             d->pushEvent("variance of correct responds :"+ stringify(getVariance(correctAnswersTiming)));
00889             d->clearScreen();
00890             d->displayText("Experiment complete. Thank you!");
00891             d->waitForMouseClick();
00892 
00893         // stop all our ModelComponents
00894             manager.stop();
00895 
00896 
00897         // all done!
00898             return 0;
00899 }
00900 
00901 #endif // INVT_HAVE_LIBSDL_IMAGE
00902 
Generated on Sun May 8 08:40:10 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3