00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 #ifndef STIM_MAKER_C_DEFINED
00040 #define STIM_MAKER_C_DEFINED
00041 
00042 #include "Psycho/StimMaker.H"
00043 
00044 StimMaker::StimMaker(const unsigned short ImageSizeX,
00045                      const unsigned short ImageSizeY,
00046                      const unsigned short frameCount,
00047                      const char bgColor)
00048 {
00049   itsFrameCount = frameCount;
00050   itsSizeX      = ImageSizeX;
00051   itsSizeY      = ImageSizeY;
00052   itsSlowRate   = SM_SLOW_RATE;
00053   itsFastRate   = SM_FAST_RATE;
00054   itsStopRate   = SM_STOP_RATE;
00055   itsRandomSeed = 0;
00056 
00057   itsBlack.set(0.0F,0.0F,0.0F);
00058   itsColorVec.resize(SM_COLORS,itsBlack);
00059 
00060   itsRed.set(255.0F,0.0F,0.0F);
00061   itsOrange.set(255.0F,128.0F,0.0F);
00062   itsYellow.set(255.0F,255.0F,0.0F);
00063   itsGreen.set(0.0F,255.0F,0.0F);
00064   itsBlue.set(0.0F,0.0F,255.0F);
00065   itsPurple.set(255.0F,0.0F,255.0F);
00066   itsWhite.set(255.0F,255.0F,255.0F);
00067 
00068   itsColorVec[0] = itsRed;
00069   itsColorVec[1] = itsOrange;
00070   itsColorVec[2] = itsYellow;
00071   itsColorVec[3] = itsGreen;
00072   itsColorVec[4] = itsBlue;
00073   itsColorVec[5] = itsPurple;
00074   itsColorVec[6] = itsWhite;
00075 
00076   itsGTtargetColor.set(255.0F,255.0F,255.0F);
00077   itsGTtargetColorPatch1.set(0.0F,128.0F,128.0F);
00078   itsGTtargetColorPatch2.set(0.0F,0.0F,255.0F);
00079   itsGTtargetColorPatch1off.set(128.0F,128.0F,0.0F);
00080   itsGTtargetColorPatch2off.set(255.0F,0.0F,0.0F);
00081   itsGTdistColor.set(128.0F,128.0F,128.0F);
00082 
00083   SM_init(bgColor);
00084 }
00085 
00086 
00087 
00088 StimMaker::~StimMaker()
00089 {}
00090 
00091 
00092 
00093 
00094 void StimMaker::SM_init(const char bgColor)
00095 {
00096   Image<PixRGB<float> > baseImage;
00097   baseImage.resize(itsSizeX,itsSizeY);
00098   itsFrames.resize(itsFrameCount, baseImage);
00099   std::vector<Image<PixRGB<float> > >::iterator framesIter = itsFrames.begin();
00100   while(framesIter != itsFrames.end())
00101   {
00102     Image<PixRGB<float> >::iterator imgIter = framesIter->beginw();
00103     while(imgIter != framesIter->endw())
00104     {
00105       *imgIter = itsColorVec[itsBGcolor+1];
00106       ++imgIter;
00107     }
00108     ++framesIter;
00109   }
00110 
00111   itsGroundTruth.resize(itsFrameCount, baseImage);
00112   framesIter = itsGroundTruth.begin();
00113   while(framesIter != itsGroundTruth.end())
00114   {
00115     Image<PixRGB<float> >::iterator imgIter = framesIter->beginw();
00116     while(imgIter != framesIter->endw())
00117     {
00118       *imgIter = itsBlack;
00119       ++imgIter;
00120     }
00121     ++framesIter;
00122   }
00123   SM_setStandardBackGround(bgColor);
00124 
00125 }
00126 
00127 
00128 
00129 
00130 void StimMaker::SM_setStandardBackGround(const unsigned char bgColor)
00131 {
00132   itsBGcolor         = bgColor;
00133   itsCustomBG        = itsColorVec[itsBGcolor];
00134   itsUseCustomColors = false;
00135 }
00136 
00137 
00138 
00139 void StimMaker::SM_overRideRates(const unsigned char slowRate,
00140                                  const unsigned char fastRate,
00141                                  const unsigned char stopRate)
00142 {
00143   itsSlowRate = slowRate;
00144   itsFastRate = fastRate;
00145   itsStopRate = stopRate;
00146 }
00147 
00148 
00149 
00150 void StimMaker::SM_setCustomColors(const PixRGB<float> BGcolor,
00151                                    const PixRGB<float> TargetColor,
00152                                    const PixRGB<float> DistColor)
00153 {
00154   itsCustomBG        = BGcolor;
00155   itsCustomTarg      = TargetColor;
00156   itsCustomDist      = DistColor;
00157   itsUseCustomColors = true;
00158 }
00159 
00160 
00161 inline ushort StimMaker::SM_speedUpCheck(ushort currBlinkRate,
00162                                          const ushort frame,
00163                                          const ushort changeFrame,
00164                                          const unsigned char stimRate,
00165                                          const unsigned char useSmoothRateChange) const
00166 {
00167   if(frame > changeFrame)
00168   {
00169     
00170     if(stimRate == SM_SLOW_STIM)
00171     {
00172       if(currBlinkRate > itsFastRate)
00173       {
00174         if(useSmoothRateChange == SM_USE_SMOOTH_RATE_CHANGE)
00175           currBlinkRate -= SM_SMOOTH_ACCEL;
00176         else
00177           currBlinkRate = itsFastRate;
00178       }
00179       else
00180         if(currBlinkRate < itsFastRate)
00181           currBlinkRate = itsFastRate;
00182     }
00183     
00184     else if(stimRate == SM_NSPD_STIM)
00185     {
00186       if(currBlinkRate != itsSlowRate)
00187         currBlinkRate = itsSlowRate;
00188     }
00189   }
00190   return currBlinkRate;
00191 }
00192 
00193 
00194 inline ushort StimMaker::SM_speedDownCheck(ushort currBlinkRate,
00195                                            const ushort frame,
00196                                            const ushort changeFrame,
00197                                            const unsigned char stimRate,
00198                                            const unsigned char useSmoothRateChange) const
00199 {
00200   if(frame > changeFrame)
00201   {
00202     
00203     if(stimRate == SM_FAST_STIM)
00204     {
00205       if(currBlinkRate < itsSlowRate)
00206       {
00207         if(useSmoothRateChange == SM_USE_SMOOTH_RATE_CHANGE)
00208           currBlinkRate += SM_SMOOTH_ACCEL;
00209         else
00210           currBlinkRate = itsSlowRate;
00211       }
00212       else
00213         if(currBlinkRate > itsSlowRate)
00214           currBlinkRate = itsSlowRate;
00215     }
00216     
00217     else if(stimRate == SM_SLOW_STIM)
00218     {
00219       if(currBlinkRate != itsStopRate)
00220         currBlinkRate = itsStopRate;
00221     }
00222   }
00223   return currBlinkRate;
00224 
00225 }
00226 
00227 
00228 
00229 
00230 
00231 inline void StimMaker::SM_drawGroundTruth(const ushort frame,
00232                                           const unsigned char stimSizeX,
00233                                           const unsigned char stimSizeY,
00234                                           const ushort PosX,
00235                                           const ushort PosY,
00236                                           const bool targetOn)
00237 {
00238   const Point2D<int> P1(PosX,PosY);
00239   if(targetOn)
00240   {
00241     drawDisk(itsGroundTruth[frame],P1,stimSizeX,itsGTtargetColorPatch1);
00242     drawDisk(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColorPatch2);
00243 
00244   }
00245   else
00246   {
00247     drawDisk(itsGroundTruth[frame],P1,stimSizeX,itsGTtargetColorPatch1off);
00248     drawDisk(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColorPatch2off);
00249   }
00250 }
00251 
00252 
00253 
00254 inline void StimMaker::SM_drawSingleTarget(const ushort frame,
00255                                            const unsigned char stimShape,
00256                                            const unsigned char stimColor,
00257                                            const unsigned char stimSizeX,
00258                                            const unsigned char stimSizeY,
00259                                            const ushort PosX,
00260                                            const ushort PosY,
00261                                            const float stimOri,
00262                                            const float shapePositionJitter,
00263                                            const float shapeOrientationJitter,
00264                                            const bool target)
00265 {
00266   
00267 
00268   unsigned char shape;
00269 
00270   if(stimShape == SM_STIM_RAND)
00271   {
00272     shape = 1 + (unsigned char)(SM_SHAPES*rand()/(RAND_MAX+1.0));
00273   }
00274   else
00275   {
00276     shape = stimShape;
00277   }
00278 
00279   
00280   if(stimColor == SM_COLOR_RAND)
00281   {
00282     unsigned char color = 1 + (unsigned char)(SM_COLORS*rand()/(RAND_MAX+1.0));
00283     if(target)
00284       itsCustomTarg = itsColorVec[color];
00285     else
00286       itsCustomDist = itsColorVec[color];
00287   }
00288   else
00289   {
00290     if(stimColor != SM_COLOR_CUSTOM)
00291     {
00292       if(target)
00293         itsCustomTarg = itsColorVec[stimColor-1];
00294       else
00295         itsCustomDist = itsColorVec[stimColor-1];
00296     }
00297   }  
00298   float posJitterX,posJitterY,oriJitter;
00299 
00300   if(shapePositionJitter != 0.0F)
00301   {
00302     
00303     
00304     float divider;
00305     if((stimShape == SM_STIM_DISK) ||
00306        (stimShape == SM_STIM_CROSS) ||
00307        (stimShape == SM_STIM_PATCH) ||
00308        (stimShape == SM_STIM_CIRC))
00309       divider = 4.0F;
00310     else
00311       divider = 2.0F;
00312     
00313     posJitterX = ((float)stimSizeX)*(shapePositionJitter*rand())
00314       /(RAND_MAX+1.0F) - stimSizeX/divider;
00315     posJitterY = ((float)stimSizeY)*(shapePositionJitter*rand())
00316       /(RAND_MAX+1.0F) - stimSizeY/divider;
00317   }
00318   else
00319   {
00320     posJitterX = 0.0F;
00321     posJitterY = 0.0F;
00322   }
00323 
00324   if(shapeOrientationJitter != 0.0F)
00325   {
00326     
00327     oriJitter  = shapeOrientationJitter *
00328       (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00329   }
00330   else
00331   {
00332     oriJitter = 0.0F;
00333   }
00334 
00335   const float newPosX = posJitterX + PosX;
00336   const float newPosY = posJitterY + PosY;
00337 
00338   const float newOri  = stimOri + oriJitter;
00339 
00340   
00341   if(shape == SM_STIM_DISK)
00342   {
00343     if(stimSizeX != stimSizeY)
00344       LINFO("WARNING: Disk size X and Y should be the same! Using X size.");
00345     if(stimOri != 0.0F)
00346       LINFO("WARNING: Disk cannot have orientation! Ignoring.");
00347     const Point2D<int> center((int)round(newPosX),(int)round(newPosY));
00348     if(target)
00349     {
00350       drawDisk(itsFrames[frame],center,stimSizeX/2,itsCustomTarg);
00351       drawDisk(itsGroundTruth[frame],center,stimSizeX/2,itsGTtargetColor);
00352     }
00353     else
00354     {
00355       drawDisk(itsFrames[frame],center,stimSizeX/2,itsCustomDist);
00356       drawDisk(itsGroundTruth[frame],center,stimSizeX/2,itsGTdistColor);
00357     }
00358   }
00359   
00360   else if(shape == SM_STIM_RECT)
00361   {
00362     const int coordX1 = (int)floor(newPosX + (float)stimSizeX/2.0F);
00363     const int coordX2 = (int)floor(newPosX - (float)stimSizeX/2.0F);
00364     const int coordY1 = (int)floor(newPosY + (float)stimSizeY/2.0F);
00365     const int coordY2 = (int)floor(newPosY - (float)stimSizeY/2.0F);
00366     Rectangle rect = Rectangle::tlbrI(coordY2,coordX2,coordY1,coordX1);
00367 
00368     if(target)
00369     {
00370       drawRectOR(itsFrames[frame],rect,itsCustomTarg,2,newOri);
00371       drawRectOR(itsGroundTruth[frame],rect,itsGTtargetColor,2,newOri);
00372     }
00373     else
00374     {
00375       drawRectOR(itsFrames[frame],rect,itsCustomDist,2,newOri);
00376       drawRectOR(itsGroundTruth[frame],rect,itsGTdistColor,2,newOri);
00377     }
00378   }
00379   
00380   else if(shape == SM_STIM_LINE)
00381   {
00382     if(stimSizeX != stimSizeY)
00383       LINFO("WARNING: Line size X and Y should be the same! Using X size.");
00384     const float newX = stimSizeX/2 * sin(newOri);
00385     const float newY = stimSizeX/2 * cos(newOri);
00386 
00387     const int coordX1 = (int)floor(newPosX + newX);
00388     const int coordX2 = (int)floor(newPosX - newX);
00389     const int coordY1 = (int)floor(newPosY + newY);
00390     const int coordY2 = (int)floor(newPosY - newY);
00391     const Point2D<int> P1(coordX1,coordY1);
00392     const Point2D<int> P2(coordX2,coordY2);
00393 
00394     if(target)
00395     {
00396       drawLine(itsFrames[frame],P1,P2,itsCustomTarg,2);
00397       drawLine(itsGroundTruth[frame],P1,P2,itsGTtargetColor,2);
00398     }
00399     else
00400     {
00401       drawLine(itsFrames[frame],P1,P2,itsCustomDist,2);
00402       drawLine(itsGroundTruth[frame],P1,P2,itsGTdistColor,2);
00403     }
00404   }
00405   
00406   else if(shape == SM_STIM_CROSS)
00407   {
00408     if(stimSizeX != stimSizeY)
00409       LINFO("WARNING: Cross size X and Y should be the same! Using X size.");
00410     const Point2D<int> P1((int)floor(newPosX),(int)floor(newPosY));
00411     if(target)
00412     {
00413       drawCrossOR(itsFrames[frame],P1,itsCustomTarg,stimSizeX/2,2,newOri);
00414       drawCrossOR(itsGroundTruth[frame],P1,itsGTtargetColor,stimSizeX/2,2,newOri);
00415     }
00416     else
00417     {
00418       drawCrossOR(itsFrames[frame],P1,itsCustomDist,stimSizeX/2,2,newOri);
00419       drawCrossOR(itsGroundTruth[frame],P1,itsGTdistColor,stimSizeX/2,2,newOri);
00420     }
00421   }
00422   
00423   else if(shape == SM_STIM_PATCH)
00424   {
00425     if(stimOri != 0.0F)
00426       LINFO("WARNING: Patch cannot have orientation! Net yet supported. Ignoring.");
00427     if(stimSizeX != stimSizeY)
00428       LINFO("WARNING: Patch size X and Y should be the same! Using X size.");
00429     const Point2D<int> P1((int)floor(newPosX),(int)floor(newPosY));
00430     if(target)
00431     {
00432       drawPatch(itsFrames[frame],P1,stimSizeX/2,itsCustomTarg);
00433       drawPatch(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColor);
00434     }
00435     else
00436     {
00437       drawPatch(itsFrames[frame],P1,stimSizeX/2,itsCustomDist);
00438       drawPatch(itsGroundTruth[frame],P1,stimSizeX/2,itsGTdistColor);
00439     }
00440   }
00441   
00442   else if(shape == SM_STIM_ARROW)
00443   {
00444     if(stimSizeX != stimSizeY)
00445       LINFO("WARNING: Arrow size X and Y should be the same! Using X size.");
00446     const float newX = stimSizeX/2 * sin(newOri);
00447     const float newY = stimSizeX/2 * cos(newOri);
00448 
00449     const int coordX1 = (int)floor(newPosX + newX);
00450     const int coordX2 = (int)floor(newPosX - newX);
00451     const int coordY1 = (int)floor(newPosY + newY);
00452     const int coordY2 = (int)floor(newPosY - newY);
00453     const Point2D<int> P1(coordX1,coordY1);
00454     const Point2D<int> P2(coordX2,coordY2);
00455 
00456     if(target)
00457     {
00458       drawArrow(itsFrames[frame],P1,P2,itsCustomTarg,2);
00459       drawArrow(itsGroundTruth[frame],P1,P2,itsGTtargetColor,2);
00460     }
00461     else
00462     {
00463       drawArrow(itsFrames[frame],P1,P2,itsCustomDist,2);
00464       drawArrow(itsGroundTruth[frame],P1,P2,itsGTdistColor,2);
00465     }
00466   }
00467   
00468   else if(shape == SM_STIM_CIRC)
00469   {
00470     if(stimSizeX != stimSizeY)
00471       LINFO("WARNING: Circle size X and Y should be the same! Using X size.");
00472     if(stimOri != 0.0F)
00473       LINFO("WARNING: Circle cannot have orientation! Ignoring.");
00474 
00475     const Point2D<int> center((int)round(newPosX),(int)round(newPosY));
00476     if(target)
00477     {
00478       drawCircle(itsFrames[frame],center,stimSizeX/2,itsCustomTarg);
00479       drawCircle(itsGroundTruth[frame],center,stimSizeX/2,itsGTtargetColor);
00480     }
00481     else
00482     {
00483       drawCircle(itsFrames[frame],center,stimSizeX/2,itsCustomDist);
00484       drawCircle(itsGroundTruth[frame],center,stimSizeX/2,itsGTdistColor);
00485     }
00486   }
00487   else
00488   {
00489     LFATAL("StimMaker tried to draw an unlisted shape %d. See list in StimMaker.H",shape);
00490   }
00491 }
00492 
00493 
00494 
00495 void StimMaker::SM_makeUniformStim(const StimMakerParam &stim)
00496 {
00497   itsRandomSeed = stim.SMP_randomSeed;
00498   
00499   srand(itsRandomSeed);
00500   LINFO("Setting up stim params");
00501   
00502   uint frame = 0;
00503   
00504   const float divX     = ceil((float)itsSizeX/(float)stim.SMP_distPerRow);
00505   const float divY     = ceil((float)itsSizeY/(float)stim.SMP_distPerCol);
00506   const float startx   = round(divX/2);
00507   const float starty   = round(divY/2);
00508   const uint movieHalf = (uint)round((float)itsFrameCount/2.0F);
00509   const uint fastBlink = itsFastRate;
00510   const uint slowBlink = itsSlowRate;
00511 
00512   uint targBlinkRate;
00513   uint distBlinkRate;
00514 
00515   
00516   const uint changeFrame = (uint)floor((movieHalf/2)+(movieHalf*rand()/(RAND_MAX+1.0)));
00517 
00518   
00519   if(stim.SMP_targetRate == SM_FAST_STIM)
00520     targBlinkRate = fastBlink;
00521   else if(stim.SMP_targetRate == SM_SLOW_STIM)
00522     targBlinkRate = slowBlink;
00523   else
00524     targBlinkRate = 0;
00525 
00526   
00527   if(stim.SMP_distRate == SM_FAST_STIM)
00528     distBlinkRate = fastBlink;
00529   else if(stim.SMP_distRate == SM_SLOW_STIM)
00530     distBlinkRate = slowBlink;
00531   else
00532     distBlinkRate = 0;
00533 
00534   
00535 
00536   
00537   
00538 
00539   
00540   
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552   
00553   uint currTargBlinkRate   = targBlinkRate;
00554   int currTargBlinkOffset  = 0;
00555   
00556   uint currTargShape       = stim.SMP_targetShape;
00557   uint currTargColor       = stim.SMP_targetColor;
00558   uint currTargSizeX       = stim.SMP_targetSizeX;
00559   uint currTargSizeY       = stim.SMP_targetSizeY;
00560   bool currTargOn          = stim.SMP_targetOn;
00561 
00562   LINFO("Computing target values");
00563   
00564   if(stim.SMP_useRandomStart == SM_USE_RANDOM_START)
00565   {
00566     const float distRand = (1.0*rand()/(RAND_MAX+1.0));
00567     currTargBlinkOffset = (uint)round((float)distBlinkRate*distRand);
00568     const float onRand = (1.0*rand()/(RAND_MAX+1.0));
00569     if(onRand > .5)
00570       currTargOn = true;
00571     else
00572       currTargOn = false;
00573   }
00574   
00575   if(stim.SMP_targetShape == SM_STIM_RAND)
00576   {
00577     const float distRand = 1.0F + (((float)(SM_SHAPES))*rand()/
00578                                       (RAND_MAX+1.0F));
00579     currTargShape = (uint)distRand;
00580   }
00581   
00582   if(stim.SMP_targetColor == SM_COLOR_RAND)
00583   {
00584     const float distRand = 1.0F + (((float)(SM_COLORS-1.0F))*rand()/
00585                                       (RAND_MAX+1.0F));
00586     currTargColor = (uint)distRand;
00587   }
00588   
00589   if(stim.SMP_targetSizeX == 0)
00590   {
00591     const float maxSizeX  = divX;
00592     const float distRandX = 1.0F + (((float)(maxSizeX-1.0F))*rand()/
00593                                        (RAND_MAX+1.0F));
00594     currTargSizeX = (uint)distRandX;
00595     const float maxSizeY  = divY;
00596     const float distRandY = 1.0F + (((float)(maxSizeY-1.0F))*rand()/
00597                                        (RAND_MAX+1.0F));
00598     currTargSizeY = (uint)distRandY;
00599   }
00600 
00601   LINFO("Setting up distractor vectors");
00602   
00603   std::vector<ushort> distInit(stim.SMP_distPerCol,0);
00604   std::vector<int> distInitS(stim.SMP_distPerCol,0);
00605   std::vector<float> distInitF(stim.SMP_distPerCol,0);
00606 
00607   std::vector<std::vector<ushort> >
00608     currDistBlinkRate(stim.SMP_distPerRow,distInit);
00609   std::vector<std::vector<ushort> >
00610     currDistShape(stim.SMP_distPerRow,distInit);
00611   std::vector<std::vector<ushort> >
00612     currDistColor(stim.SMP_distPerRow,distInit);
00613   std::vector<std::vector<ushort> >
00614     currDistSizeX(stim.SMP_distPerRow,distInit);
00615   std::vector<std::vector<ushort> >
00616     currDistSizeY(stim.SMP_distPerRow,distInit);
00617   std::vector<std::vector<ushort> >
00618     currPosX(stim.SMP_distPerRow,distInit);
00619   std::vector<std::vector<ushort> >
00620     currPosY(stim.SMP_distPerRow,distInit);
00621 
00622   std::vector<std::vector<int> >
00623     currDistBlinkOffset(stim.SMP_distPerRow,distInitS);
00624 
00625   std::vector<std::vector<float> >
00626     currDistOrientation(stim.SMP_distPerRow,distInitF);
00627 
00628   std::vector<bool> distOnInit(stim.SMP_distPerCol,stim.SMP_distOn);
00629   std::vector<std::vector<bool> > currDistOn(stim.SMP_distPerRow,distOnInit);
00630 
00631   
00632   
00633   
00634   
00635   
00636 
00637   LINFO("Setting up distractors");
00638   for(uint i = 0; i < stim.SMP_distPerRow; i++)
00639   {
00640     for(uint j = 0; j < stim.SMP_distPerCol; j++)
00641     {
00642       
00643       if(stim.SMP_useRandomStart == SM_USE_RANDOM_START)
00644       {
00645         const float distRand = (1.0F*rand()/(RAND_MAX+1.0));
00646         currDistBlinkOffset[i][j] = (uint)round((float)distBlinkRate*distRand);
00647         const float onRand = (1.0F*rand()/(RAND_MAX+1.0));
00648         if(onRand > 0.5F)
00649           currDistOn[i][j] = true;
00650         else
00651           currDistOn[i][j] = false;
00652       }
00653       else
00654       {
00655         currDistBlinkOffset[i][j] = 0;
00656       }
00657 
00658       
00659       if(stim.SMP_distShape == SM_STIM_RAND)
00660       {
00661         const float distRand = 1.0F + (((float)(SM_SHAPES))*rand()/
00662                                           (RAND_MAX+1.0F));
00663         currDistShape[i][j]  = (ushort)distRand;
00664       }
00665       else
00666       {
00667         currDistShape[i][j]  = stim.SMP_distShape;
00668       }
00669 
00670       
00671       if(stim.SMP_distColor == SM_COLOR_RAND)
00672       {
00673         const float distRand = 1.0F + (((float)(SM_COLORS - 1.0F))*rand()/
00674                                        (RAND_MAX+1.0F));
00675 
00676         
00677         currDistColor[i][j]  = (ushort)distRand;
00678       }
00679       else
00680       {
00681         currDistColor[i][j] = stim.SMP_distColor;
00682       }
00683 
00684       
00685       if(stim.SMP_distSizeX == 0)
00686       {
00687         const float maxSizeX  = divX;
00688         const float distRandX = 1.0F + (((float)(maxSizeX-1.0))*rand()/
00689                                           (RAND_MAX+1.0F));
00690         currDistSizeX[i][j]   = (ushort)distRandX;
00691         const float maxSizeY  = divY;
00692         const float distRandY = 1.0F + (((float)(maxSizeY-1.0))*rand()/
00693                                           (RAND_MAX+1.0F));
00694         currDistSizeY[i][j]   = (ushort)distRandY;
00695       }
00696       else
00697       {
00698         currDistSizeX[i][j]   = stim.SMP_distSizeX;
00699         currDistSizeY[i][j]   = stim.SMP_distSizeY;
00700       }
00701 
00702       currDistBlinkRate[i][j] = distBlinkRate;
00703 
00704       
00705       if(stim.SMP_useHexagon == SM_USE_HEXAGON)
00706       {
00707         float newDiv = 0.0F;
00708         if(j%2 == 0)
00709           newDiv = divX/4;
00710         else
00711           newDiv = -1.0F*divX/4;
00712         
00713         currPosX[i][j] = (uint)floor(newDiv + startx + i*divX);
00714         
00715         currPosY[i][j] = (uint)floor(starty + j*divY);
00716       }
00717       else
00718       {
00719         
00720         currPosX[i][j] = (uint)floor(startx + i*divX);
00721         
00722         currPosY[i][j] = (uint)floor(starty + j*divY);
00723       }
00724       float posJitterX,posJitterY;
00725       if(stim.SMP_shapePositionJitterStatic != 0.0F)
00726       {
00727         float divider;
00728         if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00729         {
00730           if((currTargShape == SM_STIM_DISK)  ||
00731              (currTargShape == SM_STIM_CROSS) ||
00732              (currTargShape == SM_STIM_PATCH) ||
00733              (currTargShape == SM_STIM_CIRC))
00734             divider = 4.0F;
00735           else
00736             divider = 2.0F;
00737 
00738           posJitterX = ((float)stim.SMP_targetSizeX)
00739             *(stim.SMP_shapePositionJitterStatic*rand())
00740             /(RAND_MAX+1.0F) - stim.SMP_distSizeX/divider;
00741           posJitterY = ((float)stim.SMP_targetSizeY)
00742             *(stim.SMP_shapePositionJitterStatic*rand())
00743             /(RAND_MAX+1.0F) - stim.SMP_distSizeY/divider;
00744 
00745         }
00746         else
00747         {
00748           if((currDistShape[i][j] == SM_STIM_DISK)  ||
00749              (currDistShape[i][j] == SM_STIM_CROSS) ||
00750              (currDistShape[i][j] == SM_STIM_PATCH) ||
00751              (currDistShape[i][j] == SM_STIM_CIRC))
00752             divider = 4.0F;
00753           else
00754             divider = 2.0F;
00755 
00756 
00757           posJitterX = ((float)stim.SMP_targetSizeX)
00758             *(stim.SMP_shapePositionJitterStatic*rand())
00759             /(RAND_MAX+1.0F) - stim.SMP_distSizeX/divider;
00760           posJitterY = ((float)stim.SMP_targetSizeY)
00761             *(stim.SMP_shapePositionJitterStatic*rand())
00762             /(RAND_MAX+1.0F) - stim.SMP_distSizeY/divider;
00763         }
00764       }
00765       else
00766       {
00767         posJitterX = 0.0F;
00768         posJitterY = 0.0F;
00769       }
00770       currPosX[i][j] = (ushort)(round(posJitterX + currPosX[i][j]));
00771       currPosY[i][j] = (ushort)(round(posJitterY + currPosY[i][j]));
00772 
00773       
00774       float oriJitter = 0.0F;
00775       if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00776       {
00777         if(stim.SMP_shapeOrientationJitterStatic != 0.0F)
00778         {
00779           oriJitter  = stim.SMP_shapeOrientationJitterStatic *
00780             (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00781         }
00782         currDistOrientation[i][j] = oriJitter + stim.SMP_targetOri;
00783       }
00784       else
00785       {
00786         if(stim.SMP_shapeOrientationJitterStatic != 0.0F)
00787         {
00788           oriJitter  = stim.SMP_shapeOrientationJitterStatic *
00789             (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00790         }
00791         currDistOrientation[i][j] = oriJitter + stim.SMP_distOri;
00792       }
00793     }
00794   }
00795 
00796   LINFO("Drawing stim images");
00797   std::vector<Image<PixRGB<float> > >::iterator framesIter = itsFrames.begin();
00798   while(framesIter != itsFrames.end())
00799   {
00800     
00801     
00802 
00803     for(uint i = 0; i < stim.SMP_distPerRow; i++)
00804     {
00805       for(uint j = 0; j < stim.SMP_distPerCol; j++)
00806 
00807       {
00808                
00809         
00810         if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00811         {
00812           
00813           if((currTargOn) || (currTargBlinkRate == 0))
00814           {
00815             SM_drawGroundTruth((ushort)frame,
00816                                (unsigned char)currTargSizeX,
00817                                (unsigned char)currTargSizeY,
00818                                (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00819                                true);
00820             
00821             
00822 
00823             SM_drawSingleTarget((ushort)frame,
00824                                 (unsigned char)currTargShape,
00825                                 (unsigned char)currTargColor,
00826                                 (unsigned char)currTargSizeX,
00827                                 (unsigned char)currTargSizeY,
00828                                 (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00829                                 currDistOrientation[i][j],
00830                                 stim.SMP_shapePositionJitter,
00831                                 stim.SMP_shapeOrientationJitter, true);
00832           }
00833           else
00834           {
00835             SM_drawGroundTruth((ushort)frame,
00836                                (unsigned char)currTargSizeX,
00837                                (unsigned char)currTargSizeY,
00838                                (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00839                                false);
00840           }
00841 
00842           
00843 
00844           bool checkSpeed = false;
00845           if(currTargBlinkRate == 0)
00846             checkSpeed = true;
00847           else if(((frame+currTargBlinkOffset)
00848                    %currTargBlinkRate) == 0)
00849             checkSpeed = true;
00850 
00851           if(checkSpeed)
00852           {
00853             if(currTargBlinkRate != 0)
00854             {
00855               if(currTargOn)
00856                 currTargOn = false;
00857               else
00858                 currTargOn = true;
00859             }
00860             else
00861               currTargOn = true;
00862             
00863             
00864             if(stim.SMP_targetState == SM_STATE_START)
00865             {
00866               const uint newRate = SM_speedUpCheck(
00867                                        currTargBlinkRate,
00868                                        frame,changeFrame,
00869                                        stim.SMP_targetRate,
00870                                        stim.SMP_useSmoothRateChange);
00871               if(newRate != currTargBlinkRate)
00872               {
00873                 currTargBlinkOffset = -1*frame;
00874                 currTargBlinkRate   = newRate;
00875               }
00876             }
00877             
00878             
00879             if(stim.SMP_targetState == SM_STATE_STOP)
00880             {
00881               const uint newRate = SM_speedDownCheck(
00882                                        currTargBlinkRate,
00883                                        frame,changeFrame,
00884                                        stim.SMP_targetRate,
00885                                        stim.SMP_useSmoothRateChange);
00886               if(newRate != currTargBlinkRate)
00887               {
00888                 currTargBlinkOffset = -1*frame;
00889                 currTargBlinkRate   = newRate;
00890               }
00891             }
00892           }
00893         }
00894         else
00895         {
00896           
00897           
00898           if((currDistOn[i][j]) || (currDistBlinkRate[i][j] == 0))
00899           {
00900             
00901             
00902             SM_drawSingleTarget((ushort)frame,
00903                                 (unsigned char)currDistShape[i][j],
00904                                 (unsigned char)currDistColor[i][j],
00905                                 (unsigned char)currDistSizeX[i][j],
00906                                 (unsigned char)currDistSizeY[i][j],
00907                                 (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00908                                 currDistOrientation[i][j],
00909                                 stim.SMP_shapePositionJitter,
00910                                 stim.SMP_shapeOrientationJitter, false);
00911           }
00912           
00913           
00914           
00915           
00916           
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928 
00929 
00930 
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 
00944 
00945 
00946 
00947 
00948 
00949 
00950 
00951 
00952 
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 
00970 
00971 
00972 
00973 
00974 
00975 
00976 
00977 
00978 
00979 
00980 
00981 
00982 
00983 
00984 
00985 
00986 
00987 
00988 
00989 
00990           
00991           
00992           
00993 
00994 
00995           bool checkSpeed = false;
00996           if(currDistBlinkRate[i][j] == 0)
00997             checkSpeed = true;
00998           else if(((frame+currDistBlinkOffset[i][j])
00999                    %currDistBlinkRate[i][j]) == 0)checkSpeed = true;
01000 
01001           if(checkSpeed)
01002           {
01003 
01004             if(currDistBlinkRate[i][j] != 0)
01005             {
01006 
01007               if(currDistOn[i][j])
01008                 currDistOn[i][j] = false;
01009               else
01010                 currDistOn[i][j] = true;
01011             }
01012             else
01013               currDistOn[i][j] = true;
01014             
01015             
01016 
01017             if(stim.SMP_distState == SM_STATE_START)
01018             {
01019 
01020                const uint newRate = SM_speedUpCheck(
01021                                         currDistBlinkRate[i][j],
01022                                         frame,changeFrame,
01023                                         stim.SMP_distRate,
01024                                         stim.SMP_useSmoothRateChange);
01025               if(newRate != currDistBlinkRate[i][j])
01026               {
01027                   currDistBlinkOffset[i][j] = -1*frame;
01028                   currDistBlinkRate[i][j]   = newRate;
01029               }
01030             }
01031 
01032             
01033             
01034             if(stim.SMP_distState == SM_STATE_STOP)
01035             {
01036 
01037               const uint newRate = SM_speedDownCheck(
01038                                         currDistBlinkRate[i][j],
01039                                         frame,changeFrame,
01040                                         stim.SMP_distRate,
01041                                         stim.SMP_useSmoothRateChange);
01042               if(newRate != currDistBlinkRate[i][j])
01043               {
01044                 currDistBlinkOffset[i][j] = -1*frame;
01045                 currDistBlinkRate[i][j]   = newRate;
01046               }
01047             }
01048           }
01049         }
01050       }
01051     }
01052 
01053     frame++; ++framesIter;
01054     
01055   }
01056   LINFO("Drawing complete");
01057 }
01058 
01059 
01060 
01061 std::vector<Image<PixRGB<float> > > StimMaker::SM_getStim() const
01062 {
01063   return itsFrames;
01064 }
01065 
01066 
01067 
01068 std::vector<Image<PixRGB<float> > > StimMaker::SM_getGroundTruth() const
01069 {
01070   return itsGroundTruth;
01071 }
01072 
01073 #endif // STIM_MAKER_H_DEFINED
01074 
01075 
01076 
01077