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