How to draw stimuli in the same position multiple times in a single routine?

Hi

I’m wondering if it’s possible to ‘draw’/present different stimuli twice at the same position in one routine?
Here is a brief summary of the experimental procedure to give you an idea of the codes that follow. Firstly, (1st routine, which not show here) participants will see two items on the left and right sides of the screen (e.g. happy (‘left stim)’ vs fearful (‘right stim’) faces presented on the screen with a dot (‘dot’), and then they will be asked to choose either ‘left’ or ‘right’. The next stimuli will show themselves based on subject’s choice (the 2nd routine, see the code below).

I’d like to show different happy and fearful faces at the same position, but for varying lengths of time (1st one is for 0.5s and second for 1.8s) inn one procedure. However, it appears that drawing two separate stimuli at the same location is not problematic that give me a grey screen.

Thank you in advance for any feedback you may provide to help me solve this problem.

# ----------initialise components for Routine2----------

routine2Clock= core.Clock()

background = visual.ImageStim(
    win=win, name='backgr',
    image=u'.\\img\\backgr.png', mask=None,
    ori=0, pos=(0.0, 0.0), size=(1280, 1024),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    texRes=128, interpolate=True, depth=0.0)

left_1_Stim = visual.ImageStim(
    win=win, name='leftStim1',
    image=u'.\\img\\leftStim1.png', mask=None,
    ori=0, pos=(-0.6, 0.0), size=(0.2, 0.25),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    texRes=128, interpolate=True, depth=-1.0)

right_1_Stim = visual.ImageStim(
    win=win, name='rightStim1',
    image=u'.\\img\\rightStim1.png', mask=None,
    ori=0, pos=(-0.6, 0.0), size=(0.2, 0.25),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    texRes=128, interpolate=True, depth=-2.0)

left_2_Stim = visual.ImageStim(
    win=win, name='leftStim2',
    image=u'.\\img\\leftStim2.png', mask=None,
    ori=0, pos=(-0.6, 0.0), size=(0.2, 0.25),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    texRes=128, interpolate=True, depth=-3.0)

right_2_Stim = visual.ImageStim(
    win=win, name='rightStim2',
    image=u'.\\img\\rightStim2.png', mask=None,
    ori=0, pos=(-0.6, 0.0), size=(0.2, 0.25),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    texRes=128, interpolate=True, depth=-4.0)

dot = visual.ImageStim(
    win=win, name='dot',
    image=u'.\\img\\dot.jpg', mask=None,
    ori=0, pos=(0, -0.22), size=(0.06, 0.07),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    flipHoriz=False, flipVert=False,
    texRes=128, interpolate=True, depth=-5.0)

# ----------start the Routine----------
t = 0
routine2Clock.reset()
frameN = -1
continueRoutine = True

key_resp = event.BuilderKeyResponse()

# keep track of which components have finished
routine2Comp = [background,left_1_stim,right_1_stim,left_2_stim, right_2_stim,dot, key_resp]

for thisComponent in routine2Comp:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

while continueRoutine:
    # get current time
    t = routine2Clock.getTime()
    frameN = frameN + 1

  # *background* updates
            if t >= 0.0 and background.status == NOT_STARTED:
                background.tStart = t
                background.frameNStart = frameN
                background.setAutoDraw(True)
            frameRemains = 0.0 + 2.3- win.monitorFramePeriod
            if background.status == STARTED and t >= frameRemains:
                background.setAutoDraw(False)

            # *left_1_stim* updates
            if t >= 0.0 and left_1_stim.status == NOT_STARTED:
                left_1_stim.tStart = t
                left_1_stim.frameNStart = frameN
                left_1_stim.setAutoDraw(True)
            frameRemains = 0.0 + 0.5- win.monitorFramePeriod
            if   left_1_stim.status == STARTED and t >= frameRemains:
                  left_1_stim.setAutoDraw(False)

            # *right_1_stim* updates
            if t >= 0.0 and right_1_stim.status == NOT_STARTED:
                right_1_stim.tStart = t
                right_1_stim.frameNStart = frameN
                right_1_stim.setAutoDraw(True)
            frameRemains = 0.0 + 0.5- win.monitorFramePeriod
            if right_1_stim.status == STARTED and t >= frameRemains:
                 right_1_stim.setAutoDraw(False)

            # *left_2_stim* updates
            if t >= 0.0 and left_2_stim.status == NOT_STARTED:
                left_2_stim.tStart = t
                left_2_stim.frameNStart = frameN
                left_2_stim.setAutoDraw(True)
            frameRemains = 0.0 + 1.8- win.monitorFramePeriod
            if  left_2_stim.status == STARTED and t >= frameRemains:
                  left_2_stim.setAutoDraw(False)

            # *right_2_stim* updates
            if t >= 0.0 and right_2_stim.status == NOT_STARTED:
                right_2_stim.tStart = t
                right_2_stim.frameNStart = frameN
                right_2_stim.setAutoDraw(True)
            frameRemains = 0.0 + 1.8- win.monitorFramePeriod
            if right_2_stim.status == STARTED and t >= frameRemains:
                 right_2_stim.setAutoDraw(False)

            # *left_2_stim* updates
            if t >= 0.0 and left_2_stim.status == NOT_STARTED:
                left_2_stim.tStart = t
                left_2_stim.frameNStart = frameN
                left_2_stim.setAutoDraw(True)
            frameRemains = 0.0 + 1.8- win.monitorFramePeriod
            if  left_2_stim.status == STARTED and t >= frameRemains:
                  left_2_stim.setAutoDraw(False)

            # *dot* updates
            if t >= 1.2 and dot.status == NOT_STARTED:
                dot.tStart = t
                dot.frameNStart = frameN  # exact frame index
                dot.setAutoDraw(True)
            frameRemains = 1.2 + keyVary2- win.monitorFramePeriod
            if dot.status == STARTED and t >= frameRemains:
                dot.setAutoDraw(False)

            # check if all components have finished
            if not continueRoutine: 
                break
            continueRoutine = False  
            for thisComponent in routine2Comp:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break 
            
            # check for quit (the Esc key)
            if endExpNow or event.getKeys(keyList=["escape"]):
                core.quit()
            
            # refresh the screen
            if continueRoutine:  
                win.flip()
            

I’m not entirely sure of what approach you’ve tried here.

Are you using Builder with code components or just Coder?

If you are using Builder, it is easier to understand your approach if you show your components rather than Python code compiled by Builder.

If you want to change the face during the same routine you can either have two components, with different start times (0 and 0.5?) and durations (0.5 and 1.8?), or you can use a single component (start 0 and duration 2.3) and then update the image in code at the appropriate time.

Thank you so much for your response! You are correct in that the codes are generated by the builder and then modified. Unfortunately, I do not have a file for builder, which is why I asked this issue here to get some helps. The first advice helped me solve the problem. But your second question, that we can set ‘frameRemains = 0.0 + 2.3- win.monitorFramePeriod’ and then update the images in code, intrigues me. I’m not sure I understand it; do you mean (see the codes below)? The example doesn’t look right to me but I try to get the point. Thanks a lot for your reply!

if t >= 0.0 and left_1_stim.status &  left_2_stim.statu == NOT_STARTED:
                left_1_stim.statu.tStart &  = t
                left_1_stim.statu.frameNStart = frameN
                left_1_stim.statu.setAutoDraw(True)
            frameRemains = 0.0 + 0.5- win.monitorFramePeriod
                left_1_stim.statu.tStart &  = t
                left_1_stim.statu.frameNStart = frameN
                left_1_stim.statu.setAutoDraw(True)
            frameRemains = 0.0 + 1.8- win.monitorFramePeriod

t is always >= 0

You code seems to have a number of typos, so it’s difficult to know what you are asking.

Personally, I tend to work with seconds rather than frames, because I’m usually either working on experiments where the exact number of frames isn’t important, or where I’m trying to run the experiment online, and I can’t therefore know the framerate of the participant’s device.