grasp_data_collection_no_release.py 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. This experiment was created using PsychoPy3 Experiment Builder (v2023.2.3),
  5. on 十二月 18, 2023, at 10:48
  6. If you publish work using this script the most relevant publication is:
  7. Peirce J, Gray JR, Simpson S, MacAskill M, Höchenberger R, Sogo H, Kastman E, Lindeløv JK. (2019)
  8. PsychoPy2: Experiments in behavior made easy Behav Res 51: 195.
  9. https://doi.org/10.3758/s13428-018-01193-y
  10. """
  11. # --- Import packages ---
  12. from psychopy import locale_setup
  13. from psychopy import prefs
  14. from psychopy import plugins
  15. plugins.activatePlugins()
  16. prefs.hardware['audioLib'] = 'ptb'
  17. prefs.hardware['audioLatencyMode'] = '3'
  18. from psychopy import sound, gui, visual, core, data, event, logging, clock, colors, layout
  19. from psychopy.tools import environmenttools
  20. from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
  21. STOPPED, FINISHED, PRESSED, RELEASED, FOREVER, priority)
  22. import numpy as np # whole numpy lib is available, prepend 'np.'
  23. from numpy import (sin, cos, tan, log, log10, pi, average,
  24. sqrt, std, deg2rad, rad2deg, linspace, asarray)
  25. from numpy.random import random, randint, normal, shuffle, choice as randchoice
  26. import os # handy system and path functions
  27. import sys # to get file system encoding
  28. import psychopy.iohub as io
  29. from psychopy.hardware import keyboard
  30. # Run 'Before Experiment' code from config
  31. import argparse
  32. import time
  33. from device.fubo_pneumatic_finger import FuboPneumaticFingerClient
  34. from device.trigger_box import TriggerNeuracle
  35. from settings.config import settings
  36. # get train params
  37. def parse_args():
  38. parser = argparse.ArgumentParser(
  39. description='Grasp training'
  40. )
  41. parser.add_argument(
  42. '--n-trials',
  43. dest='n_trials',
  44. help='Trial number',
  45. type=int,
  46. )
  47. parser.add_argument(
  48. '--com',
  49. dest='com',
  50. help='Peripheral serial port',
  51. type=str
  52. )
  53. parser.add_argument(
  54. '--finger-model',
  55. '-fm',
  56. dest='finger_model',
  57. help='Gesture to train',
  58. type=str
  59. )
  60. return parser.parse_args()
  61. args = parse_args()
  62. hand_device = FuboPneumaticFingerClient({'port': args.com})
  63. # connect to trigger box
  64. trigger = TriggerNeuracle()
  65. # Run 'Before Experiment' code from code
  66. # --- Setup global variables (available in all functions) ---
  67. # Ensure that relative paths start from the same directory as this script
  68. _thisDir = os.path.dirname(os.path.abspath(__file__))
  69. # Store info about the experiment session
  70. psychopyVersion = '2023.2.3'
  71. expName = 'grasp_data_collection' # from the Builder filename that created this script
  72. expInfo = {
  73. 'participant': f"{randint(0, 999999):06.0f}",
  74. 'session': '001',
  75. 'date': data.getDateStr(), # add a simple timestamp
  76. 'expName': expName,
  77. 'psychopyVersion': psychopyVersion,
  78. }
  79. def showExpInfoDlg(expInfo):
  80. """
  81. Show participant info dialog.
  82. Parameters
  83. ==========
  84. expInfo : dict
  85. Information about this experiment, created by the `setupExpInfo` function.
  86. Returns
  87. ==========
  88. dict
  89. Information about this experiment.
  90. """
  91. # temporarily remove keys which the dialog doesn't need to show
  92. poppedKeys = {
  93. 'date': expInfo.pop('date', data.getDateStr()),
  94. 'expName': expInfo.pop('expName', expName),
  95. 'psychopyVersion': expInfo.pop('psychopyVersion', psychopyVersion),
  96. }
  97. # show participant info dialog
  98. dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName)
  99. if dlg.OK == False:
  100. core.quit() # user pressed cancel
  101. # restore hidden keys
  102. expInfo.update(poppedKeys)
  103. # return expInfo
  104. return expInfo
  105. def setupData(expInfo, dataDir=None):
  106. """
  107. Make an ExperimentHandler to handle trials and saving.
  108. Parameters
  109. ==========
  110. expInfo : dict
  111. Information about this experiment, created by the `setupExpInfo` function.
  112. dataDir : Path, str or None
  113. Folder to save the data to, leave as None to create a folder in the current directory.
  114. Returns
  115. ==========
  116. psychopy.data.ExperimentHandler
  117. Handler object for this experiment, contains the data to save and information about
  118. where to save it to.
  119. """
  120. # data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
  121. if dataDir is None:
  122. dataDir = _thisDir
  123. filename = u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])
  124. # make sure filename is relative to dataDir
  125. if os.path.isabs(filename):
  126. dataDir = os.path.commonprefix([dataDir, filename])
  127. filename = os.path.relpath(filename, dataDir)
  128. # an ExperimentHandler isn't essential but helps with data saving
  129. thisExp = data.ExperimentHandler(
  130. name=expName, version='',
  131. extraInfo=expInfo, runtimeInfo=None,
  132. originPath='D:\\Graduate\\kraken\\backend\\grasp_data_collection_no_release.py',
  133. savePickle=True, saveWideText=True,
  134. dataFileName=dataDir + os.sep + filename, sortColumns='time'
  135. )
  136. thisExp.setPriority('thisRow.t', priority.CRITICAL)
  137. thisExp.setPriority('expName', priority.LOW)
  138. # return experiment handler
  139. return thisExp
  140. def setupLogging(filename):
  141. """
  142. Setup a log file and tell it what level to log at.
  143. Parameters
  144. ==========
  145. filename : str or pathlib.Path
  146. Filename to save log file and data files as, doesn't need an extension.
  147. Returns
  148. ==========
  149. psychopy.logging.LogFile
  150. Text stream to receive inputs from the logging system.
  151. """
  152. # this outputs to the screen, not a file
  153. logging.console.setLevel(logging.EXP)
  154. # save a log file for detail verbose info
  155. logFile = logging.LogFile(filename+'.log', level=logging.EXP)
  156. return logFile
  157. def setupWindow(expInfo=None, win=None):
  158. """
  159. Setup the Window
  160. Parameters
  161. ==========
  162. expInfo : dict
  163. Information about this experiment, created by the `setupExpInfo` function.
  164. win : psychopy.visual.Window
  165. Window to setup - leave as None to create a new window.
  166. Returns
  167. ==========
  168. psychopy.visual.Window
  169. Window in which to run this experiment.
  170. """
  171. if win is None:
  172. # if not given a window to setup, make one
  173. win = visual.Window(
  174. size=[1707, 1067], fullscr=True, screen=0,
  175. winType='pyglet', allowStencil=False,
  176. monitor='testMonitor', color=[1,1,1], colorSpace='rgb',
  177. backgroundImage='', backgroundFit='none',
  178. blendMode='avg', useFBO=True,
  179. units='height'
  180. )
  181. if expInfo is not None:
  182. # store frame rate of monitor if we can measure it
  183. expInfo['frameRate'] = win.getActualFrameRate()
  184. else:
  185. # if we have a window, just set the attributes which are safe to set
  186. win.color = [1,1,1]
  187. win.colorSpace = 'rgb'
  188. win.backgroundImage = ''
  189. win.backgroundFit = 'none'
  190. win.units = 'height'
  191. win.mouseVisible = False
  192. win.hideMessage()
  193. return win
  194. def setupInputs(expInfo, thisExp, win):
  195. """
  196. Setup whatever inputs are available (mouse, keyboard, eyetracker, etc.)
  197. Parameters
  198. ==========
  199. expInfo : dict
  200. Information about this experiment, created by the `setupExpInfo` function.
  201. thisExp : psychopy.data.ExperimentHandler
  202. Handler object for this experiment, contains the data to save and information about
  203. where to save it to.
  204. win : psychopy.visual.Window
  205. Window in which to run this experiment.
  206. Returns
  207. ==========
  208. dict
  209. Dictionary of input devices by name.
  210. """
  211. # --- Setup input devices ---
  212. inputs = {}
  213. ioConfig = {}
  214. # Setup iohub keyboard
  215. ioConfig['Keyboard'] = dict(use_keymap='psychopy')
  216. ioSession = '1'
  217. if 'session' in expInfo:
  218. ioSession = str(expInfo['session'])
  219. ioServer = io.launchHubServer(window=win, **ioConfig)
  220. eyetracker = None
  221. # create a default keyboard (e.g. to check for escape)
  222. defaultKeyboard = keyboard.Keyboard(backend='iohub')
  223. # return inputs dict
  224. return {
  225. 'ioServer': ioServer,
  226. 'defaultKeyboard': defaultKeyboard,
  227. 'eyetracker': eyetracker,
  228. }
  229. def pauseExperiment(thisExp, inputs=None, win=None, timers=[], playbackComponents=[]):
  230. """
  231. Pause this experiment, preventing the flow from advancing to the next routine until resumed.
  232. Parameters
  233. ==========
  234. thisExp : psychopy.data.ExperimentHandler
  235. Handler object for this experiment, contains the data to save and information about
  236. where to save it to.
  237. inputs : dict
  238. Dictionary of input devices by name.
  239. win : psychopy.visual.Window
  240. Window for this experiment.
  241. timers : list, tuple
  242. List of timers to reset once pausing is finished.
  243. playbackComponents : list, tuple
  244. List of any components with a `pause` method which need to be paused.
  245. """
  246. # if we are not paused, do nothing
  247. if thisExp.status != PAUSED:
  248. return
  249. # pause any playback components
  250. for comp in playbackComponents:
  251. comp.pause()
  252. # prevent components from auto-drawing
  253. win.stashAutoDraw()
  254. # run a while loop while we wait to unpause
  255. while thisExp.status == PAUSED:
  256. # make sure we have a keyboard
  257. if inputs is None:
  258. inputs = {
  259. 'defaultKeyboard': keyboard.Keyboard(backend='ioHub')
  260. }
  261. # check for quit (typically the Esc key)
  262. if inputs['defaultKeyboard'].getKeys(keyList=['escape']):
  263. endExperiment(thisExp, win=win, inputs=inputs)
  264. # flip the screen
  265. win.flip()
  266. # if stop was requested while paused, quit
  267. if thisExp.status == FINISHED:
  268. endExperiment(thisExp, inputs=inputs, win=win)
  269. # resume any playback components
  270. for comp in playbackComponents:
  271. comp.play()
  272. # restore auto-drawn components
  273. win.retrieveAutoDraw()
  274. # reset any timers
  275. for timer in timers:
  276. timer.reset()
  277. def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
  278. """
  279. Run the experiment flow.
  280. Parameters
  281. ==========
  282. expInfo : dict
  283. Information about this experiment, created by the `setupExpInfo` function.
  284. thisExp : psychopy.data.ExperimentHandler
  285. Handler object for this experiment, contains the data to save and information about
  286. where to save it to.
  287. psychopy.visual.Window
  288. Window in which to run this experiment.
  289. inputs : dict
  290. Dictionary of input devices by name.
  291. globalClock : psychopy.core.clock.Clock or None
  292. Clock to get global time from - supply None to make a new one.
  293. thisSession : psychopy.session.Session or None
  294. Handle of the Session object this experiment is being run from, if any.
  295. """
  296. # mark experiment as started
  297. thisExp.status = STARTED
  298. # make sure variables created by exec are available globally
  299. exec = environmenttools.setExecEnvironment(globals())
  300. # get device handles from dict of input devices
  301. ioServer = inputs['ioServer']
  302. defaultKeyboard = inputs['defaultKeyboard']
  303. eyetracker = inputs['eyetracker']
  304. # make sure we're running in the directory for this experiment
  305. os.chdir(_thisDir)
  306. # get filename from ExperimentHandler for convenience
  307. filename = thisExp.dataFileName
  308. frameTolerance = 0.001 # how close to onset before 'same' frame
  309. endExpNow = False # flag for 'escape' or other condition => quit the exp
  310. # get frame duration from frame rate in expInfo
  311. if 'frameRate' in expInfo and expInfo['frameRate'] is not None:
  312. frameDur = 1.0 / round(expInfo['frameRate'])
  313. else:
  314. frameDur = 1.0 / 60.0 # could not measure, so guess
  315. # Start Code - component code to be run after the window creation
  316. # --- Initialize components for Routine "prepare" ---
  317. text = visual.TextStim(win=win, name='text',
  318. text='抓握训练即将开始\n如果准备好了,请按空格键',
  319. font='Open Sans',
  320. pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0,
  321. color='black', colorSpace='rgb', opacity=1.0,
  322. languageStyle='LTR',
  323. depth=0.0);
  324. key_resp = keyboard.Keyboard()
  325. # --- Initialize components for Routine "ready" ---
  326. ready_text = visual.TextStim(win=win, name='ready_text',
  327. text='请准备',
  328. font='Open Sans',
  329. pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0,
  330. color='black', colorSpace='rgb', opacity=None,
  331. languageStyle='LTR',
  332. depth=0.0);
  333. # --- Initialize components for Routine "flex" ---
  334. flex_img = visual.ImageStim(
  335. win=win,
  336. name='flex_img',
  337. image='static/images/flex.png', mask=None, anchor='center',
  338. ori=0.0, pos=(0, 0), size=(0.5, 0.5),
  339. color=[1,1,1], colorSpace='rgb', opacity=None,
  340. flipHoriz=False, flipVert=False,
  341. texRes=128.0, interpolate=True, depth=0.0)
  342. flex_wav = sound.Sound('static/audios/flex.wav', secs=2, stereo=True, hamming=True,
  343. name='flex_wav')
  344. flex_wav.setVolume(1.0)
  345. attention = sound.Sound('static/audios/ding.wav', secs=1.0, stereo=True, hamming=True,
  346. name='attention')
  347. attention.setVolume(1.0)
  348. # --- Initialize components for Routine "hold" ---
  349. hold_img = visual.ImageStim(
  350. win=win,
  351. name='hold_img',
  352. image='static/images/hold.png', mask=None, anchor='center',
  353. ori=0.0, pos=(0, 0), size=(0.5, 0.5),
  354. color=[1,1,1], colorSpace='rgb', opacity=None,
  355. flipHoriz=False, flipVert=False,
  356. texRes=128.0, interpolate=True, depth=0.0)
  357. hold_wav = sound.Sound('static/audios/hold.wav', secs=-1, stereo=True, hamming=True,
  358. name='hold_wav')
  359. hold_wav.setVolume(1.0)
  360. # --- Initialize components for Routine "extend" ---
  361. extend_img = visual.ImageStim(
  362. win=win,
  363. name='extend_img',
  364. image='static/images/extend.png', mask=None, anchor='center',
  365. ori=0.0, pos=(0, 0), size=(0.5, 0.5),
  366. color=[1,1,1], colorSpace='rgb', opacity=None,
  367. flipHoriz=False, flipVert=False,
  368. texRes=128.0, interpolate=True, depth=0.0)
  369. extend_wav = sound.Sound('static/audios/extend.wav', secs=2, stereo=True, hamming=True,
  370. name='extend_wav')
  371. extend_wav.setVolume(1.0)
  372. # --- Initialize components for Routine "rest" ---
  373. rest_img = visual.ImageStim(
  374. win=win,
  375. name='rest_img',
  376. image='static/images/rest.png', mask=None, anchor='center',
  377. ori=0.0, pos=(0, 0), size=(0.5, 0.5),
  378. color=[1,1,1], colorSpace='rgb', opacity=None,
  379. flipHoriz=False, flipVert=False,
  380. texRes=128.0, interpolate=True, depth=0.0)
  381. rest_wav1 = sound.Sound('static/audios/rest.wav', secs=2, stereo=True, hamming=True,
  382. name='rest_wav1')
  383. rest_wav1.setVolume(1.0)
  384. # --- Initialize components for Routine "end" ---
  385. end_text = visual.TextStim(win=win, name='end_text',
  386. text='恭喜您!\n完成训练!',
  387. font='Open Sans',
  388. pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0,
  389. color='black', colorSpace='rgb', opacity=1.0,
  390. languageStyle='LTR',
  391. depth=0.0);
  392. # create some handy timers
  393. if globalClock is None:
  394. globalClock = core.Clock() # to track the time since experiment started
  395. if ioServer is not None:
  396. ioServer.syncClock(globalClock)
  397. logging.setDefaultClock(globalClock)
  398. routineTimer = core.Clock() # to track time remaining of each (possibly non-slip) routine
  399. win.flip() # flip window to reset last flip timer
  400. # store the exact time the global clock started
  401. expInfo['expStart'] = data.getDateStr(format='%Y-%m-%d %Hh%M.%S.%f %z', fractionalSecondDigits=6)
  402. # --- Prepare to start Routine "prepare" ---
  403. continueRoutine = True
  404. # update component parameters for each repeat
  405. thisExp.addData('prepare.started', globalClock.getTime())
  406. key_resp.keys = []
  407. key_resp.rt = []
  408. _key_resp_allKeys = []
  409. # Run 'Begin Routine' code from config
  410. # keep track of which components have finished
  411. prepareComponents = [text, key_resp]
  412. for thisComponent in prepareComponents:
  413. thisComponent.tStart = None
  414. thisComponent.tStop = None
  415. thisComponent.tStartRefresh = None
  416. thisComponent.tStopRefresh = None
  417. if hasattr(thisComponent, 'status'):
  418. thisComponent.status = NOT_STARTED
  419. # reset timers
  420. t = 0
  421. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  422. frameN = -1
  423. # --- Run Routine "prepare" ---
  424. routineForceEnded = not continueRoutine
  425. while continueRoutine:
  426. # get current time
  427. t = routineTimer.getTime()
  428. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  429. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  430. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  431. # update/draw components on each frame
  432. # *text* updates
  433. # if text is starting this frame...
  434. if text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  435. # keep track of start time/frame for later
  436. text.frameNStart = frameN # exact frame index
  437. text.tStart = t # local t and not account for scr refresh
  438. text.tStartRefresh = tThisFlipGlobal # on global time
  439. win.timeOnFlip(text, 'tStartRefresh') # time at next scr refresh
  440. # add timestamp to datafile
  441. thisExp.timestampOnFlip(win, 'text.started')
  442. # update status
  443. text.status = STARTED
  444. text.setAutoDraw(True)
  445. # if text is active this frame...
  446. if text.status == STARTED:
  447. # update params
  448. pass
  449. # *key_resp* updates
  450. waitOnFlip = False
  451. # if key_resp is starting this frame...
  452. if key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  453. # keep track of start time/frame for later
  454. key_resp.frameNStart = frameN # exact frame index
  455. key_resp.tStart = t # local t and not account for scr refresh
  456. key_resp.tStartRefresh = tThisFlipGlobal # on global time
  457. win.timeOnFlip(key_resp, 'tStartRefresh') # time at next scr refresh
  458. # add timestamp to datafile
  459. thisExp.timestampOnFlip(win, 'key_resp.started')
  460. # update status
  461. key_resp.status = STARTED
  462. # keyboard checking is just starting
  463. waitOnFlip = True
  464. win.callOnFlip(key_resp.clock.reset) # t=0 on next screen flip
  465. win.callOnFlip(key_resp.clearEvents, eventType='keyboard') # clear events on next screen flip
  466. if key_resp.status == STARTED and not waitOnFlip:
  467. theseKeys = key_resp.getKeys(keyList=['space'], ignoreKeys=["escape"], waitRelease=False)
  468. _key_resp_allKeys.extend(theseKeys)
  469. if len(_key_resp_allKeys):
  470. key_resp.keys = _key_resp_allKeys[-1].name # just the last key pressed
  471. key_resp.rt = _key_resp_allKeys[-1].rt
  472. key_resp.duration = _key_resp_allKeys[-1].duration
  473. # a response ends the routine
  474. continueRoutine = False
  475. # check for quit (typically the Esc key)
  476. if defaultKeyboard.getKeys(keyList=["escape"]):
  477. thisExp.status = FINISHED
  478. if thisExp.status == FINISHED or endExpNow:
  479. endExperiment(thisExp, inputs=inputs, win=win)
  480. return
  481. # check if all components have finished
  482. if not continueRoutine: # a component has requested a forced-end of Routine
  483. routineForceEnded = True
  484. break
  485. continueRoutine = False # will revert to True if at least one component still running
  486. for thisComponent in prepareComponents:
  487. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  488. continueRoutine = True
  489. break # at least one component has not yet finished
  490. # refresh the screen
  491. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  492. win.flip()
  493. # --- Ending Routine "prepare" ---
  494. for thisComponent in prepareComponents:
  495. if hasattr(thisComponent, "setAutoDraw"):
  496. thisComponent.setAutoDraw(False)
  497. thisExp.addData('prepare.stopped', globalClock.getTime())
  498. # check responses
  499. if key_resp.keys in ['', [], None]: # No response was made
  500. key_resp.keys = None
  501. thisExp.addData('key_resp.keys',key_resp.keys)
  502. if key_resp.keys != None: # we had a response
  503. thisExp.addData('key_resp.rt', key_resp.rt)
  504. thisExp.addData('key_resp.duration', key_resp.duration)
  505. thisExp.nextEntry()
  506. # the Routine "prepare" was not non-slip safe, so reset the non-slip timer
  507. routineTimer.reset()
  508. # set up handler to look after randomisation of conditions etc
  509. trials = data.TrialHandler(nReps=args.n_trials, method='random',
  510. extraInfo=expInfo, originPath=-1,
  511. trialList=[None],
  512. seed=None, name='trials')
  513. thisExp.addLoop(trials) # add the loop to the experiment
  514. thisTrial = trials.trialList[0] # so we can initialise stimuli with some values
  515. # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
  516. if thisTrial != None:
  517. for paramName in thisTrial:
  518. globals()[paramName] = thisTrial[paramName]
  519. for thisTrial in trials:
  520. currentLoop = trials
  521. thisExp.timestampOnFlip(win, 'thisRow.t')
  522. # pause experiment here if requested
  523. if thisExp.status == PAUSED:
  524. pauseExperiment(
  525. thisExp=thisExp,
  526. inputs=inputs,
  527. win=win,
  528. timers=[routineTimer],
  529. playbackComponents=[]
  530. )
  531. # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
  532. if thisTrial != None:
  533. for paramName in thisTrial:
  534. globals()[paramName] = thisTrial[paramName]
  535. # --- Prepare to start Routine "ready" ---
  536. continueRoutine = True
  537. # update component parameters for each repeat
  538. thisExp.addData('ready.started', globalClock.getTime())
  539. # keep track of which components have finished
  540. readyComponents = [ready_text]
  541. for thisComponent in readyComponents:
  542. thisComponent.tStart = None
  543. thisComponent.tStop = None
  544. thisComponent.tStartRefresh = None
  545. thisComponent.tStopRefresh = None
  546. if hasattr(thisComponent, 'status'):
  547. thisComponent.status = NOT_STARTED
  548. # reset timers
  549. t = 0
  550. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  551. frameN = -1
  552. # --- Run Routine "ready" ---
  553. routineForceEnded = not continueRoutine
  554. while continueRoutine and routineTimer.getTime() < 1.5:
  555. # get current time
  556. t = routineTimer.getTime()
  557. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  558. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  559. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  560. # update/draw components on each frame
  561. # *ready_text* updates
  562. # if ready_text is starting this frame...
  563. if ready_text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  564. # keep track of start time/frame for later
  565. ready_text.frameNStart = frameN # exact frame index
  566. ready_text.tStart = t # local t and not account for scr refresh
  567. ready_text.tStartRefresh = tThisFlipGlobal # on global time
  568. win.timeOnFlip(ready_text, 'tStartRefresh') # time at next scr refresh
  569. # add timestamp to datafile
  570. thisExp.timestampOnFlip(win, 'ready_text.started')
  571. # update status
  572. ready_text.status = STARTED
  573. ready_text.setAutoDraw(True)
  574. # if ready_text is active this frame...
  575. if ready_text.status == STARTED:
  576. # update params
  577. pass
  578. # if ready_text is stopping this frame...
  579. if ready_text.status == STARTED:
  580. # is it time to stop? (based on global clock, using actual start)
  581. if tThisFlipGlobal > ready_text.tStartRefresh + 1.5-frameTolerance:
  582. # keep track of stop time/frame for later
  583. ready_text.tStop = t # not accounting for scr refresh
  584. ready_text.frameNStop = frameN # exact frame index
  585. # add timestamp to datafile
  586. thisExp.timestampOnFlip(win, 'ready_text.stopped')
  587. # update status
  588. ready_text.status = FINISHED
  589. ready_text.setAutoDraw(False)
  590. # check for quit (typically the Esc key)
  591. if defaultKeyboard.getKeys(keyList=["escape"]):
  592. thisExp.status = FINISHED
  593. if thisExp.status == FINISHED or endExpNow:
  594. endExperiment(thisExp, inputs=inputs, win=win)
  595. return
  596. # check if all components have finished
  597. if not continueRoutine: # a component has requested a forced-end of Routine
  598. routineForceEnded = True
  599. break
  600. continueRoutine = False # will revert to True if at least one component still running
  601. for thisComponent in readyComponents:
  602. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  603. continueRoutine = True
  604. break # at least one component has not yet finished
  605. # refresh the screen
  606. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  607. win.flip()
  608. # --- Ending Routine "ready" ---
  609. for thisComponent in readyComponents:
  610. if hasattr(thisComponent, "setAutoDraw"):
  611. thisComponent.setAutoDraw(False)
  612. thisExp.addData('ready.stopped', globalClock.getTime())
  613. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  614. if routineForceEnded:
  615. routineTimer.reset()
  616. else:
  617. routineTimer.addTime(-1.500000)
  618. # --- Prepare to start Routine "flex" ---
  619. continueRoutine = True
  620. # update component parameters for each repeat
  621. thisExp.addData('flex.started', globalClock.getTime())
  622. # Run 'Begin Routine' code from code_2
  623. i = 0
  624. flex_wav.setSound('static/audios/flex.wav', secs=2, hamming=True)
  625. flex_wav.setVolume(1.0, log=False)
  626. flex_wav.seek(0)
  627. attention.setSound('static/audios/ding.wav', secs=1.0, hamming=True)
  628. attention.setVolume(1.0, log=False)
  629. attention.seek(0)
  630. # keep track of which components have finished
  631. flexComponents = [flex_img, flex_wav, attention]
  632. for thisComponent in flexComponents:
  633. thisComponent.tStart = None
  634. thisComponent.tStop = None
  635. thisComponent.tStartRefresh = None
  636. thisComponent.tStopRefresh = None
  637. if hasattr(thisComponent, 'status'):
  638. thisComponent.status = NOT_STARTED
  639. # reset timers
  640. t = 0
  641. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  642. frameN = -1
  643. # --- Run Routine "flex" ---
  644. routineForceEnded = not continueRoutine
  645. while continueRoutine and routineTimer.getTime() < 7.0:
  646. # get current time
  647. t = routineTimer.getTime()
  648. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  649. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  650. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  651. # update/draw components on each frame
  652. # *flex_img* updates
  653. # if flex_img is starting this frame...
  654. if flex_img.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
  655. # keep track of start time/frame for later
  656. flex_img.frameNStart = frameN # exact frame index
  657. flex_img.tStart = t # local t and not account for scr refresh
  658. flex_img.tStartRefresh = tThisFlipGlobal # on global time
  659. win.timeOnFlip(flex_img, 'tStartRefresh') # time at next scr refresh
  660. # add timestamp to datafile
  661. thisExp.timestampOnFlip(win, 'flex_img.started')
  662. # update status
  663. flex_img.status = STARTED
  664. flex_img.setAutoDraw(True)
  665. # if flex_img is active this frame...
  666. if flex_img.status == STARTED:
  667. # update params
  668. pass
  669. # if flex_img is stopping this frame...
  670. if flex_img.status == STARTED:
  671. # is it time to stop? (based on global clock, using actual start)
  672. if tThisFlipGlobal > flex_img.tStartRefresh + 6-frameTolerance:
  673. # keep track of stop time/frame for later
  674. flex_img.tStop = t # not accounting for scr refresh
  675. flex_img.frameNStop = frameN # exact frame index
  676. # add timestamp to datafile
  677. thisExp.timestampOnFlip(win, 'flex_img.stopped')
  678. # update status
  679. flex_img.status = FINISHED
  680. flex_img.setAutoDraw(False)
  681. # Run 'Each Frame' code from code_2
  682. if i == 119:
  683. hand_device.start(args.finger_model)
  684. # trigger
  685. current_true_label = settings.FINGERMODEL_IDS[args.finger_model]
  686. win.callOnFlip(trigger.send_trigger, current_true_label)
  687. i += 1
  688. # 每轮开始前空白等待1s + 反应时1s + 新版flex时间4.5s + 0.5s裕量 = 7s。
  689. # flex trigger打出5s(flex图片显示7s)后,hold图片显示。
  690. # if flex_wav is starting this frame...
  691. if flex_wav.status == NOT_STARTED and tThisFlip >= 1.8-frameTolerance:
  692. # keep track of start time/frame for later
  693. flex_wav.frameNStart = frameN # exact frame index
  694. flex_wav.tStart = t # local t and not account for scr refresh
  695. flex_wav.tStartRefresh = tThisFlipGlobal # on global time
  696. # add timestamp to datafile
  697. thisExp.addData('flex_wav.started', tThisFlipGlobal)
  698. # update status
  699. flex_wav.status = STARTED
  700. flex_wav.play(when=win) # sync with win flip
  701. # if flex_wav is stopping this frame...
  702. if flex_wav.status == STARTED:
  703. # is it time to stop? (based on global clock, using actual start)
  704. if tThisFlipGlobal > flex_wav.tStartRefresh + 2-frameTolerance:
  705. # keep track of stop time/frame for later
  706. flex_wav.tStop = t # not accounting for scr refresh
  707. flex_wav.frameNStop = frameN # exact frame index
  708. # add timestamp to datafile
  709. thisExp.timestampOnFlip(win, 'flex_wav.stopped')
  710. # update status
  711. flex_wav.status = FINISHED
  712. flex_wav.stop()
  713. # update flex_wav status according to whether it's playing
  714. if flex_wav.isPlaying:
  715. flex_wav.status = STARTED
  716. elif flex_wav.isFinished:
  717. flex_wav.status = FINISHED
  718. # if attention is starting this frame...
  719. if attention.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
  720. # keep track of start time/frame for later
  721. attention.frameNStart = frameN # exact frame index
  722. attention.tStart = t # local t and not account for scr refresh
  723. attention.tStartRefresh = tThisFlipGlobal # on global time
  724. # add timestamp to datafile
  725. thisExp.addData('attention.started', tThisFlipGlobal)
  726. # update status
  727. attention.status = STARTED
  728. attention.play(when=win) # sync with win flip
  729. # if attention is stopping this frame...
  730. if attention.status == STARTED:
  731. # is it time to stop? (based on global clock, using actual start)
  732. if tThisFlipGlobal > attention.tStartRefresh + 1.0-frameTolerance:
  733. # keep track of stop time/frame for later
  734. attention.tStop = t # not accounting for scr refresh
  735. attention.frameNStop = frameN # exact frame index
  736. # add timestamp to datafile
  737. thisExp.timestampOnFlip(win, 'attention.stopped')
  738. # update status
  739. attention.status = FINISHED
  740. attention.stop()
  741. # update attention status according to whether it's playing
  742. if attention.isPlaying:
  743. attention.status = STARTED
  744. elif attention.isFinished:
  745. attention.status = FINISHED
  746. # check for quit (typically the Esc key)
  747. if defaultKeyboard.getKeys(keyList=["escape"]):
  748. thisExp.status = FINISHED
  749. if thisExp.status == FINISHED or endExpNow:
  750. endExperiment(thisExp, inputs=inputs, win=win)
  751. return
  752. # check if all components have finished
  753. if not continueRoutine: # a component has requested a forced-end of Routine
  754. routineForceEnded = True
  755. break
  756. continueRoutine = False # will revert to True if at least one component still running
  757. for thisComponent in flexComponents:
  758. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  759. continueRoutine = True
  760. break # at least one component has not yet finished
  761. # refresh the screen
  762. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  763. win.flip()
  764. # --- Ending Routine "flex" ---
  765. for thisComponent in flexComponents:
  766. if hasattr(thisComponent, "setAutoDraw"):
  767. thisComponent.setAutoDraw(False)
  768. thisExp.addData('flex.stopped', globalClock.getTime())
  769. flex_wav.pause() # ensure sound has stopped at end of Routine
  770. attention.pause() # ensure sound has stopped at end of Routine
  771. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  772. if routineForceEnded:
  773. routineTimer.reset()
  774. else:
  775. routineTimer.addTime(-7.000000)
  776. # --- Prepare to start Routine "hold" ---
  777. continueRoutine = True
  778. # update component parameters for each repeat
  779. thisExp.addData('hold.started', globalClock.getTime())
  780. # Run 'Begin Routine' code from code_3
  781. win.callOnFlip(trigger.send_trigger, settings.FINGERMODEL_IDS['hold'])
  782. # hold trigger(图片)后5s,出现extend图片
  783. hold_wav.setSound('static/audios/hold.wav', secs=2.5, hamming=True)
  784. hold_wav.setVolume(1.0, log=False)
  785. hold_wav.seek(0)
  786. # keep track of which components have finished
  787. holdComponents = [hold_img, hold_wav]
  788. for thisComponent in holdComponents:
  789. thisComponent.tStart = None
  790. thisComponent.tStop = None
  791. thisComponent.tStartRefresh = None
  792. thisComponent.tStopRefresh = None
  793. if hasattr(thisComponent, 'status'):
  794. thisComponent.status = NOT_STARTED
  795. # reset timers
  796. t = 0
  797. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  798. frameN = -1
  799. # --- Run Routine "hold" ---
  800. routineForceEnded = not continueRoutine
  801. while continueRoutine and routineTimer.getTime() < 5.0:
  802. # get current time
  803. t = routineTimer.getTime()
  804. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  805. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  806. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  807. # update/draw components on each frame
  808. # *hold_img* updates
  809. # if hold_img is starting this frame...
  810. if hold_img.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  811. # keep track of start time/frame for later
  812. hold_img.frameNStart = frameN # exact frame index
  813. hold_img.tStart = t # local t and not account for scr refresh
  814. hold_img.tStartRefresh = tThisFlipGlobal # on global time
  815. win.timeOnFlip(hold_img, 'tStartRefresh') # time at next scr refresh
  816. # add timestamp to datafile
  817. thisExp.timestampOnFlip(win, 'hold_img.started')
  818. # update status
  819. hold_img.status = STARTED
  820. hold_img.setAutoDraw(True)
  821. # if hold_img is active this frame...
  822. if hold_img.status == STARTED:
  823. # update params
  824. pass
  825. # if hold_img is stopping this frame...
  826. if hold_img.status == STARTED:
  827. # is it time to stop? (based on global clock, using actual start)
  828. if tThisFlipGlobal > hold_img.tStartRefresh + 5-frameTolerance:
  829. # keep track of stop time/frame for later
  830. hold_img.tStop = t # not accounting for scr refresh
  831. hold_img.frameNStop = frameN # exact frame index
  832. # add timestamp to datafile
  833. thisExp.timestampOnFlip(win, 'hold_img.stopped')
  834. # update status
  835. hold_img.status = FINISHED
  836. hold_img.setAutoDraw(False)
  837. # if hold_wav is starting this frame...
  838. if hold_wav.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  839. # keep track of start time/frame for later
  840. hold_wav.frameNStart = frameN # exact frame index
  841. hold_wav.tStart = t # local t and not account for scr refresh
  842. hold_wav.tStartRefresh = tThisFlipGlobal # on global time
  843. # add timestamp to datafile
  844. thisExp.addData('hold_wav.started', tThisFlipGlobal)
  845. # update status
  846. hold_wav.status = STARTED
  847. hold_wav.play(when=win) # sync with win flip
  848. # if hold_wav is stopping this frame...
  849. if hold_wav.status == STARTED:
  850. # is it time to stop? (based on global clock, using actual start)
  851. if tThisFlipGlobal > hold_wav.tStartRefresh + 2.5-frameTolerance:
  852. # keep track of stop time/frame for later
  853. hold_wav.tStop = t # not accounting for scr refresh
  854. hold_wav.frameNStop = frameN # exact frame index
  855. # add timestamp to datafile
  856. thisExp.timestampOnFlip(win, 'hold_wav.stopped')
  857. # update status
  858. hold_wav.status = FINISHED
  859. hold_wav.stop()
  860. # update hold_wav status according to whether it's playing
  861. if hold_wav.isPlaying:
  862. hold_wav.status = STARTED
  863. elif hold_wav.isFinished:
  864. hold_wav.status = FINISHED
  865. # check for quit (typically the Esc key)
  866. if defaultKeyboard.getKeys(keyList=["escape"]):
  867. thisExp.status = FINISHED
  868. if thisExp.status == FINISHED or endExpNow:
  869. endExperiment(thisExp, inputs=inputs, win=win)
  870. return
  871. # check if all components have finished
  872. if not continueRoutine: # a component has requested a forced-end of Routine
  873. routineForceEnded = True
  874. break
  875. continueRoutine = False # will revert to True if at least one component still running
  876. for thisComponent in holdComponents:
  877. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  878. continueRoutine = True
  879. break # at least one component has not yet finished
  880. # refresh the screen
  881. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  882. win.flip()
  883. # --- Ending Routine "hold" ---
  884. for thisComponent in holdComponents:
  885. if hasattr(thisComponent, "setAutoDraw"):
  886. thisComponent.setAutoDraw(False)
  887. thisExp.addData('hold.stopped', globalClock.getTime())
  888. hold_wav.pause() # ensure sound has stopped at end of Routine
  889. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  890. if routineForceEnded:
  891. routineTimer.reset()
  892. else:
  893. routineTimer.addTime(-5.000000)
  894. # --- Prepare to start Routine "extend" ---
  895. continueRoutine = True
  896. # update component parameters for each repeat
  897. thisExp.addData('extend.started', globalClock.getTime())
  898. # Run 'Begin Routine' code from code
  899. i = 0
  900. extend_wav.setSound('static/audios/extend.wav', secs=2, hamming=True)
  901. extend_wav.setVolume(1.0, log=False)
  902. extend_wav.seek(0)
  903. # keep track of which components have finished
  904. extendComponents = [extend_img, extend_wav]
  905. for thisComponent in extendComponents:
  906. thisComponent.tStart = None
  907. thisComponent.tStop = None
  908. thisComponent.tStartRefresh = None
  909. thisComponent.tStopRefresh = None
  910. if hasattr(thisComponent, 'status'):
  911. thisComponent.status = NOT_STARTED
  912. # reset timers
  913. t = 0
  914. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  915. frameN = -1
  916. # --- Run Routine "extend" ---
  917. routineForceEnded = not continueRoutine
  918. while continueRoutine and routineTimer.getTime() < 6.0:
  919. # get current time
  920. t = routineTimer.getTime()
  921. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  922. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  923. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  924. # update/draw components on each frame
  925. # *extend_img* updates
  926. # if extend_img is starting this frame...
  927. if extend_img.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
  928. # keep track of start time/frame for later
  929. extend_img.frameNStart = frameN # exact frame index
  930. extend_img.tStart = t # local t and not account for scr refresh
  931. extend_img.tStartRefresh = tThisFlipGlobal # on global time
  932. win.timeOnFlip(extend_img, 'tStartRefresh') # time at next scr refresh
  933. # add timestamp to datafile
  934. thisExp.timestampOnFlip(win, 'extend_img.started')
  935. # update status
  936. extend_img.status = STARTED
  937. extend_img.setAutoDraw(True)
  938. # if extend_img is active this frame...
  939. if extend_img.status == STARTED:
  940. # update params
  941. pass
  942. # if extend_img is stopping this frame...
  943. if extend_img.status == STARTED:
  944. # is it time to stop? (based on global clock, using actual start)
  945. if tThisFlipGlobal > extend_img.tStartRefresh + 6-frameTolerance:
  946. # keep track of stop time/frame for later
  947. extend_img.tStop = t # not accounting for scr refresh
  948. extend_img.frameNStop = frameN # exact frame index
  949. # add timestamp to datafile
  950. thisExp.timestampOnFlip(win, 'extend_img.stopped')
  951. # update status
  952. extend_img.status = FINISHED
  953. extend_img.setAutoDraw(False)
  954. # Run 'Each Frame' code from code
  955. if i== 59:
  956. hand_device.start('extend')
  957. # send trigger
  958. current_true_label = settings.FINGERMODEL_IDS['extend']
  959. win.callOnFlip(trigger.send_trigger, current_true_label)
  960. i += 1
  961. # 反应时1s + 新版extend时间4.5s + 0.5s裕量 = 6s
  962. # extend 图片出现后6s,extend trigger后5s,rest图片出现
  963. # if extend_wav is starting this frame...
  964. if extend_wav.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
  965. # keep track of start time/frame for later
  966. extend_wav.frameNStart = frameN # exact frame index
  967. extend_wav.tStart = t # local t and not account for scr refresh
  968. extend_wav.tStartRefresh = tThisFlipGlobal # on global time
  969. # add timestamp to datafile
  970. thisExp.addData('extend_wav.started', tThisFlipGlobal)
  971. # update status
  972. extend_wav.status = STARTED
  973. extend_wav.play(when=win) # sync with win flip
  974. # if extend_wav is stopping this frame...
  975. if extend_wav.status == STARTED:
  976. # is it time to stop? (based on global clock, using actual start)
  977. if tThisFlipGlobal > extend_wav.tStartRefresh + 2-frameTolerance:
  978. # keep track of stop time/frame for later
  979. extend_wav.tStop = t # not accounting for scr refresh
  980. extend_wav.frameNStop = frameN # exact frame index
  981. # add timestamp to datafile
  982. thisExp.timestampOnFlip(win, 'extend_wav.stopped')
  983. # update status
  984. extend_wav.status = FINISHED
  985. extend_wav.stop()
  986. # update extend_wav status according to whether it's playing
  987. if extend_wav.isPlaying:
  988. extend_wav.status = STARTED
  989. elif extend_wav.isFinished:
  990. extend_wav.status = FINISHED
  991. # check for quit (typically the Esc key)
  992. if defaultKeyboard.getKeys(keyList=["escape"]):
  993. thisExp.status = FINISHED
  994. if thisExp.status == FINISHED or endExpNow:
  995. endExperiment(thisExp, inputs=inputs, win=win)
  996. return
  997. # check if all components have finished
  998. if not continueRoutine: # a component has requested a forced-end of Routine
  999. routineForceEnded = True
  1000. break
  1001. continueRoutine = False # will revert to True if at least one component still running
  1002. for thisComponent in extendComponents:
  1003. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  1004. continueRoutine = True
  1005. break # at least one component has not yet finished
  1006. # refresh the screen
  1007. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  1008. win.flip()
  1009. # --- Ending Routine "extend" ---
  1010. for thisComponent in extendComponents:
  1011. if hasattr(thisComponent, "setAutoDraw"):
  1012. thisComponent.setAutoDraw(False)
  1013. thisExp.addData('extend.stopped', globalClock.getTime())
  1014. extend_wav.pause() # ensure sound has stopped at end of Routine
  1015. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  1016. if routineForceEnded:
  1017. routineTimer.reset()
  1018. else:
  1019. routineTimer.addTime(-6.000000)
  1020. # --- Prepare to start Routine "rest" ---
  1021. continueRoutine = True
  1022. # update component parameters for each repeat
  1023. thisExp.addData('rest.started', globalClock.getTime())
  1024. # Run 'Begin Routine' code from code_4
  1025. i = 0
  1026. rest_wav1.setSound('static/audios/rest.wav', secs=2, hamming=True)
  1027. rest_wav1.setVolume(1.0, log=False)
  1028. rest_wav1.seek(0)
  1029. # keep track of which components have finished
  1030. restComponents = [rest_img, rest_wav1]
  1031. for thisComponent in restComponents:
  1032. thisComponent.tStart = None
  1033. thisComponent.tStop = None
  1034. thisComponent.tStartRefresh = None
  1035. thisComponent.tStopRefresh = None
  1036. if hasattr(thisComponent, 'status'):
  1037. thisComponent.status = NOT_STARTED
  1038. # reset timers
  1039. t = 0
  1040. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  1041. frameN = -1
  1042. # --- Run Routine "rest" ---
  1043. routineForceEnded = not continueRoutine
  1044. while continueRoutine and routineTimer.getTime() < 6.0:
  1045. # get current time
  1046. t = routineTimer.getTime()
  1047. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  1048. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  1049. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  1050. # update/draw components on each frame
  1051. # *rest_img* updates
  1052. # if rest_img is starting this frame...
  1053. if rest_img.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  1054. # keep track of start time/frame for later
  1055. rest_img.frameNStart = frameN # exact frame index
  1056. rest_img.tStart = t # local t and not account for scr refresh
  1057. rest_img.tStartRefresh = tThisFlipGlobal # on global time
  1058. win.timeOnFlip(rest_img, 'tStartRefresh') # time at next scr refresh
  1059. # add timestamp to datafile
  1060. thisExp.timestampOnFlip(win, 'rest_img.started')
  1061. # update status
  1062. rest_img.status = STARTED
  1063. rest_img.setAutoDraw(True)
  1064. # if rest_img is active this frame...
  1065. if rest_img.status == STARTED:
  1066. # update params
  1067. pass
  1068. # if rest_img is stopping this frame...
  1069. if rest_img.status == STARTED:
  1070. # is it time to stop? (based on global clock, using actual start)
  1071. if tThisFlipGlobal > rest_img.tStartRefresh + 6-frameTolerance:
  1072. # keep track of stop time/frame for later
  1073. rest_img.tStop = t # not accounting for scr refresh
  1074. rest_img.frameNStop = frameN # exact frame index
  1075. # add timestamp to datafile
  1076. thisExp.timestampOnFlip(win, 'rest_img.stopped')
  1077. # update status
  1078. rest_img.status = FINISHED
  1079. rest_img.setAutoDraw(False)
  1080. # Run 'Each Frame' code from code_4
  1081. if i== 59:
  1082. # hand_device.start('rest')
  1083. # trigger
  1084. win.callOnFlip(trigger.send_trigger, settings.FINGERMODEL_IDS['rest'])
  1085. i += 1
  1086. # if rest_wav1 is starting this frame...
  1087. if rest_wav1.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
  1088. # keep track of start time/frame for later
  1089. rest_wav1.frameNStart = frameN # exact frame index
  1090. rest_wav1.tStart = t # local t and not account for scr refresh
  1091. rest_wav1.tStartRefresh = tThisFlipGlobal # on global time
  1092. # add timestamp to datafile
  1093. thisExp.addData('rest_wav1.started', tThisFlipGlobal)
  1094. # update status
  1095. rest_wav1.status = STARTED
  1096. rest_wav1.play(when=win) # sync with win flip
  1097. # if rest_wav1 is stopping this frame...
  1098. if rest_wav1.status == STARTED:
  1099. # is it time to stop? (based on global clock, using actual start)
  1100. if tThisFlipGlobal > rest_wav1.tStartRefresh + 2-frameTolerance:
  1101. # keep track of stop time/frame for later
  1102. rest_wav1.tStop = t # not accounting for scr refresh
  1103. rest_wav1.frameNStop = frameN # exact frame index
  1104. # add timestamp to datafile
  1105. thisExp.timestampOnFlip(win, 'rest_wav1.stopped')
  1106. # update status
  1107. rest_wav1.status = FINISHED
  1108. rest_wav1.stop()
  1109. # update rest_wav1 status according to whether it's playing
  1110. if rest_wav1.isPlaying:
  1111. rest_wav1.status = STARTED
  1112. elif rest_wav1.isFinished:
  1113. rest_wav1.status = FINISHED
  1114. # check for quit (typically the Esc key)
  1115. if defaultKeyboard.getKeys(keyList=["escape"]):
  1116. thisExp.status = FINISHED
  1117. if thisExp.status == FINISHED or endExpNow:
  1118. endExperiment(thisExp, inputs=inputs, win=win)
  1119. return
  1120. # check if all components have finished
  1121. if not continueRoutine: # a component has requested a forced-end of Routine
  1122. routineForceEnded = True
  1123. break
  1124. continueRoutine = False # will revert to True if at least one component still running
  1125. for thisComponent in restComponents:
  1126. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  1127. continueRoutine = True
  1128. break # at least one component has not yet finished
  1129. # refresh the screen
  1130. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  1131. win.flip()
  1132. # --- Ending Routine "rest" ---
  1133. for thisComponent in restComponents:
  1134. if hasattr(thisComponent, "setAutoDraw"):
  1135. thisComponent.setAutoDraw(False)
  1136. thisExp.addData('rest.stopped', globalClock.getTime())
  1137. rest_wav1.pause() # ensure sound has stopped at end of Routine
  1138. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  1139. if routineForceEnded:
  1140. routineTimer.reset()
  1141. else:
  1142. routineTimer.addTime(-6.000000)
  1143. thisExp.nextEntry()
  1144. if thisSession is not None:
  1145. # if running in a Session with a Liaison client, send data up to now
  1146. thisSession.sendExperimentData()
  1147. # completed args.n_trials repeats of 'trials'
  1148. # --- Prepare to start Routine "end" ---
  1149. continueRoutine = True
  1150. # update component parameters for each repeat
  1151. thisExp.addData('end.started', globalClock.getTime())
  1152. # keep track of which components have finished
  1153. endComponents = [end_text]
  1154. for thisComponent in endComponents:
  1155. thisComponent.tStart = None
  1156. thisComponent.tStop = None
  1157. thisComponent.tStartRefresh = None
  1158. thisComponent.tStopRefresh = None
  1159. if hasattr(thisComponent, 'status'):
  1160. thisComponent.status = NOT_STARTED
  1161. # reset timers
  1162. t = 0
  1163. _timeToFirstFrame = win.getFutureFlipTime(clock="now")
  1164. frameN = -1
  1165. # --- Run Routine "end" ---
  1166. routineForceEnded = not continueRoutine
  1167. while continueRoutine and routineTimer.getTime() < 3.0:
  1168. # get current time
  1169. t = routineTimer.getTime()
  1170. tThisFlip = win.getFutureFlipTime(clock=routineTimer)
  1171. tThisFlipGlobal = win.getFutureFlipTime(clock=None)
  1172. frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
  1173. # update/draw components on each frame
  1174. # *end_text* updates
  1175. # if end_text is starting this frame...
  1176. if end_text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
  1177. # keep track of start time/frame for later
  1178. end_text.frameNStart = frameN # exact frame index
  1179. end_text.tStart = t # local t and not account for scr refresh
  1180. end_text.tStartRefresh = tThisFlipGlobal # on global time
  1181. win.timeOnFlip(end_text, 'tStartRefresh') # time at next scr refresh
  1182. # add timestamp to datafile
  1183. thisExp.timestampOnFlip(win, 'end_text.started')
  1184. # update status
  1185. end_text.status = STARTED
  1186. end_text.setAutoDraw(True)
  1187. # if end_text is active this frame...
  1188. if end_text.status == STARTED:
  1189. # update params
  1190. pass
  1191. # if end_text is stopping this frame...
  1192. if end_text.status == STARTED:
  1193. # is it time to stop? (based on global clock, using actual start)
  1194. if tThisFlipGlobal > end_text.tStartRefresh + 3-frameTolerance:
  1195. # keep track of stop time/frame for later
  1196. end_text.tStop = t # not accounting for scr refresh
  1197. end_text.frameNStop = frameN # exact frame index
  1198. # add timestamp to datafile
  1199. thisExp.timestampOnFlip(win, 'end_text.stopped')
  1200. # update status
  1201. end_text.status = FINISHED
  1202. end_text.setAutoDraw(False)
  1203. # check for quit (typically the Esc key)
  1204. if defaultKeyboard.getKeys(keyList=["escape"]):
  1205. thisExp.status = FINISHED
  1206. if thisExp.status == FINISHED or endExpNow:
  1207. endExperiment(thisExp, inputs=inputs, win=win)
  1208. return
  1209. # check if all components have finished
  1210. if not continueRoutine: # a component has requested a forced-end of Routine
  1211. routineForceEnded = True
  1212. break
  1213. continueRoutine = False # will revert to True if at least one component still running
  1214. for thisComponent in endComponents:
  1215. if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
  1216. continueRoutine = True
  1217. break # at least one component has not yet finished
  1218. # refresh the screen
  1219. if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
  1220. win.flip()
  1221. # --- Ending Routine "end" ---
  1222. for thisComponent in endComponents:
  1223. if hasattr(thisComponent, "setAutoDraw"):
  1224. thisComponent.setAutoDraw(False)
  1225. thisExp.addData('end.stopped', globalClock.getTime())
  1226. # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
  1227. if routineForceEnded:
  1228. routineTimer.reset()
  1229. else:
  1230. routineTimer.addTime(-3.000000)
  1231. # mark experiment as finished
  1232. endExperiment(thisExp, win=win, inputs=inputs)
  1233. def saveData(thisExp):
  1234. """
  1235. Save data from this experiment
  1236. Parameters
  1237. ==========
  1238. thisExp : psychopy.data.ExperimentHandler
  1239. Handler object for this experiment, contains the data to save and information about
  1240. where to save it to.
  1241. """
  1242. filename = thisExp.dataFileName
  1243. # these shouldn't be strictly necessary (should auto-save)
  1244. thisExp.saveAsWideText(filename + '.csv', delim='auto')
  1245. thisExp.saveAsPickle(filename)
  1246. def endExperiment(thisExp, inputs=None, win=None):
  1247. """
  1248. End this experiment, performing final shut down operations.
  1249. This function does NOT close the window or end the Python process - use `quit` for this.
  1250. Parameters
  1251. ==========
  1252. thisExp : psychopy.data.ExperimentHandler
  1253. Handler object for this experiment, contains the data to save and information about
  1254. where to save it to.
  1255. inputs : dict
  1256. Dictionary of input devices by name.
  1257. win : psychopy.visual.Window
  1258. Window for this experiment.
  1259. """
  1260. if win is not None:
  1261. # remove autodraw from all current components
  1262. win.clearAutoDraw()
  1263. # Flip one final time so any remaining win.callOnFlip()
  1264. # and win.timeOnFlip() tasks get executed
  1265. win.flip()
  1266. # mark experiment handler as finished
  1267. thisExp.status = FINISHED
  1268. # shut down eyetracker, if there is one
  1269. if inputs is not None:
  1270. if 'eyetracker' in inputs and inputs['eyetracker'] is not None:
  1271. inputs['eyetracker'].setConnectionState(False)
  1272. logging.flush()
  1273. def quit(thisExp, win=None, inputs=None, thisSession=None):
  1274. """
  1275. Fully quit, closing the window and ending the Python process.
  1276. Parameters
  1277. ==========
  1278. win : psychopy.visual.Window
  1279. Window to close.
  1280. inputs : dict
  1281. Dictionary of input devices by name.
  1282. thisSession : psychopy.session.Session or None
  1283. Handle of the Session object this experiment is being run from, if any.
  1284. """
  1285. thisExp.abort() # or data files will save again on exit
  1286. # make sure everything is closed down
  1287. if win is not None:
  1288. # Flip one final time so any remaining win.callOnFlip()
  1289. # and win.timeOnFlip() tasks get executed before quitting
  1290. win.flip()
  1291. win.close()
  1292. if inputs is not None:
  1293. if 'eyetracker' in inputs and inputs['eyetracker'] is not None:
  1294. inputs['eyetracker'].setConnectionState(False)
  1295. logging.flush()
  1296. if thisSession is not None:
  1297. thisSession.stop()
  1298. # terminate Python process
  1299. core.quit()
  1300. # if running this experiment as a script...
  1301. if __name__ == '__main__':
  1302. # call all functions in order
  1303. expInfo = showExpInfoDlg(expInfo=expInfo)
  1304. thisExp = setupData(expInfo=expInfo)
  1305. logFile = setupLogging(filename=thisExp.dataFileName)
  1306. win = setupWindow(expInfo=expInfo)
  1307. inputs = setupInputs(expInfo=expInfo, thisExp=thisExp, win=win)
  1308. run(
  1309. expInfo=expInfo,
  1310. thisExp=thisExp,
  1311. win=win,
  1312. inputs=inputs
  1313. )
  1314. saveData(thisExp=thisExp)
  1315. quit(thisExp=thisExp, win=win, inputs=inputs)