diff --git a/rds_task.psyexp b/rds_task.psyexp index 6312f2ee529323a15d42294bc9d4cb6d0831ae79..ab80db39f7fa08bf121f035fb1cc11d61f797430 100644 --- a/rds_task.psyexp +++ b/rds_task.psyexp @@ -6,7 +6,7 @@ <Param name="Completed URL" updates="None" val="" valType="str"/> <Param name="Data filename" updates="None" val="u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])" valType="code"/> <Param name="Enable Escape" updates="None" val="True" valType="bool"/> - <Param name="Experiment info" updates="None" val="{'participant': '', 'session': '001'}" valType="code"/> + <Param name="Experiment info" updates="None" val="{'participant': '', 'session': '001', 'practice': 'False'}" valType="code"/> <Param name="Force stereo" updates="None" val="True" valType="bool"/> <Param name="Full-screen window" updates="None" val="False" valType="bool"/> <Param name="HTML path" updates="None" val="html" valType="str"/> @@ -102,7 +102,7 @@ <Param name="syncScreenRefresh" updates="constant" val="False" valType="bool"/> </KeyboardComponent> <CodeComponent name="init"> - <Param name="Begin Experiment" updates="constant" val="MINLEVEL=0&#10;MAXLEVEL=9" valType="extendedCode"/> + <Param name="Begin Experiment" updates="constant" val="MINLEVEL=0&#10;MAXLEVEL=9&#10;&#10;if expInfo['practice']:&#10; nTrial = 2&#10;else:&#10; nTrial = 20" valType="extendedCode"/> <Param name="Begin JS Experiment" updates="constant" val="" valType="extendedCode"/> <Param name="Begin JS Routine" updates="constant" val="" valType="extendedCode"/> <Param name="Begin Routine" updates="constant" val="" valType="extendedCode"/> @@ -148,7 +148,7 @@ <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="forceEndRoutine" updates="constant" val="True" valType="bool"/> <Param name="name" updates="None" val="resp_keys" valType="code"/> <Param name="saveStartStop" updates="None" val="False" valType="bool"/> <Param name="startEstim" updates="None" val="" valType="code"/> @@ -156,7 +156,7 @@ <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="all keys" valType="str"/> + <Param name="store" updates="constant" val="first key" valType="str"/> <Param name="storeCorrect" updates="constant" val="False" valType="bool"/> <Param name="syncScreenRefresh" updates="constant" val="True" valType="bool"/> </KeyboardComponent> @@ -166,12 +166,12 @@ <Param name="Begin JS Routine" updates="constant" val="" valType="extendedCode"/> <Param name="Begin Routine" updates="constant" val="" valType="extendedCode"/> <Param name="Code Type" updates="None" val="Py" valType="str"/> - <Param name="Each Frame" updates="constant" val="if len(resp_keys.keys) >= len(sequence):&#10; continueRoutine = False" valType="extendedCode"/> + <Param name="Each Frame" updates="constant" val="" valType="extendedCode"/> <Param name="Each JS Frame" updates="constant" val="" valType="extendedCode"/> <Param name="End Experiment" updates="constant" val="" valType="extendedCode"/> <Param name="End JS Experiment" updates="constant" val="" valType="extendedCode"/> <Param name="End JS Routine" updates="constant" val="" valType="extendedCode"/> - <Param name="End Routine" updates="constant" val="resp_keys.corr = [int(k) for k in resp_keys.keys] == list(np.flip(sequence))&#10;stair.addResponse(resp_keys.corr)&#10;stair.addOtherData('resp_keys.keys', resp_keys.keys)&#10;stair.addOtherData('resp_keys.rt', resp_keys.rt)" valType="extendedCode"/> + <Param name="End Routine" updates="constant" val="response_keys.append(resp_keys.keys[0])&#10;response_rt.append(resp_keys.rt)&#10;resp_stim.text = resp_keys.keys[0]" valType="extendedCode"/> <Param name="disabled" updates="None" val="False" valType="bool"/> <Param name="name" updates="None" val="resp_code" valType="code"/> </CodeComponent> @@ -205,7 +205,7 @@ <Param name="Begin Experiment" updates="constant" val="" valType="extendedCode"/> <Param name="Begin JS Experiment" updates="constant" val="" valType="extendedCode"/> <Param name="Begin JS Routine" updates="constant" val="" valType="extendedCode"/> - <Param name="Begin Routine" updates="constant" val="sequence=np.random.choice(range(10),size=MAXLEVEL-level+1,replace=False)&#10;stair.addOtherData('digits.stimulus', sequence)" valType="extendedCode"/> + <Param name="Begin Routine" updates="constant" val="sequence=np.random.choice(range(10),size=MAXLEVEL-level+1,replace=False)&#10;stair.addOtherData('digits.stimulus', sequence)&#10;&#10;response_keys = []&#10;response_rt = []&#10;resp_stim.text = '?'" valType="extendedCode"/> <Param name="Code Type" updates="None" val="Py" valType="str"/> <Param name="Each Frame" updates="constant" val="" valType="extendedCode"/> <Param name="Each JS Frame" updates="constant" val="" valType="extendedCode"/> @@ -217,6 +217,73 @@ <Param name="name" updates="None" val="gen_stim" valType="code"/> </CodeComponent> </Routine> + <Routine name="response_last"> + <TextComponent name="resp_last"> + <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="Calibri" valType="str"/> + <Param name="languageStyle" updates="None" val="LTR" valType="str"/> + <Param name="letterHeight" updates="constant" val="2.5" valType="code"/> + <Param name="name" updates="None" val="resp_last" 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="duration (s)" valType="str"/> + <Param name="stopVal" updates="constant" val="1.0" valType="code"/> + <Param name="syncScreenRefresh" updates="None" val="True" valType="bool"/> + <Param name="text" updates="set every repeat" val="$resp_keys.keys[-1]" valType="str"/> + <Param name="units" updates="None" val="from exp settings" valType="str"/> + <Param name="wrapWidth" updates="constant" val="" valType="code"/> + </TextComponent> + <CodeComponent name="code"> + <Param name="Begin Experiment" updates="constant" val="" valType="extendedCode"/> + <Param name="Begin JS Experiment" updates="constant" val="" valType="extendedCode"/> + <Param name="Begin JS Routine" updates="constant" val="" valType="extendedCode"/> + <Param name="Begin Routine" updates="constant" val="" valType="extendedCode"/> + <Param name="Code Type" updates="None" val="Py" valType="str"/> + <Param name="Each Frame" updates="constant" val="" valType="extendedCode"/> + <Param name="Each JS Frame" updates="constant" val="" valType="extendedCode"/> + <Param name="End Experiment" updates="constant" val="" valType="extendedCode"/> + <Param name="End JS Experiment" updates="constant" val="" valType="extendedCode"/> + <Param name="End JS Routine" updates="constant" val="" valType="extendedCode"/> + <Param name="End Routine" updates="constant" val="response_corr = [int(k) for k in response_keys] == list(np.flip(sequence))&#10;if response_corr:&#10; feedback_stim.text = 'Correct'&#10;else:&#10; feedback_stim.text = 'Wrong'&#10;&#10;stair.addResponse(response_corr)&#10;stair.addOtherData('resp_keys.keys', response_keys)&#10;stair.addOtherData('resp_keys.rt', response_rt)" valType="extendedCode"/> + <Param name="disabled" updates="None" val="False" valType="bool"/> + <Param name="name" updates="None" val="code" valType="code"/> + </CodeComponent> + </Routine> + <Routine name="feedback"> + <TextComponent name="feedback_stim"> + <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="Calibri" valType="str"/> + <Param name="languageStyle" updates="None" val="LTR" valType="str"/> + <Param name="letterHeight" updates="constant" val="2.5" valType="code"/> + <Param name="name" updates="None" val="feedback_stim" 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="duration (s)" valType="str"/> + <Param name="stopVal" updates="constant" val="1.0" valType="code"/> + <Param name="syncScreenRefresh" updates="None" val="True" valType="bool"/> + <Param name="text" updates="constant" val="Correct" valType="str"/> + <Param name="units" updates="None" val="from exp settings" valType="str"/> + <Param name="wrapWidth" updates="constant" val="" valType="code"/> + </TextComponent> + </Routine> </Routines> <Flow> <Routine name="Instruction"/> @@ -229,14 +296,14 @@ <Param name="loopType" updates="None" val="staircase" valType="str"/> <Param name="max value" updates="None" val="MAXLEVEL" valType="code"/> <Param name="min value" updates="None" val="MINLEVEL" valType="code"/> - <Param name="nReps" updates="None" val="20" valType="code"/> + <Param name="nReps" updates="None" val="$nTrial" valType="code"/> <Param name="name" updates="None" val="stair" valType="code"/> <Param name="start value" updates="None" val="MAXLEVEL-1" valType="code"/> <Param name="step sizes" updates="None" val="[1]" valType="code"/> <Param name="step type" updates="None" val="lin" valType="str"/> </LoopInitiator> <Routine name="fixation"/> - <LoopInitiator loopType="TrialHandler" name="span"> + <LoopInitiator loopType="TrialHandler" name="span_stim"> <Param name="Selected rows" updates="None" val="" valType="str"/> <Param name="conditions" updates="None" val="None" valType="str"/> <Param name="conditionsFile" updates="None" val="" valType="str"/> @@ -244,12 +311,38 @@ <Param name="isTrials" updates="None" val="False" valType="bool"/> <Param name="loopType" updates="None" val="sequential" valType="str"/> <Param name="nReps" updates="None" val="MAXLEVEL-level+1" valType="code"/> - <Param name="name" updates="None" val="span" valType="code"/> + <Param name="name" updates="None" val="span_stim" valType="code"/> <Param name="random seed" updates="None" val="" valType="code"/> </LoopInitiator> <Routine name="trial"/> - <LoopTerminator name="span"/> + <LoopTerminator name="span_stim"/> + <LoopInitiator loopType="TrialHandler" name="span_resp"> + <Param name="Selected rows" updates="None" val="" valType="str"/> + <Param name="conditions" updates="None" val="None" valType="str"/> + <Param name="conditionsFile" updates="None" val="" valType="str"/> + <Param name="endPoints" updates="None" val="[0, 1]" valType="num"/> + <Param name="isTrials" updates="None" val="False" valType="bool"/> + <Param name="loopType" updates="None" val="sequential" valType="str"/> + <Param name="nReps" updates="None" val="MAXLEVEL-level+1" valType="code"/> + <Param name="name" updates="None" val="span_resp" valType="code"/> + <Param name="random seed" updates="None" val="" valType="code"/> + </LoopInitiator> <Routine name="response"/> + <LoopTerminator name="span_resp"/> + <Routine name="response_last"/> + <LoopInitiator loopType="TrialHandler" name="do_feedback"> + <Param name="Selected rows" updates="None" val="" valType="str"/> + <Param name="conditions" updates="None" val="None" valType="str"/> + <Param name="conditionsFile" updates="None" val="" valType="str"/> + <Param name="endPoints" updates="None" val="[0, 1]" valType="num"/> + <Param name="isTrials" updates="None" val="False" valType="bool"/> + <Param name="loopType" updates="None" val="sequential" valType="str"/> + <Param name="nReps" updates="None" val="$int(expInfo['practice'])" valType="code"/> + <Param name="name" updates="None" val="do_feedback" valType="code"/> + <Param name="random seed" updates="None" val="" valType="code"/> + </LoopInitiator> + <Routine name="feedback"/> + <LoopTerminator name="do_feedback"/> <LoopTerminator name="stair"/> </Flow> </PsychoPy2experiment> diff --git a/rds_task.py b/rds_task.py index 35d7625a642ac222e16d0372c49c9792e57fe957..c397e5a9637bebb061e2c8dc7c40d9caf67d5d31 100644 --- a/rds_task.py +++ b/rds_task.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ This experiment was created using PsychoPy3 Experiment Builder (v3.2.0), - on November 15, 2019, at 18:05 + on November 21, 2019, at 11:51 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) @@ -35,7 +35,7 @@ os.chdir(_thisDir) # Store info about the experiment session psychopyVersion = '3.2.0' expName = 'rds_task' # from the Builder filename that created this script -expInfo = {'participant': '', 'session': '001'} +expInfo = {'participant': '', 'session': '001', 'practice': False} dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName) if dlg.OK == False: core.quit() # user pressed cancel @@ -91,6 +91,11 @@ key_start = keyboard.Keyboard() MINLEVEL=0 MAXLEVEL=9 +if expInfo['practice']: + nTrial = 2 +else: + nTrial = 20 + # Initialize components for Routine "fixation" fixationClock = core.Clock() cross = visual.TextStim(win=win, name='cross', @@ -122,6 +127,26 @@ resp_stim = visual.TextStim(win=win, name='resp_stim', depth=0.0); resp_keys = keyboard.Keyboard() +# Initialize components for Routine "response_last" +response_lastClock = core.Clock() +resp_last = visual.TextStim(win=win, name='resp_last', + text='default text', + font='Calibri', + pos=(0, 0), height=2.5, wrapWidth=None, ori=0, + color='white', colorSpace='rgb', opacity=1, + languageStyle='LTR', + depth=0.0); + +# Initialize components for Routine "feedback" +feedbackClock = core.Clock() +feedback_stim = visual.TextStim(win=win, name='feedback_stim', + text='Correct', + font='Calibri', + pos=(0, 0), height=2.5, wrapWidth=None, ori=0, + color='white', colorSpace='rgb', opacity=1, + languageStyle='LTR', + 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 @@ -219,7 +244,7 @@ routineTimer.reset() # set up handler to look after next chosen value etc stair = data.StairHandler(startVal=MAXLEVEL-1, extraInfo=expInfo, stepSizes=[1], stepType='lin', - nReversals=1, nTrials=20, + nReversals=1, nTrials=nTrial, nUp=1, nDown=1, minVal=MINLEVEL, maxVal=MAXLEVEL, originPath=-1, name='stair') @@ -235,6 +260,10 @@ for thisStair in stair: # update component parameters for each repeat sequence=np.random.choice(range(10),size=MAXLEVEL-level+1,replace=False) stair.addOtherData('digits.stimulus', sequence) + + response_keys = [] + response_rt = [] + resp_stim.text = '?' # keep track of which components have finished fixationComponents = [cross] for thisComponent in fixationComponents: @@ -302,23 +331,23 @@ for thisStair in stair: stair.addOtherData('cross.stopped', cross.tStopRefresh) # set up handler to look after randomisation of conditions etc - span = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', + span_stim = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', extraInfo=expInfo, originPath=-1, trialList=[None], - seed=None, name='span') - thisExp.addLoop(span) # add the loop to the experiment - thisSpan = span.trialList[0] # so we can initialise stimuli with some values - # abbreviate parameter names if possible (e.g. rgb = thisSpan.rgb) - if thisSpan != None: - for paramName in thisSpan: - exec('{} = thisSpan[paramName]'.format(paramName)) + seed=None, name='span_stim') + thisExp.addLoop(span_stim) # add the loop to the experiment + thisSpan_stim = span_stim.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisSpan_stim.rgb) + if thisSpan_stim != None: + for paramName in thisSpan_stim: + exec('{} = thisSpan_stim[paramName]'.format(paramName)) - for thisSpan in span: - currentLoop = span - # abbreviate parameter names if possible (e.g. rgb = thisSpan.rgb) - if thisSpan != None: - for paramName in thisSpan: - exec('{} = thisSpan[paramName]'.format(paramName)) + for thisSpan_stim in span_stim: + currentLoop = span_stim + # abbreviate parameter names if possible (e.g. rgb = thisSpan_stim.rgb) + if thisSpan_stim != None: + for paramName in thisSpan_stim: + exec('{} = thisSpan_stim[paramName]'.format(paramName)) # ------Prepare to start Routine "trial"------- routineTimer.add(1.000000) @@ -387,18 +416,139 @@ for thisStair in stair: for thisComponent in trialComponents: if hasattr(thisComponent, "setAutoDraw"): thisComponent.setAutoDraw(False) - span.addData('digits.started', digits.tStartRefresh) - span.addData('digits.stopped', digits.tStopRefresh) - # completed MAXLEVEL-level+1 repeats of 'span' + span_stim.addData('digits.started', digits.tStartRefresh) + span_stim.addData('digits.stopped', digits.tStopRefresh) + # completed MAXLEVEL-level+1 repeats of 'span_stim' + + + # set up handler to look after randomisation of conditions etc + span_resp = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', + extraInfo=expInfo, originPath=-1, + trialList=[None], + seed=None, name='span_resp') + thisExp.addLoop(span_resp) # add the loop to the experiment + thisSpan_resp = span_resp.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisSpan_resp.rgb) + if thisSpan_resp != None: + for paramName in thisSpan_resp: + exec('{} = thisSpan_resp[paramName]'.format(paramName)) + + for thisSpan_resp in span_resp: + currentLoop = span_resp + # abbreviate parameter names if possible (e.g. rgb = thisSpan_resp.rgb) + if thisSpan_resp != None: + for paramName in thisSpan_resp: + exec('{} = thisSpan_resp[paramName]'.format(paramName)) + + # ------Prepare to start Routine "response"------- + # update component parameters for each repeat + resp_keys.keys = [] + resp_keys.rt = [] + # keep track of which components have finished + responseComponents = [resp_stim, resp_keys] + for thisComponent in responseComponents: + 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") + responseClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + frameN = -1 + continueRoutine = True + + # -------Run Routine "response"------- + while continueRoutine: + # get current time + t = responseClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=responseClock) + tThisFlipGlobal = win.getFutureFlipTime(clock=None) + frameN = frameN + 1 # number of completed frames (so 0 is the first frame) + # update/draw components on each frame + + # *resp_stim* updates + if resp_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + resp_stim.frameNStart = frameN # exact frame index + resp_stim.tStart = t # local t and not account for scr refresh + resp_stim.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_stim, 'tStartRefresh') # time at next scr refresh + resp_stim.setAutoDraw(True) + + # *resp_keys* updates + waitOnFlip = False + if resp_keys.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + resp_keys.frameNStart = frameN # exact frame index + resp_keys.tStart = t # local t and not account for scr refresh + resp_keys.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_keys, 'tStartRefresh') # time at next scr refresh + resp_keys.status = STARTED + # keyboard checking is just starting + waitOnFlip = True + win.callOnFlip(resp_keys.clock.reset) # t=0 on next screen flip + win.callOnFlip(resp_keys.clearEvents, eventType='keyboard') # clear events on next screen flip + if resp_keys.status == STARTED and not waitOnFlip: + theseKeys = resp_keys.getKeys(keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], waitRelease=False) + if len(theseKeys): + theseKeys = theseKeys[0] # at least one key was pressed + + # check for quit: + if "escape" == theseKeys: + endExpNow = True + if resp_keys.keys == []: # then this was the first keypress + resp_keys.keys = theseKeys.name # just the first key pressed + resp_keys.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 responseComponents: + 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 "response"------- + for thisComponent in responseComponents: + if hasattr(thisComponent, "setAutoDraw"): + thisComponent.setAutoDraw(False) + span_resp.addData('resp_stim.started', resp_stim.tStartRefresh) + span_resp.addData('resp_stim.stopped', resp_stim.tStopRefresh) + # check responses + if resp_keys.keys in ['', [], None]: # No response was made + resp_keys.keys = None + span_resp.addData('resp_keys.keys',resp_keys.keys) + if resp_keys.keys != None: # we had a response + span_resp.addData('resp_keys.rt', resp_keys.rt) + response_keys.append(resp_keys.keys[0]) + response_rt.append(resp_keys.rt) + resp_stim.text = resp_keys.keys[0] + # the Routine "response" was not non-slip safe, so reset the non-slip timer + routineTimer.reset() + # completed MAXLEVEL-level+1 repeats of 'span_resp' - # ------Prepare to start Routine "response"------- + # ------Prepare to start Routine "response_last"------- + routineTimer.add(1.000000) # update component parameters for each repeat - resp_keys.keys = [] - resp_keys.rt = [] + resp_last.setText(resp_keys.keys[-1]) # keep track of which components have finished - responseComponents = [resp_stim, resp_keys] - for thisComponent in responseComponents: + response_lastComponents = [resp_last] + for thisComponent in response_lastComponents: thisComponent.tStart = None thisComponent.tStop = None thisComponent.tStartRefresh = None @@ -408,53 +558,35 @@ for thisStair in stair: # reset timers t = 0 _timeToFirstFrame = win.getFutureFlipTime(clock="now") - responseClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + response_lastClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip frameN = -1 continueRoutine = True - # -------Run Routine "response"------- - while continueRoutine: + # -------Run Routine "response_last"------- + while continueRoutine and routineTimer.getTime() > 0: # get current time - t = responseClock.getTime() - tThisFlip = win.getFutureFlipTime(clock=responseClock) + t = response_lastClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=response_lastClock) tThisFlipGlobal = win.getFutureFlipTime(clock=None) frameN = frameN + 1 # number of completed frames (so 0 is the first frame) # update/draw components on each frame - # *resp_stim* updates - if resp_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: - # keep track of start time/frame for later - resp_stim.frameNStart = frameN # exact frame index - resp_stim.tStart = t # local t and not account for scr refresh - resp_stim.tStartRefresh = tThisFlipGlobal # on global time - win.timeOnFlip(resp_stim, 'tStartRefresh') # time at next scr refresh - resp_stim.setAutoDraw(True) - - # *resp_keys* updates - waitOnFlip = False - if resp_keys.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # *resp_last* updates + if resp_last.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: # keep track of start time/frame for later - resp_keys.frameNStart = frameN # exact frame index - resp_keys.tStart = t # local t and not account for scr refresh - resp_keys.tStartRefresh = tThisFlipGlobal # on global time - win.timeOnFlip(resp_keys, 'tStartRefresh') # time at next scr refresh - resp_keys.status = STARTED - # keyboard checking is just starting - waitOnFlip = True - win.callOnFlip(resp_keys.clock.reset) # t=0 on next screen flip - win.callOnFlip(resp_keys.clearEvents, eventType='keyboard') # clear events on next screen flip - if resp_keys.status == STARTED and not waitOnFlip: - theseKeys = resp_keys.getKeys(keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], waitRelease=False) - if len(theseKeys): - theseKeys = theseKeys[0] # at least one key was pressed - - # check for quit: - if "escape" == theseKeys: - endExpNow = True - resp_keys.keys.append(theseKeys.name) # storing all keys - resp_keys.rt.append(theseKeys.rt) - if len(resp_keys.keys) >= len(sequence): - continueRoutine = False + resp_last.frameNStart = frameN # exact frame index + resp_last.tStart = t # local t and not account for scr refresh + resp_last.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_last, 'tStartRefresh') # time at next scr refresh + resp_last.setAutoDraw(True) + if resp_last.status == STARTED: + # is it time to stop? (based on global clock, using actual start) + if tThisFlipGlobal > resp_last.tStartRefresh + 1.0-frameTolerance: + # keep track of stop time/frame for later + resp_last.tStop = t # not accounting for scr refresh + resp_last.frameNStop = frameN # exact frame index + win.timeOnFlip(resp_last, 'tStopRefresh') # time at next scr refresh + resp_last.setAutoDraw(False) # check for quit (typically the Esc key) if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]): @@ -464,7 +596,7 @@ for thisStair in stair: 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 responseComponents: + for thisComponent in response_lastComponents: if hasattr(thisComponent, "status") and thisComponent.status != FINISHED: continueRoutine = True break # at least one component has not yet finished @@ -473,21 +605,111 @@ for thisStair in stair: if continueRoutine: # don't flip if this routine is over or we'll get a blank screen win.flip() - # -------Ending Routine "response"------- - for thisComponent in responseComponents: + # -------Ending Routine "response_last"------- + for thisComponent in response_lastComponents: if hasattr(thisComponent, "setAutoDraw"): thisComponent.setAutoDraw(False) - stair.addOtherData('resp_stim.started', resp_stim.tStartRefresh) - stair.addOtherData('resp_stim.stopped', resp_stim.tStopRefresh) - # check responses - if resp_keys.keys in ['', [], None]: # No response was made - resp_keys.keys = None - resp_keys.corr = [int(k) for k in resp_keys.keys] == list(np.flip(sequence)) - stair.addResponse(resp_keys.corr) - stair.addOtherData('resp_keys.keys', resp_keys.keys) - stair.addOtherData('resp_keys.rt', resp_keys.rt) - # the Routine "response" was not non-slip safe, so reset the non-slip timer - routineTimer.reset() + stair.addOtherData('resp_last.started', resp_last.tStartRefresh) + stair.addOtherData('resp_last.stopped', resp_last.tStopRefresh) + response_corr = [int(k) for k in response_keys] == list(np.flip(sequence)) + if response_corr: + feedback_stim.text = 'Correct' + else: + feedback_stim.text = 'Wrong' + + stair.addResponse(response_corr) + stair.addOtherData('resp_keys.keys', response_keys) + stair.addOtherData('resp_keys.rt', response_rt) + + # set up handler to look after randomisation of conditions etc + do_feedback = data.TrialHandler(nReps=int(expInfo['practice']), method='sequential', + extraInfo=expInfo, originPath=-1, + trialList=[None], + seed=None, name='do_feedback') + thisExp.addLoop(do_feedback) # add the loop to the experiment + thisDo_feedback = do_feedback.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisDo_feedback.rgb) + if thisDo_feedback != None: + for paramName in thisDo_feedback: + exec('{} = thisDo_feedback[paramName]'.format(paramName)) + + for thisDo_feedback in do_feedback: + currentLoop = do_feedback + # abbreviate parameter names if possible (e.g. rgb = thisDo_feedback.rgb) + if thisDo_feedback != None: + for paramName in thisDo_feedback: + exec('{} = thisDo_feedback[paramName]'.format(paramName)) + + # ------Prepare to start Routine "feedback"------- + routineTimer.add(1.000000) + # update component parameters for each repeat + # keep track of which components have finished + feedbackComponents = [feedback_stim] + for thisComponent in feedbackComponents: + 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") + feedbackClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + frameN = -1 + continueRoutine = True + + # -------Run Routine "feedback"------- + while continueRoutine and routineTimer.getTime() > 0: + # get current time + t = feedbackClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=feedbackClock) + tThisFlipGlobal = win.getFutureFlipTime(clock=None) + frameN = frameN + 1 # number of completed frames (so 0 is the first frame) + # update/draw components on each frame + + # *feedback_stim* updates + if feedback_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + feedback_stim.frameNStart = frameN # exact frame index + feedback_stim.tStart = t # local t and not account for scr refresh + feedback_stim.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(feedback_stim, 'tStartRefresh') # time at next scr refresh + feedback_stim.setAutoDraw(True) + if feedback_stim.status == STARTED: + # is it time to stop? (based on global clock, using actual start) + if tThisFlipGlobal > feedback_stim.tStartRefresh + 1.0-frameTolerance: + # keep track of stop time/frame for later + feedback_stim.tStop = t # not accounting for scr refresh + feedback_stim.frameNStop = frameN # exact frame index + win.timeOnFlip(feedback_stim, 'tStopRefresh') # time at next scr refresh + feedback_stim.setAutoDraw(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 feedbackComponents: + 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 "feedback"------- + for thisComponent in feedbackComponents: + if hasattr(thisComponent, "setAutoDraw"): + thisComponent.setAutoDraw(False) + do_feedback.addData('feedback_stim.started', feedback_stim.tStartRefresh) + do_feedback.addData('feedback_stim.stopped', feedback_stim.tStopRefresh) + # completed int(expInfo['practice']) repeats of 'do_feedback' + thisExp.nextEntry() # staircase completed diff --git a/rds_task_lastrun.py b/rds_task_lastrun.py index 1555054fa5b58142b5256c070f1a1852caf94053..088c1e046ac4c57dd2b9de21b7bb2f439aef450b 100644 --- a/rds_task_lastrun.py +++ b/rds_task_lastrun.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ This experiment was created using PsychoPy3 Experiment Builder (v3.2.0), - on November 15, 2019, at 18:05 + on November 21, 2019, at 11:51 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) @@ -35,7 +35,7 @@ os.chdir(_thisDir) # Store info about the experiment session psychopyVersion = '3.2.0' expName = 'rds_task' # from the Builder filename that created this script -expInfo = {'participant': '', 'session': '001'} +expInfo = {'participant': '', 'session': '001', 'practice': False} dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName) if dlg.OK == False: core.quit() # user pressed cancel @@ -91,6 +91,11 @@ key_start = keyboard.Keyboard() MINLEVEL=0 MAXLEVEL=9 +if expInfo['practice']: + nTrial = 2 +else: + nTrial = 20 + # Initialize components for Routine "fixation" fixationClock = core.Clock() cross = visual.TextStim(win=win, name='cross', @@ -122,6 +127,26 @@ resp_stim = visual.TextStim(win=win, name='resp_stim', depth=0.0); resp_keys = keyboard.Keyboard() +# Initialize components for Routine "response_last" +response_lastClock = core.Clock() +resp_last = visual.TextStim(win=win, name='resp_last', + text='default text', + font='Calibri', + pos=(0, 0), height=2.5, wrapWidth=None, ori=0, + color='white', colorSpace='rgb', opacity=1, + languageStyle='LTR', + depth=0.0); + +# Initialize components for Routine "feedback" +feedbackClock = core.Clock() +feedback_stim = visual.TextStim(win=win, name='feedback_stim', + text='Correct', + font='Calibri', + pos=(0, 0), height=2.5, wrapWidth=None, ori=0, + color='white', colorSpace='rgb', opacity=1, + languageStyle='LTR', + 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 @@ -219,7 +244,7 @@ routineTimer.reset() # set up handler to look after next chosen value etc stair = data.StairHandler(startVal=MAXLEVEL-1, extraInfo=expInfo, stepSizes=[1], stepType='lin', - nReversals=1, nTrials=20, + nReversals=1, nTrials=nTrial, nUp=1, nDown=1, minVal=MINLEVEL, maxVal=MAXLEVEL, originPath=-1, name='stair') @@ -235,6 +260,10 @@ for thisStair in stair: # update component parameters for each repeat sequence=np.random.choice(range(10),size=MAXLEVEL-level+1,replace=False) stair.addOtherData('digits.stimulus', sequence) + + response_keys = [] + response_rt = [] + resp_stim.text = '?' # keep track of which components have finished fixationComponents = [cross] for thisComponent in fixationComponents: @@ -302,23 +331,23 @@ for thisStair in stair: stair.addOtherData('cross.stopped', cross.tStopRefresh) # set up handler to look after randomisation of conditions etc - span = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', + span_stim = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', extraInfo=expInfo, originPath=-1, trialList=[None], - seed=None, name='span') - thisExp.addLoop(span) # add the loop to the experiment - thisSpan = span.trialList[0] # so we can initialise stimuli with some values - # abbreviate parameter names if possible (e.g. rgb = thisSpan.rgb) - if thisSpan != None: - for paramName in thisSpan: - exec('{} = thisSpan[paramName]'.format(paramName)) + seed=None, name='span_stim') + thisExp.addLoop(span_stim) # add the loop to the experiment + thisSpan_stim = span_stim.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisSpan_stim.rgb) + if thisSpan_stim != None: + for paramName in thisSpan_stim: + exec('{} = thisSpan_stim[paramName]'.format(paramName)) - for thisSpan in span: - currentLoop = span - # abbreviate parameter names if possible (e.g. rgb = thisSpan.rgb) - if thisSpan != None: - for paramName in thisSpan: - exec('{} = thisSpan[paramName]'.format(paramName)) + for thisSpan_stim in span_stim: + currentLoop = span_stim + # abbreviate parameter names if possible (e.g. rgb = thisSpan_stim.rgb) + if thisSpan_stim != None: + for paramName in thisSpan_stim: + exec('{} = thisSpan_stim[paramName]'.format(paramName)) # ------Prepare to start Routine "trial"------- routineTimer.add(1.000000) @@ -387,18 +416,139 @@ for thisStair in stair: for thisComponent in trialComponents: if hasattr(thisComponent, "setAutoDraw"): thisComponent.setAutoDraw(False) - span.addData('digits.started', digits.tStartRefresh) - span.addData('digits.stopped', digits.tStopRefresh) - # completed MAXLEVEL-level+1 repeats of 'span' + span_stim.addData('digits.started', digits.tStartRefresh) + span_stim.addData('digits.stopped', digits.tStopRefresh) + # completed MAXLEVEL-level+1 repeats of 'span_stim' + + + # set up handler to look after randomisation of conditions etc + span_resp = data.TrialHandler(nReps=MAXLEVEL-level+1, method='sequential', + extraInfo=expInfo, originPath=-1, + trialList=[None], + seed=None, name='span_resp') + thisExp.addLoop(span_resp) # add the loop to the experiment + thisSpan_resp = span_resp.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisSpan_resp.rgb) + if thisSpan_resp != None: + for paramName in thisSpan_resp: + exec('{} = thisSpan_resp[paramName]'.format(paramName)) + + for thisSpan_resp in span_resp: + currentLoop = span_resp + # abbreviate parameter names if possible (e.g. rgb = thisSpan_resp.rgb) + if thisSpan_resp != None: + for paramName in thisSpan_resp: + exec('{} = thisSpan_resp[paramName]'.format(paramName)) + + # ------Prepare to start Routine "response"------- + # update component parameters for each repeat + resp_keys.keys = [] + resp_keys.rt = [] + # keep track of which components have finished + responseComponents = [resp_stim, resp_keys] + for thisComponent in responseComponents: + 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") + responseClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + frameN = -1 + continueRoutine = True + + # -------Run Routine "response"------- + while continueRoutine: + # get current time + t = responseClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=responseClock) + tThisFlipGlobal = win.getFutureFlipTime(clock=None) + frameN = frameN + 1 # number of completed frames (so 0 is the first frame) + # update/draw components on each frame + + # *resp_stim* updates + if resp_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + resp_stim.frameNStart = frameN # exact frame index + resp_stim.tStart = t # local t and not account for scr refresh + resp_stim.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_stim, 'tStartRefresh') # time at next scr refresh + resp_stim.setAutoDraw(True) + + # *resp_keys* updates + waitOnFlip = False + if resp_keys.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + resp_keys.frameNStart = frameN # exact frame index + resp_keys.tStart = t # local t and not account for scr refresh + resp_keys.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_keys, 'tStartRefresh') # time at next scr refresh + resp_keys.status = STARTED + # keyboard checking is just starting + waitOnFlip = True + win.callOnFlip(resp_keys.clock.reset) # t=0 on next screen flip + win.callOnFlip(resp_keys.clearEvents, eventType='keyboard') # clear events on next screen flip + if resp_keys.status == STARTED and not waitOnFlip: + theseKeys = resp_keys.getKeys(keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], waitRelease=False) + if len(theseKeys): + theseKeys = theseKeys[0] # at least one key was pressed + + # check for quit: + if "escape" == theseKeys: + endExpNow = True + if resp_keys.keys == []: # then this was the first keypress + resp_keys.keys = theseKeys.name # just the first key pressed + resp_keys.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 responseComponents: + 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 "response"------- + for thisComponent in responseComponents: + if hasattr(thisComponent, "setAutoDraw"): + thisComponent.setAutoDraw(False) + span_resp.addData('resp_stim.started', resp_stim.tStartRefresh) + span_resp.addData('resp_stim.stopped', resp_stim.tStopRefresh) + # check responses + if resp_keys.keys in ['', [], None]: # No response was made + resp_keys.keys = None + span_resp.addData('resp_keys.keys',resp_keys.keys) + if resp_keys.keys != None: # we had a response + span_resp.addData('resp_keys.rt', resp_keys.rt) + response_keys.append(resp_keys.keys[0]) + response_rt.append(resp_keys.rt) + resp_stim.text = resp_keys.keys[0] + # the Routine "response" was not non-slip safe, so reset the non-slip timer + routineTimer.reset() + # completed MAXLEVEL-level+1 repeats of 'span_resp' - # ------Prepare to start Routine "response"------- + # ------Prepare to start Routine "response_last"------- + routineTimer.add(1.000000) # update component parameters for each repeat - resp_keys.keys = [] - resp_keys.rt = [] + resp_last.setText(resp_keys.keys[-1]) # keep track of which components have finished - responseComponents = [resp_stim, resp_keys] - for thisComponent in responseComponents: + response_lastComponents = [resp_last] + for thisComponent in response_lastComponents: thisComponent.tStart = None thisComponent.tStop = None thisComponent.tStartRefresh = None @@ -408,53 +558,35 @@ for thisStair in stair: # reset timers t = 0 _timeToFirstFrame = win.getFutureFlipTime(clock="now") - responseClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + response_lastClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip frameN = -1 continueRoutine = True - # -------Run Routine "response"------- - while continueRoutine: + # -------Run Routine "response_last"------- + while continueRoutine and routineTimer.getTime() > 0: # get current time - t = responseClock.getTime() - tThisFlip = win.getFutureFlipTime(clock=responseClock) + t = response_lastClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=response_lastClock) tThisFlipGlobal = win.getFutureFlipTime(clock=None) frameN = frameN + 1 # number of completed frames (so 0 is the first frame) # update/draw components on each frame - # *resp_stim* updates - if resp_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: - # keep track of start time/frame for later - resp_stim.frameNStart = frameN # exact frame index - resp_stim.tStart = t # local t and not account for scr refresh - resp_stim.tStartRefresh = tThisFlipGlobal # on global time - win.timeOnFlip(resp_stim, 'tStartRefresh') # time at next scr refresh - resp_stim.setAutoDraw(True) - - # *resp_keys* updates - waitOnFlip = False - if resp_keys.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # *resp_last* updates + if resp_last.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: # keep track of start time/frame for later - resp_keys.frameNStart = frameN # exact frame index - resp_keys.tStart = t # local t and not account for scr refresh - resp_keys.tStartRefresh = tThisFlipGlobal # on global time - win.timeOnFlip(resp_keys, 'tStartRefresh') # time at next scr refresh - resp_keys.status = STARTED - # keyboard checking is just starting - waitOnFlip = True - win.callOnFlip(resp_keys.clock.reset) # t=0 on next screen flip - win.callOnFlip(resp_keys.clearEvents, eventType='keyboard') # clear events on next screen flip - if resp_keys.status == STARTED and not waitOnFlip: - theseKeys = resp_keys.getKeys(keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], waitRelease=False) - if len(theseKeys): - theseKeys = theseKeys[0] # at least one key was pressed - - # check for quit: - if "escape" == theseKeys: - endExpNow = True - resp_keys.keys.append(theseKeys.name) # storing all keys - resp_keys.rt.append(theseKeys.rt) - if len(resp_keys.keys) >= len(sequence): - continueRoutine = False + resp_last.frameNStart = frameN # exact frame index + resp_last.tStart = t # local t and not account for scr refresh + resp_last.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(resp_last, 'tStartRefresh') # time at next scr refresh + resp_last.setAutoDraw(True) + if resp_last.status == STARTED: + # is it time to stop? (based on global clock, using actual start) + if tThisFlipGlobal > resp_last.tStartRefresh + 1.0-frameTolerance: + # keep track of stop time/frame for later + resp_last.tStop = t # not accounting for scr refresh + resp_last.frameNStop = frameN # exact frame index + win.timeOnFlip(resp_last, 'tStopRefresh') # time at next scr refresh + resp_last.setAutoDraw(False) # check for quit (typically the Esc key) if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]): @@ -464,7 +596,7 @@ for thisStair in stair: 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 responseComponents: + for thisComponent in response_lastComponents: if hasattr(thisComponent, "status") and thisComponent.status != FINISHED: continueRoutine = True break # at least one component has not yet finished @@ -473,21 +605,111 @@ for thisStair in stair: if continueRoutine: # don't flip if this routine is over or we'll get a blank screen win.flip() - # -------Ending Routine "response"------- - for thisComponent in responseComponents: + # -------Ending Routine "response_last"------- + for thisComponent in response_lastComponents: if hasattr(thisComponent, "setAutoDraw"): thisComponent.setAutoDraw(False) - stair.addOtherData('resp_stim.started', resp_stim.tStartRefresh) - stair.addOtherData('resp_stim.stopped', resp_stim.tStopRefresh) - # check responses - if resp_keys.keys in ['', [], None]: # No response was made - resp_keys.keys = None - resp_keys.corr = [int(k) for k in resp_keys.keys] == list(np.flip(sequence)) - stair.addResponse(resp_keys.corr) - stair.addOtherData('resp_keys.keys', resp_keys.keys) - stair.addOtherData('resp_keys.rt', resp_keys.rt) - # the Routine "response" was not non-slip safe, so reset the non-slip timer - routineTimer.reset() + stair.addOtherData('resp_last.started', resp_last.tStartRefresh) + stair.addOtherData('resp_last.stopped', resp_last.tStopRefresh) + response_corr = [int(k) for k in response_keys] == list(np.flip(sequence)) + if response_corr: + feedback_stim.text = 'Correct' + else: + feedback_stim.text = 'Wrong' + + stair.addResponse(response_corr) + stair.addOtherData('resp_keys.keys', response_keys) + stair.addOtherData('resp_keys.rt', response_rt) + + # set up handler to look after randomisation of conditions etc + do_feedback = data.TrialHandler(nReps=int(expInfo['practice']), method='sequential', + extraInfo=expInfo, originPath=-1, + trialList=[None], + seed=None, name='do_feedback') + thisExp.addLoop(do_feedback) # add the loop to the experiment + thisDo_feedback = do_feedback.trialList[0] # so we can initialise stimuli with some values + # abbreviate parameter names if possible (e.g. rgb = thisDo_feedback.rgb) + if thisDo_feedback != None: + for paramName in thisDo_feedback: + exec('{} = thisDo_feedback[paramName]'.format(paramName)) + + for thisDo_feedback in do_feedback: + currentLoop = do_feedback + # abbreviate parameter names if possible (e.g. rgb = thisDo_feedback.rgb) + if thisDo_feedback != None: + for paramName in thisDo_feedback: + exec('{} = thisDo_feedback[paramName]'.format(paramName)) + + # ------Prepare to start Routine "feedback"------- + routineTimer.add(1.000000) + # update component parameters for each repeat + # keep track of which components have finished + feedbackComponents = [feedback_stim] + for thisComponent in feedbackComponents: + 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") + feedbackClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip + frameN = -1 + continueRoutine = True + + # -------Run Routine "feedback"------- + while continueRoutine and routineTimer.getTime() > 0: + # get current time + t = feedbackClock.getTime() + tThisFlip = win.getFutureFlipTime(clock=feedbackClock) + tThisFlipGlobal = win.getFutureFlipTime(clock=None) + frameN = frameN + 1 # number of completed frames (so 0 is the first frame) + # update/draw components on each frame + + # *feedback_stim* updates + if feedback_stim.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance: + # keep track of start time/frame for later + feedback_stim.frameNStart = frameN # exact frame index + feedback_stim.tStart = t # local t and not account for scr refresh + feedback_stim.tStartRefresh = tThisFlipGlobal # on global time + win.timeOnFlip(feedback_stim, 'tStartRefresh') # time at next scr refresh + feedback_stim.setAutoDraw(True) + if feedback_stim.status == STARTED: + # is it time to stop? (based on global clock, using actual start) + if tThisFlipGlobal > feedback_stim.tStartRefresh + 1.0-frameTolerance: + # keep track of stop time/frame for later + feedback_stim.tStop = t # not accounting for scr refresh + feedback_stim.frameNStop = frameN # exact frame index + win.timeOnFlip(feedback_stim, 'tStopRefresh') # time at next scr refresh + feedback_stim.setAutoDraw(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 feedbackComponents: + 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 "feedback"------- + for thisComponent in feedbackComponents: + if hasattr(thisComponent, "setAutoDraw"): + thisComponent.setAutoDraw(False) + do_feedback.addData('feedback_stim.started', feedback_stim.tStartRefresh) + do_feedback.addData('feedback_stim.stopped', feedback_stim.tStopRefresh) + # completed int(expInfo['practice']) repeats of 'do_feedback' + thisExp.nextEntry() # staircase completed