diff --git a/three-back.psyexp b/three-back.psyexp index 64a6a3c375e6b27d4212784a2a9ab663b645808d..2548f61362a1968a0efd3a75af9ff93a6cf3e9f8 100644 --- a/three-back.psyexp +++ b/three-back.psyexp @@ -49,7 +49,7 @@ <Param name="saveStartStop" updates="None" val="True" valType="bool"/> <Param name="startEstim" updates="None" val="" valType="code"/> <Param name="startType" updates="None" val="time (s)" valType="str"/> - <Param name="startVal" updates="None" val="2" valType="code"/> + <Param name="startVal" updates="None" val="0" valType="code"/> <Param name="stopType" updates="None" val="duration (s)" valType="str"/> <Param name="stopVal" updates="constant" val="0.03" valType="code"/> <Param name="syncScreenRefresh" updates="None" val="True" valType="bool"/> @@ -57,9 +57,72 @@ <Param name="units" updates="None" val="from exp settings" valType="str"/> <Param name="wrapWidth" updates="constant" val="" valType="code"/> </TextComponent> + <KeyboardComponent name="key_resp"> + <Param name="allowedKeys" updates="constant" val="'space'" valType="code"/> + <Param name="correctAns" updates="constant" val="" valType="str"/> + <Param name="disabled" updates="None" val="False" valType="bool"/> + <Param name="discard previous" updates="constant" val="True" valType="bool"/> + <Param name="durationEstim" updates="None" val="" valType="code"/> + <Param name="forceEndRoutine" updates="constant" val="False" valType="bool"/> + <Param name="name" updates="None" val="key_resp" valType="code"/> + <Param name="saveStartStop" updates="None" val="True" valType="bool"/> + <Param name="startEstim" updates="None" val="" valType="code"/> + <Param name="startType" updates="None" val="time (s)" valType="str"/> + <Param name="startVal" updates="None" val="0.0" valType="code"/> + <Param name="stopType" updates="None" val="duration (s)" valType="str"/> + <Param name="stopVal" updates="constant" val="2" valType="code"/> + <Param name="store" updates="constant" val="last key" valType="str"/> + <Param name="storeCorrect" updates="constant" val="True" valType="bool"/> + <Param name="syncScreenRefresh" updates="constant" val="True" valType="bool"/> + </KeyboardComponent> + </Routine> + <Routine name="Instructions"> + <TextComponent name="instructions"> + <Param name="color" updates="constant" val="white" valType="str"/> + <Param name="colorSpace" updates="constant" val="rgb" valType="str"/> + <Param name="disabled" updates="None" val="False" valType="bool"/> + <Param name="durationEstim" updates="None" val="" valType="code"/> + <Param name="flip" updates="constant" val="" valType="str"/> + <Param name="font" updates="constant" val="Arial" valType="str"/> + <Param name="languageStyle" updates="None" val="LTR" valType="str"/> + <Param name="letterHeight" updates="constant" val="2.4" valType="code"/> + <Param name="name" updates="None" val="instructions" valType="code"/> + <Param name="opacity" updates="constant" val="1" valType="code"/> + <Param name="ori" updates="constant" val="0" valType="code"/> + <Param name="pos" updates="constant" val="(0, 0)" valType="code"/> + <Param name="saveStartStop" updates="None" val="True" valType="bool"/> + <Param name="startEstim" updates="None" val="" valType="code"/> + <Param name="startType" updates="None" val="time (s)" valType="str"/> + <Param name="startVal" updates="None" val="0.0" valType="code"/> + <Param name="stopType" updates="None" val="condition" valType="str"/> + <Param name="stopVal" updates="constant" val="False" valType="code"/> + <Param name="syncScreenRefresh" updates="None" val="True" valType="bool"/> + <Param name="text" updates="constant" val="Press SPACE to start" valType="str"/> + <Param name="units" updates="None" val="from exp settings" valType="str"/> + <Param name="wrapWidth" updates="constant" val="" valType="code"/> + </TextComponent> + <KeyboardComponent name="key_start"> + <Param name="allowedKeys" updates="constant" val="'space'" valType="code"/> + <Param name="correctAns" updates="constant" val="" valType="str"/> + <Param name="disabled" updates="None" val="False" valType="bool"/> + <Param name="discard previous" updates="constant" val="False" valType="bool"/> + <Param name="durationEstim" updates="None" val="" valType="code"/> + <Param name="forceEndRoutine" updates="constant" val="True" valType="bool"/> + <Param name="name" updates="None" val="key_start" valType="code"/> + <Param name="saveStartStop" updates="None" val="True" valType="bool"/> + <Param name="startEstim" updates="None" val="" valType="code"/> + <Param name="startType" updates="None" val="time (s)" valType="str"/> + <Param name="startVal" updates="None" val="0.0" valType="code"/> + <Param name="stopType" updates="None" val="duration (s)" valType="str"/> + <Param name="stopVal" updates="constant" val="" valType="code"/> + <Param name="store" updates="constant" val="last key" valType="str"/> + <Param name="storeCorrect" updates="constant" val="False" valType="bool"/> + <Param name="syncScreenRefresh" updates="constant" val="False" valType="bool"/> + </KeyboardComponent> </Routine> </Routines> <Flow> + <Routine name="Instructions"/> <LoopInitiator loopType="TrialHandler" name="trials"> <Param name="Selected rows" updates="None" val="" valType="str"/> <Param name="conditions" updates="None" val="None" valType="str"/> diff --git a/three-back_lastrun.py b/three-back_lastrun.py index ac5c32cd2a4eece8ccd02be3ddc358eec2e22f5d..54ca775f6a09e1f2415cf942195d3c3899a89dd3 100644 --- a/three-back_lastrun.py +++ b/three-back_lastrun.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ This experiment was created using PsychoPy3 Experiment Builder (v3.2.0), - on November 04, 2019, at 11:23 + on November 04, 2019, at 11:31 If you publish work using this script the most relevant publication is: Peirce J, Gray JR, Simpson S, MacAskill M, Höchenberger R, Sogo H, Kastman E, Lindeløv JK. (2019) @@ -78,6 +78,17 @@ else: # create a default keyboard (e.g. to check for escape) defaultKeyboard = keyboard.Keyboard() +# Initialize components for Routine "Instructions" +InstructionsClock = core.Clock() +instructions = visual.TextStim(win=win, name='instructions', + text='Press SPACE to start', + font='Arial', + pos=(0, 0), height=2.4, wrapWidth=None, ori=0, + color='white', colorSpace='rgb', opacity=1, + languageStyle='LTR', + depth=0.0); +key_start = keyboard.Keyboard() + # Initialize components for Routine "trial" trialClock = core.Clock() letter = visual.TextStim(win=win, name='letter', @@ -87,11 +98,115 @@ letter = visual.TextStim(win=win, name='letter', color='white', colorSpace='rgb', opacity=1, languageStyle='LTR', depth=0.0); +key_resp = keyboard.Keyboard() # 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 "Instructions"------- +# update component parameters for each repeat +key_start.keys = [] +key_start.rt = [] +# keep track of which components have finished +InstructionsComponents = [instructions, key_start] +for thisComponent in InstructionsComponents: + thisComponent.tStart = None + thisComponent.tStop = None + thisComponent.tStartRefresh = None + thisComponent.tStopRefresh = None + if hasattr(thisComponent, 'status'): + thisComponent.status = NOT_STARTED +# reset timers +t = 0 +_timeToFirstFrame = win.getFutureFlipTime(clock="now") +InstructionsClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip +frameN = -1 +continueRoutine = True + +# -------Run Routine "Instructions"------- +while continueRoutine: + # get current time + t = InstructionsClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=InstructionsClock) + tThisFlipGlobal = win.getFutureFlipTime(clock=None) + frameN = frameN + 1 # number of completed frames (so 0 is the first frame) + # update/draw components on each frame + + # *instructions* updates + if instructions.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + instructions.frameNStart = frameN # exact frame index + instructions.tStart = t # local t and not account for scr refresh + instructions.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(instructions, 'tStartRefresh') # time at next scr refresh + instructions.setAutoDraw(True) + if instructions.status == STARTED: + if bool(False): + # keep track of stop time/frame for later + instructions.tStop = t # not accounting for scr refresh + instructions.frameNStop = frameN # exact frame index + win.timeOnFlip(instructions, 'tStopRefresh') # time at next scr refresh + instructions.setAutoDraw(False) + + # *key_start* updates + if key_start.status == NOT_STARTED and t >= 0.0-frameTolerance: + # keep track of start time/frame for later + key_start.frameNStart = frameN # exact frame index + key_start.tStart = t # local t and not account for scr refresh + key_start.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(key_start, 'tStartRefresh') # time at next scr refresh + key_start.status = STARTED + # keyboard checking is just starting + key_start.clock.reset() # now t=0 + if key_start.status == STARTED: + theseKeys = key_start.getKeys(keyList=['space'], waitRelease=False) + if len(theseKeys): + theseKeys = theseKeys[0] # at least one key was pressed + + # check for quit: + if "escape" == theseKeys: + endExpNow = True + key_start.keys = theseKeys.name # just the last key pressed + key_start.rt = theseKeys.rt + # a response ends the routine + continueRoutine = False + + # 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 InstructionsComponents: + 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() + +# -------Ending Routine "Instructions"------- +for thisComponent in InstructionsComponents: + if hasattr(thisComponent, "setAutoDraw"): + thisComponent.setAutoDraw(False) +thisExp.addData('instructions.started', instructions.tStartRefresh) +thisExp.addData('instructions.stopped', instructions.tStopRefresh) +# check responses +if key_start.keys in ['', [], None]: # No response was made + key_start.keys = None +thisExp.addData('key_start.keys',key_start.keys) +if key_start.keys != None: # we had a response + thisExp.addData('key_start.rt', key_start.rt) +thisExp.addData('key_start.started', key_start.tStart) +thisExp.addData('key_start.stopped', key_start.tStop) +thisExp.nextEntry() +# the Routine "Instructions" 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=20, method='random', extraInfo=expInfo, originPath=-1, @@ -112,11 +227,13 @@ for thisTrial in trials: exec('{} = thisTrial[paramName]'.format(paramName)) # ------Prepare to start Routine "trial"------- - routineTimer.add(2.030000) + routineTimer.add(2.000000) # update component parameters for each repeat letter.setText('a') + key_resp.keys = [] + key_resp.rt = [] # keep track of which components have finished - trialComponents = [letter] + trialComponents = [letter, key_resp] for thisComponent in trialComponents: thisComponent.tStart = None thisComponent.tStop = None @@ -141,7 +258,7 @@ for thisTrial in trials: # update/draw components on each frame # *letter* updates - if letter.status == NOT_STARTED and tThisFlip >= 2-frameTolerance: + if letter.status == NOT_STARTED and tThisFlip >= 0-frameTolerance: # keep track of start time/frame for later letter.frameNStart = frameN # exact frame index letter.tStart = t # local t and not account for scr refresh @@ -157,6 +274,43 @@ for thisTrial in trials: win.timeOnFlip(letter, 'tStopRefresh') # time at next scr refresh letter.setAutoDraw(False) + # *key_resp* updates + waitOnFlip = False + if key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + key_resp.frameNStart = frameN # exact frame index + key_resp.tStart = t # local t and not account for scr refresh + key_resp.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(key_resp, 'tStartRefresh') # time at next scr refresh + key_resp.status = STARTED + # keyboard checking is just starting + waitOnFlip = True + win.callOnFlip(key_resp.clock.reset) # t=0 on next screen flip + win.callOnFlip(key_resp.clearEvents, eventType='keyboard') # clear events on next screen flip + if key_resp.status == STARTED: + # is it time to stop? (based on global clock, using actual start) + if tThisFlipGlobal > key_resp.tStartRefresh + 2-frameTolerance: + # keep track of stop time/frame for later + key_resp.tStop = t # not accounting for scr refresh + key_resp.frameNStop = frameN # exact frame index + win.timeOnFlip(key_resp, 'tStopRefresh') # time at next scr refresh + key_resp.status = FINISHED + if key_resp.status == STARTED and not waitOnFlip: + theseKeys = key_resp.getKeys(keyList=['space'], waitRelease=False) + if len(theseKeys): + theseKeys = theseKeys[0] # at least one key was pressed + + # check for quit: + if "escape" == theseKeys: + endExpNow = True + key_resp.keys = theseKeys.name # just the last key pressed + key_resp.rt = theseKeys.rt + # was this 'correct'? + if (key_resp.keys == str('')) or (key_resp.keys == ''): + key_resp.corr = 1 + else: + key_resp.corr = 0 + # check for quit (typically the Esc key) if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]): core.quit() @@ -180,6 +334,21 @@ for thisTrial in trials: thisComponent.setAutoDraw(False) trials.addData('letter.started', letter.tStartRefresh) trials.addData('letter.stopped', letter.tStopRefresh) + # check responses + if key_resp.keys in ['', [], None]: # No response was made + key_resp.keys = None + # was no response the correct answer?! + if str('').lower() == 'none': + key_resp.corr = 1; # correct non-response + else: + key_resp.corr = 0; # failed to respond (incorrectly) + # store data for trials (TrialHandler) + trials.addData('key_resp.keys',key_resp.keys) + trials.addData('key_resp.corr', key_resp.corr) + if key_resp.keys != None: # we had a response + trials.addData('key_resp.rt', key_resp.rt) + trials.addData('key_resp.started', key_resp.tStartRefresh) + trials.addData('key_resp.stopped', key_resp.tStopRefresh) thisExp.nextEntry() # completed 20 repeats of 'trials'