psychopy 2025.2.4__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.
Files changed (3127) hide show
  1. psychopy/CHANGELOG.txt +3981 -0
  2. psychopy/GIT_SHA +1 -0
  3. psychopy/LICENSE.txt +11 -0
  4. psychopy/LICENSES.txt +55 -0
  5. psychopy/VERSION +1 -0
  6. psychopy/__init__.py +148 -0
  7. psychopy/alerts/__init__.py +65 -0
  8. psychopy/alerts/_alerts.py +224 -0
  9. psychopy/alerts/_errorHandler.py +50 -0
  10. psychopy/alerts/alertsCatalogue/1000.yaml +0 -0
  11. psychopy/alerts/alertsCatalogue/1100.yaml +0 -0
  12. psychopy/alerts/alertsCatalogue/1500.yaml +0 -0
  13. psychopy/alerts/alertsCatalogue/2000.yaml +0 -0
  14. psychopy/alerts/alertsCatalogue/2100.yaml +0 -0
  15. psychopy/alerts/alertsCatalogue/2110.yaml +0 -0
  16. psychopy/alerts/alertsCatalogue/2115.yaml +21 -0
  17. psychopy/alerts/alertsCatalogue/2120.yaml +22 -0
  18. psychopy/alerts/alertsCatalogue/2150.yaml +0 -0
  19. psychopy/alerts/alertsCatalogue/2155.yaml +21 -0
  20. psychopy/alerts/alertsCatalogue/2300.yaml +0 -0
  21. psychopy/alerts/alertsCatalogue/2500.yaml +0 -0
  22. psychopy/alerts/alertsCatalogue/3000.yaml +0 -0
  23. psychopy/alerts/alertsCatalogue/3100.yaml +0 -0
  24. psychopy/alerts/alertsCatalogue/3110.yaml +25 -0
  25. psychopy/alerts/alertsCatalogue/3115.yaml +24 -0
  26. psychopy/alerts/alertsCatalogue/3200.yaml +0 -0
  27. psychopy/alerts/alertsCatalogue/3210.yaml +27 -0
  28. psychopy/alerts/alertsCatalogue/3400.yaml +0 -0
  29. psychopy/alerts/alertsCatalogue/3600.yaml +0 -0
  30. psychopy/alerts/alertsCatalogue/3610.yaml +19 -0
  31. psychopy/alerts/alertsCatalogue/4000.yaml +0 -0
  32. psychopy/alerts/alertsCatalogue/4051.yaml +19 -0
  33. psychopy/alerts/alertsCatalogue/4052.yaml +19 -0
  34. psychopy/alerts/alertsCatalogue/4100.yaml +0 -0
  35. psychopy/alerts/alertsCatalogue/4105.yaml +18 -0
  36. psychopy/alerts/alertsCatalogue/4115.yaml +21 -0
  37. psychopy/alerts/alertsCatalogue/4120.yaml +19 -0
  38. psychopy/alerts/alertsCatalogue/4125.yaml +23 -0
  39. psychopy/alerts/alertsCatalogue/4130.yaml +19 -0
  40. psychopy/alerts/alertsCatalogue/4160.yaml +25 -0
  41. psychopy/alerts/alertsCatalogue/4200.yaml +0 -0
  42. psychopy/alerts/alertsCatalogue/4205.yaml +19 -0
  43. psychopy/alerts/alertsCatalogue/4210.yaml +19 -0
  44. psychopy/alerts/alertsCatalogue/4305.yaml +21 -0
  45. psychopy/alerts/alertsCatalogue/4310.yaml +21 -0
  46. psychopy/alerts/alertsCatalogue/4315.yaml +21 -0
  47. psychopy/alerts/alertsCatalogue/4320.yaml +19 -0
  48. psychopy/alerts/alertsCatalogue/4325.yaml +23 -0
  49. psychopy/alerts/alertsCatalogue/4330.yaml +19 -0
  50. psychopy/alerts/alertsCatalogue/4335.yaml +19 -0
  51. psychopy/alerts/alertsCatalogue/4340.yaml +19 -0
  52. psychopy/alerts/alertsCatalogue/4405.yaml +24 -0
  53. psychopy/alerts/alertsCatalogue/4505.yaml +22 -0
  54. psychopy/alerts/alertsCatalogue/4510.yaml +25 -0
  55. psychopy/alerts/alertsCatalogue/4520.yaml +26 -0
  56. psychopy/alerts/alertsCatalogue/4530.yaml +23 -0
  57. psychopy/alerts/alertsCatalogue/4540.yaml +19 -0
  58. psychopy/alerts/alertsCatalogue/4545.yaml +22 -0
  59. psychopy/alerts/alertsCatalogue/4550.yaml +19 -0
  60. psychopy/alerts/alertsCatalogue/4605.yaml +22 -0
  61. psychopy/alerts/alertsCatalogue/4610.yaml +22 -0
  62. psychopy/alerts/alertsCatalogue/4615.yaml +19 -0
  63. psychopy/alerts/alertsCatalogue/4705.yaml +19 -0
  64. psychopy/alerts/alertsCatalogue/4710.yaml +19 -0
  65. psychopy/alerts/alertsCatalogue/4810.yaml +19 -0
  66. psychopy/alerts/alertsCatalogue/5000.yaml +0 -0
  67. psychopy/alerts/alertsCatalogue/5055.yaml +25 -0
  68. psychopy/alerts/alertsCatalogue/6000.yaml +0 -0
  69. psychopy/alerts/alertsCatalogue/6105.yaml +18 -0
  70. psychopy/alerts/alertsCatalogue/7105.yaml +19 -0
  71. psychopy/alerts/alertsCatalogue/8105.yaml +21 -0
  72. psychopy/alerts/alertsCatalogue/8110.yaml +21 -0
  73. psychopy/alerts/alertsCatalogue/9998.yaml +19 -0
  74. psychopy/alerts/alertsCatalogue/9999.yaml +19 -0
  75. psychopy/alerts/alertsCatalogue/alertCategories.yaml +123 -0
  76. psychopy/alerts/alertsCatalogue/alertTemplate.yaml +19 -0
  77. psychopy/alerts/alertsCatalogue/alertmsg.py +173 -0
  78. psychopy/alerts/alertsCatalogue/generateAlertmsg.py +34 -0
  79. psychopy/alerts/alerttools.py +322 -0
  80. psychopy/app/Resources/README.md +12 -0
  81. psychopy/app/Resources/__init__.py +0 -0
  82. psychopy/app/Resources/betasplash.png +0 -0
  83. psychopy/app/Resources/betasplash@2x.png +0 -0
  84. psychopy/app/Resources/builder.ico +0 -0
  85. psychopy/app/Resources/classic/FlowBottom_CompLeft.png +0 -0
  86. psychopy/app/Resources/classic/FlowBottom_CompRight.png +0 -0
  87. psychopy/app/Resources/classic/FlowTop_CompLeft.png +0 -0
  88. psychopy/app/Resources/classic/FlowTop_CompRight.png +0 -0
  89. psychopy/app/Resources/classic/README.txt +9 -0
  90. psychopy/app/Resources/classic/__init__.py +0 -0
  91. psychopy/app/Resources/classic/_layouts.ai +1138 -1
  92. psychopy/app/Resources/classic/add.png +0 -0
  93. psychopy/app/Resources/classic/add@2x.png +0 -0
  94. psychopy/app/Resources/classic/addExp32.png +0 -0
  95. psychopy/app/Resources/classic/add_many.png +0 -0
  96. psychopy/app/Resources/classic/add_many@2x.png +0 -0
  97. psychopy/app/Resources/classic/alerts.png +0 -0
  98. psychopy/app/Resources/classic/beta.png +0 -0
  99. psychopy/app/Resources/classic/browser.png +0 -0
  100. psychopy/app/Resources/classic/browser@2x.png +0 -0
  101. psychopy/app/Resources/classic/bug16.png +0 -0
  102. psychopy/app/Resources/classic/case.png +0 -0
  103. psychopy/app/Resources/classic/case@2x.png +0 -0
  104. psychopy/app/Resources/classic/circle_mask.png +0 -0
  105. psychopy/app/Resources/classic/circle_mask@2x.png +0 -0
  106. psychopy/app/Resources/classic/clear.png +0 -0
  107. psychopy/app/Resources/classic/clear@2x.png +0 -0
  108. psychopy/app/Resources/classic/coderclass16.png +0 -0
  109. psychopy/app/Resources/classic/coderfunc16.png +0 -0
  110. psychopy/app/Resources/classic/coderimport16.png +0 -0
  111. psychopy/app/Resources/classic/coderjs16.png +0 -0
  112. psychopy/app/Resources/classic/coderpython16.png +0 -0
  113. psychopy/app/Resources/classic/codervar16.png +0 -0
  114. psychopy/app/Resources/classic/cogwindow32.png +0 -0
  115. psychopy/app/Resources/classic/color32.png +0 -0
  116. psychopy/app/Resources/classic/compile32.png +0 -0
  117. psychopy/app/Resources/classic/compile_js.png +0 -0
  118. psychopy/app/Resources/classic/compile_js@2x.png +0 -0
  119. psychopy/app/Resources/classic/compile_py.png +0 -0
  120. psychopy/app/Resources/classic/compile_py@2x.png +0 -0
  121. psychopy/app/Resources/classic/copy16.png +0 -0
  122. psychopy/app/Resources/classic/currentFile.png +0 -0
  123. psychopy/app/Resources/classic/currentFile@2x.png +0 -0
  124. psychopy/app/Resources/classic/delete16.png +0 -0
  125. psychopy/app/Resources/classic/desktop.png +0 -0
  126. psychopy/app/Resources/classic/desktop@2x.png +0 -0
  127. psychopy/app/Resources/classic/devices.png +0 -0
  128. psychopy/app/Resources/classic/devices@2x.png +0 -0
  129. psychopy/app/Resources/classic/dirup16.png +0 -0
  130. psychopy/app/Resources/classic/docclose16.png +0 -0
  131. psychopy/app/Resources/classic/download.png +0 -0
  132. psychopy/app/Resources/classic/edit.png +0 -0
  133. psychopy/app/Resources/classic/edit@2x.png +0 -0
  134. psychopy/app/Resources/classic/editbtn.png +0 -0
  135. psychopy/app/Resources/classic/editbtn16.png +0 -0
  136. psychopy/app/Resources/classic/editbtn16@2x.png +0 -0
  137. psychopy/app/Resources/classic/editbtn@2x.png +0 -0
  138. psychopy/app/Resources/classic/email.png +0 -0
  139. psychopy/app/Resources/classic/email@2x.png +0 -0
  140. psychopy/app/Resources/classic/experiment.png +0 -0
  141. psychopy/app/Resources/classic/experiment@2x.png +0 -0
  142. psychopy/app/Resources/classic/expsettings.png +0 -0
  143. psychopy/app/Resources/classic/expsettings@2x.png +0 -0
  144. psychopy/app/Resources/classic/file.png +0 -0
  145. psychopy/app/Resources/classic/file@2x.png +0 -0
  146. psychopy/app/Resources/classic/fileaudio.png +0 -0
  147. psychopy/app/Resources/classic/fileaudio@2x.png +0 -0
  148. psychopy/app/Resources/classic/filecss.png +0 -0
  149. psychopy/app/Resources/classic/filecss@2x.png +0 -0
  150. psychopy/app/Resources/classic/filecsv.png +0 -0
  151. psychopy/app/Resources/classic/filecsv@2x.png +0 -0
  152. psychopy/app/Resources/classic/filedesign.png +0 -0
  153. psychopy/app/Resources/classic/filedesign@2x.png +0 -0
  154. psychopy/app/Resources/classic/filefont.png +0 -0
  155. psychopy/app/Resources/classic/filefont@2x.png +0 -0
  156. psychopy/app/Resources/classic/filegit.png +0 -0
  157. psychopy/app/Resources/classic/filegit@2x.png +0 -0
  158. psychopy/app/Resources/classic/filehtml.png +0 -0
  159. psychopy/app/Resources/classic/filehtml@2x.png +0 -0
  160. psychopy/app/Resources/classic/fileimage.png +0 -0
  161. psychopy/app/Resources/classic/fileimage@2x.png +0 -0
  162. psychopy/app/Resources/classic/fileinfo.png +0 -0
  163. psychopy/app/Resources/classic/fileinfo@2x.png +0 -0
  164. psychopy/app/Resources/classic/filejs.png +0 -0
  165. psychopy/app/Resources/classic/filejs@2x.png +0 -0
  166. psychopy/app/Resources/classic/filejson.png +0 -0
  167. psychopy/app/Resources/classic/filejson@2x.png +0 -0
  168. psychopy/app/Resources/classic/filenew.png +0 -0
  169. psychopy/app/Resources/classic/filenew32.png +0 -0
  170. psychopy/app/Resources/classic/filenew@2x.png +0 -0
  171. psychopy/app/Resources/classic/fileopen.png +0 -0
  172. psychopy/app/Resources/classic/fileopen32.png +0 -0
  173. psychopy/app/Resources/classic/fileopen@2x.png +0 -0
  174. psychopy/app/Resources/classic/filepkg.png +0 -0
  175. psychopy/app/Resources/classic/filepkg@2x.png +0 -0
  176. psychopy/app/Resources/classic/filepsyexp.png +0 -0
  177. psychopy/app/Resources/classic/filepsyexp@2x.png +0 -0
  178. psychopy/app/Resources/classic/filepy.png +0 -0
  179. psychopy/app/Resources/classic/filepy@2x.png +0 -0
  180. psychopy/app/Resources/classic/filesave.png +0 -0
  181. psychopy/app/Resources/classic/filesave32.png +0 -0
  182. psychopy/app/Resources/classic/filesave@2x.png +0 -0
  183. psychopy/app/Resources/classic/filesaveas.png +0 -0
  184. psychopy/app/Resources/classic/filesaveas32.png +0 -0
  185. psychopy/app/Resources/classic/filesaveas@2x.png +0 -0
  186. psychopy/app/Resources/classic/filetxt.png +0 -0
  187. psychopy/app/Resources/classic/filetxt@2x.png +0 -0
  188. psychopy/app/Resources/classic/fileunknown.png +0 -0
  189. psychopy/app/Resources/classic/fileunknown@2x.png +0 -0
  190. psychopy/app/Resources/classic/filevideo.png +0 -0
  191. psychopy/app/Resources/classic/filevideo@2x.png +0 -0
  192. psychopy/app/Resources/classic/filter.png +0 -0
  193. psychopy/app/Resources/classic/filter@2x.png +0 -0
  194. psychopy/app/Resources/classic/find.png +0 -0
  195. psychopy/app/Resources/classic/find@2x.png +0 -0
  196. psychopy/app/Resources/classic/folder-open16.png +0 -0
  197. psychopy/app/Resources/classic/folder16.png +0 -0
  198. psychopy/app/Resources/classic/foldernew16.png +0 -0
  199. psychopy/app/Resources/classic/fork.png +0 -0
  200. psychopy/app/Resources/classic/fork@2x.png +0 -0
  201. psychopy/app/Resources/classic/github.png +0 -0
  202. psychopy/app/Resources/classic/github@2x.png +0 -0
  203. psychopy/app/Resources/classic/globe.png +0 -0
  204. psychopy/app/Resources/classic/globe@2x.png +0 -0
  205. psychopy/app/Resources/classic/globe_bug.png +0 -0
  206. psychopy/app/Resources/classic/globe_bug@2x.png +0 -0
  207. psychopy/app/Resources/classic/globe_greensync.png +0 -0
  208. psychopy/app/Resources/classic/globe_greensync@2x.png +0 -0
  209. psychopy/app/Resources/classic/globe_info.png +0 -0
  210. psychopy/app/Resources/classic/globe_info@2x.png +0 -0
  211. psychopy/app/Resources/classic/globe_magnifier.png +0 -0
  212. psychopy/app/Resources/classic/globe_magnifier@2x.png +0 -0
  213. psychopy/app/Resources/classic/globe_run.png +0 -0
  214. psychopy/app/Resources/classic/globe_run@2x.png +0 -0
  215. psychopy/app/Resources/classic/globe_user.png +0 -0
  216. psychopy/app/Resources/classic/globe_user@2x.png +0 -0
  217. psychopy/app/Resources/classic/goto16.png +0 -0
  218. psychopy/app/Resources/classic/greendot.png +0 -0
  219. psychopy/app/Resources/classic/greendot@2x.png +0 -0
  220. psychopy/app/Resources/classic/greenglobe.png +0 -0
  221. psychopy/app/Resources/classic/greenglobe@2x.png +0 -0
  222. psychopy/app/Resources/classic/greenglobe_bug.png +0 -0
  223. psychopy/app/Resources/classic/greenglobe_bug@2x.png +0 -0
  224. psychopy/app/Resources/classic/greenglobe_greensync.png +0 -0
  225. psychopy/app/Resources/classic/greenglobe_greensync@2x.png +0 -0
  226. psychopy/app/Resources/classic/greenglobe_info.png +0 -0
  227. psychopy/app/Resources/classic/greenglobe_info@2x.png +0 -0
  228. psychopy/app/Resources/classic/greenglobe_magnifier.png +0 -0
  229. psychopy/app/Resources/classic/greenglobe_magnifier@2x.png +0 -0
  230. psychopy/app/Resources/classic/greenglobe_run.png +0 -0
  231. psychopy/app/Resources/classic/greenglobe_run@2x.png +0 -0
  232. psychopy/app/Resources/classic/greenglobe_user.png +0 -0
  233. psychopy/app/Resources/classic/greenglobe_user@2x.png +0 -0
  234. psychopy/app/Resources/classic/greydot.png +0 -0
  235. psychopy/app/Resources/classic/greydot@2x.png +0 -0
  236. psychopy/app/Resources/classic/greytick.png +0 -0
  237. psychopy/app/Resources/classic/greytick@2x.png +0 -0
  238. psychopy/app/Resources/classic/invalid_img.png +0 -0
  239. psychopy/app/Resources/classic/jsPilot.png +0 -0
  240. psychopy/app/Resources/classic/jsPilot@2x.png +0 -0
  241. psychopy/app/Resources/classic/jsRun.png +0 -0
  242. psychopy/app/Resources/classic/jsRun@2x.png +0 -0
  243. psychopy/app/Resources/classic/libroot.png +0 -0
  244. psychopy/app/Resources/classic/libroot@2x.png +0 -0
  245. psychopy/app/Resources/classic/loop.png +0 -0
  246. psychopy/app/Resources/classic/loop@2x.png +0 -0
  247. psychopy/app/Resources/classic/monitor16.png +0 -0
  248. psychopy/app/Resources/classic/monitors.png +0 -0
  249. psychopy/app/Resources/classic/monitors16.png +0 -0
  250. psychopy/app/Resources/classic/monitors32.png +0 -0
  251. psychopy/app/Resources/classic/monitors@2x.png +0 -0
  252. psychopy/app/Resources/classic/orangedot.png +0 -0
  253. psychopy/app/Resources/classic/orangedot@2x.png +0 -0
  254. psychopy/app/Resources/classic/pavlovia.png +0 -0
  255. psychopy/app/Resources/classic/pavlovia16.png +0 -0
  256. psychopy/app/Resources/classic/pavlovia16@2x.png +0 -0
  257. psychopy/app/Resources/classic/pavlovia@2x.png +0 -0
  258. psychopy/app/Resources/classic/pavsync.png +0 -0
  259. psychopy/app/Resources/classic/pavsync@2x.png +0 -0
  260. psychopy/app/Resources/classic/person_off.png +0 -0
  261. psychopy/app/Resources/classic/person_off@2x.png +0 -0
  262. psychopy/app/Resources/classic/person_on.png +0 -0
  263. psychopy/app/Resources/classic/person_on@2x.png +0 -0
  264. psychopy/app/Resources/classic/photometer.png +0 -0
  265. psychopy/app/Resources/classic/photometer@2x.png +0 -0
  266. psychopy/app/Resources/classic/plugin16.png +0 -0
  267. psychopy/app/Resources/classic/plugin16@2x.png +0 -0
  268. psychopy/app/Resources/classic/plugins32.png +0 -0
  269. psychopy/app/Resources/classic/plus.png +0 -0
  270. psychopy/app/Resources/classic/plus@2x.png +0 -0
  271. psychopy/app/Resources/classic/preferences-app.png +0 -0
  272. psychopy/app/Resources/classic/preferences-app48.png +0 -0
  273. psychopy/app/Resources/classic/preferences-app@2x.png +0 -0
  274. psychopy/app/Resources/classic/preferences-conn.png +0 -0
  275. psychopy/app/Resources/classic/preferences-conn48.png +0 -0
  276. psychopy/app/Resources/classic/preferences-conn@2x.png +0 -0
  277. psychopy/app/Resources/classic/preferences-debug.png +0 -0
  278. psychopy/app/Resources/classic/preferences-debug@2x.png +0 -0
  279. psychopy/app/Resources/classic/preferences-general.png +0 -0
  280. psychopy/app/Resources/classic/preferences-general48.png +0 -0
  281. psychopy/app/Resources/classic/preferences-general@2x.png +0 -0
  282. psychopy/app/Resources/classic/preferences-hardware.png +0 -0
  283. psychopy/app/Resources/classic/preferences-hardware48.png +0 -0
  284. psychopy/app/Resources/classic/preferences-hardware@2x.png +0 -0
  285. psychopy/app/Resources/classic/preferences-keyboard.png +0 -0
  286. psychopy/app/Resources/classic/preferences-keyboard48.png +0 -0
  287. psychopy/app/Resources/classic/preferences-keyboard@2x.png +0 -0
  288. psychopy/app/Resources/classic/preferences-pilot.png +0 -0
  289. psychopy/app/Resources/classic/preferences-pilot@2x.png +0 -0
  290. psychopy/app/Resources/classic/preferences32.png +0 -0
  291. psychopy/app/Resources/classic/pyPilot.png +0 -0
  292. psychopy/app/Resources/classic/pyPilot@2x.png +0 -0
  293. psychopy/app/Resources/classic/pyRun.png +0 -0
  294. psychopy/app/Resources/classic/pyRun@2x.png +0 -0
  295. psychopy/app/Resources/classic/reddot.png +0 -0
  296. psychopy/app/Resources/classic/reddot@2x.png +0 -0
  297. psychopy/app/Resources/classic/redglobe.png +0 -0
  298. psychopy/app/Resources/classic/redglobe@2x.png +0 -0
  299. psychopy/app/Resources/classic/redglobe_bug.png +0 -0
  300. psychopy/app/Resources/classic/redglobe_bug@2x.png +0 -0
  301. psychopy/app/Resources/classic/redglobe_greensync.png +0 -0
  302. psychopy/app/Resources/classic/redglobe_greensync@2x.png +0 -0
  303. psychopy/app/Resources/classic/redglobe_info.png +0 -0
  304. psychopy/app/Resources/classic/redglobe_info@2x.png +0 -0
  305. psychopy/app/Resources/classic/redglobe_magnifier.png +0 -0
  306. psychopy/app/Resources/classic/redglobe_magnifier@2x.png +0 -0
  307. psychopy/app/Resources/classic/redglobe_run.png +0 -0
  308. psychopy/app/Resources/classic/redglobe_run@2x.png +0 -0
  309. psychopy/app/Resources/classic/redglobe_user.png +0 -0
  310. psychopy/app/Resources/classic/redglobe_user@2x.png +0 -0
  311. psychopy/app/Resources/classic/redo.png +0 -0
  312. psychopy/app/Resources/classic/redo32.png +0 -0
  313. psychopy/app/Resources/classic/redo@2x.png +0 -0
  314. psychopy/app/Resources/classic/regex.png +0 -0
  315. psychopy/app/Resources/classic/regex@2x.png +0 -0
  316. psychopy/app/Resources/classic/removeExp32.png +0 -0
  317. psychopy/app/Resources/classic/rename16.png +0 -0
  318. psychopy/app/Resources/classic/restart.png +0 -0
  319. psychopy/app/Resources/classic/restart@2x.png +0 -0
  320. psychopy/app/Resources/classic/run.png +0 -0
  321. psychopy/app/Resources/classic/run@2x.png +0 -0
  322. psychopy/app/Resources/classic/runner.png +0 -0
  323. psychopy/app/Resources/classic/runner@2x.png +0 -0
  324. psychopy/app/Resources/classic/runnerPilot.png +0 -0
  325. psychopy/app/Resources/classic/runnerPilot@2x.png +0 -0
  326. psychopy/app/Resources/classic/savebtn.png +0 -0
  327. psychopy/app/Resources/classic/savebtn16.png +0 -0
  328. psychopy/app/Resources/classic/savebtn16@2x.png +0 -0
  329. psychopy/app/Resources/classic/savebtn@2x.png +0 -0
  330. psychopy/app/Resources/classic/search.png +0 -0
  331. psychopy/app/Resources/classic/search@2x.png +0 -0
  332. psychopy/app/Resources/classic/showBuilder.png +0 -0
  333. psychopy/app/Resources/classic/showBuilder@2x.png +0 -0
  334. psychopy/app/Resources/classic/showCoder.png +0 -0
  335. psychopy/app/Resources/classic/showCoder@2x.png +0 -0
  336. psychopy/app/Resources/classic/showRunner.png +0 -0
  337. psychopy/app/Resources/classic/showRunner@2x.png +0 -0
  338. psychopy/app/Resources/classic/starred.png +0 -0
  339. psychopy/app/Resources/classic/starred@2x.png +0 -0
  340. psychopy/app/Resources/classic/start.png +0 -0
  341. psychopy/app/Resources/classic/start@2x.png +0 -0
  342. psychopy/app/Resources/classic/stdout.png +0 -0
  343. psychopy/app/Resources/classic/stop.png +0 -0
  344. psychopy/app/Resources/classic/stop32.png +0 -0
  345. psychopy/app/Resources/classic/stop@2x.png +0 -0
  346. psychopy/app/Resources/classic/switchCtrlBot.png +0 -0
  347. psychopy/app/Resources/classic/switchCtrlBot@2x.png +0 -0
  348. psychopy/app/Resources/classic/switchCtrlLeft.png +0 -0
  349. psychopy/app/Resources/classic/switchCtrlLeft@2x.png +0 -0
  350. psychopy/app/Resources/classic/switchCtrlRight.png +0 -0
  351. psychopy/app/Resources/classic/switchCtrlRight@2x.png +0 -0
  352. psychopy/app/Resources/classic/switchCtrlTop.png +0 -0
  353. psychopy/app/Resources/classic/switchCtrlTop@2x.png +0 -0
  354. psychopy/app/Resources/classic/tick.png +0 -0
  355. psychopy/app/Resources/classic/tick@2x.png +0 -0
  356. psychopy/app/Resources/classic/undo.png +0 -0
  357. psychopy/app/Resources/classic/undo32.png +0 -0
  358. psychopy/app/Resources/classic/undo@2x.png +0 -0
  359. psychopy/app/Resources/classic/unstarred.png +0 -0
  360. psychopy/app/Resources/classic/unstarred@2x.png +0 -0
  361. psychopy/app/Resources/classic/user_none.png +0 -0
  362. psychopy/app/Resources/classic/view-refresh16.png +0 -0
  363. psychopy/app/Resources/classic/viewbtn.png +0 -0
  364. psychopy/app/Resources/classic/viewbtn16.png +0 -0
  365. psychopy/app/Resources/classic/viewbtn16@2x.png +0 -0
  366. psychopy/app/Resources/classic/viewbtn@2x.png +0 -0
  367. psychopy/app/Resources/classic/windows16.png +0 -0
  368. psychopy/app/Resources/classic/windows16@2x.png +0 -0
  369. psychopy/app/Resources/coder.ico +0 -0
  370. psychopy/app/Resources/dark/FlowBottom_CompLeft.png +0 -0
  371. psychopy/app/Resources/dark/FlowBottom_CompRight.png +0 -0
  372. psychopy/app/Resources/dark/FlowTop_CompLeft.png +0 -0
  373. psychopy/app/Resources/dark/FlowTop_CompRight.png +0 -0
  374. psychopy/app/Resources/dark/README.txt +3 -0
  375. psychopy/app/Resources/dark/__init__.py +0 -0
  376. psychopy/app/Resources/dark/add.png +0 -0
  377. psychopy/app/Resources/dark/add@2x.png +0 -0
  378. psychopy/app/Resources/dark/addExp32.png +0 -0
  379. psychopy/app/Resources/dark/addExp32@2x.png +0 -0
  380. psychopy/app/Resources/dark/add_many.png +0 -0
  381. psychopy/app/Resources/dark/add_many@2x.png +0 -0
  382. psychopy/app/Resources/dark/alerts.png +0 -0
  383. psychopy/app/Resources/dark/alerts@2x.png +0 -0
  384. psychopy/app/Resources/dark/beta.png +0 -0
  385. psychopy/app/Resources/dark/beta@2x.png +0 -0
  386. psychopy/app/Resources/dark/browser.png +0 -0
  387. psychopy/app/Resources/dark/browser@2x.png +0 -0
  388. psychopy/app/Resources/dark/bug16.png +0 -0
  389. psychopy/app/Resources/dark/bug16@2x.png +0 -0
  390. psychopy/app/Resources/dark/case.png +0 -0
  391. psychopy/app/Resources/dark/case@2x.png +0 -0
  392. psychopy/app/Resources/dark/circle_mask.png +0 -0
  393. psychopy/app/Resources/dark/circle_mask@2x.png +0 -0
  394. psychopy/app/Resources/dark/clear.png +0 -0
  395. psychopy/app/Resources/dark/clear@2x.png +0 -0
  396. psychopy/app/Resources/dark/coderclass16.png +0 -0
  397. psychopy/app/Resources/dark/coderclass16@2x.png +0 -0
  398. psychopy/app/Resources/dark/coderfunc16.png +0 -0
  399. psychopy/app/Resources/dark/coderfunc16@2x.png +0 -0
  400. psychopy/app/Resources/dark/coderimport16.png +0 -0
  401. psychopy/app/Resources/dark/coderimport16@2x.png +0 -0
  402. psychopy/app/Resources/dark/coderjs.png +0 -0
  403. psychopy/app/Resources/dark/coderjs@2x.png +0 -0
  404. psychopy/app/Resources/dark/coderpython.png +0 -0
  405. psychopy/app/Resources/dark/coderpython@2x.png +0 -0
  406. psychopy/app/Resources/dark/codervar16.png +0 -0
  407. psychopy/app/Resources/dark/codervar16@2x.png +0 -0
  408. psychopy/app/Resources/dark/cogwindow32.png +0 -0
  409. psychopy/app/Resources/dark/cogwindow32@2x.png +0 -0
  410. psychopy/app/Resources/dark/color32.png +0 -0
  411. psychopy/app/Resources/dark/color32@2x.png +0 -0
  412. psychopy/app/Resources/dark/compile_js.png +0 -0
  413. psychopy/app/Resources/dark/compile_js@2x.png +0 -0
  414. psychopy/app/Resources/dark/compile_py.png +0 -0
  415. psychopy/app/Resources/dark/compile_py@2x.png +0 -0
  416. psychopy/app/Resources/dark/copy16.png +0 -0
  417. psychopy/app/Resources/dark/copy16@2x.png +0 -0
  418. psychopy/app/Resources/dark/currentFile16.png +0 -0
  419. psychopy/app/Resources/dark/currentFile16@2x.png +0 -0
  420. psychopy/app/Resources/dark/delete16.png +0 -0
  421. psychopy/app/Resources/dark/delete16@2x.png +0 -0
  422. psychopy/app/Resources/dark/desktop.png +0 -0
  423. psychopy/app/Resources/dark/desktop@2x.png +0 -0
  424. psychopy/app/Resources/dark/devices.png +0 -0
  425. psychopy/app/Resources/dark/devices@2x.png +0 -0
  426. psychopy/app/Resources/dark/dirup16.png +0 -0
  427. psychopy/app/Resources/dark/dirup16@2x.png +0 -0
  428. psychopy/app/Resources/dark/docclose16.png +0 -0
  429. psychopy/app/Resources/dark/docclose16@2x.png +0 -0
  430. psychopy/app/Resources/dark/download.png +0 -0
  431. psychopy/app/Resources/dark/download@2x.png +0 -0
  432. psychopy/app/Resources/dark/edit.png +0 -0
  433. psychopy/app/Resources/dark/edit@2x.png +0 -0
  434. psychopy/app/Resources/dark/editbtn16.png +0 -0
  435. psychopy/app/Resources/dark/editbtn16@2x.png +0 -0
  436. psychopy/app/Resources/dark/email.png +0 -0
  437. psychopy/app/Resources/dark/email@2x.png +0 -0
  438. psychopy/app/Resources/dark/experiment.png +0 -0
  439. psychopy/app/Resources/dark/experiment@2x.png +0 -0
  440. psychopy/app/Resources/dark/expsettings.png +0 -0
  441. psychopy/app/Resources/dark/expsettings@2x.png +0 -0
  442. psychopy/app/Resources/dark/file.png +0 -0
  443. psychopy/app/Resources/dark/file@16w.png +0 -0
  444. psychopy/app/Resources/dark/file@16w@2x.png +0 -0
  445. psychopy/app/Resources/dark/file@2x.png +0 -0
  446. psychopy/app/Resources/dark/fileaudio.png +0 -0
  447. psychopy/app/Resources/dark/fileaudio@2x.png +0 -0
  448. psychopy/app/Resources/dark/filecss.png +0 -0
  449. psychopy/app/Resources/dark/filecss@2x.png +0 -0
  450. psychopy/app/Resources/dark/filecsv.png +0 -0
  451. psychopy/app/Resources/dark/filecsv@2x.png +0 -0
  452. psychopy/app/Resources/dark/filedesign.png +0 -0
  453. psychopy/app/Resources/dark/filedesign@2x.png +0 -0
  454. psychopy/app/Resources/dark/filefont.png +0 -0
  455. psychopy/app/Resources/dark/filefont@2x.png +0 -0
  456. psychopy/app/Resources/dark/filegit.png +0 -0
  457. psychopy/app/Resources/dark/filegit@2x.png +0 -0
  458. psychopy/app/Resources/dark/filehtml.png +0 -0
  459. psychopy/app/Resources/dark/filehtml@2x.png +0 -0
  460. psychopy/app/Resources/dark/fileimage.png +0 -0
  461. psychopy/app/Resources/dark/fileimage@2x.png +0 -0
  462. psychopy/app/Resources/dark/fileinfo.png +0 -0
  463. psychopy/app/Resources/dark/fileinfo@2x.png +0 -0
  464. psychopy/app/Resources/dark/filejs.png +0 -0
  465. psychopy/app/Resources/dark/filejs@2x.png +0 -0
  466. psychopy/app/Resources/dark/filejson.png +0 -0
  467. psychopy/app/Resources/dark/filejson@2x.png +0 -0
  468. psychopy/app/Resources/dark/filenew.png +0 -0
  469. psychopy/app/Resources/dark/filenew32.png +0 -0
  470. psychopy/app/Resources/dark/filenew32@2x.png +0 -0
  471. psychopy/app/Resources/dark/filenew@2x.png +0 -0
  472. psychopy/app/Resources/dark/fileopen.png +0 -0
  473. psychopy/app/Resources/dark/fileopen32.png +0 -0
  474. psychopy/app/Resources/dark/fileopen32@2x.png +0 -0
  475. psychopy/app/Resources/dark/fileopen@2x.png +0 -0
  476. psychopy/app/Resources/dark/filepkg.png +0 -0
  477. psychopy/app/Resources/dark/filepkg@2x.png +0 -0
  478. psychopy/app/Resources/dark/filepsyexp.png +0 -0
  479. psychopy/app/Resources/dark/filepsyexp@2x.png +0 -0
  480. psychopy/app/Resources/dark/filepy.png +0 -0
  481. psychopy/app/Resources/dark/filepy@2x.png +0 -0
  482. psychopy/app/Resources/dark/filesave.png +0 -0
  483. psychopy/app/Resources/dark/filesave32.png +0 -0
  484. psychopy/app/Resources/dark/filesave32@2x.png +0 -0
  485. psychopy/app/Resources/dark/filesave@2x.png +0 -0
  486. psychopy/app/Resources/dark/filesaveas.png +0 -0
  487. psychopy/app/Resources/dark/filesaveas32.png +0 -0
  488. psychopy/app/Resources/dark/filesaveas32@2x.png +0 -0
  489. psychopy/app/Resources/dark/filesaveas@2x.png +0 -0
  490. psychopy/app/Resources/dark/filetxt.png +0 -0
  491. psychopy/app/Resources/dark/filetxt@2x.png +0 -0
  492. psychopy/app/Resources/dark/fileunknown.png +0 -0
  493. psychopy/app/Resources/dark/fileunknown@2x.png +0 -0
  494. psychopy/app/Resources/dark/filevideo.png +0 -0
  495. psychopy/app/Resources/dark/filevideo@2x.png +0 -0
  496. psychopy/app/Resources/dark/filter.png +0 -0
  497. psychopy/app/Resources/dark/filter@2x.png +0 -0
  498. psychopy/app/Resources/dark/find.png +0 -0
  499. psychopy/app/Resources/dark/find@2x.png +0 -0
  500. psychopy/app/Resources/dark/folder-open16.png +0 -0
  501. psychopy/app/Resources/dark/folder-open16@2x.png +0 -0
  502. psychopy/app/Resources/dark/folder16.png +0 -0
  503. psychopy/app/Resources/dark/folder16@2x.png +0 -0
  504. psychopy/app/Resources/dark/foldernew16.png +0 -0
  505. psychopy/app/Resources/dark/foldernew16@2x.png +0 -0
  506. psychopy/app/Resources/dark/fork.png +0 -0
  507. psychopy/app/Resources/dark/fork@2x.png +0 -0
  508. psychopy/app/Resources/dark/github.png +0 -0
  509. psychopy/app/Resources/dark/github@2x.png +0 -0
  510. psychopy/app/Resources/dark/globe.png +0 -0
  511. psychopy/app/Resources/dark/globe@2x.png +0 -0
  512. psychopy/app/Resources/dark/globe_bug.png +0 -0
  513. psychopy/app/Resources/dark/globe_bug@2x.png +0 -0
  514. psychopy/app/Resources/dark/globe_greensync.png +0 -0
  515. psychopy/app/Resources/dark/globe_greensync@2x.png +0 -0
  516. psychopy/app/Resources/dark/globe_info.png +0 -0
  517. psychopy/app/Resources/dark/globe_info@2x.png +0 -0
  518. psychopy/app/Resources/dark/globe_magnifier.png +0 -0
  519. psychopy/app/Resources/dark/globe_magnifier@2x.png +0 -0
  520. psychopy/app/Resources/dark/globe_run.png +0 -0
  521. psychopy/app/Resources/dark/globe_run@2x.png +0 -0
  522. psychopy/app/Resources/dark/globe_user.png +0 -0
  523. psychopy/app/Resources/dark/globe_user@2x.png +0 -0
  524. psychopy/app/Resources/dark/goto.png +0 -0
  525. psychopy/app/Resources/dark/goto@2x.png +0 -0
  526. psychopy/app/Resources/dark/greendot.png +0 -0
  527. psychopy/app/Resources/dark/greendot@2x.png +0 -0
  528. psychopy/app/Resources/dark/greenglobe.png +0 -0
  529. psychopy/app/Resources/dark/greenglobe@2x.png +0 -0
  530. psychopy/app/Resources/dark/greenglobe_bug.png +0 -0
  531. psychopy/app/Resources/dark/greenglobe_bug@2x.png +0 -0
  532. psychopy/app/Resources/dark/greenglobe_greensync.png +0 -0
  533. psychopy/app/Resources/dark/greenglobe_greensync@2x.png +0 -0
  534. psychopy/app/Resources/dark/greenglobe_info.png +0 -0
  535. psychopy/app/Resources/dark/greenglobe_info@2x.png +0 -0
  536. psychopy/app/Resources/dark/greenglobe_magnifier.png +0 -0
  537. psychopy/app/Resources/dark/greenglobe_magnifier@2x.png +0 -0
  538. psychopy/app/Resources/dark/greenglobe_run.png +0 -0
  539. psychopy/app/Resources/dark/greenglobe_run@2x.png +0 -0
  540. psychopy/app/Resources/dark/greenglobe_user.png +0 -0
  541. psychopy/app/Resources/dark/greenglobe_user@2x.png +0 -0
  542. psychopy/app/Resources/dark/greydot.png +0 -0
  543. psychopy/app/Resources/dark/greydot@2x.png +0 -0
  544. psychopy/app/Resources/dark/greytick.png +0 -0
  545. psychopy/app/Resources/dark/greytick@2x.png +0 -0
  546. psychopy/app/Resources/dark/invalid_img.png +0 -0
  547. psychopy/app/Resources/dark/jsPilot.png +0 -0
  548. psychopy/app/Resources/dark/jsPilot@2x.png +0 -0
  549. psychopy/app/Resources/dark/jsRun.png +0 -0
  550. psychopy/app/Resources/dark/jsRun@2x.png +0 -0
  551. psychopy/app/Resources/dark/libroot16.png +0 -0
  552. psychopy/app/Resources/dark/libroot16@2x.png +0 -0
  553. psychopy/app/Resources/dark/loop.png +0 -0
  554. psychopy/app/Resources/dark/loop@2x.png +0 -0
  555. psychopy/app/Resources/dark/monitor16.png +0 -0
  556. psychopy/app/Resources/dark/monitor16@2x.png +0 -0
  557. psychopy/app/Resources/dark/monitors.png +0 -0
  558. psychopy/app/Resources/dark/monitors32.png +0 -0
  559. psychopy/app/Resources/dark/monitors32@2x.png +0 -0
  560. psychopy/app/Resources/dark/monitors@2x.png +0 -0
  561. psychopy/app/Resources/dark/orangedot.png +0 -0
  562. psychopy/app/Resources/dark/orangedot@2x.png +0 -0
  563. psychopy/app/Resources/dark/pavlovia.png +0 -0
  564. psychopy/app/Resources/dark/pavlovia16.png +0 -0
  565. psychopy/app/Resources/dark/pavlovia16@2x.png +0 -0
  566. psychopy/app/Resources/dark/pavlovia@2x.png +0 -0
  567. psychopy/app/Resources/dark/pavsync.png +0 -0
  568. psychopy/app/Resources/dark/pavsync@2x.png +0 -0
  569. psychopy/app/Resources/dark/person_off.png +0 -0
  570. psychopy/app/Resources/dark/person_off@2x.png +0 -0
  571. psychopy/app/Resources/dark/person_on.png +0 -0
  572. psychopy/app/Resources/dark/person_on@2x.png +0 -0
  573. psychopy/app/Resources/dark/photometer.png +0 -0
  574. psychopy/app/Resources/dark/photometer@2x.png +0 -0
  575. psychopy/app/Resources/dark/plugin16.png +0 -0
  576. psychopy/app/Resources/dark/plugin16@2x.png +0 -0
  577. psychopy/app/Resources/dark/plugins32.png +0 -0
  578. psychopy/app/Resources/dark/plugins32@2x.png +0 -0
  579. psychopy/app/Resources/dark/plus.png +0 -0
  580. psychopy/app/Resources/dark/plus@2x.png +0 -0
  581. psychopy/app/Resources/dark/preferences-app.png +0 -0
  582. psychopy/app/Resources/dark/preferences-app48.png +0 -0
  583. psychopy/app/Resources/dark/preferences-app48@2x.png +0 -0
  584. psychopy/app/Resources/dark/preferences-app@2x.png +0 -0
  585. psychopy/app/Resources/dark/preferences-conn.png +0 -0
  586. psychopy/app/Resources/dark/preferences-conn48.png +0 -0
  587. psychopy/app/Resources/dark/preferences-conn48@2x.png +0 -0
  588. psychopy/app/Resources/dark/preferences-conn@2x.png +0 -0
  589. psychopy/app/Resources/dark/preferences-debug.png +0 -0
  590. psychopy/app/Resources/dark/preferences-debug@2x.png +0 -0
  591. psychopy/app/Resources/dark/preferences-general.png +0 -0
  592. psychopy/app/Resources/dark/preferences-general48.png +0 -0
  593. psychopy/app/Resources/dark/preferences-general48@2x.png +0 -0
  594. psychopy/app/Resources/dark/preferences-general@2x.png +0 -0
  595. psychopy/app/Resources/dark/preferences-hardware.png +0 -0
  596. psychopy/app/Resources/dark/preferences-hardware48.png +0 -0
  597. psychopy/app/Resources/dark/preferences-hardware48@2x.png +0 -0
  598. psychopy/app/Resources/dark/preferences-hardware@2x.png +0 -0
  599. psychopy/app/Resources/dark/preferences-keyboard.png +0 -0
  600. psychopy/app/Resources/dark/preferences-keyboard48.png +0 -0
  601. psychopy/app/Resources/dark/preferences-keyboard48@2x.png +0 -0
  602. psychopy/app/Resources/dark/preferences-keyboard@2x.png +0 -0
  603. psychopy/app/Resources/dark/preferences-pilot.png +0 -0
  604. psychopy/app/Resources/dark/preferences-pilot@2x.png +0 -0
  605. psychopy/app/Resources/dark/preferences32.png +0 -0
  606. psychopy/app/Resources/dark/preferences32@2x.png +0 -0
  607. psychopy/app/Resources/dark/pyPilot.png +0 -0
  608. psychopy/app/Resources/dark/pyPilot@2x.png +0 -0
  609. psychopy/app/Resources/dark/pyRun.png +0 -0
  610. psychopy/app/Resources/dark/pyRun@2x.png +0 -0
  611. psychopy/app/Resources/dark/reddot.png +0 -0
  612. psychopy/app/Resources/dark/reddot@2x.png +0 -0
  613. psychopy/app/Resources/dark/redglobe.png +0 -0
  614. psychopy/app/Resources/dark/redglobe@2x.png +0 -0
  615. psychopy/app/Resources/dark/redglobe_bug.png +0 -0
  616. psychopy/app/Resources/dark/redglobe_bug@2x.png +0 -0
  617. psychopy/app/Resources/dark/redglobe_greensync.png +0 -0
  618. psychopy/app/Resources/dark/redglobe_greensync@2x.png +0 -0
  619. psychopy/app/Resources/dark/redglobe_info.png +0 -0
  620. psychopy/app/Resources/dark/redglobe_info@2x.png +0 -0
  621. psychopy/app/Resources/dark/redglobe_magnifier.png +0 -0
  622. psychopy/app/Resources/dark/redglobe_magnifier@2x.png +0 -0
  623. psychopy/app/Resources/dark/redglobe_run.png +0 -0
  624. psychopy/app/Resources/dark/redglobe_run@2x.png +0 -0
  625. psychopy/app/Resources/dark/redglobe_user.png +0 -0
  626. psychopy/app/Resources/dark/redglobe_user@2x.png +0 -0
  627. psychopy/app/Resources/dark/redo.png +0 -0
  628. psychopy/app/Resources/dark/redo32.png +0 -0
  629. psychopy/app/Resources/dark/redo32@2x.png +0 -0
  630. psychopy/app/Resources/dark/redo@2x.png +0 -0
  631. psychopy/app/Resources/dark/regex.png +0 -0
  632. psychopy/app/Resources/dark/regex@2x.png +0 -0
  633. psychopy/app/Resources/dark/removeExp32.png +0 -0
  634. psychopy/app/Resources/dark/removeExp32@2x.png +0 -0
  635. psychopy/app/Resources/dark/rename16.png +0 -0
  636. psychopy/app/Resources/dark/rename16@2x.png +0 -0
  637. psychopy/app/Resources/dark/restart.png +0 -0
  638. psychopy/app/Resources/dark/restart@2x.png +0 -0
  639. psychopy/app/Resources/dark/runner.png +0 -0
  640. psychopy/app/Resources/dark/runner@2x.png +0 -0
  641. psychopy/app/Resources/dark/runnerPilot.png +0 -0
  642. psychopy/app/Resources/dark/runnerPilot@2x.png +0 -0
  643. psychopy/app/Resources/dark/savebtn16.png +0 -0
  644. psychopy/app/Resources/dark/savebtn16@2x.png +0 -0
  645. psychopy/app/Resources/dark/search.png +0 -0
  646. psychopy/app/Resources/dark/search@2x.png +0 -0
  647. psychopy/app/Resources/dark/showBuilder.png +0 -0
  648. psychopy/app/Resources/dark/showBuilder@2x.png +0 -0
  649. psychopy/app/Resources/dark/showCoder.png +0 -0
  650. psychopy/app/Resources/dark/showCoder@2x.png +0 -0
  651. psychopy/app/Resources/dark/showRunner.png +0 -0
  652. psychopy/app/Resources/dark/showRunner@2x.png +0 -0
  653. psychopy/app/Resources/dark/starred.png +0 -0
  654. psychopy/app/Resources/dark/starred@2x.png +0 -0
  655. psychopy/app/Resources/dark/start.png +0 -0
  656. psychopy/app/Resources/dark/start@2x.png +0 -0
  657. psychopy/app/Resources/dark/stdout.png +0 -0
  658. psychopy/app/Resources/dark/stdout@2x.png +0 -0
  659. psychopy/app/Resources/dark/stop.png +0 -0
  660. psychopy/app/Resources/dark/stop32.png +0 -0
  661. psychopy/app/Resources/dark/stop32@2x.png +0 -0
  662. psychopy/app/Resources/dark/stop@2x.png +0 -0
  663. psychopy/app/Resources/dark/switchCtrlBot.png +0 -0
  664. psychopy/app/Resources/dark/switchCtrlBot@2x.png +0 -0
  665. psychopy/app/Resources/dark/switchCtrlLeft.png +0 -0
  666. psychopy/app/Resources/dark/switchCtrlLeft@2x.png +0 -0
  667. psychopy/app/Resources/dark/switchCtrlRight.png +0 -0
  668. psychopy/app/Resources/dark/switchCtrlRight@2x.png +0 -0
  669. psychopy/app/Resources/dark/switchCtrlTop.png +0 -0
  670. psychopy/app/Resources/dark/switchCtrlTop@2x.png +0 -0
  671. psychopy/app/Resources/dark/tick.png +0 -0
  672. psychopy/app/Resources/dark/tick@2x.png +0 -0
  673. psychopy/app/Resources/dark/undo.png +0 -0
  674. psychopy/app/Resources/dark/undo32.png +0 -0
  675. psychopy/app/Resources/dark/undo32@2x.png +0 -0
  676. psychopy/app/Resources/dark/undo@2x.png +0 -0
  677. psychopy/app/Resources/dark/unstarred.png +0 -0
  678. psychopy/app/Resources/dark/unstarred@2x.png +0 -0
  679. psychopy/app/Resources/dark/user_none.png +0 -0
  680. psychopy/app/Resources/dark/view-refresh16.png +0 -0
  681. psychopy/app/Resources/dark/view-refresh16@2x.png +0 -0
  682. psychopy/app/Resources/dark/viewbtn16.png +0 -0
  683. psychopy/app/Resources/dark/viewbtn16@2x.png +0 -0
  684. psychopy/app/Resources/dark/windows16.png +0 -0
  685. psychopy/app/Resources/dark/windows16@2x.png +0 -0
  686. psychopy/app/Resources/light/FlowBottom_CompLeft.png +0 -0
  687. psychopy/app/Resources/light/FlowBottom_CompRight.png +0 -0
  688. psychopy/app/Resources/light/FlowTop_CompLeft.png +0 -0
  689. psychopy/app/Resources/light/FlowTop_CompRight.png +0 -0
  690. psychopy/app/Resources/light/README.txt +3 -0
  691. psychopy/app/Resources/light/__init__.py +0 -0
  692. psychopy/app/Resources/light/add.png +0 -0
  693. psychopy/app/Resources/light/add@2x.png +0 -0
  694. psychopy/app/Resources/light/addExp32.png +0 -0
  695. psychopy/app/Resources/light/addExp32@2x.png +0 -0
  696. psychopy/app/Resources/light/add_many.png +0 -0
  697. psychopy/app/Resources/light/add_many@2x.png +0 -0
  698. psychopy/app/Resources/light/alerts.png +0 -0
  699. psychopy/app/Resources/light/alerts@2x.png +0 -0
  700. psychopy/app/Resources/light/beta.png +0 -0
  701. psychopy/app/Resources/light/beta@2x.png +0 -0
  702. psychopy/app/Resources/light/browser.png +0 -0
  703. psychopy/app/Resources/light/browser@2x.png +0 -0
  704. psychopy/app/Resources/light/bug16.png +0 -0
  705. psychopy/app/Resources/light/bug16@2x.png +0 -0
  706. psychopy/app/Resources/light/case.png +0 -0
  707. psychopy/app/Resources/light/case@2x.png +0 -0
  708. psychopy/app/Resources/light/circle_mask.png +0 -0
  709. psychopy/app/Resources/light/circle_mask@2x.png +0 -0
  710. psychopy/app/Resources/light/clear.png +0 -0
  711. psychopy/app/Resources/light/clear@2x.png +0 -0
  712. psychopy/app/Resources/light/coderclass16.png +0 -0
  713. psychopy/app/Resources/light/coderclass16@2x.png +0 -0
  714. psychopy/app/Resources/light/coderfunc16.png +0 -0
  715. psychopy/app/Resources/light/coderfunc16@2x.png +0 -0
  716. psychopy/app/Resources/light/coderimport16.png +0 -0
  717. psychopy/app/Resources/light/coderimport16@2x.png +0 -0
  718. psychopy/app/Resources/light/coderjs.png +0 -0
  719. psychopy/app/Resources/light/coderjs@2x.png +0 -0
  720. psychopy/app/Resources/light/coderpython.png +0 -0
  721. psychopy/app/Resources/light/coderpython@2x.png +0 -0
  722. psychopy/app/Resources/light/codervar16.png +0 -0
  723. psychopy/app/Resources/light/codervar16@2x.png +0 -0
  724. psychopy/app/Resources/light/cogwindow32.png +0 -0
  725. psychopy/app/Resources/light/cogwindow32@2x.png +0 -0
  726. psychopy/app/Resources/light/color16.png +0 -0
  727. psychopy/app/Resources/light/color16@2x.png +0 -0
  728. psychopy/app/Resources/light/color32.png +0 -0
  729. psychopy/app/Resources/light/color32@2x.png +0 -0
  730. psychopy/app/Resources/light/compile_js.png +0 -0
  731. psychopy/app/Resources/light/compile_js@2x.png +0 -0
  732. psychopy/app/Resources/light/compile_py.png +0 -0
  733. psychopy/app/Resources/light/compile_py@2x.png +0 -0
  734. psychopy/app/Resources/light/copy16.png +0 -0
  735. psychopy/app/Resources/light/copy16@2x.png +0 -0
  736. psychopy/app/Resources/light/currentFile16.png +0 -0
  737. psychopy/app/Resources/light/currentFile16@2x.png +0 -0
  738. psychopy/app/Resources/light/delete16.png +0 -0
  739. psychopy/app/Resources/light/delete16@2x.png +0 -0
  740. psychopy/app/Resources/light/delete8.png +0 -0
  741. psychopy/app/Resources/light/desktop.png +0 -0
  742. psychopy/app/Resources/light/desktop@2x.png +0 -0
  743. psychopy/app/Resources/light/devices.png +0 -0
  744. psychopy/app/Resources/light/devices@2x.png +0 -0
  745. psychopy/app/Resources/light/dirup16.png +0 -0
  746. psychopy/app/Resources/light/dirup16@2x.png +0 -0
  747. psychopy/app/Resources/light/docclose16.png +0 -0
  748. psychopy/app/Resources/light/docclose16@2x.png +0 -0
  749. psychopy/app/Resources/light/download.png +0 -0
  750. psychopy/app/Resources/light/download@2x.png +0 -0
  751. psychopy/app/Resources/light/edit.png +0 -0
  752. psychopy/app/Resources/light/edit@2x.png +0 -0
  753. psychopy/app/Resources/light/editbtn16.png +0 -0
  754. psychopy/app/Resources/light/editbtn16@2x.png +0 -0
  755. psychopy/app/Resources/light/email.png +0 -0
  756. psychopy/app/Resources/light/email@2x.png +0 -0
  757. psychopy/app/Resources/light/experiment.png +0 -0
  758. psychopy/app/Resources/light/experiment@2x.png +0 -0
  759. psychopy/app/Resources/light/expsettings.png +0 -0
  760. psychopy/app/Resources/light/expsettings@2x.png +0 -0
  761. psychopy/app/Resources/light/file.png +0 -0
  762. psychopy/app/Resources/light/file@2x.png +0 -0
  763. psychopy/app/Resources/light/fileaudio.png +0 -0
  764. psychopy/app/Resources/light/fileaudio@2x.png +0 -0
  765. psychopy/app/Resources/light/filecss.png +0 -0
  766. psychopy/app/Resources/light/filecss@2x.png +0 -0
  767. psychopy/app/Resources/light/filecsv.png +0 -0
  768. psychopy/app/Resources/light/filecsv@2x.png +0 -0
  769. psychopy/app/Resources/light/filedesign.png +0 -0
  770. psychopy/app/Resources/light/filedesign@2x.png +0 -0
  771. psychopy/app/Resources/light/filefont.png +0 -0
  772. psychopy/app/Resources/light/filefont@2x.png +0 -0
  773. psychopy/app/Resources/light/filegit.png +0 -0
  774. psychopy/app/Resources/light/filegit@2x.png +0 -0
  775. psychopy/app/Resources/light/filehtml.png +0 -0
  776. psychopy/app/Resources/light/filehtml@2x.png +0 -0
  777. psychopy/app/Resources/light/fileimage.png +0 -0
  778. psychopy/app/Resources/light/fileimage@2x.png +0 -0
  779. psychopy/app/Resources/light/fileinfo.png +0 -0
  780. psychopy/app/Resources/light/fileinfo@2x.png +0 -0
  781. psychopy/app/Resources/light/filejs.png +0 -0
  782. psychopy/app/Resources/light/filejs@2x.png +0 -0
  783. psychopy/app/Resources/light/filejson.png +0 -0
  784. psychopy/app/Resources/light/filejson@2x.png +0 -0
  785. psychopy/app/Resources/light/filenew.png +0 -0
  786. psychopy/app/Resources/light/filenew32.png +0 -0
  787. psychopy/app/Resources/light/filenew32@2x.png +0 -0
  788. psychopy/app/Resources/light/filenew@2x.png +0 -0
  789. psychopy/app/Resources/light/fileopen.png +0 -0
  790. psychopy/app/Resources/light/fileopen32.png +0 -0
  791. psychopy/app/Resources/light/fileopen32@2x.png +0 -0
  792. psychopy/app/Resources/light/fileopen@2x.png +0 -0
  793. psychopy/app/Resources/light/filepkg.png +0 -0
  794. psychopy/app/Resources/light/filepkg@2x.png +0 -0
  795. psychopy/app/Resources/light/filepsyexp.png +0 -0
  796. psychopy/app/Resources/light/filepsyexp@2x.png +0 -0
  797. psychopy/app/Resources/light/filepy.png +0 -0
  798. psychopy/app/Resources/light/filepy@2x.png +0 -0
  799. psychopy/app/Resources/light/filesave.png +0 -0
  800. psychopy/app/Resources/light/filesave32.png +0 -0
  801. psychopy/app/Resources/light/filesave32@2x.png +0 -0
  802. psychopy/app/Resources/light/filesave@2x.png +0 -0
  803. psychopy/app/Resources/light/filesaveas.png +0 -0
  804. psychopy/app/Resources/light/filesaveas32.png +0 -0
  805. psychopy/app/Resources/light/filesaveas32@2x.png +0 -0
  806. psychopy/app/Resources/light/filesaveas@2x.png +0 -0
  807. psychopy/app/Resources/light/filetxt.png +0 -0
  808. psychopy/app/Resources/light/filetxt@2x.png +0 -0
  809. psychopy/app/Resources/light/fileunknown.png +0 -0
  810. psychopy/app/Resources/light/fileunknown@2x.png +0 -0
  811. psychopy/app/Resources/light/filevideo.png +0 -0
  812. psychopy/app/Resources/light/filevideo@2x.png +0 -0
  813. psychopy/app/Resources/light/filter.png +0 -0
  814. psychopy/app/Resources/light/filter@2x.png +0 -0
  815. psychopy/app/Resources/light/find.png +0 -0
  816. psychopy/app/Resources/light/find@2x.png +0 -0
  817. psychopy/app/Resources/light/folder-open16.png +0 -0
  818. psychopy/app/Resources/light/folder-open16@2x.png +0 -0
  819. psychopy/app/Resources/light/folder16.png +0 -0
  820. psychopy/app/Resources/light/folder16@2x.png +0 -0
  821. psychopy/app/Resources/light/foldernew16.png +0 -0
  822. psychopy/app/Resources/light/foldernew16@2x.png +0 -0
  823. psychopy/app/Resources/light/fork.png +0 -0
  824. psychopy/app/Resources/light/fork@2x.png +0 -0
  825. psychopy/app/Resources/light/github.png +0 -0
  826. psychopy/app/Resources/light/github@2x.png +0 -0
  827. psychopy/app/Resources/light/globe.png +0 -0
  828. psychopy/app/Resources/light/globe@2x.png +0 -0
  829. psychopy/app/Resources/light/globe_bug.png +0 -0
  830. psychopy/app/Resources/light/globe_bug@2x.png +0 -0
  831. psychopy/app/Resources/light/globe_greensync.png +0 -0
  832. psychopy/app/Resources/light/globe_greensync@2x.png +0 -0
  833. psychopy/app/Resources/light/globe_info.png +0 -0
  834. psychopy/app/Resources/light/globe_info@2x.png +0 -0
  835. psychopy/app/Resources/light/globe_magnifier.png +0 -0
  836. psychopy/app/Resources/light/globe_magnifier@2x.png +0 -0
  837. psychopy/app/Resources/light/globe_run.png +0 -0
  838. psychopy/app/Resources/light/globe_run@2x.png +0 -0
  839. psychopy/app/Resources/light/globe_user.png +0 -0
  840. psychopy/app/Resources/light/globe_user@2x.png +0 -0
  841. psychopy/app/Resources/light/goto16.png +0 -0
  842. psychopy/app/Resources/light/goto16@2x.png +0 -0
  843. psychopy/app/Resources/light/greendot.png +0 -0
  844. psychopy/app/Resources/light/greendot@2x.png +0 -0
  845. psychopy/app/Resources/light/greenglobe.png +0 -0
  846. psychopy/app/Resources/light/greenglobe@2x.png +0 -0
  847. psychopy/app/Resources/light/greenglobe_bug.png +0 -0
  848. psychopy/app/Resources/light/greenglobe_bug@2x.png +0 -0
  849. psychopy/app/Resources/light/greenglobe_greensync.png +0 -0
  850. psychopy/app/Resources/light/greenglobe_greensync@2x.png +0 -0
  851. psychopy/app/Resources/light/greenglobe_info.png +0 -0
  852. psychopy/app/Resources/light/greenglobe_info@2x.png +0 -0
  853. psychopy/app/Resources/light/greenglobe_magnifier.png +0 -0
  854. psychopy/app/Resources/light/greenglobe_magnifier@2x.png +0 -0
  855. psychopy/app/Resources/light/greenglobe_run.png +0 -0
  856. psychopy/app/Resources/light/greenglobe_run@2x.png +0 -0
  857. psychopy/app/Resources/light/greenglobe_user.png +0 -0
  858. psychopy/app/Resources/light/greenglobe_user@2x.png +0 -0
  859. psychopy/app/Resources/light/greydot.png +0 -0
  860. psychopy/app/Resources/light/greydot@2x.png +0 -0
  861. psychopy/app/Resources/light/greytick.png +0 -0
  862. psychopy/app/Resources/light/greytick@2x.png +0 -0
  863. psychopy/app/Resources/light/invalid_img.png +0 -0
  864. psychopy/app/Resources/light/jsPilot.png +0 -0
  865. psychopy/app/Resources/light/jsPilot@2x.png +0 -0
  866. psychopy/app/Resources/light/jsRun.png +0 -0
  867. psychopy/app/Resources/light/jsRun@2x.png +0 -0
  868. psychopy/app/Resources/light/libroot16.png +0 -0
  869. psychopy/app/Resources/light/libroot16@2x.png +0 -0
  870. psychopy/app/Resources/light/loop.png +0 -0
  871. psychopy/app/Resources/light/loop@2x.png +0 -0
  872. psychopy/app/Resources/light/monitor16.png +0 -0
  873. psychopy/app/Resources/light/monitor16@2x.png +0 -0
  874. psychopy/app/Resources/light/monitors.png +0 -0
  875. psychopy/app/Resources/light/monitors32.png +0 -0
  876. psychopy/app/Resources/light/monitors32@2x.png +0 -0
  877. psychopy/app/Resources/light/monitors@2x.png +0 -0
  878. psychopy/app/Resources/light/orangedot.png +0 -0
  879. psychopy/app/Resources/light/orangedot@2x.png +0 -0
  880. psychopy/app/Resources/light/pavlovia.png +0 -0
  881. psychopy/app/Resources/light/pavlovia16.png +0 -0
  882. psychopy/app/Resources/light/pavlovia16@2x.png +0 -0
  883. psychopy/app/Resources/light/pavlovia@2x.png +0 -0
  884. psychopy/app/Resources/light/pavsync.png +0 -0
  885. psychopy/app/Resources/light/pavsync@2x.png +0 -0
  886. psychopy/app/Resources/light/person_off.png +0 -0
  887. psychopy/app/Resources/light/person_off@2x.png +0 -0
  888. psychopy/app/Resources/light/person_on.png +0 -0
  889. psychopy/app/Resources/light/person_on@2x.png +0 -0
  890. psychopy/app/Resources/light/photometer.png +0 -0
  891. psychopy/app/Resources/light/photometer@2x.png +0 -0
  892. psychopy/app/Resources/light/plugin16.png +0 -0
  893. psychopy/app/Resources/light/plugin16@2x.png +0 -0
  894. psychopy/app/Resources/light/plugins32.png +0 -0
  895. psychopy/app/Resources/light/plugins32@2x.png +0 -0
  896. psychopy/app/Resources/light/plus.png +0 -0
  897. psychopy/app/Resources/light/plus@2x.png +0 -0
  898. psychopy/app/Resources/light/preferences-app.png +0 -0
  899. psychopy/app/Resources/light/preferences-app48.png +0 -0
  900. psychopy/app/Resources/light/preferences-app48@2x.png +0 -0
  901. psychopy/app/Resources/light/preferences-app@2x.png +0 -0
  902. psychopy/app/Resources/light/preferences-conn.png +0 -0
  903. psychopy/app/Resources/light/preferences-conn48.png +0 -0
  904. psychopy/app/Resources/light/preferences-conn48@2x.png +0 -0
  905. psychopy/app/Resources/light/preferences-conn@2x.png +0 -0
  906. psychopy/app/Resources/light/preferences-general.png +0 -0
  907. psychopy/app/Resources/light/preferences-general48.png +0 -0
  908. psychopy/app/Resources/light/preferences-general48@2x.png +0 -0
  909. psychopy/app/Resources/light/preferences-general@2x.png +0 -0
  910. psychopy/app/Resources/light/preferences-hardware.png +0 -0
  911. psychopy/app/Resources/light/preferences-hardware48.png +0 -0
  912. psychopy/app/Resources/light/preferences-hardware48@2x.png +0 -0
  913. psychopy/app/Resources/light/preferences-hardware@2x.png +0 -0
  914. psychopy/app/Resources/light/preferences-keyboard.png +0 -0
  915. psychopy/app/Resources/light/preferences-keyboard48.png +0 -0
  916. psychopy/app/Resources/light/preferences-keyboard48@2x.png +0 -0
  917. psychopy/app/Resources/light/preferences-keyboard@2x.png +0 -0
  918. psychopy/app/Resources/light/preferences-pilot.png +0 -0
  919. psychopy/app/Resources/light/preferences-pilot@2x.png +0 -0
  920. psychopy/app/Resources/light/preferences32.png +0 -0
  921. psychopy/app/Resources/light/preferences32@2x.png +0 -0
  922. psychopy/app/Resources/light/pyPilot.png +0 -0
  923. psychopy/app/Resources/light/pyPilot@2x.png +0 -0
  924. psychopy/app/Resources/light/pyRun.png +0 -0
  925. psychopy/app/Resources/light/pyRun@2x.png +0 -0
  926. psychopy/app/Resources/light/reddot.png +0 -0
  927. psychopy/app/Resources/light/reddot@2x.png +0 -0
  928. psychopy/app/Resources/light/redglobe.png +0 -0
  929. psychopy/app/Resources/light/redglobe@2x.png +0 -0
  930. psychopy/app/Resources/light/redglobe_bug.png +0 -0
  931. psychopy/app/Resources/light/redglobe_bug@2x.png +0 -0
  932. psychopy/app/Resources/light/redglobe_greensync.png +0 -0
  933. psychopy/app/Resources/light/redglobe_greensync@2x.png +0 -0
  934. psychopy/app/Resources/light/redglobe_info.png +0 -0
  935. psychopy/app/Resources/light/redglobe_info@2x.png +0 -0
  936. psychopy/app/Resources/light/redglobe_magnifier.png +0 -0
  937. psychopy/app/Resources/light/redglobe_magnifier@2x.png +0 -0
  938. psychopy/app/Resources/light/redglobe_run.png +0 -0
  939. psychopy/app/Resources/light/redglobe_run@2x.png +0 -0
  940. psychopy/app/Resources/light/redglobe_user.png +0 -0
  941. psychopy/app/Resources/light/redglobe_user@2x.png +0 -0
  942. psychopy/app/Resources/light/redo.png +0 -0
  943. psychopy/app/Resources/light/redo32.png +0 -0
  944. psychopy/app/Resources/light/redo32@2x.png +0 -0
  945. psychopy/app/Resources/light/redo@2x.png +0 -0
  946. psychopy/app/Resources/light/regex.png +0 -0
  947. psychopy/app/Resources/light/regex@2x.png +0 -0
  948. psychopy/app/Resources/light/removeExp32.png +0 -0
  949. psychopy/app/Resources/light/removeExp32@2x.png +0 -0
  950. psychopy/app/Resources/light/rename16.png +0 -0
  951. psychopy/app/Resources/light/rename16@2x.png +0 -0
  952. psychopy/app/Resources/light/restart.png +0 -0
  953. psychopy/app/Resources/light/restart@2x.png +0 -0
  954. psychopy/app/Resources/light/runner.png +0 -0
  955. psychopy/app/Resources/light/runner@2x.png +0 -0
  956. psychopy/app/Resources/light/runnerPilot.png +0 -0
  957. psychopy/app/Resources/light/runnerPilot@2x.png +0 -0
  958. psychopy/app/Resources/light/savebtn16.png +0 -0
  959. psychopy/app/Resources/light/savebtn16@2x.png +0 -0
  960. psychopy/app/Resources/light/search.png +0 -0
  961. psychopy/app/Resources/light/search@2x.png +0 -0
  962. psychopy/app/Resources/light/showBuilder.png +0 -0
  963. psychopy/app/Resources/light/showBuilder@2x.png +0 -0
  964. psychopy/app/Resources/light/showCoder.png +0 -0
  965. psychopy/app/Resources/light/showCoder@2x.png +0 -0
  966. psychopy/app/Resources/light/showRunner.png +0 -0
  967. psychopy/app/Resources/light/showRunner@2x.png +0 -0
  968. psychopy/app/Resources/light/starred.png +0 -0
  969. psychopy/app/Resources/light/starred@2x.png +0 -0
  970. psychopy/app/Resources/light/start.png +0 -0
  971. psychopy/app/Resources/light/start@2x.png +0 -0
  972. psychopy/app/Resources/light/stdout.png +0 -0
  973. psychopy/app/Resources/light/stdout@2x.png +0 -0
  974. psychopy/app/Resources/light/stop.png +0 -0
  975. psychopy/app/Resources/light/stop32.png +0 -0
  976. psychopy/app/Resources/light/stop32@2x.png +0 -0
  977. psychopy/app/Resources/light/stop@2x.png +0 -0
  978. psychopy/app/Resources/light/switchCtrlBot.png +0 -0
  979. psychopy/app/Resources/light/switchCtrlBot@2x.png +0 -0
  980. psychopy/app/Resources/light/switchCtrlLeft.png +0 -0
  981. psychopy/app/Resources/light/switchCtrlLeft@2x.png +0 -0
  982. psychopy/app/Resources/light/switchCtrlRight.png +0 -0
  983. psychopy/app/Resources/light/switchCtrlRight@2x.png +0 -0
  984. psychopy/app/Resources/light/switchCtrlTop.png +0 -0
  985. psychopy/app/Resources/light/switchCtrlTop@2x.png +0 -0
  986. psychopy/app/Resources/light/tick.png +0 -0
  987. psychopy/app/Resources/light/tick@2x.png +0 -0
  988. psychopy/app/Resources/light/undo.png +0 -0
  989. psychopy/app/Resources/light/undo32.png +0 -0
  990. psychopy/app/Resources/light/undo32@2x.png +0 -0
  991. psychopy/app/Resources/light/undo@2x.png +0 -0
  992. psychopy/app/Resources/light/unstarred.png +0 -0
  993. psychopy/app/Resources/light/unstarred@2x.png +0 -0
  994. psychopy/app/Resources/light/user_none.png +0 -0
  995. psychopy/app/Resources/light/view-refresh16.png +0 -0
  996. psychopy/app/Resources/light/view-refresh16@2x.png +0 -0
  997. psychopy/app/Resources/light/viewbtn16.png +0 -0
  998. psychopy/app/Resources/light/viewbtn16@2x.png +0 -0
  999. psychopy/app/Resources/light/windows16.png +0 -0
  1000. psychopy/app/Resources/light/windows16@2x.png +0 -0
  1001. psychopy/app/Resources/moveComponentIcons.py +50 -0
  1002. psychopy/app/Resources/psychopy.desktop +13 -0
  1003. psychopy/app/Resources/psychopy.icns +0 -0
  1004. psychopy/app/Resources/psychopy.ico +0 -0
  1005. psychopy/app/Resources/psychopy.png +0 -0
  1006. psychopy/app/Resources/psychopy.xml +9 -0
  1007. psychopy/app/Resources/psychopy@2x.png +0 -0
  1008. psychopy/app/Resources/routine_templates/Basic.psyexp +344 -0
  1009. psychopy/app/Resources/routine_templates/Misc.psyexp +228 -0
  1010. psychopy/app/Resources/routine_templates/Online.psyexp +200 -0
  1011. psychopy/app/Resources/routine_templates/Trials.psyexp +735 -0
  1012. psychopy/app/Resources/routine_templates/readme.md +14 -0
  1013. psychopy/app/Resources/runner.ico +0 -0
  1014. psychopy/app/Resources/splash.png +0 -0
  1015. psychopy/app/Resources/splash@2x.png +0 -0
  1016. psychopy/app/Resources/tips.txt +45 -0
  1017. psychopy/app/Resources/tips_ar_001.txt +45 -0
  1018. psychopy/app/Resources/tips_fr_FR.txt +45 -0
  1019. psychopy/app/Resources/tips_ja_JP.txt +42 -0
  1020. psychopy/app/Resources/tips_zh_CN.txt +45 -0
  1021. psychopy/app/Resources/window.ico +0 -0
  1022. psychopy/app/__init__.py +339 -0
  1023. psychopy/app/__main__.py +3 -0
  1024. psychopy/app/_psychopyApp.py +1298 -0
  1025. psychopy/app/appData.spec +58 -0
  1026. psychopy/app/builder/__init__.py +5 -0
  1027. psychopy/app/builder/builder.py +4738 -0
  1028. psychopy/app/builder/dialogs/__init__.py +1910 -0
  1029. psychopy/app/builder/dialogs/dlgsCode.py +631 -0
  1030. psychopy/app/builder/dialogs/dlgsConditions.py +669 -0
  1031. psychopy/app/builder/dialogs/findDlg.py +275 -0
  1032. psychopy/app/builder/dialogs/paramCtrls.py +1802 -0
  1033. psychopy/app/builder/validators.py +589 -0
  1034. psychopy/app/coder/__init__.py +8 -0
  1035. psychopy/app/coder/codeEditorBase.py +460 -0
  1036. psychopy/app/coder/coder.py +3100 -0
  1037. psychopy/app/coder/fileBrowser.py +714 -0
  1038. psychopy/app/coder/folding.py +128 -0
  1039. psychopy/app/coder/psychoParser.py +139 -0
  1040. psychopy/app/coder/repl.py +496 -0
  1041. psychopy/app/coder/sourceTree.py +302 -0
  1042. psychopy/app/colorpicker/__init__.py +594 -0
  1043. psychopy/app/colorpicker/ui.py +336 -0
  1044. psychopy/app/connections/__init__.py +10 -0
  1045. psychopy/app/connections/news.py +104 -0
  1046. psychopy/app/connections/sendusage.py +61 -0
  1047. psychopy/app/connections/updates.py +642 -0
  1048. psychopy/app/console.py +164 -0
  1049. psychopy/app/deviceManager/__init__.py +1 -0
  1050. psychopy/app/deviceManager/addDialog.py +218 -0
  1051. psychopy/app/deviceManager/dialog.py +185 -0
  1052. psychopy/app/deviceManager/panel.py +191 -0
  1053. psychopy/app/deviceManager/utils.py +60 -0
  1054. psychopy/app/dialogs.py +664 -0
  1055. psychopy/app/errorDlg.py +238 -0
  1056. psychopy/app/frametracker.py +8 -0
  1057. psychopy/app/idle.py +181 -0
  1058. psychopy/app/jobs.py +676 -0
  1059. psychopy/app/linuxconfig/__init__.py +153 -0
  1060. psychopy/app/linuxconfig/ui.py +88 -0
  1061. psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
  1062. psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +12695 -0
  1063. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
  1064. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.po +10199 -0
  1065. psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
  1066. psychopy/app/locale/da_DK/LC_MESSAGE/messages.po +10199 -0
  1067. psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
  1068. psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +11221 -0
  1069. psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
  1070. psychopy/app/locale/el_GR/LC_MESSAGE/messages.po +10200 -0
  1071. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
  1072. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.po +10200 -0
  1073. psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
  1074. psychopy/app/locale/en_US/LC_MESSAGE/messages.po +10195 -0
  1075. psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
  1076. psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +11917 -0
  1077. psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
  1078. psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +11924 -0
  1079. psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
  1080. psychopy/app/locale/es_US/LC_MESSAGE/messages.po +11917 -0
  1081. psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
  1082. psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +11084 -0
  1083. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
  1084. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +11590 -0
  1085. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
  1086. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.po +10199 -0
  1087. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
  1088. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +11091 -0
  1089. psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
  1090. psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +11072 -0
  1091. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
  1092. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +11071 -0
  1093. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
  1094. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.po +10200 -0
  1095. psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
  1096. psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +11072 -0
  1097. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  1098. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +11268 -0
  1099. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
  1100. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.po +10199 -0
  1101. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
  1102. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +11463 -0
  1103. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
  1104. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.po +10200 -0
  1105. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
  1106. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.po +10200 -0
  1107. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
  1108. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.po +10200 -0
  1109. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
  1110. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +11288 -0
  1111. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
  1112. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.po +10200 -0
  1113. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
  1114. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.po +10199 -0
  1115. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
  1116. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +11441 -0
  1117. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
  1118. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +11069 -0
  1119. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
  1120. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +12085 -0
  1121. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
  1122. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +11929 -0
  1123. psychopy/app/localizedStrings.py +386 -0
  1124. psychopy/app/pavlovia_ui/__init__.py +22 -0
  1125. psychopy/app/pavlovia_ui/_base.py +268 -0
  1126. psychopy/app/pavlovia_ui/functions.py +176 -0
  1127. psychopy/app/pavlovia_ui/menu.py +140 -0
  1128. psychopy/app/pavlovia_ui/project.py +943 -0
  1129. psychopy/app/pavlovia_ui/search.py +444 -0
  1130. psychopy/app/pavlovia_ui/sync.py +137 -0
  1131. psychopy/app/pavlovia_ui/user.py +264 -0
  1132. psychopy/app/plugin_manager/__init__.py +5 -0
  1133. psychopy/app/plugin_manager/dialog.py +402 -0
  1134. psychopy/app/plugin_manager/output.py +132 -0
  1135. psychopy/app/plugin_manager/packageIndex.py +303 -0
  1136. psychopy/app/plugin_manager/packages.py +643 -0
  1137. psychopy/app/plugin_manager/plugins.py +1363 -0
  1138. psychopy/app/plugin_manager/utils.py +115 -0
  1139. psychopy/app/preferencesDlg.py +771 -0
  1140. psychopy/app/psychopyApp.py +207 -0
  1141. psychopy/app/ribbon.py +1019 -0
  1142. psychopy/app/runner/__init__.py +1 -0
  1143. psychopy/app/runner/runner.py +1299 -0
  1144. psychopy/app/runner/scriptProcess.py +363 -0
  1145. psychopy/app/stdout/__init__.py +1 -0
  1146. psychopy/app/stdout/stdOutRich.py +410 -0
  1147. psychopy/app/sysInfoDlg.py +242 -0
  1148. psychopy/app/themes/__init__.py +78 -0
  1149. psychopy/app/themes/colors.py +201 -0
  1150. psychopy/app/themes/css/contrast_black.css +112 -0
  1151. psychopy/app/themes/css/contrast_white.css +115 -0
  1152. psychopy/app/themes/css/dark.css +112 -0
  1153. psychopy/app/themes/css/light.css +115 -0
  1154. psychopy/app/themes/fonts.py +629 -0
  1155. psychopy/app/themes/handlers.py +321 -0
  1156. psychopy/app/themes/icons.py +267 -0
  1157. psychopy/app/themes/spec/Classic.json +154 -0
  1158. psychopy/app/themes/spec/ClassicDark.json +154 -0
  1159. psychopy/app/themes/spec/GitHub.json +154 -0
  1160. psychopy/app/themes/spec/HiVisDark.json +153 -0
  1161. psychopy/app/themes/spec/HiVisLight.json +154 -0
  1162. psychopy/app/themes/spec/MinimalDark.json +154 -0
  1163. psychopy/app/themes/spec/MinimalLight.json +153 -0
  1164. psychopy/app/themes/spec/PsychopyDark.json +231 -0
  1165. psychopy/app/themes/spec/PsychopyLight.json +236 -0
  1166. psychopy/app/themes/ui.py +74 -0
  1167. psychopy/app/ui/__init__.py +184 -0
  1168. psychopy/app/urls.py +31 -0
  1169. psychopy/app/utils.py +1741 -0
  1170. psychopy/app/viewer/__init__.py +0 -0
  1171. psychopy/assets/Psychopy Window Favicon@16w.png +0 -0
  1172. psychopy/assets/Psychopy Window Favicon@32w.png +0 -0
  1173. psychopy/assets/USB-C.png +0 -0
  1174. psychopy/assets/USB.png +0 -0
  1175. psychopy/assets/__init__.py +0 -0
  1176. psychopy/assets/click.png +0 -0
  1177. psychopy/assets/clicknext.png +0 -0
  1178. psychopy/assets/creditCard.png +0 -0
  1179. psychopy/assets/default.mp3 +0 -0
  1180. psychopy/assets/default.mp4 +0 -0
  1181. psychopy/assets/default.png +0 -0
  1182. psychopy/assets/fonts/Arvo-Bold.ttf +0 -0
  1183. psychopy/assets/fonts/Arvo-BoldItalic.ttf +0 -0
  1184. psychopy/assets/fonts/Arvo-Italic.ttf +0 -0
  1185. psychopy/assets/fonts/Arvo-Regular.ttf +0 -0
  1186. psychopy/assets/fonts/DejaVuSerif.ttf +0 -0
  1187. psychopy/assets/fonts/IndieFlower-Regular.ttf +0 -0
  1188. psychopy/assets/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  1189. psychopy/assets/fonts/JetBrainsMono-VariableFont_wght.ttf +0 -0
  1190. psychopy/assets/fonts/NotoSans-Bold.ttf +0 -0
  1191. psychopy/assets/fonts/NotoSans-BoldItalic.ttf +0 -0
  1192. psychopy/assets/fonts/NotoSans-Italic.ttf +0 -0
  1193. psychopy/assets/fonts/NotoSans-Regular.ttf +0 -0
  1194. psychopy/assets/next.png +0 -0
  1195. psychopy/assets/psychopy.ico +0 -0
  1196. psychopy/assets/psychopy.png +0 -0
  1197. psychopy/assets/templates/__init__.py +0 -0
  1198. psychopy/assets/templates/instruct1.png +0 -0
  1199. psychopy/assets/templates/instruct2.png +0 -0
  1200. psychopy/assets/touch.png +0 -0
  1201. psychopy/assets/touchnext.png +0 -0
  1202. psychopy/assets/voicekeyThresholdStim.wav +0 -0
  1203. psychopy/assets/window.ico +0 -0
  1204. psychopy/changes/2023.1.0.md +9 -0
  1205. psychopy/changes/2024.1.0.md +16 -0
  1206. psychopy/changes/__init__.py +0 -0
  1207. psychopy/clock.py +619 -0
  1208. psychopy/colors.py +1058 -0
  1209. psychopy/compatibility.py +147 -0
  1210. psychopy/constants.py +87 -0
  1211. psychopy/contrib/__init__.py +0 -0
  1212. psychopy/contrib/configobj/LICENSE +39 -0
  1213. psychopy/contrib/configobj/__init__.py +2455 -0
  1214. psychopy/contrib/configobj/_version.py +2 -0
  1215. psychopy/contrib/configobj/validate.py +1458 -0
  1216. psychopy/contrib/lazy_import.py +402 -0
  1217. psychopy/contrib/mseq.py +273 -0
  1218. psychopy/contrib/mseqSearch.py +183 -0
  1219. psychopy/contrib/psi.py +100 -0
  1220. psychopy/contrib/quest.py +484 -0
  1221. psychopy/contrib/tesselate.py +188 -0
  1222. psychopy/core.py +167 -0
  1223. psychopy/data/__init__.py +45 -0
  1224. psychopy/data/base.py +566 -0
  1225. psychopy/data/counterbalance.py +210 -0
  1226. psychopy/data/experiment.py +1049 -0
  1227. psychopy/data/fit.py +248 -0
  1228. psychopy/data/routine.py +94 -0
  1229. psychopy/data/shelf.py +237 -0
  1230. psychopy/data/staircase.py +2270 -0
  1231. psychopy/data/trial.py +2505 -0
  1232. psychopy/data/utils.py +858 -0
  1233. psychopy/demos/__init__.py +0 -0
  1234. psychopy/demos/builder/Design Templates/branchedExperiment/README.md +5 -0
  1235. psychopy/demos/builder/Design Templates/branchedExperiment/branchedExperiment.psyexp +354 -0
  1236. psychopy/demos/builder/Design Templates/branchedExperiment/trialTypes.xlsx +0 -0
  1237. psychopy/demos/builder/Design Templates/psychophysicsStaircase/README.md +20 -0
  1238. psychopy/demos/builder/Design Templates/psychophysicsStaircase/psychophysicsStaircase.psyexp +286 -0
  1239. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/README.md +14 -0
  1240. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/psychophysicsStaircaseInterleaved.psyexp +340 -0
  1241. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/stairDefinitions.xlsx +0 -0
  1242. psychopy/demos/builder/Design Templates/randomisedBlocks/README.md +18 -0
  1243. psychopy/demos/builder/Design Templates/randomisedBlocks/chooseBlock.xlsx +0 -0
  1244. psychopy/demos/builder/Design Templates/randomisedBlocks/facesBlock.xlsx +0 -0
  1245. psychopy/demos/builder/Design Templates/randomisedBlocks/housesBlock.xlsx +0 -0
  1246. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.psyexp +219 -0
  1247. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face01.jpg +0 -0
  1248. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face02.jpg +0 -0
  1249. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/face03.jpg +0 -0
  1250. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house01.jpg +0 -0
  1251. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house02.jpg +0 -0
  1252. psychopy/demos/builder/Design Templates/randomisedBlocks/stims/house03.jpg +0 -0
  1253. psychopy/demos/builder/Experiments/BART/README.md +30 -0
  1254. psychopy/demos/builder/Experiments/BART/assets/background.jpg +0 -0
  1255. psychopy/demos/builder/Experiments/BART/assets/background.png +0 -0
  1256. psychopy/demos/builder/Experiments/BART/assets/bang.mp3 +0 -0
  1257. psychopy/demos/builder/Experiments/BART/assets/bang.wav +0 -0
  1258. psychopy/demos/builder/Experiments/BART/assets/blueBalloon.png +0 -0
  1259. psychopy/demos/builder/Experiments/BART/assets/greenBalloon.png +0 -0
  1260. psychopy/demos/builder/Experiments/BART/assets/redBalloon.png +0 -0
  1261. psychopy/demos/builder/Experiments/BART/bart.psyexp +844 -0
  1262. psychopy/demos/builder/Experiments/BART/spreadsheets/conditions.xlsx +0 -0
  1263. psychopy/demos/builder/Experiments/BigFiveInventory/BFI.psyexp +255 -0
  1264. psychopy/demos/builder/Experiments/BigFiveInventory/README.md +23 -0
  1265. psychopy/demos/builder/Experiments/BigFiveInventory/TIPI.xlsx +0 -0
  1266. psychopy/demos/builder/Experiments/BigFiveInventory/bigFiveItems.xlsx +0 -0
  1267. psychopy/demos/builder/Experiments/BigFiveInventory/demographics.xlsx +0 -0
  1268. psychopy/demos/builder/Experiments/BigFiveInventory/mini_IPIP.xlsx +0 -0
  1269. psychopy/demos/builder/Experiments/GoNoGo/conditions.xlsx +0 -0
  1270. psychopy/demos/builder/Experiments/GoNoGo/gng.psyexp +462 -0
  1271. psychopy/demos/builder/Experiments/GoNoGo/go.png +0 -0
  1272. psychopy/demos/builder/Experiments/GoNoGo/nogo.png +0 -0
  1273. psychopy/demos/builder/Experiments/dragAndDrop/README.md +5 -0
  1274. psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +494 -0
  1275. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/blank_grid.png +0 -0
  1276. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/make_shapes.psyexp +221 -0
  1277. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/readme.md +4 -0
  1278. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_1.png +0 -0
  1279. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_10.png +0 -0
  1280. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_2.png +0 -0
  1281. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_3.png +0 -0
  1282. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_4.png +0 -0
  1283. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_5.png +0 -0
  1284. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_6.png +0 -0
  1285. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_7.png +0 -0
  1286. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_8.png +0 -0
  1287. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_9.png +0 -0
  1288. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solutions.xlsx +0 -0
  1289. psychopy/demos/builder/Experiments/goNoGo/readme.md +14 -0
  1290. psychopy/demos/builder/Experiments/mentalRotation/F.png +0 -0
  1291. psychopy/demos/builder/Experiments/mentalRotation/FR.png +0 -0
  1292. psychopy/demos/builder/Experiments/mentalRotation/MentalRot.csv +33 -0
  1293. psychopy/demos/builder/Experiments/mentalRotation/MentalRotation.psyexp +646 -0
  1294. psychopy/demos/builder/Experiments/mentalRotation/README.md +23 -0
  1295. psychopy/demos/builder/Experiments/navon/NavonTask.psyexp +509 -0
  1296. psychopy/demos/builder/Experiments/navon/README.md +26 -0
  1297. psychopy/demos/builder/Experiments/navon/bigHsmallH.png +0 -0
  1298. psychopy/demos/builder/Experiments/navon/bigHsmallS.png +0 -0
  1299. psychopy/demos/builder/Experiments/navon/bigSsmallH.png +0 -0
  1300. psychopy/demos/builder/Experiments/navon/bigSsmallS.png +0 -0
  1301. psychopy/demos/builder/Experiments/navon/mask.png +0 -0
  1302. psychopy/demos/builder/Experiments/navon/stimuli.pptx +0 -0
  1303. psychopy/demos/builder/Experiments/navon/trialTypes.xlsx +0 -0
  1304. psychopy/demos/builder/Experiments/sternberg/README.md +14 -0
  1305. psychopy/demos/builder/Experiments/sternberg/mainTrials.xlsx +0 -0
  1306. psychopy/demos/builder/Experiments/sternberg/pracTrials.xlsx +0 -0
  1307. psychopy/demos/builder/Experiments/sternberg/sternberg.psyexp +649 -0
  1308. psychopy/demos/builder/Experiments/stroop/README.md +15 -0
  1309. psychopy/demos/builder/Experiments/stroop/stroop.psyexp +321 -0
  1310. psychopy/demos/builder/Experiments/stroop/trialTypes.csv +7 -0
  1311. psychopy/demos/builder/Experiments/stroopExtended/README.md +14 -0
  1312. psychopy/demos/builder/Experiments/stroopExtended/stroop.psyexp +418 -0
  1313. psychopy/demos/builder/Experiments/stroopExtended/stroopReverse.psyexp +418 -0
  1314. psychopy/demos/builder/Experiments/stroopExtended/trialTypes.xlsx +0 -0
  1315. psychopy/demos/builder/Experiments/stroopExtended/trialTypesReverse.xlsx +0 -0
  1316. psychopy/demos/builder/Experiments/stroopVoice/README.md +27 -0
  1317. psychopy/demos/builder/Experiments/stroopVoice/conditions.xlsx +0 -0
  1318. psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +382 -0
  1319. psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +371 -0
  1320. psychopy/demos/builder/Feature Demos/buttonBox/readme.md +5 -0
  1321. psychopy/demos/builder/Feature Demos/counterbalance/counterbalance.psyexp +308 -0
  1322. psychopy/demos/builder/Feature Demos/gratings/gratings.psyexp +391 -0
  1323. psychopy/demos/builder/Feature Demos/gratings/readme.md +8 -0
  1324. psychopy/demos/builder/Feature Demos/movies/movie.psyexp +220 -0
  1325. psychopy/demos/builder/Feature Demos/movies/readme.md +3 -0
  1326. psychopy/demos/builder/Feature Demos/noise/face.jpg +0 -0
  1327. psychopy/demos/builder/Feature Demos/noise/noise.psyexp +477 -0
  1328. psychopy/demos/builder/Feature Demos/noise/readme.md +3 -0
  1329. psychopy/demos/builder/Feature Demos/panorama/panImg.jpg +0 -0
  1330. psychopy/demos/builder/Feature Demos/panorama/panorama.psyexp +177 -0
  1331. psychopy/demos/builder/Feature Demos/pilotMode/pilotMode.psyexp +434 -0
  1332. psychopy/demos/builder/Feature Demos/pilotMode/readme.md +7 -0
  1333. psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp +451 -0
  1334. psychopy/demos/builder/Feature Demos/progress/readme.md +1 -0
  1335. psychopy/demos/builder/Feature Demos/sliders/README.md +8 -0
  1336. psychopy/demos/builder/Feature Demos/sliders/fruitConditions.xlsx +0 -0
  1337. psychopy/demos/builder/Feature Demos/sliders/sliders.psyexp +984 -0
  1338. psychopy/demos/builder/Feature Demos/visualValidator/readme.md +7 -0
  1339. psychopy/demos/builder/Feature Demos/visualValidator/visualValidator.psyexp +199 -0
  1340. psychopy/demos/builder/Hardware/EEG_parallel_component/EEG_triggers_parallel_comp.psyexp +639 -0
  1341. psychopy/demos/builder/Hardware/EEG_serial_code/EEG_triggers_serial_code.psyexp +415 -0
  1342. psychopy/demos/builder/Hardware/EEG_serial_component/EEG_triggers_serial_comp.psyexp +659 -0
  1343. psychopy/demos/builder/Hardware/EGI_netstation/README.md +17 -0
  1344. psychopy/demos/builder/Hardware/EGI_netstation/stroop.psyexp +339 -0
  1345. psychopy/demos/builder/Hardware/EGI_netstation/trialTypesEEG.csv +7 -0
  1346. psychopy/demos/builder/Hardware/Eyetracking_visual_search/readme.md +19 -0
  1347. psychopy/demos/builder/Hardware/Eyetracking_visual_search/trials_params.xlsx +0 -0
  1348. psychopy/demos/builder/Hardware/Eyetracking_visual_search/visualSearch.psyexp +830 -0
  1349. psychopy/demos/builder/Hardware/camera/camera.psyexp +330 -0
  1350. psychopy/demos/builder/Hardware/camera/readme.md +6 -0
  1351. psychopy/demos/builder/Hardware/eyetracking/eyetracking.psyexp +459 -0
  1352. psychopy/demos/builder/Hardware/eyetracking/readme.md +7 -0
  1353. psychopy/demos/builder/Hardware/eyetracking_custom_cal/Bullseye_grey.mov +0 -0
  1354. psychopy/demos/builder/Hardware/eyetracking_custom_cal/eyetracking_custom_cal.psyexp +468 -0
  1355. psychopy/demos/builder/Hardware/eyetracking_custom_cal/readme.md +7 -0
  1356. psychopy/demos/builder/Hardware/fMRI/fMRI_demo.psyexp +211 -0
  1357. psychopy/demos/builder/Hardware/fMRI/readme.md +7 -0
  1358. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo.psyexp +360 -0
  1359. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo_legacy.psyexp +360 -0
  1360. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo_legacy_legacy.psyexp +312 -0
  1361. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy.psyexp +360 -0
  1362. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy.psyexp +360 -0
  1363. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy_legacy.psyexp +312 -0
  1364. psychopy/demos/builder/Hardware/microphone/microphone.psyexp +484 -0
  1365. psychopy/demos/builder/Hardware/microphone/phrases.xlsx +0 -0
  1366. psychopy/demos/builder/Hardware/microphone/readme.md +9 -0
  1367. psychopy/demos/builder/Hardware/pump/README.md +19 -0
  1368. psychopy/demos/builder/Hardware/pump/pump.psyexp +646 -0
  1369. psychopy/demos/builder/Helper Tools/achorVSalignment/FlowCircular-Regular.ttf +0 -0
  1370. psychopy/demos/builder/Helper Tools/achorVSalignment/anchorAlignment.psyexp +350 -0
  1371. psychopy/demos/builder/Helper Tools/achorVSalignment/readme.md +5 -0
  1372. psychopy/demos/builder/Helper Tools/clockFace/README.md +3 -0
  1373. psychopy/demos/builder/Helper Tools/clockFace/clockFace.psyexp +211 -0
  1374. psychopy/demos/builder/Helper Tools/colors/README.md +5 -0
  1375. psychopy/demos/builder/Helper Tools/colors/colors.psyexp +321 -0
  1376. psychopy/demos/builder/Helper Tools/drawPolygon/README.md +5 -0
  1377. psychopy/demos/builder/Helper Tools/drawPolygon/drawPolygon.psyexp +704 -0
  1378. psychopy/demos/builder/Helper Tools/keyNameFinder/README.md +14 -0
  1379. psychopy/demos/builder/Helper Tools/keyNameFinder/keyNameFinder.psyexp +225 -0
  1380. psychopy/demos/builder/Helper Tools/spatialUnits/README.md +6 -0
  1381. psychopy/demos/builder/Helper Tools/spatialUnits/unitDemo.psyexp +206 -0
  1382. psychopy/demos/builder/README.txt +43 -0
  1383. psychopy/demos/builder/__init__.py +0 -0
  1384. psychopy/demos/coder/__init__.py +0 -0
  1385. psychopy/demos/coder/basic/hello_world.py +37 -0
  1386. psychopy/demos/coder/csvFromPsydat.py +29 -0
  1387. psychopy/demos/coder/experiment control/JND_staircase_analysis.py +85 -0
  1388. psychopy/demos/coder/experiment control/JND_staircase_exp.py +110 -0
  1389. psychopy/demos/coder/experiment control/TrialHandler.py +64 -0
  1390. psychopy/demos/coder/experiment control/TrialHandler2.py +42 -0
  1391. psychopy/demos/coder/experiment control/__init__.py +0 -0
  1392. psychopy/demos/coder/experiment control/autoDraw_autoLog.py +50 -0
  1393. psychopy/demos/coder/experiment control/experimentHandler.py +57 -0
  1394. psychopy/demos/coder/experiment control/fMRI_launchScan.py +74 -0
  1395. psychopy/demos/coder/experiment control/gammaMotionAnalysis.py +68 -0
  1396. psychopy/demos/coder/experiment control/gammaMotionNull.py +169 -0
  1397. psychopy/demos/coder/experiment control/logFiles.py +55 -0
  1398. psychopy/demos/coder/experiment control/piloting.py +65 -0
  1399. psychopy/demos/coder/experiment control/runtimeInfo.py +79 -0
  1400. psychopy/demos/coder/hardware/CRS_BitsBox.py +75 -0
  1401. psychopy/demos/coder/hardware/CRS_BitsPlusPlus.py +73 -0
  1402. psychopy/demos/coder/hardware/RiftHeadTrackingExample.py +95 -0
  1403. psychopy/demos/coder/hardware/RiftMinimal.py +44 -0
  1404. psychopy/demos/coder/hardware/VSHD_Distortion.py +49 -0
  1405. psychopy/demos/coder/hardware/__init__.py +0 -0
  1406. psychopy/demos/coder/hardware/camera.py +90 -0
  1407. psychopy/demos/coder/hardware/cedrusRB730.py +38 -0
  1408. psychopy/demos/coder/hardware/crsBitsAdvancedDemo.py +780 -0
  1409. psychopy/demos/coder/hardware/egi_netstation.py +45 -0
  1410. psychopy/demos/coder/hardware/hdf5_extract.py +133 -0
  1411. psychopy/demos/coder/hardware/ioLab_bbox.py +62 -0
  1412. psychopy/demos/coder/hardware/labjack_u3.py +61 -0
  1413. psychopy/demos/coder/hardware/monitorDemo.py +28 -0
  1414. psychopy/demos/coder/hardware/parallelPortOutput.py +49 -0
  1415. psychopy/demos/coder/hardware/qmixPump.py +79 -0
  1416. psychopy/demos/coder/hardware/testSoundLatency.py +127 -0
  1417. psychopy/demos/coder/input/GUI.py +52 -0
  1418. psychopy/demos/coder/input/__init__.py +0 -0
  1419. psychopy/demos/coder/input/customMouse.py +51 -0
  1420. psychopy/demos/coder/input/joystick_universal.py +84 -0
  1421. psychopy/demos/coder/input/keyNameFinder.py +39 -0
  1422. psychopy/demos/coder/input/mic.png +0 -0
  1423. psychopy/demos/coder/input/mouse.py +66 -0
  1424. psychopy/demos/coder/iohub/delaytest.py +231 -0
  1425. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/canal.jpg +0 -0
  1426. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/fall.jpg +0 -0
  1427. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/lake.jpg +0 -0
  1428. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/party.jpg +0 -0
  1429. psychopy/demos/coder/iohub/eyetracking/gcCursor/images/swimming.jpg +0 -0
  1430. psychopy/demos/coder/iohub/eyetracking/gcCursor/readTrialEventsByConditionVariables.py +67 -0
  1431. psychopy/demos/coder/iohub/eyetracking/gcCursor/readTrialEventsByMessages.py +34 -0
  1432. psychopy/demos/coder/iohub/eyetracking/gcCursor/run.py +323 -0
  1433. psychopy/demos/coder/iohub/eyetracking/gcCursor/trial_conditions.xlsx +0 -0
  1434. psychopy/demos/coder/iohub/eyetracking/simple.py +147 -0
  1435. psychopy/demos/coder/iohub/eyetracking/validation.py +251 -0
  1436. psychopy/demos/coder/iohub/iodatastore/saveEventReport.py +56 -0
  1437. psychopy/demos/coder/iohub/keyboard.py +189 -0
  1438. psychopy/demos/coder/iohub/keyboardreactiontime.py +88 -0
  1439. psychopy/demos/coder/iohub/launchHub.py +160 -0
  1440. psychopy/demos/coder/iohub/mouse.py +112 -0
  1441. psychopy/demos/coder/iohub/mouse_multi_window.py +124 -0
  1442. psychopy/demos/coder/iohub/serial/_parseserial.py +53 -0
  1443. psychopy/demos/coder/iohub/serial/customparser.py +84 -0
  1444. psychopy/demos/coder/iohub/serial/pstbox.py +166 -0
  1445. psychopy/demos/coder/iohub/wintab/_wintabgraphics.py +281 -0
  1446. psychopy/demos/coder/iohub/wintab/pen_demo.py +260 -0
  1447. psychopy/demos/coder/misc/encrypt_data.py +48 -0
  1448. psychopy/demos/coder/misc/hdf5_2_csv +33 -0
  1449. psychopy/demos/coder/misc/makeMovie.py +28 -0
  1450. psychopy/demos/coder/misc/rigidBodyTransform.py +76 -0
  1451. psychopy/demos/coder/stimuli/Campaign.ttf +0 -0
  1452. psychopy/demos/coder/stimuli/MovieStim.py +65 -0
  1453. psychopy/demos/coder/stimuli/__init__.py +0 -0
  1454. psychopy/demos/coder/stimuli/aperture.py +37 -0
  1455. psychopy/demos/coder/stimuli/beach.jpg +0 -0
  1456. psychopy/demos/coder/stimuli/bufferImageStim.py +78 -0
  1457. psychopy/demos/coder/stimuli/clockface.py +43 -0
  1458. psychopy/demos/coder/stimuli/colorPalette.py +134 -0
  1459. psychopy/demos/coder/stimuli/compare_text_timing.py +193 -0
  1460. psychopy/demos/coder/stimuli/counterphase.py +43 -0
  1461. psychopy/demos/coder/stimuli/customTextures.py +57 -0
  1462. psychopy/demos/coder/stimuli/dot_gabors.py +35 -0
  1463. psychopy/demos/coder/stimuli/dots.py +35 -0
  1464. psychopy/demos/coder/stimuli/elementArrays.py +92 -0
  1465. psychopy/demos/coder/stimuli/embeddedOpenGL.py +35 -0
  1466. psychopy/demos/coder/stimuli/face.jpg +0 -0
  1467. psychopy/demos/coder/stimuli/face_jpg.py +48 -0
  1468. psychopy/demos/coder/stimuli/gabor.py +30 -0
  1469. psychopy/demos/coder/stimuli/imagesAndPatches.py +51 -0
  1470. psychopy/demos/coder/stimuli/jwpIntro.mp4 +0 -0
  1471. psychopy/demos/coder/stimuli/kanizsa.py +41 -0
  1472. psychopy/demos/coder/stimuli/maskReveal.py +63 -0
  1473. psychopy/demos/coder/stimuli/plaid.py +43 -0
  1474. psychopy/demos/coder/stimuli/ratingScale.py +183 -0
  1475. psychopy/demos/coder/stimuli/rotatingFlashingWedge.py +37 -0
  1476. psychopy/demos/coder/stimuli/screensAndWindows.py +58 -0
  1477. psychopy/demos/coder/stimuli/secondOrderGratings.py +66 -0
  1478. psychopy/demos/coder/stimuli/shapeContains.py +50 -0
  1479. psychopy/demos/coder/stimuli/shapes.py +63 -0
  1480. psychopy/demos/coder/stimuli/soundStimuli.py +49 -0
  1481. psychopy/demos/coder/stimuli/starField.py +48 -0
  1482. psychopy/demos/coder/stimuli/stim3d.py +107 -0
  1483. psychopy/demos/coder/stimuli/textBoxStim/textbox_glyph_placement.py +93 -0
  1484. psychopy/demos/coder/stimuli/textBoxStim/textbox_simple.py +71 -0
  1485. psychopy/demos/coder/stimuli/textStimuli.py +106 -0
  1486. psychopy/demos/coder/stimuli/textbox_editable.py +64 -0
  1487. psychopy/demos/coder/stimuli/variousVisualStims.py +47 -0
  1488. psychopy/demos/coder/stimuli/visual_noise.py +31 -0
  1489. psychopy/demos/coder/sysInfo.py +56 -0
  1490. psychopy/demos/coder/timing/__init__.py +0 -0
  1491. psychopy/demos/coder/timing/callOnFlip.py +39 -0
  1492. psychopy/demos/coder/timing/clocksAndTimers.py +46 -0
  1493. psychopy/demos/coder/timing/millikeyKeyboardTimingTest.py +323 -0
  1494. psychopy/demos/coder/timing/timeByFrames.py +80 -0
  1495. psychopy/demos/coder/timing/timeByFramesEx.py +107 -0
  1496. psychopy/demos/coder/understanding psychopy/colors.py +70 -0
  1497. psychopy/demos/coder/understanding psychopy/fontLayout.py +69 -0
  1498. psychopy/demos/demo_migration.py +214 -0
  1499. psychopy/demos/modernizeDemos.py +16 -0
  1500. psychopy/demos/test_demo_migration.py +155 -0
  1501. psychopy/devices/__init__.py +8 -0
  1502. psychopy/event.py +1339 -0
  1503. psychopy/exceptions.py +59 -0
  1504. psychopy/experiment/__init__.py +51 -0
  1505. psychopy/experiment/_experiment.py +1514 -0
  1506. psychopy/experiment/blankTemplate.xltx +0 -0
  1507. psychopy/experiment/components/__init__.py +402 -0
  1508. psychopy/experiment/components/_base.py +1689 -0
  1509. psychopy/experiment/components/aperture/__init__.py +153 -0
  1510. psychopy/experiment/components/aperture/classic/aperture.png +0 -0
  1511. psychopy/experiment/components/aperture/classic/aperture@2x.png +0 -0
  1512. psychopy/experiment/components/aperture/dark/aperture.png +0 -0
  1513. psychopy/experiment/components/aperture/dark/aperture@2x.png +0 -0
  1514. psychopy/experiment/components/aperture/light/aperture.png +0 -0
  1515. psychopy/experiment/components/aperture/light/aperture@2x.png +0 -0
  1516. psychopy/experiment/components/brush/__init__.py +165 -0
  1517. psychopy/experiment/components/brush/classic/brush.png +0 -0
  1518. psychopy/experiment/components/brush/classic/brush@2x.png +0 -0
  1519. psychopy/experiment/components/brush/dark/brush.png +0 -0
  1520. psychopy/experiment/components/brush/dark/brush@2x.png +0 -0
  1521. psychopy/experiment/components/brush/light/brush.png +0 -0
  1522. psychopy/experiment/components/brush/light/brush@2x.png +0 -0
  1523. psychopy/experiment/components/button/__init__.py +493 -0
  1524. psychopy/experiment/components/button/classic/button.png +0 -0
  1525. psychopy/experiment/components/button/classic/button@2x.png +0 -0
  1526. psychopy/experiment/components/button/dark/button.png +0 -0
  1527. psychopy/experiment/components/button/dark/button@2x.png +0 -0
  1528. psychopy/experiment/components/button/light/button.png +0 -0
  1529. psychopy/experiment/components/button/light/button@2x.png +0 -0
  1530. psychopy/experiment/components/buttonBox/__init__.py +322 -0
  1531. psychopy/experiment/components/buttonBox/classic/buttonBox.png +0 -0
  1532. psychopy/experiment/components/buttonBox/classic/buttonBox@2x.png +0 -0
  1533. psychopy/experiment/components/buttonBox/dark/buttonBox.png +0 -0
  1534. psychopy/experiment/components/buttonBox/dark/buttonBox@2x.png +0 -0
  1535. psychopy/experiment/components/buttonBox/light/buttonBox.png +0 -0
  1536. psychopy/experiment/components/buttonBox/light/buttonBox@2x.png +0 -0
  1537. psychopy/experiment/components/camera/__init__.py +381 -0
  1538. psychopy/experiment/components/camera/classic/webcam.png +0 -0
  1539. psychopy/experiment/components/camera/classic/webcam@2x.png +0 -0
  1540. psychopy/experiment/components/camera/dark/webcam.png +0 -0
  1541. psychopy/experiment/components/camera/dark/webcam@2x.png +0 -0
  1542. psychopy/experiment/components/camera/light/webcam.png +0 -0
  1543. psychopy/experiment/components/camera/light/webcam@2x.png +0 -0
  1544. psychopy/experiment/components/code/__init__.py +299 -0
  1545. psychopy/experiment/components/code/classic/code.png +0 -0
  1546. psychopy/experiment/components/code/classic/code@2x.png +0 -0
  1547. psychopy/experiment/components/code/dark/code.png +0 -0
  1548. psychopy/experiment/components/code/dark/code@2x.png +0 -0
  1549. psychopy/experiment/components/code/light/code.png +0 -0
  1550. psychopy/experiment/components/code/light/code@2x.png +0 -0
  1551. psychopy/experiment/components/dots/__init__.py +199 -0
  1552. psychopy/experiment/components/dots/classic/dots.png +0 -0
  1553. psychopy/experiment/components/dots/classic/dots@2x.png +0 -0
  1554. psychopy/experiment/components/dots/dark/dots.png +0 -0
  1555. psychopy/experiment/components/dots/dark/dots@2x.png +0 -0
  1556. psychopy/experiment/components/dots/dots.xcf +0 -0
  1557. psychopy/experiment/components/dots/light/dots.png +0 -0
  1558. psychopy/experiment/components/dots/light/dots@2x.png +0 -0
  1559. psychopy/experiment/components/eyetracker_record/__init__.py +194 -0
  1560. psychopy/experiment/components/eyetracker_record/classic/eyetracker_record.png +0 -0
  1561. psychopy/experiment/components/eyetracker_record/classic/eyetracker_record@2x.png +0 -0
  1562. psychopy/experiment/components/eyetracker_record/dark/eyetracker_record.png +0 -0
  1563. psychopy/experiment/components/eyetracker_record/dark/eyetracker_record@2x.png +0 -0
  1564. psychopy/experiment/components/eyetracker_record/light/eyetracker_record.png +0 -0
  1565. psychopy/experiment/components/eyetracker_record/light/eyetracker_record@2x.png +0 -0
  1566. psychopy/experiment/components/form/__init__.py +227 -0
  1567. psychopy/experiment/components/form/classic/form.png +0 -0
  1568. psychopy/experiment/components/form/classic/form@2x.png +0 -0
  1569. psychopy/experiment/components/form/dark/form.png +0 -0
  1570. psychopy/experiment/components/form/dark/form@2x.png +0 -0
  1571. psychopy/experiment/components/form/formItems.xltx +0 -0
  1572. psychopy/experiment/components/form/light/form.png +0 -0
  1573. psychopy/experiment/components/form/light/form@2x.png +0 -0
  1574. psychopy/experiment/components/grating/__init__.py +203 -0
  1575. psychopy/experiment/components/grating/classic/grating.png +0 -0
  1576. psychopy/experiment/components/grating/classic/grating@2x.png +0 -0
  1577. psychopy/experiment/components/grating/dark/grating.png +0 -0
  1578. psychopy/experiment/components/grating/dark/grating@2x.png +0 -0
  1579. psychopy/experiment/components/grating/light/grating.png +0 -0
  1580. psychopy/experiment/components/grating/light/grating@2x.png +0 -0
  1581. psychopy/experiment/components/image/__init__.py +195 -0
  1582. psychopy/experiment/components/image/classic/image.png +0 -0
  1583. psychopy/experiment/components/image/classic/image@2x.png +0 -0
  1584. psychopy/experiment/components/image/dark/image.png +0 -0
  1585. psychopy/experiment/components/image/dark/image@2x.png +0 -0
  1586. psychopy/experiment/components/image/light/image.png +0 -0
  1587. psychopy/experiment/components/image/light/image@2x.png +0 -0
  1588. psychopy/experiment/components/joyButtons/__init__.py +453 -0
  1589. psychopy/experiment/components/joyButtons/classic/joyButtons.png +0 -0
  1590. psychopy/experiment/components/joyButtons/classic/joybuttons@2x.png +0 -0
  1591. psychopy/experiment/components/joyButtons/dark/joyButtons.png +0 -0
  1592. psychopy/experiment/components/joyButtons/dark/joyButtons@2x.png +0 -0
  1593. psychopy/experiment/components/joyButtons/light/joyButtons.png +0 -0
  1594. psychopy/experiment/components/joyButtons/light/joyButtons@2x.png +0 -0
  1595. psychopy/experiment/components/joyButtons/virtualJoyButtons.py +34 -0
  1596. psychopy/experiment/components/joystick/__init__.py +572 -0
  1597. psychopy/experiment/components/joystick/classic/joystick.png +0 -0
  1598. psychopy/experiment/components/joystick/classic/joystick@2x.png +0 -0
  1599. psychopy/experiment/components/joystick/dark/joystick.png +0 -0
  1600. psychopy/experiment/components/joystick/dark/joystick@2x.png +0 -0
  1601. psychopy/experiment/components/joystick/light/joystick.png +0 -0
  1602. psychopy/experiment/components/joystick/light/joystick@2x.png +0 -0
  1603. psychopy/experiment/components/joystick/virtualJoystick.py +40 -0
  1604. psychopy/experiment/components/keyboard/__init__.py +568 -0
  1605. psychopy/experiment/components/keyboard/classic/keyboard.png +0 -0
  1606. psychopy/experiment/components/keyboard/classic/keyboard@2x.png +0 -0
  1607. psychopy/experiment/components/keyboard/dark/keyboard.png +0 -0
  1608. psychopy/experiment/components/keyboard/dark/keyboard@2x.png +0 -0
  1609. psychopy/experiment/components/keyboard/light/keyboard.png +0 -0
  1610. psychopy/experiment/components/keyboard/light/keyboard@2x.png +0 -0
  1611. psychopy/experiment/components/keyboard.xcf +0 -0
  1612. psychopy/experiment/components/microphone/__init__.py +600 -0
  1613. psychopy/experiment/components/microphone/classic/microphone.png +0 -0
  1614. psychopy/experiment/components/microphone/classic/microphone@2x.png +0 -0
  1615. psychopy/experiment/components/microphone/dark/microphone.png +0 -0
  1616. psychopy/experiment/components/microphone/dark/microphone@2x.png +0 -0
  1617. psychopy/experiment/components/microphone/light/microphone.png +0 -0
  1618. psychopy/experiment/components/microphone/light/microphone@2x.png +0 -0
  1619. psychopy/experiment/components/mouse/__init__.py +773 -0
  1620. psychopy/experiment/components/mouse/classic/mouse.png +0 -0
  1621. psychopy/experiment/components/mouse/classic/mouse@2x.png +0 -0
  1622. psychopy/experiment/components/mouse/dark/mouse.png +0 -0
  1623. psychopy/experiment/components/mouse/dark/mouse@2x.png +0 -0
  1624. psychopy/experiment/components/mouse/light/mouse.png +0 -0
  1625. psychopy/experiment/components/mouse/light/mouse@2x.png +0 -0
  1626. psychopy/experiment/components/movie/__init__.py +348 -0
  1627. psychopy/experiment/components/movie/classic/movie.png +0 -0
  1628. psychopy/experiment/components/movie/classic/movie@2x.png +0 -0
  1629. psychopy/experiment/components/movie/dark/movie.png +0 -0
  1630. psychopy/experiment/components/movie/dark/movie@2x.png +0 -0
  1631. psychopy/experiment/components/movie/light/movie.png +0 -0
  1632. psychopy/experiment/components/movie/light/movie@2x.png +0 -0
  1633. psychopy/experiment/components/panorama/__init__.py +456 -0
  1634. psychopy/experiment/components/panorama/classic/panorama.png +0 -0
  1635. psychopy/experiment/components/panorama/classic/panorama@2x.png +0 -0
  1636. psychopy/experiment/components/panorama/dark/panorama.png +0 -0
  1637. psychopy/experiment/components/panorama/dark/panorama@2x.png +0 -0
  1638. psychopy/experiment/components/panorama/light/panorama.png +0 -0
  1639. psychopy/experiment/components/panorama/light/panorama@2x.png +0 -0
  1640. psychopy/experiment/components/parallelOut/__init__.py +178 -0
  1641. psychopy/experiment/components/parallelOut/classic/parallel.png +0 -0
  1642. psychopy/experiment/components/parallelOut/classic/parallel@2x.png +0 -0
  1643. psychopy/experiment/components/parallelOut/dark/parallel.png +0 -0
  1644. psychopy/experiment/components/parallelOut/dark/parallel@2x.png +0 -0
  1645. psychopy/experiment/components/parallelOut/light/parallel.png +0 -0
  1646. psychopy/experiment/components/parallelOut/light/parallel@2x.png +0 -0
  1647. psychopy/experiment/components/polygon/__init__.py +332 -0
  1648. psychopy/experiment/components/polygon/classic/polygon.png +0 -0
  1649. psychopy/experiment/components/polygon/classic/polygon@2x.png +0 -0
  1650. psychopy/experiment/components/polygon/dark/polygon.png +0 -0
  1651. psychopy/experiment/components/polygon/dark/polygon@2x.png +0 -0
  1652. psychopy/experiment/components/polygon/light/polygon.png +0 -0
  1653. psychopy/experiment/components/polygon/light/polygon@2x.png +0 -0
  1654. psychopy/experiment/components/progress/__init__.py +130 -0
  1655. psychopy/experiment/components/progress/classic/progress.png +0 -0
  1656. psychopy/experiment/components/progress/classic/progress@2x.png +0 -0
  1657. psychopy/experiment/components/progress/dark/progress.png +0 -0
  1658. psychopy/experiment/components/progress/dark/progress@2x.png +0 -0
  1659. psychopy/experiment/components/progress/light/progress.png +0 -0
  1660. psychopy/experiment/components/progress/light/progress@2x.png +0 -0
  1661. psychopy/experiment/components/resourceManager/__init__.py +176 -0
  1662. psychopy/experiment/components/resourceManager/classic/resource_manager.png +0 -0
  1663. psychopy/experiment/components/resourceManager/classic/resource_manager@2x.png +0 -0
  1664. psychopy/experiment/components/resourceManager/dark/resource_manager.png +0 -0
  1665. psychopy/experiment/components/resourceManager/dark/resource_manager@2x.png +0 -0
  1666. psychopy/experiment/components/resourceManager/light/resource_manager.png +0 -0
  1667. psychopy/experiment/components/resourceManager/light/resource_manager@2x.png +0 -0
  1668. psychopy/experiment/components/roi/__init__.py +316 -0
  1669. psychopy/experiment/components/roi/classic/eyetracker_roi.png +0 -0
  1670. psychopy/experiment/components/roi/classic/eyetracker_roi@2x.png +0 -0
  1671. psychopy/experiment/components/roi/dark/eyetracker_roi.png +0 -0
  1672. psychopy/experiment/components/roi/dark/eyetracker_roi@2X.png +0 -0
  1673. psychopy/experiment/components/roi/light/eyetracker_roi.png +0 -0
  1674. psychopy/experiment/components/roi/light/eyetracker_roi@2X.png +0 -0
  1675. psychopy/experiment/components/routineSettings/__init__.py +387 -0
  1676. psychopy/experiment/components/routineSettings/classic/routineSettings.png +0 -0
  1677. psychopy/experiment/components/routineSettings/classic/routineSettings@2x.png +0 -0
  1678. psychopy/experiment/components/routineSettings/dark/routineSettings.png +0 -0
  1679. psychopy/experiment/components/routineSettings/dark/routineSettings@2x.png +0 -0
  1680. psychopy/experiment/components/routineSettings/light/routineSettings.png +0 -0
  1681. psychopy/experiment/components/routineSettings/light/routineSettings@2x.png +0 -0
  1682. psychopy/experiment/components/serialOut/__init__.py +304 -0
  1683. psychopy/experiment/components/serialOut/classic/serial.png +0 -0
  1684. psychopy/experiment/components/serialOut/classic/serial@2x.png +0 -0
  1685. psychopy/experiment/components/serialOut/dark/serial.png +0 -0
  1686. psychopy/experiment/components/serialOut/dark/serial@2x.png +0 -0
  1687. psychopy/experiment/components/serialOut/light/serial.png +0 -0
  1688. psychopy/experiment/components/serialOut/light/serial@2x.png +0 -0
  1689. psychopy/experiment/components/settings/JS_htmlHeader.tmpl +23 -0
  1690. psychopy/experiment/components/settings/JS_setupExp.tmpl +28 -0
  1691. psychopy/experiment/components/settings/__init__.py +2254 -0
  1692. psychopy/experiment/components/settings/classic/settings.png +0 -0
  1693. psychopy/experiment/components/settings/classic/settings@2x.png +0 -0
  1694. psychopy/experiment/components/settings/dark/settings.png +0 -0
  1695. psychopy/experiment/components/settings/dark/settings@2x.png +0 -0
  1696. psychopy/experiment/components/settings/eyetracking.py +108 -0
  1697. psychopy/experiment/components/settings/light/settings.png +0 -0
  1698. psychopy/experiment/components/settings/light/settings@2x.png +0 -0
  1699. psychopy/experiment/components/slider/__init__.py +410 -0
  1700. psychopy/experiment/components/slider/classic/slider.png +0 -0
  1701. psychopy/experiment/components/slider/classic/slider@2x.png +0 -0
  1702. psychopy/experiment/components/slider/dark/slider.png +0 -0
  1703. psychopy/experiment/components/slider/dark/slider@2x.png +0 -0
  1704. psychopy/experiment/components/slider/light/slider.png +0 -0
  1705. psychopy/experiment/components/slider/light/slider@2x.png +0 -0
  1706. psychopy/experiment/components/sound/__init__.py +441 -0
  1707. psychopy/experiment/components/sound/classic/sound.png +0 -0
  1708. psychopy/experiment/components/sound/classic/sound@2x.png +0 -0
  1709. psychopy/experiment/components/sound/dark/sound.png +0 -0
  1710. psychopy/experiment/components/sound/dark/sound@2x.png +0 -0
  1711. psychopy/experiment/components/sound/light/sound.png +0 -0
  1712. psychopy/experiment/components/sound/light/sound@2x.png +0 -0
  1713. psychopy/experiment/components/soundsensor/__init__.py +324 -0
  1714. psychopy/experiment/components/soundsensor/classic/soundsensor.png +0 -0
  1715. psychopy/experiment/components/soundsensor/classic/soundsensor@2x.png +0 -0
  1716. psychopy/experiment/components/soundsensor/dark/soundsensor.png +0 -0
  1717. psychopy/experiment/components/soundsensor/dark/soundsensor@2x.png +0 -0
  1718. psychopy/experiment/components/soundsensor/light/soundsensor.png +0 -0
  1719. psychopy/experiment/components/soundsensor/light/soundsensor@2x.png +0 -0
  1720. psychopy/experiment/components/static/__init__.py +293 -0
  1721. psychopy/experiment/components/static/classic/static.png +0 -0
  1722. psychopy/experiment/components/static/classic/static@2x.png +0 -0
  1723. psychopy/experiment/components/static/dark/static.png +0 -0
  1724. psychopy/experiment/components/static/dark/static@2x.png +0 -0
  1725. psychopy/experiment/components/static/light/static.png +0 -0
  1726. psychopy/experiment/components/static/light/static@2x.png +0 -0
  1727. psychopy/experiment/components/text/__init__.py +190 -0
  1728. psychopy/experiment/components/text/classic/text.png +0 -0
  1729. psychopy/experiment/components/text/classic/text@2x.png +0 -0
  1730. psychopy/experiment/components/text/dark/text.png +0 -0
  1731. psychopy/experiment/components/text/dark/text@2x.png +0 -0
  1732. psychopy/experiment/components/text/light/text.png +0 -0
  1733. psychopy/experiment/components/text/light/text@2x.png +0 -0
  1734. psychopy/experiment/components/textbox/__init__.py +336 -0
  1735. psychopy/experiment/components/textbox/classic/textbox.png +0 -0
  1736. psychopy/experiment/components/textbox/classic/textbox@2x.png +0 -0
  1737. psychopy/experiment/components/textbox/dark/textbox.png +0 -0
  1738. psychopy/experiment/components/textbox/dark/textbox@2x.png +0 -0
  1739. psychopy/experiment/components/textbox/light/textbox.png +0 -0
  1740. psychopy/experiment/components/textbox/light/textbox@2x.png +0 -0
  1741. psychopy/experiment/components/unknown/__init__.py +87 -0
  1742. psychopy/experiment/components/unknown/classic/unknown.png +0 -0
  1743. psychopy/experiment/components/unknown/classic/unknown@2x.png +0 -0
  1744. psychopy/experiment/components/unknown/dark/unknown.png +0 -0
  1745. psychopy/experiment/components/unknown/dark/unknown@2x.png +0 -0
  1746. psychopy/experiment/components/unknown/light/unknown.png +0 -0
  1747. psychopy/experiment/components/unknown/light/unknown@2x.png +0 -0
  1748. psychopy/experiment/components/unknownPlugin/__init__.py +86 -0
  1749. psychopy/experiment/components/unknownPlugin/classic/unknownPlugin.png +0 -0
  1750. psychopy/experiment/components/unknownPlugin/classic/unknownPlugin@2x.png +0 -0
  1751. psychopy/experiment/components/unknownPlugin/dark/unknownPlugin.png +0 -0
  1752. psychopy/experiment/components/unknownPlugin/dark/unknownPlugin@2x.png +0 -0
  1753. psychopy/experiment/components/unknownPlugin/light/unknownPlugin.png +0 -0
  1754. psychopy/experiment/components/unknownPlugin/light/unknownPlugin@2x.png +0 -0
  1755. psychopy/experiment/components/utils.py +0 -0
  1756. psychopy/experiment/components/variable/__init__.py +184 -0
  1757. psychopy/experiment/components/variable/classic/variable.png +0 -0
  1758. psychopy/experiment/components/variable/classic/variable@2x.png +0 -0
  1759. psychopy/experiment/components/variable/dark/variable.png +0 -0
  1760. psychopy/experiment/components/variable/dark/variable@2x.png +0 -0
  1761. psychopy/experiment/components/variable/light/variable.png +0 -0
  1762. psychopy/experiment/components/variable/light/variable@2x.png +0 -0
  1763. psychopy/experiment/devices.py +303 -0
  1764. psychopy/experiment/experiment.xsd +223 -0
  1765. psychopy/experiment/exports.py +390 -0
  1766. psychopy/experiment/flow.py +547 -0
  1767. psychopy/experiment/localization.py +11 -0
  1768. psychopy/experiment/loopTemplate.xltx +0 -0
  1769. psychopy/experiment/loops.py +1051 -0
  1770. psychopy/experiment/monitor.py +74 -0
  1771. psychopy/experiment/params.py +541 -0
  1772. psychopy/experiment/plugins.py +42 -0
  1773. psychopy/experiment/py2js.py +183 -0
  1774. psychopy/experiment/py2js_transpiler.py +613 -0
  1775. psychopy/experiment/questPlusTemplate.xltx +0 -0
  1776. psychopy/experiment/questTemplate.xltx +0 -0
  1777. psychopy/experiment/routines/__init__.py +108 -0
  1778. psychopy/experiment/routines/_base.py +1172 -0
  1779. psychopy/experiment/routines/audioValidator/__init__.py +229 -0
  1780. psychopy/experiment/routines/audioValidator/classic/audio_validator.png +0 -0
  1781. psychopy/experiment/routines/audioValidator/classic/audio_validator@2x.png +0 -0
  1782. psychopy/experiment/routines/audioValidator/dark/audio_validator.png +0 -0
  1783. psychopy/experiment/routines/audioValidator/dark/audio_validator@2x.png +0 -0
  1784. psychopy/experiment/routines/audioValidator/light/audio_validator.png +0 -0
  1785. psychopy/experiment/routines/audioValidator/light/audio_validator@2x.png +0 -0
  1786. psychopy/experiment/routines/counterbalance/__init__.py +320 -0
  1787. psychopy/experiment/routines/counterbalance/classic/counterbalance.png +0 -0
  1788. psychopy/experiment/routines/counterbalance/classic/counterbalance@2x.png +0 -0
  1789. psychopy/experiment/routines/counterbalance/counterbalanceItems.xltx +0 -0
  1790. psychopy/experiment/routines/counterbalance/dark/counterbalance.png +0 -0
  1791. psychopy/experiment/routines/counterbalance/dark/counterbalance@2x.png +0 -0
  1792. psychopy/experiment/routines/counterbalance/light/counterbalance.png +0 -0
  1793. psychopy/experiment/routines/counterbalance/light/counterbalance@2x.png +0 -0
  1794. psychopy/experiment/routines/eyetracker_calibrate/__init__.py +334 -0
  1795. psychopy/experiment/routines/eyetracker_calibrate/classic/eyetracker_calib.png +0 -0
  1796. psychopy/experiment/routines/eyetracker_calibrate/dark/eyetracker_calib.png +0 -0
  1797. psychopy/experiment/routines/eyetracker_calibrate/dark/eyetracker_calib@2x.png +0 -0
  1798. psychopy/experiment/routines/eyetracker_calibrate/light/eyetracker_calib.png +0 -0
  1799. psychopy/experiment/routines/eyetracker_calibrate/light/eyetracker_calib@2x.png +0 -0
  1800. psychopy/experiment/routines/eyetracker_validate/__init__.py +354 -0
  1801. psychopy/experiment/routines/eyetracker_validate/classic/eyetracker_valid.png +0 -0
  1802. psychopy/experiment/routines/eyetracker_validate/dark/eyetracker_valid.png +0 -0
  1803. psychopy/experiment/routines/eyetracker_validate/dark/eyetracker_valid@2x.png +0 -0
  1804. psychopy/experiment/routines/eyetracker_validate/light/eyetracker_valid.png +0 -0
  1805. psychopy/experiment/routines/eyetracker_validate/light/eyetracker_valid@2x.png +0 -0
  1806. psychopy/experiment/routines/pavlovia_survey/__init__.py +236 -0
  1807. psychopy/experiment/routines/pavlovia_survey/classic/survey.png +0 -0
  1808. psychopy/experiment/routines/pavlovia_survey/classic/survey@2x.png +0 -0
  1809. psychopy/experiment/routines/pavlovia_survey/dark/survey.png +0 -0
  1810. psychopy/experiment/routines/pavlovia_survey/dark/survey@2x.png +0 -0
  1811. psychopy/experiment/routines/pavlovia_survey/light/survey.png +0 -0
  1812. psychopy/experiment/routines/pavlovia_survey/light/survey@2x.png +0 -0
  1813. psychopy/experiment/routines/unknown/__init__.py +30 -0
  1814. psychopy/experiment/routines/unknown/classic/eyetracker_record.png +0 -0
  1815. psychopy/experiment/routines/unknown/classic/unknown.png +0 -0
  1816. psychopy/experiment/routines/unknown/dark/eyetracker_record.png +0 -0
  1817. psychopy/experiment/routines/unknown/dark/eyetracker_record@2x.png +0 -0
  1818. psychopy/experiment/routines/unknown/dark/unknown.png +0 -0
  1819. psychopy/experiment/routines/unknown/dark/unknown@2x.png +0 -0
  1820. psychopy/experiment/routines/unknown/light/eyetracker_record.png +0 -0
  1821. psychopy/experiment/routines/unknown/light/eyetracker_record@2x.png +0 -0
  1822. psychopy/experiment/routines/unknown/light/unknown.png +0 -0
  1823. psychopy/experiment/routines/unknown/light/unknown@2x.png +0 -0
  1824. psychopy/experiment/routines/utils.py +0 -0
  1825. psychopy/experiment/routines/visualValidator/__init__.py +395 -0
  1826. psychopy/experiment/routines/visualValidator/classic/visual_validator.png +0 -0
  1827. psychopy/experiment/routines/visualValidator/classic/visual_validator@2x.png +0 -0
  1828. psychopy/experiment/routines/visualValidator/dark/visual_validator.png +0 -0
  1829. psychopy/experiment/routines/visualValidator/dark/visual_validator@2x.png +0 -0
  1830. psychopy/experiment/routines/visualValidator/light/visual_validator.png +0 -0
  1831. psychopy/experiment/routines/visualValidator/light/visual_validator@2x.png +0 -0
  1832. psychopy/experiment/staircaseTemplate.xltx +0 -0
  1833. psychopy/experiment/utils.py +44 -0
  1834. psychopy/filters.py +11 -0
  1835. psychopy/gamma.py +9 -0
  1836. psychopy/gui/__init__.py +47 -0
  1837. psychopy/gui/qtgui.py +882 -0
  1838. psychopy/gui/util.py +74 -0
  1839. psychopy/gui/wxgui.py +420 -0
  1840. psychopy/hardware/__init__.py +178 -0
  1841. psychopy/hardware/base.py +466 -0
  1842. psychopy/hardware/bbtk/__init__.py +24 -0
  1843. psychopy/hardware/brainproducts.py +25 -0
  1844. psychopy/hardware/button.py +238 -0
  1845. psychopy/hardware/buttonbox/__init__.py +122 -0
  1846. psychopy/hardware/camera/__init__.py +3657 -0
  1847. psychopy/hardware/cedrus.py +24 -0
  1848. psychopy/hardware/crs/__init__.py +46 -0
  1849. psychopy/hardware/crs/bits.py +37 -0
  1850. psychopy/hardware/crs/colorcal.py +18 -0
  1851. psychopy/hardware/crs/optical.py +33 -0
  1852. psychopy/hardware/crs/shaders.py +34 -0
  1853. psychopy/hardware/emotiv.py +33 -0
  1854. psychopy/hardware/emulator.py +46 -0
  1855. psychopy/hardware/exceptions.py +86 -0
  1856. psychopy/hardware/eyetracker.py +132 -0
  1857. psychopy/hardware/forp.py +37 -0
  1858. psychopy/hardware/gammasci.py +26 -0
  1859. psychopy/hardware/iolab.py +24 -0
  1860. psychopy/hardware/joystick/__init__.py +1196 -0
  1861. psychopy/hardware/joystick/_base.py +251 -0
  1862. psychopy/hardware/joystick/backend_glfw.py +306 -0
  1863. psychopy/hardware/joystick/backend_pyglet.py +309 -0
  1864. psychopy/hardware/joystick/mappings.py +287 -0
  1865. psychopy/hardware/keyboard.py +975 -0
  1866. psychopy/hardware/knownDevices.json +52 -0
  1867. psychopy/hardware/labhackers.py +27 -0
  1868. psychopy/hardware/labjacks.py +26 -0
  1869. psychopy/hardware/lightsensor.py +789 -0
  1870. psychopy/hardware/listener.py +330 -0
  1871. psychopy/hardware/manager.py +992 -0
  1872. psychopy/hardware/microphone.py +1630 -0
  1873. psychopy/hardware/minolta.py +33 -0
  1874. psychopy/hardware/monitor.py +144 -0
  1875. psychopy/hardware/mouse/__init__.py +885 -0
  1876. psychopy/hardware/photometer/__init__.py +207 -0
  1877. psychopy/hardware/pr.py +33 -0
  1878. psychopy/hardware/qmix.py +32 -0
  1879. psychopy/hardware/serialdevice.py +387 -0
  1880. psychopy/hardware/soundsensor.py +476 -0
  1881. psychopy/hardware/spatial/__init__.py +231 -0
  1882. psychopy/hardware/speaker.py +351 -0
  1883. psychopy/hardware/triggerbox/__init__.py +56 -0
  1884. psychopy/hardware/triggerbox/base.py +170 -0
  1885. psychopy/hardware/triggerbox/parallel.py +362 -0
  1886. psychopy/info.py +719 -0
  1887. psychopy/iohub/__init__.py +50 -0
  1888. psychopy/iohub/client/__init__.py +1481 -0
  1889. psychopy/iohub/client/connect.py +260 -0
  1890. psychopy/iohub/client/eyetracker/__init__.py +4 -0
  1891. psychopy/iohub/client/eyetracker/validation/__init__.py +8 -0
  1892. psychopy/iohub/client/eyetracker/validation/posgrid.py +274 -0
  1893. psychopy/iohub/client/eyetracker/validation/procedure.py +1292 -0
  1894. psychopy/iohub/client/eyetracker/validation/trigger.py +240 -0
  1895. psychopy/iohub/client/keyboard.py +513 -0
  1896. psychopy/iohub/client/wintab.py +378 -0
  1897. psychopy/iohub/constants.py +1176 -0
  1898. psychopy/iohub/datastore/__init__.py +439 -0
  1899. psychopy/iohub/datastore/default_datastore.yaml +8 -0
  1900. psychopy/iohub/datastore/util.py +868 -0
  1901. psychopy/iohub/default_config.yaml +17 -0
  1902. psychopy/iohub/devices/__init__.py +1047 -0
  1903. psychopy/iohub/devices/computer.py +607 -0
  1904. psychopy/iohub/devices/default_device.yaml +15 -0
  1905. psychopy/iohub/devices/deviceConfigValidation.py +519 -0
  1906. psychopy/iohub/devices/display/__init__.py +755 -0
  1907. psychopy/iohub/devices/display/default_display.yaml +118 -0
  1908. psychopy/iohub/devices/display/supported_config_settings.yaml +69 -0
  1909. psychopy/iohub/devices/eventfilters.py +3572 -0
  1910. psychopy/iohub/devices/experiment/__init__.py +316 -0
  1911. psychopy/iohub/devices/experiment/default_experiment.yaml +74 -0
  1912. psychopy/iohub/devices/experiment/supported_config_settings.yaml +26 -0
  1913. psychopy/iohub/devices/eyetracker/__init__.py +474 -0
  1914. psychopy/iohub/devices/eyetracker/calibration/__init__.py +1 -0
  1915. psychopy/iohub/devices/eyetracker/calibration/procedure.py +391 -0
  1916. psychopy/iohub/devices/eyetracker/default_eyetracker.yaml +18 -0
  1917. psychopy/iohub/devices/eyetracker/eye_events.py +1751 -0
  1918. psychopy/iohub/devices/eyetracker/filters/__init__.py +4 -0
  1919. psychopy/iohub/devices/eyetracker/filters/parser.py +913 -0
  1920. psychopy/iohub/devices/eyetracker/hw/__init__.py +4 -0
  1921. psychopy/iohub/devices/eyetracker/hw/gazepoint/__init__.py +29 -0
  1922. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/__init__.py +29 -0
  1923. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/calibration.py +18 -0
  1924. psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/eyetracker.py +31 -0
  1925. psychopy/iohub/devices/eyetracker/hw/mouse/__init__.py +8 -0
  1926. psychopy/iohub/devices/eyetracker/hw/mouse/calibration.py +10 -0
  1927. psychopy/iohub/devices/eyetracker/hw/mouse/default_eyetracker.yaml +102 -0
  1928. psychopy/iohub/devices/eyetracker/hw/mouse/eyetracker.py +443 -0
  1929. psychopy/iohub/devices/eyetracker/hw/mouse/supported_config_settings.yaml +110 -0
  1930. psychopy/iohub/devices/eyetracker/hw/pupil_labs/__init__.py +4 -0
  1931. psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/__init__.py +27 -0
  1932. psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/eyetracker.py +18 -0
  1933. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/__init__.py +29 -0
  1934. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/bisector.py +20 -0
  1935. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/constants.py +19 -0
  1936. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/data_parse.py +22 -0
  1937. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/eyetracker.py +18 -0
  1938. psychopy/iohub/devices/eyetracker/hw/pupil_labs/pupil_core/pupil_remote.py +18 -0
  1939. psychopy/iohub/devices/eyetracker/hw/sr_research/__init__.py +4 -0
  1940. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/__init__.py +28 -0
  1941. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/calibration.py +22 -0
  1942. psychopy/iohub/devices/eyetracker/hw/sr_research/eyelink/eyetracker.py +38 -0
  1943. psychopy/iohub/devices/eyetracker/hw/tobii/__init__.py +29 -0
  1944. psychopy/iohub/devices/eyetracker/hw/tobii/calibration.py +19 -0
  1945. psychopy/iohub/devices/eyetracker/hw/tobii/eyetracker.py +17 -0
  1946. psychopy/iohub/devices/eyetracker/hw/tobii/tobiiwrapper.py +19 -0
  1947. psychopy/iohub/devices/eyetracker/supported_config_settings.yaml +44 -0
  1948. psychopy/iohub/devices/keyboard/__init__.py +309 -0
  1949. psychopy/iohub/devices/keyboard/darwin.py +431 -0
  1950. psychopy/iohub/devices/keyboard/darwinkey.py +94 -0
  1951. psychopy/iohub/devices/keyboard/default_keyboard.yaml +94 -0
  1952. psychopy/iohub/devices/keyboard/linux2.py +102 -0
  1953. psychopy/iohub/devices/keyboard/supported_config_settings.yaml +39 -0
  1954. psychopy/iohub/devices/keyboard/win32.py +356 -0
  1955. psychopy/iohub/devices/mouse/__init__.py +709 -0
  1956. psychopy/iohub/devices/mouse/darwin.py +414 -0
  1957. psychopy/iohub/devices/mouse/default_mouse.yaml +92 -0
  1958. psychopy/iohub/devices/mouse/linux2.py +172 -0
  1959. psychopy/iohub/devices/mouse/supported_config_settings.yaml +39 -0
  1960. psychopy/iohub/devices/mouse/win32.py +284 -0
  1961. psychopy/iohub/devices/pyXHook.py +619 -0
  1962. psychopy/iohub/devices/serial/__init__.py +779 -0
  1963. psychopy/iohub/devices/serial/default_pstbox.yaml +108 -0
  1964. psychopy/iohub/devices/serial/default_serial.yaml +108 -0
  1965. psychopy/iohub/devices/serial/supported_config_settings.yaml +85 -0
  1966. psychopy/iohub/devices/serial/supported_config_settings_pstbox.yaml +85 -0
  1967. psychopy/iohub/devices/supported_config_settings.yaml +36 -0
  1968. psychopy/iohub/devices/wintab/__init__.py +580 -0
  1969. psychopy/iohub/devices/wintab/default_wintab.yaml +89 -0
  1970. psychopy/iohub/devices/wintab/supported_config_settings.yaml +42 -0
  1971. psychopy/iohub/devices/wintab/win32.py +722 -0
  1972. psychopy/iohub/devices/xlib.py +6795 -0
  1973. psychopy/iohub/errors.py +61 -0
  1974. psychopy/iohub/lazy_import.py +582 -0
  1975. psychopy/iohub/net.py +349 -0
  1976. psychopy/iohub/server.py +1075 -0
  1977. psychopy/iohub/start_iohub_process.py +121 -0
  1978. psychopy/iohub/util/__init__.py +832 -0
  1979. psychopy/iohub/util/visualangle.py +126 -0
  1980. psychopy/layout.py +916 -0
  1981. psychopy/liaison.py +471 -0
  1982. psychopy/locale_setup.py +41 -0
  1983. psychopy/localization/__init__.py +22 -0
  1984. psychopy/localization/_localization.py +155 -0
  1985. psychopy/localization/generateTranslationTemplate.py +257 -0
  1986. psychopy/localization/mappings.txt +170 -0
  1987. psychopy/localization/messages.pot +9950 -0
  1988. psychopy/localization/readme.txt +68 -0
  1989. psychopy/logging.py +415 -0
  1990. psychopy/microphone.py +28 -0
  1991. psychopy/misc.py +40 -0
  1992. psychopy/monitors/MonitorCenter.py +1354 -0
  1993. psychopy/monitors/__init__.py +30 -0
  1994. psychopy/monitors/calibData.py +78 -0
  1995. psychopy/monitors/calibTools.py +1301 -0
  1996. psychopy/monitors/getLumSeries.py +50 -0
  1997. psychopy/monitors/psychopy-icon.svg +395 -0
  1998. psychopy/monitors/psychopy.ico +0 -0
  1999. psychopy/parallel/__init__.py +206 -0
  2000. psychopy/parallel/_dlportio.py +150 -0
  2001. psychopy/parallel/_inpout.py +120 -0
  2002. psychopy/parallel/_linux.py +105 -0
  2003. psychopy/piloting.py +61 -0
  2004. psychopy/platform_specific/__init__.py +46 -0
  2005. psychopy/platform_specific/darwin.py +326 -0
  2006. psychopy/platform_specific/linux.py +77 -0
  2007. psychopy/platform_specific/win32.py +124 -0
  2008. psychopy/plugins/__init__.py +1397 -0
  2009. psychopy/plugins/util.py +104 -0
  2010. psychopy/preferences/Darwin.spec +294 -0
  2011. psychopy/preferences/FreeBSD.spec +294 -0
  2012. psychopy/preferences/Linux.spec +294 -0
  2013. psychopy/preferences/Windows.spec +294 -0
  2014. psychopy/preferences/__init__.py +20 -0
  2015. psychopy/preferences/baseNoArch.spec +290 -0
  2016. psychopy/preferences/devices.py +80 -0
  2017. psychopy/preferences/generateHints.py +93 -0
  2018. psychopy/preferences/generateSpec.py +80 -0
  2019. psychopy/preferences/hints.py +367 -0
  2020. psychopy/preferences/preferences.py +448 -0
  2021. psychopy/projects/__init__.py +11 -0
  2022. psychopy/projects/gitignore.py +45 -0
  2023. psychopy/projects/pavlovia.py +1674 -0
  2024. psychopy/projects/sshkeys.py +107 -0
  2025. psychopy/psychojs.zip +0 -0
  2026. psychopy/pylintrc +69 -0
  2027. psychopy/scripts/__init__.py +0 -0
  2028. psychopy/scripts/psychopy-pkgutil.py +969 -0
  2029. psychopy/scripts/psyexpCompile.py +229 -0
  2030. psychopy/session.py +1651 -0
  2031. psychopy/sound/__init__.py +50 -0
  2032. psychopy/sound/_base.py +399 -0
  2033. psychopy/sound/audioclip.py +1325 -0
  2034. psychopy/sound/audiodevice.py +857 -0
  2035. psychopy/sound/backend_ptb.py +406 -0
  2036. psychopy/sound/backend_pygame.py +323 -0
  2037. psychopy/sound/backend_pyo.py +64 -0
  2038. psychopy/sound/backend_pysound.py +324 -0
  2039. psychopy/sound/backend_sounddevice.py +44 -0
  2040. psychopy/sound/backends/__init__.py +0 -0
  2041. psychopy/sound/exceptions.py +115 -0
  2042. psychopy/sound/microphone.py +357 -0
  2043. psychopy/sound/sound.py +58 -0
  2044. psychopy/sound/transcribe.py +1321 -0
  2045. psychopy/tests/README.md +344 -0
  2046. psychopy/tests/__init__.py +47 -0
  2047. psychopy/tests/data/Electronic_Chime-KevanGC-495939803.wav +0 -0
  2048. psychopy/tests/data/TestCircle_w128h128_bottom_left.png +0 -0
  2049. psychopy/tests/data/TestCircle_w128h128_bottom_right.png +0 -0
  2050. psychopy/tests/data/TestCircle_w128h128_center_center.png +0 -0
  2051. psychopy/tests/data/TestCircle_w128h128_top_left.png +0 -0
  2052. psychopy/tests/data/TestCircle_w128h128_top_right.png +0 -0
  2053. psychopy/tests/data/TestCircle_w128h64_bottom_left.png +0 -0
  2054. psychopy/tests/data/TestCircle_w128h64_bottom_right.png +0 -0
  2055. psychopy/tests/data/TestCircle_w128h64_center_center.png +0 -0
  2056. psychopy/tests/data/TestCircle_w128h64_top_left.png +0 -0
  2057. psychopy/tests/data/TestCircle_w128h64_top_right.png +0 -0
  2058. psychopy/tests/data/TestCircle_w64h128_bottom_left.png +0 -0
  2059. psychopy/tests/data/TestCircle_w64h128_bottom_right.png +0 -0
  2060. psychopy/tests/data/TestCircle_w64h128_center_center.png +0 -0
  2061. psychopy/tests/data/TestCircle_w64h128_top_left.png +0 -0
  2062. psychopy/tests/data/TestCircle_w64h128_top_right.png +0 -0
  2063. psychopy/tests/data/TestCircle_w64h64_bottom_left.png +0 -0
  2064. psychopy/tests/data/TestCircle_w64h64_bottom_right.png +0 -0
  2065. psychopy/tests/data/TestCircle_w64h64_center_center.png +0 -0
  2066. psychopy/tests/data/TestCircle_w64h64_top_left.png +0 -0
  2067. psychopy/tests/data/TestCircle_w64h64_top_right.png +0 -0
  2068. psychopy/tests/data/TestForm_scrolling_nq10_s0.5.png +0 -0
  2069. psychopy/tests/data/TestForm_scrolling_nq10_s0.png +0 -0
  2070. psychopy/tests/data/TestForm_scrolling_nq10_s1.png +0 -0
  2071. psychopy/tests/data/TestForm_scrolling_nq1_s0.5.png +0 -0
  2072. psychopy/tests/data/TestForm_scrolling_nq1_s0.png +0 -0
  2073. psychopy/tests/data/TestForm_scrolling_nq1_s1.png +0 -0
  2074. psychopy/tests/data/TestForm_scrolling_nq3_s0.5.png +0 -0
  2075. psychopy/tests/data/TestForm_scrolling_nq3_s0.png +0 -0
  2076. psychopy/tests/data/TestForm_scrolling_nq3_s1.png +0 -0
  2077. psychopy/tests/data/TestImage_w128h128_bottom_left.png +0 -0
  2078. psychopy/tests/data/TestImage_w128h128_bottom_right.png +0 -0
  2079. psychopy/tests/data/TestImage_w128h128_center_center.png +0 -0
  2080. psychopy/tests/data/TestImage_w128h128_top_left.png +0 -0
  2081. psychopy/tests/data/TestImage_w128h128_top_right.png +0 -0
  2082. psychopy/tests/data/TestImage_w128h64_bottom_left.png +0 -0
  2083. psychopy/tests/data/TestImage_w128h64_bottom_right.png +0 -0
  2084. psychopy/tests/data/TestImage_w128h64_center_center.png +0 -0
  2085. psychopy/tests/data/TestImage_w128h64_top_left.png +0 -0
  2086. psychopy/tests/data/TestImage_w128h64_top_right.png +0 -0
  2087. psychopy/tests/data/TestImage_w64h128_bottom_left.png +0 -0
  2088. psychopy/tests/data/TestImage_w64h128_bottom_right.png +0 -0
  2089. psychopy/tests/data/TestImage_w64h128_center_center.png +0 -0
  2090. psychopy/tests/data/TestImage_w64h128_top_left.png +0 -0
  2091. psychopy/tests/data/TestImage_w64h128_top_right.png +0 -0
  2092. psychopy/tests/data/TestImage_w64h64_bottom_left.png +0 -0
  2093. psychopy/tests/data/TestImage_w64h64_bottom_right.png +0 -0
  2094. psychopy/tests/data/TestImage_w64h64_center_center.png +0 -0
  2095. psychopy/tests/data/TestImage_w64h64_top_left.png +0 -0
  2096. psychopy/tests/data/TestImage_w64h64_top_right.png +0 -0
  2097. psychopy/tests/data/TestProgress_testValue_horizontal_center center_0.3.png +0 -0
  2098. psychopy/tests/data/TestProgress_testValue_horizontal_center center_0.6.png +0 -0
  2099. psychopy/tests/data/TestProgress_testValue_horizontal_left center_0.3.png +0 -0
  2100. psychopy/tests/data/TestProgress_testValue_horizontal_left center_0.6.png +0 -0
  2101. psychopy/tests/data/TestProgress_testValue_horizontal_right center_0.3.png +0 -0
  2102. psychopy/tests/data/TestProgress_testValue_horizontal_right center_0.6.png +0 -0
  2103. psychopy/tests/data/TestProgress_testValue_minmax_0.png +0 -0
  2104. psychopy/tests/data/TestProgress_testValue_minmax_1.png +0 -0
  2105. psychopy/tests/data/TestProgress_testValue_vertical_bottom center_0.3.png +0 -0
  2106. psychopy/tests/data/TestProgress_testValue_vertical_bottom center_0.6.png +0 -0
  2107. psychopy/tests/data/TestProgress_testValue_vertical_center center_0.3.png +0 -0
  2108. psychopy/tests/data/TestProgress_testValue_vertical_center center_0.6.png +0 -0
  2109. psychopy/tests/data/TestProgress_testValue_vertical_top center_0.3.png +0 -0
  2110. psychopy/tests/data/TestProgress_testValue_vertical_top center_0.6.png +0 -0
  2111. psychopy/tests/data/TestProgress_w128h128_bottom_left.png +0 -0
  2112. psychopy/tests/data/TestProgress_w128h128_bottom_right.png +0 -0
  2113. psychopy/tests/data/TestProgress_w128h128_center_center.png +0 -0
  2114. psychopy/tests/data/TestProgress_w128h128_top_left.png +0 -0
  2115. psychopy/tests/data/TestProgress_w128h128_top_right.png +0 -0
  2116. psychopy/tests/data/TestProgress_w128h64_bottom_left.png +0 -0
  2117. psychopy/tests/data/TestProgress_w128h64_bottom_right.png +0 -0
  2118. psychopy/tests/data/TestProgress_w128h64_center_center.png +0 -0
  2119. psychopy/tests/data/TestProgress_w128h64_top_left.png +0 -0
  2120. psychopy/tests/data/TestProgress_w128h64_top_right.png +0 -0
  2121. psychopy/tests/data/TestProgress_w64h128_bottom_left.png +0 -0
  2122. psychopy/tests/data/TestProgress_w64h128_bottom_right.png +0 -0
  2123. psychopy/tests/data/TestProgress_w64h128_center_center.png +0 -0
  2124. psychopy/tests/data/TestProgress_w64h128_top_left.png +0 -0
  2125. psychopy/tests/data/TestProgress_w64h128_top_right.png +0 -0
  2126. psychopy/tests/data/TestProgress_w64h64_bottom_left.png +0 -0
  2127. psychopy/tests/data/TestProgress_w64h64_bottom_right.png +0 -0
  2128. psychopy/tests/data/TestProgress_w64h64_center_center.png +0 -0
  2129. psychopy/tests/data/TestProgress_w64h64_top_left.png +0 -0
  2130. psychopy/tests/data/TestProgress_w64h64_top_right.png +0 -0
  2131. psychopy/tests/data/TestROI_w128h128_bottom_left.png +0 -0
  2132. psychopy/tests/data/TestROI_w128h128_bottom_right.png +0 -0
  2133. psychopy/tests/data/TestROI_w128h128_center_center.png +0 -0
  2134. psychopy/tests/data/TestROI_w128h128_top_left.png +0 -0
  2135. psychopy/tests/data/TestROI_w128h128_top_right.png +0 -0
  2136. psychopy/tests/data/TestROI_w128h64_bottom_left.png +0 -0
  2137. psychopy/tests/data/TestROI_w128h64_bottom_right.png +0 -0
  2138. psychopy/tests/data/TestROI_w128h64_center_center.png +0 -0
  2139. psychopy/tests/data/TestROI_w128h64_top_left.png +0 -0
  2140. psychopy/tests/data/TestROI_w128h64_top_right.png +0 -0
  2141. psychopy/tests/data/TestROI_w64h128_bottom_left.png +0 -0
  2142. psychopy/tests/data/TestROI_w64h128_bottom_right.png +0 -0
  2143. psychopy/tests/data/TestROI_w64h128_center_center.png +0 -0
  2144. psychopy/tests/data/TestROI_w64h128_top_left.png +0 -0
  2145. psychopy/tests/data/TestROI_w64h128_top_right.png +0 -0
  2146. psychopy/tests/data/TestROI_w64h64_bottom_left.png +0 -0
  2147. psychopy/tests/data/TestROI_w64h64_bottom_right.png +0 -0
  2148. psychopy/tests/data/TestROI_w64h64_center_center.png +0 -0
  2149. psychopy/tests/data/TestROI_w64h64_top_left.png +0 -0
  2150. psychopy/tests/data/TestROI_w64h64_top_right.png +0 -0
  2151. psychopy/tests/data/TestSession_exp1.png +0 -0
  2152. psychopy/tests/data/TestSession_exp2.png +0 -0
  2153. psychopy/tests/data/TestShape_w128h128_bottom_left.png +0 -0
  2154. psychopy/tests/data/TestShape_w128h128_bottom_right.png +0 -0
  2155. psychopy/tests/data/TestShape_w128h128_center_center.png +0 -0
  2156. psychopy/tests/data/TestShape_w128h128_top_left.png +0 -0
  2157. psychopy/tests/data/TestShape_w128h128_top_right.png +0 -0
  2158. psychopy/tests/data/TestShape_w128h64_bottom_left.png +0 -0
  2159. psychopy/tests/data/TestShape_w128h64_bottom_right.png +0 -0
  2160. psychopy/tests/data/TestShape_w128h64_center_center.png +0 -0
  2161. psychopy/tests/data/TestShape_w128h64_top_left.png +0 -0
  2162. psychopy/tests/data/TestShape_w128h64_top_right.png +0 -0
  2163. psychopy/tests/data/TestShape_w64h128_bottom_left.png +0 -0
  2164. psychopy/tests/data/TestShape_w64h128_bottom_right.png +0 -0
  2165. psychopy/tests/data/TestShape_w64h128_center_center.png +0 -0
  2166. psychopy/tests/data/TestShape_w64h128_top_left.png +0 -0
  2167. psychopy/tests/data/TestShape_w64h128_top_right.png +0 -0
  2168. psychopy/tests/data/TestShape_w64h64_bottom_left.png +0 -0
  2169. psychopy/tests/data/TestShape_w64h64_bottom_right.png +0 -0
  2170. psychopy/tests/data/TestShape_w64h64_center_center.png +0 -0
  2171. psychopy/tests/data/TestShape_w64h64_top_left.png +0 -0
  2172. psychopy/tests/data/TestShape_w64h64_top_right.png +0 -0
  2173. psychopy/tests/data/TestTarget_w128h128_bottom_left.png +0 -0
  2174. psychopy/tests/data/TestTarget_w128h128_bottom_right.png +0 -0
  2175. psychopy/tests/data/TestTarget_w128h128_center_center.png +0 -0
  2176. psychopy/tests/data/TestTarget_w128h128_top_left.png +0 -0
  2177. psychopy/tests/data/TestTarget_w128h128_top_right.png +0 -0
  2178. psychopy/tests/data/TestTarget_w128h64_bottom_left.png +0 -0
  2179. psychopy/tests/data/TestTarget_w128h64_bottom_right.png +0 -0
  2180. psychopy/tests/data/TestTarget_w128h64_center_center.png +0 -0
  2181. psychopy/tests/data/TestTarget_w128h64_top_left.png +0 -0
  2182. psychopy/tests/data/TestTarget_w128h64_top_right.png +0 -0
  2183. psychopy/tests/data/TestTarget_w64h128_bottom_left.png +0 -0
  2184. psychopy/tests/data/TestTarget_w64h128_bottom_right.png +0 -0
  2185. psychopy/tests/data/TestTarget_w64h128_center_center.png +0 -0
  2186. psychopy/tests/data/TestTarget_w64h128_top_left.png +0 -0
  2187. psychopy/tests/data/TestTarget_w64h128_top_right.png +0 -0
  2188. psychopy/tests/data/TestTarget_w64h64_bottom_left.png +0 -0
  2189. psychopy/tests/data/TestTarget_w64h64_bottom_right.png +0 -0
  2190. psychopy/tests/data/TestTarget_w64h64_center_center.png +0 -0
  2191. psychopy/tests/data/TestTarget_w64h64_top_left.png +0 -0
  2192. psychopy/tests/data/TestTarget_w64h64_top_right.png +0 -0
  2193. psychopy/tests/data/TestTextbox_testLetterSpacing_0p6.png +0 -0
  2194. psychopy/tests/data/TestTextbox_testLetterSpacing_0p8.png +0 -0
  2195. psychopy/tests/data/TestTextbox_testLetterSpacing_1.png +0 -0
  2196. psychopy/tests/data/TestTextbox_testLetterSpacing_1p2.png +0 -0
  2197. psychopy/tests/data/TestTextbox_testLetterSpacing_1p4.png +0 -0
  2198. psychopy/tests/data/TestTextbox_testLetterSpacing_1p6.png +0 -0
  2199. psychopy/tests/data/TestTextbox_testLetterSpacing_1p8.png +0 -0
  2200. psychopy/tests/data/TestTextbox_testLetterSpacing_2p0.png +0 -0
  2201. psychopy/tests/data/TestTextbox_testLetterSpacing_None.png +0 -0
  2202. psychopy/tests/data/TestUnknownPluginComponent_load_resave.psyexp +135 -0
  2203. psychopy/tests/data/Test_textbox/test_ori_0_bottom right.png +0 -0
  2204. psychopy/tests/data/Test_textbox/test_ori_0_center.png +0 -0
  2205. psychopy/tests/data/Test_textbox/test_ori_0_top left.png +0 -0
  2206. psychopy/tests/data/Test_textbox/test_ori_120_bottom right.png +0 -0
  2207. psychopy/tests/data/Test_textbox/test_ori_120_center.png +0 -0
  2208. psychopy/tests/data/Test_textbox/test_ori_120_top left.png +0 -0
  2209. psychopy/tests/data/Test_textbox/test_ori_180_bottom right.png +0 -0
  2210. psychopy/tests/data/Test_textbox/test_ori_180_center.png +0 -0
  2211. psychopy/tests/data/Test_textbox/test_ori_180_top left.png +0 -0
  2212. psychopy/tests/data/Test_textbox/test_ori_240_bottom right.png +0 -0
  2213. psychopy/tests/data/Test_textbox/test_ori_240_center.png +0 -0
  2214. psychopy/tests/data/Test_textbox/test_ori_240_top left.png +0 -0
  2215. psychopy/tests/data/Test_textbox_testSpeechpoint_-3ovr8_0ovr8.png +0 -0
  2216. psychopy/tests/data/Test_textbox_testSpeechpoint_0ovr8_-3ovr8.png +0 -0
  2217. psychopy/tests/data/Test_textbox_testSpeechpoint_0ovr8_3ovr8.png +0 -0
  2218. psychopy/tests/data/Test_textbox_testSpeechpoint_3ovr8_0ovr8.png +0 -0
  2219. psychopy/tests/data/Test_textbox_w128h128_bottom_left.png +0 -0
  2220. psychopy/tests/data/Test_textbox_w128h128_bottom_right.png +0 -0
  2221. psychopy/tests/data/Test_textbox_w128h128_center_center.png +0 -0
  2222. psychopy/tests/data/Test_textbox_w128h128_top_left.png +0 -0
  2223. psychopy/tests/data/Test_textbox_w128h128_top_right.png +0 -0
  2224. psychopy/tests/data/Test_textbox_w128h64_bottom_left.png +0 -0
  2225. psychopy/tests/data/Test_textbox_w128h64_bottom_right.png +0 -0
  2226. psychopy/tests/data/Test_textbox_w128h64_center_center.png +0 -0
  2227. psychopy/tests/data/Test_textbox_w128h64_top_left.png +0 -0
  2228. psychopy/tests/data/Test_textbox_w128h64_top_right.png +0 -0
  2229. psychopy/tests/data/Test_textbox_w64h128_bottom_left.png +0 -0
  2230. psychopy/tests/data/Test_textbox_w64h128_bottom_right.png +0 -0
  2231. psychopy/tests/data/Test_textbox_w64h128_center_center.png +0 -0
  2232. psychopy/tests/data/Test_textbox_w64h128_top_left.png +0 -0
  2233. psychopy/tests/data/Test_textbox_w64h128_top_right.png +0 -0
  2234. psychopy/tests/data/Test_textbox_w64h64_bottom_left.png +0 -0
  2235. psychopy/tests/data/Test_textbox_w64h64_bottom_right.png +0 -0
  2236. psychopy/tests/data/Test_textbox_w64h64_center_center.png +0 -0
  2237. psychopy/tests/data/Test_textbox_w64h64_top_left.png +0 -0
  2238. psychopy/tests/data/Test_textbox_w64h64_top_right.png +0 -0
  2239. psychopy/tests/data/Test_uax14_textbox_w128h128_bottom_left.png +0 -0
  2240. psychopy/tests/data/Test_uax14_textbox_w128h128_bottom_right.png +0 -0
  2241. psychopy/tests/data/Test_uax14_textbox_w128h128_center_center.png +0 -0
  2242. psychopy/tests/data/Test_uax14_textbox_w128h128_top_left.png +0 -0
  2243. psychopy/tests/data/Test_uax14_textbox_w128h128_top_right.png +0 -0
  2244. psychopy/tests/data/Test_uax14_textbox_w128h64_bottom_left.png +0 -0
  2245. psychopy/tests/data/Test_uax14_textbox_w128h64_bottom_right.png +0 -0
  2246. psychopy/tests/data/Test_uax14_textbox_w128h64_center_center.png +0 -0
  2247. psychopy/tests/data/Test_uax14_textbox_w128h64_top_left.png +0 -0
  2248. psychopy/tests/data/Test_uax14_textbox_w128h64_top_right.png +0 -0
  2249. psychopy/tests/data/Test_uax14_textbox_w64h128_bottom_left.png +0 -0
  2250. psychopy/tests/data/Test_uax14_textbox_w64h128_bottom_right.png +0 -0
  2251. psychopy/tests/data/Test_uax14_textbox_w64h128_center_center.png +0 -0
  2252. psychopy/tests/data/Test_uax14_textbox_w64h128_top_left.png +0 -0
  2253. psychopy/tests/data/Test_uax14_textbox_w64h128_top_right.png +0 -0
  2254. psychopy/tests/data/Test_uax14_textbox_w64h64_bottom_left.png +0 -0
  2255. psychopy/tests/data/Test_uax14_textbox_w64h64_bottom_right.png +0 -0
  2256. psychopy/tests/data/Test_uax14_textbox_w64h64_center_center.png +0 -0
  2257. psychopy/tests/data/Test_uax14_textbox_w64h64_top_left.png +0 -0
  2258. psychopy/tests/data/Test_uax14_textbox_w64h64_top_right.png +0 -0
  2259. psychopy/tests/data/TextComponent_disabled.psyexp +63 -0
  2260. psychopy/tests/data/TextComponent_not_disabled.psyexp +63 -0
  2261. psychopy/tests/data/aperture1_deg.png +0 -0
  2262. psychopy/tests/data/aperture1_degFlat.png +0 -0
  2263. psychopy/tests/data/aperture1_degFlatPos.png +0 -0
  2264. psychopy/tests/data/aperture1_norm.png +0 -0
  2265. psychopy/tests/data/aperture1_normHexbackground.png +0 -0
  2266. psychopy/tests/data/aperture1_normNoShade.png +0 -0
  2267. psychopy/tests/data/aperture1_pix.png +0 -0
  2268. psychopy/tests/data/aperture1_stencil.png +0 -0
  2269. psychopy/tests/data/aperture2_deg.png +0 -0
  2270. psychopy/tests/data/aperture2_degFlat.png +0 -0
  2271. psychopy/tests/data/aperture2_degFlatPos.png +0 -0
  2272. psychopy/tests/data/aperture2_norm.png +0 -0
  2273. psychopy/tests/data/aperture2_normHexbackground.png +0 -0
  2274. psychopy/tests/data/aperture2_normNoShade.png +0 -0
  2275. psychopy/tests/data/aperture2_pix.png +0 -0
  2276. psychopy/tests/data/aperture2_stencil.png +0 -0
  2277. psychopy/tests/data/beatandrcos_cm.png +0 -0
  2278. psychopy/tests/data/beatandrcos_deg.png +0 -0
  2279. psychopy/tests/data/beatandrcos_degFlat.png +0 -0
  2280. psychopy/tests/data/beatandrcos_degFlatPos.png +0 -0
  2281. psychopy/tests/data/beatandrcos_height.png +0 -0
  2282. psychopy/tests/data/beatandrcos_norm.png +0 -0
  2283. psychopy/tests/data/beatandrcos_normAddBlend.png +0 -0
  2284. psychopy/tests/data/beatandrcos_normHexbackground.png +0 -0
  2285. psychopy/tests/data/beatandrcos_pix.png +0 -0
  2286. psychopy/tests/data/beatandrcos_stencil.png +0 -0
  2287. psychopy/tests/data/blend_add_cm.png +0 -0
  2288. psychopy/tests/data/blend_add_deg.png +0 -0
  2289. psychopy/tests/data/blend_add_degFlat.png +0 -0
  2290. psychopy/tests/data/blend_add_degFlatPos.png +0 -0
  2291. psychopy/tests/data/blend_add_height.png +0 -0
  2292. psychopy/tests/data/blend_add_norm.png +0 -0
  2293. psychopy/tests/data/blend_add_normAddBlend.png +0 -0
  2294. psychopy/tests/data/blend_add_normHexbackground.png +0 -0
  2295. psychopy/tests/data/blend_add_normNoShade.png +0 -0
  2296. psychopy/tests/data/blend_add_pix.png +0 -0
  2297. psychopy/tests/data/blend_add_stencil.png +0 -0
  2298. psychopy/tests/data/broken2020_2_5_resources/broken_resources.psyexp +84 -0
  2299. psychopy/tests/data/broken2020_2_5_resources/psychopy72.png +0 -0
  2300. psychopy/tests/data/bufferimg_gabor_cm.png +0 -0
  2301. psychopy/tests/data/bufferimg_gabor_deg.png +0 -0
  2302. psychopy/tests/data/bufferimg_gabor_degFlat.png +0 -0
  2303. psychopy/tests/data/bufferimg_gabor_degFlatPos.png +0 -0
  2304. psychopy/tests/data/bufferimg_gabor_height.png +0 -0
  2305. psychopy/tests/data/bufferimg_gabor_norm.png +0 -0
  2306. psychopy/tests/data/bufferimg_gabor_normAddBlend.png +0 -0
  2307. psychopy/tests/data/bufferimg_gabor_normHexbackground.png +0 -0
  2308. psychopy/tests/data/bufferimg_gabor_normNoShade.png +0 -0
  2309. psychopy/tests/data/bufferimg_gabor_pix.png +0 -0
  2310. psychopy/tests/data/bufferimg_gabor_stencil.png +0 -0
  2311. psychopy/tests/data/circleHex_cm.png +0 -0
  2312. psychopy/tests/data/circleHex_deg.png +0 -0
  2313. psychopy/tests/data/circleHex_degFlat.png +0 -0
  2314. psychopy/tests/data/circleHex_degFlatPos.png +0 -0
  2315. psychopy/tests/data/circleHex_height.png +0 -0
  2316. psychopy/tests/data/circleHex_norm.png +0 -0
  2317. psychopy/tests/data/circleHex_normAddBlend.png +0 -0
  2318. psychopy/tests/data/circleHex_normHexbackground.png +0 -0
  2319. psychopy/tests/data/circleHex_normNoShade.png +0 -0
  2320. psychopy/tests/data/circleHex_pix.png +0 -0
  2321. psychopy/tests/data/circleHex_stencil.png +0 -0
  2322. psychopy/tests/data/corrFullRandom.csv +16 -0
  2323. psychopy/tests/data/corrFullRandom.tsv +6 -0
  2324. psychopy/tests/data/corrFullRandomTH2.csv +16 -0
  2325. psychopy/tests/data/corrMultiKeyExpWide.csv +3 -0
  2326. psychopy/tests/data/corrMultiKeyTrials.csv +8 -0
  2327. psychopy/tests/data/corrMultiKeyTrials.xlsx +0 -0
  2328. psychopy/tests/data/corrRandom.csv +16 -0
  2329. psychopy/tests/data/corrRandom.tsv +6 -0
  2330. psychopy/tests/data/corrRandomTH2.csv +16 -0
  2331. psychopy/tests/data/corrXlsx.xlsx +0 -0
  2332. psychopy/tests/data/correctScript/js/correctCodeComponent.js +181 -0
  2333. psychopy/tests/data/correctScript/js/correctImageComponent.js +204 -0
  2334. psychopy/tests/data/correctScript/js/correctKeyboardComponent.js +225 -0
  2335. psychopy/tests/data/correctScript/js/correctMouseComponent.js +221 -0
  2336. psychopy/tests/data/correctScript/js/correctMovieComponent.js +210 -0
  2337. psychopy/tests/data/correctScript/js/correctPolygonComponent.js +205 -0
  2338. psychopy/tests/data/correctScript/js/correctSliderComponent.js +209 -0
  2339. psychopy/tests/data/correctScript/js/correctSoundComponent.js +205 -0
  2340. psychopy/tests/data/correctScript/js/correctTextComponent.js +207 -0
  2341. psychopy/tests/data/correctScript/python/correctApertureComponent.py +157 -0
  2342. psychopy/tests/data/correctScript/python/correctCodeComponent.py +135 -0
  2343. psychopy/tests/data/correctScript/python/correctDotsComponent.py +161 -0
  2344. psychopy/tests/data/correctScript/python/correctEnvGratingComponent.py +167 -0
  2345. psychopy/tests/data/correctScript/python/correctFormComponent.py +150 -0
  2346. psychopy/tests/data/correctScript/python/correctGratingComponent.py +158 -0
  2347. psychopy/tests/data/correctScript/python/correctImageComponent.py +160 -0
  2348. psychopy/tests/data/correctScript/python/correctJoyButtonsComponent.py +204 -0
  2349. psychopy/tests/data/correctScript/python/correctJoystickComponent.py +214 -0
  2350. psychopy/tests/data/correctScript/python/correctKeyboardComponent.py +169 -0
  2351. psychopy/tests/data/correctScript/python/correctMicrophoneComponent.py +163 -0
  2352. psychopy/tests/data/correctScript/python/correctMouseComponent.py +174 -0
  2353. psychopy/tests/data/correctScript/python/correctMovieComponent.py +160 -0
  2354. psychopy/tests/data/correctScript/python/correctNoiseStimComponent.py +169 -0
  2355. psychopy/tests/data/correctScript/python/correctParallelOutComponent.py +156 -0
  2356. psychopy/tests/data/correctScript/python/correctPatchComponent.py +159 -0
  2357. psychopy/tests/data/correctScript/python/correctPolygonComponent.py +159 -0
  2358. psychopy/tests/data/correctScript/python/correctQmixPumpComponent.py +174 -0
  2359. psychopy/tests/data/correctScript/python/correctRatingScaleComponent.py +152 -0
  2360. psychopy/tests/data/correctScript/python/correctSliderComponent.py +159 -0
  2361. psychopy/tests/data/correctScript/python/correctSoundComponent.py +157 -0
  2362. psychopy/tests/data/correctScript/python/correctStaticComponent.py +176 -0
  2363. psychopy/tests/data/correctScript/python/correctTextComponent.py +159 -0
  2364. psychopy/tests/data/correctScript/python/correctVariableComponent.py +139 -0
  2365. psychopy/tests/data/correctScript/python/correctcedrusButtonBoxComponent.py +199 -0
  2366. psychopy/tests/data/correctScript/python/correctioLabsButtonBoxComponent.py +187 -0
  2367. psychopy/tests/data/dataTest.xlsx +0 -0
  2368. psychopy/tests/data/dots_cm.png +0 -0
  2369. psychopy/tests/data/dots_deg.png +0 -0
  2370. psychopy/tests/data/dots_degFlat.png +0 -0
  2371. psychopy/tests/data/dots_degFlatPos.png +0 -0
  2372. psychopy/tests/data/dots_height.png +0 -0
  2373. psychopy/tests/data/dots_norm.png +0 -0
  2374. psychopy/tests/data/dots_normAddBlend.png +0 -0
  2375. psychopy/tests/data/dots_normHexbackground.png +0 -0
  2376. psychopy/tests/data/dots_normNoShade.png +0 -0
  2377. psychopy/tests/data/dots_pix.png +0 -0
  2378. psychopy/tests/data/dots_stencil.png +0 -0
  2379. psychopy/tests/data/duplicateHeaders.csv +2 -0
  2380. psychopy/tests/data/elarray1_cm.png +0 -0
  2381. psychopy/tests/data/elarray1_deg.png +0 -0
  2382. psychopy/tests/data/elarray1_degFlat.png +0 -0
  2383. psychopy/tests/data/elarray1_degFlatPos.png +0 -0
  2384. psychopy/tests/data/elarray1_height.png +0 -0
  2385. psychopy/tests/data/elarray1_norm.png +0 -0
  2386. psychopy/tests/data/elarray1_normAddBlend.png +0 -0
  2387. psychopy/tests/data/elarray1_normHexbackground.png +0 -0
  2388. psychopy/tests/data/elarray1_pix.png +0 -0
  2389. psychopy/tests/data/elarray1_stencil.png +0 -0
  2390. psychopy/tests/data/envelopeandrcos_cm.png +0 -0
  2391. psychopy/tests/data/envelopeandrcos_deg.png +0 -0
  2392. psychopy/tests/data/envelopeandrcos_degFlat.png +0 -0
  2393. psychopy/tests/data/envelopeandrcos_degFlatPos.png +0 -0
  2394. psychopy/tests/data/envelopeandrcos_height.png +0 -0
  2395. psychopy/tests/data/envelopeandrcos_norm.png +0 -0
  2396. psychopy/tests/data/envelopeandrcos_normAddBlend.png +0 -0
  2397. psychopy/tests/data/envelopeandrcos_normHexbackground.png +0 -0
  2398. psychopy/tests/data/envelopeandrcos_pix.png +0 -0
  2399. psychopy/tests/data/envelopeandrcos_stencil.png +0 -0
  2400. psychopy/tests/data/envelopepowerandrcos_cm.png +0 -0
  2401. psychopy/tests/data/envelopepowerandrcos_deg.png +0 -0
  2402. psychopy/tests/data/envelopepowerandrcos_degFlat.png +0 -0
  2403. psychopy/tests/data/envelopepowerandrcos_degFlatPos.png +0 -0
  2404. psychopy/tests/data/envelopepowerandrcos_height.png +0 -0
  2405. psychopy/tests/data/envelopepowerandrcos_norm.png +0 -0
  2406. psychopy/tests/data/envelopepowerandrcos_normAddBlend.png +0 -0
  2407. psychopy/tests/data/envelopepowerandrcos_normHexbackground.png +0 -0
  2408. psychopy/tests/data/envelopepowerandrcos_pix.png +0 -0
  2409. psychopy/tests/data/envelopepowerandrcos_stencil.png +0 -0
  2410. psychopy/tests/data/filltext.png +0 -0
  2411. psychopy/tests/data/form_font_demographics.png +0 -0
  2412. psychopy/tests/data/form_font_demographics.xlsx +0 -0
  2413. psychopy/tests/data/form_font_languages.png +0 -0
  2414. psychopy/tests/data/form_font_languages.xlsx +0 -0
  2415. psychopy/tests/data/form_font_nonstandard.png +0 -0
  2416. psychopy/tests/data/futureParams.psyexp +150 -0
  2417. psychopy/tests/data/gabor1_cm.png +0 -0
  2418. psychopy/tests/data/gabor1_deg.png +0 -0
  2419. psychopy/tests/data/gabor1_degFlat.png +0 -0
  2420. psychopy/tests/data/gabor1_degFlatPos.png +0 -0
  2421. psychopy/tests/data/gabor1_height.png +0 -0
  2422. psychopy/tests/data/gabor1_norm.png +0 -0
  2423. psychopy/tests/data/gabor1_normAddBlend.png +0 -0
  2424. psychopy/tests/data/gabor1_normHexbackground.png +0 -0
  2425. psychopy/tests/data/gabor1_normNoShade.png +0 -0
  2426. psychopy/tests/data/gabor1_pix.png +0 -0
  2427. psychopy/tests/data/gabor1_stencil.png +0 -0
  2428. psychopy/tests/data/gabor2_cm.png +0 -0
  2429. psychopy/tests/data/gabor2_deg.png +0 -0
  2430. psychopy/tests/data/gabor2_degFlat.png +0 -0
  2431. psychopy/tests/data/gabor2_degFlatPos.png +0 -0
  2432. psychopy/tests/data/gabor2_height.png +0 -0
  2433. psychopy/tests/data/gabor2_norm.png +0 -0
  2434. psychopy/tests/data/gabor2_normAddBlend.png +0 -0
  2435. psychopy/tests/data/gabor2_normHexbackground.png +0 -0
  2436. psychopy/tests/data/gabor2_normNoShade.png +0 -0
  2437. psychopy/tests/data/gabor2_pix.png +0 -0
  2438. psychopy/tests/data/gabor2_stencil.png +0 -0
  2439. psychopy/tests/data/ghost_stroop.psyexp +131 -0
  2440. psychopy/tests/data/ghost_trialTypes.xlsx +0 -0
  2441. psychopy/tests/data/green_48000.flac.dist +0 -0
  2442. psychopy/tests/data/greyscale.jpg +0 -0
  2443. psychopy/tests/data/greyscale2.png +0 -0
  2444. psychopy/tests/data/greyscale2_cm.png +0 -0
  2445. psychopy/tests/data/greyscale2_deg.png +0 -0
  2446. psychopy/tests/data/greyscale2_degFlat.png +0 -0
  2447. psychopy/tests/data/greyscale2_degFlatPos.png +0 -0
  2448. psychopy/tests/data/greyscale2_height.png +0 -0
  2449. psychopy/tests/data/greyscale2_norm.png +0 -0
  2450. psychopy/tests/data/greyscale2_normAddBlend.png +0 -0
  2451. psychopy/tests/data/greyscale2_normHexbackground.png +0 -0
  2452. psychopy/tests/data/greyscale2_normNoShade.png +0 -0
  2453. psychopy/tests/data/greyscale2_pix.png +0 -0
  2454. psychopy/tests/data/greyscale2_stencil.png +0 -0
  2455. psychopy/tests/data/greyscaleLowContr_cm.png +0 -0
  2456. psychopy/tests/data/greyscaleLowContr_deg.png +0 -0
  2457. psychopy/tests/data/greyscaleLowContr_degFlat.png +0 -0
  2458. psychopy/tests/data/greyscaleLowContr_degFlatPos.png +0 -0
  2459. psychopy/tests/data/greyscaleLowContr_height.png +0 -0
  2460. psychopy/tests/data/greyscaleLowContr_norm.png +0 -0
  2461. psychopy/tests/data/greyscaleLowContr_normAddBlend.png +0 -0
  2462. psychopy/tests/data/greyscaleLowContr_normHexbackground.png +0 -0
  2463. psychopy/tests/data/greyscaleLowContr_normNoShade.png +0 -0
  2464. psychopy/tests/data/greyscaleLowContr_pix.png +0 -0
  2465. psychopy/tests/data/greyscaleLowContr_stencil.png +0 -0
  2466. psychopy/tests/data/greyscale_cm.png +0 -0
  2467. psychopy/tests/data/greyscale_deg.png +0 -0
  2468. psychopy/tests/data/greyscale_degFlat.png +0 -0
  2469. psychopy/tests/data/greyscale_degFlatPos.png +0 -0
  2470. psychopy/tests/data/greyscale_height.png +0 -0
  2471. psychopy/tests/data/greyscale_norm.png +0 -0
  2472. psychopy/tests/data/greyscale_normAddBlend.png +0 -0
  2473. psychopy/tests/data/greyscale_normHexbackground.png +0 -0
  2474. psychopy/tests/data/greyscale_normNoShade.png +0 -0
  2475. psychopy/tests/data/greyscale_pix.png +0 -0
  2476. psychopy/tests/data/greyscale_stencil.png +0 -0
  2477. psychopy/tests/data/imageAndGauss_cm.png +0 -0
  2478. psychopy/tests/data/imageAndGauss_deg.png +0 -0
  2479. psychopy/tests/data/imageAndGauss_degFlat.png +0 -0
  2480. psychopy/tests/data/imageAndGauss_degFlatPos.png +0 -0
  2481. psychopy/tests/data/imageAndGauss_height.png +0 -0
  2482. psychopy/tests/data/imageAndGauss_norm.png +0 -0
  2483. psychopy/tests/data/imageAndGauss_normAddBlend.png +0 -0
  2484. psychopy/tests/data/imageAndGauss_normHexbackground.png +0 -0
  2485. psychopy/tests/data/imageAndGauss_normNoShade.png +0 -0
  2486. psychopy/tests/data/imageAndGauss_pix.png +0 -0
  2487. psychopy/tests/data/imageAndGauss_stencil.png +0 -0
  2488. psychopy/tests/data/movFrame1_cm.png +0 -0
  2489. psychopy/tests/data/movFrame1_deg.png +0 -0
  2490. psychopy/tests/data/movFrame1_degFlat.png +0 -0
  2491. psychopy/tests/data/movFrame1_degFlatPos.png +0 -0
  2492. psychopy/tests/data/movFrame1_height.png +0 -0
  2493. psychopy/tests/data/movFrame1_norm.png +0 -0
  2494. psychopy/tests/data/movFrame1_normAddBlend.png +0 -0
  2495. psychopy/tests/data/movFrame1_normHexbackground.png +0 -0
  2496. psychopy/tests/data/movFrame1_normNoShade.png +0 -0
  2497. psychopy/tests/data/movFrame1_pix.png +0 -0
  2498. psychopy/tests/data/movFrame1_stencil.png +0 -0
  2499. psychopy/tests/data/multiKeypressExperiment.psydat +357 -0
  2500. psychopy/tests/data/multiKeypressTrialhandler.psydat +252 -0
  2501. psychopy/tests/data/multiStairConds.xlsx +0 -0
  2502. psychopy/tests/data/multiStairQuestPlus.xlsx +0 -0
  2503. psychopy/tests/data/newstyle.psydat +6155 -0
  2504. psychopy/tests/data/noiseAndRcos_cm.png +0 -0
  2505. psychopy/tests/data/noiseAndRcos_deg.png +0 -0
  2506. psychopy/tests/data/noiseAndRcos_degFlat.png +0 -0
  2507. psychopy/tests/data/noiseAndRcos_degFlatPos.png +0 -0
  2508. psychopy/tests/data/noiseAndRcos_height.png +0 -0
  2509. psychopy/tests/data/noiseAndRcos_norm.png +0 -0
  2510. psychopy/tests/data/noiseAndRcos_normAddBlend.png +0 -0
  2511. psychopy/tests/data/noiseAndRcos_normHexbackground.png +0 -0
  2512. psychopy/tests/data/noiseAndRcos_normNoShade.png +0 -0
  2513. psychopy/tests/data/noiseAndRcos_pix.png +0 -0
  2514. psychopy/tests/data/noiseAndRcos_stencil.png +0 -0
  2515. psychopy/tests/data/noiseFiltersAndRcos_cm.png +0 -0
  2516. psychopy/tests/data/noiseFiltersAndRcos_deg.png +0 -0
  2517. psychopy/tests/data/noiseFiltersAndRcos_degFlat.png +0 -0
  2518. psychopy/tests/data/noiseFiltersAndRcos_degFlatPos.png +0 -0
  2519. psychopy/tests/data/noiseFiltersAndRcos_height.png +0 -0
  2520. psychopy/tests/data/noiseFiltersAndRcos_norm.png +0 -0
  2521. psychopy/tests/data/noiseFiltersAndRcos_normAddBlend.png +0 -0
  2522. psychopy/tests/data/noiseFiltersAndRcos_normHexbackground.png +0 -0
  2523. psychopy/tests/data/noiseFiltersAndRcos_normNoShade.png +0 -0
  2524. psychopy/tests/data/noiseFiltersAndRcos_pix.png +0 -0
  2525. psychopy/tests/data/noiseFiltersAndRcos_stencil.png +0 -0
  2526. psychopy/tests/data/numpyImage_cm.png +0 -0
  2527. psychopy/tests/data/numpyImage_deg.png +0 -0
  2528. psychopy/tests/data/numpyImage_degFlat.png +0 -0
  2529. psychopy/tests/data/numpyImage_degFlatPos.png +0 -0
  2530. psychopy/tests/data/numpyImage_height.png +0 -0
  2531. psychopy/tests/data/numpyImage_norm.png +0 -0
  2532. psychopy/tests/data/numpyImage_normAddBlend.png +0 -0
  2533. psychopy/tests/data/numpyImage_normHexbackground.png +0 -0
  2534. psychopy/tests/data/numpyImage_normNoShade.png +0 -0
  2535. psychopy/tests/data/numpyImage_pix.png +0 -0
  2536. psychopy/tests/data/numpyImage_stencil.png +0 -0
  2537. psychopy/tests/data/numpyLowContr_cm.png +0 -0
  2538. psychopy/tests/data/numpyLowContr_deg.png +0 -0
  2539. psychopy/tests/data/numpyLowContr_degFlat.png +0 -0
  2540. psychopy/tests/data/numpyLowContr_degFlatPos.png +0 -0
  2541. psychopy/tests/data/numpyLowContr_height.png +0 -0
  2542. psychopy/tests/data/numpyLowContr_norm.png +0 -0
  2543. psychopy/tests/data/numpyLowContr_normAddBlend.png +0 -0
  2544. psychopy/tests/data/numpyLowContr_normHexbackground.png +0 -0
  2545. psychopy/tests/data/numpyLowContr_normNoShade.png +0 -0
  2546. psychopy/tests/data/numpyLowContr_pix.png +0 -0
  2547. psychopy/tests/data/numpyLowContr_stencil.png +0 -0
  2548. psychopy/tests/data/oldstyle.psydat +1534 -0
  2549. psychopy/tests/data/oldstyle_stair.psydat +263 -0
  2550. psychopy/tests/data/ratingscale1_cm.png +0 -0
  2551. psychopy/tests/data/ratingscale1_deg.png +0 -0
  2552. psychopy/tests/data/ratingscale1_degFlat.png +0 -0
  2553. psychopy/tests/data/ratingscale1_degFlatPos.png +0 -0
  2554. psychopy/tests/data/ratingscale1_height.png +0 -0
  2555. psychopy/tests/data/ratingscale1_norm.png +0 -0
  2556. psychopy/tests/data/ratingscale1_normAddBlend.png +0 -0
  2557. psychopy/tests/data/ratingscale1_normHexbackground.png +0 -0
  2558. psychopy/tests/data/ratingscale1_normNoShade.png +0 -0
  2559. psychopy/tests/data/ratingscale1_pix.png +0 -0
  2560. psychopy/tests/data/ratingscale1_stencil.png +0 -0
  2561. psychopy/tests/data/red_16000.flac.dist +0 -0
  2562. psychopy/tests/data/retroListParam.psyexp +82 -0
  2563. psychopy/tests/data/right_to_left_unidcode.xlsx +0 -0
  2564. psychopy/tests/data/sample.meshwarp.data +11522 -0
  2565. psychopy/tests/data/shape2_1_cm.png +0 -0
  2566. psychopy/tests/data/shape2_1_deg.png +0 -0
  2567. psychopy/tests/data/shape2_1_degFlat.png +0 -0
  2568. psychopy/tests/data/shape2_1_degFlatPos.png +0 -0
  2569. psychopy/tests/data/shape2_1_height.png +0 -0
  2570. psychopy/tests/data/shape2_1_norm.png +0 -0
  2571. psychopy/tests/data/shape2_1_normAddBlend.png +0 -0
  2572. psychopy/tests/data/shape2_1_normHexbackground.png +0 -0
  2573. psychopy/tests/data/shape2_1_normNoShade.png +0 -0
  2574. psychopy/tests/data/shape2_1_pix.png +0 -0
  2575. psychopy/tests/data/shape2_1_stencil.png +0 -0
  2576. psychopy/tests/data/shape2_2_cm.png +0 -0
  2577. psychopy/tests/data/shape2_2_deg.png +0 -0
  2578. psychopy/tests/data/shape2_2_degFlat.png +0 -0
  2579. psychopy/tests/data/shape2_2_degFlatPos.png +0 -0
  2580. psychopy/tests/data/shape2_2_height.png +0 -0
  2581. psychopy/tests/data/shape2_2_norm.png +0 -0
  2582. psychopy/tests/data/shape2_2_normAddBlend.png +0 -0
  2583. psychopy/tests/data/shape2_2_normHexbackground.png +0 -0
  2584. psychopy/tests/data/shape2_2_normNoShade.png +0 -0
  2585. psychopy/tests/data/shape2_2_pix.png +0 -0
  2586. psychopy/tests/data/shape2_2_stencil.png +0 -0
  2587. psychopy/tests/data/simpleimage1_cm.png +0 -0
  2588. psychopy/tests/data/simpleimage1_deg.png +0 -0
  2589. psychopy/tests/data/simpleimage1_degFlat.png +0 -0
  2590. psychopy/tests/data/simpleimage1_degFlatPos.png +0 -0
  2591. psychopy/tests/data/simpleimage1_height.png +0 -0
  2592. psychopy/tests/data/simpleimage1_norm.png +0 -0
  2593. psychopy/tests/data/simpleimage1_normAddBlend.png +0 -0
  2594. psychopy/tests/data/simpleimage1_normHexbackground.png +0 -0
  2595. psychopy/tests/data/simpleimage1_normNoShade.png +0 -0
  2596. psychopy/tests/data/simpleimage1_pix.png +0 -0
  2597. psychopy/tests/data/simpleimage1_stencil.png +0 -0
  2598. psychopy/tests/data/test001EntryImporting.psyexp +66 -0
  2599. psychopy/tests/data/testMovie.mp4 +0 -0
  2600. psychopy/tests/data/test_basic_run.py +1 -0
  2601. psychopy/tests/data/test_circle_radius_.1height.png +0 -0
  2602. psychopy/tests/data/test_circle_radius_.2height.png +0 -0
  2603. psychopy/tests/data/test_circle_radius_10pix.png +0 -0
  2604. psychopy/tests/data/test_circle_radius_20pix.png +0 -0
  2605. psychopy/tests/data/test_components/testClearKeyboard/testClearKeyboard.psyexp +200 -0
  2606. psychopy/tests/data/test_form_combinations_choice_bigItem.png +0 -0
  2607. psychopy/tests/data/test_form_combinations_choice_bigItemOverflow.png +0 -0
  2608. psychopy/tests/data/test_form_combinations_choice_bigResp.png +0 -0
  2609. psychopy/tests/data/test_form_combinations_choice_bigRespOverflow.png +0 -0
  2610. psychopy/tests/data/test_form_combinations_description_bigItem.png +0 -0
  2611. psychopy/tests/data/test_form_combinations_description_bigItemOverflow.png +0 -0
  2612. psychopy/tests/data/test_form_combinations_description_bigResp.png +0 -0
  2613. psychopy/tests/data/test_form_combinations_description_bigRespOverflow.png +0 -0
  2614. psychopy/tests/data/test_form_combinations_free text_bigItem.png +0 -0
  2615. psychopy/tests/data/test_form_combinations_free text_bigItemOverflow.png +0 -0
  2616. psychopy/tests/data/test_form_combinations_free text_bigResp.png +0 -0
  2617. psychopy/tests/data/test_form_combinations_free text_bigRespOverflow.png +0 -0
  2618. psychopy/tests/data/test_form_combinations_heading_bigItem.png +0 -0
  2619. psychopy/tests/data/test_form_combinations_heading_bigItemOverflow.png +0 -0
  2620. psychopy/tests/data/test_form_combinations_heading_bigResp.png +0 -0
  2621. psychopy/tests/data/test_form_combinations_heading_bigRespOverflow.png +0 -0
  2622. psychopy/tests/data/test_form_combinations_radio_bigItem.png +0 -0
  2623. psychopy/tests/data/test_form_combinations_radio_bigItemOverflow.png +0 -0
  2624. psychopy/tests/data/test_form_combinations_radio_bigResp.png +0 -0
  2625. psychopy/tests/data/test_form_combinations_radio_bigRespOverflow.png +0 -0
  2626. psychopy/tests/data/test_form_combinations_rating_bigItem.png +0 -0
  2627. psychopy/tests/data/test_form_combinations_rating_bigItemOverflow.png +0 -0
  2628. psychopy/tests/data/test_form_combinations_rating_bigResp.png +0 -0
  2629. psychopy/tests/data/test_form_combinations_rating_bigRespOverflow.png +0 -0
  2630. psychopy/tests/data/test_form_combinations_slider_bigItem.png +0 -0
  2631. psychopy/tests/data/test_form_combinations_slider_bigItemOverflow.png +0 -0
  2632. psychopy/tests/data/test_form_combinations_slider_bigResp.png +0 -0
  2633. psychopy/tests/data/test_form_combinations_slider_bigRespOverflow.png +0 -0
  2634. psychopy/tests/data/test_get_resources/blue.png +0 -0
  2635. psychopy/tests/data/test_get_resources/groupA.csv +3 -0
  2636. psychopy/tests/data/test_get_resources/groupB.csv +3 -0
  2637. psychopy/tests/data/test_get_resources/groups.csv +3 -0
  2638. psychopy/tests/data/test_get_resources/handledbyrm_constrloop.psyexp +143 -0
  2639. psychopy/tests/data/test_get_resources/handledbyrm_noloop.psyexp +114 -0
  2640. psychopy/tests/data/test_get_resources/handledbyrm_recurloop.psyexp +138 -0
  2641. psychopy/tests/data/test_get_resources/handledbyrm_strloop.psyexp +126 -0
  2642. psychopy/tests/data/test_get_resources/handledbystatic_constrloop.psyexp +141 -0
  2643. psychopy/tests/data/test_get_resources/handledbystatic_noloop.psyexp +112 -0
  2644. psychopy/tests/data/test_get_resources/handledbystatic_recurloop.psyexp +136 -0
  2645. psychopy/tests/data/test_get_resources/handledbystatic_strloop.psyexp +124 -0
  2646. psychopy/tests/data/test_get_resources/unhandled_constrloop.psyexp +128 -0
  2647. psychopy/tests/data/test_get_resources/unhandled_noloop.psyexp +99 -0
  2648. psychopy/tests/data/test_get_resources/unhandled_recurloop.psyexp +123 -0
  2649. psychopy/tests/data/test_get_resources/unhandled_strloop.psyexp +111 -0
  2650. psychopy/tests/data/test_get_resources/white.png +0 -0
  2651. psychopy/tests/data/test_get_resources/yellow.png +0 -0
  2652. psychopy/tests/data/test_image_aspect_default_None.png +0 -0
  2653. psychopy/tests/data/test_image_aspect_default_xFull_yNone.png +0 -0
  2654. psychopy/tests/data/test_image_aspect_default_xNone_yFull.png +0 -0
  2655. psychopy/tests/data/test_image_aspect_default_xNone_yNone.png +0 -0
  2656. psychopy/tests/data/test_image_flip_anchor_horiz.png +0 -0
  2657. psychopy/tests/data/test_image_flip_anchor_vert.png +0 -0
  2658. psychopy/tests/data/test_loaded_namespace/test_counterbalance.psyexp +142 -0
  2659. psychopy/tests/data/test_loaded_namespace/test_custom_missing.psyexp +129 -0
  2660. psychopy/tests/data/test_loaded_namespace/test_missing_counterbalance.psyexp +116 -0
  2661. psychopy/tests/data/test_loaded_namespace/test_mix_exp.psyexp +181 -0
  2662. psychopy/tests/data/test_loaded_namespace/test_mix_missing.psyexp +140 -0
  2663. psychopy/tests/data/test_loaded_namespace/test_mix_name_calibration.psyexp +164 -0
  2664. psychopy/tests/data/test_loops/testLoopsBlocks.psyexp +161 -0
  2665. psychopy/tests/data/test_loops/testStaircase.psyexp +105 -0
  2666. psychopy/tests/data/test_loops/test_current_loop_attr.psyexp +185 -0
  2667. psychopy/tests/data/test_panorama/panoramaTestImage.png +0 -0
  2668. psychopy/tests/data/test_panorama/panoramaTestImage.svg +1 -0
  2669. psychopy/tests/data/test_panorama/testPanorama_mvmt_-0.3_-0.3.png +0 -0
  2670. psychopy/tests/data/test_panorama/testPanorama_mvmt_-0.3_0.3.png +0 -0
  2671. psychopy/tests/data/test_panorama/testPanorama_mvmt_-1.0_-0.3.png +0 -0
  2672. psychopy/tests/data/test_panorama/testPanorama_mvmt_-1.0_0.3.png +0 -0
  2673. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.0_-1.0.png +0 -0
  2674. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.0_1.0.png +0 -0
  2675. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.3_-0.3.png +0 -0
  2676. psychopy/tests/data/test_panorama/testPanorama_mvmt_0.3_0.3.png +0 -0
  2677. psychopy/tests/data/test_resources.psyexp +491 -0
  2678. psychopy/tests/data/test_session/outside_root/externalExp.psyexp +116 -0
  2679. psychopy/tests/data/test_session/root/annotation/annotation.psyexp +161 -0
  2680. psychopy/tests/data/test_session/root/error/error.psyexp +93 -0
  2681. psychopy/tests/data/test_session/root/exp1/exp1.psyexp +133 -0
  2682. psychopy/tests/data/test_session/root/exp2/exp2.psyexp +133 -0
  2683. psychopy/tests/data/test_session/root/frameRate/frameRate.psyexp +114 -0
  2684. psychopy/tests/data/test_session/root/invUseVersion/invUseVersion.psyexp +133 -0
  2685. psychopy/tests/data/test_session/root/testClockFormat/testClockFormat.psyexp +122 -0
  2686. psychopy/tests/data/test_session/root/testCtrls/testCtrls.psyexp +115 -0
  2687. psychopy/tests/data/test_session/root/testEditExpInfo/testEditExpInfo.psyexp +135 -0
  2688. psychopy/tests/data/test_session/root/testFutureTrials/testFutureTrials.psyexp +155 -0
  2689. psychopy/tests/data/test_session/root/testNamedButtonBox/testNamedButtonBox.psyexp +145 -0
  2690. psychopy/tests/data/test_session/root/testTrialNav/trialNav.psyexp +158 -0
  2691. psychopy/tests/data/test_slider_horiz_accute_horiz.png +0 -0
  2692. psychopy/tests/data/test_slider_horiz_accute_vert.png +0 -0
  2693. psychopy/tests/data/test_slider_horiz_horiz.png +0 -0
  2694. psychopy/tests/data/test_slider_horiz_obtuse_horiz.png +0 -0
  2695. psychopy/tests/data/test_slider_horiz_obtuse_vert.png +0 -0
  2696. psychopy/tests/data/test_slider_horiz_vert.png +0 -0
  2697. psychopy/tests/data/test_slider_ticklabelloc_blanks.png +0 -0
  2698. psychopy/tests/data/test_slider_ticklabelloc_clustered.png +0 -0
  2699. psychopy/tests/data/test_slider_ticklabelloc_morelabels.png +0 -0
  2700. psychopy/tests/data/test_slider_ticklabelloc_morelabelsclustered.png +0 -0
  2701. psychopy/tests/data/test_slider_ticklabelloc_moreticks.png +0 -0
  2702. psychopy/tests/data/test_slider_ticklabelloc_moreticksclustered.png +0 -0
  2703. psychopy/tests/data/test_slider_ticklabelloc_nolabels.png +0 -0
  2704. psychopy/tests/data/test_slider_ticklabelloc_noticks.png +0 -0
  2705. psychopy/tests/data/test_slider_ticklabelloc_simple.png +0 -0
  2706. psychopy/tests/data/test_slider_triangle_horiz_False_flip_False.png +0 -0
  2707. psychopy/tests/data/test_slider_triangle_horiz_False_flip_True.png +0 -0
  2708. psychopy/tests/data/test_slider_triangle_horiz_True_flip_False.png +0 -0
  2709. psychopy/tests/data/test_slider_triangle_horiz_True_flip_True.png +0 -0
  2710. psychopy/tests/data/test_sounds/default_16000.wav +0 -0
  2711. psychopy/tests/data/test_sounds/default_192000.wav +0 -0
  2712. psychopy/tests/data/test_sounds/default_22050.wav +0 -0
  2713. psychopy/tests/data/test_sounds/default_32000.wav +0 -0
  2714. psychopy/tests/data/test_sounds/default_44100.wav +0 -0
  2715. psychopy/tests/data/test_sounds/default_48000.wav +0 -0
  2716. psychopy/tests/data/test_sounds/default_8000.wav +0 -0
  2717. psychopy/tests/data/test_sounds/default_96000.wav +0 -0
  2718. psychopy/tests/data/test_static_component_script.psyexp +76 -0
  2719. psychopy/tests/data/test_win_bg_large_256_default.png +0 -0
  2720. psychopy/tests/data/test_win_bg_large_500_default.png +0 -0
  2721. psychopy/tests/data/test_win_bg_small_200_default.png +0 -0
  2722. psychopy/tests/data/test_win_bg_small_256_default.png +0 -0
  2723. psychopy/tests/data/test_win_bg_tall_200_default.png +0 -0
  2724. psychopy/tests/data/test_win_bg_tall_256_default.png +0 -0
  2725. psychopy/tests/data/test_win_bg_tall_500_default.png +0 -0
  2726. psychopy/tests/data/test_win_bg_tall_fill_default.png +0 -0
  2727. psychopy/tests/data/test_win_bg_wide_200_default.png +0 -0
  2728. psychopy/tests/data/test_win_bg_wide_256_default.png +0 -0
  2729. psychopy/tests/data/test_win_bg_wide_500_default.png +0 -0
  2730. psychopy/tests/data/test_win_bg_wide_fill_default.png +0 -0
  2731. psychopy/tests/data/test_win_bgcolor_blue.png +0 -0
  2732. psychopy/tests/data/test_win_bgcolor_green.png +0 -0
  2733. psychopy/tests/data/test_win_bgcolor_red.png +0 -0
  2734. psychopy/tests/data/testimage.jpg +0 -0
  2735. psychopy/tests/data/testimagegray.jpg +0 -0
  2736. psychopy/tests/data/testpixels.png +0 -0
  2737. psychopy/tests/data/testwedges.png +0 -0
  2738. psychopy/tests/data/text1_cm.png +0 -0
  2739. psychopy/tests/data/text1_deg.png +0 -0
  2740. psychopy/tests/data/text1_degFlat.png +0 -0
  2741. psychopy/tests/data/text1_degFlatPos.png +0 -0
  2742. psychopy/tests/data/text1_height.png +0 -0
  2743. psychopy/tests/data/text1_norm.png +0 -0
  2744. psychopy/tests/data/text1_normAddBlend.png +0 -0
  2745. psychopy/tests/data/text1_normHexbackground.png +0 -0
  2746. psychopy/tests/data/text1_normNoShade.png +0 -0
  2747. psychopy/tests/data/text1_pix.png +0 -0
  2748. psychopy/tests/data/text1_stencil.png +0 -0
  2749. psychopy/tests/data/text2_cm.png +0 -0
  2750. psychopy/tests/data/text2_deg.png +0 -0
  2751. psychopy/tests/data/text2_degFlat.png +0 -0
  2752. psychopy/tests/data/text2_degFlatPos.png +0 -0
  2753. psychopy/tests/data/text2_norm.png +0 -0
  2754. psychopy/tests/data/text2_normNoShade.png +0 -0
  2755. psychopy/tests/data/text2_pix.png +0 -0
  2756. psychopy/tests/data/textbox_charcolors_default_roygbiv.png +0 -0
  2757. psychopy/tests/data/textbox_charcolors_default_white_hello_black_there.png +0 -0
  2758. psychopy/tests/data/textbox_default_align_bottom_center.png +0 -0
  2759. psychopy/tests/data/textbox_default_align_bottom_left.png +0 -0
  2760. psychopy/tests/data/textbox_default_align_bottom_right.png +0 -0
  2761. psychopy/tests/data/textbox_default_align_center.png +0 -0
  2762. psychopy/tests/data/textbox_default_align_center_center.png +0 -0
  2763. psychopy/tests/data/textbox_default_align_center_left.png +0 -0
  2764. psychopy/tests/data/textbox_default_align_center_right.png +0 -0
  2765. psychopy/tests/data/textbox_default_align_centre.png +0 -0
  2766. psychopy/tests/data/textbox_default_align_centre_centre.png +0 -0
  2767. psychopy/tests/data/textbox_default_align_more_than_two_words.png +0 -0
  2768. psychopy/tests/data/textbox_default_align_someword.png +0 -0
  2769. psychopy/tests/data/textbox_default_align_top_center.png +0 -0
  2770. psychopy/tests/data/textbox_default_align_top_left.png +0 -0
  2771. psychopy/tests/data/textbox_default_align_top_right.png +0 -0
  2772. psychopy/tests/data/textbox_default_colors_WOB.png +0 -0
  2773. psychopy/tests/data/textbox_default_colors_exemplar1.png +0 -0
  2774. psychopy/tests/data/textbox_default_colors_exemplar2.png +0 -0
  2775. psychopy/tests/data/textbox_default_colors_exemplar3.png +0 -0
  2776. psychopy/tests/data/textbox_default_colors_tyke1.png +0 -0
  2777. psychopy/tests/data/textbox_default_colors_tyke2.png +0 -0
  2778. psychopy/tests/data/textbox_default_colors_tyke3.png +0 -0
  2779. psychopy/tests/data/textbox_default_cutoff_top.png +0 -0
  2780. psychopy/tests/data/textbox_default_exemplar_1.png +0 -0
  2781. psychopy/tests/data/textbox_default_exemplar_2.png +0 -0
  2782. psychopy/tests/data/textbox_default_exemplar_3.png +0 -0
  2783. psychopy/tests/data/textbox_default_exemplar_4.png +0 -0
  2784. psychopy/tests/data/textbox_default_tyke_1.png +0 -0
  2785. psychopy/tests/data/textbox_default_tyke_2.png +0 -0
  2786. psychopy/tests/data/textbox_typing_blank.png +0 -0
  2787. psychopy/tests/data/textbox_typing_longKoeran.png +0 -0
  2788. psychopy/tests/data/textbox_typing_longWord.png +0 -0
  2789. psychopy/tests/data/textbox_typing_navDel.png +0 -0
  2790. psychopy/tests/data/textbox_typing_navLR.png +0 -0
  2791. psychopy/tests/data/textbox_typing_newline.png +0 -0
  2792. psychopy/tests/data/textbox_typing_pangram.png +0 -0
  2793. psychopy/tests/data/textbox_uax14_align_bottom_center.png +0 -0
  2794. psychopy/tests/data/textbox_uax14_align_bottom_left.png +0 -0
  2795. psychopy/tests/data/textbox_uax14_align_bottom_right.png +0 -0
  2796. psychopy/tests/data/textbox_uax14_align_center.png +0 -0
  2797. psychopy/tests/data/textbox_uax14_align_center_center.png +0 -0
  2798. psychopy/tests/data/textbox_uax14_align_center_left.png +0 -0
  2799. psychopy/tests/data/textbox_uax14_align_center_right.png +0 -0
  2800. psychopy/tests/data/textbox_uax14_align_centre.png +0 -0
  2801. psychopy/tests/data/textbox_uax14_align_centre_centre.png +0 -0
  2802. psychopy/tests/data/textbox_uax14_align_more_than_two_words.png +0 -0
  2803. psychopy/tests/data/textbox_uax14_align_someword.png +0 -0
  2804. psychopy/tests/data/textbox_uax14_align_top_center.png +0 -0
  2805. psychopy/tests/data/textbox_uax14_align_top_left.png +0 -0
  2806. psychopy/tests/data/textbox_uax14_align_top_right.png +0 -0
  2807. psychopy/tests/data/textbox_uax14_colors_WOB.png +0 -0
  2808. psychopy/tests/data/textbox_uax14_colors_exemplar1.png +0 -0
  2809. psychopy/tests/data/textbox_uax14_colors_exemplar2.png +0 -0
  2810. psychopy/tests/data/textbox_uax14_colors_exemplar3.png +0 -0
  2811. psychopy/tests/data/textbox_uax14_colors_tyke1.png +0 -0
  2812. psychopy/tests/data/textbox_uax14_colors_tyke2.png +0 -0
  2813. psychopy/tests/data/textbox_uax14_colors_tyke3.png +0 -0
  2814. psychopy/tests/data/textbox_uax14_cutoff_top.png +0 -0
  2815. psychopy/tests/data/textbox_uax14_exemplar_1.png +0 -0
  2816. psychopy/tests/data/textbox_uax14_exemplar_2.png +0 -0
  2817. psychopy/tests/data/textbox_uax14_exemplar_3.png +0 -0
  2818. psychopy/tests/data/textbox_uax14_exemplar_4.png +0 -0
  2819. psychopy/tests/data/textbox_uax14_tyke_1.png +0 -0
  2820. psychopy/tests/data/textbox_uax14_tyke_2.png +0 -0
  2821. psychopy/tests/data/trialTypes.csv +1 -0
  2822. psychopy/tests/data/trialTypes.docx +0 -0
  2823. psychopy/tests/data/trialTypes.pkl +0 -0
  2824. psychopy/tests/data/trialTypes.tsv +7 -0
  2825. psychopy/tests/data/trialTypes.xls +0 -0
  2826. psychopy/tests/data/trialTypes.xlsx +0 -0
  2827. psychopy/tests/data/trialTypes_eu.csv +7 -0
  2828. psychopy/tests/data/trialsBlankCols.xlsx +0 -0
  2829. psychopy/tests/data/wedge1_cm.png +0 -0
  2830. psychopy/tests/data/wedge1_deg.png +0 -0
  2831. psychopy/tests/data/wedge1_degFlat.png +0 -0
  2832. psychopy/tests/data/wedge1_degFlatPos.png +0 -0
  2833. psychopy/tests/data/wedge1_height.png +0 -0
  2834. psychopy/tests/data/wedge1_norm.png +0 -0
  2835. psychopy/tests/data/wedge1_normAddBlend.png +0 -0
  2836. psychopy/tests/data/wedge1_normHexbackground.png +0 -0
  2837. psychopy/tests/data/wedge1_normNoShade.png +0 -0
  2838. psychopy/tests/data/wedge1_pix.png +0 -0
  2839. psychopy/tests/data/wedge1_stencil.png +0 -0
  2840. psychopy/tests/data/wedge2_cm.png +0 -0
  2841. psychopy/tests/data/wedge2_deg.png +0 -0
  2842. psychopy/tests/data/wedge2_degFlat.png +0 -0
  2843. psychopy/tests/data/wedge2_degFlatPos.png +0 -0
  2844. psychopy/tests/data/wedge2_height.png +0 -0
  2845. psychopy/tests/data/wedge2_norm.png +0 -0
  2846. psychopy/tests/data/wedge2_normAddBlend.png +0 -0
  2847. psychopy/tests/data/wedge2_normHexbackground.png +0 -0
  2848. psychopy/tests/data/wedge2_normNoShade.png +0 -0
  2849. psychopy/tests/data/wedge2_pix.png +0 -0
  2850. psychopy/tests/data/wedge2_stencil.png +0 -0
  2851. psychopy/tests/data/winScalePos_ori0_scale-1_-1_pos-0.4_0.png +0 -0
  2852. psychopy/tests/data/winScalePos_ori0_scale-1_-1_pos0_0.png +0 -0
  2853. psychopy/tests/data/winScalePos_ori0_scale-1_1_pos-0.4_0.png +0 -0
  2854. psychopy/tests/data/winScalePos_ori0_scale-1_1_pos0_0.png +0 -0
  2855. psychopy/tests/data/winScalePos_ori0_scale-2_-2_pos-0.4_0.png +0 -0
  2856. psychopy/tests/data/winScalePos_ori0_scale-2_-2_pos0_0.png +0 -0
  2857. psychopy/tests/data/winScalePos_ori0_scale-2_2_pos-0.4_0.png +0 -0
  2858. psychopy/tests/data/winScalePos_ori0_scale-2_2_pos0_0.png +0 -0
  2859. psychopy/tests/data/winScalePos_ori0_scale1_-1_pos-0.4_0.png +0 -0
  2860. psychopy/tests/data/winScalePos_ori0_scale1_-1_pos0_0.png +0 -0
  2861. psychopy/tests/data/winScalePos_ori0_scale1_1_pos-0.4_0.png +0 -0
  2862. psychopy/tests/data/winScalePos_ori0_scale1_1_pos0_0.png +0 -0
  2863. psychopy/tests/data/winScalePos_ori0_scale2_-2_pos-0.4_0.png +0 -0
  2864. psychopy/tests/data/winScalePos_ori0_scale2_-2_pos0_0.png +0 -0
  2865. psychopy/tests/data/winScalePos_ori0_scale2_2_pos-0.4_0.png +0 -0
  2866. psychopy/tests/data/winScalePos_ori0_scale2_2_pos0_0.png +0 -0
  2867. psychopy/tests/data/winScalePos_ori45_scale-1_-1_pos0_0.png +0 -0
  2868. psychopy/tests/data/winScalePos_ori45_scale-1_1_pos0_0.png +0 -0
  2869. psychopy/tests/data/winScalePos_ori45_scale-2_-2_pos0_0.png +0 -0
  2870. psychopy/tests/data/winScalePos_ori45_scale-2_2_pos0_0.png +0 -0
  2871. psychopy/tests/data/winScalePos_ori45_scale1_-1_pos0_0.png +0 -0
  2872. psychopy/tests/data/winScalePos_ori45_scale1_1_pos0_0.png +0 -0
  2873. psychopy/tests/data/winScalePos_ori45_scale2_-2_pos0_0.png +0 -0
  2874. psychopy/tests/data/winScalePos_ori45_scale2_2_pos0_0.png +0 -0
  2875. psychopy/tests/doc/run_btn.png +0 -0
  2876. psychopy/tests/doc/test-suite-bugs.jpg +0 -0
  2877. psychopy/tests/doc/user-bugs.jpg +0 -0
  2878. psychopy/tests/dummy_xorg.conf +21 -0
  2879. psychopy/tests/run.py +50 -0
  2880. psychopy/tests/test_Installation.py +38 -0
  2881. psychopy/tests/test_alerts/test_alerts.py +37 -0
  2882. psychopy/tests/test_alerts/test_alerttools.py +132 -0
  2883. psychopy/tests/test_app/__init__.py +0 -0
  2884. psychopy/tests/test_app/conftest.py +40 -0
  2885. psychopy/tests/test_app/test_builder/__init__.py +0 -0
  2886. psychopy/tests/test_app/test_builder/test_BuilderFrame.py +166 -0
  2887. psychopy/tests/test_app/test_builder/test_CompileFromBuilder.py +133 -0
  2888. psychopy/tests/test_app/test_builder/test_ComponentDialogs.py +98 -0
  2889. psychopy/tests/test_app/test_command_line.py +65 -0
  2890. psychopy/tests/test_app/test_runner/__init__.py +0 -0
  2891. psychopy/tests/test_app/test_runner/test_RunnerFrame.py +166 -0
  2892. psychopy/tests/test_app/test_speed.py +147 -0
  2893. psychopy/tests/test_app/test_themes/test_icons.py +79 -0
  2894. psychopy/tests/test_codecov.py +29 -0
  2895. psychopy/tests/test_colors/test_Color.py +41 -0
  2896. psychopy/tests/test_data/dataPrev.xlsx +0 -0
  2897. psychopy/tests/test_data/test_ExperimentHandler.py +171 -0
  2898. psychopy/tests/test_data/test_MultiStairHandler.py +174 -0
  2899. psychopy/tests/test_data/test_StairHandlers.py +1241 -0
  2900. psychopy/tests/test_data/test_TrialHandler.py +335 -0
  2901. psychopy/tests/test_data/test_TrialHandler2.py +584 -0
  2902. psychopy/tests/test_data/test_TrialHandlerExt.py +359 -0
  2903. psychopy/tests/test_data/test_fitFunctions.py +101 -0
  2904. psychopy/tests/test_data/test_utils.py +173 -0
  2905. psychopy/tests/test_data/test_xlsx.py +92 -0
  2906. psychopy/tests/test_demos/test_builder_demos.py +52 -0
  2907. psychopy/tests/test_experiment/__init__.py +0 -0
  2908. psychopy/tests/test_experiment/known_py_diffs.txt +47 -0
  2909. psychopy/tests/test_experiment/needs_wx/__init__.py +0 -0
  2910. psychopy/tests/test_experiment/needs_wx/componsTemplate.txt +14780 -0
  2911. psychopy/tests/test_experiment/needs_wx/genComponsTemplate.py +130 -0
  2912. psychopy/tests/test_experiment/needs_wx/test_Experiment.py +406 -0
  2913. psychopy/tests/test_experiment/needs_wx/test_components.py +170 -0
  2914. psychopy/tests/test_experiment/test_component_compile_js.py +59 -0
  2915. psychopy/tests/test_experiment/test_component_compile_python.py +165 -0
  2916. psychopy/tests/test_experiment/test_components/__init__.py +1 -0
  2917. psychopy/tests/test_experiment/test_components/test_ButtonBoxComponent.py +218 -0
  2918. psychopy/tests/test_experiment/test_components/test_CodeComponent.py +70 -0
  2919. psychopy/tests/test_experiment/test_components/test_GratingComponent.py +7 -0
  2920. psychopy/tests/test_experiment/test_components/test_ImageComponent.py +8 -0
  2921. psychopy/tests/test_experiment/test_components/test_KeyboardComponent.py +28 -0
  2922. psychopy/tests/test_experiment/test_components/test_MouseComponent.py +136 -0
  2923. psychopy/tests/test_experiment/test_components/test_PolygonComponent.py +65 -0
  2924. psychopy/tests/test_experiment/test_components/test_ResourceManagerComponent.py +50 -0
  2925. psychopy/tests/test_experiment/test_components/test_RoutineSettingsComponent.py +16 -0
  2926. psychopy/tests/test_experiment/test_components/test_SettingsComponent.py +80 -0
  2927. psychopy/tests/test_experiment/test_components/test_StaticComponent.py +51 -0
  2928. psychopy/tests/test_experiment/test_components/test_UnknownPluginComponent.py +27 -0
  2929. psychopy/tests/test_experiment/test_components/test_all_components.py +104 -0
  2930. psychopy/tests/test_experiment/test_components/test_base_components.py +477 -0
  2931. psychopy/tests/test_experiment/test_experiment.py +199 -0
  2932. psychopy/tests/test_experiment/test_loops.py +103 -0
  2933. psychopy/tests/test_experiment/test_params.py +363 -0
  2934. psychopy/tests/test_experiment/test_py2js.py +230 -0
  2935. psychopy/tests/test_experiment/test_routines/__init__.py +1 -0
  2936. psychopy/tests/test_experiment/test_routines/test_EyetrackerCalibrationRoutine.py +9 -0
  2937. psychopy/tests/test_experiment/test_routines/test_PhotodiodeValidationRoutine.py +9 -0
  2938. psychopy/tests/test_experiment/test_routines/test_all_routines.py +23 -0
  2939. psychopy/tests/test_experiment/test_routines/test_base_routine.py +154 -0
  2940. psychopy/tests/test_experiment/test_routines/test_standalone_routines.py +36 -0
  2941. psychopy/tests/test_gui/test_DlgFromDictQt.py +82 -0
  2942. psychopy/tests/test_gui/test_DlgFromDictWx.py +82 -0
  2943. psychopy/tests/test_hardware/__init__.py +0 -0
  2944. psychopy/tests/test_hardware/test_device_manager.py +36 -0
  2945. psychopy/tests/test_hardware/test_emulator.py +106 -0
  2946. psychopy/tests/test_hardware/test_gammasci.py +35 -0
  2947. psychopy/tests/test_hardware/test_keyboard.py +241 -0
  2948. psychopy/tests/test_hardware/test_keyboard_events.py +362 -0
  2949. psychopy/tests/test_hardware/test_photodiode.py +66 -0
  2950. psychopy/tests/test_hardware/test_ports.py +129 -0
  2951. psychopy/tests/test_iohub/__init__.py +1 -0
  2952. psychopy/tests/test_iohub/test_computer.py +124 -0
  2953. psychopy/tests/test_iohub/test_event_get_and_clear.py +94 -0
  2954. psychopy/tests/test_iohub/test_keyboard.py +91 -0
  2955. psychopy/tests/test_iohub/test_launch.py +19 -0
  2956. psychopy/tests/test_iohub/testutil.py +54 -0
  2957. psychopy/tests/test_liaison/test_Liaison.py +275 -0
  2958. psychopy/tests/test_misc/__init__.py +0 -0
  2959. psychopy/tests/test_misc/memory_usage.py +164 -0
  2960. psychopy/tests/test_misc/test_GammaFun.py +15 -0
  2961. psychopy/tests/test_misc/test_clock.py +63 -0
  2962. psychopy/tests/test_misc/test_color.py +205 -0
  2963. psychopy/tests/test_misc/test_core.py +451 -0
  2964. psychopy/tests/test_misc/test_event.py +308 -0
  2965. psychopy/tests/test_misc/test_info.py +18 -0
  2966. psychopy/tests/test_misc/test_layout.py +49 -0
  2967. psychopy/tests/test_misc/test_locale.py +38 -0
  2968. psychopy/tests/test_misc/test_web.py +22 -0
  2969. psychopy/tests/test_monitors/test_monitors.py +91 -0
  2970. psychopy/tests/test_plugins/__init__.py +0 -0
  2971. psychopy/tests/test_plugins/test_plugin_stubs.py +125 -0
  2972. psychopy/tests/test_preferences/__init__.py +0 -0
  2973. psychopy/tests/test_preferences/test_prefs.py +28 -0
  2974. psychopy/tests/test_session/test_Session.py +257 -0
  2975. psychopy/tests/test_sound/__init__.py +0 -0
  2976. psychopy/tests/test_sound/test_audioclip.py +331 -0
  2977. psychopy/tests/test_sound/test_hamming.py +45 -0
  2978. psychopy/tests/test_sound/test_sound.py +138 -0
  2979. psychopy/tests/test_sound/test_sound_pygame.py +67 -0
  2980. psychopy/tests/test_tools/test_animationtools.py +51 -0
  2981. psychopy/tests/test_tools/test_arraytools.py +242 -0
  2982. psychopy/tests/test_tools/test_attributetools.py +257 -0
  2983. psychopy/tests/test_tools/test_colorspacetools.py +150 -0
  2984. psychopy/tests/test_tools/test_environmenttools.py +52 -0
  2985. psychopy/tests/test_tools/test_fileerrortools.py +97 -0
  2986. psychopy/tests/test_tools/test_filetools.py +104 -0
  2987. psychopy/tests/test_tools/test_imagetools.py +57 -0
  2988. psychopy/tests/test_tools/test_mathtools.py +688 -0
  2989. psychopy/tests/test_tools/test_stringtools.py +143 -0
  2990. psychopy/tests/test_tools/test_versionchooser.py +209 -0
  2991. psychopy/tests/test_tools/test_viewtools.py +168 -0
  2992. psychopy/tests/test_validators/__init__.py +0 -0
  2993. psychopy/tests/test_validators/test_voicekeyValidator.py +95 -0
  2994. psychopy/tests/test_visual/__init__.py +0 -0
  2995. psychopy/tests/test_visual/measure_parity.py +243 -0
  2996. psychopy/tests/test_visual/test_all_stimuli.py +655 -0
  2997. psychopy/tests/test_visual/test_basevisual.py +564 -0
  2998. psychopy/tests/test_visual/test_brush.py +68 -0
  2999. psychopy/tests/test_visual/test_button.py +15 -0
  3000. psychopy/tests/test_visual/test_circle.py +74 -0
  3001. psychopy/tests/test_visual/test_contains_overlaps.py +242 -0
  3002. psychopy/tests/test_visual/test_custommouse.py +47 -0
  3003. psychopy/tests/test_visual/test_dots.py +155 -0
  3004. psychopy/tests/test_visual/test_form.py +414 -0
  3005. psychopy/tests/test_visual/test_framepacking.py +41 -0
  3006. psychopy/tests/test_visual/test_gamma.py +152 -0
  3007. psychopy/tests/test_visual/test_glfw_backend.py +14 -0
  3008. psychopy/tests/test_visual/test_image.py +219 -0
  3009. psychopy/tests/test_visual/test_panorama.py +41 -0
  3010. psychopy/tests/test_visual/test_progress.py +96 -0
  3011. psychopy/tests/test_visual/test_projections.py +215 -0
  3012. psychopy/tests/test_visual/test_projections_interactive.py +163 -0
  3013. psychopy/tests/test_visual/test_roi.py +105 -0
  3014. psychopy/tests/test_visual/test_shape.py +23 -0
  3015. psychopy/tests/test_visual/test_slider.py +328 -0
  3016. psychopy/tests/test_visual/test_target.py +35 -0
  3017. psychopy/tests/test_visual/test_textbox.py +508 -0
  3018. psychopy/tests/test_visual/test_winFlipTiming.py +95 -0
  3019. psychopy/tests/test_visual/test_winScalePos.py +78 -0
  3020. psychopy/tests/test_visual/test_window.py +124 -0
  3021. psychopy/tests/utils.py +372 -0
  3022. psychopy/tools/LineBreak.txt +3597 -0
  3023. psychopy/tools/__init__.py +9 -0
  3024. psychopy/tools/animationtools.py +49 -0
  3025. psychopy/tools/apptools.py +32 -0
  3026. psychopy/tools/arraytools.py +561 -0
  3027. psychopy/tools/attributetools.py +263 -0
  3028. psychopy/tools/audiotools.py +361 -0
  3029. psychopy/tools/colorspacetools.py +717 -0
  3030. psychopy/tools/coordinatetools.py +104 -0
  3031. psychopy/tools/environmenttools.py +62 -0
  3032. psychopy/tools/fileerrortools.py +66 -0
  3033. psychopy/tools/filetools.py +406 -0
  3034. psychopy/tools/fontmanager.py +1065 -0
  3035. psychopy/tools/gltools.py +7367 -0
  3036. psychopy/tools/imagetools.py +65 -0
  3037. psychopy/tools/linebreak.py +322 -0
  3038. psychopy/tools/mathtools.py +4910 -0
  3039. psychopy/tools/monitorunittools.py +276 -0
  3040. psychopy/tools/movietools.py +1111 -0
  3041. psychopy/tools/pkgtools.py +654 -0
  3042. psychopy/tools/plottools.py +25 -0
  3043. psychopy/tools/rifttools.py +76 -0
  3044. psychopy/tools/stereotools.py +9 -0
  3045. psychopy/tools/stimulustools.py +198 -0
  3046. psychopy/tools/stringtools.py +466 -0
  3047. psychopy/tools/systemtools.py +1331 -0
  3048. psychopy/tools/typetools.py +52 -0
  3049. psychopy/tools/unittools.py +16 -0
  3050. psychopy/tools/versionchooser.py +604 -0
  3051. psychopy/tools/viewtools.py +1068 -0
  3052. psychopy/tools/wizard.py +804 -0
  3053. psychopy/validation/__init__.py +6 -0
  3054. psychopy/validation/audio.py +78 -0
  3055. psychopy/validation/visual.py +119 -0
  3056. psychopy/visual/__init__.py +121 -0
  3057. psychopy/visual/aperture.py +333 -0
  3058. psychopy/visual/backends/__init__.py +77 -0
  3059. psychopy/visual/backends/_base.py +481 -0
  3060. psychopy/visual/backends/gamma.py +349 -0
  3061. psychopy/visual/backends/glfwbackend.py +24 -0
  3062. psychopy/visual/backends/pygamebackend.py +343 -0
  3063. psychopy/visual/backends/pygletbackend.py +970 -0
  3064. psychopy/visual/basevisual.py +2027 -0
  3065. psychopy/visual/brush.py +204 -0
  3066. psychopy/visual/bufferimage.py +311 -0
  3067. psychopy/visual/button.py +194 -0
  3068. psychopy/visual/circle.py +165 -0
  3069. psychopy/visual/custommouse.py +263 -0
  3070. psychopy/visual/dot.py +734 -0
  3071. psychopy/visual/dropdown.py +165 -0
  3072. psychopy/visual/elementarray.py +802 -0
  3073. psychopy/visual/filters.py +419 -0
  3074. psychopy/visual/form.py +1195 -0
  3075. psychopy/visual/globalVars.py +24 -0
  3076. psychopy/visual/grating.py +581 -0
  3077. psychopy/visual/helpers.py +336 -0
  3078. psychopy/visual/image.py +438 -0
  3079. psychopy/visual/line.py +227 -0
  3080. psychopy/visual/movie.py +12 -0
  3081. psychopy/visual/movie2.py +21 -0
  3082. psychopy/visual/movie3.py +18 -0
  3083. psychopy/visual/movies/__init__.py +2334 -0
  3084. psychopy/visual/movies/frame.py +258 -0
  3085. psychopy/visual/movies/metadata.py +242 -0
  3086. psychopy/visual/movies/players/_base.py +364 -0
  3087. psychopy/visual/nnlvs.py +830 -0
  3088. psychopy/visual/noise.py +32 -0
  3089. psychopy/visual/panorama.py +313 -0
  3090. psychopy/visual/patch.py +21 -0
  3091. psychopy/visual/pie.py +237 -0
  3092. psychopy/visual/polygon.py +226 -0
  3093. psychopy/visual/progress.py +313 -0
  3094. psychopy/visual/radial.py +29 -0
  3095. psychopy/visual/ratingscale.py +18 -0
  3096. psychopy/visual/rect.py +195 -0
  3097. psychopy/visual/rift.py +2660 -0
  3098. psychopy/visual/roi.py +141 -0
  3099. psychopy/visual/secondorder.py +27 -0
  3100. psychopy/visual/shaders.py +787 -0
  3101. psychopy/visual/shape.py +897 -0
  3102. psychopy/visual/simpleimage.py +303 -0
  3103. psychopy/visual/slider.py +1222 -0
  3104. psychopy/visual/stim3d.py +2109 -0
  3105. psychopy/visual/target.py +278 -0
  3106. psychopy/visual/text.py +769 -0
  3107. psychopy/visual/textbox/__init__.py +1280 -0
  3108. psychopy/visual/textbox/fontmanager.py +574 -0
  3109. psychopy/visual/textbox/parsedtext.py +317 -0
  3110. psychopy/visual/textbox/textgrid.py +278 -0
  3111. psychopy/visual/textbox/textureatlas.py +248 -0
  3112. psychopy/visual/textbox2/__init__.py +4 -0
  3113. psychopy/visual/textbox2/textbox2.py +1970 -0
  3114. psychopy/visual/vlcmoviestim.py +1294 -0
  3115. psychopy/visual/window.py +3910 -0
  3116. psychopy/visual/windowframepack.py +86 -0
  3117. psychopy/visual/windowwarp.py +457 -0
  3118. psychopy/voicekey/__init__.py +56 -0
  3119. psychopy/voicekey/labjack_vks.py +9 -0
  3120. psychopy/voicekey/parallel_vks.py +9 -0
  3121. psychopy/voicekey/vk_tools.py +131 -0
  3122. psychopy/web.py +289 -0
  3123. psychopy-2025.2.4.dist-info/METADATA +160 -0
  3124. psychopy-2025.2.4.dist-info/RECORD +3127 -0
  3125. psychopy-2025.2.4.dist-info/WHEEL +4 -0
  3126. psychopy-2025.2.4.dist-info/entry_points.txt +5 -0
  3127. psychopy-2025.2.4.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,3910 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """A class representing a window for displaying one or more stimuli"""
5
+
6
+ # Part of the PsychoPy library
7
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
8
+ # Distributed under the terms of the GNU General Public License (GPL).
9
+
10
+ import ctypes
11
+ import os
12
+ import sys
13
+ import weakref
14
+ import atexit
15
+ from itertools import product
16
+ from collections import deque
17
+
18
+ from psychopy.contrib.lazy_import import lazy_import
19
+ from psychopy import colors, event
20
+ from psychopy.localization import _translate
21
+ from psychopy.tools.systemtools import getCurrentPID, registerPID
22
+ import math
23
+ # from psychopy.clock import monotonicClock
24
+
25
+ # try to find avbin (we'll overload pyglet's load_library tool and then
26
+ # add some paths
27
+ from ..colors import Color, colorSpaces
28
+ from .textbox2 import TextBox2
29
+
30
+ import pyglet
31
+
32
+
33
+ haveAvbin = False
34
+
35
+ # on windows try to load avbin now (other libs can interfere)
36
+ if sys.platform == 'win32':
37
+ # make sure we also check in SysWOW64 if on 64-bit windows
38
+ if 'C:\\Windows\\SysWOW64' not in os.environ['PATH']:
39
+ os.environ['PATH'] += ';C:\\Windows\\SysWOW64'
40
+
41
+ try:
42
+ from pyglet.media import avbin
43
+ haveAvbin = True
44
+ except ImportError:
45
+ haveAvbin = False
46
+ # either avbin isn't installed or scipy.stats has been imported
47
+ # (prevents avbin loading)
48
+ except AttributeError:
49
+ # avbin is not found, causing exception in pyglet 1.2??
50
+ # (running psychopy 1.81 standalone on windows 7):
51
+ #
52
+ # File "C:\Program Files (x86)\PsychoPy2\lib\site-packages\
53
+ # pyglet\media\avbin.py", line 158, in <module>
54
+ # av.avbin_get_version.restype = ctypes.c_int
55
+ # AttributeError: 'NoneType' object has no attribute
56
+ # 'avbin_get_version'
57
+ haveAvbin = False
58
+ except Exception:
59
+ # WindowsError on some systems
60
+ # AttributeError if using avbin5 from pyglet 1.2?
61
+ haveAvbin = False
62
+
63
+ # for pyglet 1.3
64
+ if not haveAvbin:
65
+ try:
66
+ from pyglet.media.sources import avbin
67
+ haveAvbin = True
68
+ except ImportError:
69
+ haveAvbin = False
70
+ except AttributeError:
71
+ haveAvbin = False
72
+ except Exception:
73
+ haveAvbin = False
74
+
75
+ import psychopy # so we can get the __path__
76
+ from psychopy import core, platform_specific, logging, prefs, monitors
77
+ import psychopy.event
78
+ from . import backends, image
79
+
80
+ # tools must only be imported *after* event or MovieStim breaks on win32
81
+ # (JWP has no idea why!)
82
+ from psychopy.tools.attributetools import attributeSetter, setAttribute
83
+ from psychopy.tools.arraytools import val2array
84
+ from psychopy.tools.monitorunittools import convertToPix
85
+ import psychopy.tools.viewtools as viewtools
86
+ import psychopy.tools.gltools as gltools
87
+ import psychopy.tools.mathtools as mathtools
88
+ from .text import TextStim
89
+ from .grating import GratingStim
90
+ from .helpers import setColor
91
+ from . import globalVars
92
+
93
+ try:
94
+ from PIL import Image
95
+ except ImportError:
96
+ import Image
97
+
98
+ import numpy
99
+
100
+ from psychopy.core import rush
101
+
102
+ reportNDroppedFrames = 5 # stop raising warning after this
103
+
104
+ # import pyglet.gl, pyglet.window, pyglet.image, pyglet.font, pyglet.event
105
+ from . import shaders as _shaders
106
+ try:
107
+ from pyglet import media
108
+ havePygletMedia = True
109
+ except Exception:
110
+ havePygletMedia = False
111
+
112
+ # lazy_import puts pygame into the namespace but delays import until needed
113
+ lazy_import(globals(), "import pygame")
114
+
115
+ DEBUG = False
116
+ IOHUB_ACTIVE = False
117
+ retinaContext = None # only needed for retina-ready displays
118
+
119
+
120
+ class OpenWinList(list):
121
+ """Class to keep keep track of windows that have been opened.
122
+
123
+ Uses a list of weak references so that we don't stop the window
124
+ being deleted.
125
+
126
+ """
127
+ def append(self, item):
128
+ list.append(self, weakref.ref(item))
129
+
130
+ def remove(self, item):
131
+ for ref in self:
132
+ obj = ref()
133
+ if obj is None or item == obj:
134
+ list.remove(self, ref)
135
+
136
+
137
+ openWindows = core.openWindows = OpenWinList() # core needs this for wait()
138
+
139
+
140
+ class Window():
141
+ """Used to set up a context in which to draw objects,
142
+ using either `pyglet <http://www.pyglet.org>`_,
143
+ `pygame <http://www.pygame.org>`_, or `glfw <https://www.glfw.org>`_.
144
+
145
+ The pyglet backend allows multiple windows to be created, allows the user
146
+ to specify which screen to use (if more than one is available, duh!) and
147
+ allows movies to be rendered.
148
+
149
+ The GLFW backend is a new addition which provides most of the same features
150
+ as pyglet, but provides greater flexibility for complex display
151
+ configurations.
152
+
153
+ Pygame may still work for you but it's officially deprecated in this
154
+ project (we won't be fixing pygame-specific bugs).
155
+
156
+ """
157
+ USE_LEGACY_GL = pyglet.version < '2.0'
158
+ def __init__(self,
159
+ size=(800, 600),
160
+ pos=None,
161
+ color=(0, 0, 0),
162
+ colorSpace='rgb',
163
+ backgroundImage=None,
164
+ backgroundFit="cover",
165
+ rgb=None,
166
+ dkl=None,
167
+ lms=None,
168
+ fullscr=None,
169
+ allowGUI=None,
170
+ monitor=None,
171
+ bitsMode=None,
172
+ winType=None,
173
+ units=None,
174
+ gamma=None,
175
+ blendMode='avg',
176
+ screen=0,
177
+ viewScale=None,
178
+ viewPos=None,
179
+ viewOri=0.0,
180
+ waitBlanking=True,
181
+ allowStencil=False,
182
+ multiSample=False,
183
+ numSamples=2,
184
+ stereo=False,
185
+ name='window1',
186
+ title="PsychoPy",
187
+ checkTiming=True,
188
+ useFBO=False,
189
+ useRetina=True,
190
+ autoLog=True,
191
+ gammaErrorPolicy='raise',
192
+ bpc=(8, 8, 8),
193
+ depthBits=8,
194
+ stencilBits=8,
195
+ backendConf=None,
196
+ infoMsg=None):
197
+ """
198
+ These attributes can only be set at initialization. See further down
199
+ for a list of attributes which can be changed after initialization
200
+ of the Window, e.g. color, colorSpace, gamma etc.
201
+
202
+ Parameters
203
+ ----------
204
+ size : array-like of int
205
+ Size of the window in pixels [x, y].
206
+ pos : array-like of int
207
+ Location of the top-left corner of the window on the screen [x, y].
208
+ color : array-like of float
209
+ Color of background as [r, g, b] list or single value. Each gun can
210
+ take values between -1.0 and 1.0.
211
+ fullscr : bool or None
212
+ Create a window in 'full-screen' mode. Better timing can be achieved
213
+ in full-screen mode.
214
+ allowGUI : bool or None
215
+ If set to False, window will be drawn with no frame and no buttons
216
+ to close etc., use `None` for value from preferences.
217
+ winType : str or None
218
+ Set the window type or back-end to use. If `None` then PsychoPy will
219
+ revert to user/site preferences.
220
+ monitor : :class:`~psychopy.monitors.Monitor` or None
221
+ The monitor to be used during the experiment. If `None` a default
222
+ monitor profile will be used.
223
+ units : str or None
224
+ Defines the default units of stimuli drawn in the window (can be
225
+ overridden by each stimulus). Values can be *None*, 'height' (of the
226
+ window), 'norm' (normalised), 'deg', 'cm', 'pix'. See :ref:`units`
227
+ for explanation of options.
228
+ screen : int
229
+ Specifies the physical screen that stimuli will appear on ('pyglet'
230
+ and 'glfw' `winType` only). Values can be >0 if more than one screen
231
+ is present.
232
+ viewScale : array-like of float or None
233
+ Scaling factors [x, y] to apply custom scaling to the current units
234
+ of the :class:`~psychopy.visual.Window` instance.
235
+ viewPos : array-like of float or None
236
+ If not `None`, redefines the origin within the window, in the units
237
+ of the window. Values outside the borders will be clamped to lie on
238
+ the border.
239
+ viewOri : float
240
+ A single value determining the orientation of the view in degrees.
241
+ waitBlanking : bool or None
242
+ After a call to :py:attr:`~Window.flip()` should we wait for the
243
+ blank before the script continues.
244
+ bitsMode : bool
245
+ DEPRECATED in 1.80.02. Use BitsSharp class from pycrsltd
246
+ instead.
247
+ checkTiming : bool
248
+ Whether to calculate frame duration on initialization. Estimated
249
+ duration is saved in :py:attr:`~Window.monitorFramePeriod`. The
250
+ message displayed on the screen can be set with the `infoMsg`
251
+ argument.
252
+ allowStencil : bool
253
+ When set to `True`, this allows operations that use the OpenGL
254
+ stencil buffer (notably, allowing the
255
+ :class:`~psychopy.visual.Aperture` to be used).
256
+ multiSample : bool
257
+ If `True` and your graphics driver supports multisample buffers,
258
+ multiple color samples will be taken per-pixel, providing an
259
+ anti-aliased image through spatial filtering. This setting cannot
260
+ be changed after opening a window. Only works with 'pyglet' and
261
+ 'glfw' `winTypes`, and `useFBO` is `False`.
262
+ numSamples : int
263
+ A single value specifying the number of samples per pixel if
264
+ multisample is enabled. The higher the number, the better the
265
+ image quality, but can delay frame flipping. The largest number of
266
+ samples is determined by ``GL_MAX_SAMPLES``, usually 16 or 32 on
267
+ newer hardware, will crash if number is invalid.
268
+ stereo : bool
269
+ If `True` and your graphics card supports quad buffers then
270
+ this will be enabled. You can switch between left and right-eye
271
+ scenes for drawing operations using
272
+ :py:attr:`~psychopy.visual.Window.setBuffer()`.
273
+ title : str
274
+ Name of the Window according to your Operating System. This is
275
+ the text which appears on the title sash.
276
+ useRetina : bool
277
+ In PsychoPy >1.85.3 this should always be `True` as pyglet
278
+ (or Apple) no longer allows us to create a non-retina display.
279
+ NB when you use Retina display the initial win size
280
+ request will be in the larger pixels but subsequent use of
281
+ ``units='pix'`` should refer to the tiny Retina pixels. Window.size
282
+ will give the actual size of the screen in Retina pixels.
283
+ gammaErrorPolicy: str
284
+ If `raise`, an error is raised if the gamma table is unable to be
285
+ retrieved or set. If `warn`, a warning is raised instead. If
286
+ `ignore`, neither an error nor a warning are raised.
287
+ bpc : array_like or int
288
+ Bits per color (BPC) for the back buffer as a tuple to specify
289
+ bit depths for each color channel separately (red, green, blue), or
290
+ a single value to set all of them to the same value. Valid values
291
+ depend on the output color depth of the display (screen) the window
292
+ is set to use and the system graphics configuration. By default, it
293
+ is assumed the display has 8-bits per color (8, 8, 8). Behaviour may
294
+ be undefined for non-fullscreen windows, or if multiple screens are
295
+ attached with varying color output depths.
296
+ depthBits : int
297
+ Back buffer depth bits. Default is 8, but can be set higher (eg. 24)
298
+ if drawing 3D stimuli to minimize artifacts such a 'Z-fighting'.
299
+ stencilBits : int
300
+ Back buffer stencil bits. Default is 8.
301
+ backendConf : dict or None
302
+ Additional options to pass to the backend specified by `winType`.
303
+ Each backend may provide unique functionality which may not be
304
+ available across all of them. This allows you to pass special
305
+ configuration options to a specific backend to configure the
306
+ feature.
307
+ infoMsg : str or None
308
+ Message to display during frame rate measurement (i.e., when
309
+ ``checkTiming=True``). Default is None, which means that a default
310
+ message is displayed. If you want to hide the message, pass an
311
+ empty string.
312
+
313
+ Notes
314
+ -----
315
+ * Some parameters (e.g. units) can now be given default values in the
316
+ user/site preferences and these will be used if `None` is given here.
317
+ If you do specify a value here it will take precedence over
318
+ preferences.
319
+
320
+ Attributes
321
+ ----------
322
+ size : array-like (float)
323
+ Dimensions of the window's drawing area/buffer in pixels [w, h].
324
+ monitorFramePeriod : float
325
+ Refresh rate of the display if ``checkTiming=True`` on window
326
+ instantiation.
327
+
328
+ """
329
+ # what local vars are defined (these are the init params) for use by
330
+ # __repr__
331
+ self._initParams = dir()
332
+ self._closed = False
333
+ self.backend = None # this will be set later
334
+ for unecess in ['self', 'checkTiming', 'rgb', 'dkl', ]:
335
+ self._initParams.remove(unecess)
336
+
337
+ # Check autoLog value
338
+ if autoLog not in (True, False):
339
+ raise ValueError(
340
+ 'autoLog must be either True or False for visual.Window')
341
+
342
+ self.autoLog = False # to suppress log msg during init
343
+ self.name = name
344
+ self.clientSize = numpy.array(size, int) # size of window, not buffer
345
+ # size of the window when restored (not fullscreen)
346
+ self._windowedSize = self.clientSize.copy()
347
+
348
+ self.pos = pos
349
+ # this will get overridden once the window is created
350
+ self.winHandle = None
351
+ self.useFBO = useFBO
352
+ self.useRetina = useRetina and sys.platform == 'darwin'
353
+
354
+ if gammaErrorPolicy not in ['raise', 'warn', 'ignore']:
355
+ raise ValueError('Unexpected `gammaErrorPolicy`')
356
+ self.gammaErrorPolicy = gammaErrorPolicy
357
+
358
+ self._toLog = []
359
+ self._toCall = []
360
+ # settings for the monitor: local settings (if available) override
361
+ # monitor
362
+ # if we have a monitors.Monitor object (psychopy 0.54 onwards)
363
+ # convert to a Monitor object
364
+ if not monitor:
365
+ self.monitor = monitors.Monitor('__blank__', autoLog=autoLog)
366
+ elif isinstance(monitor, str):
367
+ self.monitor = monitors.Monitor(monitor, autoLog=autoLog)
368
+ elif hasattr(monitor, 'keys'):
369
+ # convert into a monitor object
370
+ self.monitor = monitors.Monitor('temp', currentCalib=monitor,
371
+ verbose=False, autoLog=autoLog)
372
+ else:
373
+ self.monitor = monitor
374
+
375
+ # otherwise monitor will just be a dict
376
+ self.scrWidthCM = self.monitor.getWidth()
377
+ self.scrDistCM = self.monitor.getDistance()
378
+
379
+ scrSize = self.monitor.getSizePix()
380
+ if scrSize is None:
381
+ self.scrWidthPIX = None
382
+ else:
383
+ self.scrWidthPIX = scrSize[0]
384
+
385
+ # if fullscreen not specified, get from prefs
386
+ if fullscr is None:
387
+ fullscr = prefs.general['fullscr']
388
+ self._isFullScr = fullscr
389
+
390
+ self.units = units
391
+
392
+ if allowGUI is None:
393
+ allowGUI = prefs.general['allowGUI']
394
+ self.allowGUI = allowGUI
395
+
396
+ self.screen = screen
397
+ self.stereo = stereo # use quad buffer if requested (and if possible)
398
+
399
+ # enable multisampling
400
+ self.multiSample = multiSample
401
+ self.numSamples = numSamples
402
+
403
+ # load color conversion matrices
404
+ self.dkl_rgb = self.monitor.getDKL_RGB()
405
+ self.lms_rgb = self.monitor.getLMS_RGB()
406
+
407
+ # set screen color
408
+ self.__dict__['colorSpace'] = colorSpace
409
+ if rgb is not None:
410
+ logging.warning("Use of rgb arguments to stimuli are deprecated. "
411
+ "Please use color and colorSpace args instead")
412
+ color = rgb
413
+ colorSpace = 'rgb'
414
+ elif dkl is not None:
415
+ logging.warning("Use of dkl arguments to stimuli are deprecated. "
416
+ "Please use color and colorSpace args instead")
417
+ color = dkl
418
+ colorSpace = 'dkl'
419
+ elif lms is not None:
420
+ logging.warning("Use of lms arguments to stimuli are deprecated. "
421
+ "Please use color and colorSpace args instead")
422
+ color = lms
423
+ colorSpace = 'lms'
424
+ self.setColor(color, colorSpace=colorSpace, log=False)
425
+
426
+ self.allowStencil = allowStencil
427
+ # check whether FBOs are supported
428
+ if blendMode == 'add' and not self.useFBO:
429
+ logging.warning('User requested a blendmode of "add" but '
430
+ 'window requires useFBO=True')
431
+ # resort to the simpler blending without float rendering
432
+ self.__dict__['blendMode'] = 'avg'
433
+ else:
434
+ self.__dict__['blendMode'] = blendMode
435
+ # then set up gl context and then call self.setBlendMode
436
+
437
+ # setup context and openGL()
438
+ if winType is None: # choose the default windowing
439
+ winType = "pyglet"
440
+ self.winType = winType
441
+
442
+ # setup the context
443
+
444
+ # backend specific options are passed as a dictionary
445
+ backendConf = backendConf if backendConf is not None else {}
446
+
447
+ # Here we make sure all the open windows use the same `winType` and have
448
+ # context sharing enabled. The context to share is passed as an option
449
+ # to `backendConf`.
450
+ if openWindows:
451
+ primaryWindow = openWindows[0]() # resolve ref
452
+ if primaryWindow.winType != self.winType:
453
+ raise ValueError(
454
+ "Only one kind of `winType` can be used per session.")
455
+
456
+ # Allow for context sharing, only used by the GLFW backend, Pyglet
457
+ # uses `shadow_window` by default here so we don't need to worry
458
+ # about it.
459
+ backendConf['share'] = self
460
+
461
+ if not isinstance(backendConf, dict): # type check on options
462
+ raise TypeError(
463
+ 'Object passed to `backendConf` must be type `dict`.')
464
+
465
+ # augment settings with dedicated attributes
466
+ backendConf['bpc'] = bpc
467
+ backendConf['depthBits'] = depthBits
468
+ backendConf['stencilBits'] = stencilBits
469
+
470
+ # get the backend, pass the options to it
471
+ self.backend = backends.getBackend(win=self, backendConf=backendConf)
472
+
473
+ self.winHandle = self.backend.winHandle
474
+ global GL
475
+ GL = self.backend.GL
476
+
477
+ # check whether shaders are supported
478
+ # also will need to check for ARB_float extension,
479
+ # but that should be done after context is created
480
+ self._haveShaders = self.backend.shadersSupported
481
+
482
+ self._setupGL()
483
+
484
+ self.blendMode = self.blendMode
485
+
486
+ # now that we have a window handle, set title
487
+ self.title = title
488
+
489
+ # parameters for transforming the overall view
490
+ self.viewScale = val2array(viewScale)
491
+ if viewPos is not None and self.units is None:
492
+ raise ValueError('You must define the window units to use viewPos')
493
+ self.viewPos = val2array(viewPos, withScalar=False)
494
+ self.viewOri = float(viewOri)
495
+ if self.viewOri != 0. and self.viewPos is not None:
496
+ msg = "Window: viewPos & viewOri are currently incompatible"
497
+ raise NotImplementedError(msg)
498
+
499
+ # scaling factor for HiDPI displays, `None` until initialized
500
+ self._contentScaleFactor = None
501
+
502
+ # Code to allow iohub to know id of any psychopy windows created
503
+ # so kb and mouse event filtering by window id can be supported.
504
+ #
505
+ # If an iohubConnection is active, give this window os handle to
506
+ # to the ioHub server. If windows were already created before the
507
+ # iohub was active, also send them to iohub.
508
+ #
509
+ if IOHUB_ACTIVE:
510
+ from psychopy.iohub.client import ioHubConnection as ioconn
511
+ if ioconn.ACTIVE_CONNECTION:
512
+ from psychopy.iohub.client import windowInfoDict
513
+ win_infos = []
514
+ win_handles = []
515
+ for w in openWindows:
516
+ winfo = windowInfoDict(w())
517
+ win_infos.append(winfo)
518
+ win_handles.append(w()._hw_handle)
519
+
520
+ if self._hw_handle not in win_handles:
521
+ winfo = windowInfoDict(self)
522
+ win_infos.append(winfo)
523
+ win_handles.append(self._hw_handle)
524
+ ioconn.ACTIVE_CONNECTION.registerWindowHandles(*win_infos)
525
+ self.backend.onMoveCallback = ioconn.ACTIVE_CONNECTION.updateWindowPos
526
+
527
+ # near and far clipping planes
528
+ self._nearClip = 0.1
529
+ self._farClip = 100.0
530
+
531
+ # 3D rendering related attributes
532
+ self.frontFace = 'ccw'
533
+ self.depthFunc = 'less'
534
+ self.depthMask = False
535
+ self.cullFace = False
536
+ self.cullFaceMode = 'back'
537
+ self.draw3d = False
538
+
539
+ # gl viewport and scissor
540
+ self._viewport = self._scissor = None # set later
541
+
542
+ self._fboVerts = numpy.ascontiguousarray(
543
+ [[-1, -1], [-1, 1], [1, 1], [1, -1]], dtype=numpy.float32)
544
+ self._fboTexCoords = numpy.ascontiguousarray(
545
+ [[0, 0], [0, 1], [1, 1], [1, 0]], dtype=numpy.float32)
546
+
547
+ # scene light sources
548
+ self._lights = []
549
+ self._useLights = False
550
+ self._nLights = 0
551
+ self._ambientLight = numpy.array([0.0, 0.0, 0.0, 1.0],
552
+ dtype=numpy.float32)
553
+
554
+ # stereo rendering settings, set later by the user
555
+ self._eyeOffset = 0.0
556
+ self._convergeOffset = 0.0
557
+
558
+ # gamma
559
+ self.bits = None # this may change in a few lines time!
560
+ self.__dict__['gamma'] = gamma
561
+ self._setupGamma(gamma)
562
+
563
+ # setup bits++ if needed. NB The new preferred method is for this
564
+ # to be handled by the bits class instead. (we pass the Window to
565
+ # bits not passing bits to the window)
566
+ if bitsMode is not None:
567
+ logging.warn("Use of Window(bitsMode=******) is deprecated. See "
568
+ "the Coder>Demos>Hardware demo for new methods")
569
+ self.bitsMode = bitsMode # could be [None, 'fast', 'slow']
570
+ logging.warn("calling Window(...,bitsMode='fast') is deprecated."
571
+ " XXX provide further info")
572
+ from psychopy.hardware.crs.bits import BitsPlusPlus
573
+ self.bits = self.interface = BitsPlusPlus(self)
574
+ self.haveBits = True
575
+ if (hasattr(self.monitor, 'linearizeLums') or
576
+ hasattr(self.monitor, 'lineariseLums')):
577
+ # rather than a gamma value we could use bits++ and provide a
578
+ # complete linearised lookup table using
579
+ # monitor.linearizeLums(lumLevels)
580
+ self.__dict__['gamma'] = None
581
+
582
+ self.frameClock = core.Clock() # from psycho/core
583
+ self.frames = 0 # frames since last fps calc
584
+ self.movieFrames = [] # list of captured frames (Image objects)
585
+
586
+ self.recordFrameIntervals = False
587
+ # Be able to omit the long timegap that follows each time turn it off
588
+ self.recordFrameIntervalsJustTurnedOn = False
589
+ self.nDroppedFrames = 0
590
+ self.frameIntervals = []
591
+ self._frameTimes = deque(maxlen=1000) # 1000 keeps overhead low
592
+
593
+ self._toDraw = []
594
+ self._heldDraw = []
595
+ self._toDrawDepths = []
596
+ self._eventDispatchers = []
597
+
598
+ # dict of stimulus:validator pairs
599
+ self.validators = {}
600
+
601
+ self.lastFrameT = core.getTime()
602
+ self.waitBlanking = waitBlanking
603
+
604
+ # set the swap interval if using GLFW
605
+ if self.winType == 'glfw':
606
+ self.backend.setSwapInterval(int(waitBlanking))
607
+
608
+ self.refreshThreshold = 1.0 # initial val needed by flip()
609
+
610
+ # store editable stimuli
611
+ self._editableChildren = []
612
+ self._currentEditableRef = None
613
+ # store draggable stimuli
614
+ self.currentDraggable = None
615
+
616
+ # splash screen
617
+ self._splashTextbox = None # created on first use
618
+ self._showSplash = False
619
+ self.resetViewport() # set viewport to full window size
620
+
621
+ # transformation
622
+ self._projectionMatrix = numpy.identity(4, dtype=numpy.float32)
623
+ self._viewMatrix = numpy.identity(4, dtype=numpy.float32)
624
+
625
+ self._projectionMatrixNeedsUpdate = True
626
+ self._viewMatrixNeedsUpdate = True
627
+
628
+ self.setDefaultView() # initialize view/proj matrix
629
+
630
+ # piloting indicator
631
+ self._pilotingIndicator = None
632
+ self._showPilotingIndicator = False
633
+
634
+ # over several frames with no drawing
635
+ self._monitorFrameRate = None
636
+ # for testing when to stop drawing a stim:
637
+ self.monitorFramePeriod = 0.0
638
+ if checkTiming:
639
+ self._monitorFrameRate = self.getActualFrameRate(infoMsg=infoMsg)
640
+
641
+ if self._monitorFrameRate is not None:
642
+ self.monitorFramePeriod = 1.0 / self._monitorFrameRate
643
+ else:
644
+ self.monitorFramePeriod = 1.0 / 60 # assume a flat panel?
645
+ self.refreshThreshold = self.monitorFramePeriod * 1.2
646
+ openWindows.append(self)
647
+
648
+ self.autoLog = autoLog
649
+ if self.autoLog:
650
+ logging.exp("Created %s = %s" % (self.name, str(self)))
651
+
652
+ # Make sure this window's close method is called when exiting, even in
653
+ # the event of an error we should be able to restore the original gamma
654
+ # table. Note that a reference to this window object will live in this
655
+ # function, preventing it from being garbage collected.
656
+ def close_on_exit():
657
+ if self._closed is False:
658
+ self.close()
659
+
660
+ atexit.register(close_on_exit)
661
+
662
+ self._mouse = event.Mouse(win=self)
663
+ self.backgroundImage = backgroundImage
664
+ self.backgroundFit = backgroundFit
665
+ if hasattr(self.backgroundImage, "draw"):
666
+ self.backgroundImage.draw()
667
+
668
+ def __del__(self):
669
+ if self._closed is False:
670
+ self.close()
671
+
672
+ def __enter__(self):
673
+ return self
674
+
675
+ def __exit__(self, exc_type, exc_value, traceback):
676
+ if not self._closed:
677
+ self.close()
678
+
679
+ def __str__(self):
680
+ className = 'Window'
681
+ paramStrings = []
682
+ for param in self._initParams:
683
+ if hasattr(self, param):
684
+ paramStrings.append("%s=%s" %
685
+ (param, repr(getattr(self, param))))
686
+ else:
687
+ paramStrings.append("%s=UNKNOWN" % (param))
688
+ # paramStrings = ["%s=%s" %(param, getattr(self, param))
689
+ # for param in self._initParams]
690
+ params = ", ".join(paramStrings)
691
+ s = "%s(%s)" % (className, params)
692
+ return s
693
+
694
+ @attributeSetter
695
+ def title(self, value):
696
+ self.__dict__['title'] = value
697
+ if hasattr(self.winHandle, "set_caption"):
698
+ # Pyglet backend
699
+ self.winHandle.set_caption(value)
700
+ elif hasattr(self.winHandle, "SetWindowTitle"):
701
+ # GLFW backend
702
+ self.winHandle.SetWindowTitle(value)
703
+ else:
704
+ # Unknown backend
705
+ logging.warning(f"Cannot set Window title in backend {self.winType}")
706
+
707
+ @attributeSetter
708
+ def units(self, value):
709
+ """*None*, 'height' (of the window), 'norm', 'deg', 'cm', 'pix'
710
+ Defines the default units of stimuli initialized in the window.
711
+ I.e. if you change units, already initialized stimuli won't change
712
+ their units.
713
+
714
+ Can be overridden by each stimulus, if units is specified on
715
+ initialization.
716
+
717
+ See :ref:`units` for explanation of options.
718
+
719
+ """
720
+ if value is None:
721
+ value = prefs.general['units']
722
+ self.__dict__['units'] = value
723
+
724
+ def setUnits(self, value, log=True):
725
+ setAttribute(self, 'units', value, log=log)
726
+
727
+ @attributeSetter
728
+ def viewPos(self, value):
729
+ """The origin of the window onto which stimulus-objects are drawn.
730
+
731
+ The value should be given in the units defined for the window. NB:
732
+ Never change a single component (x or y) of the origin, instead replace
733
+ the viewPos-attribute in one shot, e.g.::
734
+
735
+ win.viewPos = [new_xval, new_yval] # This is the way to do it
736
+ win.viewPos[0] = new_xval # DO NOT DO THIS! Errors will result.
737
+
738
+ """
739
+ self.__dict__['viewPos'] = value
740
+ if value is not None:
741
+ # let setter take care of normalisation
742
+ setattr(self, '_viewPosNorm', value)
743
+
744
+ @attributeSetter
745
+ def _viewPosNorm(self, value):
746
+ """Normalised value of viewPos, hidden from user view."""
747
+ # first convert to pixels, then normalise to window units
748
+ viewPos_pix = convertToPix([0, 0], list(value),
749
+ units=self.units, win=self)[:2]
750
+ viewPos_norm = viewPos_pix / (self.size / 2.0)
751
+ # Clip to +/- 1; should going out-of-window raise an exception?
752
+ viewPos_norm = numpy.clip(viewPos_norm, a_min=-1., a_max=1.)
753
+ self._viewMatrixNeedsUpdate = True
754
+ self.__dict__['_viewPosNorm'] = viewPos_norm
755
+
756
+ def setViewPos(self, value, log=True):
757
+ setAttribute(self, 'viewPos', value, log=log)
758
+
759
+ @attributeSetter
760
+ def viewOri(self, value):
761
+ """Set the rotation of the view in degrees.
762
+
763
+ The rotation is applied around the origin of the window, which is
764
+ defined by the viewPos attribute. The rotation is applied after scaling
765
+ but before translation.
766
+
767
+ """
768
+ self.__dict__['viewOri'] = value
769
+ self._viewMatrixNeedsUpdate = True
770
+
771
+ def setViewOri(self, value, log=True):
772
+ setAttribute(self, 'viewOri', value, log=log)
773
+
774
+ @attributeSetter
775
+ def viewScale(self, value):
776
+ """Set the scale factors for the view.
777
+
778
+ The scaling is applied around the origin of the window, which is defined
779
+ by the viewPos attribute. The scaling is applied before translation and
780
+ rotation.
781
+
782
+ """
783
+ self.__dict__['viewScale'] = value
784
+ self._viewMatrixNeedsUpdate = True
785
+
786
+ def setViewScale(self, value, log=True):
787
+ setAttribute(self, 'viewScale', value, log=log)
788
+
789
+ def _updateViewMatrix(self):
790
+ """Update the default orthographic view matrix based on the current
791
+ window settings.
792
+ """
793
+ if self._viewMatrixNeedsUpdate:
794
+ if self.viewScale is None:
795
+ sx, sy = [1.0, 1.0]
796
+ else:
797
+ sx, sy = self.viewScale
798
+
799
+ if self.viewOri is None:
800
+ viewOri = 0.0
801
+ else:
802
+ viewOri = self.viewOri
803
+
804
+ if self.viewPos is None:
805
+ tx, ty = [0.0, 0.0]
806
+ else:
807
+ tx, ty = self.viewPos
808
+
809
+ scaleMatrix = mathtools.scaleMatrix([sx, sy, 1.0])
810
+ rotateMatrix = mathtools.rotationMatrix(viewOri, axis='-z')
811
+ translateMatrix = mathtools.translationMatrix([tx, ty, 0.0])
812
+
813
+ # compute SRT matrix
814
+ self._viewMatrix[:, :] = mathtools.multMatrix([
815
+ translateMatrix,
816
+ rotateMatrix,
817
+ scaleMatrix])
818
+ self._viewMatrixNeedsUpdate = False
819
+
820
+ def _updateProjectionMatrix(self):
821
+ """Update the default projection matrix based on the current window
822
+ settings.
823
+ """
824
+ if self._projectionMatrixNeedsUpdate:
825
+ # widthOver2 = self.size[0] / 2.0
826
+ # heightOver2 = self.size[1] / 2.0
827
+ # self._projectionMatrix[:, :] = viewtools.orthoProjectionMatrix(
828
+ # -widthOver2, widthOver2, # -X, +X
829
+ # -heightOver2, heightOver2, # -Y, +Y
830
+ # -1.0, 1.0, # -Z, +Z
831
+ # dtype=numpy.float32)
832
+ self._projectionMatrix[:, :] = numpy.identity(4, dtype=numpy.float32)
833
+ self._projectionMatrixNeedsUpdate = False
834
+
835
+ @property
836
+ def fullscr(self):
837
+ """Return whether the window is in fullscreen mode."""
838
+ return self._isFullScr
839
+
840
+ @fullscr.setter
841
+ def fullscr(self, value):
842
+ """Set whether fullscreen mode is `True` or `False` (not all backends
843
+ can toggle an open window).
844
+ """
845
+ self.backend.setFullScr(value)
846
+ self._isFullScr = value
847
+
848
+ @attributeSetter
849
+ def waitBlanking(self, value):
850
+ """After a call to :py:attr:`~Window.flip()` should we wait for the
851
+ blank before the script continues.
852
+
853
+ """
854
+ self.__dict__['waitBlanking'] = value
855
+
856
+ @attributeSetter
857
+ def recordFrameIntervals(self, value):
858
+ """Record time elapsed per frame.
859
+
860
+ Provides accurate measures of frame intervals to determine
861
+ whether frames are being dropped. The intervals are the times between
862
+ calls to :py:attr:`~Window.flip()`. Set to `True` only during the
863
+ time-critical parts of the script. Set this to `False` while the screen
864
+ is not being updated, i.e., during any slow, non-frame-time-critical
865
+ sections of your code, including inter-trial-intervals,
866
+ ``event.waitkeys()``, ``core.wait()``, or ``image.setImage()``.
867
+
868
+ Examples
869
+ --------
870
+ Enable frame interval recording, successive frame intervals will be
871
+ stored::
872
+
873
+ win.recordFrameIntervals = True
874
+
875
+ Frame intervals can be saved by calling the
876
+ :py:attr:`~Window.saveFrameIntervals` method::
877
+
878
+ win.saveFrameIntervals()
879
+
880
+ """
881
+ # was off, and now turning it on
882
+ self.recordFrameIntervalsJustTurnedOn = bool(
883
+ not self.recordFrameIntervals and value)
884
+ self.__dict__['recordFrameIntervals'] = value
885
+ self.frameClock.reset()
886
+
887
+ def setRecordFrameIntervals(self, value=True, log=None):
888
+ """Usually you can use 'stim.attribute = value' syntax instead,
889
+ but use this method if you need to suppress the log message.
890
+ """
891
+ setAttribute(self, 'recordFrameIntervals', value, log)
892
+
893
+ def saveFrameIntervals(self, fileName=None, clear=True):
894
+ """Save recorded screen frame intervals to disk, as comma-separated
895
+ values.
896
+
897
+ Parameters
898
+ ----------
899
+ fileName : *None* or str
900
+ *None* or the filename (including path if necessary) in which to
901
+ store the data. If None then 'lastFrameIntervals.log' will be used.
902
+ clear : bool
903
+ Clear buffer frames intervals were stored after saving. Default is
904
+ `True`.
905
+
906
+ """
907
+ if not fileName:
908
+ fileName = 'lastFrameIntervals.log'
909
+ if len(self.frameIntervals):
910
+ intervalStr = str(self.frameIntervals)[1:-1]
911
+ f = open(fileName, 'w')
912
+ f.write(intervalStr)
913
+ f.close()
914
+ if clear:
915
+ self.frameIntervals = []
916
+ self.frameClock.reset()
917
+
918
+ def _setCurrent(self):
919
+ """Make this window's OpenGL context current.
920
+
921
+ If called on a window whose context is current, the function will return
922
+ immediately. This reduces the number of redundant calls if no context
923
+ switch is required. If ``useFBO=True``, the framebuffer is bound after
924
+ the context switch.
925
+
926
+ """
927
+ # don't configure if we haven't changed context
928
+ if not self.backend.setCurrent():
929
+ return
930
+
931
+ # if we are using an FBO, bind it
932
+ if hasattr(self, 'frameBuffer'):
933
+ GL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER,
934
+ self.frameBuffer)
935
+ GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0)
936
+ GL.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0)
937
+
938
+ # NB - check if we need these
939
+ GL.glActiveTexture(GL.GL_TEXTURE0)
940
+ GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
941
+
942
+ # set these to match the current window or buffer's settings
943
+ fbw, fbh = self.frameBufferSize
944
+ self.viewport = self.scissor = [0, 0, fbw, fbh]
945
+ self.scissorTest = True
946
+
947
+ # apply the view transforms for this window
948
+ #self.applyEyeTransform()
949
+
950
+ def onResize(self, width, height):
951
+ """A default resize event handler.
952
+
953
+ This default handler updates the GL viewport to cover the entire
954
+ window and sets the ``GL_PROJECTION`` matrix to be orthogonal in
955
+ window space. The bottom-left corner is (0, 0) and the top-right
956
+ corner is the width and height of the :class:`~psychopy.visual.Window`
957
+ in pixels.
958
+
959
+ Override this event handler with your own to create another
960
+ projection, for example in perspective.
961
+ """
962
+ # this has to be external so that pyglet can use it too without
963
+ # circular referencing
964
+ self.backend.onResize(width, height)
965
+
966
+ def logOnFlip(self, msg, level, obj=None):
967
+ """Send a log message that should be time-stamped at the next
968
+ :py:attr:`~Window.flip()` command.
969
+
970
+ Parameters
971
+ ----------
972
+ msg : str
973
+ The message to be logged.
974
+ level : int
975
+ The level of importance for the message.
976
+ obj : object, optional
977
+ The python object that might be associated with this message if
978
+ desired.
979
+
980
+ """
981
+ self._toLog.append({'msg': msg, 'level': level, 'obj': repr(obj)})
982
+
983
+ def callOnFlip(self, function, *args, **kwargs):
984
+ """Call a function immediately after the next :py:attr:`~Window.flip()`
985
+ command.
986
+
987
+ The first argument should be the function to call, the following args
988
+ should be used exactly as you would for your normal call to the
989
+ function (can use ordered arguments or keyword arguments as normal).
990
+
991
+ e.g. If you have a function that you would normally call like this::
992
+
993
+ pingMyDevice(portToPing, channel=2, level=0)
994
+
995
+ then you could call :py:attr:`~Window.callOnFlip()` to have the function
996
+ call synchronized with the frame flip like this::
997
+
998
+ win.callOnFlip(pingMyDevice, portToPing, channel=2, level=0)
999
+
1000
+ """
1001
+ self._toCall.append({'function': function,
1002
+ 'args': args,
1003
+ 'kwargs': kwargs})
1004
+
1005
+ def timeOnFlip(self, obj, attrib, format=float):
1006
+ """Retrieves the time on the next flip and assigns it to the `attrib`
1007
+ for this `obj`.
1008
+
1009
+ Parameters
1010
+ ----------
1011
+ obj : dict or object
1012
+ A mutable object (usually a dict of class instance).
1013
+ attrib : str
1014
+ Key or attribute of `obj` to assign the flip time to.
1015
+ format : str, class or None
1016
+ Format in which to return time, see clock.Timestamp.resolve() for more info. Defaults to `float`.
1017
+
1018
+ Examples
1019
+ --------
1020
+ Assign time on flip to the ``tStartRefresh`` key of ``myTimingDict``::
1021
+
1022
+ win.getTimeOnFlip(myTimingDict, 'tStartRefresh')
1023
+
1024
+ """
1025
+ self.callOnFlip(self._assignFlipTime, obj, attrib, format)
1026
+
1027
+ def getFutureFlipTime(self, targetTime=0, clock=None):
1028
+ """The expected time of the next screen refresh. This is currently
1029
+ calculated as win._lastFrameTime + refreshInterval
1030
+
1031
+ Parameters
1032
+ -----------
1033
+ targetTime: float
1034
+ The delay *from now* for which you want the flip time. 0 will give the
1035
+ because that the earliest we can achieve. 0.15 will give the schedule
1036
+ flip time that gets as close to 150 ms as possible
1037
+ clock : None, 'ptb', 'now' or any Clock object
1038
+ If True then the time returned is compatible with ptb.GetSecs()
1039
+ verbose: bool
1040
+ Set to True to view the calculations along the way
1041
+ """
1042
+ baseClock = logging.defaultClock
1043
+ if not self.monitorFramePeriod:
1044
+ raise AttributeError("Cannot calculate nextFlipTime due to unknown "
1045
+ "monitorFramePeriod")
1046
+ lastFlip = self._frameTimes[-1] # unlike win.lastFrameTime this is always on
1047
+ timeNext = lastFlip + self.monitorFramePeriod
1048
+ now = baseClock.getTime()
1049
+ if (now + targetTime) > timeNext: # target is more than 1 frame in future
1050
+ extraFrames = math.ceil((now + targetTime - timeNext)/self.monitorFramePeriod)
1051
+ thisT = timeNext + extraFrames*self.monitorFramePeriod
1052
+ else:
1053
+ thisT = timeNext
1054
+ # convert back to target clock timebase
1055
+ if clock=='ptb': # add back the lastResetTime (that's the clock difference)
1056
+ output = thisT + baseClock.getLastResetTime()
1057
+ elif clock=='now': # time from now is easy!
1058
+ output = thisT - now
1059
+ elif clock:
1060
+ output = thisT + baseClock.getLastResetTime() - clock.getLastResetTime()
1061
+ else:
1062
+ output = thisT
1063
+
1064
+ return output
1065
+
1066
+ def _assignFlipTime(self, obj, attrib, format=float):
1067
+ """Helper function to assign the time of last flip to the obj.attrib
1068
+
1069
+ Parameters
1070
+ ----------
1071
+ obj : dict or object
1072
+ A mutable object (usually a dict of class instance).
1073
+ attrib : str
1074
+ Key or attribute of ``obj`` to assign the flip time to.
1075
+ format : str, class or None
1076
+ Format in which to return time, see clock.Timestamp.resolve() for more info. Defaults to `float`.
1077
+
1078
+ """
1079
+ frameTime = self._frameTime.resolve(format=format)
1080
+ if hasattr(obj, attrib):
1081
+ setattr(obj, attrib, frameTime)
1082
+ elif isinstance(obj, dict):
1083
+ obj[attrib] = frameTime
1084
+ else:
1085
+ raise TypeError("Window.getTimeOnFlip() should be called with an "
1086
+ "object and its attribute or a dict and its key. "
1087
+ "In this case it was called with obj={}"
1088
+ .format(repr(obj)))
1089
+
1090
+ def _cleanEditables(self):
1091
+ """
1092
+ Make sure there are no dead refs in the editables list
1093
+ """
1094
+ for ref in self._editableChildren:
1095
+ obj = ref()
1096
+ if obj is None:
1097
+ self._editableChildren.remove(ref)
1098
+
1099
+ @property
1100
+ def currentEditable(self):
1101
+ """The editable (Text?) object that currently has key focus"""
1102
+ if self._currentEditableRef:
1103
+ return self._currentEditableRef()
1104
+
1105
+ @currentEditable.setter
1106
+ def currentEditable(self, editable):
1107
+ """Keeps the current editable stored as a weak ref"""
1108
+ # Ensure that item is added to editables list
1109
+ self.addEditable(editable)
1110
+
1111
+ # Set the editable as the current editable stim in the window
1112
+ eRef = None
1113
+ for ref in weakref.getweakrefs(editable):
1114
+ if ref in self._editableChildren:
1115
+ eRef = ref
1116
+ break
1117
+ if eRef:
1118
+ self._currentEditableRef = eRef
1119
+
1120
+ def addEditable(self, editable):
1121
+ """Adds an editable element to the screen (something to which
1122
+ characters can be sent with meaning from the keyboard).
1123
+
1124
+ The current editable object receiving chars is Window.currentEditable
1125
+
1126
+ :param editable:
1127
+ :return:
1128
+ """
1129
+ # Ignore if object is not editable
1130
+ if not hasattr(editable, "editable"):
1131
+ return
1132
+ if not editable.editable:
1133
+ return
1134
+ # If editable is already present do nothing
1135
+ eRef = False
1136
+ for ref in weakref.getweakrefs(editable):
1137
+ if ref in self._editableChildren:
1138
+ eRef = ref
1139
+ break
1140
+
1141
+ if eRef is False:
1142
+ eRef = weakref.ref(editable)
1143
+ # If editable is not already present, add it to the editables list
1144
+ self._editableChildren.append(eRef)
1145
+
1146
+ # If this is the first editable obj then make it the current
1147
+ if len(self._editableChildren) == 1:
1148
+ self._currentEditableRef = eRef
1149
+ # Clean editables list
1150
+ self._cleanEditables()
1151
+
1152
+ def removeEditable(self, editable):
1153
+ # If editable is present, remove it from editables list
1154
+ for ref in weakref.getweakrefs(editable):
1155
+ if ref in self._editableChildren:
1156
+ # If editable was current, move on to next current
1157
+ if self.currentEditable == editable:
1158
+ self.nextEditable()
1159
+ self._editableChildren.remove(ref)
1160
+ return True
1161
+ else:
1162
+ logging.warning(f"Request to remove editable object {editable} could not be completed as weakref "
1163
+ f"to this object could not be found in window.")
1164
+ # Clean editables list
1165
+ self._cleanEditables()
1166
+
1167
+ return False
1168
+
1169
+ def nextEditable(self):
1170
+ """Moves focus of the cursor to the next editable window"""
1171
+ # Clean editables list
1172
+ self._cleanEditables()
1173
+ # Progress
1174
+ if self.currentEditable is None:
1175
+ if len(self._editableChildren):
1176
+ self._currentEditableRef = self._editableChildren[0]
1177
+ else:
1178
+ for ref in weakref.getweakrefs(self.currentEditable):
1179
+ if ref in self._editableChildren:
1180
+ cei = self._editableChildren.index(ref)
1181
+ nei = cei+1
1182
+ if nei >= len(self._editableChildren):
1183
+ nei=0
1184
+ self._currentEditableRef = self._editableChildren[nei]
1185
+ return self.currentEditable
1186
+
1187
+ @classmethod
1188
+ def dispatchAllWindowEvents(cls):
1189
+ """
1190
+ Dispatches events for all pyglet windows. Used by iohub 2.0
1191
+ psychopy kb event integration.
1192
+ """
1193
+ Window.backend.dispatchEvents()
1194
+
1195
+ def clearAutoDraw(self):
1196
+ """
1197
+ Remove all autoDraw components, meaning they get autoDraw set to False and are not
1198
+ added to any list (as in .stashAutoDraw)
1199
+ """
1200
+ for thisStim in self._toDraw.copy():
1201
+ # set autoDraw to False
1202
+ thisStim.autoDraw = False
1203
+
1204
+ def stashAutoDraw(self):
1205
+ """
1206
+ Put autoDraw components on 'hold', meaning they get autoDraw set to False but
1207
+ are added to an internal list to be 'released' when .releaseAutoDraw is called.
1208
+ """
1209
+ for thisStim in self._toDraw.copy():
1210
+ # set autoDraw to False
1211
+ thisStim.autoDraw = False
1212
+ # add stim to held list
1213
+ self._heldDraw.append(thisStim)
1214
+
1215
+ def retrieveAutoDraw(self):
1216
+ """
1217
+ Add all stimuli which are on 'hold' back into the autoDraw list, and clear the
1218
+ hold list.
1219
+ """
1220
+ for thisStim in self._heldDraw:
1221
+ # set autoDraw to True
1222
+ thisStim.autoDraw = True
1223
+ # clear list
1224
+ self._heldDraw = []
1225
+
1226
+ def flip(self, clearBuffer=True):
1227
+ """Flip the front and back buffers after drawing everything for your
1228
+ frame. (This replaces the :py:attr:`~Window.update()` method, better
1229
+ reflecting what is happening underneath).
1230
+
1231
+ Parameters
1232
+ ----------
1233
+ clearBuffer : bool, optional
1234
+ Clear the draw buffer after flipping. Default is `True`.
1235
+
1236
+ Returns
1237
+ -------
1238
+ float or None
1239
+ Wall-clock time in seconds the flip completed. Returns `None` if
1240
+ :py:attr:`~Window.waitBlanking` is `False`.
1241
+
1242
+ Notes
1243
+ -----
1244
+ * The time returned when :py:attr:`~Window.waitBlanking` is `True`
1245
+ corresponds to when the graphics driver releases the draw buffer to
1246
+ accept draw commands again. This time is usually close to the vertical
1247
+ sync signal of the display.
1248
+
1249
+ Examples
1250
+ --------
1251
+
1252
+ Results in a clear screen after flipping::
1253
+
1254
+ win.flip(clearBuffer=True)
1255
+
1256
+ The screen is not cleared (so represent the previous screen)::
1257
+
1258
+ win.flip(clearBuffer=False)
1259
+
1260
+ """
1261
+ # draw message/splash if needed
1262
+ if self._showSplash:
1263
+ self._splashTextbox.draw()
1264
+
1265
+ if self._toDraw:
1266
+ for thisStim in self._toDraw:
1267
+ # draw
1268
+ thisStim.draw()
1269
+ # draw validation rect if needed
1270
+ if thisStim in self.validators:
1271
+ self.validators[thisStim].draw()
1272
+ # handle dragging
1273
+ if getattr(thisStim, "draggable", False):
1274
+ thisStim.doDragging()
1275
+
1276
+ if getattr(thisStim, "clickable", False):
1277
+ thisStim.doPointerActions()
1278
+
1279
+ else:
1280
+ self.backend.setCurrent()
1281
+
1282
+ # set these to match the current window or buffer's settings
1283
+ self.viewport = self.scissor = \
1284
+ (0, 0, self.frameBufferSize[0], self.frameBufferSize[1])
1285
+ if not self.scissorTest:
1286
+ self.scissorTest = True
1287
+
1288
+ # clear the projection and modelview matrix for FBO blit
1289
+ # DEPRECATED: these are all removed from OpenGL 3.1
1290
+ if self.USE_LEGACY_GL:
1291
+ GL.glMatrixMode(GL.GL_PROJECTION)
1292
+ GL.glLoadIdentity()
1293
+ GL.glOrtho(-1, 1, -1, 1, -1, 1)
1294
+ GL.glMatrixMode(GL.GL_MODELVIEW)
1295
+ GL.glLoadIdentity()
1296
+
1297
+ # disable lighting
1298
+ self.useLights = False
1299
+
1300
+ # Check for mouse clicks on editables
1301
+ if hasattr(self, '_editableChildren'):
1302
+ # Make sure _editableChildren has actually been created
1303
+ editablesOnScreen = []
1304
+ for thisObj in self._editableChildren:
1305
+ # Iterate through editables and decide which one should have focus
1306
+ if isinstance(thisObj, weakref.ref):
1307
+ # Solidify weakref if necessary
1308
+ thisObj = thisObj()
1309
+ if thisObj is None:
1310
+ continue
1311
+ if isinstance(thisObj.autoDraw, (bool, int, float)):
1312
+ # Store whether this editable is on screen
1313
+ editablesOnScreen.append(thisObj.autoDraw)
1314
+ else:
1315
+ editablesOnScreen.append(False)
1316
+ if self._mouse.isPressedIn(thisObj):
1317
+ # If editable was clicked on, give it focus
1318
+ self.currentEditable = thisObj
1319
+ # If there is only one editable on screen, make sure it starts off with focus
1320
+ if sum(editablesOnScreen) == 1:
1321
+ self.currentEditable = self._editableChildren[editablesOnScreen.index(True)]()
1322
+
1323
+ flipThisFrame = self._startOfFlip()
1324
+ if self.useFBO and flipThisFrame:
1325
+ self.draw3d = False # disable 3d drawing
1326
+ self._prepareFBOrender()
1327
+ # need blit the framebuffer object to the actual back buffer
1328
+
1329
+ # unbind the framebuffer as the render target
1330
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
1331
+ GL.glDisable(GL.GL_BLEND)
1332
+ stencilOn = self.stencilTest
1333
+ self.stencilTest = False
1334
+
1335
+ if self.bits is not None:
1336
+ self.bits._prepareFBOrender()
1337
+
1338
+ # before flipping need to copy the renderBuffer to the
1339
+ # frameBuffer
1340
+ GL.glActiveTexture(GL.GL_TEXTURE0)
1341
+ GL.glEnable(GL.GL_TEXTURE_2D)
1342
+ GL.glBindTexture(GL.GL_TEXTURE_2D, self.frameTexture)
1343
+ if self.USE_LEGACY_GL:
1344
+ GL.glColor3f(1.0, 1.0, 1.0) # glColor multiplies with texture
1345
+
1346
+ GL.glColorMask(True, True, True, True)
1347
+
1348
+ self._renderFBO()
1349
+
1350
+ GL.glEnable(GL.GL_BLEND)
1351
+ self._finishFBOrender()
1352
+
1353
+ # call this before flip() whether FBO was used or not
1354
+ self._afterFBOrender()
1355
+
1356
+ self.backend.swapBuffers(flipThisFrame)
1357
+
1358
+ if self.useFBO and flipThisFrame:
1359
+ # set rendering back to the framebuffer object
1360
+ GL.glBindFramebuffer(
1361
+ GL.GL_FRAMEBUFFER, self.frameBuffer)
1362
+ GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0)
1363
+ GL.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0)
1364
+ # set to no active rendering texture
1365
+ GL.glActiveTexture(GL.GL_TEXTURE0)
1366
+ GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
1367
+ if stencilOn:
1368
+ self.stencilTest = True
1369
+
1370
+ # rescale, reposition, & rotate
1371
+ # DEPRECATED: these are all removed from OpenGL 3.1
1372
+ if self.USE_LEGACY_GL:
1373
+ GL.glMatrixMode(GL.GL_MODELVIEW)
1374
+ GL.glLoadIdentity()
1375
+ if self.viewScale is not None:
1376
+ # DEPRECATED: these are all removed from OpenGL 3.1
1377
+ GL.glScalef(self.viewScale[0], self.viewScale[1], 1)
1378
+
1379
+ absScaleX = abs(self.viewScale[0])
1380
+ absScaleY = abs(self.viewScale[1])
1381
+ else:
1382
+ absScaleX, absScaleY = 1, 1
1383
+
1384
+ if self.viewPos is not None:
1385
+ # here we must use normalised units in _viewPosNorm,
1386
+ # see the corresponding attributeSetter above
1387
+ normRfPosX = self._viewPosNorm[0] / absScaleX
1388
+ normRfPosY = self._viewPosNorm[1] / absScaleY
1389
+
1390
+ # DEPRECATED: these are all removed from OpenGL 3.1
1391
+ GL.glTranslatef(normRfPosX, normRfPosY, 0.0)
1392
+
1393
+ if self.viewOri: # float
1394
+ # the logic below for flip is partially correct, but does not
1395
+ # handle a nonzero viewPos
1396
+ flip = 1
1397
+ if self.viewScale is not None:
1398
+ _f = self.viewScale[0] * self.viewScale[1]
1399
+ if _f < 0:
1400
+ flip = -1
1401
+ # DEPERECATED: these are all removed from OpenGL 3.1
1402
+ GL.glRotatef(flip * self.viewOri, 0.0, 0.0, -1.0)
1403
+
1404
+ # reset returned buffer for next frame
1405
+ self._endOfFlip(clearBuffer)
1406
+
1407
+ # waitBlanking
1408
+ if self.waitBlanking and flipThisFrame:
1409
+ # DEPRECATED: these are all removed from OpenGL 3.1
1410
+ if self.USE_LEGACY_GL:
1411
+ GL.glBegin(GL.GL_POINTS)
1412
+ GL.glColor4f(0, 0, 0, 0)
1413
+ if sys.platform == 'win32' and self.glVendor.startswith('ati'):
1414
+ pass
1415
+ else:
1416
+ # this corrupts text rendering on win with some ATI cards :-(
1417
+ GL.glVertex2i(10, 10)
1418
+ pass
1419
+ GL.glEnd()
1420
+ GL.glFinish()
1421
+
1422
+ # get timestamp
1423
+ self._frameTime = now = logging.defaultClock.getTime()
1424
+ self._frameTimes.append(self._frameTime)
1425
+
1426
+ # run scheduled functions immediately after flip completes
1427
+ n_items = len(self._toCall)
1428
+ for i in range(n_items):
1429
+ self._toCall[i]['function'](*self._toCall[i]['args'], **self._toCall[i]['kwargs'])
1430
+ # leave newly scheduled functions for next flip
1431
+ del self._toCall[:n_items]
1432
+
1433
+ # do bookkeeping
1434
+ if self.recordFrameIntervals:
1435
+ self.frames += 1
1436
+ deltaT = now - self.lastFrameT
1437
+ self.lastFrameT = now
1438
+
1439
+ if self.recordFrameIntervalsJustTurnedOn: # don't do anything
1440
+ self.recordFrameIntervalsJustTurnedOn = False
1441
+ else: # past the first frame since turned on
1442
+ self.frameIntervals.append(deltaT)
1443
+ if deltaT > self.refreshThreshold:
1444
+ self.nDroppedFrames += 1
1445
+ if self.nDroppedFrames < reportNDroppedFrames:
1446
+ txt = 't of last frame was %.2fms (=1/%i)'
1447
+ msg = txt % (deltaT * 1000, 1 / deltaT)
1448
+ logging.warning(msg, t=now)
1449
+ elif self.nDroppedFrames == reportNDroppedFrames:
1450
+ logging.warning("Multiple dropped frames have "
1451
+ "occurred - I'll stop bothering you "
1452
+ "about them!")
1453
+
1454
+ # log events
1455
+ for logEntry in self._toLog:
1456
+ # {'msg':msg, 'level':level, 'obj':copy.copy(obj)}
1457
+ logging.log(msg=logEntry['msg'],
1458
+ level=logEntry['level'],
1459
+ t=now,
1460
+ obj=logEntry['obj'])
1461
+ del self._toLog[:]
1462
+
1463
+ # keep the system awake (prevent screen-saver or sleep)
1464
+ platform_specific.sendStayAwake()
1465
+
1466
+ # draw background (if present) for next frame
1467
+ if hasattr(self.backgroundImage, "draw"):
1468
+ self.backgroundImage.draw()
1469
+
1470
+ # draw piloting indicator (if piloting) for next frame
1471
+ if self._showPilotingIndicator:
1472
+ self._pilotingIndicator.draw()
1473
+
1474
+ # If self.waitBlanking is True, then return the time that
1475
+ # GL.glFinish() returned, set as the 'now' variable. Otherwise
1476
+ # return None as before
1477
+ #
1478
+ if self.waitBlanking is True:
1479
+ return now
1480
+
1481
+ def update(self):
1482
+ """Deprecated: use Window.flip() instead
1483
+ """
1484
+ # clearBuffer was the original behaviour for win.update()
1485
+ self.flip(clearBuffer=True)
1486
+
1487
+ def multiFlip(self, flips=1, clearBuffer=True):
1488
+ """Flip multiple times while maintaining the display constant.
1489
+ Use this method for precise timing.
1490
+
1491
+ **WARNING:** This function should not be used. See the `Notes` section
1492
+ for details.
1493
+
1494
+ Parameters
1495
+ ----------
1496
+ flips : int, optional
1497
+ The number of monitor frames to flip. Floats will be
1498
+ rounded to integers, and a warning will be emitted.
1499
+ ``Window.multiFlip(flips=1)`` is equivalent to ``Window.flip()``.
1500
+ Defaults to `1`.
1501
+ clearBuffer : bool, optional
1502
+ Whether to clear the screen after the last flip.
1503
+ Defaults to `True`.
1504
+
1505
+ Notes
1506
+ -----
1507
+ - This function can behave unpredictably, and the PsychoPy authors
1508
+ recommend against using it. See
1509
+ https://github.com/psychopy/psychopy/issues/867 for more information.
1510
+
1511
+ Examples
1512
+ --------
1513
+ Example of using ``multiFlip``::
1514
+
1515
+ # Draws myStim1 to buffer
1516
+ myStim1.draw()
1517
+ # Show stimulus for 4 frames (90 ms at 60Hz)
1518
+ myWin.multiFlip(clearBuffer=False, flips=6)
1519
+ # Draw myStim2 "on top of" myStim1
1520
+ # (because buffer was not cleared above)
1521
+ myStim2.draw()
1522
+ # Show this for 2 frames (30 ms at 60Hz)
1523
+ myWin.multiFlip(flips=2)
1524
+ # Show blank screen for 3 frames (buffer was cleared above)
1525
+ myWin.multiFlip(flips=3)
1526
+
1527
+ """
1528
+ if flips < 1:
1529
+ logging.error("flips argument for multiFlip should be "
1530
+ "a positive integer")
1531
+
1532
+ if flips != int(flips):
1533
+ flips = int(round(flips))
1534
+ logging.warning("Number of flips was not an integer; "
1535
+ "rounding to the next integer. Will flip "
1536
+ "%i times." % flips)
1537
+
1538
+ if flips > 1 and not self.waitBlanking:
1539
+ logging.warning("Call to Window.multiFlip() with flips > 1 is "
1540
+ "unnecessary because Window.waitBlanking=False")
1541
+
1542
+ # Do the flipping with last flip as special case
1543
+ for _ in range(flips - 1):
1544
+ self.flip(clearBuffer=False)
1545
+ self.flip(clearBuffer=clearBuffer)
1546
+
1547
+
1548
+
1549
+ def setBuffer(self, buffer, clear=True):
1550
+ """Choose which buffer to draw to ('left' or 'right').
1551
+
1552
+ Requires the Window to be initialised with stereo=True and requires a
1553
+ graphics card that supports quad buffering (e,g nVidia Quadro series)
1554
+
1555
+ PsychoPy always draws to the back buffers, so 'left' will use
1556
+ ``GL_BACK_LEFT`` This then needs to be flipped once both eye's buffers
1557
+ have been rendered.
1558
+
1559
+ Parameters
1560
+ ----------
1561
+ buffer : str
1562
+ Buffer to draw to. Can either be 'left' or 'right'.
1563
+ clear : bool, optional
1564
+ Clear the buffer before drawing. Default is ``True``.
1565
+
1566
+ Examples
1567
+ --------
1568
+ Stereoscopic rendering example using quad-buffers::
1569
+
1570
+ win = visual.Window(...., stereo=True)
1571
+ while True:
1572
+ # clear may not actually be needed
1573
+ win.setBuffer('left', clear=True)
1574
+ # do drawing for left eye
1575
+ win.setBuffer('right', clear=True)
1576
+ # do drawing for right eye
1577
+ win.flip()
1578
+
1579
+ """
1580
+ if buffer == 'left':
1581
+ GL.glDrawBuffer(GL.GL_BACK_LEFT)
1582
+ elif buffer == 'right':
1583
+ GL.glDrawBuffer(GL.GL_BACK_RIGHT)
1584
+ else:
1585
+ raise "Unknown buffer '%s' requested in Window.setBuffer" % buffer
1586
+ if clear:
1587
+ self.clearBuffer()
1588
+
1589
+ def clearBuffer(self, color=True, depth=False, stencil=False):
1590
+ """Clear the present buffer (to which you are currently drawing) without
1591
+ flipping the window.
1592
+
1593
+ Useful if you want to generate movie sequences from the back buffer
1594
+ without actually taking the time to flip the window.
1595
+
1596
+ Set `color` prior to clearing to set the color to clear the color buffer
1597
+ to. By default, the depth buffer is cleared to a value of 1.0.
1598
+
1599
+ Parameters
1600
+ ----------
1601
+ color, depth, stencil : bool
1602
+ Buffers to clear.
1603
+
1604
+ Examples
1605
+ --------
1606
+ Clear the color buffer to a specified color::
1607
+
1608
+ win.color = (1, 0, 0)
1609
+ win.clearBuffer(color=True)
1610
+
1611
+ Clear only the depth buffer, `depthMask` must be `True` or else this
1612
+ will have no effect. Depth mask is usually `True` by default, but
1613
+ may change::
1614
+
1615
+ win.depthMask = True
1616
+ win.clearBuffer(color=False, depth=True, stencil=False)
1617
+
1618
+ """
1619
+ clearBufferBits = GL.GL_NONE
1620
+
1621
+ if color:
1622
+ clearBufferBits |= GL.GL_COLOR_BUFFER_BIT
1623
+
1624
+ if depth:
1625
+ clearBufferBits |= GL.GL_DEPTH_BUFFER_BIT
1626
+
1627
+ if stencil:
1628
+ clearBufferBits |= GL.GL_STENCIL_BUFFER_BIT
1629
+
1630
+ # reset returned buffer for next frame
1631
+ GL.glClear(clearBufferBits)
1632
+
1633
+ @property
1634
+ def size(self):
1635
+ """Size of the drawable area in pixels (w, h)."""
1636
+ # report clientSize until we get framebuffer size from
1637
+ # the backend, needs to be done properly in the future
1638
+ if self.backend is not None:
1639
+ return self.viewport[2:]
1640
+ else:
1641
+ return self.clientSize
1642
+
1643
+ @property
1644
+ def frameBufferSize(self):
1645
+ """Size of the framebuffer in pixels (w, h)."""
1646
+ # Dimensions should match window size unless using a retina display
1647
+ return self.backend.frameBufferSize
1648
+
1649
+ @property
1650
+ def windowedSize(self):
1651
+ """Size of the window to use when not fullscreen (w, h)."""
1652
+ return self._windowedSize
1653
+
1654
+ @windowedSize.setter
1655
+ def windowedSize(self, value):
1656
+ """Size of the window to use when not fullscreen (w, h)."""
1657
+ self._windowedSize[:] = value
1658
+
1659
+ def getContentScaleFactor(self):
1660
+ """Get the scaling factor required for scaling correctly on high-DPI
1661
+ displays.
1662
+
1663
+ If the returned value is 1.0, no scaling needs to be applied to objects
1664
+ drawn on the backbuffer. A value >1.0 indicates that the backbuffer is
1665
+ larger than the reported client area, requiring points to be scaled to
1666
+ maintain constant size across similarly sized displays. In other words,
1667
+ the scaling required to convert framebuffer to client coordinates.
1668
+
1669
+ Returns
1670
+ -------
1671
+ float
1672
+ Scaling factor to be applied along both horizontal and vertical
1673
+ dimensions.
1674
+
1675
+ Examples
1676
+ --------
1677
+ Get the size of the client area::
1678
+
1679
+ clientSize = win.frameBufferSize / win.getContentScaleFactor()
1680
+
1681
+ Get the framebuffer size from the client size::
1682
+
1683
+ frameBufferSize = win.clientSize * win.getContentScaleFactor()
1684
+
1685
+ Convert client (window) to framebuffer pixel coordinates (eg., a mouse
1686
+ coordinate, vertices, etc.)::
1687
+
1688
+ # `mousePosXY` is an array ...
1689
+ frameBufferXY = mousePosXY * win.getContentScaleFactor()
1690
+ # you can also use the attribute ...
1691
+ frameBufferXY = mousePosXY * win.contentScaleFactor
1692
+
1693
+ Notes
1694
+ -----
1695
+ * This value is only valid after the window has been fully realized.
1696
+
1697
+ """
1698
+ # this might be accessed at lots of points, probably shouldn't compute
1699
+ # this all the time
1700
+ if self._contentScaleFactor is not None:
1701
+ return self._contentScaleFactor
1702
+
1703
+ sx = self.frameBufferSize[0] / float(self.clientSize[0])
1704
+ sy = self.frameBufferSize[1] / float(self.clientSize[1])
1705
+
1706
+ if sx != sy: # messed up DPI settings return 1.0 and show warning
1707
+ self._contentScaleFactor = 1.0
1708
+ else:
1709
+ self._contentScaleFactor = sx
1710
+
1711
+ return self._contentScaleFactor
1712
+
1713
+ @property
1714
+ def contentScaleFactor(self):
1715
+ """Scaling factor (`float`) to use when drawing to the backbuffer to
1716
+ convert framebuffer to client coordinates.
1717
+
1718
+ See Also
1719
+ --------
1720
+ getContentScaleFactor
1721
+
1722
+ """
1723
+ return self.getContentScaleFactor()
1724
+
1725
+ @property
1726
+ def aspect(self):
1727
+ """Aspect ratio of the current viewport (width / height)."""
1728
+ return self._viewport[2] / float(self._viewport[3])
1729
+
1730
+ @property
1731
+ def ambientLight(self):
1732
+ """Ambient light color for the scene [r, g, b, a]. Values range from 0.0
1733
+ to 1.0. Only applicable if `useLights` is `True`.
1734
+
1735
+ Examples
1736
+ --------
1737
+ Setting the ambient light color::
1738
+
1739
+ win.ambientLight = [0.5, 0.5, 0.5]
1740
+
1741
+ # don't do this!!!
1742
+ win.ambientLight[0] = 0.5
1743
+ win.ambientLight[1] = 0.5
1744
+ win.ambientLight[2] = 0.5
1745
+
1746
+ """
1747
+ # TODO - use signed color and colorspace instead
1748
+ return self._ambientLight[:3]
1749
+
1750
+ @ambientLight.setter
1751
+ def ambientLight(self, value):
1752
+ self._ambientLight[:3] = value
1753
+ GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT,
1754
+ numpy.ctypeslib.as_ctypes(self._ambientLight))
1755
+
1756
+ @property
1757
+ def lights(self):
1758
+ """Scene lights.
1759
+
1760
+ This is specified as an array of `~psychopy.visual.LightSource`
1761
+ objects. If a single value is given, it will be converted to a `list`
1762
+ before setting. Set `useLights` to `True` before rendering to enable
1763
+ lighting/shading on subsequent objects. If `lights` is `None` or an
1764
+ empty `list`, no lights will be enabled if `useLights=True`, however,
1765
+ the scene ambient light set with `ambientLight` will be still be used.
1766
+
1767
+ Examples
1768
+ --------
1769
+ Create a directional light source and add it to scene lights::
1770
+
1771
+ dirLight = gltools.LightSource((0., 1., 0.), lightType='directional')
1772
+ win.lights = dirLight # `win.lights` will be a list when accessed!
1773
+
1774
+ Multiple lights can be specified by passing values as a list::
1775
+
1776
+ myLights = [gltools.LightSource((0., 5., 0.)),
1777
+ gltools.LightSource((-2., -2., 0.))
1778
+ win.lights = myLights
1779
+
1780
+ """
1781
+ return self._lights
1782
+
1783
+ @lights.setter
1784
+ def lights(self, value):
1785
+ # if None or empty list, disable all lights
1786
+ if value is None or not value:
1787
+ for index in range(self._nLights):
1788
+ GL.glDisable(GL.GL_LIGHT0 + index)
1789
+
1790
+ self._nLights = 0 # set number of lights to zero
1791
+ self._lights = value
1792
+
1793
+ return
1794
+
1795
+ # set the lights and make sure it's a list if a single value was passed
1796
+ self._lights = value if isinstance(value, (list, tuple,)) else [value]
1797
+
1798
+ # disable excess lights if less lights were specified this time
1799
+ oldNumLights = self._nLights
1800
+ self._nLights = len(self._lights) # number of lights enabled
1801
+ if oldNumLights > self._nLights:
1802
+ for index in range(self._nLights, oldNumLights):
1803
+ GL.glDisable(GL.GL_LIGHT0 + index)
1804
+
1805
+ # Setup legacy lights, new spec shader programs should access the
1806
+ # `lights` attribute directly to setup lighting uniforms.
1807
+ # The index of the lights is defined by the order it appears in
1808
+ # `self._lights`.
1809
+ for index, light in enumerate(self._lights):
1810
+ enumLight = GL.GL_LIGHT0 + index
1811
+
1812
+ # convert data in light class to ctypes
1813
+ #pos = numpy.ctypeslib.as_ctypes(light.pos)
1814
+ diffuse = numpy.ctypeslib.as_ctypes(light._diffuseRGB)
1815
+ specular = numpy.ctypeslib.as_ctypes(light._specularRGB)
1816
+ ambient = numpy.ctypeslib.as_ctypes(light._ambientRGB)
1817
+
1818
+ # pass values to OpenGL
1819
+ #GL.glLightfv(enumLight, GL.GL_POSITION, pos)
1820
+ GL.glLightfv(enumLight, GL.GL_DIFFUSE, diffuse)
1821
+ GL.glLightfv(enumLight, GL.GL_SPECULAR, specular)
1822
+ GL.glLightfv(enumLight, GL.GL_AMBIENT, ambient)
1823
+
1824
+ constant, linear, quadratic = light._kAttenuation
1825
+ GL.glLightf(enumLight, GL.GL_CONSTANT_ATTENUATION, constant)
1826
+ GL.glLightf(enumLight, GL.GL_LINEAR_ATTENUATION, linear)
1827
+ GL.glLightf(enumLight, GL.GL_QUADRATIC_ATTENUATION, quadratic)
1828
+
1829
+ # enable the light
1830
+ GL.glEnable(enumLight)
1831
+
1832
+ @property
1833
+ def useLights(self):
1834
+ """Enable scene lighting.
1835
+
1836
+ Lights will be enabled if using legacy OpenGL lighting. Stimuli using
1837
+ shaders for lighting should check if `useLights` is `True` since this
1838
+ will have no effect on them, and disable or use a no lighting shader
1839
+ instead. Lights will be transformed to the current view matrix upon
1840
+ setting to `True`.
1841
+
1842
+ Lights are transformed by the present `GL_MODELVIEW` matrix. Setting
1843
+ `useLights` will result in their positions being transformed by it.
1844
+ If you want lights to appear at the specified positions in world space,
1845
+ make sure the current matrix defines the view/eye transformation when
1846
+ setting `useLights=True`.
1847
+
1848
+ This flag is reset to `False` at the beginning of each frame. Should be
1849
+ `False` if rendering 2D stimuli or else the colors will be incorrect.
1850
+ """
1851
+ return self._useLights
1852
+
1853
+ @useLights.setter
1854
+ def useLights(self, value):
1855
+ self._useLights = value
1856
+
1857
+ # DEPRECATED: this is not needed in modern OpenGL
1858
+
1859
+ # # Setup legacy lights, new spec shader programs should access the
1860
+ # # `lights` attribute directly to setup lighting uniforms.
1861
+ # if self._useLights and self._lights:
1862
+ # GL.glEnable(GL.GL_LIGHTING)
1863
+ # # make sure specular lights are computed relative to eye position,
1864
+ # # this is more realistic than the default. Does not affect shaders.
1865
+ # GL.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE)
1866
+
1867
+ # # update light positions for current model matrix
1868
+ # for index, light in enumerate(self._lights):
1869
+ # enumLight = GL.GL_LIGHT0 + index
1870
+ # pos = numpy.ctypeslib.as_ctypes(light.pos)
1871
+ # GL.glLightfv(enumLight, GL.GL_POSITION, pos)
1872
+ # else:
1873
+ # # disable lights
1874
+ # GL.glDisable(GL.GL_LIGHTING)
1875
+
1876
+ def updateLights(self, index=None):
1877
+ """Explicitly update scene lights if they were modified.
1878
+
1879
+ This is required if modifications to objects referenced in `lights` have
1880
+ been changed since assignment. If you removed or added items of `lights`
1881
+ you must refresh all of them.
1882
+
1883
+ Parameters
1884
+ ----------
1885
+ index : int, optional
1886
+ Index of light source in `lights` to update. If `None`, all lights
1887
+ will be refreshed.
1888
+
1889
+ Examples
1890
+ --------
1891
+ Call `updateLights` if you modified lights directly like this::
1892
+
1893
+ win.lights[1].diffuseColor = [1., 0., 0.]
1894
+ win.updateLights(1)
1895
+
1896
+ """
1897
+ if self._lights is None:
1898
+ return # nop if there are no lights
1899
+
1900
+ if index is None:
1901
+ self.lights = self._lights
1902
+ else:
1903
+ if index > len(self._lights) - 1:
1904
+ raise IndexError('Invalid index for `lights`.')
1905
+
1906
+ enumLight = GL.GL_LIGHT0 + index
1907
+
1908
+ # light object to modify
1909
+ light = self._lights[index]
1910
+
1911
+ # convert data in light class to ctypes
1912
+ # pos = numpy.ctypeslib.as_ctypes(light.pos)
1913
+ diffuse = numpy.ctypeslib.as_ctypes(light.diffuse)
1914
+ specular = numpy.ctypeslib.as_ctypes(light.specular)
1915
+ ambient = numpy.ctypeslib.as_ctypes(light.ambient)
1916
+
1917
+ # pass values to OpenGL
1918
+ # GL.glLightfv(enumLight, GL.GL_POSITION, pos)
1919
+ GL.glLightfv(enumLight, GL.GL_DIFFUSE, diffuse)
1920
+ GL.glLightfv(enumLight, GL.GL_SPECULAR, specular)
1921
+ GL.glLightfv(enumLight, GL.GL_AMBIENT, ambient)
1922
+
1923
+ def resetViewport(self):
1924
+ """Reset the viewport to cover the whole framebuffer.
1925
+
1926
+ Set the viewport to match the dimensions of the back buffer or
1927
+ framebuffer (if `useFBO=True`). The scissor rectangle is also set to
1928
+ match the dimensions of the viewport.
1929
+
1930
+ """
1931
+ # use the framebuffer size here, not the window size (hi-dpi compat)
1932
+ bufferWidth, bufferHeight = self.frameBufferSize
1933
+ self.scissor = self.viewport = [0, 0, bufferWidth, bufferHeight]
1934
+
1935
+ @property
1936
+ def viewport(self):
1937
+ """Viewport rectangle (x, y, w, h) for the current draw buffer.
1938
+
1939
+ Values `x` and `y` define the origin, and `w` and `h` the size of the
1940
+ rectangle in pixels.
1941
+
1942
+ This is typically set to cover the whole buffer, however it can be
1943
+ changed for applications like multi-view rendering. Stimuli will draw
1944
+ according to the new shape of the viewport, for instance and stimulus
1945
+ with position (0, 0) will be drawn at the center of the viewport, not
1946
+ the window.
1947
+
1948
+ Examples
1949
+ --------
1950
+ Constrain drawing to the left and right halves of the screen, where
1951
+ stimuli will be drawn centered on the new rectangle. Note that you need
1952
+ to set both the `viewport` and the `scissor` rectangle::
1953
+
1954
+ x, y, w, h = win.frameBufferSize # size of the framebuffer
1955
+ win.viewport = win.scissor = [x, y, w / 2.0, h]
1956
+ # draw left stimuli ...
1957
+
1958
+ win.viewport = win.scissor = [x + (w / 2.0), y, w / 2.0, h]
1959
+ # draw right stimuli ...
1960
+
1961
+ # restore drawing to the whole screen
1962
+ win.viewport = win.scissor = [x, y, w, h]
1963
+
1964
+ """
1965
+ return self._viewport
1966
+
1967
+ @viewport.setter
1968
+ def viewport(self, value):
1969
+ self._viewport = numpy.array(value, int)
1970
+ GL.glViewport(*self._viewport)
1971
+
1972
+ @property
1973
+ def scissor(self):
1974
+ """Scissor rectangle (x, y, w, h) for the current draw buffer.
1975
+
1976
+ Values `x` and `y` define the origin, and `w` and `h` the size
1977
+ of the rectangle in pixels. The scissor operation is only active
1978
+ if `scissorTest=True`.
1979
+
1980
+ Usually, the scissor and viewport are set to the same rectangle
1981
+ to prevent drawing operations from `spilling` into other regions
1982
+ of the screen. For instance, calling `clearBuffer` will only
1983
+ clear within the scissor rectangle.
1984
+
1985
+ Setting the scissor rectangle but not the viewport will restrict
1986
+ drawing within the defined region (like a rectangular aperture),
1987
+ not changing the positions of stimuli.
1988
+
1989
+ """
1990
+ return self._scissor
1991
+
1992
+ @scissor.setter
1993
+ def scissor(self, value):
1994
+ self._scissor = numpy.array(value, int)
1995
+ GL.glScissor(*self._scissor)
1996
+
1997
+ @property
1998
+ def scissorTest(self):
1999
+ """`True` if scissor testing is enabled."""
2000
+ return self._scissorTest
2001
+
2002
+ @scissorTest.setter
2003
+ def scissorTest(self, value):
2004
+ if value is True:
2005
+ GL.glEnable(GL.GL_SCISSOR_TEST)
2006
+ elif value is False:
2007
+ GL.glDisable(GL.GL_SCISSOR_TEST)
2008
+ else:
2009
+ raise TypeError("Value must be boolean.")
2010
+
2011
+ self._scissorTest = value
2012
+
2013
+ @property
2014
+ def stencilTest(self):
2015
+ """`True` if stencil testing is enabled."""
2016
+ return self._stencilTest
2017
+
2018
+ @stencilTest.setter
2019
+ def stencilTest(self, value):
2020
+ if value is True:
2021
+ GL.glEnable(GL.GL_STENCIL_TEST)
2022
+ elif value is False:
2023
+ GL.glDisable(GL.GL_STENCIL_TEST)
2024
+ else:
2025
+ raise TypeError("Value must be boolean.")
2026
+
2027
+ self._stencilTest = value
2028
+
2029
+ @property
2030
+ def nearClip(self):
2031
+ """Distance to the near clipping plane in meters."""
2032
+ return self._nearClip
2033
+
2034
+ @nearClip.setter
2035
+ def nearClip(self, value):
2036
+ self._nearClip = value
2037
+
2038
+ @property
2039
+ def farClip(self):
2040
+ """Distance to the far clipping plane in meters."""
2041
+ return self._farClip
2042
+
2043
+ @farClip.setter
2044
+ def farClip(self, value):
2045
+ self._farClip = value
2046
+
2047
+ @property
2048
+ def projectionMatrix(self):
2049
+ """Projection matrix defined as a 4x4 numpy array."""
2050
+ return self._projectionMatrix
2051
+
2052
+ @projectionMatrix.setter
2053
+ def projectionMatrix(self, value):
2054
+ self._projectionMatrix = numpy.asarray(value, numpy.float32)
2055
+ assert self._projectionMatrix.shape == (4, 4)
2056
+
2057
+ @property
2058
+ def viewMatrix(self):
2059
+ """View matrix defined as a 4x4 numpy array."""
2060
+ return self._viewMatrix
2061
+
2062
+ @viewMatrix.setter
2063
+ def viewMatrix(self, value):
2064
+ self._viewMatrix = numpy.asarray(value, numpy.float32)
2065
+ assert self._viewMatrix.shape == (4, 4)
2066
+
2067
+ @property
2068
+ def eyeOffset(self):
2069
+ """Eye offset in centimeters.
2070
+
2071
+ This value is used by `setPerspectiveView` to apply a lateral
2072
+ offset to the view, therefore it must be set prior to calling it. Use a
2073
+ positive offset for the right eye, and a negative one for the left.
2074
+ Offsets should be the distance to from the middle of the face to the
2075
+ center of the eye, or half the inter-ocular distance.
2076
+
2077
+ """
2078
+ return self._eyeOffset * 100.0
2079
+
2080
+ @eyeOffset.setter
2081
+ def eyeOffset(self, value):
2082
+ self._eyeOffset = value / 100.0
2083
+
2084
+ @property
2085
+ def convergeOffset(self):
2086
+ """Convergence offset from monitor in centimeters.
2087
+
2088
+ This is value corresponds to the offset from screen plane to set the
2089
+ convergence plane (or point for `toe-in` projections). Positive offsets
2090
+ move the plane farther away from the viewer, while negative offsets
2091
+ nearer. This value is used by `setPerspectiveView` and should be set
2092
+ before calling it to take effect.
2093
+
2094
+ Notes
2095
+ -----
2096
+ * This value is only applicable for `setToeIn` and `setOffAxisView`.
2097
+
2098
+ """
2099
+ return self._convergeOffset * 100.0
2100
+
2101
+ @convergeOffset.setter
2102
+ def convergeOffset(self, value):
2103
+ self._convergeOffset = value / 100.0
2104
+
2105
+ def _clearDepthBuffer(self):
2106
+ """Clear the depth buffer.
2107
+ """
2108
+ oldDepthMask = self.depthMask
2109
+ GL.glDepthMask(GL.GL_TRUE)
2110
+ GL.glClear(GL.GL_DEPTH_BUFFER_BIT)
2111
+
2112
+ if oldDepthMask is False: # return to old state if needed
2113
+ GL.glDepthMask(GL.GL_FALSE)
2114
+
2115
+ def setOffAxisView(self, applyTransform=True, clearDepth=True):
2116
+ """Set an off-axis projection.
2117
+
2118
+ Create an off-axis projection for subsequent rendering calls. Sets the
2119
+ `viewMatrix` and `projectionMatrix` accordingly so the scene origin is
2120
+ on the screen plane. If `eyeOffset` is correct and the view distance and
2121
+ screen size is defined in the monitor configuration, the resulting view
2122
+ will approximate `ortho-stereo` viewing.
2123
+
2124
+ The convergence plane can be adjusted by setting `convergeOffset`. By
2125
+ default, the convergence plane is set to the screen plane. Any points
2126
+ on the screen plane will have zero disparity.
2127
+
2128
+ Parameters
2129
+ ----------
2130
+ applyTransform : bool
2131
+ Apply transformations after computing them in immediate mode. Same
2132
+ as calling :py:attr:`~Window.applyEyeTransform()` afterwards.
2133
+ clearDepth : bool, optional
2134
+ Clear the depth buffer.
2135
+
2136
+ """
2137
+ scrDistM = 0.5 if self.scrDistCM is None else self.scrDistCM / 100.0
2138
+ scrWidthM = 0.5 if self.scrWidthCM is None else self.scrWidthCM / 100.0
2139
+
2140
+ # Not in full screen mode? Need to compute the dimensions of the display
2141
+ # area to ensure disparities are correct even when in windowed-mode.
2142
+ aspect = self.size[0] / self.size[1]
2143
+ if not self._isFullScr:
2144
+ scrWidthM = (self.size[0] / self.scrWidthPIX) * scrWidthM
2145
+
2146
+ frustum = viewtools.computeFrustum(
2147
+ scrWidthM, # width of screen
2148
+ aspect, # aspect ratio
2149
+ scrDistM, # distance to screen
2150
+ eyeOffset=self._eyeOffset,
2151
+ convergeOffset=self._convergeOffset,
2152
+ nearClip=self._nearClip,
2153
+ farClip=self._farClip)
2154
+
2155
+ self._projectionMatrix = viewtools.perspectiveProjectionMatrix(*frustum)
2156
+
2157
+ # translate away from screen
2158
+ self._viewMatrix = numpy.identity(4, dtype=numpy.float32)
2159
+ self._viewMatrix[0, 3] = -self._eyeOffset # apply eye offset
2160
+ self._viewMatrix[2, 3] = -scrDistM # displace scene away from viewer
2161
+
2162
+ if applyTransform:
2163
+ self.applyEyeTransform(clearDepth=clearDepth)
2164
+
2165
+ def setToeInView(self, applyTransform=True, clearDepth=True):
2166
+ """Set toe-in projection.
2167
+
2168
+ Create a toe-in projection for subsequent rendering calls. Sets the
2169
+ `viewMatrix` and `projectionMatrix` accordingly so the scene origin is
2170
+ on the screen plane. The value of `convergeOffset` will define the
2171
+ convergence point of the view, which is offset perpendicular to the
2172
+ center of the screen plane. Points falling on a vertical line at the
2173
+ convergence point will have zero disparity.
2174
+
2175
+ Parameters
2176
+ ----------
2177
+ applyTransform : bool
2178
+ Apply transformations after computing them in immediate mode. Same
2179
+ as calling :py:attr:`~Window.applyEyeTransform()` afterwards.
2180
+ clearDepth : bool, optional
2181
+ Clear the depth buffer.
2182
+
2183
+ Notes
2184
+ -----
2185
+ * This projection mode is only 'correct' if the viewer's eyes are
2186
+ converged at the convergence point. Due to perspective, this
2187
+ projection introduces vertical disparities which increase in magnitude
2188
+ with eccentricity. Use `setOffAxisView` if you want to display
2189
+ something the viewer can look around the screen comfortably.
2190
+
2191
+ """
2192
+ scrDistM = 0.5 if self.scrDistCM is None else self.scrDistCM / 100.0
2193
+ scrWidthM = 0.5 if self.scrWidthCM is None else self.scrWidthCM / 100.0
2194
+
2195
+ # Not in full screen mode? Need to compute the dimensions of the display
2196
+ # area to ensure disparities are correct even when in windowed-mode.
2197
+ aspect = self.size[0] / self.size[1]
2198
+ if not self._isFullScr:
2199
+ scrWidthM = (self.size[0] / self.scrWidthPIX) * scrWidthM
2200
+
2201
+ frustum = viewtools.computeFrustum(
2202
+ scrWidthM, # width of screen
2203
+ aspect, # aspect ratio
2204
+ scrDistM, # distance to screen
2205
+ nearClip=self._nearClip,
2206
+ farClip=self._farClip)
2207
+
2208
+ self._projectionMatrix = viewtools.perspectiveProjectionMatrix(*frustum)
2209
+
2210
+ # translate away from screen
2211
+ eyePos = (self._eyeOffset, 0.0, scrDistM)
2212
+ convergePoint = (0.0, 0.0, self.convergeOffset)
2213
+ self._viewMatrix = viewtools.lookAt(eyePos, convergePoint)
2214
+
2215
+ if applyTransform:
2216
+ self.applyEyeTransform(clearDepth=clearDepth)
2217
+
2218
+ def setPerspectiveView(self, applyTransform=True, clearDepth=True):
2219
+ """Set the projection and view matrix to render with perspective.
2220
+
2221
+ Matrices are computed using values specified in the monitor
2222
+ configuration with the scene origin on the screen plane. Calculations
2223
+ assume units are in meters. If `eyeOffset != 0`, the view will be
2224
+ transformed laterally, however the frustum shape will remain the
2225
+ same.
2226
+
2227
+ Note that the values of :py:attr:`~Window.projectionMatrix` and
2228
+ :py:attr:`~Window.viewMatrix` will be replaced when calling this
2229
+ function.
2230
+
2231
+ Parameters
2232
+ ----------
2233
+ applyTransform : bool
2234
+ Apply transformations after computing them in immediate mode. Same
2235
+ as calling :py:attr:`~Window.applyEyeTransform()` afterwards if
2236
+ `False`.
2237
+ clearDepth : bool, optional
2238
+ Clear the depth buffer.
2239
+
2240
+ """
2241
+ # NB - we should eventually compute these matrices lazily since they may
2242
+ # not change over the course of an experiment under most circumstances.
2243
+ #
2244
+ scrDistM = 0.5 if self.scrDistCM is None else self.scrDistCM / 100.0
2245
+ scrWidthM = 0.5 if self.scrWidthCM is None else self.scrWidthCM / 100.0
2246
+
2247
+ # Not in full screen mode? Need to compute the dimensions of the display
2248
+ # area to ensure disparities are correct even when in windowed-mode.
2249
+ aspect = self.size[0] / self.size[1]
2250
+ if not self._isFullScr:
2251
+ scrWidthM = (self.size[0] / self.scrWidthPIX) * scrWidthM
2252
+
2253
+ frustum = viewtools.computeFrustum(
2254
+ scrWidthM, # width of screen
2255
+ aspect, # aspect ratio
2256
+ scrDistM, # distance to screen
2257
+ nearClip=self._nearClip,
2258
+ farClip=self._farClip)
2259
+
2260
+ self._projectionMatrix = \
2261
+ viewtools.perspectiveProjectionMatrix(*frustum, dtype=numpy.float32)
2262
+
2263
+ # translate away from screen
2264
+ self._viewMatrix = numpy.identity(4, dtype=numpy.float32)
2265
+ self._viewMatrix[0, 3] = -self._eyeOffset # apply eye offset
2266
+ self._viewMatrix[2, 3] = -scrDistM # displace scene away from viewer
2267
+
2268
+ if applyTransform:
2269
+ self.applyEyeTransform(clearDepth=clearDepth)
2270
+
2271
+ def setDefaultView(self, applyTransform=True, clearDepth=True):
2272
+ """Set the projection and view matrix to PsychoPy's default.
2273
+
2274
+ This is the mode which is typically used for rendering 2D stimuli. It should
2275
+ be called prior to rendering any 2D stimuli if the projection has been
2276
+ changed.
2277
+
2278
+ """
2279
+ self._updateViewMatrix()
2280
+ self._updateProjectionMatrix()
2281
+
2282
+ if applyTransform:
2283
+ self.applyEyeTransform(clearDepth=clearDepth)
2284
+
2285
+ def setOrthographicView(self, applyTransform=True, clearDepth=True):
2286
+ """Set the projection and view matrix to render with orthographic view.
2287
+
2288
+ Orthographic projection is used to render 3D objects without perspective
2289
+ distortion. The scene origin is centered on the screen plane. The
2290
+ frustum is defined by the size of the window in pixels, with the origin
2291
+ at the center of the window. 2D stimuli are typically drawn using this
2292
+ projection.
2293
+
2294
+ Note that the values of :py:attr:`~Window.projectionMatrix` and
2295
+ :py:attr:`~Window.viewMatrix` will be replaced when calling this
2296
+ function.
2297
+
2298
+ Parameters
2299
+ ----------
2300
+ applyTransform : bool
2301
+ Apply transformations after computing them in immediate mode. Same
2302
+ as calling :py:attr:`~Window.applyEyeTransform()` afterwards if
2303
+ `False`.
2304
+ clearDepth : bool, optional
2305
+ Clear the depth buffer.
2306
+
2307
+ """
2308
+ self._updateViewMatrix()
2309
+
2310
+ widthOver2 = self.size[0] / 2.0
2311
+ heightOver2 = self.size[1] / 2.0
2312
+ self._projectionMatrix[:, :] = viewtools.orthoProjectionMatrix(
2313
+ -widthOver2, widthOver2, # -X, +X
2314
+ -heightOver2, heightOver2, # -Y, +Y
2315
+ -1.0, 1.0, # -Z, +Z
2316
+ dtype=numpy.float32)
2317
+ self._projectionMatrix[:, :] = numpy.identity(4, dtype=numpy.float32)
2318
+
2319
+ if applyTransform:
2320
+ self.applyEyeTransform(clearDepth=clearDepth)
2321
+
2322
+ def applyEyeTransform(self, clearDepth=True):
2323
+ """Apply the current view and projection matrices.
2324
+
2325
+ Matrices specified by attributes :py:attr:`~Window.viewMatrix` and
2326
+ :py:attr:`~Window.projectionMatrix` are applied using 'immediate mode'
2327
+ OpenGL functions. Subsequent drawing operations will be affected until
2328
+ :py:attr:`~Window.flip()` is called.
2329
+
2330
+ All transformations in ``GL_PROJECTION`` and ``GL_MODELVIEW`` matrix
2331
+ stacks will be cleared (set to identity) prior to applying. After this
2332
+ is called, the current matrix mode will be set to ``GL_MODELVIEW``.
2333
+
2334
+ Parameters
2335
+ ----------
2336
+ clearDepth : bool
2337
+ Clear the depth buffer. This may be required prior to rendering 3D
2338
+ objects.
2339
+
2340
+ Examples
2341
+ --------
2342
+ Using a custom view and projection matrix::
2343
+
2344
+ # Must be called every frame since these values are reset after
2345
+ # `flip()` is called!
2346
+ win.viewMatrix = viewtools.lookAt( ... )
2347
+ win.projectionMatrix = viewtools.perspectiveProjectionMatrix( ... )
2348
+ win.applyEyeTransform()
2349
+ # draw 3D objects here ...
2350
+
2351
+ """
2352
+ if self.USE_LEGACY_GL:
2353
+ # apply the projection and view transformations
2354
+ GL.glMatrixMode(GL.GL_PROJECTION)
2355
+ GL.glLoadIdentity()
2356
+ projMat = self._projectionMatrix.ctypes.data_as(
2357
+ ctypes.POINTER(ctypes.c_float))
2358
+ GL.glMultTransposeMatrixf(projMat)
2359
+
2360
+ GL.glMatrixMode(GL.GL_MODELVIEW)
2361
+ GL.glLoadIdentity()
2362
+ viewMat = self._viewMatrix.ctypes.data_as(
2363
+ ctypes.POINTER(ctypes.c_float))
2364
+ GL.glMultTransposeMatrixf(viewMat)
2365
+
2366
+ oldDepthMask = self.depthMask
2367
+ if clearDepth:
2368
+ GL.glDepthMask(GL.GL_TRUE)
2369
+ GL.glClear(GL.GL_DEPTH_BUFFER_BIT)
2370
+
2371
+ if oldDepthMask is False: # return to old state if needed
2372
+ GL.glDepthMask(GL.GL_FALSE)
2373
+
2374
+ def resetEyeTransform(self, clearDepth=True):
2375
+ """Restore the default projection and view settings to PsychoPy
2376
+ defaults. Call this prior to drawing 2D stimuli objects (i.e.
2377
+ GratingStim, ImageStim, Rect, etc.) if any eye transformations were
2378
+ applied for the stimuli to be drawn correctly.
2379
+
2380
+ Parameters
2381
+ ----------
2382
+ clearDepth : bool
2383
+ Clear the depth buffer upon reset. This ensures successive draw
2384
+ commands are not affected by previous data written to the depth
2385
+ buffer. Default is `True`.
2386
+
2387
+ Notes
2388
+ -----
2389
+ * Calling :py:attr:`~Window.flip()` automatically resets the view and
2390
+ projection to defaults. So you don't need to call this unless you are
2391
+ mixing 3D and 2D stimuli.
2392
+
2393
+ Examples
2394
+ --------
2395
+ Going between 3D and 2D stimuli::
2396
+
2397
+ # 2D stimuli can be drawn before setting a perspective projection
2398
+ win.setPerspectiveView()
2399
+ # draw 3D stimuli here ...
2400
+ win.resetEyeTransform()
2401
+ # 2D stimuli can be drawn here again ...
2402
+ win.flip()
2403
+
2404
+ """
2405
+ self.setOrthographicView(clearDepth)
2406
+
2407
+ if self.USE_LEGACY_GL:
2408
+ self.applyEyeTransform(clearDepth)
2409
+
2410
+ def coordToRay(self, screenXY):
2411
+ """Convert a screen coordinate to a direction vector.
2412
+
2413
+ Takes a screen/window coordinate and computes a vector which projects
2414
+ a ray from the viewpoint through it (line-of-sight). Any 3D point
2415
+ touching the ray will appear at the screen coordinate.
2416
+
2417
+ Uses the current `viewport` and `projectionMatrix` to calculate the
2418
+ vector. The vector is in eye-space, where the origin of the scene is
2419
+ centered at the viewpoint and the forward direction aligned with the -Z
2420
+ axis. A ray of (0, 0, -1) results from a point at the very center of the
2421
+ screen assuming symmetric frustums.
2422
+
2423
+ Note that if you are using a flipped/mirrored view, you must invert your
2424
+ supplied screen coordinates (`screenXY`) prior to passing them to this
2425
+ function.
2426
+
2427
+ Parameters
2428
+ ----------
2429
+ screenXY : array_like
2430
+ X, Y screen coordinate. Must be in units of the window.
2431
+
2432
+ Returns
2433
+ -------
2434
+ ndarray
2435
+ Normalized direction vector [x, y, z].
2436
+
2437
+ Examples
2438
+ --------
2439
+ Getting the direction vector between the mouse cursor and the eye::
2440
+
2441
+ mx, my = mouse.getPos()
2442
+ dir = win.coordToRay((mx, my))
2443
+
2444
+ Set the position of a 3D stimulus object using the mouse, constrained to
2445
+ a plane. The object origin will always be at the screen coordinate of
2446
+ the mouse cursor::
2447
+
2448
+ # the eye position in the scene is defined by a rigid body pose
2449
+ win.viewMatrix = camera.getViewMatrix()
2450
+ win.applyEyeTransform()
2451
+
2452
+ # get the mouse location and calculate the intercept
2453
+ mx, my = mouse.getPos()
2454
+ ray = win.coordToRay([mx, my])
2455
+ result = intersectRayPlane( # from mathtools
2456
+ orig=camera.pos,
2457
+ dir=camera.transformNormal(ray),
2458
+ planeOrig=(0, 0, -10),
2459
+ planeNormal=(0, 1, 0))
2460
+
2461
+ # if result is `None`, there is no intercept
2462
+ if result is not None:
2463
+ pos, dist = result
2464
+ objModel.thePose.pos = pos
2465
+ else:
2466
+ objModel.thePose.pos = (0, 0, -10) # plane origin
2467
+
2468
+ If you don't define the position of the viewer with a `RigidBodyPose`,
2469
+ you can obtain the appropriate eye position and rotate the ray by doing
2470
+ the following::
2471
+
2472
+ pos = numpy.linalg.inv(win.viewMatrix)[:3, 3]
2473
+ ray = win.coordToRay([mx, my]).dot(win.viewMatrix[:3, :3])
2474
+ # then ...
2475
+ result = intersectRayPlane(
2476
+ orig=pos,
2477
+ dir=ray,
2478
+ planeOrig=(0, 0, -10),
2479
+ planeNormal=(0, 1, 0))
2480
+
2481
+ """
2482
+ # put in units of pixels
2483
+ if self.units == 'pix':
2484
+ scrX, scrY = numpy.asarray(screenXY, numpy.float32)
2485
+ else:
2486
+ scrX, scrY = convertToPix(numpy.asarray([0, 0]),
2487
+ numpy.asarray(screenXY),
2488
+ units=self.units,
2489
+ win=self)[:2]
2490
+
2491
+ # transform psychopy mouse coordinates to viewport coordinates
2492
+ scrX += (self.size[0] / 2.)
2493
+ scrY += (self.size[1] / 2.)
2494
+
2495
+ # get the NDC coordinates of the
2496
+ projX = 2. * (scrX - self.viewport[0]) / self.viewport[2] - 1.
2497
+ projY = 2. * (scrY - self.viewport[1]) / self.viewport[3] - 1.
2498
+
2499
+ vecNear = numpy.array((projX, projY, 0., 1.), dtype=numpy.float32)
2500
+ vecFar = numpy.array((projX, projY, 1., 1.), dtype=numpy.float32)
2501
+
2502
+ # compute the inverse projection matrix
2503
+ invPM = numpy.linalg.inv(self.projectionMatrix)
2504
+
2505
+ vecNear[:] = vecNear.dot(invPM.T)
2506
+ vecFar[:] = vecFar.dot(invPM.T)
2507
+
2508
+ vecNear /= vecNear[3]
2509
+ vecFar /= vecFar[3]
2510
+
2511
+ # direction vector, get rid of `w`
2512
+ dirVec = vecFar[:3] - vecNear[:3]
2513
+
2514
+ return dirVec / numpy.linalg.norm(dirVec)
2515
+
2516
+ def getMovieFrame(self, buffer='front'):
2517
+ """Capture the current Window as an image.
2518
+
2519
+ Saves to stack for :py:attr:`~Window.saveMovieFrames()`. As of v1.81.00
2520
+ this also returns the frame as a PIL image
2521
+
2522
+ This can be done at any time (usually after a :py:attr:`~Window.flip()`
2523
+ command).
2524
+
2525
+ Frames are stored in memory until a :py:attr:`~Window.saveMovieFrames()`
2526
+ command is issued. You can issue :py:attr:`~Window.getMovieFrame()` as
2527
+ often as you like and then save them all in one go when finished.
2528
+
2529
+ The back buffer will return the frame that hasn't yet been 'flipped'
2530
+ to be visible on screen but has the advantage that the mouse and any
2531
+ other overlapping windows won't get in the way.
2532
+
2533
+ The default front buffer is to be called immediately after a
2534
+ :py:attr:`~Window.flip()` and gives a complete copy of the screen at the
2535
+ window's coordinates.
2536
+
2537
+ Parameters
2538
+ ----------
2539
+ buffer : str, optional
2540
+ Buffer to capture.
2541
+
2542
+ Returns
2543
+ -------
2544
+ Image
2545
+ Buffer pixel contents as a PIL/Pillow image object.
2546
+
2547
+ """
2548
+ im = self._getFrame(buffer=buffer)
2549
+ self.movieFrames.append(im)
2550
+ return im
2551
+
2552
+ def _getPixels(self, rect=None, buffer='front', includeAlpha=True,
2553
+ makeLum=False):
2554
+ """Return an array of pixel values from the current window buffer or
2555
+ sub-region.
2556
+
2557
+ Parameters
2558
+ ----------
2559
+ rect : tuple[int], optional
2560
+ The region of the window to capture in pixel coordinates (left,
2561
+ bottom, width, height). If `None`, the whole window is captured.
2562
+ buffer : str, optional
2563
+ Buffer to capture.
2564
+ includeAlpha : bool, optional
2565
+ Include the alpha channel in the returned array. Default is `True`.
2566
+ makeLum : bool, optional
2567
+ Convert the RGB values to luminance values. Values are rounded to
2568
+ the nearest integer. Default is `False`.
2569
+
2570
+ Returns
2571
+ -------
2572
+ ndarray
2573
+ Pixel values as a 3D array of shape (height, width, channels). If
2574
+ `includeAlpha` is `False`, the array will have shape (height, width,
2575
+ 3). If `makeLum` is `True`, the array will have shape (height,
2576
+ width).
2577
+
2578
+ Examples
2579
+ --------
2580
+ Get the pixel values of the whole window::
2581
+
2582
+ pix = win._getPixels()
2583
+
2584
+ Get pixel values and convert to luminance and get average::
2585
+
2586
+ pix = win._getPixels(makeLum=True)
2587
+ average = pix.mean()
2588
+
2589
+ """
2590
+ # do the reading of the pixels
2591
+ if buffer == 'back' and self.useFBO:
2592
+ GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0)
2593
+ elif buffer == 'back':
2594
+ GL.glReadBuffer(GL.GL_BACK)
2595
+ elif buffer == 'front':
2596
+ if self.useFBO:
2597
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
2598
+ GL.glReadBuffer(GL.GL_FRONT)
2599
+ else:
2600
+ raise ValueError("Requested read from buffer '{}' but should be "
2601
+ "'front' or 'back'".format(buffer))
2602
+
2603
+ if rect:
2604
+ # box corners in pix
2605
+ left, bottom, w, h = rect
2606
+ else:
2607
+ left = bottom = 0
2608
+ w, h = self.size
2609
+
2610
+ # get pixel data
2611
+ bufferDat = (GL.GLubyte * (4 * w * h))()
2612
+ GL.glReadPixels(
2613
+ left, bottom, w, h,
2614
+ GL.GL_RGBA,
2615
+ GL.GL_UNSIGNED_BYTE,
2616
+ bufferDat)
2617
+
2618
+ # convert to array
2619
+ toReturn = numpy.frombuffer(bufferDat, dtype=numpy.uint8)
2620
+ toReturn = toReturn.reshape((h, w, 4))
2621
+
2622
+ # rebind front buffer if needed
2623
+ if buffer == 'front' and self.useFBO:
2624
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.frameBuffer)
2625
+
2626
+ # if we want the color data without an alpha channel, we need to
2627
+ # convert the data to a numpy array and remove the alpha channel
2628
+ if not includeAlpha:
2629
+ toReturn = toReturn[:, :, :3] # remove alpha channel
2630
+
2631
+ # convert to luminance if requested
2632
+ if makeLum:
2633
+ coeffs = [0.2989, 0.5870, 0.1140]
2634
+ toReturn = numpy.rint(numpy.dot(toReturn[:, :, :3], coeffs)).astype(
2635
+ numpy.uint8)
2636
+
2637
+ return toReturn
2638
+
2639
+ def _getFrame(self, rect=None, buffer='front'):
2640
+ """Return the current Window as an image.
2641
+ """
2642
+ # GL.glLoadIdentity()
2643
+ # do the reading of the pixels
2644
+ if buffer == 'back' and self.useFBO:
2645
+ GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0)
2646
+ elif buffer == 'back':
2647
+ GL.glReadBuffer(GL.GL_BACK)
2648
+ elif buffer == 'front':
2649
+ if self.useFBO:
2650
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
2651
+ GL.glReadBuffer(GL.GL_FRONT)
2652
+ else:
2653
+ raise ValueError("Requested read from buffer '{}' but should be "
2654
+ "'front' or 'back'".format(buffer))
2655
+
2656
+ if rect:
2657
+ x, y = self.size # of window, not image
2658
+ imType = 'RGBA' # not tested with anything else
2659
+
2660
+ # box corners in pix
2661
+ left = int((rect[0] / 2. + 0.5) * x)
2662
+ bottom = int((rect[3] / 2. + 0.5) * y)
2663
+ w = int((rect[2] / 2. + 0.5) * x) - left
2664
+ h = int((rect[1] / 2. + 0.5) * y) - bottom
2665
+ else:
2666
+ left = bottom = 0
2667
+ w, h = self.size
2668
+
2669
+ # http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml
2670
+ bufferDat = (GL.GLubyte * (4 * w * h))()
2671
+ GL.glReadPixels(left, bottom, w, h,
2672
+ GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, bufferDat)
2673
+ try:
2674
+ im = Image.fromstring(mode='RGBA', size=(w, h),
2675
+ data=bufferDat)
2676
+ except Exception:
2677
+ im = Image.frombytes(mode='RGBA', size=(w, h),
2678
+ data=bufferDat)
2679
+
2680
+ im = im.transpose(Image.FLIP_TOP_BOTTOM)
2681
+ im = im.convert('RGB')
2682
+
2683
+ if self.useFBO and buffer == 'front':
2684
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.frameBuffer)
2685
+ return im
2686
+
2687
+ @property
2688
+ def screenshot(self):
2689
+ return self._getFrame()
2690
+
2691
+ def saveMovieFrames(self, fileName, codec='libx264',
2692
+ fps=30, clearFrames=True):
2693
+ """Writes any captured frames to disk.
2694
+
2695
+ Will write any format that is understood by PIL (tif, jpg, png, ...)
2696
+
2697
+ Parameters
2698
+ ----------
2699
+ filename : str
2700
+ Name of file, including path. The extension at the end of the file
2701
+ determines the type of file(s) created. If an image type (e.g. .png)
2702
+ is given, then multiple static frames are created. If it is .gif
2703
+ then an animated GIF image is created (although you will get higher
2704
+ quality GIF by saving PNG files and then combining them in dedicated
2705
+ image manipulation software, such as GIMP). On Windows and Linux
2706
+ `.mpeg` files can be created if `pymedia` is installed. On macOS
2707
+ `.mov` files can be created if the pyobjc-frameworks-QTKit is
2708
+ installed. Unfortunately the libs used for movie generation can be
2709
+ flaky and poor quality. As for animated GIFs, better results can be
2710
+ achieved by saving as individual .png frames and then combining them
2711
+ into a movie using software like ffmpeg.
2712
+ codec : str, optional
2713
+ The codec to be used **by moviepy** for mp4/mpg/mov files. If
2714
+ `None` then the default will depend on file extension. Can be
2715
+ one of ``libx264``, ``mpeg4`` for mp4/mov files. Can be
2716
+ ``rawvideo``, ``png`` for avi files (not recommended). Can be
2717
+ ``libvorbis`` for ogv files. Default is ``libx264``.
2718
+ fps : int, optional
2719
+ The frame rate to be used throughout the movie. **Only for
2720
+ quicktime (.mov) movies.**. Default is `30`.
2721
+ clearFrames : bool, optional
2722
+ Set this to `False` if you want the frames to be kept for
2723
+ additional calls to ``saveMovieFrames``. Default is `True`.
2724
+
2725
+ Examples
2726
+ --------
2727
+ Writes a series of static frames as frame001.tif, frame002.tif etc.::
2728
+
2729
+ myWin.saveMovieFrames('frame.tif')
2730
+
2731
+ As of PsychoPy 1.84.1 the following are written with moviepy::
2732
+
2733
+ myWin.saveMovieFrames('stimuli.mp4') # codec = 'libx264' or 'mpeg4'
2734
+ myWin.saveMovieFrames('stimuli.mov')
2735
+ myWin.saveMovieFrames('stimuli.gif')
2736
+
2737
+ """
2738
+ fileRoot, fileExt = os.path.splitext(fileName)
2739
+ fileExt = fileExt.lower() # easier than testing both later
2740
+ if len(self.movieFrames) == 0:
2741
+ logging.error('no frames to write - did you forget to update '
2742
+ 'your window or call win.getMovieFrame()?')
2743
+ return
2744
+ else:
2745
+ logging.info('Writing %i frames to %s' % (len(self.movieFrames),
2746
+ fileName))
2747
+
2748
+ if fileExt in ['.gif', '.mpg', '.mpeg', '.mp4', '.mov']:
2749
+ # lazy loading of moviepy.editor (rarely needed)
2750
+ from moviepy import ImageSequenceClip
2751
+ # save variety of movies with moviepy
2752
+ numpyFrames = []
2753
+ for frame in self.movieFrames:
2754
+ numpyFrames.append(numpy.array(frame))
2755
+ clip = ImageSequenceClip(numpyFrames, fps=fps)
2756
+ if fileExt == '.gif':
2757
+ clip.write_gif(fileName, fps=fps, fuzz=0, opt='nq')
2758
+ else:
2759
+ clip.write_videofile(fileName, codec=codec)
2760
+ elif len(self.movieFrames) == 1:
2761
+ # save an image using pillow
2762
+ self.movieFrames[0].save(fileName)
2763
+ else:
2764
+ frmc = numpy.ceil(numpy.log10(len(self.movieFrames) + 1))
2765
+ frame_name_format = "%s%%0%dd%s" % (fileRoot, frmc, fileExt)
2766
+ for frameN, thisFrame in enumerate(self.movieFrames):
2767
+ thisFileName = frame_name_format % (frameN + 1,)
2768
+ thisFrame.save(thisFileName)
2769
+ if clearFrames:
2770
+ self.movieFrames = []
2771
+
2772
+ def _getRegionOfFrame(self, rect=(-1, 1, 1, -1), buffer='front',
2773
+ power2=False, squarePower2=False):
2774
+ """Deprecated function, here for historical reasons. You may now use
2775
+ `:py:attr:`~Window._getFrame()` and specify a rect to get a sub-region,
2776
+ just as used here.
2777
+
2778
+ power2 can be useful with older OpenGL versions to avoid interpolation
2779
+ in :py:attr:`PatchStim`. If power2 or squarePower2, it will expand rect
2780
+ dimensions up to next power of two. squarePower2 uses the max
2781
+ dimensions. You need to check what your hardware & OpenGL supports,
2782
+ and call :py:attr:`~Window._getRegionOfFrame()` as appropriate.
2783
+ """
2784
+ # Ideally: rewrite using GL frame buffer object; glReadPixels == slow
2785
+ region = self._getFrame(rect=rect, buffer=buffer)
2786
+ if power2 or squarePower2: # use to avoid interpolation in PatchStim
2787
+ if squarePower2:
2788
+ maxsize = max(region.size)
2789
+ xPowerOf2 = int(2**numpy.ceil(numpy.log2(maxsize)))
2790
+ yPowerOf2 = xPowerOf2
2791
+ else:
2792
+ xPowerOf2 = int(2**numpy.ceil(numpy.log2(region.size[0])))
2793
+ yPowerOf2 = int(2**numpy.ceil(numpy.log2(region.size[1])))
2794
+ imP2 = Image.new('RGBA', (xPowerOf2, yPowerOf2))
2795
+ # paste centered
2796
+ imP2.paste(region, (int(xPowerOf2 / 2. - region.size[0] / 2.),
2797
+ int(yPowerOf2 / 2.) - region.size[1] / 2))
2798
+ region = imP2
2799
+ return region
2800
+
2801
+ def close(self):
2802
+ """Close the window (and reset the Bits++ if necess).
2803
+ """
2804
+ self._closed = True
2805
+
2806
+ # If iohub is running, inform it to stop using this win id
2807
+ # for mouse events
2808
+ try:
2809
+ if IOHUB_ACTIVE:
2810
+ from psychopy.iohub.client import ioHubConnection
2811
+ ioHubConnection.ACTIVE_CONNECTION.unregisterWindowHandles(self._hw_handle)
2812
+ except Exception:
2813
+ pass
2814
+
2815
+ self.backend.close() # moved here, dereferencing the window prevents
2816
+ # backend specific actions to take place
2817
+
2818
+ try:
2819
+ openWindows.remove(self)
2820
+ except Exception:
2821
+ pass
2822
+
2823
+ try:
2824
+ self.mouseVisible = True
2825
+ except Exception:
2826
+ # can cause unimportant "'NoneType' object is not callable"
2827
+ pass
2828
+
2829
+ try:
2830
+ if self.bits is not None:
2831
+ self.bits.reset()
2832
+ except Exception:
2833
+ pass
2834
+ try:
2835
+ logging.flush()
2836
+ except Exception:
2837
+ pass
2838
+
2839
+ def fps(self):
2840
+ """Report the frames per second since the last call to this function
2841
+ (or since the window was created if this is first call)"""
2842
+ fps = self.frames / self.frameClock.getTime()
2843
+ self.frameClock.reset()
2844
+ self.frames = 0
2845
+ return fps
2846
+
2847
+ @property
2848
+ def depthTest(self):
2849
+ """`True` if depth testing is enabled."""
2850
+ return self._depthTest
2851
+
2852
+ @depthTest.setter
2853
+ def depthTest(self, value):
2854
+ if value is True:
2855
+ GL.glEnable(GL.GL_DEPTH_TEST)
2856
+ elif value is False:
2857
+ GL.glDisable(GL.GL_DEPTH_TEST)
2858
+ else:
2859
+ raise TypeError("Value must be boolean.")
2860
+
2861
+ self._depthTest = value
2862
+
2863
+ @property
2864
+ def depthFunc(self):
2865
+ """Depth test comparison function for rendering."""
2866
+ return self._depthFunc
2867
+
2868
+ @depthFunc.setter
2869
+ def depthFunc(self, value):
2870
+ depthFuncs = {'never': GL.GL_NEVER, 'less': GL.GL_LESS,
2871
+ 'equal': GL.GL_EQUAL, 'lequal': GL.GL_LEQUAL,
2872
+ 'greater': GL.GL_GREATER, 'notequal': GL.GL_NOTEQUAL,
2873
+ 'gequal': GL.GL_GEQUAL, 'always': GL.GL_ALWAYS}
2874
+
2875
+ GL.glDepthFunc(depthFuncs[value])
2876
+
2877
+ self._depthFunc = value
2878
+
2879
+ @property
2880
+ def depthMask(self):
2881
+ """`True` if depth masking is enabled. Writing to the depth buffer will
2882
+ be disabled.
2883
+ """
2884
+ return self._depthMask
2885
+
2886
+ @depthMask.setter
2887
+ def depthMask(self, value):
2888
+ if value is True:
2889
+ GL.glDepthMask(GL.GL_TRUE)
2890
+ elif value is False:
2891
+ GL.glDepthMask(GL.GL_FALSE)
2892
+ else:
2893
+ raise TypeError("Value must be boolean.")
2894
+
2895
+ self._depthMask = value
2896
+
2897
+ @property
2898
+ def cullFaceMode(self):
2899
+ """Face culling mode, either `back`, `front` or `both`."""
2900
+ return self._cullFaceMode
2901
+
2902
+ @cullFaceMode.setter
2903
+ def cullFaceMode(self, value):
2904
+ if value == 'back':
2905
+ GL.glCullFace(GL.GL_BACK)
2906
+ elif value == 'front':
2907
+ GL.glCullFace(GL.GL_FRONT)
2908
+ elif value == 'both':
2909
+ GL.glCullFace(GL.GL_FRONT_AND_BACK)
2910
+ else:
2911
+ raise ValueError('Invalid face cull mode.')
2912
+
2913
+ self._cullFaceMode = value
2914
+
2915
+ @property
2916
+ def cullFace(self):
2917
+ """`True` if face culling is enabled.`"""
2918
+ return self._cullFace
2919
+
2920
+ @cullFace.setter
2921
+ def cullFace(self, value):
2922
+ if value is True:
2923
+ GL.glEnable(GL.GL_CULL_FACE)
2924
+ elif value is False:
2925
+ GL.glDisable(GL.GL_CULL_FACE)
2926
+ else:
2927
+ raise TypeError('Value must be type `bool`.')
2928
+
2929
+ self._cullFace = value
2930
+
2931
+ @property
2932
+ def frontFace(self):
2933
+ """Face winding order to define front, either `ccw` or `cw`."""
2934
+ return self._frontFace
2935
+
2936
+ @frontFace.setter
2937
+ def frontFace(self, value):
2938
+ if value == 'ccw':
2939
+ GL.glFrontFace(GL.GL_CCW)
2940
+ elif value == 'cw':
2941
+ GL.glFrontFace(GL.GL_CW)
2942
+ else:
2943
+ raise ValueError('Invalid value, must be `ccw` or `cw`.')
2944
+
2945
+ self._frontFace = value
2946
+
2947
+ @property
2948
+ def draw3d(self):
2949
+ """`True` if 3D drawing is enabled on this window."""
2950
+ return self._draw3d
2951
+
2952
+ @draw3d.setter
2953
+ def draw3d(self, value):
2954
+ if value is True:
2955
+ if self.depthMask is False:
2956
+ self.depthMask = True
2957
+ if self.depthTest is False:
2958
+ self.depthTest = True
2959
+ if self.cullFace is False:
2960
+ self.cullFace = True
2961
+ elif value is False:
2962
+ if self.depthMask is True:
2963
+ self.depthMask = False
2964
+ if self.depthTest is True:
2965
+ self.depthTest = False
2966
+ if self.cullFace is True:
2967
+ self.cullFace = False
2968
+ else:
2969
+ raise TypeError('Value must be type `bool`.')
2970
+
2971
+ self._draw3d = value
2972
+
2973
+ @attributeSetter
2974
+ def blendMode(self, blendMode):
2975
+ """Blend mode to use."""
2976
+ self.__dict__['blendMode'] = blendMode
2977
+ if blendMode == 'avg':
2978
+ GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
2979
+ if hasattr(self, '_shaders'):
2980
+ self._progSignedFrag = self._shaders['signedColor']
2981
+ self._progSignedTex = self._shaders['signedTex']
2982
+ self._progSignedTexMask = self._shaders['signedTexMask']
2983
+ self._progSignedTexMask1D = self._shaders['signedTexMask1D']
2984
+ self._progImageStim = self._shaders['imageStim']
2985
+ elif blendMode == 'add':
2986
+ GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE)
2987
+ if hasattr(self, '_shaders'):
2988
+ self._progSignedFrag = self._shaders['signedColor_adding']
2989
+ self._progSignedTex = self._shaders['signedTex_adding']
2990
+ self._progSignedTexMask = self._shaders['signedTexMask_adding']
2991
+ tmp = self._shaders['signedTexMask1D_adding']
2992
+ self._progSignedTexMask1D = tmp
2993
+ self._progImageStim = self._shaders['imageStim_adding']
2994
+ else:
2995
+ raise ValueError("Window blendMode should be set to 'avg' or 'add'"
2996
+ " but we received the value {}"
2997
+ .format(repr(blendMode)))
2998
+
2999
+ def setBlendMode(self, blendMode, log=None):
3000
+ """Usually you can use 'stim.attribute = value' syntax instead,
3001
+ but use this method if you need to suppress the log message.
3002
+ """
3003
+ setAttribute(self, 'blendMode', blendMode, log)
3004
+
3005
+ @property
3006
+ def colorSpace(self):
3007
+ """The name of the color space currently being used
3008
+
3009
+ Value should be: a string or None
3010
+
3011
+ For strings and hex values this is not needed.
3012
+ If None the default colorSpace for the stimulus is
3013
+ used (defined during initialisation).
3014
+
3015
+ Please note that changing colorSpace does not change stimulus
3016
+ parameters. Thus you usually want to specify colorSpace before
3017
+ setting the color. Example::
3018
+
3019
+ # A light green text
3020
+ stim = visual.TextStim(win, 'Color me!',
3021
+ color=(0, 1, 0), colorSpace='rgb')
3022
+
3023
+ # An almost-black text
3024
+ stim.colorSpace = 'rgb255'
3025
+
3026
+ # Make it light green again
3027
+ stim.color = (128, 255, 128)
3028
+ """
3029
+ if hasattr(self, '_colorSpace'):
3030
+ return self._colorSpace
3031
+ else:
3032
+ return 'rgb'
3033
+ @colorSpace.setter
3034
+ def colorSpace(self, value):
3035
+ if value in colorSpaces:
3036
+ self._colorSpace = value
3037
+ else:
3038
+ logging.error(f"'{value}' is not a valid color space")
3039
+
3040
+ @property
3041
+ def color(self):
3042
+ """Set the color of the window.
3043
+
3044
+ This command sets the color that the blank screen will have on the
3045
+ next clear operation. As a result it effectively takes TWO
3046
+ :py:attr:`~Window.flip()` operations to become visible (the first uses
3047
+ the color to create the new screen, the second presents that screen to
3048
+ the viewer). For this reason, if you want to changed background color of
3049
+ the window "on the fly", it might be a better idea to draw a
3050
+ :py:attr:`Rect` that fills the whole window with the desired
3051
+ :py:attr:`Rect.fillColor` attribute. That'll show up on first flip.
3052
+
3053
+ See other stimuli (e.g. :py:attr:`GratingStim.color`)
3054
+ for more info on the color attribute which essentially works the same on
3055
+ all PsychoPy stimuli.
3056
+
3057
+ See :ref:`colorspaces` for further information about the ways to
3058
+ specify colors and their various implications.
3059
+ """
3060
+ if hasattr(self, '_color'):
3061
+ return getattr(self._color, self.colorSpace)
3062
+ @color.setter
3063
+ def color(self, value):
3064
+ if isinstance(value, Color):
3065
+ # If supplied with a color object, set as that
3066
+ self._color = value
3067
+ else:
3068
+ # Otherwise, use it to make a color object
3069
+ self._color = Color(value, self.colorSpace)
3070
+ if not self._color:
3071
+ self._color = Color()
3072
+ logging.error(f"'{value}' is not a valid {self.colorSpace} color")
3073
+
3074
+ # if it is None then this will be done during window setup
3075
+ if self.backend is not None:
3076
+ self.backend.setCurrent() # make sure this window is active
3077
+ GL.glClearColor(*self._color.render('rgba1'))
3078
+
3079
+ def setColor(self, color, colorSpace=None, operation='', log=None):
3080
+ """Usually you can use ``stim.attribute = value`` syntax instead,
3081
+ but use this method if you want to set color and colorSpace
3082
+ simultaneously.
3083
+
3084
+ See :py:attr:`~Window.color` for documentation on colors.
3085
+ """
3086
+ self.colorSpace = colorSpace
3087
+ self.color = color
3088
+
3089
+ def setRGB(self, newRGB):
3090
+ """Deprecated: As of v1.61.00 please use `setColor()` instead
3091
+ """
3092
+ self.setColor(newRGB, colorSpace="rgb")
3093
+
3094
+ @property
3095
+ def rgb(self):
3096
+ if hasattr(self, "_color"):
3097
+ return self._color.render("rgb")
3098
+ @rgb.setter
3099
+ def rgb(self, value):
3100
+ self.color = Color(value, 'rgb')
3101
+
3102
+ @attributeSetter
3103
+ def backgroundImage(self, value):
3104
+ """
3105
+ Background image for the window, can be either a visual.ImageStim object or anything which could be passed to
3106
+ visual.ImageStim.image to create one. Will be drawn each time `win.flip()` is called, meaning it is always
3107
+ below all other contents of the window.
3108
+ """
3109
+ if value in (None, "None", "none", ""):
3110
+ # If given None, store so we know not to use a background image
3111
+ self._backgroundImage = None
3112
+ self.__dict__['backgroundImage'] = self._backgroundImage
3113
+ return
3114
+ elif hasattr(value, "draw") and hasattr(value, "win"):
3115
+ # If given a visual object, set its parent window to self and use it
3116
+ value.win = self
3117
+ self._backgroundImage = value
3118
+ else:
3119
+ # Otherwise, try to make an image from value (start off as if backgroundFit was None)
3120
+ self._backgroundImage = image.ImageStim(self, image=value, size=None, pos=(0, 0))
3121
+
3122
+ # Set background fit again now that we have an image
3123
+ if hasattr(self, "_backgroundFit"):
3124
+ self.backgroundFit = self._backgroundFit
3125
+
3126
+ self.__dict__['backgroundImage'] = self._backgroundImage
3127
+
3128
+ @attributeSetter
3129
+ def backgroundFit(self, value):
3130
+ """
3131
+ How should the background image of this window fit? Options are:
3132
+
3133
+ None, "None", "none"
3134
+ No scaling is applied, image is present at its pixel size unaltered.
3135
+ "cover"
3136
+ Image is scaled such that it covers the whole screen without changing its aspect ratio. In other words,
3137
+ both dimensions are evenly scaled such that its SHORTEST dimension matches the window's LONGEST dimension.
3138
+ "contain"
3139
+ Image is scaled such that it is contained within the screen without changing its aspect ratio. In other
3140
+ words, both dimensions are evenly scaled such that its LONGEST dimension matches the window's SHORTEST
3141
+ dimension.
3142
+ "scaleDown", "scale-down", "scaledown"
3143
+ If image is bigger than the window along any dimension, it will behave as if backgroundFit were "contain".
3144
+ Otherwise, it will behave as if backgroundFit were None.
3145
+ """
3146
+ self._backgroundFit = value
3147
+
3148
+ # Skip if no background image
3149
+ if (not hasattr(self, "_backgroundImage")) or (self._backgroundImage is None):
3150
+ self.__dict__['backgroundFit'] = self._backgroundFit
3151
+ return
3152
+
3153
+ # If value is scaleDown or alias, set to None or "contain" based on relative size
3154
+ if value in ("scaleDown", "scale-down", "scaledown"):
3155
+ overflow = numpy.asarray(self._backgroundImage._origSize) > numpy.asarray(self.size)
3156
+ if overflow.any():
3157
+ value = "contain"
3158
+ else:
3159
+ value = None
3160
+
3161
+ if value in (None, "None", "none"):
3162
+ # If value is None, don't change the backgroundImage at all
3163
+ pass
3164
+ elif value == "fill":
3165
+ # If value is fill, make backgroundImage fill screen
3166
+ self._backgroundImage.units = "norm"
3167
+ self._backgroundImage.size = (2, 2)
3168
+ self._backgroundImage.pos = (0, 0)
3169
+ if value in ("contain", "cover"):
3170
+ # If value is contain or cover, set one dimension to fill screen and the other to maintain ratio
3171
+ ratios = numpy.asarray(self._backgroundImage._origSize) / numpy.asarray(self.size)
3172
+ if value == "cover":
3173
+ i = ratios.argmin()
3174
+ else:
3175
+ i = ratios.argmax()
3176
+ size = [None, None]
3177
+ size[i] = 2
3178
+ self._backgroundImage.units = "norm"
3179
+ self._backgroundImage.size = size
3180
+ self._backgroundImage.pos = (0, 0)
3181
+
3182
+ self.__dict__['backgroundFit'] = self._backgroundFit
3183
+
3184
+ def _setupGamma(self, gammaVal):
3185
+ """A private method to work out how to handle gamma for this Window
3186
+ given that the user might have specified an explicit value, or maybe
3187
+ gave a Monitor.
3188
+ """
3189
+ # determine which gamma value to use (or native ramp)
3190
+ if gammaVal is not None:
3191
+ self._checkGamma()
3192
+ self.useNativeGamma = False
3193
+ elif not self.monitor.gammaIsDefault():
3194
+ if self.monitor.getGamma() is not None:
3195
+ self.__dict__['gamma'] = self.monitor.getGamma()
3196
+ self.useNativeGamma = False
3197
+ else:
3198
+ self.__dict__['gamma'] = None # gamma wasn't set anywhere
3199
+ self.useNativeGamma = True
3200
+
3201
+ # then try setting it
3202
+ if self.useNativeGamma:
3203
+ if self.autoLog:
3204
+ logging.info('Using gamma table of operating system')
3205
+ else:
3206
+ if self.autoLog:
3207
+ logging.info('Using gamma: self.gamma' + str(self.gamma))
3208
+ self.gamma = gammaVal # using either pygame or bits++
3209
+
3210
+
3211
+ @attributeSetter
3212
+ def gamma(self, gamma):
3213
+ """Set the monitor gamma for linearization.
3214
+
3215
+ Warnings
3216
+ --------
3217
+ Don't use this if using a Bits++ or Bits#, as it overrides monitor
3218
+ settings.
3219
+
3220
+ """
3221
+ self._checkGamma(gamma)
3222
+
3223
+ if self.bits is not None:
3224
+ msg = ("Do not use try to set the gamma of a window with "
3225
+ "Bits++/Bits# enabled. It was ambiguous what should "
3226
+ "happen. Use the setGamma() function of the bits box "
3227
+ "instead")
3228
+ raise DeprecationWarning(msg)
3229
+
3230
+ self.backend.gamma = self.__dict__['gamma']
3231
+
3232
+ def setGamma(self, gamma, log=None):
3233
+ """Usually you can use 'stim.attribute = value' syntax instead,
3234
+ but use this method if you need to suppress the log message.
3235
+
3236
+ """
3237
+ setAttribute(self, 'gamma', gamma, log)
3238
+
3239
+ @attributeSetter
3240
+ def gammaRamp(self, newRamp):
3241
+ """Sets the hardware CLUT using a specified 3xN array of floats ranging
3242
+ between 0.0 and 1.0.
3243
+
3244
+ Array must have a number of rows equal to 2 ^ max(bpc).
3245
+
3246
+ """
3247
+ self.backend.gammaRamp = newRamp
3248
+
3249
+ def _checkGamma(self, gamma=None):
3250
+ if gamma is None:
3251
+ gamma = self.gamma
3252
+ if isinstance(gamma, (float, int)):
3253
+ self.__dict__['gamma'] = [gamma] * 3
3254
+ elif hasattr(gamma, '__iter__'):
3255
+ self.__dict__['gamma'] = gamma
3256
+ else:
3257
+ raise ValueError('gamma must be a numeric scalar or iterable')
3258
+
3259
+ def setScale(self, units, font='dummyFont', prevScale=(1.0, 1.0)):
3260
+ """DEPRECATED: this method used to be used to switch between units for
3261
+ stimulus drawing but this is now handled by the stimuli themselves and
3262
+ the window should always be left in units of 'pix'
3263
+ """
3264
+ if self.useRetina:
3265
+ retinaScale = 2.0
3266
+ else:
3267
+ retinaScale = 1.0
3268
+ # then unit-specific changes
3269
+ if units == "norm":
3270
+ thisScale = numpy.array([1.0, 1.0])
3271
+ elif units == "height":
3272
+ thisScale = numpy.array([2.0 * self.size[1] / self.size[0], 2.0])
3273
+ elif units in ["pix", "pixels"]:
3274
+ thisScale = 2.0 / numpy.array(self.size) * retinaScale
3275
+ elif units == "cm":
3276
+ # windowPerCM = windowPerPIX / CMperPIX
3277
+ # = (window/winPIX) / (scrCm/scrPIX)
3278
+ if self.scrWidthCM in [0, None] or self.scrWidthPIX in [0, None]:
3279
+ logging.error('you did not give the width of the screen (pixels'
3280
+ ' and cm). Check settings in MonitorCentre.')
3281
+ core.wait(1.0)
3282
+ core.quit()
3283
+ thisScale = ((numpy.array([2.0, 2.0]) / self.size * retinaScale)
3284
+ / (self.scrWidthCM / self.scrWidthPIX))
3285
+ elif units in ["deg", "degs"]:
3286
+ # windowPerDeg = winPerCM * CMperDEG
3287
+ # = winPerCM * tan(pi/180) * distance
3288
+ if ((self.scrWidthCM in [0, None]) or
3289
+ (self.scrWidthPIX in [0, None])):
3290
+ logging.error('you did not give the width of the screen (pixels'
3291
+ ' and cm). Check settings in MonitorCentre.')
3292
+ core.wait(1.0)
3293
+ core.quit()
3294
+ cmScale = ((numpy.array([2.0, 2.0]) / self.size) * retinaScale /
3295
+ (self.scrWidthCM / self.scrWidthPIX))
3296
+ thisScale = cmScale * 0.017455 * self.scrDistCM
3297
+ elif units == "stroke_font":
3298
+ lw = 2 * font.letterWidth
3299
+ thisScale = numpy.array([lw, lw] / self.size * retinaScale / 38.0)
3300
+ # actually set the scale as appropriate
3301
+ # allows undoing of a previous scaling procedure
3302
+ if self.USE_LEGACY_GL:
3303
+ thisScale = thisScale / numpy.asarray(prevScale)
3304
+ GL.glScalef(thisScale[0], thisScale[1], 1.0)
3305
+
3306
+ return thisScale
3307
+
3308
+ def _checkMatchingSizes(self, requested, actual):
3309
+ """Checks whether the requested and actual screen sizes differ.
3310
+ If not then a warning is output and the window size is set to actual
3311
+ """
3312
+ if list(requested) != list(actual):
3313
+ logging.warning("User requested fullscreen with size %s, "
3314
+ "but screen is actually %s. Using actual size" %
3315
+ (requested, actual))
3316
+ self.clientSize = numpy.array(actual)
3317
+
3318
+ def _setupGL(self):
3319
+ """Setup OpenGL state for this window.
3320
+ """
3321
+ # setup screen color
3322
+ self.color = self.color # call attributeSetter
3323
+ GL.glClearDepth(1.0)
3324
+
3325
+ # viewport or drawable area of the framebuffer
3326
+ self.viewport = self.scissor = \
3327
+ (0, 0, self.frameBufferSize[0], self.frameBufferSize[1])
3328
+ self.scissorTest = True
3329
+ self.stencilTest = False
3330
+ self.depthTest = False
3331
+
3332
+ if self.USE_LEGACY_GL:
3333
+ GL.glMatrixMode(GL.GL_PROJECTION) # Reset the projection matrix
3334
+ GL.glLoadIdentity()
3335
+ GL.gluOrtho2D(-1, 1, -1, 1)
3336
+
3337
+ GL.glMatrixMode(GL.GL_MODELVIEW) # Reset the modelview matrix
3338
+ GL.glLoadIdentity()
3339
+
3340
+ GL.glEnable(GL.GL_DEPTH_TEST) # Enables Depth Testing
3341
+ GL.glDepthFunc(GL.GL_LESS) # The Type Of Depth Test To Do
3342
+
3343
+ GL.glShadeModel(GL.GL_SMOOTH) # Color Shading (FLAT or SMOOTH)
3344
+ GL.glEnable(GL.GL_POINT_SMOOTH) # Enable Point Smoothing
3345
+
3346
+ GL.glEnable(GL.GL_BLEND)
3347
+
3348
+ # check for GL_ARB_texture_float
3349
+ # (which is needed for shaders to be useful)
3350
+ # this needs to be done AFTER the context has been created
3351
+ if not GL.gl_info.have_extension('GL_ARB_texture_float'):
3352
+ self._haveShaders = False
3353
+
3354
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT)
3355
+
3356
+ # identify gfx card vendor
3357
+ self.glVendor = GL.gl_info.get_vendor().lower()
3358
+
3359
+ requestedFBO = self.useFBO
3360
+ if self._haveShaders: # do this after setting up FrameBufferObject
3361
+ self._setupShaders()
3362
+ else:
3363
+ self.useFBO = False
3364
+ if self.useFBO:
3365
+ success = self._setupFrameBuffer()
3366
+ if not success:
3367
+ self.useFBO = False
3368
+ if requestedFBO and not self.useFBO:
3369
+ logging.warning("Framebuffer object (FBO) not supported on "
3370
+ "this graphics card")
3371
+ if self.blendMode == 'add' and not self.useFBO:
3372
+ logging.warning("Framebuffer object (FBO) is required for "
3373
+ "blendMode='add'. Reverting to blendMode='avg'")
3374
+ self.blendMode = 'avg'
3375
+
3376
+ def _setupShaders(self):
3377
+ if self.USE_LEGACY_GL:
3378
+ self._progSignedTexFont = _shaders.compileProgram(
3379
+ _shaders.vertSimple, _shaders.fragSignedColorTexFont)
3380
+ else:
3381
+ self._progSignedTexFont = _shaders.compileProgram(
3382
+ _shaders.vertSimpleText, _shaders.fragSignedColorTexFont)
3383
+
3384
+ self._progFBOtoFrame = _shaders.compileProgram(
3385
+ _shaders.vertSimple, _shaders.fragFBOtoFrame)
3386
+ self._shaders = {}
3387
+ self._shaders['signedColor'] = _shaders.compileProgram(
3388
+ _shaders.vertSimple, _shaders.fragSignedColor)
3389
+ self._shaders['signedColor_adding'] = _shaders.compileProgram(
3390
+ _shaders.vertSimple, _shaders.fragSignedColor_adding)
3391
+ self._shaders['signedTex'] = _shaders.compileProgram(
3392
+ _shaders.vertSimple, _shaders.fragSignedColorTex)
3393
+ self._shaders['signedTexMask'] = _shaders.compileProgram(
3394
+ _shaders.vertSimple, _shaders.fragSignedColorTexMask)
3395
+ self._shaders['signedTexMask1D'] = _shaders.compileProgram(
3396
+ _shaders.vertSimple, _shaders.fragSignedColorTexMask1D)
3397
+ self._shaders['signedTex_adding'] = _shaders.compileProgram(
3398
+ _shaders.vertSimple, _shaders.fragSignedColorTex_adding)
3399
+ self._shaders['signedTexMask_adding'] = _shaders.compileProgram(
3400
+ _shaders.vertSimple, _shaders.fragSignedColorTexMask_adding)
3401
+ self._shaders['signedTexMask1D_adding'] = _shaders.compileProgram(
3402
+ _shaders.vertSimple, _shaders.fragSignedColorTexMask1D_adding)
3403
+ self._shaders['imageStim'] = _shaders.compileProgram(
3404
+ _shaders.vertSimple, _shaders.fragImageStim)
3405
+ self._shaders['imageStim_adding'] = _shaders.compileProgram(
3406
+ _shaders.vertSimple, _shaders.fragImageStim_adding)
3407
+ # self._shaders['stim3d_phong'] = {}
3408
+
3409
+ # # Create shader flags, these are used as keys to pick the appropriate
3410
+ # # shader for the given material and lighting configuration.
3411
+ # shaderFlags = []
3412
+ # for i in range(0, 8 + 1):
3413
+ # for j in product((True, False), repeat=1):
3414
+ # shaderFlags.append((i, j[0]))
3415
+
3416
+ # # Compile shaders based on generated flags.
3417
+ # for flag in shaderFlags:
3418
+ # # Define GLSL preprocessor values to enable code paths for specific
3419
+ # # material properties.
3420
+ # srcDefs = {'MAX_LIGHTS': flag[0]}
3421
+
3422
+ # if flag[1]: # has diffuse texture map
3423
+ # srcDefs['DIFFUSE_TEXTURE'] = 1
3424
+
3425
+ # # embed #DEFINE statements in GLSL source code
3426
+ # vertSrc = gltools.embedShaderSourceDefs(
3427
+ # _shaders.vertPhongLighting, srcDefs)
3428
+ # fragSrc = gltools.embedShaderSourceDefs(
3429
+ # _shaders.fragPhongLighting, srcDefs)
3430
+
3431
+ # # build a shader program
3432
+ # prog = gltools.createProgram()
3433
+ # vertexShader = gltools.compileShader(
3434
+ # vertSrc, GL.GL_VERTEX_SHADER)
3435
+ # fragmentShader = gltools.compileShader(
3436
+ # fragSrc, GL.GL_FRAGMENT_SHADER)
3437
+
3438
+ # gltools.attachShader(prog, vertexShader)
3439
+ # gltools.attachShader(prog, fragmentShader)
3440
+ # gltools.linkProgram(prog)
3441
+ # gltools.detachShader(prog, vertexShader)
3442
+ # gltools.detachShader(prog, fragmentShader)
3443
+ # gltools.deleteShader(vertexShader)
3444
+ # gltools.deleteShader(fragmentShader)
3445
+
3446
+ # # set the flag
3447
+ # self._shaders['stim3d_phong'][flag] = prog
3448
+
3449
+ def _setupFrameBuffer(self):
3450
+ """Setup the framebuffer object for this window.
3451
+
3452
+ Returns
3453
+ -------
3454
+ bool
3455
+ `True` if the framebuffer was successfully setup, `False` otherwise.
3456
+ If `False`, the framebuffer was not complete. Make sure that your
3457
+ driver supports the necessary formats.
3458
+
3459
+ """
3460
+ # Setup framebuffer
3461
+ self.frameBuffer = GL.GLuint()
3462
+ GL.glGenFramebuffers(1, ctypes.byref(self.frameBuffer))
3463
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, self.frameBuffer)
3464
+
3465
+ # Create texture to render to
3466
+ self.frameTexture = GL.GLuint()
3467
+ GL.glGenTextures(1, ctypes.byref(self.frameTexture))
3468
+ GL.glBindTexture(GL.GL_TEXTURE_2D, self.frameTexture)
3469
+ GL.glTexParameteri(
3470
+ GL.GL_TEXTURE_2D,
3471
+ GL.GL_TEXTURE_MAG_FILTER,
3472
+ GL.GL_LINEAR)
3473
+ GL.glTexParameteri(
3474
+ GL.GL_TEXTURE_2D,
3475
+ GL.GL_TEXTURE_MIN_FILTER,
3476
+ GL.GL_LINEAR)
3477
+ GL.glTexImage2D(
3478
+ GL.GL_TEXTURE_2D, 0, GL.GL_RGBA32F,
3479
+ int(self.size[0]), int(self.size[1]), 0,
3480
+ GL.GL_RGBA, GL.GL_FLOAT, None)
3481
+ # attach texture to the frame buffer
3482
+ GL.glFramebufferTexture2D(
3483
+ GL.GL_FRAMEBUFFER,
3484
+ GL.GL_COLOR_ATTACHMENT0,
3485
+ GL.GL_TEXTURE_2D,
3486
+ self.frameTexture, 0)
3487
+
3488
+ # add a stencil buffer
3489
+ self._stencilTexture = GL.GLuint()
3490
+ GL.glGenRenderbuffers(1, ctypes.byref(
3491
+ self._stencilTexture)) # like glGenTextures
3492
+ GL.glBindRenderbuffer(GL.GL_RENDERBUFFER, self._stencilTexture)
3493
+ GL.glRenderbufferStorage(
3494
+ GL.GL_RENDERBUFFER,
3495
+ GL.GL_DEPTH24_STENCIL8,
3496
+ int(self.size[0]), int(self.size[1]))
3497
+ GL.glFramebufferRenderbuffer(
3498
+ GL.GL_FRAMEBUFFER,
3499
+ GL.GL_DEPTH_ATTACHMENT,
3500
+ GL.GL_RENDERBUFFER,
3501
+ self._stencilTexture)
3502
+ GL.glFramebufferRenderbuffer(
3503
+ GL.GL_FRAMEBUFFER,
3504
+ GL.GL_STENCIL_ATTACHMENT,
3505
+ GL.GL_RENDERBUFFER,
3506
+ self._stencilTexture)
3507
+
3508
+ # check the framebuffer status
3509
+ status = GL.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER)
3510
+ if status != GL.GL_FRAMEBUFFER_COMPLETE:
3511
+ logging.error("Error in framebuffer activation")
3512
+ # UNBIND THE FRAME BUFFER OBJECT THAT WE HAD CREATED
3513
+ GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)
3514
+
3515
+ return False
3516
+
3517
+ GL.glDisable(GL.GL_TEXTURE_2D)
3518
+
3519
+ # clear the buffers (otherwise the texture memory can contain
3520
+ # junk from other app)
3521
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT)
3522
+ GL.glClear(GL.GL_STENCIL_BUFFER_BIT)
3523
+ GL.glClear(GL.GL_DEPTH_BUFFER_BIT)
3524
+
3525
+ return True
3526
+
3527
+ @property
3528
+ def mouseVisible(self):
3529
+ """Returns the visibility of the mouse cursor."""
3530
+ return self.backend.mouseVisible
3531
+
3532
+ @mouseVisible.setter
3533
+ def mouseVisible(self, visibility):
3534
+ """Sets the visibility of the mouse cursor.
3535
+
3536
+ If Window was initialized with ``allowGUI=False`` then the mouse is
3537
+ initially set to invisible, otherwise it will initially be visible.
3538
+
3539
+ Usage::
3540
+
3541
+ win.mouseVisible = False
3542
+ win.mouseVisible = True
3543
+
3544
+ """
3545
+ self.backend.setMouseVisibility(visibility)
3546
+
3547
+ def setMouseVisible(self, visibility, log=None):
3548
+ """Usually you can use 'stim.attribute = value' syntax instead,
3549
+ but use this method if you need to suppress the log message."""
3550
+ setAttribute(self, 'mouseVisible', visibility, log)
3551
+
3552
+ def setMouseType(self, name='arrow'):
3553
+ """Change the appearance of the cursor for this window. Cursor types
3554
+ provide contextual hints about how to interact with on-screen objects.
3555
+
3556
+ The graphics used 'standard cursors' provided by the operating system.
3557
+ They may vary in appearance and hot spot location across platforms. The
3558
+ following names are valid on most platforms:
3559
+
3560
+ * ``arrow`` : Default pointer.
3561
+ * ``ibeam`` : Indicates text can be edited.
3562
+ * ``crosshair`` : Crosshair with hot-spot at center.
3563
+ * ``hand`` : A pointing hand.
3564
+ * ``hresize`` : Double arrows pointing horizontally.
3565
+ * ``vresize`` : Double arrows pointing vertically.
3566
+
3567
+ Parameters
3568
+ ----------
3569
+ name : str
3570
+ Type of standard cursor to use (see above). Default is ``arrow``.
3571
+
3572
+ Notes
3573
+ -----
3574
+ * On Windows the ``crosshair`` option is negated with the background
3575
+ color. It will not be visible when placed over 50% grey fields.
3576
+
3577
+ """
3578
+ if hasattr(self.backend, "setMouseType"):
3579
+ self.backend.setMouseType(name)
3580
+
3581
+ def showPilotingIndicator(self):
3582
+ """
3583
+ Show the visual indicator which shows we are in piloting mode.
3584
+ """
3585
+ # if we haven't made the indicator yet, do that now
3586
+ if self._pilotingIndicator is None:
3587
+ self._pilotingIndicator = TextBox2(
3588
+ self, text=_translate("PILOTING: Switch to run mode before testing."),
3589
+ letterHeight=0.1, alignment="bottom left",
3590
+ units="norm", size=(2, 2),
3591
+ borderColor="#EC9703", color="#EC9703", fillColor="transparent",
3592
+ borderWidth=20,
3593
+ autoDraw=False
3594
+ )
3595
+ # mark it as to be shown
3596
+ self._showPilotingIndicator = True
3597
+
3598
+ def hidePilotingIndicator(self):
3599
+ """
3600
+ Hide the visual indicator which shows we are in piloting mode.
3601
+ """
3602
+ # mark indicator as to be hidden
3603
+ self._showPilotingIndicator = False
3604
+
3605
+ def showMessage(self, msg):
3606
+ """Show a message in the window. This can be used to show information
3607
+ to the participant.
3608
+
3609
+ This creates a TextBox2 object that is displayed in the window. The
3610
+ text can be updated by calling this method again with a new message.
3611
+ The updated text will appear the next time `draw()` is called.
3612
+
3613
+ Parameters
3614
+ ----------
3615
+ msg : str or None
3616
+ Message text to display. If None, then any existing message is
3617
+ removed.
3618
+
3619
+ """
3620
+ if msg is None:
3621
+ self.hideMessage()
3622
+ else:
3623
+ self._showSplash = True
3624
+
3625
+ if self._splashTextbox is None: # create the textbox
3626
+ self._splashTextbox = TextBox2(
3627
+ self, text=msg,
3628
+ units="norm", size=(2, 2), alignment="center", # full screen and centred
3629
+ letterHeight=0.1, # font size relative to window
3630
+ autoDraw=False
3631
+ )
3632
+ else:
3633
+ self._splashTextbox.text = str(msg) # update the text
3634
+ # set text color to contrast with background
3635
+ self._splashTextbox.color = self._color.getReadable(contrast=1)
3636
+
3637
+ def hideMessage(self):
3638
+ """Remove any message that is currently being displayed."""
3639
+ self._showSplash = False
3640
+
3641
+ def getActualFrameRate(self, nIdentical=10, nMaxFrames=100,
3642
+ nWarmUpFrames=10, threshold=1, infoMsg=None):
3643
+ """Measures the actual frames-per-second (FPS) for the screen.
3644
+
3645
+ This is done by waiting (for a max of `nMaxFrames`) until
3646
+ `nIdentical` frames in a row have identical frame times (std dev below
3647
+ `threshold` ms).
3648
+
3649
+ Parameters
3650
+ ----------
3651
+ nIdentical : int, optional
3652
+ The number of consecutive frames that will be evaluated.
3653
+ Higher --> greater precision. Lower --> faster.
3654
+ nMaxFrames : int, optional
3655
+ The maximum number of frames to wait for a matching set of
3656
+ nIdentical.
3657
+ nWarmUpFrames : int, optional
3658
+ The number of frames to display before starting the test
3659
+ (this is in place to allow the system to settle after opening
3660
+ the `Window` for the first time.
3661
+ threshold : int or float, optional
3662
+ The threshold for the std deviation (in ms) before the set
3663
+ are considered a match.
3664
+
3665
+ Returns
3666
+ -------
3667
+ float or None
3668
+ Frame rate (FPS) in seconds. If there is no such sequence of
3669
+ identical frames a warning is logged and `None` will be returned.
3670
+
3671
+ """
3672
+ if nIdentical > nMaxFrames:
3673
+ raise ValueError(
3674
+ 'Parameter `nIdentical` must be equal to or less than '
3675
+ '`nMaxFrames`')
3676
+
3677
+ screen = self.screen
3678
+ name = self.name
3679
+
3680
+ if infoMsg is None:
3681
+ infoMsg = "Attempting to measure frame rate of screen, please wait ..."
3682
+
3683
+ self.showMessage(infoMsg)
3684
+
3685
+ # log that we're measuring the frame rate now
3686
+ if self.autoLog:
3687
+ msg = "{}: Attempting to measure frame rate of screen ({:d}) ..."
3688
+ logging.exp(msg.format(name, screen))
3689
+
3690
+ # Disable `recordFrameIntervals` prior to the warmup as we expect to see
3691
+ # some instability here.
3692
+ recordFrmIntsOrig = self.recordFrameIntervals
3693
+ self.recordFrameIntervals = False
3694
+
3695
+ # warm-up, allow the system to settle a bit before measuring frames
3696
+ for frameN in range(nWarmUpFrames):
3697
+ self.flip()
3698
+
3699
+ # run test frames
3700
+ self.recordFrameIntervals = True # record intervals for actual test
3701
+ threshSecs = threshold / 1000.0 # must be in seconds
3702
+ for frameN in range(nMaxFrames):
3703
+ self.flip()
3704
+ recentFrames = self.frameIntervals[-nIdentical:]
3705
+ nIntervals = len(self.frameIntervals)
3706
+ if len(recentFrames) < 3:
3707
+ continue # no need to check variance yet
3708
+ recentFramesStd = numpy.std(recentFrames) # compute variability
3709
+ if nIntervals >= nIdentical and recentFramesStd < threshSecs:
3710
+ # average duration of recent frames
3711
+ period = numpy.mean(recentFrames) # log this too?
3712
+ rate = 1.0 / period # compute frame rate in Hz
3713
+ if self.autoLog:
3714
+ scrStr = "" if screen is None else " (%i)" % screen
3715
+ msg = "Screen{} actual frame rate measured at {:.2f}Hz"
3716
+ logging.exp(msg.format(scrStr, rate))
3717
+
3718
+ self.recordFrameIntervals = recordFrmIntsOrig
3719
+ self.frameIntervals = []
3720
+ self.hideMessage() # remove the message
3721
+ return rate
3722
+
3723
+ self.hideMessage() # remove the message
3724
+
3725
+ # if we get here we reached end of `maxFrames` with no consistent value
3726
+ msg = ("Couldn't measure a consistent frame rate!\n"
3727
+ " - Is your graphics card set to sync to vertical blank?\n"
3728
+ " - Are you running other processes on your computer?\n")
3729
+ logging.warning(msg)
3730
+
3731
+ return None
3732
+
3733
+ def getMsPerFrame(self, nFrames=60, showVisual=False, msg='', msDelay=0.):
3734
+ """Assesses the monitor refresh rate (average, median, SD) under
3735
+ current conditions, over at least 60 frames.
3736
+
3737
+ Records time for each refresh (frame) for n frames (at least 60),
3738
+ while displaying an optional visual. The visual is just eye-candy to
3739
+ show that something is happening when assessing many frames. You can
3740
+ also give it text to display instead of a visual,
3741
+ e.g., ``msg='(testing refresh rate...)'``; setting msg implies
3742
+ ``showVisual == False``.
3743
+
3744
+ To simulate refresh rate under cpu load, you can specify a time to
3745
+ wait within the loop prior to doing the :py:attr:`~Window.flip()`.
3746
+ If 0 < msDelay < 100, wait for that long in ms.
3747
+
3748
+ Returns timing stats (in ms) of:
3749
+
3750
+ - average time per frame, for all frames
3751
+ - standard deviation of all frames
3752
+ - median, as the average of 12 frame times around the median
3753
+ (~monitor refresh rate)
3754
+
3755
+ :Author:
3756
+ - 2010 written by Jeremy Gray
3757
+
3758
+ """
3759
+
3760
+ # lower bound of 60 samples--need enough to estimate the SD
3761
+ nFrames = max(60, nFrames)
3762
+ num2avg = 12 # how many to average from around the median
3763
+ if len(msg):
3764
+ showVisual = False
3765
+ showText = True
3766
+ myMsg = TextStim(self, text=msg, italic=True,
3767
+ color=(.7, .6, .5), colorSpace='rgb',
3768
+ height=0.1, autoLog=False)
3769
+ else:
3770
+ showText = False
3771
+ if showVisual:
3772
+ x, y = self.size
3773
+ myStim = GratingStim(self, tex='sin', mask='gauss',
3774
+ size=[.6 * y / float(x), .6], sf=3.0,
3775
+ opacity=.2,
3776
+ autoLog=False)
3777
+ clockt = [] # clock times
3778
+ # end of drawing time, in clock time units,
3779
+ # for testing how long myStim.draw() takes
3780
+ drawt = []
3781
+
3782
+ if msDelay > 0 and msDelay < 100:
3783
+ doWait = True
3784
+ delayTime = msDelay / 1000. # sec
3785
+ else:
3786
+ doWait = False
3787
+
3788
+ winUnitsSaved = self.units
3789
+ # norm is required for the visual (or text) display, as coded below
3790
+ self.units = 'norm'
3791
+
3792
+ # accumulate secs per frame (and time-to-draw) for a bunch of frames:
3793
+ rush(True)
3794
+ for i in range(5): # wake everybody up
3795
+ self.flip()
3796
+ for i in range(nFrames): # ... and go for real this time
3797
+ clockt.append(core.getTime())
3798
+ if showVisual:
3799
+ myStim.setPhase(1.0 / nFrames, '+', log=False)
3800
+ myStim.setSF(3. / nFrames, '+', log=False)
3801
+ myStim.setOri(12. / nFrames, '+', log=False)
3802
+ myStim.setOpacity(.9 / nFrames, '+', log=False)
3803
+ myStim.draw()
3804
+ elif showText:
3805
+ myMsg.draw()
3806
+ if doWait:
3807
+ core.wait(delayTime)
3808
+ drawt.append(core.getTime())
3809
+ self.flip()
3810
+ rush(False)
3811
+
3812
+ self.units = winUnitsSaved # restore
3813
+
3814
+ frameTimes = [(clockt[i] - clockt[i - 1])
3815
+ for i in range(1, len(clockt))]
3816
+ drawTimes = [(drawt[i] - clockt[i]) for
3817
+ i in range(len(clockt))] # == drawing only
3818
+ freeTimes = [frameTimes[i] - drawTimes[i] for
3819
+ i in range(len(frameTimes))] # == unused time
3820
+
3821
+ # cast to float so that the resulting type == type(0.123)
3822
+ # for median
3823
+ frameTimes.sort()
3824
+ # median-most slice
3825
+ msPFmed = 1000. * float(numpy.average(
3826
+ frameTimes[((nFrames - num2avg) // 2):((nFrames + num2avg) // 2)]))
3827
+ msPFavg = 1000. * float(numpy.average(frameTimes))
3828
+ msPFstd = 1000. * float(numpy.std(frameTimes))
3829
+ msdrawAvg = 1000. * float(numpy.average(drawTimes))
3830
+ msdrawSD = 1000. * float(numpy.std(drawTimes))
3831
+ msfree = 1000. * float(numpy.average(freeTimes))
3832
+
3833
+ return msPFavg, msPFstd, msPFmed # msdrawAvg, msdrawSD, msfree
3834
+
3835
+ def _startOfFlip(self):
3836
+ """Custom hardware classes may want to prevent flipping from
3837
+ occurring and can override this method as needed.
3838
+
3839
+ Return `True` to indicate hardware flip.
3840
+ """
3841
+ return True
3842
+
3843
+ def _renderFBO(self):
3844
+ """Perform a warp operation.
3845
+
3846
+ (in this case a copy operation without any warping)
3847
+ """
3848
+ if self.USE_LEGACY_GL:
3849
+ GL.glBegin(GL.GL_QUADS)
3850
+ GL.glTexCoord2f(0.0, 0.0)
3851
+ GL.glVertex2f(-1.0, -1.0)
3852
+ GL.glTexCoord2f(0.0, 1.0)
3853
+ GL.glVertex2f(-1.0, 1.0)
3854
+ GL.glTexCoord2f(1.0, 1.0)
3855
+ GL.glVertex2f(1.0, 1.0)
3856
+ GL.glTexCoord2f(1.0, 0.0)
3857
+ GL.glVertex2f(1.0, -1.0)
3858
+ GL.glEnd()
3859
+ else:
3860
+ gltools.setUniformSampler2D(self._progFBOtoFrame, b'texture', 0)
3861
+ gltools.drawClientArrays({
3862
+ 'gl_Vertex': self._fboVerts,
3863
+ 'gl_MultiTexCoord0': self._fboTexCoords},
3864
+ 'GL_QUADS')
3865
+
3866
+ def _prepareFBOrender(self):
3867
+ gltools.useProgram(self._progFBOtoFrame)
3868
+
3869
+ def _finishFBOrender(self):
3870
+ gltools.useProgram(None)
3871
+
3872
+ def _afterFBOrender(self):
3873
+ pass
3874
+
3875
+ def _endOfFlip(self, clearBuffer):
3876
+ """Override end of flip with custom color channel masking if required.
3877
+ """
3878
+ if clearBuffer:
3879
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT)
3880
+
3881
+
3882
+ def getMsPerFrame(myWin, nFrames=60, showVisual=False, msg='', msDelay=0.):
3883
+ """
3884
+ Deprecated: please use the getMsPerFrame method in the
3885
+ `psychopy.visual.Window` class.
3886
+
3887
+ Assesses the monitor refresh rate (average, median, SD) under current
3888
+ conditions, over at least 60 frames.
3889
+
3890
+ Records time for each refresh (frame) for n frames (at least 60), while
3891
+ displaying an optional visual. The visual is just eye-candy to show that
3892
+ something is happening when assessing many frames. You can also give it
3893
+ text to display instead of a visual, e.g.,
3894
+ msg='(testing refresh rate...)'; setting msg implies showVisual == False.
3895
+ To simulate refresh rate under
3896
+ cpu load, you can specify a time to wait within the loop prior to
3897
+ doing the win.flip(). If 0 < msDelay < 100, wait for that long in ms.
3898
+
3899
+ Returns timing stats (in ms) of:
3900
+
3901
+ - average time per frame, for all frames
3902
+ - standard deviation of all frames
3903
+ - median, as the average of 12 frame times around the median
3904
+ (~monitor refresh rate)
3905
+
3906
+ :Author:
3907
+ - 2010 written by Jeremy Gray
3908
+ """
3909
+ return myWin.getMsPerFrame(nFrames=60, showVisual=showVisual, msg=msg,
3910
+ msDelay=0.)