# Associate conditions to trials without adding loops

**URL:** <https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425>\
**Category:** Coding\
**Created:** [April 26, 2018, 6:12am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425 "2018-04-26T06:12:13Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 26, 2018, 6:12am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/1 "2018-04-26T06:12:13Z")

</div>

**What are you trying to achieve?:**  
I’m trying to do a test where:

1. one word among six is first shown on the screen, and the candidate needs to hit one of two buttons (only one correct), and then
2. one image among six is shown, and the candidate needs to hit one of two buttons (only one correct).
3. This loop is repeated six times, until each of the six words and images have been selected (random mode).

**What did you try to make it work?:**  
I did the following code (corresponds to a builder of two sequential routines, one for the words, one for the images, and one loop with the conditions excel file associated):  
#!/usr/bin/env python

# -_- coding: utf-8 -_-

“”"  
This experiment was created using PsychoPy2 Experiment Builder (v1.90.1),  
on Thu Apr 26 16:05:08 2018  
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, sound, gui, visual, core, data, event, logging, clock  
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 = ‘finalversion’ # from the Builder filename that created this script  
expInfo = {‘session’: ‘001’, ‘participant’: ‘’}  
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=(1024, 768), 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 “Words”

WordsClock = core.Clock()  
WordStimuli = visual.TextStim(win=win, name=‘WordStimuli’,  
text=‘default text’,  
font=‘Arial’,  
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,  
color=‘black’, colorSpace=‘rgb’, opacity=1,  
depth=0.0);

# Initialize components for Routine “Images”

ImagesClock = core.Clock()  
ImageStimuli = visual.ImageStim(  
win=win, name=‘ImageStimuli’,units=‘cm’,  
image=‘sin’, mask=None,  
ori=0, pos=(0, 0), size=(6.35, 8.89),  
color=[1,1,1], colorSpace=‘rgb’, opacity=1,  
flipHoriz=False, flipVert=False,  
texRes=128, interpolate=True, depth=0.0)

# 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

# set up handler to look after randomisation of conditions etc

trials = data.TrialHandler(nReps=2, method=‘random’,  
extraInfo=expInfo, originPath=-1,  
trialList=data.importConditions(‘PsychoPyProgram/ConditionsBlock1.xlsx’),  
seed=None, name=‘trials’)  
thisExp.addLoop(trials) # add the loop to the experiment  
thisTrial = trials.trialList[0] # so we can initialise stimuli with some values

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

if thisTrial != None:  
for paramName in thisTrial:  
exec(’{} = thisTrial[paramName]’.format(paramName))

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

```
# ------Prepare to start Routine "Words"-------
t = 0
WordsClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(1.500000)
# update component parameters for each repeat
WordStimuli.setText(StimulusPresented)
WordResponse = event.BuilderKeyResponse()
# keep track of which components have finished
WordsComponents = [WordStimuli, WordResponse]
for thisComponent in WordsComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Words"-------
while continueRoutine and routineTimer.getTime() > 0:
    # get current time
    t = WordsClock.getTime()
    frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *WordStimuli* updates
    if t >= 0.0 and WordStimuli.status == NOT_STARTED:
        # keep track of start time/frame for later
        WordStimuli.tStart = t
        WordStimuli.frameNStart = frameN # exact frame index
        WordStimuli.setAutoDraw(True)
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if WordStimuli.status == STARTED and t >= frameRemains:
        WordStimuli.setAutoDraw(False)
    
    # *WordResponse* updates
    if t >= 0.0 and WordResponse.status == NOT_STARTED:
        # keep track of start time/frame for later
        WordResponse.tStart = t
        WordResponse.frameNStart = frameN # exact frame index
        WordResponse.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(WordResponse.clock.reset) # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if WordResponse.status == STARTED and t >= frameRemains:
        WordResponse.status = STOPPED
    if WordResponse.status == STARTED:
        theseKeys = event.getKeys(keyList=['e', 'i'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0: # at least one key was pressed
            if WordResponse.keys == []: # then this was the first keypress
                WordResponse.keys = theseKeys[0] # just the first key pressed
                WordResponse.rt = WordResponse.clock.getTime()
                # was this 'correct'?
                if (WordResponse.keys == str(AnswerStimulus)) or (WordResponse.keys == AnswerStimulus):
                    WordResponse.corr = 1
                else:
                    WordResponse.corr = 0
    
    # 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 WordsComponents:
        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 "Words"-------
for thisComponent in WordsComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if WordResponse.keys in ['', [], None]: # No response was made
    WordResponse.keys=None
    # was no response the correct answer?!
    if str(AnswerStimulus).lower() == 'none':
       WordResponse.corr = 1 # correct non-response
    else:
       WordResponse.corr = 0 # failed to respond (incorrectly)
# store data for trials (TrialHandler)
trials.addData('WordResponse.keys',WordResponse.keys)
trials.addData('WordResponse.corr', WordResponse.corr)
if WordResponse.keys != None: # we had a response
    trials.addData('WordResponse.rt', WordResponse.rt)

# ------Prepare to start Routine "Images"-------
t = 0
ImagesClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(1.500000)
# update component parameters for each repeat
ImageStimuli.setImage(ImagePresented)
ImageResponse = event.BuilderKeyResponse()
# keep track of which components have finished
ImagesComponents = [ImageStimuli, ImageResponse]
for thisComponent in ImagesComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "Images"-------
while continueRoutine and routineTimer.getTime() > 0:
    # get current time
    t = ImagesClock.getTime()
    frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *ImageStimuli* updates
    if t >= 0.0 and ImageStimuli.status == NOT_STARTED:
        # keep track of start time/frame for later
        ImageStimuli.tStart = t
        ImageStimuli.frameNStart = frameN # exact frame index
        ImageStimuli.setAutoDraw(True)
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if ImageStimuli.status == STARTED and t >= frameRemains:
        ImageStimuli.setAutoDraw(False)
    
    # *ImageResponse* updates
    if t >= 0.0 and ImageResponse.status == NOT_STARTED:
        # keep track of start time/frame for later
        ImageResponse.tStart = t
        ImageResponse.frameNStart = frameN # exact frame index
        ImageResponse.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(ImageResponse.clock.reset) # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if ImageResponse.status == STARTED and t >= frameRemains:
        ImageResponse.status = STOPPED
    if ImageResponse.status == STARTED:
        theseKeys = event.getKeys(keyList=['e', 'i'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0: # at least one key was pressed
            if ImageResponse.keys == []: # then this was the first keypress
                ImageResponse.keys = theseKeys[0] # just the first key pressed
                ImageResponse.rt = ImageResponse.clock.getTime()
                # was this 'correct'?
                if (ImageResponse.keys == str(AnswerImage)) or (ImageResponse.keys == AnswerImage):
                    ImageResponse.corr = 1
                else:
                    ImageResponse.corr = 0
    
    # 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 ImagesComponents:
        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 "Images"-------
for thisComponent in ImagesComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if ImageResponse.keys in ['', [], None]: # No response was made
    ImageResponse.keys=None
    # was no response the correct answer?!
    if str(AnswerImage).lower() == 'none':
       ImageResponse.corr = 1 # correct non-response
    else:
       ImageResponse.corr = 0 # failed to respond (incorrectly)
# store data for trials (TrialHandler)
trials.addData('ImageResponse.keys',ImageResponse.keys)
trials.addData('ImageResponse.corr', ImageResponse.corr)
if ImageResponse.keys != None: # we had a response
    trials.addData('ImageResponse.rt', ImageResponse.rt)
thisExp.nextEntry()

```

# completed 2 repeats of ‘trials’

# 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()

**What specifically went wrong when you tried that?:**  
Everything worked perfectly, except that: given that there is only one condition file, it always selects the word and then the Image of the same row of the Excel file associated to the conidtions. But I need that this choice is made completely randomly, i.e. that one random row is selected for the words routine, and then one random row is selected for the image routine. In other words, I would need to indicate specfic selection conditions to each of the two trials, without creating new loops. Is that possible?

---

<div class="post-metadata">

**Author:** ![jderrfuss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/jderrfuss/32/5245_2.png) [@jderrfuss](https://discourse.psychopy.org/u/jderrfuss)\
**Post date:** [April 26, 2018, 8:47pm UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/2 "2018-04-26T20:47:11Z")

</div>

Hi,

If you can live with your stimuli not being defined in the input file, the attached experiment might be one possible approach (the example is for three different stimuli per condition only, and both trials use text components).

I’d be curious to see other approaches though.

Jan

[two\_trials\_with\_random\_stimuli.psyexp](https://us1.discourse-cdn.com/flex002/uploads/psychopy/original/2X/6/63f84d66f6c29fd8789b31907ec23768a8fbcbf0.psyexp) (9.4 KB)

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 27, 2018, 9:23am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/3 "2018-04-27T09:23:48Z")

</div>

Wow that’s just amazing, didn’t think that it would be so easy!! Thank you so much!

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 27, 2018, 9:43am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/4 "2018-04-27T09:43:23Z")

</div>

However, still a question: How do I implement correct key responses now that differ in one trial? For example, in your program, how do I assign the ‘e’-key as correct response to the text ‘a’ and ‘b’, and the ‘i’-key as correct response to the text ‘c’?

---

<div class="post-metadata">

**Author:** ![jderrfuss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/jderrfuss/32/5245_2.png) [@jderrfuss](https://discourse.psychopy.org/u/jderrfuss)\
**Post date:** [April 27, 2018, 10:01am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/5 "2018-04-27T10:01:53Z")

</div>

I thought you might ask that question. 🙂 One possible solution is in the attached experiment.

Note that currently the stimulus/response information is written to the output file as a list, e.g. `['c', 'left']`. If you would like to have them separately, you can use the same approach that I used for presenting stimuli/determining the correct response, i.e. do something along these lines:

```auto
trials.addData("textA_stim", textA[trials.thisN][0])
trials.addData("textA_resp", textA[trials.thisN][1])

```

Jan

[two\_trials\_with\_random\_stimuli\_new.psyexp](https://us1.discourse-cdn.com/flex002/uploads/psychopy/original/2X/5/545302e92a35088d24c52425b5c00499b1084359.psyexp) (9.6 KB)

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 27, 2018, 10:21am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/6 "2018-04-27T10:21:26Z")

</div>

Hahahha amaziiing! Could you may tell me the following (sorry but the explanations for the builder online are not as good as for code commands, and you seem to be experienced). In the experiment I need to measure reaction times. If I insert a limit into the stimulus presentation and the key hit, the label color of the corresponding trial turns into green. This means that the reaction time is stored using the non-slip timing method, where the clock of the trial is compared to a global clock at each trial, to assure precise millisecond storage, is that correct? I just need to make sure that my exported reaction time results are not biaised by any errors associated to time calculations of my computer. Non-slip timing avoids that, is that correct or am I wrong?

---

<div class="post-metadata">

**Author:** ![jderrfuss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/jderrfuss/32/5245_2.png) [@jderrfuss](https://discourse.psychopy.org/u/jderrfuss)\
**Post date:** [April 27, 2018, 1:32pm UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/7 "2018-04-27T13:32:56Z")

</div>

> This means that the reaction time is stored using the non-slip timing method, where the clock of the trial is compared to a global clock at each trial, to assure precise millisecond storage, is that correct?

If I’m not mistaken, not really. The green colour means that the trial has a known endpoint in time. As a result of this, non-slip timing can be used. Non-slip timing ensures that your experiment timing doesn’t drift (see [here](http://www.psychopy.org/general/timing/nonSlipTiming.html) for more information on this). This is unrelated to how the RT is measured. With regard to this issue, you might want to have a look at the _Other questions about timing_ [here](http://www.psychopy.org/general/timing/timing.html).

Jan

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 27, 2018, 3:49pm UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/8 "2018-04-27T15:49:51Z")

</div>

Thanks again for your answer.

Alright, so this means that if my trials turn into green, I should calculate the number of frames present for my machine and its frame rate (60 Hz -\> 16.67 ms / frame flip) and indicate the stimulus presentation times in frames rather than seconds to be heavily precise and to assure that each stimuli is presented for the exact same amount of time, namely for the exact same amount of frames (I verified with the demo that there were no frames dropping in my machine). In other words, stimuli onset in the builder will be set to 0 frames. stimuli stop (I want it to be as close possible to 1500 ms) is thus 1500 ms / 16.6667 = about 90 -\> stimuli stop at frame number 90. Like this, it will be assured that the stimuli are all presented for the exact same period, true? Or does the builder do exact presentation timing automatically when a trial gets green / does the program automatically implement non-slip timing for trials with an endpoint?

In terms of RT measurement, I’m aware of errors associated to external factors as keyboard response latencies, human behaviour, etc., as stated in the link you send me. I only need to be able to compare the response latencies in between them, and thus need to assure that the only variations of the response latencies are associated to hardware or other external factors, rather than to variations in reaction time measurements by the program. Not sure if you know what I mean here. In other words, is Psychopy measuring the RT always in the same way over all trials in one experiment over several blocks, or is there a certain shift present in RT measurements, for example if you compare trial #1 with trial #1000? Is it maybe more precise to return the RT with frame numbers, converting it back to milliseconds for the output?

Thanks for your help, really!

---

<div class="post-metadata">

**Author:** ![jderrfuss](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.psychopy.org/jderrfuss/32/5245_2.png) [@jderrfuss](https://discourse.psychopy.org/u/jderrfuss)\
**Post date:** [April 27, 2018, 6:58pm UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/9 "2018-04-27T18:58:17Z")

</div>

A few comments (I would suggest that you also spend some time searching the forum as I’m pretty sure that similar questions have been asked in the past; if not, it might be preferable to start a new topic):

- Yes, you will get the most precise stimulus timing with frames. (But does one frame more or less really matter for a stimulus that is presented for 1500 ms?)
- Yes, the Builder automatically implements non-slip timing for trials with a known endpoint - but I suspect you misinterpret what exactly non-slip timing does. Put simply, non-slip timing corrects overshoots when stimulus presentation is time-based (to avoid an accrual of these overshoots over the course of the experiment - a major issue for fMRI). It does not actually play a role when stimulus presentation is frame-based. And, as mentioned before, it has nothing to do with your RT measurement.
- Yes, PsychoPy should always measure the RT in the same way, even after many trials.

Jan

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 28, 2018, 4:44am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/10 "2018-04-28T04:44:17Z")

</div>

Thank you so much, that’s all I need to know! Sorry for taking so much of your time!

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 28, 2018, 2:59pm UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/11 "2018-04-28T14:59:55Z")

</div>

Sorry to bother you again, but I just can’t find out the following:

- show a ‘Wrong’ Message on the screen, below the shown stimulus, if the wrong response key was hitten (for 200ms). (Instant feedback). I tried to do a conditional TextStimuli, but I don’t get how I need to set the conditions. I want to avoid to make an additional trial just for the feedback as in the demo provided, becuase this just adds another trial in my experiment already full of trials.
- show a ‘Too Slow’ Message on the screen, on top of the stimulus, if no key has been pushed in the first 800ms. Same problem as on top.
- Repeat an entire practice trial if more than 50% of the provided key responses during that same practice trial were wrong, or if more than 50% of the provided key responses were too slow.

Could you may help me out here again?

---

<div class="post-metadata">

**Author:** ![HelloHello](https://avatars.discourse-cdn.com/v4/letter/h/898d66/32.png) [@HelloHello](https://discourse.psychopy.org/u/HelloHello)\
**Post date:** [April 29, 2018, 4:54am UTC](https://discourse.psychopy.org/t/associate-conditions-to-trials-without-adding-loops/4425/12 "2018-04-29T04:54:06Z")

</div>

Okay so I figured out how to implement the instant error message, that’s done.  
The Too Slow Message is also implemented in the code below, but here’s the problem: The Too Slow Message shows up at right timing, but it shows up even if a key was hit previously, The message should however only show up if no key was hitten until 800ms of each trial.

Code: (Basically, you only need to focus only on lines 185-191, it must be adapted somewhere there I guess).

#!/usr/bin/env python

# -_- coding: utf-8 -_-

“”"  
This experiment was created using PsychoPy2 Experiment Builder (v1.90.1),  
on Sun Apr 29 13:13:45 2018  
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, sound, gui, visual, core, data, event, logging, clock  
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 = u’Instant\_Errormessage’ # from the Builder filename that created this script  
expInfo = {u’session’: u’001’, u’participant’: u’’}  
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=[2560, 1440], 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 “trial”

trialClock = core.Clock()  
text = visual.TextStim(win=win, name=‘text’,  
text=‘default text’,  
font=u’Arial’,  
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,  
color=u’white’, colorSpace=‘rgb’, opacity=1,  
depth=0.0);  
textA = [[“a”, “space”], [“b”, “space”], [“c”, “space”]]

shuffle(textA)

bg\_Question = visual.TextStim(win,  
text = “IS THIS RELATED TO YOUR STIMULI?”, pos = (0,0.85),  
color = u’black’)

bg\_YES = visual.TextStim(win,  
text = “e=YES”, pos = (-0.85,0.75), color = u’green’)

bg\_NO = visual.TextStim(win,  
text = “e=YES”, pos = (0.85,0.75), color = u’green’)

bg\_Question.autoDraw = True  
bg\_YES.autoDraw = True  
bg\_NO.autoDraw = True

errormsg = visual.TextStim(win, text = ‘WRONG!’,color = u’red’, pos = (0,-0.5))  
tsmsg = visual.TextStim(win, text = ‘TOO SLOW!’, color = u’red’, pos = (0,0.4))

# 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

# set up handler to look after randomisation of conditions etc

trials = data.TrialHandler(nReps=3, method=‘sequential’,  
extraInfo=expInfo, originPath=-1,  
trialList=[None],  
seed=None, name=‘trials’)  
thisExp.addLoop(trials) # add the loop to the experiment  
thisTrial = trials.trialList[0] # so we can initialise stimuli with some values

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

if thisTrial != None:  
for paramName in thisTrial:  
exec(’{} = thisTrial[paramName]’.format(paramName))

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

```
# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(1.500000)
# update component parameters for each repeat
text.setText(textA[trials.thisN][0])
key_resp_2 = event.BuilderKeyResponse()
trials.addData("textA", textA[trials.thisN])
# keep track of which components have finished
trialComponents = [text, key_resp_2]
for thisComponent in trialComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "trial"-------
while continueRoutine and routineTimer.getTime() > 0:
    # get current time
    t = trialClock.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)
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if text.status == STARTED and t >= frameRemains:
        text.setAutoDraw(False)
    
    # *key_resp_2* updates
    if t >= 0.0 and key_resp_2.status == NOT_STARTED:
        # keep track of start time/frame for later
        key_resp_2.tStart = t
        key_resp_2.frameNStart = frameN # exact frame index
        key_resp_2.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(key_resp_2.clock.reset) # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    frameRemains = 0.0 + 1.5- win.monitorFramePeriod * 0.75 # most of one frame period left
    if key_resp_2.status == STARTED and t >= frameRemains:
        key_resp_2.status = STOPPED
    if key_resp_2.status == STARTED:
        theseKeys = event.getKeys(keyList=['e', 'i', 'space'])
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0: # at least one key was pressed
            if key_resp_2.keys == []: # then this was the first keypress
                key_resp_2.keys = theseKeys[0] # just the first key pressed
                key_resp_2.rt = key_resp_2.clock.getTime()
                # was this 'correct'?
                if (key_resp_2.keys == str(textA[trials.thisN][1])) or (key_resp_2.keys == textA[trials.thisN][1]):
                    key_resp_2.corr = 1
                else:
                    key_resp_2.corr = 0
                    ErrorTimer = core.CountdownTimer(0.4)
                    while ErrorTimer.getTime() > 0:
                        errormsg.setAutoDraw(True)
                        win.flip()
                    errormsg.setAutoDraw(False)
                    win.flip()
        if len(theseKeys) == 0 and t > 0.8 :
            TooSlowTimer = core.CountdownTimer(0.4)
            while TooSlowTimer.getTime() > 0:
                tsmsg.setAutoDraw(True)
                win.flip()
            tsmsg.setAutoDraw(False)
            win.flip()
    # 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 trialComponents:
        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 "trial"-------
for thisComponent in trialComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if key_resp_2.keys in ['', [], None]: # No response was made
    key_resp_2.keys=None
    # was no response the correct answer?!
    if str(textA[trials.thisN][1]).lower() == 'none':
       key_resp_2.corr = 1 # correct non-response
    else:
       key_resp_2.corr = 0 # failed to respond (incorrectly)
# store data for trials (TrialHandler)
trials.addData('key_resp_2.keys',key_resp_2.keys)
trials.addData('key_resp_2.corr', key_resp_2.corr)
if key_resp_2.keys != None: # we had a response
    trials.addData('key_resp_2.rt', key_resp_2.rt)

thisExp.nextEntry()

```

# completed 3 repeats of ‘trials’

# 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()
