Repeat a stimulus

Hi there,

I am trying to write some code where the same stimulus (e.g. a square) is presented at specific time intervals, 1s, 2s, 3s, 4s etc. At each timepoint, I want the square to be displayed in one of 6 randomly selected locations. At the same time as these squares are playing, there is another ongoing task, with a stimulus presented in the middle of the screen. I want the squares to be presented at the 1s, 2s, 3s, 4s intervals for as long as the other task lasts.

Can someone offer some guidance/help as to how you would code this? The builder view only allows me to go so far I think - i.e. I can get the ongoing task going, but I can only present one red square (although I can get it to choose the location randomly)

Any help would be greatly appreciated,

Thank you,

Jo

It’s hard to know without more information, but probably the easiest thing to do is insert another loop around your trial routine, with nReps set to 6, and probably with is trials marked as false.

i.e. set your stimulus to appear for 1 second, at its random location. Also set the main stimulus to appear at its fixed central location, also for 1 second. This should appear to the subject as there being a static central stimulus with a square which moves very second.

Adding code components in the builder can make it pretty powerful. Post some of your work (screenshots, .pysexp files, code formatted with three backticks ``` on the line above and the line below) and people can start helping.

EDIT

Whoops, sorry @Michael , posted at the same time.

Aha OK. Thank you so much for responding. Is that how you would recommend progressing from builder to coder? i.e. inserting code into the builder view, rather than going straight into coder itself? I was struggling to bridge the gap to be honest. i.e. I compiled the script from the builder view and made changes, but it became apparent that probably wasn’t too good any idea for major changes. Equally, going from scratch in the coder view is a bit difficult, resisting the urge to repeat what is in the builder view.

Thanks Michael, What does ‘is trials’ actually mean? It is an odd experiment, but I want the main stimulus to be stopped by a spacebar press, and the red square to be stopped by a mouseclick, but for them both to appear concurrently on the screen…I will post some pictures.

Thank you both so much, this forum is a really helpful place. Not many people in my lab use Psychopy, if at all, so this community is very much my light in the dark!

In the experiment in this picture, I am trying to get the arithmetic problem to be continuously presented until the person presses a spacebar. There are 6 empty squares surrounding the arithmetic problem. I want one of these squares to flash red, once every second, in a random order, until the person presses a mouse-click.

The script PsychoPy has compiled is:

“”"#!/usr/bin/env python2

-- coding: utf-8 --

“”“
This experiment was created using PsychoPy2 Experiment Builder (v1.84.2),
on November 29, 2016, at 09:49
If you publish work using this script please cite the PsychoPy publications:
Peirce, JW (2007) PsychoPy - Psychophysics software in Python.
Journal of Neuroscience Methods, 162(1-2), 8-13.
Peirce, JW (2009) Generating stimuli for neuroscience using PsychoPy.
Frontiers in Neuroinformatics, 2:10. doi: 10.3389/neuro.11.010.2008
"”"

from future import absolute_import, division
from psychopy import locale_setup, gui, visual, core, data, event, logging, sound
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np # whole numpy lib is available, prepend 'np.'
from numpy import (sin, cos, tan, log, log10, pi, average,
sqrt, std, deg2rad, rad2deg, linspace, asarray)
from numpy.random import random, randint, normal, shuffle
import os # handy system and path functions
import sys # to get file system encoding

Ensure that relative paths start from the same directory as this script

_thisDir = os.path.dirname(os.path.abspath(file)).decode(sys.getfilesystemencoding())
os.chdir(_thisDir)

Store info about the experiment session

expName = ‘Expt1’ # from the Builder filename that created this script
expInfo = {‘participant’:’’, ‘session’:‘001’}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False:
core.quit() # user pressed cancel
expInfo[‘date’] = data.getDateStr() # add a simple timestamp
expInfo[‘expName’] = expName

Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc

filename = thisDir + os.sep + u’data/%s%s_%s’ % (expInfo[‘participant’], expName, expInfo[‘date’])

An ExperimentHandler isn’t essential but helps with data saving

thisExp = data.ExperimentHandler(name=expName, version=’’,
extraInfo=expInfo, runtimeInfo=None,
originPath=None,
savePickle=True, saveWideText=True,
dataFileName=filename)

save a log file for detail verbose info

logFile = logging.LogFile(filename+’.log’, level=logging.EXP)
logging.console.setLevel(logging.WARNING) # this outputs to the screen, not a file

endExpNow = False # flag for ‘escape’ or other condition => quit the exp

Start Code - component code to be run before the window creation

Setup the Window

win = visual.Window(
size=(1600, 900), fullscr=True, screen=0,
allowGUI=False, allowStencil=False,
monitor=‘testMonitor’, color=[0,0,0], colorSpace=‘rgb’,
blendMode=‘avg’, useFBO=True)

store frame rate of monitor if we can measure it

expInfo[‘frameRate’] = win.getActualFrameRate()
if expInfo[‘frameRate’] != None:
frameDur = 1.0 / round(expInfo[‘frameRate’])
else:
frameDur = 1.0 / 60.0 # could not measure, so guess

Initialize components for Routine “Instructions1”

Instructions1Clock = core.Clock()
text = visual.TextStim(win=win, name=‘text’,
text=‘Answer the arithmetic problem by saying aloud your answer and pressing the spacebar at the same time’,
font=‘Arial’,
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,
color=‘white’, colorSpace=‘rgb’, opacity=1,
depth=0.0);

Initialize components for Routine “Arithmetic_problem”

Arithmetic_problemClock = core.Clock()
from numpy.random import random, randint, normal, shuffle
import random
locations = [-0.6,0.0,0.6]
rloca = random.choice(locations)
rlocb = random.choice(locations)
Fixation = visual.TextStim(win=win, name=‘Fixation’,
text=‘READY’,
font=‘Arial’,
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,
color=‘white’, colorSpace=‘rgb’, opacity=1,
depth=-1.0);
Arithmetic = visual.TextStim(win=win, name=‘Arithmetic’,
text=‘default text’,
font=‘Arial’,
pos=(0, 0), height=0.2, wrapWidth=None, ori=0,
color=‘white’, colorSpace=‘rgb’, opacity=1,
depth=-2.0);
S_MU = visual.ImageStim(
win=win, name=‘S_MU’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(0, 0.6), size=(0.25, 0.4),
color=1.0, colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-4.0)
S_ML = visual.ImageStim(
win=win, name=‘S_ML’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(0, -0.6), size=(0.25, 0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-5.0)
S_LU = visual.ImageStim(
win=win, name=‘S_LU’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(-0.6, 0.6), size=(0.25, 0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-6.0)
S_LL = visual.ImageStim(
win=win, name=‘S_LL’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(-0.6, -0.6), size=(0.25, 0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-7.0)
S_RU = visual.ImageStim(
win=win, name=‘S_RU’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(0.6,0.6), size=(0.25,0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-8.0)
S_RL = visual.ImageStim(
win=win, name=‘S_RL’,
image=‘C:\Users\User\Documents\Experiment1\square.png’, mask=None,
ori=0, pos=(0.6,-0.6), size=(0.25,0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-9.0)
imagered = visual.ImageStim(
win=win, name=‘imagered’,
image=u’C:\Users\User\Documents\Experiment1\fillsquare.png’, mask=None,
ori=0, pos=(rloca,rlocb), size=(0.25, 0.4),
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-10.0)

Initialize components for Routine “Button1”

Button1Clock = core.Clock()

Initialize components for Routine “Button2”

Button2Clock = core.Clock()

Initialize components for Routine “Button3”

Button3Clock = core.Clock()

Create some handy timers

globalClock = core.Clock() # to track the time since experiment started
routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine

------Prepare to start Routine “Instructions1”-------

t = 0
Instructions1Clock.reset() # clock
frameN = -1
continueRoutine = True

update component parameters for each repeat

End_instructions = event.BuilderKeyResponse()

keep track of which components have finished

Instructions1Components = [text, End_instructions]
for thisComponent in Instructions1Components:
if hasattr(thisComponent, ‘status’):
thisComponent.status = NOT_STARTED

-------Start Routine “Instructions1”-------

while continueRoutine:
# get current time
t = Instructions1Clock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame

# *text* updates
if t >= 0.0 and text.status == NOT_STARTED:
    # keep track of start time/frame for later
    text.tStart = t
    text.frameNStart = frameN  # exact frame index
    text.setAutoDraw(True)

# *End_instructions* updates
if t >= 0.0 and End_instructions.status == NOT_STARTED:
    # keep track of start time/frame for later
    End_instructions.tStart = t
    End_instructions.frameNStart = frameN  # exact frame index
    End_instructions.status = STARTED
    # keyboard checking is just starting
    win.callOnFlip(End_instructions.clock.reset)  # t=0 on next screen flip
    event.clearEvents(eventType='keyboard')
if End_instructions.status == STARTED:
    theseKeys = event.getKeys()
    
    # check for quit:
    if "escape" in theseKeys:
        endExpNow = True
    if len(theseKeys) > 0:  # at least one key was pressed
        End_instructions.keys = theseKeys[-1]  # just the last key pressed
        End_instructions.rt = End_instructions.clock.getTime()
        # a response ends the routine
        continueRoutine = False

# check if all components have finished
if not continueRoutine:  # a component has requested a forced-end of Routine
    break
continueRoutine = False  # will revert to True if at least one component still running
for thisComponent in Instructions1Components:
    if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
        continueRoutine = True
        break  # at least one component has not yet finished

# check for quit (the Esc key)
if endExpNow or event.getKeys(keyList=["escape"]):
    core.quit()

# refresh the screen
if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
    win.flip()

-------Ending Routine “Instructions1”-------

for thisComponent in Instructions1Components:
if hasattr(thisComponent, “setAutoDraw”):
thisComponent.setAutoDraw(False)

check responses

if End_instructions.keys in [’’, [], None]: # No response was made
End_instructions.keys=None
thisExp.addData(‘End_instructions.keys’,End_instructions.keys)
if End_instructions.keys != None: # we had a response
thisExp.addData(‘End_instructions.rt’, End_instructions.rt)
thisExp.nextEntry()

the Routine “Instructions1” was not non-slip safe, so reset the non-slip timer

routineTimer.reset()

set up handler to look after randomisation of conditions etc

Primary_task = data.TrialHandler(nReps=1, method=‘fullRandom’,
extraInfo=expInfo, originPath=-1,
trialList=data.importConditions(‘Batch1.xlsx’),
seed=None, name=‘Primary_task’)
thisExp.addLoop(Primary_task) # add the loop to the experiment
thisPrimary_task = Primary_task.trialList[0] # so we can initialise stimuli with some values

abbreviate parameter names if possible (e.g. rgb = thisPrimary_task.rgb)

if thisPrimary_task != None:
for paramName in thisPrimary_task.keys():
exec(paramName + ‘= thisPrimary_task.’ + paramName)

for thisPrimary_task in Primary_task:
currentLoop = Primary_task
# abbreviate parameter names if possible (e.g. rgb = thisPrimary_task.rgb)
if thisPrimary_task != None:
for paramName in thisPrimary_task.keys():
exec(paramName + ‘= thisPrimary_task.’ + paramName)

# ------Prepare to start Routine "Arithmetic_problem"-------
t = 0
Arithmetic_problemClock.reset()  # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat

Arithmetic.setText(Problem)
Reaction_time = event.BuilderKeyResponse()
# keep track of which components have finished
Arithmetic_problemComponents = [Fixation, Arithmetic, Reaction_time, S_MU, S_ML, S_LU, S_LL, S_RU, S_RL, imagered]
for thisComponent in Arithmetic_problemComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Arithmetic_problem"-------
while continueRoutine:
    # get current time
    t = Arithmetic_problemClock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    
    # *Fixation* updates
    if t >= 0.0 and Fixation.status == NOT_STARTED:
        # keep track of start time/frame for later
        Fixation.tStart = t
        Fixation.frameNStart = frameN  # exact frame index
        Fixation.setAutoDraw(True)
    frameRemains = 0.0 + 1- win.monitorFramePeriod * 0.75  # most of one frame period left
    if Fixation.status == STARTED and t >= frameRemains:
        Fixation.setAutoDraw(False)
    
    # *Arithmetic* updates
    if t >= 1 and Arithmetic.status == NOT_STARTED:
        # keep track of start time/frame for later
        Arithmetic.tStart = t
        Arithmetic.frameNStart = frameN  # exact frame index
        Arithmetic.setAutoDraw(True)
    
    # *Reaction_time* updates
    if t >= 1 and Reaction_time.status == NOT_STARTED:
        # keep track of start time/frame for later
        Reaction_time.tStart = t
        Reaction_time.frameNStart = frameN  # exact frame index
        Reaction_time.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(Reaction_time.clock.reset)  # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    if Reaction_time.status == STARTED:
        theseKeys = event.getKeys(keyList=['space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            if Reaction_time.keys == []:  # then this was the first keypress
                Reaction_time.keys = theseKeys[0]  # just the first key pressed
                Reaction_time.rt = Reaction_time.clock.getTime()
                # a response ends the routine
                continueRoutine = False
    
    # *S_MU* updates
    if t >= 0.0 and S_MU.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_MU.tStart = t
        S_MU.frameNStart = frameN  # exact frame index
        S_MU.setAutoDraw(True)
    if S_MU.status == STARTED:  # only update if drawing
        S_MU.setColor([1,1,1], colorSpace='rgb', log=False)
    
    # *S_ML* updates
    if t >= 0.0 and S_ML.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_ML.tStart = t
        S_ML.frameNStart = frameN  # exact frame index
        S_ML.setAutoDraw(True)
    
    # *S_LU* updates
    if t >= 0.0 and S_LU.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_LU.tStart = t
        S_LU.frameNStart = frameN  # exact frame index
        S_LU.setAutoDraw(True)
    
    # *S_LL* updates
    if t >= 0.0 and S_LL.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_LL.tStart = t
        S_LL.frameNStart = frameN  # exact frame index
        S_LL.setAutoDraw(True)
    
    # *S_RU* updates
    if t >= 0.0 and S_RU.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_RU.tStart = t
        S_RU.frameNStart = frameN  # exact frame index
        S_RU.setAutoDraw(True)
    
    # *S_RL* updates
    if t >= 0.0 and S_RL.status == NOT_STARTED:
        # keep track of start time/frame for later
        S_RL.tStart = t
        S_RL.frameNStart = frameN  # exact frame index
        S_RL.setAutoDraw(True)
    
    # *imagered* updates
    if t >= 0.0 and imagered.status == NOT_STARTED:
        # keep track of start time/frame for later
        imagered.tStart = t
        imagered.frameNStart = frameN  # exact frame index
        imagered.setAutoDraw(True)
    frameRemains = 0.0 + 1.0- win.monitorFramePeriod * 0.75  # most of one frame period left
    if imagered.status == STARTED and t >= frameRemains:
        imagered.setAutoDraw(False)
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Arithmetic_problemComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "Arithmetic_problem"-------
for thisComponent in Arithmetic_problemComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)

# check responses
if Reaction_time.keys in ['', [], None]:  # No response was made
    Reaction_time.keys=None
Primary_task.addData('Reaction_time.keys',Reaction_time.keys)
if Reaction_time.keys != None:  # we had a response
    Primary_task.addData('Reaction_time.rt', Reaction_time.rt)
# the Routine "Arithmetic_problem" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()

# ------Prepare to start Routine "Button1"-------
t = 0
Button1Clock.reset()  # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
Button_1 = event.BuilderKeyResponse()
# keep track of which components have finished
Button1Components = [Button_1]
for thisComponent in Button1Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Button1"-------
while continueRoutine:
    # get current time
    t = Button1Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *Button_1* updates
    if t >= 0.0 and Button_1.status == NOT_STARTED:
        # keep track of start time/frame for later
        Button_1.tStart = t
        Button_1.frameNStart = frameN  # exact frame index
        Button_1.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(Button_1.clock.reset)  # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    if Button_1.status == STARTED:
        theseKeys = event.getKeys()
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            Button_1.keys = theseKeys[-1]  # just the last key pressed
            Button_1.rt = Button_1.clock.getTime()
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Button1Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "Button1"-------
for thisComponent in Button1Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if Button_1.keys in ['', [], None]:  # No response was made
    Button_1.keys=None
Primary_task.addData('Button_1.keys',Button_1.keys)
if Button_1.keys != None:  # we had a response
    Primary_task.addData('Button_1.rt', Button_1.rt)
# the Routine "Button1" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()

# ------Prepare to start Routine "Button2"-------
t = 0
Button2Clock.reset()  # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
Button_2 = event.BuilderKeyResponse()
# keep track of which components have finished
Button2Components = [Button_2]
for thisComponent in Button2Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Button2"-------
while continueRoutine:
    # get current time
    t = Button2Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *Button_2* updates
    if t >= 0.0 and Button_2.status == NOT_STARTED:
        # keep track of start time/frame for later
        Button_2.tStart = t
        Button_2.frameNStart = frameN  # exact frame index
        Button_2.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(Button_2.clock.reset)  # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    if Button_2.status == STARTED:
        theseKeys = event.getKeys()
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            Button_2.keys = theseKeys[-1]  # just the last key pressed
            Button_2.rt = Button_2.clock.getTime()
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Button2Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "Button2"-------
for thisComponent in Button2Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if Button_2.keys in ['', [], None]:  # No response was made
    Button_2.keys=None
Primary_task.addData('Button_2.keys',Button_2.keys)
if Button_2.keys != None:  # we had a response
    Primary_task.addData('Button_2.rt', Button_2.rt)
# the Routine "Button2" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()

# ------Prepare to start Routine "Button3"-------
t = 0
Button3Clock.reset()  # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
Button_3 = event.BuilderKeyResponse()
# keep track of which components have finished
Button3Components = [Button_3]
for thisComponent in Button3Components:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Button3"-------
while continueRoutine:
    # get current time
    t = Button3Clock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *Button_3* updates
    if t >= 0.0 and Button_3.status == NOT_STARTED:
        # keep track of start time/frame for later
        Button_3.tStart = t
        Button_3.frameNStart = frameN  # exact frame index
        Button_3.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(Button_3.clock.reset)  # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    if Button_3.status == STARTED:
        theseKeys = event.getKeys(keyList=['return'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            Button_3.keys = theseKeys[-1]  # just the last key pressed
            Button_3.rt = Button_3.clock.getTime()
            # a response ends the routine
            continueRoutine = False
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in Button3Components:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "Button3"-------
for thisComponent in Button3Components:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if Button_3.keys in ['', [], None]:  # No response was made
    Button_3.keys=None
Primary_task.addData('Button_3.keys',Button_3.keys)
if Button_3.keys != None:  # we had a response
    Primary_task.addData('Button_3.rt', Button_3.rt)
# the Routine "Button3" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()

completed 1 repeats of ‘Primary_task’

these shouldn’t be strictly necessary (should auto-save)

thisExp.saveAsWideText(filename+’.csv’)
thisExp.saveAsPickle(filename)
logging.flush()

make sure everything is closed down

thisExp.abort() # or data files will save again on exit
win.close()
core.quit()""""

Hello Joanne,

A couple of things. Firstly, whenever you include code here, please format it like this, with three backticks both on the line above and a line below:

```python

#your code here
fact = "This is much more legible for a programmer."

```

It’s nearly illegible otherwise.

Also, posting the entire script is also going to scare off potential responders, because it’s way too much information.

So in your case, if you could upload a simple, minimal experiment (the .psyexp file) and a simple conditions file for people to play with, you’ll be more likely to get help.

Lastly, concerning using the builder and / or coder, it’s not a good idea to directly edit the _lastRun.py file, because every time you run your experiment from the builder this file will be erased and created anew. It is a very good idea to study this file however, so that you can understand how your selections in the builder are converted into code.

There are two ways to approach this:

  1. Use the builder, and add code components. Study the _lastrun.py file that this generates to see where this code is inserted. This is great because you don’t have to jump headfirst into programming everything, and much of the heavy lifting like data saving and stimulus presentation is largely handled for you.

  2. Use the coder. Obviously the most flexible option, but it comes at the price of requiring a lot more knowledge, work, and responsibility from you. (I say responsibility because you really have to know what you’re doing if reaction times with visual stimuli are important to you).

If you’re just starting out, I recommend the first route for a while, until it’s feasible to jump in with the coder yourself.

So upload some files we can mess with and I’m sure we’ll be able to help out.

Hi Joanne, Daniel is right. Stick with Builder, modifying behaviour via code inserted in a code component. Once you have reached a degree of confidence with coding, you might want to shift to coding the whole thing in a future experiment. But even many experienced users find there is an advantage to Builder taking care of the mundane stuff (as Daniel notes) and just adding some extra spice via code components.

My suggestion is that you should break up your trial as shown in the Arithmetic_problem screenshot above into two routines. In the first one, present the fixation target. In the second one, show the arithmetic problem for one second and seven squares (6 blank and one red) for one second.

Both routines should be surrounded by a loop (connected to your conditions file, that I guess defines the arithmetic problems and so on for each trial). But the second routine gets its own loop (i.e. nested within the outer loop but not including the fixation routine. This inner loop is not connected to the conditions file and is not marked as Is trials. What this means is that this routine only will run 6 times within each trial. i.e. the data from the conditions file will stay constant for all 6 repetitions (e.g. the arithmetic problem text).

To get the red quarter to move, you need to set up six locations for it, randomise them, and then select a new one on each of the iterations of the second routine.

i.e. put this in the Begin routine tab of a code component in the fixation routine, so that it only happens once per actual trial:

# list of positions that correspond to the positions of your blank squares:
red_locations = [(-0.5, 0.5), (0, 0.5), (0.5, 0.5), (-0.5, -0.5), (0, -0.5), (0.5, -0.5)]

# randomise their order:
shuffle(red_locations)

Then in the Begin routine tab of a code component in the arithmetic routine, so that it happens six times per trial:

# update the location of your red square stimulus with the next 
# randomised value:
red_stimulus.pos = red_locations.pop()

It is then probably best to handle the key press and mouse press in the Each frame tab of the code component in the arithmetic routine. When a key or button is pressed, you need to end the routine, and terminate the inner loop, and save whatever data you need to record in response.

1 Like

Hi Michael,

Thank you for a such a thorough reply. What you’ve said is partially what I am after however:

  1. From the code you have given, nothing seems to change after 1 second (?)

  2. I don’t know how many flashes of the red square I want - I want it to continue flashing randomly until the arithmetic problem has been solved.

Ideally, the experiment I want to run consists of two tasks being performed at the same time. In the first task, an arithmetic problem is presented which participants make a keyboard response to when they have solved it. At the same time, they are asked to response when a square that flashes red on the screen is the same as the one which flashed immediately before it (Condition A), or is the same as the one that flashed red twice before it (Condition B). The flashing task continues throughout the whole time period within the routine - so it is the length of the arithmetic routine that determines how many red flashes are played. I am completely stuck!