psychopy.org | Reference | Downloads | Github

Randomize Stimulus Interval

I am trying to figure out how to randomize the interval and position that a stimulus appears. Right now I have a csv file that imports the four conditions (2 intervals x 2 positions). I am able to get the positions to work by simply using setPos(), but for the interval that the stimulus appears, I am not sure how to do this. I have the intervals for the stimulus set to frames 101 and 202. I may have also messed up with the frame timing in my range. I’m a bit confused on when a frame starts and ends. gabTime is the variable used in the csv file for the frame of the stimulus to appear.


cond_loop = data.TrialHandler(nReps=5, method='fullRandom', 
    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions('gabor_list.csv'),
    seed=None)
thisExp.addLoop(cond_loop)  # add the loop to the experiment
thisTrial = cond_loop.trialList[0]  # so we can initialise stimuli with some values
frameN=-1

for thisTrial in cond_loop:
    currentLoop = cond_loop
    # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
    if thisTrial != None:
        for paramName in thisTrial:
            exec('{} = thisTrial[paramName]'.format(paramName))
            

    # number of completed frames (so 0 is the first frame)
    frameN = frameN + 1
    grating.setPos(gabLoc)
    
    # Timing in frames for drawing the stimulus and fixation
    for frameN in range(222):
        if 0 <= frameN < 100:
            circle.draw()
        if 100 <= frameN < 101:
            diamond.draw()
        if frameN >= gabTime :
            grating.draw()
        if 101 <= frameN < 201:
            circle.draw()
        if 201 <= frameN < 202:
            diamond.draw()
        if 202 <= frameN < 222:
            ITI.draw()
        win.flip()

Please precisely describe how you actually intend the stimuli to be controlled with respect to their time of onset/offset.

I am using a 100hz monitor. I intend for the stumuli to appear in this order:

  • circle (100 frames, 2 seconds)
  • diamond (1 frame, 20 ms) - gabor
  • circle (100 frames, 2 seconds)
  • diamond (1 frame, 20 ms) - gabor
  • ITI (20 frames, 400 ms)

the gabor will appear either in frame 101 or 202.

Not sure I really understand those timings (e.g. at 100 Hz, 100 frames == 1 s), but regardless, to control your Gabor patch appearance, you can just use the gabTime variable in place of the literal frame numbers in your expressions, as you have done.

So what exactly is going wrong?

 
 

EDIT: not that it is important, but this line doesn’t do anything:

frameN = frameN + 1

as it is immediately superseded by this line:

for frameN in range(222):

and for clarity of reading, lines like this:

if 100 <= frameN < 101:

could simply be:

if frameN == 100:

and you could make some compound expressions for some stimuli:

# brackets optional but help with readability:
if (frameN < 100) or (101 <= frameN < 201):
    circle.draw()

If I changed this

if 100 <= frameN < 101:

to

if frameN == 100:

then wouldn’t the stimulus continue beyond 1 frame? I want to stimuli to start an stop at a specific frame.

Oops, multiply all the frames by 2. I adjusted the frames. The problem is that the first two if statements appear, but the none of the other ones are drawn. I took out the if statement for the gabor just to see if I could get this thing to work for starters.

for frameN in range(444):
        frameN = frameN + 1
        if 0 <= frameN < 200:
            circle.draw()
        if 200 <= frameN < 203:           
            diamond.draw()
        if 202 <= frameN < 403:
            circle.draw()
        if 402 <= frameN < 405:
            diamond.draw()
        if 404 <= frameN < 444:
            ITI.draw()
        win.flip()

It works now. The frameN + 1 line caused problems and the numbering order going from if statement to if statement was causing problem. Also, I heard using all if statements can cause a competition for resources so I changed some to elif.

for frameN in range(444):
        #frameN = frameN + 1
        if (0 <= frameN < 200) or (202 <= frameN < 402):
            circle.draw()
        elif (200 <= frameN < 202) or (402 <= frameN < 404):
            diamond.draw()
        elif 404 <= frameN < 444:
            ITI.draw()
        win.flip()