psychopy 2024.2.4__py3-none-any.whl → 2025.1.0__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 +208 -4
- 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 +1514 -3259
- 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 +37 -15
- 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 +2 -0
- 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 +1 -1
- 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/{Feature Demos/eyetracking/eyetracking.xml → Hardware/lab_streaming_layer/lsl_triggers_demo_legacy_legacy.psyexp} +154 -140
- 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 +62 -16
- 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 +16 -3
- 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 +534 -154
- 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/client/__init__.py +17 -0
- psychopy/iohub/client/keyboard.py +5 -0
- psychopy/iohub/devices/eyetracker/__init__.py +10 -18
- psychopy/iohub/devices/eyetracker/calibration/procedure.py +15 -33
- psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/__init__.py +1 -0
- psychopy/iohub/devices/mouse/linux2.py +6 -1
- psychopy/iohub/devices/mouse/win32.py +5 -0
- 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_loaded_namespace/test_counterbalance.psyexp +142 -0
- psychopy/tests/data/test_loaded_namespace/test_custom_missing.psyexp +129 -0
- psychopy/tests/data/test_loaded_namespace/test_missing_counterbalance.psyexp +116 -0
- psychopy/tests/data/test_loaded_namespace/test_mix_exp.psyexp +181 -0
- psychopy/tests/data/test_loaded_namespace/test_mix_missing.psyexp +140 -0
- psychopy/tests/data/test_loaded_namespace/test_mix_name_calibration.psyexp +164 -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_experiment.py +96 -0
- 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/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 +2964 -558
- 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 +1 -1
- 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 +373 -200
- psychopy/web.py +1 -1
- {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/METADATA +9 -9
- {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/RECORD +653 -660
- 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/zh_CN/LC_MESSAGE/zh_CN.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN.po +0 -6127
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.po +0 -7366
- psychopy/core.py.orig +0 -169
- psychopy/demos/builder/.DS_Store +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/index.html +0 -23
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks-legacy-browsers.js +0 -423
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks.js +0 -427
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/chooseBlock.xlsx +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/facesBlock.xlsx +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/housesBlock.xlsx +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face01.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face02.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face03.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house01.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house02.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house03.jpg +0 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.py +0 -330
- 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/Feature Demos/eyetracking/eyetracking.xsd +0 -120
- 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.psyexp +0 -323
- psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual.py +0 -562
- psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual_lastrun.py +0 -562
- psychopy/demos/builder/Tools/gammaCalibration/questStairs.xlsx +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/resources/low_contrast.png +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/resources/make_2nd_order_tex.py +0 -59
- psychopy/demos/builder/Tools/gammaCalibration/resources/second_order_tex.png +0 -0
- 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/demos/coder/stimuli/radialGratingContracting.py +0 -29
- 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/hardware/serialport.py +0 -51
- 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/__test.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/corrFullRandom_local.csv +0 -16
- psychopy/tests/data/corrFullRandom_local.tsv +0 -6
- 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/testLoopsBlocks.psyexp_local.py +0 -328
- 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/text2_height.png +0 -0
- psychopy/tests/data/text2_normAddBlend.png +0 -0
- psychopy/tests/data/text2_normHexbackground.png +0 -0
- psychopy/tests/data/text2_stencil.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.csv +0 -9
- 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.csv +0 -9
- 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/{demos/builder/Tools/gammaCalibration/readme.md → tests/test_plugins/__init__.py} +0 -0
- {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/WHEEL +0 -0
- {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/entry_points.txt +0 -0
- {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from psychopy import constants, core, sound, logging
|
|
3
|
+
from psychopy.hardware import base, DeviceManager
|
|
4
|
+
from psychopy.localization import _translate
|
|
5
|
+
from psychopy.hardware import keyboard
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SoundSensorResponse(base.BaseResponse):
|
|
9
|
+
# list of fields known to be a part of this response type
|
|
10
|
+
fields = ["t", "value", "channel", "threshold"]
|
|
11
|
+
|
|
12
|
+
def __init__(self, t, value, channel, device=None, threshold=None):
|
|
13
|
+
# initialise base response class
|
|
14
|
+
base.BaseResponse.__init__(self, t=t, value=value, device=device)
|
|
15
|
+
# store channel and threshold
|
|
16
|
+
self.channel = channel
|
|
17
|
+
self.threshold = threshold
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BaseSoundSensorGroup(base.BaseResponseDevice):
|
|
21
|
+
|
|
22
|
+
def __init__(self, channels=1, threshold=None):
|
|
23
|
+
base.BaseResponseDevice.__init__(self)
|
|
24
|
+
# store number of channels
|
|
25
|
+
self.channels = channels
|
|
26
|
+
# attribute in which to store current state
|
|
27
|
+
self.state = [False] * channels
|
|
28
|
+
# set initial threshold
|
|
29
|
+
self.threshold = [None] * channels
|
|
30
|
+
self.setThreshold(threshold, channel=list(range(channels)))
|
|
31
|
+
|
|
32
|
+
def findThreshold(self, speaker, channel=None, samplingWindow=0.5):
|
|
33
|
+
"""
|
|
34
|
+
Find the best threshold for this device with a given speaker.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
speaker : psychopy.hardware.speaker.SpeakerDevice
|
|
39
|
+
Speaker to find best threshold for.
|
|
40
|
+
channel : int or list[int]
|
|
41
|
+
Channel to look for responses in, or a list of channels
|
|
42
|
+
samplingWindow : float
|
|
43
|
+
How long (s) to wait for a response after playing the test noise
|
|
44
|
+
"""
|
|
45
|
+
# if not given any channels, use all
|
|
46
|
+
if channel is None:
|
|
47
|
+
channel = list(range(self.channels))
|
|
48
|
+
# is given many channels, find for each
|
|
49
|
+
if isinstance(channel, (list, tuple)):
|
|
50
|
+
thresholds = []
|
|
51
|
+
# iterate through channels
|
|
52
|
+
for thisChannel in channel:
|
|
53
|
+
thresholds.append(
|
|
54
|
+
self.findThreshold(speaker, channel=thisChannel)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return thresholds
|
|
58
|
+
|
|
59
|
+
# sound to play
|
|
60
|
+
snd = sound.Sound("voicekeyThresholdStim.wav", speaker=speaker, secs=5, loops=-1)
|
|
61
|
+
# keyboard to check for escape/continue
|
|
62
|
+
kb = keyboard.Keyboard(deviceName="defaultKeyboard")
|
|
63
|
+
|
|
64
|
+
def _bisectThreshold(threshRange, recursionLimit=16):
|
|
65
|
+
"""
|
|
66
|
+
Recursively narrow thresholds to approach an acceptable threshold
|
|
67
|
+
"""
|
|
68
|
+
# work out current
|
|
69
|
+
current = sum(threshRange) / 2
|
|
70
|
+
# set threshold
|
|
71
|
+
self._setThreshold(current, channel=channel)
|
|
72
|
+
# reset current state and clear responses
|
|
73
|
+
self.state[channel] = None
|
|
74
|
+
self.responses = []
|
|
75
|
+
# start a countdown for beep duration
|
|
76
|
+
countdown = core.CountdownTimer(samplingWindow)
|
|
77
|
+
# wait for a response
|
|
78
|
+
gotResp = False
|
|
79
|
+
while countdown.getTime() > 0:
|
|
80
|
+
gotResp = gotResp or self.getState(channel=channel)
|
|
81
|
+
# get state
|
|
82
|
+
value = self.getState(channel=channel)
|
|
83
|
+
# log
|
|
84
|
+
logging.debug(
|
|
85
|
+
f"Trying threshold range: {threshRange}, detected sound: {value}"
|
|
86
|
+
)
|
|
87
|
+
# set either upper or lower bound according to whether we got sound
|
|
88
|
+
if value:
|
|
89
|
+
threshRange[1] = current
|
|
90
|
+
else:
|
|
91
|
+
threshRange[0] = current
|
|
92
|
+
# check for escape before entering recursion
|
|
93
|
+
if kb.getKeys(['escape']):
|
|
94
|
+
return current
|
|
95
|
+
# check for recursion limit before reentering recursion
|
|
96
|
+
if recursionLimit <= 0:
|
|
97
|
+
return current
|
|
98
|
+
# return if threshold is small enough
|
|
99
|
+
if abs(threshRange[1] - threshRange[0]) < 4:
|
|
100
|
+
return current
|
|
101
|
+
# recur with new range
|
|
102
|
+
return _bisectThreshold(threshRange, recursionLimit=recursionLimit-1)
|
|
103
|
+
|
|
104
|
+
# reset state
|
|
105
|
+
self.dispatchMessages()
|
|
106
|
+
self.clearResponses()
|
|
107
|
+
# make sure sound isn't playing
|
|
108
|
+
snd.stop()
|
|
109
|
+
# get threshold with no sound
|
|
110
|
+
offThreshold = _bisectThreshold([0, 1], recursionLimit=16)
|
|
111
|
+
# play sound
|
|
112
|
+
snd.play()
|
|
113
|
+
# get threshold with sound
|
|
114
|
+
onThreshold = _bisectThreshold([0, 1], recursionLimit=16)
|
|
115
|
+
# stop sound once done
|
|
116
|
+
snd.stop()
|
|
117
|
+
# pick a threshold between white and black (i.e. one that's safe)
|
|
118
|
+
threshold = (offThreshold + onThreshold) / 2
|
|
119
|
+
# clear all the events created by this process
|
|
120
|
+
self.state = [None] * self.channels
|
|
121
|
+
self.dispatchMessages()
|
|
122
|
+
self.clearResponses()
|
|
123
|
+
# set to found threshold
|
|
124
|
+
self._setThreshold(int(threshold), channel=channel)
|
|
125
|
+
|
|
126
|
+
return int(threshold)
|
|
127
|
+
|
|
128
|
+
def getThreshold(self, channel):
|
|
129
|
+
return self.threshold[channel]
|
|
130
|
+
|
|
131
|
+
def setThreshold(self, threshold, channel=None):
|
|
132
|
+
# if not given a channel, set for all channels
|
|
133
|
+
if channel is None:
|
|
134
|
+
channel = list(range(self.channels))
|
|
135
|
+
# if given multiple channels, set for each
|
|
136
|
+
if isinstance(channel, (list, tuple)):
|
|
137
|
+
state = []
|
|
138
|
+
for thisChannel in channel:
|
|
139
|
+
state.append(
|
|
140
|
+
self.setThreshold(threshold, channel=thisChannel)
|
|
141
|
+
)
|
|
142
|
+
return state
|
|
143
|
+
|
|
144
|
+
# store threshold value
|
|
145
|
+
self.threshold[channel] = threshold
|
|
146
|
+
# do device-specific threshold setting
|
|
147
|
+
state = self._setThreshold(threshold, channel=channel)
|
|
148
|
+
|
|
149
|
+
return state
|
|
150
|
+
|
|
151
|
+
def _setThreshold(self, threshold, channel=None):
|
|
152
|
+
"""
|
|
153
|
+
Device-specific threshold setting method. This will be called by `setThreshold` and should
|
|
154
|
+
be overloaded by child classes of BaseSoundSensor.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
threshold : int
|
|
159
|
+
Threshold at which to register a SoundSensor response, with 0 being the lowest possible
|
|
160
|
+
volume and 255 being the highest.
|
|
161
|
+
channel : int
|
|
162
|
+
Channel to set the threshold for (if applicable to device)
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
------
|
|
166
|
+
bool
|
|
167
|
+
True if current decibel level is above the threshold.
|
|
168
|
+
"""
|
|
169
|
+
raise NotImplementedError()
|
|
170
|
+
|
|
171
|
+
def getResponses(self, state=None, channel=None, clear=True):
|
|
172
|
+
"""
|
|
173
|
+
Get responses which match a given on/off state.
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
state : bool or None
|
|
178
|
+
True to get voicekey "on" responses, False to get voicekey "off" responses, None to
|
|
179
|
+
get all responses.
|
|
180
|
+
channel : int
|
|
181
|
+
Which voicekey to get responses from?
|
|
182
|
+
clear : bool
|
|
183
|
+
Whether or not to remove responses matching `state` after retrieval.
|
|
184
|
+
|
|
185
|
+
Returns
|
|
186
|
+
-------
|
|
187
|
+
list[SoundSensorResponse]
|
|
188
|
+
List of matching responses.
|
|
189
|
+
"""
|
|
190
|
+
# make sure parent dispatches messages
|
|
191
|
+
self.dispatchMessages()
|
|
192
|
+
# array to store matching responses
|
|
193
|
+
matches = []
|
|
194
|
+
# check messages in chronological order
|
|
195
|
+
for resp in self.responses.copy():
|
|
196
|
+
# does this message meet the criterion?
|
|
197
|
+
if (state is None or resp.value == state) and (channel is None or resp.channel == channel):
|
|
198
|
+
# if clear, remove the response
|
|
199
|
+
if clear:
|
|
200
|
+
i = self.responses.index(resp)
|
|
201
|
+
resp = self.responses.pop(i)
|
|
202
|
+
# append the response to responses array
|
|
203
|
+
matches.append(resp)
|
|
204
|
+
|
|
205
|
+
return matches
|
|
206
|
+
|
|
207
|
+
def receiveMessage(self, message):
|
|
208
|
+
# do base receiving
|
|
209
|
+
base.BaseResponseDevice.receiveMessage(self, message)
|
|
210
|
+
# update state
|
|
211
|
+
self.state[message.channel] = message.value
|
|
212
|
+
|
|
213
|
+
def resetTimer(self, clock=logging.defaultClock):
|
|
214
|
+
raise NotImplementedError()
|
|
215
|
+
|
|
216
|
+
def getState(self, channel):
|
|
217
|
+
# dispatch messages from parent
|
|
218
|
+
self.dispatchMessages()
|
|
219
|
+
# return state after update
|
|
220
|
+
return self.state[channel]
|
|
221
|
+
|
|
222
|
+
def findSpeakers(self, channel, allowedSpeakers=None, beepDur=1):
|
|
223
|
+
"""
|
|
224
|
+
Play a sound on different speakers and return a list of all those which this SoundSensor was
|
|
225
|
+
able to detect.
|
|
226
|
+
|
|
227
|
+
Parameters
|
|
228
|
+
----------
|
|
229
|
+
channel : int
|
|
230
|
+
Channel to listen for responses on.
|
|
231
|
+
allowedSpeakers : list[SpeakerDevice or dict] or None
|
|
232
|
+
List of speakers to test, or leave as None to test all speakers. If speakers are given
|
|
233
|
+
as a dict, SpeakerDevice objects will be created via DeviceManager.
|
|
234
|
+
beepDur : float
|
|
235
|
+
How long (s) to play a beep for on each speaker?
|
|
236
|
+
"""
|
|
237
|
+
# if no allowed speakers given, use all
|
|
238
|
+
if allowedSpeakers is None:
|
|
239
|
+
allowedSpeakers = DeviceManager.getAvailableDevices(
|
|
240
|
+
"psychopy.hardware.speaker.SpeakerDevice"
|
|
241
|
+
)
|
|
242
|
+
# list of found speakers
|
|
243
|
+
foundSpeakers = []
|
|
244
|
+
# iterate through allowed speakers
|
|
245
|
+
for speaker in allowedSpeakers:
|
|
246
|
+
# if given a dict, actualise it
|
|
247
|
+
if isinstance(speaker, dict):
|
|
248
|
+
speakerProfile = speaker
|
|
249
|
+
speaker = DeviceManager.getDevice(speakerProfile['deviceName'])
|
|
250
|
+
if speaker is None:
|
|
251
|
+
speaker = DeviceManager.addDevice(**speakerProfile)
|
|
252
|
+
# generate a sound for this speaker
|
|
253
|
+
try:
|
|
254
|
+
snd = sound.Sound("A", speaker=speaker)
|
|
255
|
+
except Exception as err:
|
|
256
|
+
# silently skip on error
|
|
257
|
+
logging.warn(f"Failed to play audio on speaker {speaker}, reason: {err}")
|
|
258
|
+
continue
|
|
259
|
+
# reset current state and clear responses
|
|
260
|
+
self.state[channel] = False
|
|
261
|
+
self.responses = []
|
|
262
|
+
# start a countdown for beep duration
|
|
263
|
+
countdown = core.CountdownTimer(beepDur)
|
|
264
|
+
# start playing sound
|
|
265
|
+
snd.play()
|
|
266
|
+
# wait for a response
|
|
267
|
+
while countdown.getTime() > 0:
|
|
268
|
+
self.dispatchMessages()
|
|
269
|
+
# stop playing sound
|
|
270
|
+
snd.stop()
|
|
271
|
+
# wait again for the off message, to a max of the beep duration
|
|
272
|
+
countdown.reset(beepDur)
|
|
273
|
+
while countdown.getTime() > 0 and len(self.responses) <= 1:
|
|
274
|
+
self.dispatchMessages()
|
|
275
|
+
# if we got messages, the speaker is good
|
|
276
|
+
if len(self.responses) == 2:
|
|
277
|
+
foundSpeakers.append(speaker)
|
|
278
|
+
|
|
279
|
+
return foundSpeakers
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class MicrophoneSoundSensor(BaseSoundSensorGroup):
|
|
284
|
+
"""
|
|
285
|
+
Use a MicrophoneDevice to emulate a SoundSensor, by continuously querying its volume.
|
|
286
|
+
|
|
287
|
+
Parameters
|
|
288
|
+
----------
|
|
289
|
+
device : psychopy.hardware.MicrophoneDevice
|
|
290
|
+
Microphone to sample from
|
|
291
|
+
threshold : int, optional
|
|
292
|
+
Threshold (0-1) at which to register a response, by default 0.5
|
|
293
|
+
dbRange : tuple, optional
|
|
294
|
+
Range of possible decibels to expect mic responses to be in, by default (0, 1)
|
|
295
|
+
samplingWindow : float
|
|
296
|
+
How long (s) to average samples from the microphone across? Larger sampling windows reduce
|
|
297
|
+
the chance of random spikes, but also reduce sensitivity.
|
|
298
|
+
"""
|
|
299
|
+
def __init__(self, device, threshold=0.5, dbRange=(0, 1), samplingWindow=0.03):
|
|
300
|
+
# if device is given by name, get it from DeviceManager
|
|
301
|
+
if isinstance(device, str):
|
|
302
|
+
deviceName = device
|
|
303
|
+
device = DeviceManager.getDevice(deviceName)
|
|
304
|
+
# if none by that name, try by that index
|
|
305
|
+
if device is None:
|
|
306
|
+
device = DeviceManager.getDeviceBy("index", deviceName)
|
|
307
|
+
# if none by that index, do any profiles match?
|
|
308
|
+
if device is None:
|
|
309
|
+
for profile in DeviceManager.getAvailableDevices(
|
|
310
|
+
"psychopy.hardware.microphone.MicrophoneDevice"
|
|
311
|
+
):
|
|
312
|
+
# if any match the index, make a device from that profile
|
|
313
|
+
if deviceName in (profile['index'], profile['deviceName']):
|
|
314
|
+
device = DeviceManager.addDevice(**profile)
|
|
315
|
+
# if none found, fallback to default and print warning
|
|
316
|
+
if device is None:
|
|
317
|
+
logging.warn(
|
|
318
|
+
f"No Microphonen named {deviceName}, falling back to default device."
|
|
319
|
+
)
|
|
320
|
+
# if no device given, get default
|
|
321
|
+
if device is None:
|
|
322
|
+
device = DeviceManager.getDeviceBy("index", None)
|
|
323
|
+
# store device
|
|
324
|
+
self.device = device
|
|
325
|
+
# store decibel range
|
|
326
|
+
self.dbRange = dbRange
|
|
327
|
+
# store sampling window
|
|
328
|
+
self.samplingWindow = samplingWindow
|
|
329
|
+
# make clock
|
|
330
|
+
from psychopy.core import Clock
|
|
331
|
+
self.clock = Clock()
|
|
332
|
+
# initialise base class
|
|
333
|
+
BaseSoundSensorGroup.__init__(
|
|
334
|
+
self, channels=1, threshold=threshold
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
def getThreshold(self, channel=None):
|
|
338
|
+
return BaseSoundSensorGroup.getThreshold(self, channel=channel or 0)
|
|
339
|
+
|
|
340
|
+
def getThresholdDb(self, channel=None):
|
|
341
|
+
"""
|
|
342
|
+
Get the volume threshold in dB rather than arbitrary units.
|
|
343
|
+
"""
|
|
344
|
+
return (
|
|
345
|
+
min(self.dbRange) +
|
|
346
|
+
self.getThreshold(channel=channel) * (max(self.dbRange) - min(self.dbRange))
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
def _setThreshold(self, threshold, channel=None):
|
|
350
|
+
"""
|
|
351
|
+
No additional setup is needed for emulator as thresholding is emulated outside of the
|
|
352
|
+
device.
|
|
353
|
+
"""
|
|
354
|
+
return self.getState(channel=channel)
|
|
355
|
+
|
|
356
|
+
def dispatchMessages(self):
|
|
357
|
+
"""
|
|
358
|
+
Check the Microphone volume and deliver appropriate response.
|
|
359
|
+
"""
|
|
360
|
+
# make sure mic is recording
|
|
361
|
+
if not self.device.isStarted:
|
|
362
|
+
self.device.start()
|
|
363
|
+
# get current volume
|
|
364
|
+
vol = self.device.getCurrentVolume(timeframe=self.samplingWindow)
|
|
365
|
+
# if device is multi-channel, take max
|
|
366
|
+
if not isinstance(vol, (int, float)):
|
|
367
|
+
vol = max(vol)
|
|
368
|
+
# transform volume to arbitrary units
|
|
369
|
+
adjVol = int(
|
|
370
|
+
(vol - min(self.dbRange)) / (max(self.dbRange) - min(self.dbRange)) * 255
|
|
371
|
+
)
|
|
372
|
+
# iterate through channels
|
|
373
|
+
for channel in range(self.channels):
|
|
374
|
+
# work out state from adjusted volume
|
|
375
|
+
state = adjVol > self.getThreshold(channel=channel)
|
|
376
|
+
# if state has changed, make an event
|
|
377
|
+
if state != self.state[channel]:
|
|
378
|
+
resp = SoundSensorResponse(
|
|
379
|
+
t=self.clock.getTime(),
|
|
380
|
+
value=state,
|
|
381
|
+
channel=channel,
|
|
382
|
+
threshold=self.getThreshold(channel=channel),
|
|
383
|
+
device=self
|
|
384
|
+
)
|
|
385
|
+
self.receiveMessage(resp)
|
|
386
|
+
|
|
387
|
+
def parseMessage(self, message):
|
|
388
|
+
"""
|
|
389
|
+
Events are created as SoundSensorResponse, so parseMessage is not needed. Will return message
|
|
390
|
+
unchanged.
|
|
391
|
+
"""
|
|
392
|
+
return message
|
|
393
|
+
|
|
394
|
+
def isSameDevice(self, other):
|
|
395
|
+
if isinstance(other, type(self)):
|
|
396
|
+
# if both objects are this class, then compare mics
|
|
397
|
+
return other.device is self.device
|
|
398
|
+
else:
|
|
399
|
+
# if types don't match up, it's not the same device
|
|
400
|
+
return False
|
|
401
|
+
|
|
402
|
+
@staticmethod
|
|
403
|
+
def getAvailableDevices():
|
|
404
|
+
profiles = []
|
|
405
|
+
# iterate through available microphones
|
|
406
|
+
for micProfile in DeviceManager.getAvailableDevices("psychopy.hardware.microphone.MicrophoneDevice"):
|
|
407
|
+
profiles.append({
|
|
408
|
+
'deviceName': "SoundSensor Emulator (%(deviceName)s)" % micProfile,
|
|
409
|
+
'deviceClass': "psychopy.hardware.soundsensor.MicrophoneSoundSensor",
|
|
410
|
+
'device': micProfile['index'],
|
|
411
|
+
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
return profiles
|
|
415
|
+
|
|
416
|
+
def resetTimer(self, clock=logging.defaultClock):
|
|
417
|
+
self.clock._timeAtLastReset = clock._timeAtLastReset
|
|
418
|
+
self.clock._epochTimeAtLastReset = clock._epochTimeAtLastReset
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
class SoundSensor:
|
|
422
|
+
"""
|
|
423
|
+
Object to represent a SoundSensor in Builder experiments. Largely exists as a wrapper around
|
|
424
|
+
BaseSoundSensorGroup, with the ability to inherit a device defined by a backend.
|
|
425
|
+
"""
|
|
426
|
+
def __init__(self, device):
|
|
427
|
+
if isinstance(device, BaseSoundSensorGroup):
|
|
428
|
+
# if given a button group, use it
|
|
429
|
+
self.device = device
|
|
430
|
+
# if given a string, get via DeviceManager
|
|
431
|
+
if isinstance(device, str):
|
|
432
|
+
if device in DeviceManager.devices:
|
|
433
|
+
self.device = DeviceManager.getDevice(device)
|
|
434
|
+
else:
|
|
435
|
+
# don't use formatted string literals in _translate()
|
|
436
|
+
raise ValueError(_translate(
|
|
437
|
+
"Could not find device named '{device}', make sure it has been set up "
|
|
438
|
+
"in DeviceManager."
|
|
439
|
+
).format(device))
|
|
440
|
+
|
|
441
|
+
# starting value for status (Builder)
|
|
442
|
+
self.status = constants.NOT_STARTED
|
|
443
|
+
# arrays to store info (Builder)
|
|
444
|
+
self.buttons = []
|
|
445
|
+
self.times = []
|
|
446
|
+
self.corr = []
|
|
447
|
+
|
|
448
|
+
def getAvailableDevices(self):
|
|
449
|
+
return self.device.getAvailableDevices()
|
|
450
|
+
|
|
451
|
+
def getResponses(self, state=None, channel=None, clear=True):
|
|
452
|
+
return self.device.getResponses(state=state, channel=channel, clear=clear)
|
|
453
|
+
|
|
454
|
+
def resetTimer(self, clock=logging.defaultClock):
|
|
455
|
+
return self.device.resetTimer(clock=clock)
|
|
456
|
+
|
|
457
|
+
def getState(self, channel):
|
|
458
|
+
return self.device.getState(channel=channel)
|
|
459
|
+
|
|
460
|
+
def clearResponses(self):
|
|
461
|
+
return self.device.clearResponses()
|
|
462
|
+
|
|
463
|
+
def findSpeakers(self, channel, allowedSpeakers=None, beepDur=1):
|
|
464
|
+
return self.device.findSpeakers(channel, allowedSpeakers=allowedSpeakers, beepDur=beepDur)
|
|
465
|
+
|
|
466
|
+
def findThreshold(self, speaker, channel=None, samplingWindow=0.5):
|
|
467
|
+
self.device.findThreshold(speaker, channel=channel, samplingWindow=samplingWindow)
|
|
468
|
+
|
|
469
|
+
def getThreshold(self, channel):
|
|
470
|
+
self.device.getThreshold(channel=channel)
|
|
471
|
+
|
|
472
|
+
def setThreshold(self, threshold, channel=None):
|
|
473
|
+
self.device.setThreshold(threshold=threshold, channel=channel)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Classes and functions for spatial tracking devices in PsychoPy.
|
|
4
|
+
"""
|
|
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 psychopy.tools.mathtools as mt
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TrackerData:
|
|
15
|
+
"""Class for storing motion tracking data.
|
|
16
|
+
|
|
17
|
+
This class is used to store data from a motion tracking device. The data
|
|
18
|
+
includes the position and orientation of the tracker, as well as the
|
|
19
|
+
angular and linear velocity and acceleration values reported by the device.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
absSampleTime : float
|
|
24
|
+
The absolute sample time of the tracker data in seconds.
|
|
25
|
+
pos : tuple
|
|
26
|
+
The position of the tracker in [x, y, z] coordinates.
|
|
27
|
+
ori : tuple
|
|
28
|
+
The orientation of the tracker in [x, y, z, w] quaternion.
|
|
29
|
+
linearVelocity : tuple
|
|
30
|
+
The linear velocity of the tracker in [vx, vy, vz] coordinates.
|
|
31
|
+
angularVelocity : tuple
|
|
32
|
+
The angular velocity of the tracker in [vx, vy, vz] coordinates.
|
|
33
|
+
linearAcceleration : tuple
|
|
34
|
+
The linear acceleration of the tracker in [ax, ay, az] coordinates.
|
|
35
|
+
angularAcceleration : tuple
|
|
36
|
+
The angular acceleration of the tracker in [ax, ay, az] coordinates.
|
|
37
|
+
compassHeading : float
|
|
38
|
+
The compass heading of the tracker in degrees.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
absSampleTime,
|
|
44
|
+
pos=(0., 0., 0.),
|
|
45
|
+
ori=(0., 0., 0., 1.),
|
|
46
|
+
linearVelocity=(0., 0., 0.),
|
|
47
|
+
angularVelocity=(0., 0., 0.),
|
|
48
|
+
linearAcceleration=(0., 0., 0.),
|
|
49
|
+
angularAcceleration=(0., 0., 0.),
|
|
50
|
+
compassHeading=0.0):
|
|
51
|
+
|
|
52
|
+
# time the data was sampled from the device
|
|
53
|
+
self._absSampleTime = float(absSampleTime)
|
|
54
|
+
|
|
55
|
+
# tracker pose
|
|
56
|
+
self._thePose = mt.RigidBodyPose(pos, ori, dtype=float)
|
|
57
|
+
|
|
58
|
+
# IMU data
|
|
59
|
+
self._angularVelocity = np.asarray(angularVelocity, dtype=float)
|
|
60
|
+
self._linearVelocity = np.asarray(linearVelocity, dtype=float)
|
|
61
|
+
self._angularAcceleration = np.asarray(linearAcceleration, dtype=float)
|
|
62
|
+
self._linearAcceleration = np.asarray(angularAcceleration, dtype=float)
|
|
63
|
+
self._compassHeading = float(compassHeading)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def thePose(self):
|
|
67
|
+
"""The pose of the tracker in 3D space.
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
RigidBodyPose
|
|
72
|
+
The pose of the tracker.
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
return self._thePose
|
|
76
|
+
|
|
77
|
+
@thePose.setter
|
|
78
|
+
def thePose(self, value):
|
|
79
|
+
if not isinstance(value, mt.RigidBodyPose):
|
|
80
|
+
raise TypeError("Expected a `RigidBodyPose` object.")
|
|
81
|
+
|
|
82
|
+
self._thePose = value
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def pos(self):
|
|
86
|
+
"""Return the position of the tracker.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
numpy.ndarray
|
|
91
|
+
The position of the tracker.
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
return self._trackerPose.getPos()
|
|
95
|
+
|
|
96
|
+
@pos.setter
|
|
97
|
+
def pos(self, value):
|
|
98
|
+
self._trackerPose.setPos(value)
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def ori(self):
|
|
102
|
+
"""Return the orientation of the tracker.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
numpy.ndarray
|
|
107
|
+
The orientation of the tracker.
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
return self._trackerPose.getOri()
|
|
111
|
+
|
|
112
|
+
@ori.setter
|
|
113
|
+
def ori(self, value):
|
|
114
|
+
self._trackerPose.setOri(value)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def posOri(self):
|
|
118
|
+
"""Return the position and orientation of the tracker.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
tuple
|
|
123
|
+
The position and orientation of the tracker.
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
return self._trackerPose.getPosOri()
|
|
127
|
+
|
|
128
|
+
@posOri.setter
|
|
129
|
+
def posOri(self, value):
|
|
130
|
+
self._trackerPose.setPosOri(value)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def absSampleTime(self):
|
|
134
|
+
"""Return the absolute sample time of the tracker data.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
float
|
|
139
|
+
The absolute sample time of the tracker data.
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
return self._absSampleTime
|
|
143
|
+
|
|
144
|
+
@absSampleTime.setter
|
|
145
|
+
def absSampleTime(self, value):
|
|
146
|
+
self._absSampleTime = float(value)
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def angularVelocity(self):
|
|
150
|
+
"""Return the angular velocity of the tracker.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
numpy.ndarray
|
|
155
|
+
The angular velocity of the tracker.
|
|
156
|
+
|
|
157
|
+
"""
|
|
158
|
+
return self._angularVelocity
|
|
159
|
+
|
|
160
|
+
@angularVelocity.setter
|
|
161
|
+
def angularVelocity(self, value):
|
|
162
|
+
self._angularVelocity[:] = value
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def linearVelocity(self):
|
|
166
|
+
"""Return the linear velocity of the tracker.
|
|
167
|
+
|
|
168
|
+
Returns
|
|
169
|
+
-------
|
|
170
|
+
numpy.ndarray
|
|
171
|
+
The linear velocity of the tracker.
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
return self._linearVelocity
|
|
175
|
+
|
|
176
|
+
@linearVelocity.setter
|
|
177
|
+
def linearVelocity(self, value):
|
|
178
|
+
self._linearVelocity[:] = value
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def angularAcceleration(self):
|
|
182
|
+
"""Return the angular acceleration of the tracker.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
numpy.ndarray
|
|
187
|
+
The angular acceleration of the tracker.
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
return self._angularAcceleration
|
|
191
|
+
|
|
192
|
+
@angularAcceleration.setter
|
|
193
|
+
def angularAcceleration(self, value):
|
|
194
|
+
self._angularAcceleration[:] = value
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def linearAcceleration(self):
|
|
198
|
+
"""Return the linear acceleration of the tracker.
|
|
199
|
+
|
|
200
|
+
Returns
|
|
201
|
+
-------
|
|
202
|
+
numpy.ndarray
|
|
203
|
+
The linear acceleration of the tracker.
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
return self._linearAcceleration
|
|
207
|
+
|
|
208
|
+
@linearAcceleration.setter
|
|
209
|
+
def linearAcceleration(self, value):
|
|
210
|
+
self._linearAcceleration[:] = value
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def compassHeading(self):
|
|
214
|
+
"""Return the compass heading of the tracker.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
float
|
|
219
|
+
The compass heading of the tracker.
|
|
220
|
+
|
|
221
|
+
"""
|
|
222
|
+
return self._compassHeading
|
|
223
|
+
|
|
224
|
+
@compassHeading.setter
|
|
225
|
+
def compassHeading(self, value):
|
|
226
|
+
self._compassHeading = value
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
pass
|
|
231
|
+
|