psychopy 2024.2.1__py3-none-any.whl → 2024.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of psychopy might be problematic. Click here for more details.

Files changed (252) hide show
  1. psychopy/.DS_Store +0 -0
  2. psychopy/CHANGELOG.txt +204 -0
  3. psychopy/GIT_SHA +1 -1
  4. psychopy/VERSION +1 -1
  5. psychopy/__init__.py +10 -1
  6. psychopy/__init__.py.orig +65 -0
  7. psychopy/app/.DS_Store +0 -0
  8. psychopy/app/Resources/.DS_Store +0 -0
  9. psychopy/app/_psychopyApp.py +11 -3
  10. psychopy/app/appData.spec +1 -1
  11. psychopy/app/builder/builder.py +1 -1
  12. psychopy/app/builder/builder.py.orig +3932 -0
  13. psychopy/app/builder/dialogs/__init__.py.orig +1679 -0
  14. psychopy/app/builder/dialogs/paramCtrls.py +1 -1
  15. psychopy/app/builder/dialogs/paramCtrls.py.orig +713 -0
  16. psychopy/app/colorpicker/__init__.py.orig +411 -0
  17. psychopy/app/cortex.log +0 -0
  18. psychopy/app/jobs.py +8 -1
  19. psychopy/app/locale/ar_001/.DS_Store +0 -0
  20. psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +792 -1816
  21. psychopy/app/plugin_manager/dialog.py +9 -7
  22. psychopy/app/ribbon.py +2 -1
  23. psychopy/app/runner/runner.py +25 -13
  24. psychopy/clock.py +8 -4
  25. psychopy/core.py.orig +169 -0
  26. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks_lastrun.py +330 -0
  27. psychopy/demos/builder/Tools/.DS_Store +0 -0
  28. psychopy/demos/builder/Tools/gammaCalibration/.DS_Store +0 -0
  29. psychopy/demos/builder/Tools/gammaCalibration/data/.DS_Store +0 -0
  30. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.csv +38 -0
  31. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.log +3418 -0
  32. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.psydat +0 -0
  33. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.csv +2 -0
  34. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.log +15 -0
  35. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.psydat +0 -0
  36. psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual_lastrun.py +562 -0
  37. psychopy/demos/coder/.DS_Store +0 -0
  38. psychopy/demos/coder/experiment control/info_gamma.pickle +0 -0
  39. psychopy/demos/coder/iohub/.iohpid +1 -0
  40. psychopy/demos/coder/iohub/eyetracking/.iohpid +1 -0
  41. psychopy/demos/coder/iohub/wintab/.DS_Store +0 -0
  42. psychopy/demos/coder/stimuli/.DS_Store +0 -0
  43. psychopy/experiment/_experiment.py +32 -7
  44. psychopy/experiment/_experiment.py.orig +1032 -0
  45. psychopy/experiment/components/.DS_Store +0 -0
  46. psychopy/experiment/components/_base.py +13 -4
  47. psychopy/experiment/components/_base.py.orig +823 -0
  48. psychopy/experiment/components/form/.DS_Store +0 -0
  49. psychopy/experiment/components/microphone/__init__.py +10 -1
  50. psychopy/experiment/components/microphone/__init__.py.orig +490 -0
  51. psychopy/experiment/components/polygon/__init__.py +21 -22
  52. psychopy/experiment/components/settings/__init__.py +13 -14
  53. psychopy/experiment/components/settings/__init__.py.orig +1337 -0
  54. psychopy/experiment/components/textbox/__init__.py.orig +310 -0
  55. psychopy/experiment/components/webcam/.DS_Store +0 -0
  56. psychopy/experiment/components/webcam/light/.DS_Store +0 -0
  57. psychopy/experiment/flow.py +10 -8
  58. psychopy/experiment/loops.py.orig +829 -0
  59. psychopy/experiment/params.py +8 -3
  60. psychopy/experiment/params.py.orig +408 -0
  61. psychopy/experiment/routine.py.orig +503 -0
  62. psychopy/experiment/routines/_base.py +15 -6
  63. psychopy/experiment/routines/counterbalance/__init__.py +1 -0
  64. psychopy/gui/qtgui.py +14 -7
  65. psychopy/gui/util.py +10 -14
  66. psychopy/gui/wxgui.py +10 -4
  67. psychopy/hardware/.DS_Store +0 -0
  68. psychopy/hardware/brainproducts.py.orig +680 -0
  69. psychopy/hardware/iolab.py.orig +238 -0
  70. psychopy/hardware/manager.py +1 -1
  71. psychopy/hardware/photodiode.py +59 -27
  72. psychopy/hardware/speaker.py +4 -4
  73. psychopy/iohub/client/__init__.py +17 -0
  74. psychopy/iohub/client/keyboard.py +5 -0
  75. psychopy/iohub/datastore/__init__.py.orig +443 -0
  76. psychopy/iohub/datastore/util.py.orig +692 -0
  77. psychopy/iohub/devices/mouse/darwin.py.orig +427 -0
  78. psychopy/iohub/devices/mouse/linux2.py +4 -0
  79. psychopy/iohub/devices/mouse/linux2.py.orig +198 -0
  80. psychopy/iohub/devices/mouse/win32.py +5 -0
  81. psychopy/preferences/.DS_Store +0 -0
  82. psychopy/projects/pavlovia.py +10 -3
  83. psychopy/projects/pavlovia.py.orig +1295 -0
  84. psychopy/sound/backend_ptb.py +22 -5
  85. psychopy/sound/transcribe.py +24 -4
  86. psychopy/tests/.DS_Store +0 -0
  87. psychopy/tests/data/.DS_Store +0 -0
  88. psychopy/tests/data/TestCircle_fill_local.png +0 -0
  89. psychopy/tests/data/aperture1_normHexbackground_local.png +0 -0
  90. psychopy/tests/data/aperture1_norm_local.png +0 -0
  91. psychopy/tests/data/aperture2_normHexbackground_local.png +0 -0
  92. psychopy/tests/data/beatandrcos_height_local.png +0 -0
  93. psychopy/tests/data/beatandrcos_normAddBlend_local.png +0 -0
  94. psychopy/tests/data/beatandrcos_normHexbackground_local.png +0 -0
  95. psychopy/tests/data/beatandrcos_norm_local.png +0 -0
  96. psychopy/tests/data/beatandrcos_stencil_local.png +0 -0
  97. psychopy/tests/data/blend_add_height_local.png +0 -0
  98. psychopy/tests/data/blend_add_normAddBlend_local.png +0 -0
  99. psychopy/tests/data/blend_add_normHexbackground_local.png +0 -0
  100. psychopy/tests/data/blend_add_normNoShade_local.png +0 -0
  101. psychopy/tests/data/blend_add_norm_local.png +0 -0
  102. psychopy/tests/data/blend_add_stencil_local.png +0 -0
  103. psychopy/tests/data/bufferimg_gabor_height_local.png +0 -0
  104. psychopy/tests/data/bufferimg_gabor_normAddBlend_local.png +0 -0
  105. psychopy/tests/data/bufferimg_gabor_normHexbackground_local.png +0 -0
  106. psychopy/tests/data/bufferimg_gabor_normNoShade_local.png +0 -0
  107. psychopy/tests/data/bufferimg_gabor_norm_local.png +0 -0
  108. psychopy/tests/data/bufferimg_gabor_stencil_local.png +0 -0
  109. psychopy/tests/data/circleHex_height_local.png +0 -0
  110. psychopy/tests/data/circleHex_normAddBlend_local.png +0 -0
  111. psychopy/tests/data/circleHex_normHexbackground_local.png +0 -0
  112. psychopy/tests/data/circleHex_normNoShade_local.png +0 -0
  113. psychopy/tests/data/circleHex_norm_local.png +0 -0
  114. psychopy/tests/data/circleHex_stencil_local.png +0 -0
  115. psychopy/tests/data/color_comparison_local.png +0 -0
  116. psychopy/tests/data/correctScript/.DS_Store +0 -0
  117. psychopy/tests/data/dots_height_local.png +0 -0
  118. psychopy/tests/data/dots_normAddBlend_local.png +0 -0
  119. psychopy/tests/data/dots_normHexbackground_local.png +0 -0
  120. psychopy/tests/data/dots_normNoShade_local.png +0 -0
  121. psychopy/tests/data/dots_norm_local.png +0 -0
  122. psychopy/tests/data/dots_stencil_local.png +0 -0
  123. psychopy/tests/data/elarray1_height_local.png +0 -0
  124. psychopy/tests/data/elarray1_normAddBlend_local.png +0 -0
  125. psychopy/tests/data/elarray1_normHexbackground_local.png +0 -0
  126. psychopy/tests/data/elarray1_norm_local.png +0 -0
  127. psychopy/tests/data/elarray1_stencil_local.png +0 -0
  128. psychopy/tests/data/envelopeandrcos_height_local.png +0 -0
  129. psychopy/tests/data/envelopeandrcos_normAddBlend_local.png +0 -0
  130. psychopy/tests/data/envelopeandrcos_normHexbackground_local.png +0 -0
  131. psychopy/tests/data/envelopeandrcos_norm_local.png +0 -0
  132. psychopy/tests/data/envelopeandrcos_stencil_local.png +0 -0
  133. psychopy/tests/data/envelopepowerandrcos_height_local.png +0 -0
  134. psychopy/tests/data/envelopepowerandrcos_normAddBlend_local.png +0 -0
  135. psychopy/tests/data/envelopepowerandrcos_normHexbackground_local.png +0 -0
  136. psychopy/tests/data/envelopepowerandrcos_norm_local.png +0 -0
  137. psychopy/tests/data/envelopepowerandrcos_stencil_local.png +0 -0
  138. psychopy/tests/data/gabor1_height_local.png +0 -0
  139. psychopy/tests/data/gabor1_normAddBlend_local.png +0 -0
  140. psychopy/tests/data/gabor1_normHexbackground_local.png +0 -0
  141. psychopy/tests/data/gabor1_normNoShade_local.png +0 -0
  142. psychopy/tests/data/gabor1_norm_local.png +0 -0
  143. psychopy/tests/data/gabor1_stencil_local.png +0 -0
  144. psychopy/tests/data/greyscale_normHexbackground_local.png +0 -0
  145. psychopy/tests/data/imageAndGauss_height_local.png +0 -0
  146. psychopy/tests/data/imageAndGauss_normAddBlend_local.png +0 -0
  147. psychopy/tests/data/imageAndGauss_normHexbackground_local.png +0 -0
  148. psychopy/tests/data/imageAndGauss_normNoShade_local.png +0 -0
  149. psychopy/tests/data/imageAndGauss_norm_local.png +0 -0
  150. psychopy/tests/data/imageAndGauss_stencil_local.png +0 -0
  151. psychopy/tests/data/movFrame1_stencil_local.png +0 -0
  152. psychopy/tests/data/noiseAndRcos_height_local.png +0 -0
  153. psychopy/tests/data/noiseAndRcos_normAddBlend_local.png +0 -0
  154. psychopy/tests/data/noiseAndRcos_normHexbackground_local.png +0 -0
  155. psychopy/tests/data/noiseAndRcos_normNoShade_local.png +0 -0
  156. psychopy/tests/data/noiseAndRcos_norm_local.png +0 -0
  157. psychopy/tests/data/noiseAndRcos_stencil_local.png +0 -0
  158. psychopy/tests/data/noiseFiltersAndRcos_height_local.png +0 -0
  159. psychopy/tests/data/noiseFiltersAndRcos_normAddBlend_local.png +0 -0
  160. psychopy/tests/data/noiseFiltersAndRcos_normHexbackground_local.png +0 -0
  161. psychopy/tests/data/noiseFiltersAndRcos_normNoShade_local.png +0 -0
  162. psychopy/tests/data/noiseFiltersAndRcos_norm_local.png +0 -0
  163. psychopy/tests/data/noiseFiltersAndRcos_stencil_local.png +0 -0
  164. psychopy/tests/data/numpyImage_height_local.png +0 -0
  165. psychopy/tests/data/numpyImage_normAddBlend_local.png +0 -0
  166. psychopy/tests/data/numpyImage_normHexbackground_local.png +0 -0
  167. psychopy/tests/data/numpyImage_normNoShade_local.png +0 -0
  168. psychopy/tests/data/numpyImage_norm_local.png +0 -0
  169. psychopy/tests/data/numpyImage_stencil_local.png +0 -0
  170. psychopy/tests/data/shape2_1_normAddBlend_local.png +0 -0
  171. psychopy/tests/data/shape2_1_normHexbackground_local.png +0 -0
  172. psychopy/tests/data/shape2_1_normNoShade_local.png +0 -0
  173. psychopy/tests/data/shape2_1_norm_local.png +0 -0
  174. psychopy/tests/data/shape2_1_stencil_local.png +0 -0
  175. psychopy/tests/data/test_loaded_namespace/test_counterbalance.psyexp +142 -0
  176. psychopy/tests/data/test_loaded_namespace/test_custom_missing.psyexp +129 -0
  177. psychopy/tests/data/test_loaded_namespace/test_missing_counterbalance.psyexp +116 -0
  178. psychopy/tests/data/test_loaded_namespace/test_mix_exp.psyexp +181 -0
  179. psychopy/tests/data/test_loaded_namespace/test_mix_missing.psyexp +140 -0
  180. psychopy/tests/data/test_loaded_namespace/test_mix_name_calibration.psyexp +164 -0
  181. psychopy/tests/data/text1_height_local.png +0 -0
  182. psychopy/tests/data/text1_normAddBlend_local.png +0 -0
  183. psychopy/tests/data/text1_normHexbackground_local.png +0 -0
  184. psychopy/tests/data/text1_norm_local.png +0 -0
  185. psychopy/tests/data/text1_stencil_local.png +0 -0
  186. psychopy/tests/data/wedge1_height_local.png +0 -0
  187. psychopy/tests/data/wedge1_normAddBlend_local.png +0 -0
  188. psychopy/tests/data/wedge1_normHexbackground_local.png +0 -0
  189. psychopy/tests/data/wedge1_normNoShade_local.png +0 -0
  190. psychopy/tests/data/wedge1_norm_local.png +0 -0
  191. psychopy/tests/data/wedge1_stencil_local.png +0 -0
  192. psychopy/tests/test_app/.DS_Store +0 -0
  193. psychopy/tests/test_app/test_builder/.DS_Store +0 -0
  194. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.log +177 -0
  195. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.psydat +0 -0
  196. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.xlsx +0 -0
  197. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.log +168 -0
  198. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.psydat +0 -0
  199. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.xlsx +0 -0
  200. psychopy/tests/test_data/.DS_Store +0 -0
  201. psychopy/tests/test_experiment/test_experiment.py +96 -0
  202. psychopy/tests/test_hardware/test_CRS_BitsSharp.py.orig +68 -0
  203. psychopy/tests/test_tools/test_arraytools.py +112 -0
  204. psychopy/tests/test_visual/test_image.py.orig +219 -0
  205. psychopy/tools/arraytools.py +47 -0
  206. psychopy/tools/versionchooser.py +1 -1
  207. psychopy/visual/backends/pygletbackend.py +26 -8
  208. psychopy/visual/basevisual.py.orig +1723 -0
  209. psychopy/visual/form.py.orig +1181 -0
  210. psychopy/visual/text.py.orig +752 -0
  211. psychopy/visual/textbox2/textbox2.py.orig +1315 -0
  212. psychopy/visual/window.py +13 -5
  213. psychopy/visual/windowwarp.py.orig +463 -0
  214. {psychopy-2024.2.1.dist-info → psychopy-2024.2.5.dist-info}/METADATA +9 -9
  215. {psychopy-2024.2.1.dist-info → psychopy-2024.2.5.dist-info}/RECORD +220 -84
  216. {psychopy-2024.2.1.dist-info → psychopy-2024.2.5.dist-info}/WHEEL +1 -1
  217. {psychopy-2024.2.1.dist-info → psychopy-2024.2.5.dist-info}/entry_points.txt +2 -0
  218. psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
  219. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
  220. psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
  221. psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
  222. psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
  223. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
  224. psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
  225. psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
  226. psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
  227. psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
  228. psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
  229. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
  230. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
  231. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
  232. psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
  233. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
  234. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
  235. psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
  236. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  237. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
  238. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
  239. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
  240. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
  241. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
  242. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
  243. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
  244. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
  245. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
  246. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
  247. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
  248. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
  249. psychopy-2024.2.1.dist-info/licenses/AUTHORS.md +0 -138
  250. /psychopy/{app/locale/es_ES/LC_MESSAGE → demos/builder}/.DS_Store +0 -0
  251. /psychopy/{visual → demos/builder/Experiments}/.DS_Store +0 -0
  252. {psychopy-2024.2.1.dist-info → psychopy-2024.2.5.dist-info}/licenses/LICENSE +0 -0
@@ -68,7 +68,6 @@ class EnvironmentManagerDlg(wx.Dialog):
68
68
 
69
69
  self.notebook.ChangeSelection(0)
70
70
 
71
-
72
71
  @staticmethod
73
72
  def getPackageVersionInfo(packageName):
74
73
  """Query packages for available versions.
@@ -278,10 +277,13 @@ class EnvironmentManagerDlg(wx.Dialog):
278
277
  )
279
278
  else:
280
279
  command.append('--user')
281
-
280
+
282
281
  # add other options to the command
283
282
  command += ['--prefer-binary', '--no-input', '--no-color']
284
-
283
+
284
+ # disable pip version check
285
+ command += ['--disable-pip-version-check']
286
+
285
287
  # write command to output panel
286
288
  self.output.writeCmd(" ".join(command))
287
289
  # append own name to extra
@@ -359,7 +361,7 @@ class EnvironmentManagerDlg(wx.Dialog):
359
361
  # write installation termination statement
360
362
  msg = "Installation complete"
361
363
  if 'pipname' in self.pipProcess.extra:
362
- msg = f"Finished installing %(pipname)s" % self.pipProcess.extra
364
+ msg = "Finished installing %(pipname)s" % self.pipProcess.extra
363
365
  self.output.writeTerminus(msg)
364
366
 
365
367
  # if we have a plugin, write additional plugin information post-install
@@ -411,12 +413,12 @@ class EnvironmentManagerDlg(wx.Dialog):
411
413
  # refresh view
412
414
  pkgtools.refreshPackages()
413
415
  self.pluginMgr.updateInfo()
414
-
416
+
415
417
  def onUninstallExit(self, pid, exitCode):
416
418
  # write installation termination statement
417
419
  msg = "Uninstall complete"
418
420
  if 'pipname' in self.pipProcess.extra:
419
- msg = f"Finished uninstalling %(pipname)s" % self.pipProcess.extra
421
+ msg = "Finished uninstalling %(pipname)s" % self.pipProcess.extra
420
422
  self.output.writeTerminus(msg)
421
423
  # clear pip process
422
424
  self.pipProcess = None
@@ -435,7 +437,7 @@ class EnvironmentManagerDlg(wx.Dialog):
435
437
  # if they change their mind, cancel closing
436
438
  if dlg.ShowModal() == wx.ID_NO:
437
439
  return
438
-
440
+
439
441
  if evt is not None:
440
442
  evt.Skip()
441
443
 
psychopy/app/ribbon.py CHANGED
@@ -467,7 +467,8 @@ class FrameRibbonButton(wx.Button, handlers.ThemeMixin):
467
467
  wx.Button.__init__(self, parent, style=wx.BORDER_NONE | style, size=(w, 44))
468
468
  self.SetMinSize((40, 44))
469
469
  # set label
470
- self.SetLabelText(label)
470
+ if label and style | wx.BU_NOTEXT != style:
471
+ self.SetLabelText(label)
471
472
  # set tooltip
472
473
  if tooltip and style | wx.BU_NOTEXT == style:
473
474
  # if there's no label, include it in the tooltip
@@ -490,7 +490,6 @@ class RunnerPanel(wx.Panel, ScriptProcess, handlers.ThemeMixin):
490
490
 
491
491
  # setup ribbon
492
492
  self.ribbon = RunnerRibbon(self)
493
- self.ribbon.buttons['pyswitch'].setMode(0)
494
493
  self.mainSizer.Add(self.ribbon, border=0, flag=wx.EXPAND | wx.ALL)
495
494
 
496
495
  # Setup splitter
@@ -684,11 +683,13 @@ class RunnerPanel(wx.Panel, ScriptProcess, handlers.ThemeMixin):
684
683
  # get relevant paths
685
684
  htmlPath = str(self.currentFile.parent / self.outputPath)
686
685
  jsFile = self.currentFile.parent / (self.currentFile.stem + ".js")
687
- # make sure JS file exists
688
- if not os.path.exists(jsFile):
689
- generateScript(outfile=str(jsFile),
690
- exp=self.loadExperiment(),
691
- target="PsychoJS")
686
+ # regenerate JS file
687
+ if self.currentFile.suffix == ".psyexp":
688
+ generateScript(
689
+ outfile=str(jsFile),
690
+ exp=self.loadExperiment(),
691
+ target="PsychoJS"
692
+ )
692
693
  # start server
693
694
  self.startServer(htmlPath, port=port)
694
695
  # open experiment
@@ -841,25 +842,36 @@ class RunnerPanel(wx.Panel, ScriptProcess, handlers.ThemeMixin):
841
842
  del self.entries[self.currentFile] # remove from our tracking dictionary
842
843
  self.expCtrl.DeleteItem(self.currentSelection) # from wx control
843
844
  self.app.updateWindowMenu()
844
-
845
- def onRunModeToggle(self, evt):
845
+
846
+ def updateRunModeIcons(self, evt=None):
846
847
  """
847
- Function to execute when switching between pilot and run modes
848
+ Function to update run/pilot icons according to run mode
848
849
  """
849
- mode = evt.GetInt()
850
- # update buttons
850
+ mode = self.ribbon.buttons['pyswitch'].mode
851
851
  # show/hide run buttons
852
852
  for key in ("pyrun", "jsrun"):
853
853
  self.ribbon.buttons[key].Show(mode)
854
854
  # hide/show pilot buttons
855
855
  for key in ("pypilot", "jspilot"):
856
856
  self.ribbon.buttons[key].Show(not mode)
857
+ # update
858
+ self.ribbon.Layout()
859
+
860
+ def onRunModeToggle(self, evt):
861
+ """
862
+ Function to execute when switching between pilot and run modes
863
+ """
864
+ mode = evt.GetInt()
865
+ # update buttons
866
+ self.updateRunModeIcons()
857
867
  # update experiment mode
858
868
  if self.currentExperiment is not None:
859
869
  # find any Builder windows with this experiment open
860
870
  for frame in self.app.getAllFrames(frameType='builder'):
861
871
  if frame.exp == self.currentExperiment:
862
- frame.ribbon.buttons['pyswitch'].setMode(mode)
872
+ frame.ribbon.buttons['pyswitch'].setMode(mode, silent=True)
873
+ if hasattr(frame, "updateRunModeIcons"):
874
+ frame.updateRunModeIcons()
863
875
  # update current selection
864
876
  runMode = "pilot"
865
877
  if mode:
@@ -902,7 +914,7 @@ class RunnerPanel(wx.Panel, ScriptProcess, handlers.ThemeMixin):
902
914
  # disable stop
903
915
  self.ribbon.buttons['pystop'].Disable()
904
916
  # switch mode
905
- self.ribbon.buttons['pyswitch'].setMode(runMode == "run", silent=True)
917
+ self.ribbon.buttons['pyswitch'].setMode(runMode == "run")
906
918
  # update
907
919
  self.updateAlerts()
908
920
  self.app.updateWindowMenu()
psychopy/clock.py CHANGED
@@ -332,14 +332,18 @@ class Clock(MonotonicClock):
332
332
  self._epochTimeAtLastReset -= t
333
333
 
334
334
  def add(self, t):
335
- """DEPRECATED: use .addTime() instead
335
+ """
336
+ DEPRECATED: use .addTime() instead
336
337
 
337
338
  This function adds time TO THE BASE (t0) which, counterintuitively,
338
339
  reduces the apparent time on the clock
339
340
  """
340
- logging.warning("DEPRECATED: Clock.add() is deprecated in favor of .addTime() due to "
341
- "the counterintuitive design (it added time to the baseline, which "
342
- "reduced the values returned from getTime()")
341
+ psychopy.logging.log(msg=(
342
+ "Clock.add() is deprecated in favor of .addTime() due to the counterintuitive design "
343
+ "(it added time to the baseline, which reduced the values returned from getTime() )"
344
+ ),
345
+ level=psychopy.logging.DEPRECATION
346
+ )
343
347
  self._timeAtLastReset += t
344
348
  self._epochTimeAtLastReset += t
345
349
 
psychopy/core.py.orig ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """Basic functions, including timing, rush (imported), quit
5
+ """
6
+ # Part of the PsychoPy library
7
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2021 Open Science Tools Ltd.
8
+ # Distributed under the terms of the GNU General Public License (GPL).
9
+
10
+ import sys
11
+ import threading
12
+ import subprocess
13
+ import shlex
14
+ import locale
15
+
16
+ # some things are imported just to be accessible within core's namespace
17
+ from psychopy.clock import (MonotonicClock, Clock, CountdownTimer,
18
+ wait, monotonicClock, getAbsTime,
19
+ StaticPeriod) # pylint: disable=W0611
20
+
21
+ # always safe to call rush, even if its not going to do anything for a
22
+ # particular OS
23
+ from psychopy.platform_specific import rush # pylint: disable=W0611
24
+ from psychopy import logging
25
+ <<<<<<< HEAD
26
+ from psychopy.constants import STARTED, NOT_STARTED, FINISHED
27
+ =======
28
+ from psychopy.constants import STARTED, NOT_STARTED, FINISHED, PY3
29
+ from psychopy.iohub.client import ioHubConnection
30
+ >>>>>>> c06fff3cf5e2f418f6db297fd47819041a00c07d
31
+
32
+ try:
33
+ import pyglet
34
+ havePyglet = True
35
+ # may not want to check, to preserve terminal window focus
36
+ checkPygletDuringWait = True
37
+ except ImportError:
38
+ havePyglet = False
39
+ checkPygletDuringWait = False
40
+
41
+ try:
42
+ import glfw
43
+ haveGLFW = True
44
+ except ImportError:
45
+ haveGLFW = False
46
+
47
+ runningThreads = [] # just for backwards compatibility?
48
+ openWindows = [] # visual.Window updates this, event.py and clock.py use it
49
+
50
+ # Set getTime in core to == the monotonicClock instance created in the
51
+ # clockModule.
52
+ # The logging module sets the defaultClock to == clock.monotonicClock,
53
+ # so by default the core.getTime() and logging.defaultClock.getTime()
54
+ # functions return the 'same' timebase.
55
+ #
56
+ # This way 'all' OSs have a core.getTime() timebase that starts at 0.0 when
57
+ # the experiment is launched, instead of it being this way on Windows only
58
+ # (which was also a descripancy between OS's when win32 was using time.clock).
59
+
60
+
61
+ def getTime(applyZero = True):
62
+ """Get the current time since psychopy.core was loaded.
63
+
64
+
65
+
66
+ Version Notes: Note that prior to PsychoPy 1.77.00 the behaviour of
67
+ getTime() was platform dependent (on OSX and linux it was equivalent to
68
+ :func:`psychopy.core.getAbsTime`
69
+ whereas on windows it returned time since loading of the module, as now)
70
+ """
71
+ return monotonicClock.getTime(applyZero)
72
+
73
+
74
+ def quit():
75
+ """Close everything and exit nicely (ending the experiment)
76
+ """
77
+ # pygame.quit() # safe even if pygame was never initialised
78
+ logging.flush()
79
+
80
+ # properly shutdown ioHub server
81
+ if ioHubConnection.ACTIVE_CONNECTION:
82
+ ioHubConnection.ACTIVE_CONNECTION.quit()
83
+
84
+ for thisThread in threading.enumerate():
85
+ if hasattr(thisThread, 'stop') and hasattr(thisThread, 'running'):
86
+ # this is one of our event threads - kill it and wait for success
87
+ thisThread.stop()
88
+ while thisThread.running == 0:
89
+ pass # wait until it has properly finished polling
90
+
91
+ sys.exit(0) # quits the python session entirely
92
+
93
+
94
+ def shellCall(shellCmd, stdin='', stderr=False, env=None, encoding=None):
95
+ """Call a single system command with arguments, return its stdout.
96
+ Returns stdout, stderr if stderr is True.
97
+ Handles simple pipes, passing stdin to shellCmd (pipes are untested
98
+ on windows) can accept string or list as the first argument
99
+
100
+ Parameters
101
+ ----------
102
+ shellCmd : str, or iterable
103
+ The command to execute, and its respective arguments.
104
+
105
+ stdin : str, or None
106
+ Input to pass to the command.
107
+
108
+ stderr : bool
109
+ Whether to return the standard error output once execution is finished.
110
+
111
+ env : dict
112
+ The environment variables to set during execution.
113
+
114
+ encoding : str
115
+ The encoding to use for communication with the executed command.
116
+ This argument will be ignored on Python 2.7.
117
+
118
+ Notes
119
+ -----
120
+ We use ``subprocess.Popen`` to execute the command and establish
121
+ `stdin` and `stdout` pipes.
122
+ Python 2.7 always opens the pipes in text mode; however,
123
+ Python 3 defaults to binary mode, unless an encoding is specified.
124
+ To unify pipe communication across Python 2 and 3, we now provide an
125
+ `encoding` parameter, enforcing `utf-8` text mode by default.
126
+ This parameter is present from Python 3.6 onwards; using an older
127
+ Python 3 version will raise an exception. The parameter will be ignored
128
+ when running Python 2.7.
129
+
130
+ """
131
+ if encoding is None:
132
+ encoding = locale.getpreferredencoding()
133
+
134
+ if type(shellCmd) == str:
135
+ # safely split into cmd+list-of-args, no pipes here
136
+ shellCmdList = shlex.split(shellCmd)
137
+ elif type(shellCmd) == bytes:
138
+ # safely split into cmd+list-of-args, no pipes here
139
+ shellCmdList = shlex.split(shellCmd.decode('utf-8'))
140
+ elif type(shellCmd) in (list, tuple): # handles whitespace in filenames
141
+ shellCmdList = shellCmd
142
+ else:
143
+ msg = 'shellCmd requires a string or iterable.'
144
+ raise TypeError(msg)
145
+
146
+ cmdObjects = []
147
+ for obj in shellCmdList:
148
+ if type(obj) != bytes:
149
+ cmdObjects.append(obj)
150
+ else:
151
+ cmdObjects.append(obj.decode('utf-8'))
152
+
153
+ # the `encoding` parameter results in unicode coming back
154
+ if sys.version_info.minor >= 6:
155
+ proc = subprocess.Popen(cmdObjects, stdin=subprocess.PIPE,
156
+ stdout=subprocess.PIPE,
157
+ stderr=subprocess.PIPE,
158
+ encoding=encoding, env=env)
159
+ else:
160
+ msg = 'shellCall() requires Python 2.7, or 3.6 and newer.'
161
+ raise RuntimeError(msg)
162
+
163
+ stdoutData, stderrData = proc.communicate(stdin)
164
+
165
+ del proc
166
+ if stderr:
167
+ return stdoutData.strip(), stderrData.strip()
168
+ else:
169
+ return stdoutData.strip()
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ This experiment was created using PsychoPy3 Experiment Builder (v2022.2.0dev3),
5
+ on Thu May 26 17:00:03 2022
6
+ If you publish work using this script the most relevant publication is:
7
+
8
+ Peirce J, Gray JR, Simpson S, MacAskill M, Höchenberger R, Sogo H, Kastman E, Lindeløv JK. (2019)
9
+ PsychoPy2: Experiments in behavior made easy Behav Res 51: 195.
10
+ https://doi.org/10.3758/s13428-018-01193-y
11
+
12
+ """
13
+
14
+ # --- Import packages ---
15
+ from psychopy import locale_setup
16
+ from psychopy import prefs
17
+ from psychopy import sound, gui, visual, core, data, event, logging, clock, colors, layout
18
+ from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
19
+ STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
20
+
21
+ import numpy as np # whole numpy lib is available, prepend 'np.'
22
+ from numpy import (sin, cos, tan, log, log10, pi, average,
23
+ sqrt, std, deg2rad, rad2deg, linspace, asarray)
24
+ from numpy.random import random, randint, normal, shuffle, choice as randchoice
25
+ import os # handy system and path functions
26
+ import sys # to get file system encoding
27
+
28
+ import psychopy.iohub as io
29
+ from psychopy.hardware import keyboard
30
+
31
+
32
+
33
+ # Ensure that relative paths start from the same directory as this script
34
+ _thisDir = os.path.dirname(os.path.abspath(__file__))
35
+ os.chdir(_thisDir)
36
+ # Store info about the experiment session
37
+ psychopyVersion = '2022.2.0dev3'
38
+ expName = 'blockedTrials' # from the Builder filename that created this script
39
+ expInfo = {
40
+ 'session': '001',
41
+ 'participant': "subj%06.0f" %(random()*100000),
42
+ }
43
+ # --- Show participant info dialog --
44
+ dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName)
45
+ if dlg.OK == False:
46
+ core.quit() # user pressed cancel
47
+ expInfo['date'] = data.getDateStr() # add a simple timestamp
48
+ expInfo['expName'] = expName
49
+ expInfo['psychopyVersion'] = psychopyVersion
50
+
51
+ # Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
52
+ filename = _thisDir + os.sep + u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])
53
+
54
+ # An ExperimentHandler isn't essential but helps with data saving
55
+ thisExp = data.ExperimentHandler(name=expName, version='',
56
+ extraInfo=expInfo, runtimeInfo=None,
57
+ originPath='psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks_lastrun.py',
58
+ savePickle=True, saveWideText=True,
59
+ dataFileName=filename)
60
+ # save a log file for detail verbose info
61
+ logFile = logging.LogFile(filename+'.log', level=logging.EXP)
62
+ logging.console.setLevel(logging.WARNING) # this outputs to the screen, not a file
63
+
64
+ endExpNow = False # flag for 'escape' or other condition => quit the exp
65
+ frameTolerance = 0.001 # how close to onset before 'same' frame
66
+
67
+ # Start Code - component code to be run after the window creation
68
+
69
+ # --- Setup the Window ---
70
+ win = visual.Window(
71
+ size=[1440, 900], fullscr=True, screen=0,
72
+ winType='pyglet', allowGUI=False, allowStencil=False,
73
+ monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
74
+ blendMode='avg', useFBO=True,
75
+ units='height')
76
+ # store frame rate of monitor if we can measure it
77
+ expInfo['frameRate'] = win.getActualFrameRate()
78
+ if expInfo['frameRate'] != None:
79
+ frameDur = 1.0 / round(expInfo['frameRate'])
80
+ else:
81
+ frameDur = 1.0 / 60.0 # could not measure, so guess
82
+ # --- Setup input devices ---
83
+ ioConfig = {}
84
+
85
+ # Setup iohub keyboard
86
+ ioConfig['Keyboard'] = dict(use_keymap='psychopy')
87
+
88
+ ioSession = '1'
89
+ if 'session' in expInfo:
90
+ ioSession = str(expInfo['session'])
91
+ ioServer = io.launchHubServer(window=win, **ioConfig)
92
+ eyetracker = None
93
+
94
+ # create a default keyboard (e.g. to check for escape)
95
+ defaultKeyboard = keyboard.Keyboard(backend='iohub')
96
+
97
+ # --- Initialize components for Routine "readyMessage" ---
98
+ readyMessageClock = core.Clock()
99
+ textbox = visual.TextBox2(
100
+ win, text='', font='Open Sans',
101
+ pos=(0, 0), letterHeight=0.05,
102
+ size=(0.4, 0.4), borderWidth=2.0,
103
+ color='white', colorSpace='rgb',
104
+ opacity=1.0,
105
+ bold=False, italic=False,
106
+ lineSpacing=1.0,
107
+ padding=None, alignment='center',
108
+ anchor='center',
109
+ fillColor=None, borderColor=None,
110
+ flipHoriz=False, flipVert=False, languageStyle='LTR',
111
+ editable=False,
112
+ name='textbox',
113
+ autoLog=True,
114
+ )
115
+
116
+ # --- Initialize components for Routine "trial" ---
117
+ trialClock = core.Clock()
118
+ image = visual.ImageStim(
119
+ win=win,
120
+ name='image', units='height',
121
+ image='sin', mask=None, anchor='center',
122
+ ori=0, pos=(0, 0), size=(0.5,0.5),
123
+ color=[1,1,1], colorSpace='rgb', opacity=1,
124
+ flipHoriz=False, flipVert=False,
125
+ texRes=128, interpolate=True, depth=0.0)
126
+
127
+ # Create some handy timers
128
+ globalClock = core.Clock() # to track the time since experiment started
129
+ routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine
130
+
131
+ # set up handler to look after randomisation of conditions etc
132
+ blocks = data.TrialHandler(nReps=2, method='random',
133
+ extraInfo=expInfo, originPath=-1,
134
+ trialList=data.importConditions('chooseBlock.xlsx'),
135
+ seed=None, name='blocks')
136
+ thisExp.addLoop(blocks) # add the loop to the experiment
137
+ thisBlock = blocks.trialList[0] # so we can initialise stimuli with some values
138
+ # abbreviate parameter names if possible (e.g. rgb = thisBlock.rgb)
139
+ if thisBlock != None:
140
+ for paramName in thisBlock:
141
+ exec('{} = thisBlock[paramName]'.format(paramName))
142
+
143
+ for thisBlock in blocks:
144
+ currentLoop = blocks
145
+ # abbreviate parameter names if possible (e.g. rgb = thisBlock.rgb)
146
+ if thisBlock != None:
147
+ for paramName in thisBlock:
148
+ exec('{} = thisBlock[paramName]'.format(paramName))
149
+
150
+ # --- Prepare to start Routine "readyMessage" ---
151
+ continueRoutine = True
152
+ routineTimer.add(1.000000)
153
+ # update component parameters for each repeat
154
+ textbox.reset()
155
+ textbox.setText(readyMsg)
156
+ # keep track of which components have finished
157
+ readyMessageComponents = [textbox]
158
+ for thisComponent in readyMessageComponents:
159
+ thisComponent.tStart = None
160
+ thisComponent.tStop = None
161
+ thisComponent.tStartRefresh = None
162
+ thisComponent.tStopRefresh = None
163
+ if hasattr(thisComponent, 'status'):
164
+ thisComponent.status = NOT_STARTED
165
+ # reset timers
166
+ t = 0
167
+ _timeToFirstFrame = win.getFutureFlipTime(clock="now")
168
+ readyMessageClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip
169
+ frameN = -1
170
+
171
+ # --- Run Routine "readyMessage" ---
172
+ while continueRoutine and routineTimer.getTime() > 0:
173
+ # get current time
174
+ t = readyMessageClock.getTime()
175
+ tThisFlip = win.getFutureFlipTime(clock=readyMessageClock)
176
+ tThisFlipGlobal = win.getFutureFlipTime(clock=None)
177
+ frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
178
+ # update/draw components on each frame
179
+
180
+ # *textbox* updates
181
+ if textbox.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
182
+ # keep track of start time/frame for later
183
+ textbox.frameNStart = frameN # exact frame index
184
+ textbox.tStart = t # local t and not account for scr refresh
185
+ textbox.tStartRefresh = tThisFlipGlobal # on global time
186
+ win.timeOnFlip(textbox, 'tStartRefresh') # time at next scr refresh
187
+ textbox.setAutoDraw(True)
188
+ if textbox.status == STARTED:
189
+ # is it time to stop? (based on global clock, using actual start)
190
+ if tThisFlipGlobal > textbox.tStartRefresh + 1.0-frameTolerance:
191
+ # keep track of stop time/frame for later
192
+ textbox.tStop = t # not accounting for scr refresh
193
+ textbox.frameNStop = frameN # exact frame index
194
+ win.timeOnFlip(textbox, 'tStopRefresh') # time at next scr refresh
195
+ textbox.setAutoDraw(False)
196
+
197
+ # check for quit (typically the Esc key)
198
+ if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
199
+ core.quit()
200
+
201
+ # check if all components have finished
202
+ if not continueRoutine: # a component has requested a forced-end of Routine
203
+ break
204
+ continueRoutine = False # will revert to True if at least one component still running
205
+ for thisComponent in readyMessageComponents:
206
+ if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
207
+ continueRoutine = True
208
+ break # at least one component has not yet finished
209
+
210
+ # refresh the screen
211
+ if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
212
+ win.flip()
213
+
214
+ # --- Ending Routine "readyMessage" ---
215
+ for thisComponent in readyMessageComponents:
216
+ if hasattr(thisComponent, "setAutoDraw"):
217
+ thisComponent.setAutoDraw(False)
218
+ blocks.addData('textbox.started', textbox.tStartRefresh)
219
+ blocks.addData('textbox.stopped', textbox.tStopRefresh)
220
+
221
+ # set up handler to look after randomisation of conditions etc
222
+ trials = data.TrialHandler(nReps=1, method='random',
223
+ extraInfo=expInfo, originPath=-1,
224
+ trialList=data.importConditions(condsFile),
225
+ seed=None, name='trials')
226
+ thisExp.addLoop(trials) # add the loop to the experiment
227
+ thisTrial = trials.trialList[0] # so we can initialise stimuli with some values
228
+ # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
229
+ if thisTrial != None:
230
+ for paramName in thisTrial:
231
+ exec('{} = thisTrial[paramName]'.format(paramName))
232
+
233
+ for thisTrial in trials:
234
+ currentLoop = trials
235
+ # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
236
+ if thisTrial != None:
237
+ for paramName in thisTrial:
238
+ exec('{} = thisTrial[paramName]'.format(paramName))
239
+
240
+ # --- Prepare to start Routine "trial" ---
241
+ continueRoutine = True
242
+ routineTimer.add(1.500000)
243
+ # update component parameters for each repeat
244
+ image.setImage(stimFile)
245
+ # keep track of which components have finished
246
+ trialComponents = [image]
247
+ for thisComponent in trialComponents:
248
+ thisComponent.tStart = None
249
+ thisComponent.tStop = None
250
+ thisComponent.tStartRefresh = None
251
+ thisComponent.tStopRefresh = None
252
+ if hasattr(thisComponent, 'status'):
253
+ thisComponent.status = NOT_STARTED
254
+ # reset timers
255
+ t = 0
256
+ _timeToFirstFrame = win.getFutureFlipTime(clock="now")
257
+ trialClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip
258
+ frameN = -1
259
+
260
+ # --- Run Routine "trial" ---
261
+ while continueRoutine and routineTimer.getTime() > 0:
262
+ # get current time
263
+ t = trialClock.getTime()
264
+ tThisFlip = win.getFutureFlipTime(clock=trialClock)
265
+ tThisFlipGlobal = win.getFutureFlipTime(clock=None)
266
+ frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
267
+ # update/draw components on each frame
268
+
269
+ # *image* updates
270
+ if image.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
271
+ # keep track of start time/frame for later
272
+ image.frameNStart = frameN # exact frame index
273
+ image.tStart = t # local t and not account for scr refresh
274
+ image.tStartRefresh = tThisFlipGlobal # on global time
275
+ win.timeOnFlip(image, 'tStartRefresh') # time at next scr refresh
276
+ image.setAutoDraw(True)
277
+ if image.status == STARTED:
278
+ # is it time to stop? (based on global clock, using actual start)
279
+ if tThisFlipGlobal > image.tStartRefresh + 1.0-frameTolerance:
280
+ # keep track of stop time/frame for later
281
+ image.tStop = t # not accounting for scr refresh
282
+ image.frameNStop = frameN # exact frame index
283
+ win.timeOnFlip(image, 'tStopRefresh') # time at next scr refresh
284
+ image.setAutoDraw(False)
285
+
286
+ # check for quit (typically the Esc key)
287
+ if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
288
+ core.quit()
289
+
290
+ # check if all components have finished
291
+ if not continueRoutine: # a component has requested a forced-end of Routine
292
+ break
293
+ continueRoutine = False # will revert to True if at least one component still running
294
+ for thisComponent in trialComponents:
295
+ if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
296
+ continueRoutine = True
297
+ break # at least one component has not yet finished
298
+
299
+ # refresh the screen
300
+ if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
301
+ win.flip()
302
+
303
+ # --- Ending Routine "trial" ---
304
+ for thisComponent in trialComponents:
305
+ if hasattr(thisComponent, "setAutoDraw"):
306
+ thisComponent.setAutoDraw(False)
307
+ trials.addData('image.started', image.tStartRefresh)
308
+ trials.addData('image.stopped', image.tStopRefresh)
309
+ thisExp.nextEntry()
310
+
311
+ # completed 1 repeats of 'trials'
312
+
313
+ # completed 2 repeats of 'blocks'
314
+
315
+
316
+ # --- End experiment ---
317
+ # Flip one final time so any remaining win.callOnFlip()
318
+ # and win.timeOnFlip() tasks get executed before quitting
319
+ win.flip()
320
+
321
+ # these shouldn't be strictly necessary (should auto-save)
322
+ thisExp.saveAsWideText(filename+'.csv', delim='auto')
323
+ thisExp.saveAsPickle(filename)
324
+ logging.flush()
325
+ # make sure everything is closed down
326
+ if eyetracker:
327
+ eyetracker.setConnectionState(False)
328
+ thisExp.abort() # or data files will save again on exit
329
+ win.close()
330
+ core.quit()
Binary file