psychopy 2024.2.5__py3-none-any.whl → 2025.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of psychopy might be problematic. Click here for more details.
- psychopy/CHANGELOG.txt +4 -4
- psychopy/GIT_SHA +1 -1
- psychopy/LICENSE.txt +1 -1
- psychopy/VERSION +1 -1
- psychopy/__init__.py +10 -7
- psychopy/alerts/__init__.py +1 -1
- psychopy/alerts/_alerts.py +53 -17
- psychopy/alerts/_errorHandler.py +3 -4
- psychopy/alerts/alertsCatalogue/3210.yaml +27 -0
- psychopy/alerts/alertsCatalogue/3610.yaml +19 -0
- psychopy/alerts/alertsCatalogue/4130.yaml +19 -0
- psychopy/alerts/alertsCatalogue/alertCategories.yaml +8 -1
- psychopy/alerts/alertsCatalogue/alertmsg.py +1 -1
- psychopy/alerts/alerttools.py +0 -16
- psychopy/app/Resources/betasplash.png +0 -0
- psychopy/app/Resources/betasplash@2x.png +0 -0
- psychopy/app/Resources/classic/case.png +0 -0
- psychopy/app/Resources/classic/case@2x.png +0 -0
- psychopy/app/Resources/classic/fileaudio.png +0 -0
- psychopy/app/Resources/classic/fileaudio@2x.png +0 -0
- psychopy/app/Resources/classic/filecss.png +0 -0
- psychopy/app/Resources/classic/filecss@2x.png +0 -0
- psychopy/app/Resources/classic/filecsv.png +0 -0
- psychopy/app/Resources/classic/filecsv@2x.png +0 -0
- psychopy/app/Resources/classic/filedesign.png +0 -0
- psychopy/app/Resources/classic/filedesign@2x.png +0 -0
- psychopy/app/Resources/classic/filefont.png +0 -0
- psychopy/app/Resources/classic/filefont@2x.png +0 -0
- psychopy/app/Resources/classic/filegit.png +0 -0
- psychopy/app/Resources/classic/filegit@2x.png +0 -0
- psychopy/app/Resources/classic/filehtml.png +0 -0
- psychopy/app/Resources/classic/filehtml@2x.png +0 -0
- psychopy/app/Resources/classic/fileimage.png +0 -0
- psychopy/app/Resources/classic/fileimage@2x.png +0 -0
- psychopy/app/Resources/classic/fileinfo.png +0 -0
- psychopy/app/Resources/classic/fileinfo@2x.png +0 -0
- psychopy/app/Resources/classic/filejs.png +0 -0
- psychopy/app/Resources/classic/filejs@2x.png +0 -0
- psychopy/app/Resources/classic/filejson.png +0 -0
- psychopy/app/Resources/classic/filejson@2x.png +0 -0
- psychopy/app/Resources/classic/filepkg.png +0 -0
- psychopy/app/Resources/classic/filepkg@2x.png +0 -0
- psychopy/app/Resources/classic/filepsyexp.png +0 -0
- psychopy/app/Resources/classic/filepsyexp@2x.png +0 -0
- psychopy/app/Resources/classic/filepy.png +0 -0
- psychopy/app/Resources/classic/filepy@2x.png +0 -0
- psychopy/app/Resources/classic/filetxt.png +0 -0
- psychopy/app/Resources/classic/filetxt@2x.png +0 -0
- psychopy/app/Resources/classic/fileunknown.png +0 -0
- psychopy/app/Resources/classic/fileunknown@2x.png +0 -0
- psychopy/app/Resources/classic/filevideo.png +0 -0
- psychopy/app/Resources/classic/filevideo@2x.png +0 -0
- psychopy/app/Resources/classic/find.png +0 -0
- psychopy/app/Resources/classic/find@2x.png +0 -0
- psychopy/app/Resources/classic/loop.png +0 -0
- psychopy/app/Resources/classic/loop@2x.png +0 -0
- psychopy/app/Resources/classic/regex.png +0 -0
- psychopy/app/Resources/classic/regex@2x.png +0 -0
- psychopy/app/Resources/dark/case.png +0 -0
- psychopy/app/Resources/dark/case@2x.png +0 -0
- psychopy/app/Resources/dark/fileaudio.png +0 -0
- psychopy/app/Resources/dark/fileaudio@2x.png +0 -0
- psychopy/app/Resources/dark/filecss.png +0 -0
- psychopy/app/Resources/dark/filecss@2x.png +0 -0
- psychopy/app/Resources/dark/filecsv.png +0 -0
- psychopy/app/Resources/dark/filecsv@2x.png +0 -0
- psychopy/app/Resources/dark/filedesign.png +0 -0
- psychopy/app/Resources/dark/filedesign@2x.png +0 -0
- psychopy/app/Resources/dark/filefont.png +0 -0
- psychopy/app/Resources/dark/filefont@2x.png +0 -0
- psychopy/app/Resources/dark/filegit.png +0 -0
- psychopy/app/Resources/dark/filegit@2x.png +0 -0
- psychopy/app/Resources/dark/filehtml.png +0 -0
- psychopy/app/Resources/dark/filehtml@2x.png +0 -0
- psychopy/app/Resources/dark/fileimage.png +0 -0
- psychopy/app/Resources/dark/fileimage@2x.png +0 -0
- psychopy/app/Resources/dark/fileinfo.png +0 -0
- psychopy/app/Resources/dark/fileinfo@2x.png +0 -0
- psychopy/app/Resources/dark/filejs.png +0 -0
- psychopy/app/Resources/dark/filejs@2x.png +0 -0
- psychopy/app/Resources/dark/filejson.png +0 -0
- psychopy/app/Resources/dark/filejson@2x.png +0 -0
- psychopy/app/Resources/dark/filepkg.png +0 -0
- psychopy/app/Resources/dark/filepkg@2x.png +0 -0
- psychopy/app/Resources/dark/filepsyexp.png +0 -0
- psychopy/app/Resources/dark/filepsyexp@2x.png +0 -0
- psychopy/app/Resources/dark/filepy.png +0 -0
- psychopy/app/Resources/dark/filepy@2x.png +0 -0
- psychopy/app/Resources/dark/filetxt.png +0 -0
- psychopy/app/Resources/dark/filetxt@2x.png +0 -0
- psychopy/app/Resources/dark/fileunknown.png +0 -0
- psychopy/app/Resources/dark/fileunknown@2x.png +0 -0
- psychopy/app/Resources/dark/filevideo.png +0 -0
- psychopy/app/Resources/dark/filevideo@2x.png +0 -0
- psychopy/app/Resources/dark/find.png +0 -0
- psychopy/app/Resources/dark/find@2x.png +0 -0
- psychopy/app/Resources/dark/loop.png +0 -0
- psychopy/app/Resources/dark/loop@2x.png +0 -0
- psychopy/app/Resources/dark/regex.png +0 -0
- psychopy/app/Resources/dark/regex@2x.png +0 -0
- psychopy/app/Resources/light/case.png +0 -0
- psychopy/app/Resources/light/case@2x.png +0 -0
- psychopy/app/Resources/light/fileaudio.png +0 -0
- psychopy/app/Resources/light/fileaudio@2x.png +0 -0
- psychopy/app/Resources/light/filecss.png +0 -0
- psychopy/app/Resources/light/filecss@2x.png +0 -0
- psychopy/app/Resources/light/filecsv.png +0 -0
- psychopy/app/Resources/light/filecsv@2x.png +0 -0
- psychopy/app/Resources/light/filedesign.png +0 -0
- psychopy/app/Resources/light/filedesign@2x.png +0 -0
- psychopy/app/Resources/light/filefont.png +0 -0
- psychopy/app/Resources/light/filefont@2x.png +0 -0
- psychopy/app/Resources/light/filegit.png +0 -0
- psychopy/app/Resources/light/filegit@2x.png +0 -0
- psychopy/app/Resources/light/filehtml.png +0 -0
- psychopy/app/Resources/light/filehtml@2x.png +0 -0
- psychopy/app/Resources/light/fileimage.png +0 -0
- psychopy/app/Resources/light/fileimage@2x.png +0 -0
- psychopy/app/Resources/light/fileinfo.png +0 -0
- psychopy/app/Resources/light/fileinfo@2x.png +0 -0
- psychopy/app/Resources/light/filejs.png +0 -0
- psychopy/app/Resources/light/filejs@2x.png +0 -0
- psychopy/app/Resources/light/filejson.png +0 -0
- psychopy/app/Resources/light/filejson@2x.png +0 -0
- psychopy/app/Resources/light/filepkg.png +0 -0
- psychopy/app/Resources/light/filepkg@2x.png +0 -0
- psychopy/app/Resources/light/filepsyexp.png +0 -0
- psychopy/app/Resources/light/filepsyexp@2x.png +0 -0
- psychopy/app/Resources/light/filepy.png +0 -0
- psychopy/app/Resources/light/filepy@2x.png +0 -0
- psychopy/app/Resources/light/filetxt.png +0 -0
- psychopy/app/Resources/light/filetxt@2x.png +0 -0
- psychopy/app/Resources/light/fileunknown.png +0 -0
- psychopy/app/Resources/light/fileunknown@2x.png +0 -0
- psychopy/app/Resources/light/filevideo.png +0 -0
- psychopy/app/Resources/light/filevideo@2x.png +0 -0
- psychopy/app/Resources/light/find.png +0 -0
- psychopy/app/Resources/light/find@2x.png +0 -0
- psychopy/app/Resources/light/loop.png +0 -0
- psychopy/app/Resources/light/loop@2x.png +0 -0
- psychopy/app/Resources/light/regex.png +0 -0
- psychopy/app/Resources/light/regex@2x.png +0 -0
- psychopy/app/Resources/routine_templates/Basic.psyexp +0 -1
- psychopy/app/Resources/routine_templates/Misc.psyexp +0 -1
- psychopy/app/Resources/routine_templates/Online.psyexp +0 -2
- psychopy/app/Resources/routine_templates/Trials.psyexp +0 -1
- psychopy/app/Resources/splash.png +0 -0
- psychopy/app/Resources/splash@2x.png +0 -0
- psychopy/app/__init__.py +49 -8
- psychopy/app/__main__.py +3 -0
- psychopy/app/_psychopyApp.py +134 -125
- psychopy/app/builder/builder.py +42 -22
- psychopy/app/builder/dialogs/__init__.py +44 -11
- psychopy/app/builder/dialogs/dlgsCode.py +1 -1
- psychopy/app/builder/dialogs/dlgsConditions.py +1 -1
- psychopy/app/builder/dialogs/findDlg.py +106 -20
- psychopy/app/builder/dialogs/paramCtrls.py +42 -1
- psychopy/app/builder/validators.py +1 -1
- psychopy/app/coder/codeEditorBase.py +8 -8
- psychopy/app/coder/coder.py +32 -29
- psychopy/app/coder/fileBrowser.py +68 -22
- psychopy/app/coder/folding.py +1 -1
- psychopy/app/coder/psychoParser.py +1 -1
- psychopy/app/coder/repl.py +1 -1
- psychopy/app/coder/sourceTree.py +1 -1
- psychopy/app/connections/__init__.py +1 -1
- psychopy/app/connections/news.py +1 -1
- psychopy/app/connections/sendusage.py +1 -1
- psychopy/app/connections/updates.py +1 -1
- psychopy/app/console.py +1 -1
- psychopy/app/errorDlg.py +1 -1
- psychopy/app/frametracker.py +1 -1
- psychopy/app/idle.py +1 -1
- psychopy/app/jobs.py +5 -2
- psychopy/app/linuxconfig/__init__.py +1 -1
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +4 -4
- psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +3 -3
- psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +4 -4
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +4 -4
- psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_US/LC_MESSAGE/messages.po +4 -4
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +1 -1
- psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +3421 -2396
- psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +4 -4
- psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +2 -2
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +3 -3
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +2 -2
- psychopy/app/{builder/localizedStrings.py → localizedStrings.py} +173 -26
- psychopy/app/pavlovia_ui/__init__.py +1 -1
- psychopy/app/pavlovia_ui/_base.py +1 -1
- psychopy/app/pavlovia_ui/functions.py +1 -1
- psychopy/app/pavlovia_ui/menu.py +1 -1
- psychopy/app/pavlovia_ui/project.py +1 -1
- psychopy/app/pavlovia_ui/search.py +1 -1
- psychopy/app/pavlovia_ui/sync.py +1 -1
- psychopy/app/pavlovia_ui/user.py +1 -1
- psychopy/app/plugin_manager/dialog.py +34 -96
- psychopy/app/plugin_manager/packages.py +10 -14
- psychopy/app/plugin_manager/plugins.py +64 -4
- psychopy/app/preferencesDlg.py +12 -37
- psychopy/app/psychopyApp.py +130 -44
- psychopy/app/ribbon.py +1 -0
- psychopy/app/runner/runner.py +19 -7
- psychopy/app/runner/scriptProcess.py +11 -6
- psychopy/app/stdout/stdOutRich.py +9 -2
- psychopy/app/themes/fonts.py +1 -1
- psychopy/app/themes/icons.py +2 -38
- psychopy/app/ui/__init__.py +1 -1
- psychopy/app/utils.py +3 -3
- psychopy/assets/default.mp3 +0 -0
- psychopy/assets/fonts/NotoSans-Bold.ttf +0 -0
- psychopy/assets/fonts/NotoSans-BoldItalic.ttf +0 -0
- psychopy/assets/fonts/NotoSans-Italic.ttf +0 -0
- psychopy/assets/fonts/NotoSans-Regular.ttf +0 -0
- psychopy/assets/voicekeyThresholdStim.wav +0 -0
- psychopy/clock.py +4 -1
- psychopy/colors.py +12 -5
- psychopy/core.py +1 -1
- psychopy/data/base.py +1 -1
- psychopy/data/experiment.py +151 -46
- psychopy/data/routine.py +27 -1
- psychopy/data/staircase.py +2 -1
- psychopy/data/trial.py +62 -14
- psychopy/data/utils.py +2 -2
- psychopy/demos/builder/Design Templates/branchedExperiment/branchedExperiment.psyexp +333 -218
- psychopy/demos/builder/Design Templates/psychophysicsStaircase/psychophysicsStaircase.psyexp +261 -239
- psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/psychophysicsStaircaseInterleaved.psyexp +319 -180
- psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.psyexp +204 -116
- psychopy/demos/builder/Experiments/BART/assets/background.jpg +0 -0
- psychopy/demos/builder/Experiments/BART/assets/blueBalloon.png +0 -0
- psychopy/demos/builder/Experiments/BART/assets/greenBalloon.png +0 -0
- psychopy/demos/builder/Experiments/BART/assets/redBalloon.png +0 -0
- psychopy/demos/builder/Experiments/BART/bart.psyexp +779 -866
- psychopy/demos/builder/Experiments/BigFiveInventory/BFI.psyexp +242 -180
- psychopy/demos/builder/Experiments/GoNoGo/gng.psyexp +419 -406
- psychopy/demos/builder/Experiments/dragAndDrop/README.md +2 -37
- psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +460 -1204
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/blank_grid.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/make_shapes.psyexp +221 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/readme.md +4 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_1.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_10.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_2.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_3.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_4.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_5.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_6.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_7.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_8.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_9.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solutions.xlsx +0 -0
- psychopy/demos/builder/Experiments/mentalRotation/MentalRotation.psyexp +583 -542
- psychopy/demos/builder/Experiments/navon/NavonTask.psyexp +458 -427
- psychopy/demos/builder/Experiments/sternberg/sternberg.psyexp +588 -550
- psychopy/demos/builder/Experiments/stroop/stroop.psyexp +303 -207
- psychopy/demos/builder/Experiments/stroopExtended/stroop.psyexp +390 -215
- psychopy/demos/builder/Experiments/stroopExtended/stroopReverse.psyexp +390 -215
- psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +357 -331
- psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +3 -2
- psychopy/demos/builder/Feature Demos/counterbalance/counterbalance.psyexp +287 -277
- psychopy/demos/builder/Feature Demos/gratings/gratings.psyexp +370 -320
- psychopy/demos/builder/Feature Demos/noise/noise.psyexp +452 -399
- psychopy/demos/builder/Feature Demos/panorama/panorama.psyexp +168 -133
- psychopy/demos/builder/Feature Demos/pilotMode/pilotMode.psyexp +4 -3
- psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp +420 -392
- psychopy/demos/builder/Feature Demos/sliders/sliders.psyexp +917 -871
- psychopy/demos/builder/Feature Demos/visualValidator/readme.md +7 -0
- psychopy/demos/builder/Feature Demos/visualValidator/visualValidator.psyexp +200 -0
- psychopy/demos/builder/Hardware/EEG_parallel_component/EEG_triggers_parallel_comp.psyexp +25 -9
- psychopy/demos/builder/Hardware/EEG_serial_code/EEG_triggers_serial_code.psyexp +372 -361
- psychopy/demos/builder/Hardware/EEG_serial_component/EEG_triggers_serial_comp.psyexp +25 -9
- psychopy/demos/builder/Hardware/EGI_netstation/stroop.psyexp +320 -235
- psychopy/demos/builder/Hardware/Eyetracking_visual_search/visualSearch.psyexp +790 -651
- psychopy/demos/builder/Hardware/camera/camera.psyexp +326 -246
- psychopy/demos/builder/Hardware/eyetracking/eyetracking.psyexp +432 -327
- psychopy/demos/builder/Hardware/eyetracking_custom_cal/eyetracking_custom_cal.psyexp +440 -321
- psychopy/demos/builder/Hardware/fMRI/fMRI_demo.psyexp +190 -181
- psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo.psyexp +323 -312
- psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo_legacy.psyexp +360 -0
- psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo_legacy_legacy.psyexp +312 -0
- psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy.psyexp +329 -273
- psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy.psyexp +360 -0
- psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy_legacy.psyexp +312 -0
- psychopy/demos/builder/Hardware/microphone/microphone.psyexp +450 -404
- psychopy/demos/builder/Hardware/pump/pump.psyexp +593 -329
- psychopy/demos/builder/Helper Tools/achorVSalignment/FlowCircular-Regular.ttf +0 -0
- psychopy/demos/builder/Helper Tools/achorVSalignment/anchorAlignment.psyexp +336 -274
- psychopy/demos/builder/Helper Tools/clockFace/clockFace.psyexp +200 -149
- psychopy/demos/builder/Helper Tools/colors/colors.psyexp +300 -279
- psychopy/demos/builder/Helper Tools/drawPolygon/drawPolygon.psyexp +677 -564
- psychopy/demos/builder/Helper Tools/keyNameFinder/keyNameFinder.psyexp +214 -158
- psychopy/demos/builder/Helper Tools/spatialUnits/unitDemo.psyexp +195 -146
- psychopy/demos/coder/experiment control/runtimeInfo.py +1 -1
- psychopy/devices/__init__.py +1 -1
- psychopy/event.py +1 -1
- psychopy/exceptions.py +1 -1
- psychopy/experiment/__init__.py +1 -1
- psychopy/experiment/_experiment.py +30 -9
- psychopy/experiment/components/__init__.py +1 -6
- psychopy/experiment/components/_base.py +44 -19
- psychopy/experiment/components/aperture/__init__.py +1 -1
- psychopy/experiment/components/brush/__init__.py +2 -2
- psychopy/experiment/components/button/__init__.py +24 -28
- psychopy/experiment/components/camera/__init__.py +38 -39
- psychopy/experiment/components/code/__init__.py +1 -1
- psychopy/experiment/components/dots/__init__.py +1 -1
- psychopy/experiment/components/eyetracker_record/__init__.py +7 -3
- psychopy/experiment/components/form/__init__.py +3 -3
- psychopy/experiment/components/grating/__init__.py +1 -1
- psychopy/experiment/components/image/__init__.py +1 -1
- psychopy/experiment/components/joyButtons/__init__.py +2 -2
- psychopy/experiment/components/joyButtons/virtualJoyButtons.py +1 -1
- psychopy/experiment/components/joystick/__init__.py +3 -3
- psychopy/experiment/components/joystick/virtualJoystick.py +1 -1
- psychopy/experiment/components/keyboard/__init__.py +98 -122
- psychopy/experiment/components/microphone/__init__.py +54 -98
- psychopy/experiment/components/mouse/__init__.py +92 -93
- psychopy/experiment/components/movie/__init__.py +28 -50
- psychopy/experiment/components/parallelOut/__init__.py +3 -3
- psychopy/experiment/components/polygon/__init__.py +2 -3
- psychopy/experiment/components/roi/__init__.py +2 -2
- psychopy/experiment/components/routineSettings/__init__.py +2 -0
- psychopy/experiment/components/serialOut/__init__.py +7 -7
- psychopy/experiment/components/settings/__init__.py +317 -313
- psychopy/experiment/components/settings/eyetracking.py +108 -0
- psychopy/experiment/components/slider/__init__.py +5 -5
- psychopy/experiment/components/sound/__init__.py +168 -78
- psychopy/experiment/components/soundsensor/__init__.py +361 -0
- psychopy/experiment/components/soundsensor/classic/soundsensor.png +0 -0
- psychopy/experiment/components/soundsensor/classic/soundsensor@2x.png +0 -0
- psychopy/experiment/components/soundsensor/dark/soundsensor.png +0 -0
- psychopy/experiment/components/soundsensor/dark/soundsensor@2x.png +0 -0
- psychopy/experiment/components/soundsensor/light/soundsensor.png +0 -0
- psychopy/experiment/components/soundsensor/light/soundsensor@2x.png +0 -0
- psychopy/experiment/components/static/__init__.py +59 -33
- psychopy/experiment/components/text/__init__.py +2 -6
- psychopy/experiment/components/textbox/__init__.py +3 -7
- psychopy/experiment/components/unknown/__init__.py +2 -0
- psychopy/experiment/components/unknownPlugin/__init__.py +2 -0
- psychopy/experiment/exports.py +1 -1
- psychopy/experiment/flow.py +2 -2
- psychopy/experiment/localization.py +1 -1
- psychopy/experiment/loops.py +43 -10
- psychopy/experiment/params.py +6 -4
- psychopy/experiment/plugins.py +8 -1
- psychopy/experiment/py2js.py +1 -1
- psychopy/experiment/py2js_transpiler.py +1 -1
- psychopy/experiment/routines/__init__.py +1 -1
- psychopy/experiment/routines/_base.py +23 -24
- psychopy/experiment/routines/audioValidator/__init__.py +343 -0
- psychopy/experiment/routines/audioValidator/classic/audio_validator.png +0 -0
- psychopy/experiment/routines/audioValidator/classic/audio_validator@2x.png +0 -0
- psychopy/experiment/routines/audioValidator/dark/audio_validator.png +0 -0
- psychopy/experiment/routines/audioValidator/dark/audio_validator@2x.png +0 -0
- psychopy/experiment/routines/audioValidator/light/audio_validator.png +0 -0
- psychopy/experiment/routines/audioValidator/light/audio_validator@2x.png +0 -0
- psychopy/experiment/routines/eyetracker_calibrate/__init__.py +76 -17
- psychopy/experiment/routines/eyetracker_validate/__init__.py +1 -1
- psychopy/experiment/routines/unknown/__init__.py +2 -0
- psychopy/experiment/routines/{photodiodeValidator → visualValidator}/__init__.py +89 -120
- psychopy/experiment/routines/visualValidator/classic/visual_validator.png +0 -0
- psychopy/experiment/routines/visualValidator/classic/visual_validator@2x.png +0 -0
- psychopy/experiment/routines/visualValidator/dark/visual_validator.png +0 -0
- psychopy/experiment/routines/visualValidator/dark/visual_validator@2x.png +0 -0
- psychopy/experiment/routines/visualValidator/light/visual_validator.png +0 -0
- psychopy/experiment/routines/visualValidator/light/visual_validator@2x.png +0 -0
- psychopy/experiment/utils.py +1 -1
- psychopy/gui/__init__.py +1 -1
- psychopy/gui/qtgui.py +15 -6
- psychopy/gui/wxgui.py +1 -1
- psychopy/hardware/__init__.py +0 -1
- psychopy/hardware/base.py +147 -16
- psychopy/hardware/bbtk/__init__.py +10 -16
- psychopy/hardware/brainproducts.py +7 -13
- psychopy/hardware/button.py +21 -2
- psychopy/hardware/buttonbox/__init__.py +1 -1
- psychopy/hardware/camera/__init__.py +18 -5
- psychopy/hardware/cedrus.py +5 -16
- psychopy/hardware/crs/__init__.py +1 -1
- psychopy/hardware/crs/bits.py +36 -33
- psychopy/hardware/crs/colorcal.py +8 -11
- psychopy/hardware/crs/optical.py +7 -10
- psychopy/hardware/crs/shaders.py +18 -5
- psychopy/hardware/emotiv.py +1 -1
- psychopy/hardware/emulator.py +11 -5
- psychopy/hardware/exceptions.py +86 -0
- psychopy/hardware/forp.py +18 -23
- psychopy/hardware/gammasci.py +8 -3
- psychopy/hardware/iolab.py +8 -19
- psychopy/hardware/joystick/__init__.py +865 -266
- psychopy/hardware/joystick/_base.py +251 -0
- psychopy/hardware/joystick/backend_glfw.py +306 -0
- psychopy/hardware/joystick/backend_pyglet.py +309 -0
- psychopy/hardware/joystick/mappings.py +287 -0
- psychopy/hardware/keyboard.py +4 -2
- psychopy/hardware/labhackers.py +1 -1
- psychopy/hardware/labjacks.py +9 -13
- psychopy/hardware/{photodiode.py → lightsensor.py} +146 -203
- psychopy/hardware/listener.py +9 -8
- psychopy/hardware/manager.py +24 -35
- psychopy/hardware/microphone.py +535 -155
- psychopy/hardware/minolta.py +14 -4
- psychopy/hardware/mouse/__init__.py +1 -1
- psychopy/hardware/photometer/__init__.py +2 -2
- psychopy/hardware/pr.py +14 -4
- psychopy/hardware/qmix.py +18 -27
- psychopy/hardware/serialdevice.py +43 -12
- psychopy/hardware/soundsensor.py +473 -0
- psychopy/hardware/spatial/__init__.py +231 -0
- psychopy/hardware/speaker.py +298 -36
- psychopy/hardware/triggerbox/__init__.py +1 -1
- psychopy/hardware/triggerbox/base.py +1 -1
- psychopy/hardware/triggerbox/parallel.py +1 -1
- psychopy/info.py +1 -1
- psychopy/iohub/devices/eyetracker/__init__.py +10 -18
- psychopy/iohub/devices/eyetracker/calibration/procedure.py +15 -33
- psychopy/iohub/devices/eyetracker/hw/gazepoint/__init__.py +2 -2
- psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/__init__.py +1 -0
- psychopy/iohub/devices/eyetracker/hw/gazepoint/gp3/eyetracker.py +10 -0
- psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/__init__.py +1 -0
- psychopy/iohub/devices/mouse/linux2.py +2 -1
- psychopy/layout.py +1 -1
- psychopy/liaison.py +91 -39
- psychopy/locale_setup.py +11 -1
- psychopy/localization/__init__.py +1 -1
- psychopy/localization/_localization.py +1 -1
- psychopy/localization/messages.pot +2 -2
- psychopy/logging.py +14 -12
- psychopy/microphone.py +4 -3
- psychopy/misc.py +1 -1
- psychopy/monitors/MonitorCenter.py +3 -3
- psychopy/monitors/__init__.py +1 -1
- psychopy/monitors/calibData.py +1 -1
- psychopy/monitors/calibTools.py +3 -2
- psychopy/platform_specific/__init__.py +1 -1
- psychopy/platform_specific/darwin.py +1 -1
- psychopy/platform_specific/linux.py +1 -1
- psychopy/platform_specific/win32.py +1 -1
- psychopy/plugins/__init__.py +26 -17
- psychopy/plugins/util.py +65 -0
- psychopy/preferences/Darwin.spec +11 -3
- psychopy/preferences/FreeBSD.spec +11 -3
- psychopy/preferences/Linux.spec +11 -3
- psychopy/preferences/Windows.spec +11 -3
- psychopy/preferences/__init__.py +1 -1
- psychopy/preferences/baseNoArch.spec +11 -3
- psychopy/preferences/hints.py +78 -61
- psychopy/preferences/preferences.py +82 -13
- psychopy/projects/__init__.py +1 -1
- psychopy/projects/pavlovia.py +29 -13
- psychopy/scripts/psyexpCompile.py +1 -1
- psychopy/session.py +81 -8
- psychopy/sound/__init__.py +25 -10
- psychopy/sound/_base.py +134 -34
- psychopy/sound/audioclip.py +38 -15
- psychopy/sound/audiodevice.py +1 -1
- psychopy/sound/backend_ptb.py +53 -321
- psychopy/sound/backend_pygame.py +7 -3
- psychopy/sound/backend_pyo.py +53 -22
- psychopy/sound/backend_pysound.py +10 -27
- psychopy/sound/backend_sounddevice.py +33 -21
- psychopy/sound/exceptions.py +1 -1
- psychopy/sound/microphone.py +83 -5
- psychopy/sound/transcribe.py +3 -3
- psychopy/tests/data/test_basic_run.py +1 -0
- psychopy/tests/data/test_sounds/default_16000.wav +0 -0
- psychopy/tests/data/test_sounds/default_192000.wav +0 -0
- psychopy/tests/data/test_sounds/default_22050.wav +0 -0
- psychopy/tests/data/test_sounds/default_32000.wav +0 -0
- psychopy/tests/data/test_sounds/default_44100.wav +0 -0
- psychopy/tests/data/test_sounds/default_48000.wav +0 -0
- psychopy/tests/data/test_sounds/default_8000.wav +0 -0
- psychopy/tests/data/test_sounds/default_96000.wav +0 -0
- psychopy/tests/test_alerts/test_alerttools.py +2 -1
- psychopy/tests/test_app/test_command_line.py +65 -0
- psychopy/tests/test_data/test_TrialHandler2.py +18 -7
- psychopy/tests/test_demos/test_builder_demos.py +1 -1
- psychopy/tests/test_experiment/needs_wx/componsTemplate.txt +5238 -4188
- psychopy/tests/test_experiment/needs_wx/test_components.py +1 -1
- psychopy/tests/test_experiment/test_components/test_RoutineSettingsComponent.py +16 -0
- psychopy/tests/test_experiment/test_components/test_all_components.py +1 -1
- psychopy/tests/test_experiment/test_components/test_base_components.py +26 -17
- psychopy/tests/test_experiment/test_loops.py +12 -4
- psychopy/tests/test_experiment/test_params.py +17 -4
- psychopy/tests/test_experiment/test_routines/test_PhotodiodeValidationRoutine.py +2 -2
- psychopy/tests/test_hardware/test_photodiode.py +66 -0
- psychopy/tests/test_liaison/test_Liaison.py +4 -4
- psychopy/tests/test_misc/test_clock.py +2 -0
- psychopy/tests/test_misc/test_color.py +2 -0
- psychopy/tests/test_misc/test_event.py +1 -0
- psychopy/tests/test_plugins/__init__.py +0 -0
- psychopy/tests/test_plugins/test_plugin_stubs.py +125 -0
- psychopy/tests/test_sound/test_sound.py +111 -40
- psychopy/tests/test_tools/test_colorspacetools.py +24 -23
- psychopy/tests/test_tools/test_mathtools.py +9 -9
- psychopy/tests/test_tools/test_viewtools.py +101 -0
- psychopy/tests/test_validators/__init__.py +0 -0
- psychopy/tests/test_validators/test_voicekeyValidator.py +95 -0
- psychopy/tests/test_visual/test_all_stimuli.py +2 -2
- psychopy/tests/test_visual/test_basevisual.py +37 -7
- psychopy/tests/test_visual/test_button.py +2 -2
- psychopy/tests/test_visual/test_circle.py +10 -2
- psychopy/tests/test_visual/test_dots.py +1 -1
- psychopy/tests/test_visual/test_form.py +13 -13
- psychopy/tests/test_visual/test_gamma.py +3 -3
- psychopy/tests/test_visual/test_image.py +2 -2
- psychopy/tests/test_visual/test_progress.py +2 -2
- psychopy/tests/test_visual/test_roi.py +8 -2
- psychopy/tests/test_visual/test_shape.py +2 -2
- psychopy/tests/test_visual/test_slider.py +2 -2
- psychopy/tests/test_visual/test_target.py +2 -2
- psychopy/tests/test_visual/test_textbox.py +6 -8
- psychopy/tests/test_visual/test_winScalePos.py +6 -5
- psychopy/tests/test_visual/test_window.py +17 -0
- psychopy/tests/utils.py +51 -1
- psychopy/tools/__init__.py +1 -1
- psychopy/tools/arraytools.py +2 -2
- psychopy/tools/attributetools.py +52 -1
- psychopy/tools/audiotools.py +4 -1
- psychopy/tools/colorspacetools.py +6 -4
- psychopy/tools/coordinatetools.py +1 -1
- psychopy/tools/fileerrortools.py +21 -9
- psychopy/tools/filetools.py +2 -2
- psychopy/tools/fontmanager.py +47 -28
- psychopy/tools/gltools.py +2967 -559
- psychopy/tools/imagetools.py +1 -1
- psychopy/tools/mathtools.py +997 -127
- psychopy/tools/monitorunittools.py +7 -1
- psychopy/tools/movietools.py +1 -2
- psychopy/tools/pkgtools.py +157 -127
- psychopy/tools/plottools.py +1 -1
- psychopy/tools/rifttools.py +1 -1
- psychopy/tools/stereotools.py +1 -1
- psychopy/tools/stimulustools.py +172 -2
- psychopy/tools/stringtools.py +22 -2
- psychopy/tools/systemtools.py +1 -1
- psychopy/tools/typetools.py +1 -1
- psychopy/tools/unittools.py +1 -1
- psychopy/tools/versionchooser.py +3 -1
- psychopy/tools/viewtools.py +54 -70
- psychopy/tools/wizard.py +2 -2
- psychopy/validation/__init__.py +6 -0
- psychopy/validation/audio.py +74 -0
- psychopy/validation/visual.py +115 -0
- psychopy/visual/__init__.py +1 -4
- psychopy/visual/aperture.py +9 -6
- psychopy/visual/backends/__init__.py +1 -1
- psychopy/visual/backends/_base.py +1 -1
- psychopy/visual/backends/gamma.py +1 -1
- psychopy/visual/backends/glfwbackend.py +8 -12
- psychopy/visual/backends/pygamebackend.py +1 -1
- psychopy/visual/backends/pygletbackend.py +32 -11
- psychopy/visual/basevisual.py +93 -13
- psychopy/visual/brush.py +1 -1
- psychopy/visual/bufferimage.py +90 -10
- psychopy/visual/button.py +1 -1
- psychopy/visual/circle.py +12 -20
- psychopy/visual/custommouse.py +1 -1
- psychopy/visual/dot.py +80 -14
- psychopy/visual/elementarray.py +84 -10
- psychopy/visual/filters.py +1 -1
- psychopy/visual/form.py +43 -28
- psychopy/visual/grating.py +105 -25
- psychopy/visual/helpers.py +4 -2
- psychopy/visual/image.py +98 -20
- psychopy/visual/line.py +15 -25
- psychopy/visual/movie.py +1 -1
- psychopy/visual/movie2.py +4 -3
- psychopy/visual/movie3.py +4 -3
- psychopy/visual/movies/__init__.py +1 -1
- psychopy/visual/movies/frame.py +1 -1
- psychopy/visual/movies/metadata.py +1 -1
- psychopy/visual/movies/players/__init__.py +1 -1
- psychopy/visual/movies/players/_base.py +1 -1
- psychopy/visual/movies/players/ffpyplayer_player.py +2 -3
- psychopy/visual/nnlvs.py +9 -6
- psychopy/visual/noise.py +4 -16
- psychopy/visual/patch.py +4 -3
- psychopy/visual/pie.py +3 -14
- psychopy/visual/polygon.py +21 -28
- psychopy/visual/radial.py +4 -18
- psychopy/visual/ratingscale.py +4 -3
- psychopy/visual/rect.py +16 -25
- psychopy/visual/rift.py +8 -2
- psychopy/visual/secondorder.py +4 -16
- psychopy/visual/shaders.py +620 -286
- psychopy/visual/shape.py +281 -90
- psychopy/visual/simpleimage.py +1 -1
- psychopy/visual/slider.py +78 -25
- psychopy/visual/stim3d.py +5 -608
- psychopy/visual/text.py +13 -3
- psychopy/visual/textbox2/textbox2.py +188 -56
- psychopy/visual/vlcmoviestim.py +1 -1
- psychopy/visual/window.py +374 -201
- psychopy/web.py +1 -1
- {psychopy-2024.2.5.dist-info → psychopy-2025.1.1.dist-info}/METADATA +13 -12
- {psychopy-2024.2.5.dist-info → psychopy-2025.1.1.dist-info}/RECORD +647 -624
- {psychopy-2024.2.5.dist-info → psychopy-2025.1.1.dist-info}/WHEEL +1 -1
- psychopy/.DS_Store +0 -0
- psychopy/__init__.py.orig +0 -65
- psychopy/app/.DS_Store +0 -0
- psychopy/app/Resources/.DS_Store +0 -0
- psychopy/app/Resources/classic/filecsv16.png +0 -0
- psychopy/app/Resources/classic/fileimage16.png +0 -0
- psychopy/app/Resources/classic/fileunknown16.png +0 -0
- psychopy/app/Resources/dark/filecsv16.png +0 -0
- psychopy/app/Resources/dark/filecsv16@2x.png +0 -0
- psychopy/app/Resources/dark/fileimage16.png +0 -0
- psychopy/app/Resources/dark/fileimage16@2x.png +0 -0
- psychopy/app/Resources/dark/fileunknown16.png +0 -0
- psychopy/app/Resources/dark/fileunknown16@2x.png +0 -0
- psychopy/app/Resources/fonts/OpenSans-Bold.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-BoldItalic.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-ExtraBold.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-Italic.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-Light.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-LightItalic.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-Regular.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-SemiBold.ttf +0 -0
- psychopy/app/Resources/fonts/OpenSans-SemiBoldItalic.ttf +0 -0
- psychopy/app/Resources/light/filecsv16.png +0 -0
- psychopy/app/Resources/light/filecsv16@2x.png +0 -0
- psychopy/app/Resources/light/fileimage16.png +0 -0
- psychopy/app/Resources/light/fileimage16@2x.png +0 -0
- psychopy/app/Resources/light/fileunknown16.png +0 -0
- psychopy/app/Resources/light/fileunknown16@2x.png +0 -0
- psychopy/app/Resources/psychopySplash.png +0 -0
- psychopy/app/Resources/psychopySplash@2x.png +0 -0
- psychopy/app/builder/builder.py.orig +0 -3932
- psychopy/app/builder/dialogs/__init__.py.orig +0 -1679
- psychopy/app/builder/dialogs/paramCtrls.py.orig +0 -713
- psychopy/app/colorpicker/__init__.py.orig +0 -411
- psychopy/app/locale/ar_001/.DS_Store +0 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/.DS_Store +0 -0
- psychopy/core.py.orig +0 -169
- psychopy/demos/builder/.DS_Store +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks_lastrun.py +0 -330
- psychopy/demos/builder/Experiments/.DS_Store +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/archived_conditions.xlsx +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/draw grid stim.py +0 -61
- psychopy/demos/builder/Experiments/dragAndDrop/shapeMaker.psyexp +0 -91
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_1.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_10.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_2.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_3.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_4.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_5.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_6.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_7.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_8.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_9.png +0 -0
- psychopy/demos/builder/Experiments/dragAndDrop/updated_conditions.xlsx +0 -0
- psychopy/demos/builder/Tools/.DS_Store +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/.DS_Store +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/.DS_Store +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.csv +0 -38
- psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.log +0 -3418
- psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.psydat +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.csv +0 -2
- psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.log +0 -15
- psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.psydat +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual_lastrun.py +0 -562
- psychopy/demos/coder/.DS_Store +0 -0
- psychopy/demos/coder/experiment control/info_gamma.pickle +0 -0
- psychopy/demos/coder/iohub/.iohpid +0 -1
- psychopy/demos/coder/iohub/eyetracking/.iohpid +0 -1
- psychopy/demos/coder/iohub/wintab/.DS_Store +0 -0
- psychopy/demos/coder/stimuli/.DS_Store +0 -0
- psychopy/experiment/_experiment.py.orig +0 -1032
- psychopy/experiment/components/.DS_Store +0 -0
- psychopy/experiment/components/_base.py.orig +0 -823
- psychopy/experiment/components/form/.DS_Store +0 -0
- psychopy/experiment/components/microphone/__init__.py.orig +0 -490
- psychopy/experiment/components/settings/__init__.py.orig +0 -1337
- psychopy/experiment/components/textbox/__init__.py.orig +0 -310
- psychopy/experiment/components/webcam/.DS_Store +0 -0
- psychopy/experiment/components/webcam/light/.DS_Store +0 -0
- psychopy/experiment/loops.py.orig +0 -829
- psychopy/experiment/params.py.orig +0 -408
- psychopy/experiment/routine.py.orig +0 -503
- psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator.png +0 -0
- psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator@2x.png +0 -0
- psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator.png +0 -0
- psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator@2x.png +0 -0
- psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator.png +0 -0
- psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator@2x.png +0 -0
- psychopy/hardware/.DS_Store +0 -0
- psychopy/hardware/brainproducts.py.orig +0 -680
- psychopy/hardware/iolab.py.orig +0 -238
- psychopy/iohub/datastore/__init__.py.orig +0 -443
- psychopy/iohub/datastore/util.py.orig +0 -692
- psychopy/iohub/devices/mouse/darwin.py.orig +0 -427
- psychopy/iohub/devices/mouse/linux2.py.orig +0 -198
- psychopy/preferences/.DS_Store +0 -0
- psychopy/projects/pavlovia.py.orig +0 -1295
- psychopy/tests/.DS_Store +0 -0
- psychopy/tests/data/.DS_Store +0 -0
- psychopy/tests/data/TestCircle_fill_local.png +0 -0
- psychopy/tests/data/aperture1_normHexbackground_local.png +0 -0
- psychopy/tests/data/aperture1_norm_local.png +0 -0
- psychopy/tests/data/aperture2_normHexbackground_local.png +0 -0
- psychopy/tests/data/beatandrcos_height_local.png +0 -0
- psychopy/tests/data/beatandrcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/beatandrcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/beatandrcos_norm_local.png +0 -0
- psychopy/tests/data/beatandrcos_stencil_local.png +0 -0
- psychopy/tests/data/blend_add_height_local.png +0 -0
- psychopy/tests/data/blend_add_normAddBlend_local.png +0 -0
- psychopy/tests/data/blend_add_normHexbackground_local.png +0 -0
- psychopy/tests/data/blend_add_normNoShade_local.png +0 -0
- psychopy/tests/data/blend_add_norm_local.png +0 -0
- psychopy/tests/data/blend_add_stencil_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_height_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_normAddBlend_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_normHexbackground_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_normNoShade_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_norm_local.png +0 -0
- psychopy/tests/data/bufferimg_gabor_stencil_local.png +0 -0
- psychopy/tests/data/circleHex_height_local.png +0 -0
- psychopy/tests/data/circleHex_normAddBlend_local.png +0 -0
- psychopy/tests/data/circleHex_normHexbackground_local.png +0 -0
- psychopy/tests/data/circleHex_normNoShade_local.png +0 -0
- psychopy/tests/data/circleHex_norm_local.png +0 -0
- psychopy/tests/data/circleHex_stencil_local.png +0 -0
- psychopy/tests/data/color_comparison_local.png +0 -0
- psychopy/tests/data/correctScript/.DS_Store +0 -0
- psychopy/tests/data/dots_height_local.png +0 -0
- psychopy/tests/data/dots_normAddBlend_local.png +0 -0
- psychopy/tests/data/dots_normHexbackground_local.png +0 -0
- psychopy/tests/data/dots_normNoShade_local.png +0 -0
- psychopy/tests/data/dots_norm_local.png +0 -0
- psychopy/tests/data/dots_stencil_local.png +0 -0
- psychopy/tests/data/elarray1_height_local.png +0 -0
- psychopy/tests/data/elarray1_normAddBlend_local.png +0 -0
- psychopy/tests/data/elarray1_normHexbackground_local.png +0 -0
- psychopy/tests/data/elarray1_norm_local.png +0 -0
- psychopy/tests/data/elarray1_stencil_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_height_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_norm_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_stencil_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_height_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_norm_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_stencil_local.png +0 -0
- psychopy/tests/data/gabor1_height_local.png +0 -0
- psychopy/tests/data/gabor1_normAddBlend_local.png +0 -0
- psychopy/tests/data/gabor1_normHexbackground_local.png +0 -0
- psychopy/tests/data/gabor1_normNoShade_local.png +0 -0
- psychopy/tests/data/gabor1_norm_local.png +0 -0
- psychopy/tests/data/gabor1_stencil_local.png +0 -0
- psychopy/tests/data/greyscale_normHexbackground_local.png +0 -0
- psychopy/tests/data/imageAndGauss_height_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normAddBlend_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normHexbackground_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normNoShade_local.png +0 -0
- psychopy/tests/data/imageAndGauss_norm_local.png +0 -0
- psychopy/tests/data/imageAndGauss_stencil_local.png +0 -0
- psychopy/tests/data/movFrame1_stencil_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_height_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normNoShade_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_norm_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_stencil_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_height_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normNoShade_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_norm_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_stencil_local.png +0 -0
- psychopy/tests/data/numpyImage_height_local.png +0 -0
- psychopy/tests/data/numpyImage_normAddBlend_local.png +0 -0
- psychopy/tests/data/numpyImage_normHexbackground_local.png +0 -0
- psychopy/tests/data/numpyImage_normNoShade_local.png +0 -0
- psychopy/tests/data/numpyImage_norm_local.png +0 -0
- psychopy/tests/data/numpyImage_stencil_local.png +0 -0
- psychopy/tests/data/shape2_1_normAddBlend_local.png +0 -0
- psychopy/tests/data/shape2_1_normHexbackground_local.png +0 -0
- psychopy/tests/data/shape2_1_normNoShade_local.png +0 -0
- psychopy/tests/data/shape2_1_norm_local.png +0 -0
- psychopy/tests/data/shape2_1_stencil_local.png +0 -0
- psychopy/tests/data/text1_height_local.png +0 -0
- psychopy/tests/data/text1_normAddBlend_local.png +0 -0
- psychopy/tests/data/text1_normHexbackground_local.png +0 -0
- psychopy/tests/data/text1_norm_local.png +0 -0
- psychopy/tests/data/text1_stencil_local.png +0 -0
- psychopy/tests/data/wedge1_height_local.png +0 -0
- psychopy/tests/data/wedge1_normAddBlend_local.png +0 -0
- psychopy/tests/data/wedge1_normHexbackground_local.png +0 -0
- psychopy/tests/data/wedge1_normNoShade_local.png +0 -0
- psychopy/tests/data/wedge1_norm_local.png +0 -0
- psychopy/tests/data/wedge1_stencil_local.png +0 -0
- psychopy/tests/test_app/.DS_Store +0 -0
- psychopy/tests/test_app/test_builder/.DS_Store +0 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.log +0 -177
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.psydat +0 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.xlsx +0 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.log +0 -168
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.psydat +0 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.xlsx +0 -0
- psychopy/tests/test_data/.DS_Store +0 -0
- psychopy/tests/test_hardware/test_CRS_BitsSharp.py +0 -67
- psychopy/tests/test_hardware/test_CRS_BitsSharp.py.orig +0 -68
- psychopy/tests/test_hardware/test_CRS_bitsShaders.py +0 -110
- psychopy/tests/test_visual/test_image.py.orig +0 -219
- psychopy/visual/basevisual.py.orig +0 -1723
- psychopy/visual/form.py.orig +0 -1181
- psychopy/visual/text.py.orig +0 -752
- psychopy/visual/textbox2/textbox2.py.orig +0 -1315
- psychopy/visual/windowwarp.py.orig +0 -463
- /psychopy/{app/cortex.log → alerts/alertsCatalogue/3600.yaml} +0 -0
- /psychopy/{app/Resources → assets}/fonts/Arvo-Bold.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/Arvo-BoldItalic.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/Arvo-Italic.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/Arvo-Regular.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/DejaVuSerif.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/IndieFlower-Regular.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
- /psychopy/{app/Resources → assets}/fonts/JetBrainsMono-VariableFont_wght.ttf +0 -0
- /psychopy/demos/builder/Experiments/{GoNoGo → goNoGo}/readme.md +0 -0
- {psychopy-2024.2.5.dist-info → psychopy-2025.1.1.dist-info}/entry_points.txt +0 -0
- {psychopy-2024.2.5.dist-info → psychopy-2025.1.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from psychopy import core, layout, logging
|
|
3
2
|
from psychopy.hardware import base, DeviceManager
|
|
4
3
|
from psychopy.localization import _translate
|
|
5
4
|
from psychopy.hardware import keyboard
|
|
5
|
+
# for legacy compatability, import VisualValidator and VisualValidationError here
|
|
6
|
+
from psychopy.validation.visual import VisualValidator, VisualValidationError
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
class
|
|
9
|
+
class LightSensorResponse(base.BaseResponse):
|
|
9
10
|
# list of fields known to be a part of this response type
|
|
10
11
|
fields = ["t", "value", "channel", "threshold"]
|
|
11
12
|
|
|
12
|
-
def __init__(self, t, value, channel, threshold=None):
|
|
13
|
+
def __init__(self, t, value, channel, device=None, threshold=None):
|
|
13
14
|
# initialise base response class
|
|
14
|
-
base.BaseResponse.__init__(self, t=t, value=value)
|
|
15
|
+
base.BaseResponse.__init__(self, t=t, value=value, device=device)
|
|
15
16
|
# store channel and threshold
|
|
16
17
|
self.channel = channel
|
|
17
18
|
self.threshold = threshold
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class
|
|
21
|
-
responseClass =
|
|
21
|
+
class BaseLightSensorGroup(base.BaseResponseDevice):
|
|
22
|
+
responseClass = LightSensorResponse
|
|
22
23
|
|
|
23
24
|
def __init__(self, channels=1, threshold=None, pos=None, size=None, units=None):
|
|
24
25
|
base.BaseResponseDevice.__init__(self)
|
|
@@ -28,6 +29,8 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
28
29
|
self.state = [False] * channels
|
|
29
30
|
# set initial threshold
|
|
30
31
|
self.threshold = [None] * channels
|
|
32
|
+
if threshold is None:
|
|
33
|
+
threshold = 0.5
|
|
31
34
|
self.setThreshold(threshold, channel=list(range(channels)))
|
|
32
35
|
# store position params
|
|
33
36
|
self.units = units
|
|
@@ -60,8 +63,8 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
60
63
|
for cls in DeviceManager.deviceClasses:
|
|
61
64
|
# get class from class str
|
|
62
65
|
cls = DeviceManager._resolveClassString(cls)
|
|
63
|
-
# if class is a
|
|
64
|
-
if issubclass(cls,
|
|
66
|
+
# if class is a light sensor, add its available devices
|
|
67
|
+
if issubclass(cls, BaseLightSensorGroup) and cls is not BaseLightSensorGroup:
|
|
65
68
|
devices += cls.getAvailableDevices()
|
|
66
69
|
|
|
67
70
|
return devices
|
|
@@ -73,15 +76,15 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
73
76
|
Parameters
|
|
74
77
|
----------
|
|
75
78
|
state : bool or None
|
|
76
|
-
True to get
|
|
79
|
+
True to get light sensor "on" responses, False to get light sensor "off" responses, None to get all responses.
|
|
77
80
|
channel : int
|
|
78
|
-
Which
|
|
81
|
+
Which light sensor to get responses from?
|
|
79
82
|
clear : bool
|
|
80
83
|
Whether or not to remove responses matching `state` after retrieval.
|
|
81
84
|
|
|
82
85
|
Returns
|
|
83
86
|
-------
|
|
84
|
-
list[
|
|
87
|
+
list[LightSensorResponse]
|
|
85
88
|
List of matching responses.
|
|
86
89
|
"""
|
|
87
90
|
# make sure parent dispatches messages
|
|
@@ -125,7 +128,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
125
128
|
rect.fillColor = "black"
|
|
126
129
|
rect.draw()
|
|
127
130
|
win.flip()
|
|
128
|
-
# wait 250ms for flip to happen and
|
|
131
|
+
# wait 250ms for flip to happen and light sensor to catch it
|
|
129
132
|
timeoutClock.reset()
|
|
130
133
|
while timeoutClock.getTime() < 0.25:
|
|
131
134
|
self.dispatchMessages()
|
|
@@ -138,7 +141,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
138
141
|
rect.fillColor = "white"
|
|
139
142
|
rect.draw()
|
|
140
143
|
win.flip()
|
|
141
|
-
# wait 250ms for flip to happen and
|
|
144
|
+
# wait 250ms for flip to happen and light sensor to catch it
|
|
142
145
|
timeoutClock.reset()
|
|
143
146
|
while timeoutClock.getTime() < 0.25:
|
|
144
147
|
self.dispatchMessages()
|
|
@@ -146,32 +149,58 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
146
149
|
while self.hasUnfinishedMessage():
|
|
147
150
|
self.dispatchMessages()
|
|
148
151
|
# start off with no channels
|
|
149
|
-
|
|
152
|
+
channelsOn = set()
|
|
150
153
|
# iterate through potential channels
|
|
151
154
|
for i, state in enumerate(self.state):
|
|
152
|
-
# if
|
|
155
|
+
# skip if we got more than 1 message
|
|
156
|
+
if len(self.getResponses(channel=i, clear=False)) > 1:
|
|
157
|
+
continue
|
|
158
|
+
# if any detected the flash, append it (test for false negative)
|
|
153
159
|
if state:
|
|
154
|
-
|
|
160
|
+
channelsOn.add(i)
|
|
161
|
+
# clear caught messages so we're starting afresh
|
|
162
|
+
self.clearResponses()
|
|
163
|
+
# show black
|
|
164
|
+
rect.fillColor = "black"
|
|
165
|
+
rect.draw()
|
|
166
|
+
win.flip()
|
|
167
|
+
# wait 250ms for flip to happen and sensor to catch it
|
|
168
|
+
timeoutClock.reset()
|
|
169
|
+
while timeoutClock.getTime() < 0.25:
|
|
170
|
+
self.dispatchMessages()
|
|
171
|
+
# finish dispatching any messages which are only partially received
|
|
172
|
+
while self.hasUnfinishedMessage():
|
|
173
|
+
self.dispatchMessages()
|
|
174
|
+
# start off with no channels
|
|
175
|
+
channelsOff = set()
|
|
176
|
+
# iterate through potential channels
|
|
177
|
+
for i, state in enumerate(self.state):
|
|
178
|
+
# skip if we got more than 1 message
|
|
179
|
+
if len(self.getResponses(channel=i, clear=False)) > 1:
|
|
180
|
+
continue
|
|
181
|
+
# if any detected the lack of flash, append it (test for false positive)
|
|
182
|
+
if not state:
|
|
183
|
+
channelsOff.add(i)
|
|
155
184
|
|
|
156
|
-
return
|
|
185
|
+
return tuple(channelsOn & channelsOff)
|
|
157
186
|
|
|
158
|
-
def
|
|
187
|
+
def findSensor(self, win, channel=None, retryLimit=5):
|
|
159
188
|
"""
|
|
160
|
-
Draws rectangles on the screen and records
|
|
189
|
+
Draws rectangles on the screen and records light sensor responses to recursively find the location of the diode.
|
|
161
190
|
|
|
162
191
|
Returns
|
|
163
192
|
-------
|
|
164
193
|
psychopy.layout.Position
|
|
165
|
-
Position of the diode on the window. Essentially, the center of the last rectangle which the
|
|
194
|
+
Position of the diode on the window. Essentially, the center of the last rectangle which the light sensor
|
|
166
195
|
was able to detect.
|
|
167
196
|
psychopy.layout.Size
|
|
168
|
-
Size of the area of certainty. Essentially, the size of the last (smallest) rectangle which the
|
|
197
|
+
Size of the area of certainty. Essentially, the size of the last (smallest) rectangle which the light sensor
|
|
169
198
|
was able to detect.
|
|
170
199
|
"""
|
|
171
200
|
# timeout clock
|
|
172
201
|
timeoutClock = core.Clock()
|
|
173
202
|
# keyboard to check for escape
|
|
174
|
-
kb = keyboard.Keyboard(deviceName="
|
|
203
|
+
kb = keyboard.Keyboard(deviceName="visualValidatorKeyboard")
|
|
175
204
|
# stash autodraw
|
|
176
205
|
win.stashAutoDraw()
|
|
177
206
|
# import visual here - if they're using this function, it's already in the stack
|
|
@@ -186,7 +215,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
186
215
|
# add low opacity label
|
|
187
216
|
label = visual.TextBox2(
|
|
188
217
|
win,
|
|
189
|
-
text=f"Finding
|
|
218
|
+
text=f"Finding light sensor...",
|
|
190
219
|
fillColor=(0, 0, 0), color=(80, 80, 80), colorSpace="rgb255",
|
|
191
220
|
pos=(0, 0), size=(2, 2), units="norm",
|
|
192
221
|
alignment="center",
|
|
@@ -211,18 +240,18 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
211
240
|
# if no channels are responsive, use 0th channel and let scanQuadrants fail cleanly
|
|
212
241
|
channel = 0
|
|
213
242
|
# update label text once we have a channel
|
|
214
|
-
label.text = f"Finding
|
|
243
|
+
label.text = f"Finding light sensor {channel}..."
|
|
215
244
|
|
|
216
245
|
def scanQuadrants(responsive=False):
|
|
217
246
|
"""
|
|
218
|
-
Recursively shrink the rectangle around the position of the
|
|
247
|
+
Recursively shrink the rectangle around the position of the light sensor until it's too
|
|
219
248
|
small to detect.
|
|
220
249
|
|
|
221
250
|
Parameters
|
|
222
251
|
----------
|
|
223
252
|
responsive : bool
|
|
224
253
|
When calling manually, this should always be left as False! Will be set to True if
|
|
225
|
-
any response was received from the
|
|
254
|
+
any response was received from the light sensor.
|
|
226
255
|
"""
|
|
227
256
|
# work out width and height of area
|
|
228
257
|
w, h = rect.size
|
|
@@ -251,7 +280,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
251
280
|
label.draw()
|
|
252
281
|
rect.draw()
|
|
253
282
|
win.flip()
|
|
254
|
-
# wait for flip to happen and
|
|
283
|
+
# wait for flip to happen and light sensor to catch it (max 250ms)
|
|
255
284
|
timeoutClock.reset()
|
|
256
285
|
self.clearResponses()
|
|
257
286
|
while not self.responses and timeoutClock.getTime() < 0.25:
|
|
@@ -262,16 +291,18 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
262
291
|
# check for escape before entering recursion
|
|
263
292
|
if kb.getKeys(['escape']):
|
|
264
293
|
return None
|
|
265
|
-
# poll
|
|
294
|
+
# poll light sensor
|
|
266
295
|
if self.getState(channel):
|
|
267
296
|
# mark that we've got a response
|
|
268
297
|
responsive = True
|
|
269
298
|
# if it detected this rectangle, recur
|
|
270
299
|
return scanQuadrants(responsive=responsive)
|
|
271
|
-
# if none of these have returned, rect is too small to cover the whole
|
|
300
|
+
# if none of these have returned, rect is too small to cover the whole light sensor, so return
|
|
272
301
|
return responsive
|
|
273
302
|
|
|
274
303
|
def handleNonResponse(label, rect, timeout=5):
|
|
304
|
+
# log error
|
|
305
|
+
logging.error("Failed to find light sensor")
|
|
275
306
|
# skip if retry limit hit
|
|
276
307
|
if retryLimit <= 0:
|
|
277
308
|
return None
|
|
@@ -279,10 +310,10 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
279
310
|
timer = core.CountdownTimer(start=timeout)
|
|
280
311
|
# set label text to alert user
|
|
281
312
|
msg = (
|
|
282
|
-
"Received no responses from
|
|
313
|
+
"Received no responses from light sensor during `findSensor`. Light sensor may not "
|
|
283
314
|
"be connected or may be configured incorrectly.\n"
|
|
284
315
|
"\n"
|
|
285
|
-
"To manually specify the
|
|
316
|
+
"To manually specify the light sensor's position, press ENTER. To quit, press "
|
|
286
317
|
"ESCAPE. Otherwise, will retry in {:.0f}s\n"
|
|
287
318
|
)
|
|
288
319
|
label.foreColor = "red"
|
|
@@ -303,13 +334,17 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
303
334
|
label.draw()
|
|
304
335
|
# flip
|
|
305
336
|
win.flip()
|
|
306
|
-
# if we timed out
|
|
307
|
-
|
|
337
|
+
# if we timed out...
|
|
338
|
+
logging.error("Trying to find light sensor again after failing")
|
|
339
|
+
# re-detect threshold
|
|
340
|
+
self.findThreshold(win, channel=channel)
|
|
341
|
+
# re-find light sensor
|
|
342
|
+
return self.findSensor(win, channel=channel, retryLimit=retryLimit-1)
|
|
308
343
|
|
|
309
344
|
def specifyManually(label, rect):
|
|
310
345
|
# set label text to alert user
|
|
311
346
|
label.text = (
|
|
312
|
-
"Use the arrow keys to move the
|
|
347
|
+
"Use the arrow keys to move the light sensor patch and use the plus/minus keys to "
|
|
313
348
|
"resize it. Press ENTER when finished, or press ESCAPE to quit.\n"
|
|
314
349
|
)
|
|
315
350
|
label.foreColor = "red"
|
|
@@ -360,12 +395,12 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
360
395
|
self.state = [None] * self.channels
|
|
361
396
|
self.dispatchMessages()
|
|
362
397
|
self.clearResponses()
|
|
363
|
-
# recursively shrink rect around the
|
|
398
|
+
# recursively shrink rect around the light sensor
|
|
364
399
|
responsive = scanQuadrants()
|
|
365
400
|
# if cancelled, warn and continue
|
|
366
401
|
if responsive is None:
|
|
367
402
|
logging.warn(
|
|
368
|
-
"`
|
|
403
|
+
"`findSensor` procedure cancelled by user."
|
|
369
404
|
)
|
|
370
405
|
return (
|
|
371
406
|
layout.Position(self.pos, units="norm", win=win),
|
|
@@ -373,7 +408,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
373
408
|
)
|
|
374
409
|
# if we didn't get any responses at all, prompt to try again
|
|
375
410
|
if not responsive:
|
|
376
|
-
handleNonResponse(label=label, rect=rect)
|
|
411
|
+
return handleNonResponse(label=label, rect=rect)
|
|
377
412
|
# clear all the events created by this process
|
|
378
413
|
self.state = [None] * self.channels
|
|
379
414
|
self.dispatchMessages()
|
|
@@ -386,7 +421,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
386
421
|
# set size/pos/units
|
|
387
422
|
self.units = "norm"
|
|
388
423
|
self.size = rect.size * 2
|
|
389
|
-
self.pos = rect.pos
|
|
424
|
+
self.pos = rect.pos
|
|
390
425
|
|
|
391
426
|
return (
|
|
392
427
|
layout.Position(self.pos, units="norm", win=win),
|
|
@@ -405,7 +440,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
405
440
|
# return array of thresholds
|
|
406
441
|
return thresholds
|
|
407
442
|
# keyboard to check for escape/continue
|
|
408
|
-
kb = keyboard.Keyboard(deviceName="
|
|
443
|
+
kb = keyboard.Keyboard(deviceName="defaultKeyboard")
|
|
409
444
|
# stash autodraw
|
|
410
445
|
win.stashAutoDraw()
|
|
411
446
|
# import visual here - if they're using this function, it's already in the stack
|
|
@@ -419,7 +454,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
419
454
|
# add low opacity label
|
|
420
455
|
label = visual.TextBox2(
|
|
421
456
|
win,
|
|
422
|
-
text=f"Finding best threshold for
|
|
457
|
+
text=f"Finding best threshold for light sensor {channel}...",
|
|
423
458
|
fillColor=None, color=(0, 0, 0), colorSpace="rgb",
|
|
424
459
|
pos=(0, 0), size=(2, 2), units="norm",
|
|
425
460
|
alignment="center",
|
|
@@ -435,11 +470,9 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
435
470
|
f"Trying threshold range: {threshRange}"
|
|
436
471
|
)
|
|
437
472
|
# work out current
|
|
438
|
-
current =
|
|
439
|
-
sum(threshRange) / 2
|
|
440
|
-
)
|
|
473
|
+
current = sum(threshRange) / 2
|
|
441
474
|
# set threshold and get value
|
|
442
|
-
value = self._setThreshold(
|
|
475
|
+
value = self._setThreshold(current, channel=channel)
|
|
443
476
|
|
|
444
477
|
if value:
|
|
445
478
|
# if expecting light and got light, we have an upper bound
|
|
@@ -454,7 +487,7 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
454
487
|
if recursionLimit <= 0:
|
|
455
488
|
return current
|
|
456
489
|
# return if threshold is small enough
|
|
457
|
-
if abs(threshRange[1] - threshRange[0]) <
|
|
490
|
+
if abs(threshRange[1] - threshRange[0]) < 0.01:
|
|
458
491
|
return current
|
|
459
492
|
# recur with new range
|
|
460
493
|
return _bisectThreshold(threshRange, recursionLimit=recursionLimit-1)
|
|
@@ -477,7 +510,18 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
477
510
|
label.draw()
|
|
478
511
|
win.flip()
|
|
479
512
|
# get threshold
|
|
480
|
-
thresholds[col] = _bisectThreshold([0,
|
|
513
|
+
thresholds[col] = _bisectThreshold([0, 1], recursionLimit=16)
|
|
514
|
+
# report thresholds
|
|
515
|
+
logging.debug(f"Channel {channel} responded 'on' for a black screen at threshold {thresholds['black']}")
|
|
516
|
+
logging.debug(f"Channel {channel} responded 'on' for a white screen at threshold {thresholds['white']}")
|
|
517
|
+
# if black is detected at the same or lower threshold as white, the sensor isn't working
|
|
518
|
+
if thresholds['black'] <= thresholds['white']:
|
|
519
|
+
logging.debug(
|
|
520
|
+
f"Could not detect a reasonable threshold for channel {channel}, sensor may be "
|
|
521
|
+
f"unplugged."
|
|
522
|
+
)
|
|
523
|
+
self._setThreshold(0, channel=channel)
|
|
524
|
+
return None
|
|
481
525
|
# pick a threshold between white and black (i.e. one that's safe)
|
|
482
526
|
threshold = (thresholds['white'] + thresholds['black']) / 2
|
|
483
527
|
# clear bg rect
|
|
@@ -495,6 +539,46 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
495
539
|
|
|
496
540
|
return int(threshold)
|
|
497
541
|
|
|
542
|
+
def checkSensor(self, win, channels=None, reps=1):
|
|
543
|
+
"""
|
|
544
|
+
Check that the sensor is responsive on a given channel by alternating the full window
|
|
545
|
+
between white and black, then checking that the channel state is True when white and False
|
|
546
|
+
when black.
|
|
547
|
+
|
|
548
|
+
Parameters
|
|
549
|
+
----------
|
|
550
|
+
win : psychopy.visual.Window
|
|
551
|
+
Window to use for checking.
|
|
552
|
+
channels : list[int] or tuple[int] or int or None, optional
|
|
553
|
+
Channel or channels to check, use None (default) to check all channels.
|
|
554
|
+
reps : int, optional
|
|
555
|
+
How many times to repeat the test - if the sensor has a habit of randomly
|
|
556
|
+
flickering, there's a chance of it passing tests by random chance, so you may wish to
|
|
557
|
+
repeat it several times. Default is 1 (aka do not repeat)
|
|
558
|
+
|
|
559
|
+
Returns
|
|
560
|
+
-------
|
|
561
|
+
bool
|
|
562
|
+
True
|
|
563
|
+
"""
|
|
564
|
+
# if given just one channel, wrap it in a list
|
|
565
|
+
if isinstance(channels, int):
|
|
566
|
+
channels = [channels]
|
|
567
|
+
# if None, check all channels
|
|
568
|
+
if channels is None:
|
|
569
|
+
channels = list(range(self.channels))
|
|
570
|
+
# for each specified channel...
|
|
571
|
+
for channel in channels:
|
|
572
|
+
# the following is repeated for good measure, as many times as specified
|
|
573
|
+
for rep in range(reps):
|
|
574
|
+
# run findChannels
|
|
575
|
+
found = self.findChannels(win)
|
|
576
|
+
# if the given channel isn't found, test fails
|
|
577
|
+
if channel not in found:
|
|
578
|
+
return False
|
|
579
|
+
|
|
580
|
+
return True
|
|
581
|
+
|
|
498
582
|
def setThreshold(self, threshold, channel):
|
|
499
583
|
if isinstance(channel, (list, tuple)):
|
|
500
584
|
# if given a list of channels, iterate
|
|
@@ -530,18 +614,14 @@ class BasePhotodiodeGroup(base.BaseResponseDevice):
|
|
|
530
614
|
return self.state[channel]
|
|
531
615
|
|
|
532
616
|
|
|
533
|
-
class
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
538
|
-
def __init__(self, win, threshold=125, pos=None, size=None, units=None):
|
|
617
|
+
class ScreenBufferSampler(BaseLightSensorGroup):
|
|
618
|
+
def __init__(self, win, threshold=0.5, pos=None, size=None, units=None):
|
|
539
619
|
# store win
|
|
540
620
|
self.win = win
|
|
541
621
|
# default rect
|
|
542
622
|
self.rect = None
|
|
543
623
|
# initialise base class
|
|
544
|
-
|
|
624
|
+
BaseLightSensorGroup.__init__(
|
|
545
625
|
self, channels=1, threshold=threshold, pos=pos, size=size, units=units
|
|
546
626
|
)
|
|
547
627
|
# make clock
|
|
@@ -558,8 +638,9 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
558
638
|
"""
|
|
559
639
|
Check the screen for changes and dispatch events as appropriate
|
|
560
640
|
"""
|
|
641
|
+
from psychopy.visual import Window
|
|
561
642
|
# if there's no window, skip
|
|
562
|
-
if self.win
|
|
643
|
+
if not isinstance(self.win, Window):
|
|
563
644
|
return
|
|
564
645
|
# get rect
|
|
565
646
|
left, bottom = self._pos.pix + self.win.size / 2
|
|
@@ -575,24 +656,25 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
575
656
|
makeLum=True
|
|
576
657
|
)
|
|
577
658
|
# work out whether it's brighter than threshold
|
|
578
|
-
state = pixels.mean() > (255 - self.getThreshold())
|
|
659
|
+
state = pixels.mean() > (255 - self.getThreshold() * 255)
|
|
579
660
|
# if state has changed, make an event
|
|
580
661
|
if state != self.state[0]:
|
|
581
662
|
if self.win._frameTimes:
|
|
582
663
|
frameT = logging.defaultClock.getTime() - self.win._frameTimes[-1]
|
|
583
664
|
else:
|
|
584
665
|
frameT = 0
|
|
585
|
-
resp =
|
|
666
|
+
resp = LightSensorResponse(
|
|
586
667
|
t=self.clock.getTime() - frameT,
|
|
587
668
|
value=state,
|
|
588
669
|
channel=0,
|
|
589
|
-
threshold=self._threshold
|
|
670
|
+
threshold=self._threshold,
|
|
671
|
+
device=self
|
|
590
672
|
)
|
|
591
673
|
self.receiveMessage(resp)
|
|
592
674
|
|
|
593
675
|
def parseMessage(self, message):
|
|
594
676
|
"""
|
|
595
|
-
Events are created as
|
|
677
|
+
Events are created as LightSensorResponses, so parseMessage is not needed for
|
|
596
678
|
ScreenBufferValidator. Will return message unchanged.
|
|
597
679
|
"""
|
|
598
680
|
return message
|
|
@@ -615,8 +697,8 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
615
697
|
@staticmethod
|
|
616
698
|
def getAvailableDevices():
|
|
617
699
|
return [{
|
|
618
|
-
'deviceName': "
|
|
619
|
-
'deviceClass': "psychopy.hardware.
|
|
700
|
+
'deviceName': "Light Sensor Emulator (Screen Buffer)",
|
|
701
|
+
'deviceClass': "psychopy.hardware.lightsensor.ScreenBufferSampler",
|
|
620
702
|
'win': "session.win"
|
|
621
703
|
}]
|
|
622
704
|
|
|
@@ -678,7 +760,7 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
678
760
|
def units(self, value):
|
|
679
761
|
self._units = value
|
|
680
762
|
|
|
681
|
-
def
|
|
763
|
+
def findSensor(self, win=None, channel=0):
|
|
682
764
|
if win is None:
|
|
683
765
|
win = self.win
|
|
684
766
|
else:
|
|
@@ -686,7 +768,7 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
686
768
|
# handle None
|
|
687
769
|
if channel is None:
|
|
688
770
|
channel = 0
|
|
689
|
-
# there's no physical
|
|
771
|
+
# there's no physical light sensor, so just pick a reasonable place for it
|
|
690
772
|
self._pos = layout.Position((0.95, -0.95), units="norm", win=win)
|
|
691
773
|
self._size = layout.Size((0.05, 0.05), units="norm", win=win)
|
|
692
774
|
self.units = "norm"
|
|
@@ -701,146 +783,7 @@ class ScreenBufferSampler(BasePhotodiodeGroup):
|
|
|
701
783
|
# handle None
|
|
702
784
|
if channel is None:
|
|
703
785
|
channel = 0
|
|
704
|
-
# there's no physical
|
|
705
|
-
self.setThreshold(
|
|
786
|
+
# there's no physical light sensor, so just pick a reasonable threshold
|
|
787
|
+
self.setThreshold(0.5, channel=channel)
|
|
706
788
|
|
|
707
789
|
return self.getThreshold(channel=channel)
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
class PhotodiodeValidator:
|
|
711
|
-
|
|
712
|
-
def __init__(
|
|
713
|
-
self, win, diode, channel=None,
|
|
714
|
-
variability=1/60,
|
|
715
|
-
report="log",
|
|
716
|
-
autoLog=False):
|
|
717
|
-
# set autolog
|
|
718
|
-
self.autoLog = autoLog
|
|
719
|
-
# store window handle
|
|
720
|
-
self.win = win
|
|
721
|
-
# store diode handle
|
|
722
|
-
self.diode = diode
|
|
723
|
-
self.channel = channel
|
|
724
|
-
# store method of reporting
|
|
725
|
-
self.report = report
|
|
726
|
-
# set acceptable variability
|
|
727
|
-
self.variability = variability
|
|
728
|
-
|
|
729
|
-
from psychopy import visual
|
|
730
|
-
# black rect which is always drawn on win flip
|
|
731
|
-
self.offRect = visual.Rect(
|
|
732
|
-
win,
|
|
733
|
-
fillColor="black",
|
|
734
|
-
depth=1, autoDraw=True,
|
|
735
|
-
autoLog=False
|
|
736
|
-
)
|
|
737
|
-
# white rect which is only drawn when target stim is, and covers black rect
|
|
738
|
-
self.onRect = visual.Rect(
|
|
739
|
-
win,
|
|
740
|
-
fillColor="white",
|
|
741
|
-
depth=0, autoDraw=False,
|
|
742
|
-
autoLog=False
|
|
743
|
-
)
|
|
744
|
-
# update rects to match diode
|
|
745
|
-
self.updateRects()
|
|
746
|
-
|
|
747
|
-
def connectStimulus(self, stim):
|
|
748
|
-
# store mapping of stimulus to self in window
|
|
749
|
-
self.win.validators[stim] = self
|
|
750
|
-
stim.validator = self
|
|
751
|
-
|
|
752
|
-
def draw(self):
|
|
753
|
-
self.onRect.draw()
|
|
754
|
-
|
|
755
|
-
def updateRects(self):
|
|
756
|
-
"""
|
|
757
|
-
Update the size and position of this validator's rectangles to match the size and position of the associated
|
|
758
|
-
diode.
|
|
759
|
-
"""
|
|
760
|
-
for rect in (self.onRect, self.offRect):
|
|
761
|
-
# set units from diode
|
|
762
|
-
rect.units = self.diode.units
|
|
763
|
-
# set pos from diode, or choose default if None
|
|
764
|
-
if self.diode.pos is not None:
|
|
765
|
-
rect.pos = self.diode.pos
|
|
766
|
-
else:
|
|
767
|
-
rect.pos = layout.Position((0.95, -0.95), units="norm", win=self.win)
|
|
768
|
-
# set size from diode, or choose default if None
|
|
769
|
-
if self.diode.size is not None:
|
|
770
|
-
rect.size = self.diode.size
|
|
771
|
-
else:
|
|
772
|
-
rect.size = layout.Size((0.05, 0.05), units="norm", win=self.win)
|
|
773
|
-
|
|
774
|
-
def validate(self, state, t=None):
|
|
775
|
-
"""
|
|
776
|
-
Confirm that stimulus was shown/hidden at the correct time, to within an acceptable margin of variability.
|
|
777
|
-
|
|
778
|
-
Parameters
|
|
779
|
-
----------
|
|
780
|
-
state : bool
|
|
781
|
-
State which the photodiode is expected to have been in
|
|
782
|
-
t : clock.Timestamp, visual.Window or None
|
|
783
|
-
Time at which the photodiode should have read the given state.
|
|
784
|
-
|
|
785
|
-
Returns
|
|
786
|
-
-------
|
|
787
|
-
bool
|
|
788
|
-
True if photodiode state matched requested state, False otherwise.
|
|
789
|
-
"""
|
|
790
|
-
# get and clear responses
|
|
791
|
-
messages = self.diode.getResponses(state=state, channel=self.channel, clear=True)
|
|
792
|
-
# if there have been no responses yet, return empty handed
|
|
793
|
-
if not messages:
|
|
794
|
-
return None, None
|
|
795
|
-
|
|
796
|
-
# if there are responses, get most recent timestamp
|
|
797
|
-
lastTime = messages[-1].t
|
|
798
|
-
# validate
|
|
799
|
-
valid = abs(lastTime - t) < self.variability
|
|
800
|
-
|
|
801
|
-
# construct message to report
|
|
802
|
-
validStr = "within acceptable variability"
|
|
803
|
-
if not valid:
|
|
804
|
-
validStr = "not " + validStr
|
|
805
|
-
logMsg = (
|
|
806
|
-
"Photodiode expected to receive {state} within {variability}s of {t}s. Actually received {state} at "
|
|
807
|
-
"{lastTime}. This is {validStr}."
|
|
808
|
-
).format(
|
|
809
|
-
state=state, variability=self.variability, t=t, lastTime=lastTime, validStr=validStr
|
|
810
|
-
)
|
|
811
|
-
|
|
812
|
-
# report as requested
|
|
813
|
-
if self.report in ("log",):
|
|
814
|
-
# if report mode is log or error, log result
|
|
815
|
-
logging.debug(logMsg)
|
|
816
|
-
if self.report in ("err", "error") and not valid:
|
|
817
|
-
# if report mode is error, raise error for invalid
|
|
818
|
-
err = PhotodiodeValidationError(logMsg)
|
|
819
|
-
logging.error(err)
|
|
820
|
-
raise err
|
|
821
|
-
if callable(self.report):
|
|
822
|
-
# if self.report is a method, call it with args state, t, valid and logMsg
|
|
823
|
-
self.report(state, t, valid, logMsg)
|
|
824
|
-
|
|
825
|
-
# return timestamp and validity
|
|
826
|
-
return lastTime, valid
|
|
827
|
-
|
|
828
|
-
def resetTimer(self, clock=logging.defaultClock):
|
|
829
|
-
self.diode.resetTimer(clock=clock)
|
|
830
|
-
|
|
831
|
-
def getDiodeState(self):
|
|
832
|
-
return self.diode.getState()
|
|
833
|
-
|
|
834
|
-
@staticmethod
|
|
835
|
-
def onValid(isWhite):
|
|
836
|
-
pass
|
|
837
|
-
|
|
838
|
-
@staticmethod
|
|
839
|
-
def onInvalid(isWhite):
|
|
840
|
-
msg = "Stimulus validation failed. "
|
|
841
|
-
if isWhite:
|
|
842
|
-
msg += "Stimulus drawn when not expected."
|
|
843
|
-
else:
|
|
844
|
-
msg += "Stimulus not drawn when expected."
|
|
845
|
-
|
|
846
|
-
raise AssertionError(msg)
|