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