Hi there,
I am new to Psychopy (since Monday!) and do not have any Python experience, so am using Builder. I am using Win7,PsychoPy version 3.0.0b7.
I am trying to give feedback to participants after a trial regarding whether their response was correct or incorrect. However, at the moment, the feedback is always telling them that they are incorrect.
In my study, each trial involves two pictures being shown at the same time - a shape and label. Prior to the trial, participants are instructed that certain shapes are matched with certain labels (e.g., triangle = affected hand, circle = unaffected hand, square = other (strangers) hand). Then in the trials, if the two images that they see on the screen are a correct pairing, then they are to press â3â and if it is incorrect, then press â2â.
This is the way that I have my .xlsx spreadsheet set up:
Here is how I have things set-up in BuilderâŚ
Practice trials
Feedback:
Here are the settings for the response in the practice trial (Practice_Resp):
For the Picture_trial and the Label_trial, I have chosen âset every repeatâ and the Trials loop is ârandomâ, 1 rep, rows 0:60.
I followed a past thread about error in giving feedback (Error in giving feedback after a trial) which was very helpful and I tried all the suggestions - i.e., in case my excel CorAns values were being treated like integers instead of string variables.
Here is the output that I got when I ran the updated the program with the suggestions from the previous thread:
Running:
keys: <psychopy.event.BuilderKeyResponse object at 0x11940B50>
CorAns: 3
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x11944C30>
CorAns: 2
False
True
keys: <psychopy.event.BuilderKeyResponse object at 0x119470D0>
CorAns: 3
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x11947490>
CorAns: 2
False
True
keys: <psychopy.event.BuilderKeyResponse object at 0x119477B0>
CorAns: 3
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x119478D0>
CorAns: 3
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x11947AF0>
CorAns: 2
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x11947D10>
CorAns: 3
False
False
keys: <psychopy.event.BuilderKeyResponse object at 0x11944FF0>
CorAns: 2
False
True
keys: <psychopy.event.BuilderKeyResponse object at 0x119400D0>
CorAns: 2
False
True
This is clearly going wrong, but Iâm not quite sure what to fix! It seems like it is giving a separate true or false answer for each of my stimuli (shape picture and label picture), when I what I want is for it to give a true/false answer for the stimuli pair. I suppose this might be a problem with randomisation if the stimuli are not being presented as a pair (i.e., as one row in the excel spreadsheet) and instead are being randomly sampled from the column. However, I donât think this is the case as it was my understanding that using the set-up I have, the random function (loop) should randomly select a row. I am sure there are other problems too because I donât know why I am getting this output for key response (<psychopy.event.BuilderKeyResponse object at 0x119400D0>
This is what I have for the code component in my feedback routine:
if Practice_Resp == CorAns:
msg = âCorrectâ
else:
msg = âSorry, Incorrectâ
And this is what I have for my variable component (Practice_feedback_msg):
Last, here is what I get when I click on Compile Script:
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))
os.chdir(_thisDir)
Store info about the experiment session
expName = âCRPS_SPEtask_5_Jie_deg_setttingsâ # from the Builder filename that created this script
expInfo = {âparticipantâ: ââ, âRespHandâ: â[âleftâ, ârightâ]â, âShapelabelpairingâ: â[âAâ, âBâ, âCâ, âDâ, âEâ, âFâ]â, â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=âC:\Users\stantonr\Desktop\TASH\RESEARCH PROJECTS\Visit to Charles Spence Oxford\CRPS and SPE\CRPS SPE Experiment\CRPS_SPEtask_5_Jie_deg_setttings.pyâ,
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=[1920, 1080], 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 âShapelabelpairsâ
ShapelabelpairsClock = core.Clock()
imageShape = visual.ImageStim(
win=win, name=âimageShapeâ,
image=None, mask=None,
ori=0, pos=(0, 0), size=(0.5, 0.5),
color=[1,1,1], colorSpace=ârgbâ, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=0.0)
Initialize components for Routine âInstrTaskâ
InstrTaskClock = core.Clock()
InstrTask_2 = visual.TextStim(win=win, name=âInstrTask_2â,
text=âA key - LEFT index finger\nPress this if the shape and label MATCH\n\nQ key - LEFT middle finger\nPress this if the shape and label DO NOT MATCH\n\nPlease be as FAST and as ACCURATE as posssible.\n\nPress any button to begin\nâ,
font=âArialâ,
pos=(0, 0), height=0.07, wrapWidth=None, ori=0,
color=âwhiteâ, colorSpace=ârgbâ, opacity=1,
languageStyle=âLTRâ,
depth=0.0);
Initialize components for Routine âPracticetrialsâ
PracticetrialsClock = core.Clock()
Fix = visual.TextStim(win=win, name=âFixâ,
text=â+â,
font=âArialâ,
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,
color=âwhiteâ, colorSpace=ârgbâ, opacity=1,
languageStyle=âLTRâ,
depth=0.0);
Picture_trial = visual.ImageStim(
win=win, name=âPicture_trialâ,units=âdegâ,
image=âsinâ, mask=None,
ori=0, pos=(0, 3.5), size=(3.8, 3.8),
color=[1,1,1], colorSpace=ârgbâ, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-2.0)
Label_trial = visual.ImageStim(
win=win, name=âLabel_trialâ,units=âdegâ,
image=âsinâ, mask=None,
ori=0, pos=(0, -3.5), size=(6.3, 3.6),
color=[1,1,1], colorSpace=ârgbâ, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-3.0)
Initialize components for Routine âFeedbackâ
FeedbackClock = core.Clock()
#msg variable just needs some value at start
msg=âdohâ
Practice_feedback_msg = visual.TextStim(win=win, name=âPractice_feedback_msgâ,
text=âdefault textâ,
font=âArialâ,
pos=(0, 0), height=0.1, wrapWidth=None, ori=0,
color=âwhiteâ, colorSpace=ârgbâ, opacity=1,
languageStyle=âLTRâ,
depth=-1.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
------Prepare to start Routine âShapelabelpairsâ-------
t = 0
ShapelabelpairsClock.reset() # clock
frameN = -1
continueRoutine = True
update component parameters for each repeat
shapelabelpairs = event.BuilderKeyResponse()
keep track of which components have finished
ShapelabelpairsComponents = [imageShape, shapelabelpairs]
for thisComponent in ShapelabelpairsComponents:
if hasattr(thisComponent, âstatusâ):
thisComponent.status = NOT_STARTED
-------Start Routine âShapelabelpairsâ-------
while continueRoutine:
# get current time
t = ShapelabelpairsClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *imageShape* updates
if t >= 0.0 and imageShape.status == NOT_STARTED:
# keep track of start time/frame for later
imageShape.tStart = t
imageShape.frameNStart = frameN # exact frame index
imageShape.setAutoDraw(True)
frameRemains = 0.0 + 1.0- win.monitorFramePeriod * 0.75 # most of one frame period left
if imageShape.status == STARTED and t >= frameRemains:
imageShape.setAutoDraw(False)
# *shapelabelpairs* updates
if t >= 0.0 and shapelabelpairs.status == NOT_STARTED:
# keep track of start time/frame for later
shapelabelpairs.tStart = t
shapelabelpairs.frameNStart = frameN # exact frame index
shapelabelpairs.status = STARTED
# keyboard checking is just starting
win.callOnFlip(shapelabelpairs.clock.reset) # t=0 on next screen flip
event.clearEvents(eventType='keyboard')
if shapelabelpairs.status == STARTED:
theseKeys = event.getKeys()
# check for quit:
if "escape" in theseKeys:
endExpNow = True
if len(theseKeys) > 0: # at least one key was pressed
if shapelabelpairs.keys == []: # then this was the first keypress
shapelabelpairs.keys = theseKeys[0] # just the first key pressed
shapelabelpairs.rt = shapelabelpairs.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 ShapelabelpairsComponents:
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 âShapelabelpairsâ-------
for thisComponent in ShapelabelpairsComponents:
if hasattr(thisComponent, âsetAutoDrawâ):
thisComponent.setAutoDraw(False)
check responses
if shapelabelpairs.keys in [ââ, , None]: # No response was made
shapelabelpairs.keys=None
thisExp.addData(âshapelabelpairs.keysâ,shapelabelpairs.keys)
if shapelabelpairs.keys != None: # we had a response
thisExp.addData(âshapelabelpairs.rtâ, shapelabelpairs.rt)
thisExp.nextEntry()
the Routine âShapelabelpairsâ was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
------Prepare to start Routine âInstrTaskâ-------
t = 0
InstrTaskClock.reset() # clock
frameN = -1
continueRoutine = True
update component parameters for each repeat
key_resp_InstrTask = event.BuilderKeyResponse()
keep track of which components have finished
InstrTaskComponents = [InstrTask_2, key_resp_InstrTask]
for thisComponent in InstrTaskComponents:
if hasattr(thisComponent, âstatusâ):
thisComponent.status = NOT_STARTED
-------Start Routine âInstrTaskâ-------
while continueRoutine:
# get current time
t = InstrTaskClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *InstrTask_2* updates
if t >= 0.0 and InstrTask_2.status == NOT_STARTED:
# keep track of start time/frame for later
InstrTask_2.tStart = t
InstrTask_2.frameNStart = frameN # exact frame index
InstrTask_2.setAutoDraw(True)
# *key_resp_InstrTask* updates
if t >= 0.0 and key_resp_InstrTask.status == NOT_STARTED:
# keep track of start time/frame for later
key_resp_InstrTask.tStart = t
key_resp_InstrTask.frameNStart = frameN # exact frame index
key_resp_InstrTask.status = STARTED
# keyboard checking is just starting
event.clearEvents(eventType='keyboard')
if key_resp_InstrTask.status == STARTED:
theseKeys = event.getKeys()
# check for quit:
if "escape" in theseKeys:
endExpNow = True
if len(theseKeys) > 0: # at least one key was pressed
# 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 InstrTaskComponents:
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 âInstrTaskâ-------
for thisComponent in InstrTaskComponents:
if hasattr(thisComponent, âsetAutoDrawâ):
thisComponent.setAutoDraw(False)
the Routine âInstrTaskâ was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
set up handler to look after randomisation of conditions etc
Trials = data.TrialHandler(nReps=1, method=ârandomâ,
extraInfo=expInfo, originPath=-1,
trialList=data.importConditions(âConditions_2.xlsxâ, selection=â0:60â),
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 "Practicetrials"-------
t = 0
PracticetrialsClock.reset() # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
Practice_Resp = event.BuilderKeyResponse()
Picture_trial.setImage(Picture)
Label_trial.setImage(Label)
# keep track of which components have finished
PracticetrialsComponents = [Fix, Practice_Resp, Picture_trial, Label_trial]
for thisComponent in PracticetrialsComponents:
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# -------Start Routine "Practicetrials"-------
while continueRoutine:
# get current time
t = PracticetrialsClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *Fix* updates
if t >= 0.0 and Fix.status == NOT_STARTED:
# keep track of start time/frame for later
Fix.tStart = t
Fix.frameNStart = frameN # exact frame index
Fix.setAutoDraw(True)
# *Practice_Resp* updates
if t >= 0.0 and Practice_Resp.status == NOT_STARTED:
# keep track of start time/frame for later
Practice_Resp.tStart = t
Practice_Resp.frameNStart = frameN # exact frame index
Practice_Resp.status = STARTED
# keyboard checking is just starting
win.callOnFlip(Practice_Resp.clock.reset) # t=0 on next screen flip
event.clearEvents(eventType='keyboard')
if Practice_Resp.status == STARTED:
theseKeys = event.getKeys(keyList=['2', '3'])
# check for quit:
if "escape" in theseKeys:
endExpNow = True
if len(theseKeys) > 0: # at least one key was pressed
if Practice_Resp.keys == []: # then this was the first keypress
Practice_Resp.keys = theseKeys[0] # just the first key pressed
Practice_Resp.rt = Practice_Resp.clock.getTime()
# was this 'correct'?
if (Practice_Resp.keys == str(CorAns)) or (Practice_Resp.keys == CorAns):
Practice_Resp.corr = 1
else:
Practice_Resp.corr = 0
# a response ends the routine
continueRoutine = False
# *Picture_trial* updates
if t >= 1.0 and Picture_trial.status == NOT_STARTED:
# keep track of start time/frame for later
Picture_trial.tStart = t
Picture_trial.frameNStart = frameN # exact frame index
Picture_trial.setAutoDraw(True)
frameRemains = 1.0 + 0.20- win.monitorFramePeriod * 0.75 # most of one frame period left
if Picture_trial.status == STARTED and t >= frameRemains:
Picture_trial.setAutoDraw(False)
# *Label_trial* updates
if t >= 1.0 and Label_trial.status == NOT_STARTED:
# keep track of start time/frame for later
Label_trial.tStart = t
Label_trial.frameNStart = frameN # exact frame index
Label_trial.setAutoDraw(True)
frameRemains = 1.0 + 0.20- win.monitorFramePeriod * 0.75 # most of one frame period left
if Label_trial.status == STARTED and t >= frameRemains:
Label_trial.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 PracticetrialsComponents:
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 "Practicetrials"-------
for thisComponent in PracticetrialsComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
# check responses
if Practice_Resp.keys in ['', [], None]: # No response was made
Practice_Resp.keys=None
# was no response the correct answer?!
if str(CorAns).lower() == 'none':
Practice_Resp.corr = 1; # correct non-response
else:
Practice_Resp.corr = 0; # failed to respond (incorrectly)
# store data for Trials (TrialHandler)
Trials.addData('Practice_Resp.keys',Practice_Resp.keys)
Trials.addData('Practice_Resp.corr', Practice_Resp.corr)
if Practice_Resp.keys != None: # we had a response
Trials.addData('Practice_Resp.rt', Practice_Resp.rt)
# the Routine "Practicetrials" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
# ------Prepare to start Routine "Feedback"-------
t = 0
FeedbackClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(1.500000)
# update component parameters for each repeat
if Practice_Resp == CorAns:
msg = 'Correct'
else:
msg = 'Sorry, Incorrect'
print("keys: %r" %(Practice_Resp))
print("CorAns: %r" %(CorAns))
print(CorAns == Practice_Resp.keys)
print(str(CorAns) == Practice_Resp.keys)
Practice_feedback_msg.setText(msg)
# keep track of which components have finished
FeedbackComponents = [Practice_feedback_msg]
for thisComponent in FeedbackComponents:
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# -------Start Routine "Feedback"-------
while continueRoutine and routineTimer.getTime() > 0:
# get current time
t = FeedbackClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *Practice_feedback_msg* updates
if t >= 0.5 and Practice_feedback_msg.status == NOT_STARTED:
# keep track of start time/frame for later
Practice_feedback_msg.tStart = t
Practice_feedback_msg.frameNStart = frameN # exact frame index
Practice_feedback_msg.setAutoDraw(True)
frameRemains = 0.5 + 1.0- win.monitorFramePeriod * 0.75 # most of one frame period left
if Practice_feedback_msg.status == STARTED and t >= frameRemains:
Practice_feedback_msg.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 FeedbackComponents:
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 "Feedback"-------
for thisComponent in FeedbackComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
thisExp.nextEntry()
completed 1 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()
Sorry for the long message, but Iâve tried to provide as much detail as I can to assist with your answer!
Kind regards,
Tasha