Hi all.
I am really new to Psychopy and Python and have to code a risk decision making task using Psychopy (variation of Balloon Analogue Risk Task). My task basically asks participants to click on any one of three rectangles (left/mid/rightButton) on free trials, or the correct one on forced trials. The choice availability is indicated with the rectangle’s colour turning yellow. The tricky bit is that, like inflating a balloon, we ask them to hold on the mouse instead of just clicking on the rectangle they want, and the longer they hold it, the bigger the potential reward, but also the bigger the chance of losing all reward (each rectangle has a different rate of reward/risk incrementation). I managed to get the appearance and trial conditions of the 3 stages of my study (between trial waiting - trial - reward (if won)) set up alright with builder but now got really stuck after I go into coding the bit where I determine reward/risk outcomes. I checked that the bit of code I wrote for determining if the choice (‘anyclick’) made was correct (esp for forced trials), and I think until then the code works fine. But whenever I attempt to add in timer to time the duration of the mouse click, the program seems to be stuck between/within loops. I have made versions after versions to try to find the problem in my loops, but maybe it is just because my code is way too complex and inefficient.
Here is the failed code - with my print commands I find it is stuck and only printed ‘step 1’ (previous attempts I have also gotten infinite loop between step 2 and 4, step 2 and 8)
(I think I should use while loop before ‘if buttons != prevButtonState:’ to track mouse click/release, but somehow the programmed still get stuck and only printed ‘step1’). Would really appreciate any comments or suggestions! Thank you in advance.
-------Run Routine “trial”-------
while continueRoutine:
# get current time
t = trialClock.getTime()
tThisFlip = win.getFutureFlipTime(clock=trialClock)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *leftbutton* updates
if leftbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
leftbutton.frameNStart = frameN # exact frame index
leftbutton.tStart = t # local t and not account for scr refresh
leftbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(leftbutton, 'tStartRefresh') # time at next scr refresh
leftbutton.setAutoDraw(True)
# *midbutton* updates
if midbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
midbutton.frameNStart = frameN # exact frame index
midbutton.tStart = t # local t and not account for scr refresh
midbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(midbutton, 'tStartRefresh') # time at next scr refresh
midbutton.setAutoDraw(True)
# *rightbutton* updates
if rightbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
rightbutton.frameNStart = frameN # exact frame index
rightbutton.tStart = t # local t and not account for scr refresh
rightbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(rightbutton, 'tStartRefresh') # time at next scr refresh
rightbutton.setAutoDraw(True)
# *anyclick* updates
if anyclick.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
anyclick.frameNStart = frameN # exact frame index
anyclick.tStart = t # local t and not account for scr refresh
anyclick.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(anyclick, 'tStartRefresh') # time at next scr refresh
anyclick.status = STARTED
anyclick.mouseClock.reset()
prevButtonState = anyclick.getPressed() # if button is down already this ISN'T a new click
if anyclick.status == STARTED: # only update if started and not finished!
x, y = anyclick.getPos()
anyclick.x.append(x)
anyclick.y.append(y)
buttons = anyclick.getPressed()
anyclick.leftButton.append(buttons[0])
anyclick.midButton.append(buttons[1])
anyclick.rightButton.append(buttons[2])
gotclick=False
gotValidClick=False
unclicked=False
Attempt1=True
print("step1")
if buttons != prevButtonState: # button state changed?
prevButtonState = buttons
if sum(buttons) > 0:
t0=time.clock()
gotValidClick = False
gotclick = True
print("step2")
if sum(buttons) == 0 and gotclick == True:
t1=time.clock()
tpoke=t1-t0
unclicked = True
pokeduration = visual.TextStim(win=win, name='poke duration',
text=str(tpoke),
font='Arial',
units='norm', pos=(0, 0), height=0.07, wrapWidth=None, ori=0,
color='white', colorSpace='rgb', opacity=1,
languageStyle='LTR',
depth=0.0);
pokeduration.setAutoDraw(True)
print("step3:"+tpoke)
while gotclick == True and gotValidClick == False:
if thisTrial['contingency']=='ll':
for obj in LLcorAns:
if obj.contains(anyclick):
gotValidClick = True
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
print("step4")
break
else:
gotValidClick = False
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
print("step5")
continue
break
if thisTrial['contingency']=='mm':
for obj in MMcorAns:
if obj.contains(anyclick):
gotValidClick = True
flag=False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
print("step6")
break
else:
gotValidClick = False
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
print("step7")
continue
break
if thisTrial['contingency']=='hh':
for obj in HHcorAns:
if obj.contains(anyclick):
gotValidClick = True
flag=False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
print("step8")
break
else:
gotValidClick = False
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
print("step9")
continue
break
if thisTrial['contingency']=='free':
for obj in FFcorAns:
if obj.contains(anyclick):
gotValidClick = True
flag=False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
print("step10")
break
else:
gotValidClick = False
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
print("step11")
continue
break
while True:
if gotValidClick == True and unclicked == True:
print("step12")
continueRoutine = False
break
# *collectbutton* updates
if collectbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
collectbutton.frameNStart = frameN # exact frame index
collectbutton.tStart = t # local t and not account for scr refresh
collectbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(collectbutton, 'tStartRefresh') # time at next scr refresh
collectbutton.setAutoDraw(True)
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# 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
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
Here is a code for trial that worked without the timing feature.
# -------Run Routine "trial"-------
while continueRoutine:
# get current time
t = trialClock.getTime()
tThisFlip = win.getFutureFlipTime(clock=trialClock)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *leftbutton* updates
if leftbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
leftbutton.frameNStart = frameN # exact frame index
leftbutton.tStart = t # local t and not account for scr refresh
leftbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(leftbutton, 'tStartRefresh') # time at next scr refresh
leftbutton.setAutoDraw(True)
# *midbutton* updates
if midbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
midbutton.frameNStart = frameN # exact frame index
midbutton.tStart = t # local t and not account for scr refresh
midbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(midbutton, 'tStartRefresh') # time at next scr refresh
midbutton.setAutoDraw(True)
# *rightbutton* updates
if rightbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
rightbutton.frameNStart = frameN # exact frame index
rightbutton.tStart = t # local t and not account for scr refresh
rightbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(rightbutton, 'tStartRefresh') # time at next scr refresh
rightbutton.setAutoDraw(True)
# *anyclick* updates
if anyclick.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
anyclick.frameNStart = frameN # exact frame index
anyclick.tStart = t # local t and not account for scr refresh
anyclick.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(anyclick, 'tStartRefresh') # time at next scr refresh
anyclick.status = STARTED
anyclick.mouseClock.reset()
prevButtonState = anyclick.getPressed() # if button is down already this ISN'T a new click
if anyclick.status == STARTED: # only update if started and not finished!
x, y = anyclick.getPos()
anyclick.x.append(x)
anyclick.y.append(y)
buttons = anyclick.getPressed()
anyclick.leftButton.append(buttons[0])
anyclick.midButton.append(buttons[1])
anyclick.rightButton.append(buttons[2])
buttons = anyclick.getPressed()
if buttons != prevButtonState: # button state changed?
prevButtonState = buttons
if sum(buttons) > 0: # state changed to a new click
# check if the mouse was inside our 'clickable' objects
gotValidClick = False
if thisTrial['contingency']=='ll':
for obj in LLcorAns:
if obj.contains(anyclick):
gotValidClick = True
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
else:
gotValidClick = False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
elif thisTrial['contingency']=='mm':
for obj in MMcorAns:
if obj.contains(anyclick):
gotValidClick = True
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
else:
gotValidClick = False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
elif thisTrial['contingency']=='hh':
for obj in HHcorAns:
if obj.contains(anyclick):
gotValidClick = True
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
else:
gotValidClick = False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
elif thisTrial['contingency']=='free':
for obj in FFcorAns:
if obj.contains(anyclick):
gotValidClick = True
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
correct.append(obj.name)
correcttime.append(anyclick.mouseClock.getTime())
else:
gotValidClick = False
anyclick.clicked_name.append(obj.name)
anyclick.clicked_pos.append(obj.pos)
anyclick.time.append(anyclick.mouseClock.getTime())
incorrect.append(obj.name)
incorrecttime.append(anyclick.mouseClock.getTime())
if gotValidClick: # abort routine on response
continueRoutine = False
# *collectbutton* updates
if collectbutton.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
collectbutton.frameNStart = frameN # exact frame index
collectbutton.tStart = t # local t and not account for scr refresh
collectbutton.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(collectbutton, 'tStartRefresh') # time at next scr refresh
collectbutton.setAutoDraw(True)
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# 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
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()