psycho-spatial-nback.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-spatial-nback.C Psychophysics test to measure the effect of executive tasks on spatial memory */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-spatial-orientation-2back.C $
00035 // $Id: psycho-spatial-memory.C 13040 2010-03-23 03:59:25Z nnoori $
00036 //
00037 
00038 #include "Component/ModelManager.H"
00039 #include "Image/Image.H"
00040 #include "Psycho/PsychoDisplay.H"
00041 #include "Psycho/EyeTrackerConfigurator.H"
00042 #include "Psycho/EyeTracker.H"
00043 #include "Psycho/PsychoOpts.H"
00044 #include "Component/EventLog.H"
00045 #include "Component/ComponentOpts.H"
00046 #include "Raster/Raster.H"
00047 #include "Util/MathFunctions.H"
00048 #include "Util/Types.H"
00049 #include "GameBoard/basic-graphics.H"
00050 #include <sys/types.h>
00051 #include <dirent.h>
00052 #include <errno.h>
00053 #include <vector>
00054 #include <string>
00055 #include <iostream>
00056 #include <SDL/SDL.h>
00057 #include <SDL/SDL_image.h>
00058 #include <SDL/SDL_mixer.h>
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <sstream>
00062 #include <time.h>
00063 #include "Image/DrawOps.H"
00064 #include "GameBoard/resize.h"
00065 #include <iostream>
00066 #include <fstream>
00067 #include <set>
00068 #include <algorithm>
00069 #include <ctime>
00070 
00071 #ifndef INVT_HAVE_LIBSDL_IMAGE
00072 #include <cstdio>
00073 int main()
00074 {
00075         fprintf(stderr, "The SDL_image library must be installed to use this program\n");
00076         return 1;
00077 }
00078 
00079 #else
00080 
00081 
00082 
00083 using namespace std;
00084 
00085 // ######################################################################
00086 
00087 ModelManager manager("Psycho-Spatial-nback");
00088 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00089 map<uint,uint> testMap ;
00090 map<string,string> argMap ;
00091 map<string,vector<SDL_Rect*>*> clipsmap;
00092 
00093 
00094 //////////////////////////////////////////////
00095 // a functionf for stringigying things
00096 //////////////////////////////////////////////
00097 template <class T> std::string stringify(T i)
00098 {
00099         ostringstream o ;
00100         o << i ;
00101         return o.str();
00102 }
00103 
00104 
00105 int pickOne(int l){
00106   int s = (l*l+l)/2;
00107   int pre_p = rand()%s +1;
00108   int p = 1;
00109   int ps = 0 ;
00110   for(int i=1;i<=l;i++){
00111     ps +=i;
00112     if(pre_p > ps) p=i+1;
00113   }
00114   return p-1;
00115 }
00116 
00117 
00118 double getAvarage(vector<long> v){
00119         double f = 0.0 ;
00120         for( uint i = 0 ; i <  v.size() ; i++ ){
00121                 f += v[i] ;
00122         }
00123         if (v.size()!=0) return f/v.size() ;
00124         return -1 ;
00125 }
00126 
00127 double getVariance(vector<long> v){
00128         double m = getAvarage(v);
00129         double var = 0.0 ;
00130         for( uint i = 0 ; i < v.size(); i++ ){
00131                 var += (v[i]-m)*(v[i]-m) ;
00132         }
00133         if (v.size()!=0) return var/v.size() ;
00134         return -1 ;
00135 }
00136 
00137 bool itIsInThere(int x , vector<int> bag){
00138         for( uint i=0 ; i < bag.size(); i++ ){
00139                 if(x == bag[i]) return true ;
00140         }
00141         return false ;
00142 }
00143 
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //// gets a string as the argument and returns a string composed of
00147 //// characters of the first string sorted in the ascending order
00148 ///////////////////////////////////////////////////////////////////
00149 string ascSort(string st)
00150 {
00151         string res = "" ;
00152         vector<string> v = vector<string>();
00153         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00154 
00155         std::sort(v.begin(), v.end());
00156 
00157         for ( uint i = 0 ; i < v.size() ; i++ ){
00158                 res += v[i] ;
00159         }
00160         return res;
00161 }
00162 
00163 
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //// gets a string as the argument and returns a string composed of
00167 //// characters of the first string sorted in the descending order
00168 ///////////////////////////////////////////////////////////////////
00169 string desSort(string st)
00170 {
00171         string res = "" ;
00172         vector<string> v = vector<string>();
00173         for(uint i = 0 ; i < st.size() ; i++) v.push_back(st.substr(i,1)) ;
00174         std::sort(v.begin(), v.end());
00175         std::reverse(v.begin(), v.end());
00176         for ( uint i = 0 ; i < v.size() ; i++ ){
00177                 res += v[i] ;
00178         }
00179         return res;
00180 }
00181 
00182 
00183 ////////////////////////////////////////////////////////
00184 ///// simply generates a sequence of characters out of master string
00185 ////////////////////////////////////////////////////////
00186 
00187 string getARandomString(uint l, string alphabet="0123456789" ){
00188 
00189         string test = string("") ;
00190         string retString ;
00191         test = "" ;
00192         string tp = string("") ;
00193         vector<int> pickedones = vector<int>() ;
00194         for(uint i = 0 ; i < l ; i++){
00195                         int nd;
00196             do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones)) ;
00197                         pickedones.push_back(nd);
00198                         tp = alphabet.substr(nd,1) ;
00199                         test += tp ;
00200         }
00201         retString = test ;
00202         return retString ;
00203 }
00204 
00205 
00206 
00207 ///////////////////////////////////////////////////////
00208 //this function is not called in this program, but it generates a random string and it will show it in
00209 //a random place on the screen.
00210 //////////////////////////////////////////////////////
00211 string digitMemorizationTask(uint l, string alphabet="0123456789" , int displayFrame = 10  ){
00212         d->clearScreen() ;
00213         vector<int> pickedones = vector<int>() ;
00214         string test = string("") ;
00215         string tp = string("") ;
00216         for(uint i = 0 ; i < l ; i++){
00217                 int nd;
00218                 do{ nd= rand()% alphabet.size() ; }while(itIsInThere(nd,pickedones) && pickedones.size() <= alphabet.size()) ;
00219                 pickedones.push_back(nd);
00220                 tp = alphabet.substr(nd,1) ;
00221                 test += tp ;
00222         }
00223         d->displayText(test,true,0) ;
00224         d->waitFrames(displayFrame) ;
00225         d->clearScreen() ;
00226         return test ;
00227 }
00228 
00229 
00230 ////////////////////////////////////////////////////////
00231 ///////this will change the order of elements in a vector to a random order
00232 ////////////////////////////////////////////////////////
00233 void scramble(vector<string>& v){
00234         vector<string> tv = vector<string>() ;
00235         while(v.size()>0){
00236                 tv.push_back(v[0]);
00237                 v.erase(v.begin());
00238         }
00239         int i = 0 ;
00240         while(tv.size()>0){
00241                 i = rand()%tv.size() ;
00242                 v.push_back(tv[i]);
00243                 tv.erase(tv.begin()+i);
00244         }
00245 }
00246 
00247 void scramble(vector<int>& v){
00248     vector<int> tv = vector<int>() ;
00249     while(v.size()>0){
00250         tv.push_back(v[0]);
00251         v.erase(v.begin());
00252     }
00253     int i = 0 ;
00254     while(tv.size()>0){
00255         i = rand()%tv.size() ;
00256         v.push_back(tv[i]);
00257         tv.erase(tv.begin()+i);
00258     }
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////
00262 ////This is our button factory
00263 ////////////////////////////////////////////////////////////////
00264 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){
00265         Image<PixRGB<byte> > textIm(d->getWidth(),d->getHeight(),ZEROS);
00266         textIm.clear(bgcolor);
00267         writeText(textIm, Point2D<int>((size.i - label.length()*10)/2,(size.j-20) /2),label.c_str(),txtcolor,bgcolor);
00268         SDL_Surface *surf = d->makeBlittableSurface(textIm , true);
00269         Uint32 bc = d->getUint32color(bordercolor);
00270         drawRectangle(surf,bc,0,0,size.i -1,size.j -1 ,border);
00271         SDL_Surface* blank =getABlankSurface(size.i , size.j);
00272         SDL_Rect clip;
00273         clip.x = 0 ;
00274         clip.y = 0 ;
00275         clip.w = size.i ;
00276         clip.h = size.j ;
00277         apply_surface(0,0,*surf,*blank,clip);
00278         dumpSurface(surf) ;
00279         return blank ;
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////////
00283 ////This is the function for creating the keypad, in fact it generates
00284 ////12 buttons and associates the actions to the region for each button
00285 ////////////////////////////////////////////////////////////////////////
00286 
00287 SDL_Surface* getKeyPad(string alphabet,map<string , SDL_Rect>& buttmap){
00288         SDL_Surface* pad= getABlankSurface(d->getWidth()/4,d->getHeight()/3);
00289         SDL_Rect clip;
00290         clip.x=0;
00291         clip.y=0;
00292         int numofrows = alphabet.size()/3 +1;
00293         if(alphabet.size()%3 != 0 ) numofrows++ ;
00294         int numofcolumns = 3 ;
00295         clip.w= pad->w / numofcolumns ;
00296         clip.h = pad->h / numofrows ;
00297 
00298   //keys for 1 to 9
00299         for( int i = 0 ; i < numofrows*3 ; i++){
00300                 SDL_Surface* but ;
00301                 if((uint)i < alphabet.size()){
00302                         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);
00303                 }else{
00304                         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);
00305                 }
00306 
00307                 SDL_Rect cl ;
00308                 cl.x = ((i)%numofcolumns)*(pad->w)/numofcolumns ; cl.y= ((i)/numofcolumns)*((pad->h)/numofrows) ;
00309                 cl.w = clip.w ;
00310                 cl.h = clip.h ;
00311                 apply_surface( cl.x , cl.y ,*but,*pad,clip);
00312                 if((uint)i < alphabet.size()) buttmap[alphabet.substr(i,1)] = cl ;
00313                 dumpSurface(but);
00314         }
00315         SDL_Rect cl1 ;
00316         cl1.x = 0 ; cl1.y= (numofrows-1)*((pad->h)/numofrows) ;
00317         cl1.w = clip.w ;
00318         cl1.h = clip.h ;
00319         buttmap["!"] = cl1 ;
00320         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);
00321         apply_surface(0, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00322         dumpSurface(but);
00323         SDL_Rect cl2 ;
00324         cl2.x = (pad->w)/numofcolumns ; cl2.y= (numofrows-1)*((pad->h)/numofrows) ;
00325         cl2.w = clip.w ;
00326         cl2.h = clip.h ;
00327         buttmap[" "] = cl2 ;
00328         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);
00329         apply_surface((pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00330         dumpSurface(but);
00331         SDL_Rect cl3 ;
00332         cl3.x = 2*(pad->w)/numofcolumns ; cl3.y= (numofrows-1)*((pad->h)/numofrows) ;
00333         cl3.w = clip.w ;
00334         cl3.h = clip.h ;
00335         buttmap["*"] = cl3 ;
00336         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);
00337         apply_surface(2*(pad->w)/numofcolumns, (numofrows-1)*((pad->h)/numofrows),*but,*pad,clip);
00338         dumpSurface(but);
00339         return pad ;
00340 }
00341 
00342 
00343 
00344 
00345 ///////////////////////////////////////////////////////////////////////////
00346 /////this function listens to mouse clicks and then finds the region of the screen
00347 /////associated with the action, buttmap is the map of the region, offset is the offset of
00348 /////buttons
00349 ///////////////////////////////////////////////////////////////////////////
00350 string getPressedButtonCommand(map<string , SDL_Rect>& buttmap,Point2D<int> offset=Point2D<int>(0,0)){
00351         int quit = 0 ;
00352         string s ;
00353         SDL_Event event ;
00354         while( quit!=2 ){
00355                 while( SDL_PollEvent( &event ) ) {
00356                         if(event.type == SDL_MOUSEBUTTONDOWN  && event.button.button == SDL_BUTTON_LEFT ){
00357                                 for( map<string , SDL_Rect>::iterator it = buttmap.begin() ; it!=buttmap.end() ; ++it){
00358                                         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) {
00359                                                 quit = 2 ;
00360                                                 s = it->first ;
00361                                                 break;
00362                                         }
00363 
00364                                 }
00365                         }
00366 
00367                 }
00368         }
00369         return s ;
00370 
00371 }
00372 
00373 
00374 ////////////////////////////////////////////////////
00375 ////This function creates a virtual keypad, creates a map of buttons
00376 ////and their representation area and listens to the button press and at
00377 ////the end returns the keyed digits
00378 ////////////////////////////////////////////////////
00379 string getDigitSequenceFromSubject(string alphabet="0123456789" , uint maxl = 7 , string message=""){
00380         d->showCursor(true) ;
00381         //let's creat a map to map actions to regions of the screen, each region is represented as an SDL_Rect
00382         map<string , SDL_Rect>* buttmap = new map<string , SDL_Rect>();
00383         //now let's get the keypad surface while we get the actions map to regions
00384         SDL_Surface * keypad = getKeyPad(alphabet,*buttmap);
00385         //this will be the offset of displaying the keypad on the screen
00386         SDL_Rect offset ;
00387         offset.x = (d->getWidth() - keypad->w) /2;
00388         offset.y = (d-> getHeight() - keypad->h) /2;
00389         //d->displayText(message, Point2D<int>(d->getWidth()/3,d->getHeight()*2 /16) , PixRGB<byte>(0,0,0) ,PixRGB<byte>(127,127,127)) ;
00390         SDL_Surface* msgp = getButtonImage(message ,PixRGB<byte>(195,60,12) ,PixRGB<byte>(127,127,127) ,Point2D<int>(d->getWidth()/6,d->getHeight() /15) ,PixRGB<byte>(127,127,127) , 4) ;
00391         SDL_Rect msgoffs ; msgoffs.x = (d->getWidth() - msgp->w) /2 ; msgoffs.y = 2*d->getHeight()/9 ;
00392         d->displaySDLSurfacePatch(msgp , &msgoffs , NULL , -2 , false ,true ) ;
00393         dumpSurface(msgp) ;
00394         //now let's display the keypad
00395         d->displaySDLSurfacePatch(keypad , &offset,NULL , -2,false, true);
00396         //this will hold the final string keyed be the subject
00397         string p = string("") ;
00398         //this is a temporary string holding the last action related to the pressed key
00399         string tp = string("");
00400         //now let's record subject's key press
00401         while( tp.compare("*")!=0 ){
00402                 //this button is actually the display for the current string
00403                 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) ;
00404                 SDL_Rect offs ; offs.x = (d->getWidth() - dp->w) /2 ; offs.y = d->getHeight()/6 ;
00405                 d->displaySDLSurfacePatch(dp , &offs , NULL , -2 , false ,true ) ;
00406                 //now let's listen to button events
00407                 tp = getPressedButtonCommand(*buttmap,Point2D<int>(offset.x,offset.y)) ;
00408                 dumpSurface(dp) ;
00409                 if(tp.compare("!")==0 && p.size()>=0 ) {
00410                         if (p.size()>0) p = p.substr(0,p.size()-1) ;
00411                 }else{
00412                         if(p.size() < maxl && tp.compare("*")!=0) {
00413                                 p +=tp ;
00414                         }
00415 
00416                 }
00417 
00418         }
00419         
00420         buttmap = 0 ;
00421         dumpSurface(keypad) ;
00422         d->clearScreen() ;
00423         return p ;
00424 
00425 }
00426 
00427 
00428 
00429 ///////////////////////////////////////////////////////////////
00430 //////gets the test string, answer and the mode and identifies if
00431 //////the answer matches the thing it should be, mode=0 checks if
00432 //////if the answer and test string simply the same, mode=1 matches
00433 //////the answer against the ascending sorted string of the test string
00434 //////mode=2 compares the answer against the descending sorted of
00435 //////the test string
00436 ///////////////////////////////////////////////////////////////
00437 bool isAnswerCorrect(string test , string answer , int mode){
00438 
00439         if(mode == 0 && answer.compare(test)==0) return true ;
00440 
00441         if(mode == 1 && answer.compare(ascSort(test))==0) return true ;
00442 
00443         if(mode == 2 && answer.compare(desSort(test))==0) return true ;
00444 
00445         return false;
00446 }
00447 
00448 
00449 
00450 int addArgument(const string st,const string delim="="){
00451         int i = st.find(delim) ;
00452         argMap[st.substr(0,i)] = st.substr(i+1);
00453 
00454         return 0 ;
00455 }
00456 
00457 std::string getArgumentValue(string arg){
00458         return argMap[arg] ;
00459 }
00460 
00461 
00462 vector<int> spatial_memory_task(int onsetTime, int isd ,int rad=100 ,  int ma=45 ,int Ma=90){
00463 
00464     int w = d->getWidth();
00465     int h = d->getHeight();
00466     int a1 = rand() % 360 ;
00467     int direction = (int)(((rand()%2)-0.5)/0.5);
00468     int a2 =a1 +direction*((rand() % (Ma-ma))+ma);
00469     //d->displayFixation();
00470     d->displayRedDotFixation(w/2+rad*cos(a1*3.1415/180),h/2 + rad*sin(a1*3.1415/180));
00471     d->waitFrames(onsetTime);
00472     d->clearScreen();
00473     //d->displayFixation();
00474     d->waitFrames(isd);
00475     d->displayRedDotFixation(w/2+rad*cos(a2*3.1415/180),h/2 + rad*sin(a2*3.1415/180));
00476     d->waitFrames(onsetTime);
00477     d->clearScreen();
00478     vector<int> angles;
00479     angles.push_back(a1);
00480     angles.push_back(a2);
00481     return angles ;
00482 }
00483 
00484 vector<int> getA2NonRepeatingSeqence(int numOfElements , int lenght){
00485   vector<int> sequence;
00486   //let's first push two elements in the sequence
00487   sequence.push_back(rand()%numOfElements);
00488   sequence.push_back(rand()%numOfElements);
00489   for(int i = 2 ; i < lenght ; i++){
00490     int r = rand()%(numOfElements) ;
00491     if(r== sequence[i-2]) r = (r+1)%numOfElements;
00492     sequence.push_back(r);
00493   }
00494   
00495   return sequence;
00496 }
00497 
00498 vector<int> getA2RepeatingSequence(int numOfElements , int length){
00499   vector<int> nonrepeatingsequence = getA2NonRepeatingSeqence(numOfElements,length);
00500   int repeatPlace = 2+ pickOne(length-2);
00501   nonrepeatingsequence[repeatPlace] = nonrepeatingsequence[repeatPlace-2];
00502   return nonrepeatingsequence;
00503 }
00504 
00505 
00506 
00507 vector<int> getA1NonRepeatingSeqence(int numOfElements , int lenght){
00508   vector<int> sequence;
00509   //let's first push one elements in the sequence
00510   sequence.push_back(rand()%numOfElements);
00511  // sequence.push_back(rand()%numOfElements);
00512   for(int i = 1 ; i < lenght ; i++){
00513     int r = rand()%(numOfElements) ;
00514     if(r== sequence[i-1]) r = (r+1)%numOfElements;
00515     sequence.push_back(r);
00516   }
00517   
00518   return sequence;
00519 }
00520 
00521 vector<int> getA1RepeatingSequence(int numOfElements , int length){
00522   vector<int> nonrepeatingsequence = getA1NonRepeatingSeqence(numOfElements,length);
00523   int repeatPlace = 1+ pickOne(length-1);
00524   nonrepeatingsequence[repeatPlace] = nonrepeatingsequence[repeatPlace-1];
00525   return nonrepeatingsequence;
00526 }
00527 
00528 
00529 vector<int> getNonRepeatingSeqenceForPassiveTest(int numOfElements , int lenght){
00530   vector<int> sequence;
00531   //let's first push two elements in the sequence
00532   for(int i = 0 ; i < lenght ; i++){
00533     int r = rand()%(numOfElements-1) +1 ;
00534     sequence.push_back(r);
00535   } 
00536   return sequence;
00537 }
00538 
00539 vector<int> getRepeatingSeqenceForPassiveTest(int numOfElements , int lenght){
00540   vector<int> sequence = getNonRepeatingSeqenceForPassiveTest(numOfElements,lenght);
00541   int p = pickOne(lenght);
00542   sequence[p] = 0 ;
00543   return sequence;
00544 }
00545 /*
00546 int spatial_memory_retrival(vector<int> dotsVector,int dir ,int ma=30 , int Ma=120 ,int ds=30 ){
00547     
00548     int w = d->getWidth();
00549     int h = d->getHeight();
00550     int change = rand()%2;
00551     int neg = dotsVector.at(0); int pos = dotsVector.at(1);
00552     switch( change ){
00553         case 0 : d->pushEvent("same target");break;
00554         case 1 : d->pushEvent("target changed");break;
00555     }
00556     if(change == 1){
00557         int chDir = rand()%2;
00558         int c=0;
00559         if(chDir==0){
00560             c =((rand()%2 -0.5)/0.5 );
00561             if( neg+ ds > Ma ) c = -1 ;
00562             if(neg -ds < ma ) c=+1 ;
00563             neg = neg + c*ds ;
00564         }
00565         if(chDir==1){
00566             c =((rand()%2 -0.5)/0.5 );
00567             if( pos+ ds > Ma ) c = -1 ;
00568             if(pos -ds < ma ) c=+1 ;
00569             pos = pos + c*ds ;
00570         }
00571     }
00572     
00573     d->pushEvent("for retrieval dots showed at negative side :"+ stringify(neg)+" positive side:" + stringify(pos));
00574     if(dir == 0){
00575         d->displayRedDotFixation(w/2+pos,h/2);
00576         d->displayRedDotFixation(w/2-neg,h/2);
00577     }
00578     if(dir == 1){
00579         d->displayRedDotFixation(w/2,h/2+pos);
00580         d->displayRedDotFixation(w/2,h/2-neg);
00581     }
00582     d->waitFrames(30);
00583     d->clearScreen();
00584     string ans = getDigitSequenceFromSubject("yn-",1,"same dots?");
00585     int res = 0 ;
00586     if(change==0 && ans.compare("y")==0) res=1;
00587     if(change==1 && ans.compare("n")==0) res=1;
00588     return res ;
00589 }
00590 */
00591 int playTone(Mix_Music* tone ){
00592 if(Mix_PlayMusic(tone,0)==-1){return -1;}
00593                 while(Mix_PlayingMusic()==1){} ;
00594 return 0 ;
00595 }
00596 
00597 
00598 
00599 
00600 int spatial_memory_retrival(vector<int> angles ,int rad = 100 ){
00601         int res=0 ;
00602         int flip = rand()%2;
00603         int w = d->getWidth();
00604         int h = d->getHeight();
00605         if(flip==0){
00606                 d->displayRedDotFixation(w/2+rad*cos(angles.at(0)*3.1415/180),h/2 + rad*sin(angles.at(0)*3.1415/180));
00607                 d->displayRedDotFixation(w/2+rad*cos(angles.at(1)*3.1415/180),h/2 + rad*sin(angles.at(1)*3.1415/180));
00608         }else{
00609                 int a1=angles.at(0) % 360;
00610                 int a2=angles.at(1) % 360;
00611                 if (a2<a1) {
00612                         int tmp = a2 ;
00613                         a2=a1;
00614                         a1=tmp;
00615                 }
00616                 int sflip=rand()%2;
00617                 int del = ((rand()%15) + 30);
00618                 if(sflip==0){
00619                         a1=a1-del;
00620                 }else{
00621                         a2=a2+del;
00622                 }
00623                 d->displayRedDotFixation(w/2+rad*cos(a1*3.1415/180),h/2 + rad*sin(a1*3.1415/180));
00624                 d->displayRedDotFixation(w/2+rad*cos(a2*3.1415/180),h/2 + rad*sin(a2*3.1415/180));
00625         }
00626         d->waitFrames(20);
00627         d->clearScreen();
00628         string ans = getDigitSequenceFromSubject("yn",1,"same dots?");
00629         if(flip==0){
00630                 res = 0 ;
00631                 if(ans.compare("y")==0) res=1;
00632         }else{
00633                 res = 0 ;
00634                 if(ans.compare("n")==0) res=1;
00635         }
00636         return res ;
00637 }
00638 
00639 std::string getUsageComment(){
00640 
00641         string com = string("\nlist of arguments : \n");
00642 
00643         com += "\nlogfile=[logfilename.psy] {default = psycho-sm-or.psy}\n" ;
00644         com += "\nmemo=[a_string_without_white_space]\n";
00645         com += "\nstring-size=[>0](the size of counter string){default=4} \n";
00646         com += "\nsubject=[subject_name] \n" ;
00647         com += "\nnum-of-trials=[>1] (number of trials ) {default=10}\n";
00648         com += "\nalphabet=[a string of characters](a string of characters){default=abcdefghijklmnopqrstuvwxyz}\n";
00649         com += "\nmode=[1,2,3](1 for spatial memory task 2 for single counter task, 2 for concurrent task){default=1}\n";
00650         com += "\nsingle-dot-onset=[>1](number of frames that the single dot should be presented){default=16}\n";
00651         com += "\ndots_ISI=[>1](number of frames between dots presentations){default=16}\n";
00652         com += "\ndots-radius=[>1](the radius for circle of dots in pixel){default=100}\n";
00653         com += "\ndots-min-radius=[>0](minimum distance of dots from center){default=32}\n";
00654         com += "\ndots-max-radius=[>0] (maximum distance of dots from center){default=158}\n";
00655         com += "\nspatial-delay=[>0](number of frames for spatial memory task ){default=180}\n";
00656         com += "\n spatial-counter-ISI=[>1](numer of frames between last dot presentation and start of counter task){default=16}\n";
00657         com += "\n counter-length=[>1](total lenght of counter experiment in frames){default=300}\n";
00658         com += "\n counter-spatial-query-ISI=[>1](the delay between end of counter trail and start of spatial memory query in number of frames){default=16}\n";
00659         com += "\n spatial-query-length=[>1](the total length for showing the spatial memory test in number of frames){default=60}\n";
00660         com += "\n spatial-query-counter-query-ISI=[>1](number of frames between the unspeeded spatial memory query and showing the counter query){default=30}\n";
00661         com += "\n counter-query-length=[>1](number of frames for presenting the counter query){default=60}\n";
00662         com += "\n cue-onset-frames=[>1](){default=3}\n";;
00663         com += "\nsound-dir=[path to wav files directory]{default=..}\n";
00664         com += "\ntone1=[a valid file name](name of wav file without extension for tone 1){default=sin}\n";
00665         com += "\ntone2=[a valid file name](name of wav file without extension for tone 2){default=square}\n";
00666         com += "\ndot-shift=[>1](amount of shift in dots position in pixel)[default=16]\n";
00667         com +="\n2back-isi=[>1](inter stimuli interval between two items of 2 back test){default=30}\n";
00668         return com ;
00669 }
00670 
00671 extern "C" int main(const int argc, char** argv)
00672 {
00673 
00674         MYLOGVERB = LOG_INFO;  // suppress debug messages
00675         //let's push the initial value for the parameters
00676         argMap["experiment"]="spatial-memory-test";
00677         argMap["logfile"]="psycho-sm.psy" ;
00678         argMap["string-size"]="5" ;
00679         argMap["num-of-trials"]="2";
00680         argMap["subject"]="" ;
00681         argMap["memo"]="" ;
00682         argMap["single-dot-onset"]="16" ;
00683         argMap["dots-ISI"]="16";
00684         argMap["dots_radius"]="100";
00685         argMap["spatial-delay"]="180";
00686         argMap["spatial-counter-ISI"]="16";
00687         argMap["counter-length"]="300";
00688         argMap["counter-spatial-query-ISI"]="16";
00689         argMap["spatial-query-length"]="60";
00690         argMap["spatial-query-counter-query-ISI"]="30";
00691         argMap["counter-query-length"]="60";
00692         argMap["alphabet"]="djs";
00693         argMap["mode"]="0" ;
00694         argMap["cue-onset-frames"] = "3" ;
00695         argMap["sound-dir"]="..";
00696         argMap["tone1"]="sine";
00697         argMap["tone2"]="square";
00698         argMap["cue-file"]="cue1";
00699         argMap["min-tone-wait"]="50";
00700         argMap["max-tone-wait"]="80";
00701         argMap["dots_min_angle"]="45";
00702         argMap["dots_max_angle"]="90";
00703         argMap["dot-shift"] = "32";
00704         argMap["backtask-length"]="7";
00705         argMap["2back-isi"]="30";
00706         manager.addSubComponent(d);
00707         nub::soft_ref<EventLog> el(new EventLog(manager));
00708         manager.addSubComponent(el);
00709         d->setEventLog(el);
00710        
00711 
00712         if (manager.parseCommandLine(argc, argv,
00713             "at least one argument needed", 1, -1)==false){
00714                     cout<<getUsageComment()<<endl;
00715                     return(1);
00716             }
00717 
00718             for(uint i = 0 ; i < manager.numExtraArgs() ; i++){
00719                     addArgument(manager.getExtraArg(i),std::string("=")) ;
00720             }
00721 
00722             manager.setOptionValString(&OPT_EventLogFileName, argMap["logfile"]);
00723 
00724   // let's get all our ModelComponent instances started:
00725             manager.start();
00726             for(map<string,string>::iterator it= argMap.begin(); it!= argMap.end() ; ++it) d->pushEvent("arg:"+ it->first+" value:"+it->second ) ;
00727   // let's display an ISCAN calibration grid:
00728             d->clearScreen();
00729             d->displayISCANcalib();
00730             d->waitForMouseClick();
00731             d->displayText("Here the experiment starts! click to start!");
00732             d->waitForMouseClick();
00733             d->clearScreen();
00734         //let's see in what mode the user like to run the program
00735             //int mode = atoi(argMap["mode"].c_str());
00736             string masterString=argMap["alphabet"];
00737             
00738             int mode = atoi(argMap["mode"].c_str());
00739             int numOfTests = atoi(argMap["num-of-trials"].c_str()) ;
00740 
00741             int dots_ISI = atoi(argMap["dots-ISI"].c_str()) ;
00742             int dot_onset = atoi(argMap["single-dot-onset"].c_str());
00743             int dots_radius = atoi(argMap["dots_radius"].c_str());
00744             int dots_min_angle = atoi(argMap["dots_min_angle"].c_str());
00745             int dots_max_angle = atoi(argMap["dots_max_angle"].c_str());
00746           //  int delayForSorting = atoi(argMap["sorting-delay"].c_str());
00747             int numOfBackTaskElements = masterString.size();
00748             int lengthOfBackTask = atoi(argMap["backtask-length"].c_str());
00749            // int dot_max_change = atoi(argMap["dot-shift"].c_str());
00750             int two_back_isi = atoi(argMap["2back-isi"].c_str());
00751           vector<int> orientation_task_Vector;
00752           for( int i = 0 ; i< numOfTests ; i++ ){
00753               orientation_task_Vector.push_back(0);
00754               orientation_task_Vector.push_back(1);
00755           }
00756        
00757           scramble(orientation_task_Vector);
00758             //let's do calibration        
00759            
00760             
00761             d->clearScreen();
00762             
00763             cout<< stringify(d->getWidth())<<" x "<<stringify(d->getHeight())<<endl;
00764            // Mix_Music* cueMusic = NULL;//this is the cue for the start of trial 
00765             Mix_Music* tone1 = NULL;//tone 1
00766             Mix_Music* tone2 = NULL;//tone 2
00767             map<int,Mix_Music*>  audio_map ;//we will have access to the audios for stimulus presentation using this map
00768             map<string,int>  charmap ;
00769             map<int,string>  charinvmap ;
00770             //now let's open the audio channel
00771             if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ){
00772                   LINFO( "did not open the mix-audio") ;
00773                   return -1 ;
00774             }
00775             //now that everyting is ok, let's load the main string audio files and push them in a map
00776             for(uint i = 0; i < masterString.size() ; i++){
00777                 string str = argMap["sound-dir"]+"/"+masterString.substr(i,1)+".wav";
00778                 audio_map[i]=Mix_LoadMUS(str.c_str());
00779                 charmap[masterString.substr(i,1)]=i;
00780                 charinvmap[i]=masterString.substr(i,1) ;
00781             }
00782 
00783             for( uint i=10;i<100 ;i++ ){
00784                 charmap[stringify(i)]=i;
00785                 charinvmap[i]=stringify(i);
00786             }
00787             
00788             
00789             string tmpstr = argMap["sound-dir"]+"/"+argMap["tone1"]+".wav";
00790             tone1 = Mix_LoadMUS(tmpstr.c_str());
00791             tmpstr = argMap["sound-dir"]+"/"+argMap["tone2"]+".wav";
00792             tone2 = Mix_LoadMUS(tmpstr.c_str());
00793             
00794             int cr = numOfTests ;//this is the counter for number of rounds
00795             d->showCursor(true);
00796             d->displayText("click one of the  mouse buttons to start!");
00797             d->waitForMouseClick() ;
00798             d->showCursor(false);
00799            
00800     map<int,int> correctSPMMap;correctSPMMap[0]=0;correctSPMMap[1]=0;correctSPMMap[2]=0;correctSPMMap[3]=0;
00801     map<int,int> incorrectSPMMap;incorrectSPMMap[0]=0;incorrectSPMMap[1]=0;incorrectSPMMap[2]=0;incorrectSPMMap[3]=0;
00802         cr=0;
00803     while( cr < 2*numOfTests ){
00804 d->pushEvent("**************************************") ;
00805         int flp = rand()%2;
00806         //twoBackTaskType = 0  is reserved for non-repeating 2back task twoBackTaskType = 1 is for repeating one
00807         int twoBackTaskType = 0 ; 
00808         if(flp == 0) twoBackTaskType = 1;
00809         
00810         switch(twoBackTaskType){
00811           case 0 : d->pushEvent("non-repeating string");break;
00812           case 1 : d->pushEvent("repeating string");break;
00813         }
00814         
00815         vector<int> backTaskSequence;
00816         if(mode == 2){
00817           switch(twoBackTaskType){
00818             case 0 : backTaskSequence = getA2NonRepeatingSeqence(numOfBackTaskElements,lengthOfBackTask);break;
00819             case 1 : backTaskSequence = getA2RepeatingSequence(numOfBackTaskElements,lengthOfBackTask);break; 
00820           }
00821         }
00822         if(mode==0){
00823           switch(twoBackTaskType){
00824             case 0 : backTaskSequence = getNonRepeatingSeqenceForPassiveTest(numOfBackTaskElements,lengthOfBackTask);break;
00825             case 1 : backTaskSequence = getRepeatingSeqenceForPassiveTest(numOfBackTaskElements,lengthOfBackTask);break; 
00826           }
00827         }
00828         if(mode==1){
00829           switch(twoBackTaskType){
00830             case 0 : backTaskSequence = getA1NonRepeatingSeqence(numOfBackTaskElements,lengthOfBackTask);break;
00831             case 1 : backTaskSequence = getA1RepeatingSequence(numOfBackTaskElements,lengthOfBackTask);break; 
00832           }
00833         }
00834         
00835         d->showCursor(false);
00836         d->clearScreen() ;
00837         d->clearScreen() ;
00838         d->displayFixationBlink();
00839         
00840         d->pushEvent("trial number: "+ stringify(cr));
00841         d->pushEvent("verbal task type : " + stringify(twoBackTaskType));
00842         string seq = "";
00843          for( int i = 0 ;  i < lengthOfBackTask ; i++ ){
00844             seq += stringify(backTaskSequence[i]) ;
00845         }
00846         d->pushEvent("verbal task sequence: "+seq);
00847         d->waitFrames(30);
00848         d->displayFixation();
00849         d->waitFrames(10);
00850         d->clearScreen() ;
00851          playTone(tone1);
00852                 vector<int> angles = spatial_memory_task(dot_onset,dots_ISI,dots_radius,dots_min_angle,dots_max_angle);
00853         d->pushEvent("dots showed at these angles :"+ stringify(angles.at(0))+" and " + stringify(angles.at(1)));
00854         
00855         d->displayFixation();
00856         d->waitFrames(15);
00857         
00858         //let's play the items of 2backtask
00859         for( int i = 0 ;  i < lengthOfBackTask ; i++ ){
00860             playTone(audio_map[backTaskSequence[i]]);
00861             d->waitFrames(two_back_isi);
00862         }
00863         int currentTask=mode;
00864    
00865         if(currentTask==0){
00866             d->pushEvent("task condition: engage");
00867             
00868         }else{
00869           d->pushEvent("task condition: igore");
00870         }
00871         //d->waitFrames(delayForSorting);
00872         playTone(tone2);
00873         d->waitFrames(30);
00874         
00875         int spMemAns = spatial_memory_retrival(angles,dots_radius);
00876         switch( spMemAns ){
00877             case 0: incorrectSPMMap[orientation_task_Vector.at(cr)]= incorrectSPMMap[orientation_task_Vector.at(cr)]+1;d->pushEvent("incorrect spatial memory answer");break;
00878             case 1: correctSPMMap[orientation_task_Vector.at(cr)]= correctSPMMap[orientation_task_Vector.at(cr)]+1;d->pushEvent("correct spatial memory answer");break;
00879         }
00880         
00881         string ans1 = getDigitSequenceFromSubject("yn",1,"repeated?");
00882         d->pushEvent("string answer to repeated question: "+ans1);
00883         
00884             if((ans1.compare("y")==0 && twoBackTaskType== 1) || (ans1.compare("n")==0 && twoBackTaskType==0) ){
00885                 d->pushEvent("correct verbal task :)");
00886                 d->displayText(":)");
00887                 d->waitFrames(15);
00888             }else{
00889                 d->pushEvent("incorrect verbal task :(");
00890                 d->displayText(":(");
00891                 d->waitFrames(15);
00892             }
00893         
00894         
00895         cr++;
00896         }
00897         
00898             d->pushEvent("horizontal, memory correct:"+stringify(correctSPMMap[0]));
00899             d->pushEvent("vertical, memory correct:"+stringify(correctSPMMap[1]));
00900             d->pushEvent("horizontal, memory incorrect:"+stringify(incorrectSPMMap[0]));
00901             d->pushEvent("vertical, memory incorrect:"+stringify(incorrectSPMMap[1]));
00902             
00903             d->displayText("Experiment complete. Thank you!");
00904             d->waitForMouseClick();
00905 
00906           // stop all our ModelComponents
00907             manager.stop();
00908 
00909 
00910           // all done!
00911             return 0;
00912 }
00913 
00914 #endif // INVT_HAVE_LIBSDL_IMAGE
00915 
Generated on Sun May 8 08:04:13 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3