|
@@ -2,7 +2,7 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
This experiment was created using PsychoPy3 Experiment Builder (v2023.2.3),
|
|
|
- on 十一月 13, 2023, at 16:29
|
|
|
+ on 十一月 14, 2023, at 14:23
|
|
|
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)
|
|
@@ -34,13 +34,11 @@ import psychopy.iohub as io
|
|
|
from psychopy.hardware import keyboard
|
|
|
|
|
|
# Run 'Before Experiment' code from config
|
|
|
-import sqlite3
|
|
|
import os
|
|
|
import datetime
|
|
|
from time import sleep
|
|
|
import argparse
|
|
|
|
|
|
-from db.models import train
|
|
|
from device.sig_chain.sig_receive import Receiver
|
|
|
from device.sig_chain.device.connector_interface import Device
|
|
|
from device.sig_chain.trigger_box import TriggerNeuracle
|
|
@@ -189,7 +187,7 @@ def setupData(expInfo, dataDir=None):
|
|
|
thisExp = data.ExperimentHandler(
|
|
|
name=expName, version='',
|
|
|
extraInfo=expInfo, runtimeInfo=None,
|
|
|
- originPath='C:\\Users\\dkunl\\kraken\\backend\\train.py',
|
|
|
+ originPath='C:\\Users\\dkunl\\kraken\\backend\\general_grasp_training.py',
|
|
|
savePickle=True, saveWideText=True,
|
|
|
dataFileName=dataDir + os.sep + filename, sortColumns='time'
|
|
|
)
|
|
@@ -405,37 +403,29 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
languageStyle='LTR',
|
|
|
depth=0.0);
|
|
|
instruction = visual.TextStim(win=win, name='instruction',
|
|
|
- text='静息态采集\n请保持放松,注视十字准星',
|
|
|
+ text='准备进行一般抓握训练,\n按回车键继续',
|
|
|
font='Open Sans',
|
|
|
pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0,
|
|
|
color='white', colorSpace='rgb', opacity=None,
|
|
|
languageStyle='LTR',
|
|
|
depth=-1.0);
|
|
|
- img_reststate = visual.ImageStim(
|
|
|
- win=win,
|
|
|
- name='img_reststate',
|
|
|
- image='C:/Users/zhengyan/myWork/py_work/Kraken/Albatross/backend/static/images/reststate.png', mask=None, anchor='center',
|
|
|
- ori=0.0, pos=(0, 0), size=(0.5, 0.5),
|
|
|
- color=[1,1,1], colorSpace='rgb', opacity=None,
|
|
|
- flipHoriz=False, flipVert=False,
|
|
|
- texRes=128.0, interpolate=True, depth=-2.0)
|
|
|
+ key_resp = keyboard.Keyboard()
|
|
|
|
|
|
# --- Initialize components for Routine "mi_prepare" ---
|
|
|
- img_prepare = visual.ImageStim(
|
|
|
- win=win,
|
|
|
- name='img_prepare',
|
|
|
- image='C:/Users/zhengyan/myWork/py_work/Kraken/Albatross/backend/static/images/reststate.png', mask=None, anchor='center',
|
|
|
- ori=0.0, pos=(0, 0), size=(0.5, 0.5),
|
|
|
- color=[1,1,1], colorSpace='rgb', opacity=None,
|
|
|
- flipHoriz=False, flipVert=False,
|
|
|
- texRes=128.0, interpolate=True, depth=0.0)
|
|
|
+ text = visual.TextStim(win=win, name='text',
|
|
|
+ text='请准备开始尝试运动',
|
|
|
+ font='Open Sans',
|
|
|
+ pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0,
|
|
|
+ color='white', colorSpace='rgb', opacity=None,
|
|
|
+ languageStyle='LTR',
|
|
|
+ depth=-1.0);
|
|
|
|
|
|
# --- Initialize components for Routine "mi_begin" ---
|
|
|
img_right = visual.ImageStim(
|
|
|
win=win,
|
|
|
name='img_right',
|
|
|
- image='C:/Users/zhengyan/myWork/py_work/Kraken/Albatross/backend/static/images/right.png', mask=None, anchor='center',
|
|
|
- ori=0.0, pos=(0, 0), size=(0.5, 0.5),
|
|
|
+ image='static/images/hand_move.jpg', mask=None, anchor='center',
|
|
|
+ ori=0.0, pos=(0, 0), size=None,
|
|
|
color=[1,1,1], colorSpace='rgb', opacity=None,
|
|
|
flipHoriz=False, flipVert=False,
|
|
|
texRes=128.0, interpolate=True, depth=0.0)
|
|
@@ -455,8 +445,8 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
img_rest = visual.ImageStim(
|
|
|
win=win,
|
|
|
name='img_rest',
|
|
|
- image='C:/Users/zhengyan/myWork/py_work/Kraken/Albatross/backend/static/images/rest.png', mask=None, anchor='center',
|
|
|
- ori=0.0, pos=(0, 0), size=(0.5, 0.5),
|
|
|
+ image='static/images/rest.jpg', mask=None, anchor='center',
|
|
|
+ ori=0.0, pos=(0, 0), size=None,
|
|
|
color=[1,1,1], colorSpace='rgb', opacity=None,
|
|
|
flipHoriz=False, flipVert=False,
|
|
|
texRes=128.0, interpolate=True, depth=0.0)
|
|
@@ -485,8 +475,11 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
continueRoutine = True
|
|
|
# update component parameters for each repeat
|
|
|
thisExp.addData('before_mi.started', globalClock.getTime())
|
|
|
+ key_resp.keys = []
|
|
|
+ key_resp.rt = []
|
|
|
+ _key_resp_allKeys = []
|
|
|
# keep track of which components have finished
|
|
|
- before_miComponents = [train_position, instruction, img_reststate]
|
|
|
+ before_miComponents = [train_position, instruction, key_resp]
|
|
|
for thisComponent in before_miComponents:
|
|
|
thisComponent.tStart = None
|
|
|
thisComponent.tStop = None
|
|
@@ -545,7 +538,7 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
# *instruction* updates
|
|
|
|
|
|
# if instruction is starting this frame...
|
|
|
- if instruction.status == NOT_STARTED and tThisFlip >= 3-frameTolerance:
|
|
|
+ if instruction.status == NOT_STARTED and tThisFlip >= 2-frameTolerance:
|
|
|
# keep track of start time/frame for later
|
|
|
instruction.frameNStart = frameN # exact frame index
|
|
|
instruction.tStart = t # local t and not account for scr refresh
|
|
@@ -562,51 +555,33 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
# update params
|
|
|
pass
|
|
|
|
|
|
- # if instruction is stopping this frame...
|
|
|
- if instruction.status == STARTED:
|
|
|
- # is it time to stop? (based on global clock, using actual start)
|
|
|
- if tThisFlipGlobal > instruction.tStartRefresh + 2-frameTolerance:
|
|
|
- # keep track of stop time/frame for later
|
|
|
- instruction.tStop = t # not accounting for scr refresh
|
|
|
- instruction.frameNStop = frameN # exact frame index
|
|
|
- # add timestamp to datafile
|
|
|
- thisExp.timestampOnFlip(win, 'instruction.stopped')
|
|
|
- # update status
|
|
|
- instruction.status = FINISHED
|
|
|
- instruction.setAutoDraw(False)
|
|
|
-
|
|
|
- # *img_reststate* updates
|
|
|
+ # *key_resp* updates
|
|
|
+ waitOnFlip = False
|
|
|
|
|
|
- # if img_reststate is starting this frame...
|
|
|
- if img_reststate.status == NOT_STARTED and tThisFlip >= 6.5-frameTolerance:
|
|
|
+ # if key_resp is starting this frame...
|
|
|
+ if key_resp.status == NOT_STARTED and tThisFlip >= 2-frameTolerance:
|
|
|
# keep track of start time/frame for later
|
|
|
- img_reststate.frameNStart = frameN # exact frame index
|
|
|
- img_reststate.tStart = t # local t and not account for scr refresh
|
|
|
- img_reststate.tStartRefresh = tThisFlipGlobal # on global time
|
|
|
- win.timeOnFlip(img_reststate, 'tStartRefresh') # time at next scr refresh
|
|
|
+ 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
|
|
|
# add timestamp to datafile
|
|
|
- thisExp.timestampOnFlip(win, 'img_reststate.started')
|
|
|
+ thisExp.timestampOnFlip(win, 'key_resp.started')
|
|
|
# update status
|
|
|
- img_reststate.status = STARTED
|
|
|
- img_reststate.setAutoDraw(True)
|
|
|
-
|
|
|
- # if img_reststate is active this frame...
|
|
|
- if img_reststate.status == STARTED:
|
|
|
- # update params
|
|
|
- pass
|
|
|
-
|
|
|
- # if img_reststate is stopping this frame...
|
|
|
- if img_reststate.status == STARTED:
|
|
|
- # is it time to stop? (based on global clock, using actual start)
|
|
|
- if tThisFlipGlobal > img_reststate.tStartRefresh + 10-frameTolerance:
|
|
|
- # keep track of stop time/frame for later
|
|
|
- img_reststate.tStop = t # not accounting for scr refresh
|
|
|
- img_reststate.frameNStop = frameN # exact frame index
|
|
|
- # add timestamp to datafile
|
|
|
- thisExp.timestampOnFlip(win, 'img_reststate.stopped')
|
|
|
- # update status
|
|
|
- img_reststate.status = FINISHED
|
|
|
- img_reststate.setAutoDraw(False)
|
|
|
+ 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 and not waitOnFlip:
|
|
|
+ theseKeys = key_resp.getKeys(keyList=['return'], ignoreKeys=["escape"], waitRelease=False)
|
|
|
+ _key_resp_allKeys.extend(theseKeys)
|
|
|
+ if len(_key_resp_allKeys):
|
|
|
+ key_resp.keys = _key_resp_allKeys[-1].name # just the last key pressed
|
|
|
+ key_resp.rt = _key_resp_allKeys[-1].rt
|
|
|
+ key_resp.duration = _key_resp_allKeys[-1].duration
|
|
|
+ # a response ends the routine
|
|
|
+ continueRoutine = False
|
|
|
|
|
|
# check for quit (typically the Esc key)
|
|
|
if defaultKeyboard.getKeys(keyList=["escape"]):
|
|
@@ -641,6 +616,14 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
path = utils.create_data_dir(subject, args.train_id) # owner_name, train_id
|
|
|
filename = f"{subject}_{datetime.datetime.now().strftime('%H%M%S')}.bdf"
|
|
|
receiver.connector.saver.set_edf_header(subject, filename, 5, path)
|
|
|
+ # check responses
|
|
|
+ if key_resp.keys in ['', [], None]: # No response was made
|
|
|
+ key_resp.keys = None
|
|
|
+ thisExp.addData('key_resp.keys',key_resp.keys)
|
|
|
+ if key_resp.keys != None: # we had a response
|
|
|
+ thisExp.addData('key_resp.rt', key_resp.rt)
|
|
|
+ thisExp.addData('key_resp.duration', key_resp.duration)
|
|
|
+ thisExp.nextEntry()
|
|
|
# the Routine "before_mi" was not non-slip safe, so reset the non-slip timer
|
|
|
routineTimer.reset()
|
|
|
|
|
@@ -680,7 +663,7 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
# Run 'Begin Routine' code from initialize_buffer
|
|
|
decision_buffer = []
|
|
|
# keep track of which components have finished
|
|
|
- mi_prepareComponents = [img_prepare]
|
|
|
+ mi_prepareComponents = [text]
|
|
|
for thisComponent in mi_prepareComponents:
|
|
|
thisComponent.tStart = None
|
|
|
thisComponent.tStop = None
|
|
@@ -703,38 +686,38 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
|
|
|
# update/draw components on each frame
|
|
|
|
|
|
- # *img_prepare* updates
|
|
|
+ # *text* updates
|
|
|
|
|
|
- # if img_prepare is starting this frame...
|
|
|
- if img_prepare.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
|
|
|
+ # if text is starting this frame...
|
|
|
+ if text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
|
|
|
# keep track of start time/frame for later
|
|
|
- img_prepare.frameNStart = frameN # exact frame index
|
|
|
- img_prepare.tStart = t # local t and not account for scr refresh
|
|
|
- img_prepare.tStartRefresh = tThisFlipGlobal # on global time
|
|
|
- win.timeOnFlip(img_prepare, 'tStartRefresh') # time at next scr refresh
|
|
|
+ text.frameNStart = frameN # exact frame index
|
|
|
+ text.tStart = t # local t and not account for scr refresh
|
|
|
+ text.tStartRefresh = tThisFlipGlobal # on global time
|
|
|
+ win.timeOnFlip(text, 'tStartRefresh') # time at next scr refresh
|
|
|
# add timestamp to datafile
|
|
|
- thisExp.timestampOnFlip(win, 'img_prepare.started')
|
|
|
+ thisExp.timestampOnFlip(win, 'text.started')
|
|
|
# update status
|
|
|
- img_prepare.status = STARTED
|
|
|
- img_prepare.setAutoDraw(True)
|
|
|
+ text.status = STARTED
|
|
|
+ text.setAutoDraw(True)
|
|
|
|
|
|
- # if img_prepare is active this frame...
|
|
|
- if img_prepare.status == STARTED:
|
|
|
+ # if text is active this frame...
|
|
|
+ if text.status == STARTED:
|
|
|
# update params
|
|
|
pass
|
|
|
|
|
|
- # if img_prepare is stopping this frame...
|
|
|
- if img_prepare.status == STARTED:
|
|
|
+ # if text is stopping this frame...
|
|
|
+ if text.status == STARTED:
|
|
|
# is it time to stop? (based on global clock, using actual start)
|
|
|
- if tThisFlipGlobal > img_prepare.tStartRefresh + 1.5-frameTolerance:
|
|
|
+ if tThisFlipGlobal > text.tStartRefresh + 1.5-frameTolerance:
|
|
|
# keep track of stop time/frame for later
|
|
|
- img_prepare.tStop = t # not accounting for scr refresh
|
|
|
- img_prepare.frameNStop = frameN # exact frame index
|
|
|
+ text.tStop = t # not accounting for scr refresh
|
|
|
+ text.frameNStop = frameN # exact frame index
|
|
|
# add timestamp to datafile
|
|
|
- thisExp.timestampOnFlip(win, 'img_prepare.stopped')
|
|
|
+ thisExp.timestampOnFlip(win, 'text.stopped')
|
|
|
# update status
|
|
|
- img_prepare.status = FINISHED
|
|
|
- img_prepare.setAutoDraw(False)
|
|
|
+ text.status = FINISHED
|
|
|
+ text.setAutoDraw(False)
|
|
|
|
|
|
# check for quit (typically the Esc key)
|
|
|
if defaultKeyboard.getKeys(keyList=["escape"]):
|
|
@@ -976,6 +959,11 @@ def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
|
|
|
continueRoutine = True
|
|
|
# update component parameters for each repeat
|
|
|
thisExp.addData('mi_feedback.started', globalClock.getTime())
|
|
|
+ # Run 'Begin Routine' code from code
|
|
|
+ if feedback_time == 10:
|
|
|
+ feedback.text = '恭喜!'
|
|
|
+ else:
|
|
|
+ feedback.text = '继续努力!'
|
|
|
# keep track of which components have finished
|
|
|
mi_feedbackComponents = [feedback]
|
|
|
for thisComponent in mi_feedbackComponents:
|