psychopy 2025.1.1__py3-none-any.whl → 2025.2.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/VERSION +1 -1
- psychopy/alerts/alertsCatalogue/4810.yaml +19 -0
- psychopy/alerts/alertsCatalogue/alertCategories.yaml +4 -0
- psychopy/alerts/alertsCatalogue/alertmsg.py +15 -1
- psychopy/alerts/alertsCatalogue/generateAlertmsg.py +2 -2
- psychopy/app/Resources/classic/add_many.png +0 -0
- psychopy/app/Resources/classic/add_many@2x.png +0 -0
- psychopy/app/Resources/classic/devices.png +0 -0
- psychopy/app/Resources/classic/devices@2x.png +0 -0
- psychopy/app/Resources/classic/photometer.png +0 -0
- psychopy/app/Resources/classic/photometer@2x.png +0 -0
- psychopy/app/Resources/dark/add_many.png +0 -0
- psychopy/app/Resources/dark/add_many@2x.png +0 -0
- psychopy/app/Resources/dark/devices.png +0 -0
- psychopy/app/Resources/dark/devices@2x.png +0 -0
- psychopy/app/Resources/dark/photometer.png +0 -0
- psychopy/app/Resources/dark/photometer@2x.png +0 -0
- psychopy/app/Resources/light/add_many.png +0 -0
- psychopy/app/Resources/light/add_many@2x.png +0 -0
- psychopy/app/Resources/light/devices.png +0 -0
- psychopy/app/Resources/light/devices@2x.png +0 -0
- psychopy/app/Resources/light/photometer.png +0 -0
- psychopy/app/Resources/light/photometer@2x.png +0 -0
- psychopy/app/_psychopyApp.py +35 -13
- psychopy/app/builder/builder.py +88 -35
- psychopy/app/builder/dialogs/__init__.py +69 -220
- psychopy/app/builder/dialogs/dlgsCode.py +29 -8
- psychopy/app/builder/dialogs/paramCtrls.py +1468 -904
- psychopy/app/builder/validators.py +25 -17
- psychopy/app/coder/coder.py +12 -1
- psychopy/app/coder/repl.py +5 -2
- psychopy/app/colorpicker/__init__.py +1 -1
- psychopy/app/deviceManager/__init__.py +1 -0
- psychopy/app/deviceManager/addDialog.py +218 -0
- psychopy/app/deviceManager/dialog.py +185 -0
- psychopy/app/deviceManager/panel.py +191 -0
- psychopy/app/deviceManager/utils.py +60 -0
- psychopy/app/idle.py +7 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +12695 -10592
- psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/da_DK/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +11221 -9712
- psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/el_GR/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_NZ/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/en_US/LC_MESSAGE/messages.po +10195 -18
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +11917 -9101
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +11924 -9103
- psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_US/LC_MESSAGE/messages.po +11917 -9101
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +11084 -9569
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +11590 -5806
- psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fi_FI/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +11091 -9577
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +11072 -9549
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +11071 -9559
- psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hu_HU/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +11072 -9560
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +1485 -1137
- psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ko_KR/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +11463 -8757
- psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/nl_NL/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/nn_NO/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pl_PL/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +11288 -9434
- psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ro_RO/LC_MESSAGE/messages.po +10200 -25
- psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ru_RU/LC_MESSAGE/messages.po +10199 -24
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +11441 -8747
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +11069 -9545
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +12085 -8268
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +11929 -8022
- psychopy/app/plugin_manager/dialog.py +12 -3
- psychopy/app/plugin_manager/packageIndex.py +303 -0
- psychopy/app/plugin_manager/packages.py +203 -63
- psychopy/app/plugin_manager/plugins.py +120 -240
- psychopy/app/preferencesDlg.py +6 -1
- psychopy/app/psychopyApp.py +16 -4
- psychopy/app/runner/runner.py +10 -2
- psychopy/app/runner/scriptProcess.py +8 -3
- psychopy/app/stdout/stdOutRich.py +11 -4
- psychopy/app/themes/icons.py +3 -0
- psychopy/app/utils.py +61 -0
- psychopy/data/experiment.py +133 -23
- psychopy/data/routine.py +12 -0
- psychopy/data/staircase.py +42 -20
- psychopy/data/trial.py +20 -12
- psychopy/data/utils.py +42 -2
- psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +22 -5
- psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solutions.xlsx +0 -0
- psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +2 -12
- psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +3 -8
- psychopy/demos/builder/Feature Demos/movies/movie.psyexp +220 -0
- psychopy/demos/builder/Feature Demos/movies/readme.md +3 -0
- psychopy/demos/builder/Feature Demos/visualValidator/visualValidator.psyexp +1 -2
- psychopy/demos/builder/Hardware/camera/camera.psyexp +3 -16
- psychopy/demos/builder/Hardware/microphone/microphone.psyexp +3 -16
- psychopy/demos/coder/hardware/hdf5_extract.py +133 -0
- psychopy/event.py +20 -15
- psychopy/experiment/_experiment.py +86 -10
- psychopy/experiment/components/__init__.py +3 -10
- psychopy/experiment/components/_base.py +9 -20
- psychopy/experiment/components/button/__init__.py +1 -1
- psychopy/experiment/components/buttonBox/__init__.py +50 -54
- psychopy/experiment/components/camera/__init__.py +137 -359
- psychopy/experiment/components/keyboard/__init__.py +17 -24
- psychopy/experiment/components/microphone/__init__.py +61 -110
- psychopy/experiment/components/movie/__init__.py +2 -3
- psychopy/experiment/components/serialOut/__init__.py +192 -93
- psychopy/experiment/components/settings/__init__.py +45 -27
- psychopy/experiment/components/sound/__init__.py +82 -73
- psychopy/experiment/components/soundsensor/__init__.py +43 -80
- psychopy/experiment/devices.py +303 -0
- psychopy/experiment/exports.py +20 -18
- psychopy/experiment/flow.py +7 -0
- psychopy/experiment/loops.py +47 -29
- psychopy/experiment/monitor.py +74 -0
- psychopy/experiment/params.py +48 -10
- psychopy/experiment/plugins.py +28 -108
- psychopy/experiment/py2js_transpiler.py +1 -1
- psychopy/experiment/routines/__init__.py +1 -1
- psychopy/experiment/routines/_base.py +59 -24
- psychopy/experiment/routines/audioValidator/__init__.py +19 -155
- psychopy/experiment/routines/visualValidator/__init__.py +25 -25
- psychopy/hardware/__init__.py +20 -57
- psychopy/hardware/button.py +15 -2
- psychopy/hardware/camera/__init__.py +2237 -1394
- psychopy/hardware/joystick/__init__.py +1 -1
- psychopy/hardware/keyboard.py +5 -8
- psychopy/hardware/listener.py +4 -1
- psychopy/hardware/manager.py +75 -35
- psychopy/hardware/microphone.py +52 -6
- psychopy/hardware/monitor.py +144 -0
- psychopy/hardware/photometer/__init__.py +156 -117
- psychopy/hardware/serialdevice.py +16 -2
- psychopy/hardware/soundsensor.py +4 -1
- psychopy/iohub/devices/deviceConfigValidation.py +2 -1
- psychopy/iohub/devices/keyboard/darwin.py +8 -5
- psychopy/iohub/util/__init__.py +7 -8
- psychopy/localization/generateTranslationTemplate.py +208 -116
- psychopy/localization/messages.pot +4305 -3502
- psychopy/monitors/MonitorCenter.py +174 -74
- psychopy/plugins/__init__.py +6 -4
- psychopy/preferences/devices.py +80 -0
- psychopy/preferences/generateHints.py +2 -1
- psychopy/preferences/preferences.py +35 -11
- psychopy/scripts/psychopy-pkgutil.py +969 -0
- psychopy/scripts/psyexpCompile.py +1 -1
- psychopy/session.py +34 -38
- psychopy/sound/__init__.py +6 -260
- psychopy/sound/audioclip.py +164 -0
- psychopy/sound/backend_ptb.py +8 -0
- psychopy/sound/backend_pygame.py +10 -0
- psychopy/sound/backend_pysound.py +9 -0
- psychopy/sound/backends/__init__.py +0 -0
- psychopy/sound/microphone.py +3 -0
- psychopy/sound/sound.py +58 -0
- psychopy/tests/data/correctScript/python/correctNoiseStimComponent.py +1 -1
- psychopy/tests/data/duplicateHeaders.csv +2 -0
- psychopy/tests/test_app/test_builder/test_BuilderFrame.py +22 -7
- psychopy/tests/test_app/test_builder/test_CompileFromBuilder.py +0 -2
- psychopy/tests/test_data/test_utils.py +5 -1
- psychopy/tests/test_experiment/test_components/test_ButtonBoxComponent.py +22 -2
- psychopy/tests/test_hardware/test_ports.py +0 -12
- psychopy/tests/test_tools/test_stringtools.py +1 -1
- psychopy/tools/attributetools.py +12 -5
- psychopy/tools/fontmanager.py +17 -14
- psychopy/tools/movietools.py +43 -2
- psychopy/tools/stringtools.py +33 -8
- psychopy/tools/versionchooser.py +1 -1
- psychopy/validation/audio.py +5 -1
- psychopy/validation/visual.py +5 -1
- psychopy/visual/basevisual.py +8 -7
- psychopy/visual/circle.py +2 -2
- psychopy/visual/image.py +29 -109
- psychopy/visual/movies/__init__.py +1800 -313
- psychopy/visual/polygon.py +4 -0
- psychopy/visual/shape.py +2 -2
- psychopy/visual/window.py +34 -11
- psychopy/voicekey/__init__.py +41 -669
- psychopy/voicekey/labjack_vks.py +7 -48
- psychopy/voicekey/parallel_vks.py +7 -42
- psychopy/voicekey/vk_tools.py +114 -263
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/METADATA +17 -11
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/RECORD +216 -184
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/WHEEL +1 -1
- psychopy/visual/movies/players/__init__.py +0 -62
- psychopy/visual/movies/players/ffpyplayer_player.py +0 -1401
- psychopy/voicekey/demo_vks.py +0 -12
- psychopy/voicekey/signal.py +0 -42
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/entry_points.txt +0 -0
- {psychopy-2025.1.1.dist-info → psychopy-2025.2.1.dist-info}/licenses/LICENSE +0 -0
psychopy/voicekey/labjack_vks.py
CHANGED
|
@@ -1,50 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
1
|
+
from psychopy.plugins import PluginStub
|
|
3
2
|
|
|
4
|
-
"""Class for voicekey trip signaling via Labjack device
|
|
5
|
-
"""
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
have_labjack = 'from labjack'
|
|
14
|
-
# ImportError: # other errors too, like labjack.u12.U12Exception (??)
|
|
15
|
-
except Exception:
|
|
16
|
-
try:
|
|
17
|
-
from psychopy.hardware import labjacks
|
|
18
|
-
labjack_U3 = labjacks.u3.U3
|
|
19
|
-
have_labjack = 'from psychopy.hardware.labjacks'
|
|
20
|
-
except Exception: # ImportError:
|
|
21
|
-
have_labjack = False
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class LabJackU3VoiceKeySignal(_BaseVoiceKeySignal):
|
|
25
|
-
"""Class for using a LabJack U3 device as a signal channel.
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def __init__(self, sec=0.010, delay=0, on=1, off=0, address=6008):
|
|
29
|
-
if not have_labjack:
|
|
30
|
-
raise ImportError("could not import labjack (for LabJack u3)")
|
|
31
|
-
super(LabJackU3VoiceKeySignal, self).__init__(sec, delay, on, off)
|
|
32
|
-
self.device = labjack_U3()
|
|
33
|
-
self.address = address
|
|
34
|
-
self.id = address
|
|
35
|
-
|
|
36
|
-
def signal(self):
|
|
37
|
-
"""Send a signal at the desired time.
|
|
38
|
-
|
|
39
|
-
After an optional `delay`, set a port to `on` for `sec`, then to `off`.
|
|
40
|
-
A delay is not recommended unless your system's time.sleep() function
|
|
41
|
-
has ms-level precision (yes Mac or linux, typically no for Windows).
|
|
42
|
-
"""
|
|
43
|
-
if self.delay:
|
|
44
|
-
sleep(self.delay)
|
|
45
|
-
t0 = get_time()
|
|
46
|
-
self.device.writeRegister(self.address, self.on)
|
|
47
|
-
# check time and self.running:
|
|
48
|
-
while self.running and get_time() - t0 < self.sec:
|
|
49
|
-
sleep(0.001)
|
|
50
|
-
self.device.writeRegister(self.address, self.off)
|
|
4
|
+
class LabJackU3VoiceKeySignal(
|
|
5
|
+
PluginStub,
|
|
6
|
+
plugin="psychopy-legacy",
|
|
7
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
8
|
+
):
|
|
9
|
+
pass
|
|
@@ -1,44 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
1
|
+
from psychopy.plugins import PluginStub
|
|
3
2
|
|
|
4
|
-
"""Completely untested. Doesn't work at all on Mac (no parallel).
|
|
5
|
-
"""
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
except Exception: # ImportError:
|
|
14
|
-
have_parallel = False
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class ParallelVoiceKeySignal(_BaseVoiceKeySignal):
|
|
18
|
-
"""Class for using PsychoPy parallel as a signal channel.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
def __init__(self, sec=0.010, delay=0, on=1, off=0, address=0x378, pin=2):
|
|
22
|
-
if not have_parallel:
|
|
23
|
-
raise ImportError("could not import parallel (for signaler)")
|
|
24
|
-
super(ParallelVoiceKeySignal, self).__init__(sec, delay, on, off)
|
|
25
|
-
self.id = '({0}, pin={1})'.format(hex(address), pin)
|
|
26
|
-
self.address = address
|
|
27
|
-
self.pin = pin # 2-9
|
|
28
|
-
self.port = parallel.ParallelPort(address)
|
|
29
|
-
|
|
30
|
-
def signal(self):
|
|
31
|
-
"""Send a signal at the desired time.
|
|
32
|
-
|
|
33
|
-
After an optional `delay`, set a pin to `on` for `sec`, then to `off`.
|
|
34
|
-
A delay is not recommended unless your system's time.sleep() function
|
|
35
|
-
has ms-level precision (yes Mac or linux, typically no for Windows).
|
|
36
|
-
"""
|
|
37
|
-
if self.delay:
|
|
38
|
-
sleep(self.delay)
|
|
39
|
-
t0 = get_time()
|
|
40
|
-
self.port.setData(self.on)
|
|
41
|
-
# check time and self.running:
|
|
42
|
-
while self.running and get_time() - t0 < self.sec:
|
|
43
|
-
sleep(0.001)
|
|
44
|
-
self.port.setData(self.off)
|
|
4
|
+
class ParallelVoiceKeySignal(
|
|
5
|
+
PluginStub,
|
|
6
|
+
plugin="psychopy-legacy",
|
|
7
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
8
|
+
):
|
|
9
|
+
pass
|
psychopy/voicekey/vk_tools.py
CHANGED
|
@@ -1,280 +1,131 @@
|
|
|
1
|
-
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
1
|
+
from psychopy.plugins import PluginStub
|
|
3
2
|
|
|
4
|
-
"""Digital signal processing functions; pyo table, file, & sample conversions
|
|
5
|
-
"""
|
|
6
3
|
|
|
4
|
+
class get_time(
|
|
5
|
+
PluginStub,
|
|
6
|
+
plugin="psychopy-legacy",
|
|
7
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
8
|
+
):
|
|
9
|
+
pass
|
|
7
10
|
|
|
8
11
|
|
|
12
|
+
class sleep(
|
|
13
|
+
PluginStub,
|
|
14
|
+
plugin="psychopy-legacy",
|
|
15
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
16
|
+
):
|
|
17
|
+
pass
|
|
9
18
|
|
|
10
|
-
import os
|
|
11
|
-
import sys
|
|
12
|
-
import time
|
|
13
|
-
import numpy as np
|
|
14
|
-
from scipy.signal import butter, lfilter
|
|
15
|
-
try:
|
|
16
|
-
import pyo64 as pyo
|
|
17
|
-
except Exception:
|
|
18
|
-
import pyo
|
|
19
19
|
|
|
20
|
+
class bandpass_pre_cache(
|
|
21
|
+
PluginStub,
|
|
22
|
+
plugin="psychopy-legacy",
|
|
23
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
24
|
+
):
|
|
25
|
+
pass
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
|
|
28
|
+
class bandpass(
|
|
29
|
+
PluginStub,
|
|
30
|
+
plugin="psychopy-legacy",
|
|
31
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
32
|
+
):
|
|
22
33
|
pass
|
|
23
34
|
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
_qpfreq = c_int64()
|
|
32
|
-
windll.Kernel32.QueryPerformanceFrequency(byref(_qpfreq))
|
|
33
|
-
_qpfreq = float(_qpfreq.value)
|
|
34
|
-
_winQPC = windll.Kernel32.QueryPerformanceCounter
|
|
36
|
+
class rms(
|
|
37
|
+
PluginStub,
|
|
38
|
+
plugin="psychopy-legacy",
|
|
39
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
40
|
+
):
|
|
41
|
+
pass
|
|
35
42
|
|
|
36
|
-
def get_time():
|
|
37
|
-
"""High-precision replacement for time.time() on Windows.
|
|
38
|
-
"""
|
|
39
|
-
_winQPC(byref(_fcounter))
|
|
40
|
-
return _fcounter.value / _qpfreq
|
|
41
|
-
else:
|
|
42
|
-
import timeit
|
|
43
|
-
get_time = timeit.default_timer
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
class std(
|
|
45
|
+
PluginStub,
|
|
46
|
+
plugin="psychopy-legacy",
|
|
47
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
48
|
+
):
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class smooth(
|
|
53
|
+
PluginStub,
|
|
54
|
+
plugin="psychopy-legacy",
|
|
55
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
56
|
+
):
|
|
57
|
+
pass
|
|
52
58
|
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
class zero_crossings(
|
|
61
|
+
PluginStub,
|
|
62
|
+
plugin="psychopy-legacy",
|
|
63
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
64
|
+
):
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class tone(
|
|
69
|
+
PluginStub,
|
|
70
|
+
plugin="psychopy-legacy",
|
|
71
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
72
|
+
):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class apodize(
|
|
77
|
+
PluginStub,
|
|
78
|
+
plugin="psychopy-legacy",
|
|
79
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
80
|
+
):
|
|
81
|
+
pass
|
|
82
|
+
|
|
61
83
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
class samples_from_table(
|
|
85
|
+
PluginStub,
|
|
86
|
+
plugin="psychopy-legacy",
|
|
87
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
88
|
+
):
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class table_from_samples(
|
|
93
|
+
PluginStub,
|
|
94
|
+
plugin="psychopy-legacy",
|
|
95
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
96
|
+
):
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class table_from_file(
|
|
101
|
+
PluginStub,
|
|
102
|
+
plugin="psychopy-legacy",
|
|
103
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
104
|
+
):
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class samples_from_file(
|
|
109
|
+
PluginStub,
|
|
110
|
+
plugin="psychopy-legacy",
|
|
111
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
112
|
+
):
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class samples_to_file(
|
|
117
|
+
PluginStub,
|
|
118
|
+
plugin="psychopy-legacy",
|
|
119
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
120
|
+
):
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class table_to_file(
|
|
125
|
+
PluginStub,
|
|
126
|
+
plugin="psychopy-legacy",
|
|
127
|
+
docsHome="https://psychopy.github.io/psychopy-legacy"
|
|
128
|
+
):
|
|
129
|
+
pass
|
|
73
130
|
|
|
74
131
|
|
|
75
|
-
def bandpass_pre_cache(lows=(80, 100, 120),
|
|
76
|
-
highs=(1200, 3000, 8000),
|
|
77
|
-
bands=((2000, 8000),), # content-filtered speech
|
|
78
|
-
rate=44100):
|
|
79
|
-
"""Call _butter now to cache some useful (b, a) values.
|
|
80
|
-
"""
|
|
81
|
-
for low in lows:
|
|
82
|
-
for high in highs:
|
|
83
|
-
_butter(6, (low, high), rate=rate)
|
|
84
|
-
for band in bands:
|
|
85
|
-
_butter(6, band, rate=rate)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def bandpass(data, low=80, high=1200, rate=44100, order=6):
|
|
89
|
-
"""Return bandpass filtered `data`.
|
|
90
|
-
"""
|
|
91
|
-
b, a = _butter(order, (low, high), rate)
|
|
92
|
-
return lfilter(b, a, data)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def rms(data):
|
|
96
|
-
"""Basic audio-power measure: root-mean-square of data.
|
|
97
|
-
|
|
98
|
-
Identical to `std` when the mean is zero; faster to compute just rms.
|
|
99
|
-
"""
|
|
100
|
-
if data.dtype == np.int16:
|
|
101
|
-
md2 = data.astype(float) ** 2 # int16 wrap around --> negative
|
|
102
|
-
else:
|
|
103
|
-
md2 = data ** 2
|
|
104
|
-
return np.sqrt(np.mean(md2))
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def std(data):
|
|
108
|
-
"""Like rms, but also subtracts the mean (= slower).
|
|
109
|
-
"""
|
|
110
|
-
return np.std(data)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def smooth(data, win=16, tile=True):
|
|
114
|
-
"""Running smoothed average, via convolution over `win` window-size.
|
|
115
|
-
|
|
116
|
-
`tile` with the mean at start and end by default; otherwise replace with 0.
|
|
117
|
-
"""
|
|
118
|
-
weights = np.ones(win) / win
|
|
119
|
-
data_c = np.convolve(data, weights)[win - 1:-(win - 1)]
|
|
120
|
-
if tile:
|
|
121
|
-
pre = np.tile(data_c[0], win // 2)
|
|
122
|
-
post = np.tile(data_c[-1], win // 2)
|
|
123
|
-
else:
|
|
124
|
-
pre = post = np.zeros(win // 2)
|
|
125
|
-
data_pre_c = np.concatenate((pre, data_c))
|
|
126
|
-
data_pre_c_post = np.concatenate((data_pre_c, post))
|
|
127
|
-
return data_pre_c_post[:len(data)]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def zero_crossings(data):
|
|
131
|
-
"""Return a vector of length n-1 of zero-crossings within vector `data`.
|
|
132
|
-
|
|
133
|
-
1 if the adjacent values switched sign, or
|
|
134
|
-
0 if they stayed the same sign.
|
|
135
|
-
"""
|
|
136
|
-
zx = np.zeros(len(data))
|
|
137
|
-
zx[np.where(data[:-1] * data[1:] < 0)] = 1
|
|
138
|
-
return zx
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def tone(freq=440, sec=2, rate=44100, vol=.99):
|
|
142
|
-
"""Return a np.array suitable for use as a tone (pure sine wave).
|
|
143
|
-
"""
|
|
144
|
-
samples = sec * rate
|
|
145
|
-
time_steps = np.arange(0., 1., 1. / samples)
|
|
146
|
-
scaling = 2 * np.pi * freq * sec
|
|
147
|
-
return np.sin(time_steps * scaling) * vol
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def apodize(data, ms=5, rate=44100):
|
|
151
|
-
"""Apply a Hanning window (5ms) to reduce a sound's 'click' onset / offset.
|
|
152
|
-
"""
|
|
153
|
-
hw_size = int(min(rate // (1000 / ms), len(data) // 15))
|
|
154
|
-
hanning_window = np.hanning(2 * hw_size + 1)
|
|
155
|
-
data[:hw_size] *= hanning_window[:hw_size]
|
|
156
|
-
data[-hw_size:] *= hanning_window[-hw_size:]
|
|
157
|
-
return data
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# --- pyo helper functions ------------------------------------------------
|
|
161
|
-
|
|
162
|
-
# format codes for _get_pyo_codes():
|
|
163
|
-
pyo_formats = {'wav': 0, 'aif': 1, 'aiff': 1, 'au': 2, 'raw': 3,
|
|
164
|
-
'sd2': 4, 'flac': 5, 'caf': 6, 'ogg': 7}
|
|
165
|
-
pyo_dtype = {'int16': 0, 'int24': 1, 'int32': 2, 'float32': 3,
|
|
166
|
-
'float64': 4, 'U-Law': 5, 'A-Law': 6}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
def _get_pyo_codes(fmt='', dtype='int16', file_out=''):
|
|
170
|
-
"""Convert file and data formats to int codes, e.g., wav int16 -> (0, 0).
|
|
171
|
-
"""
|
|
172
|
-
|
|
173
|
-
if not fmt:
|
|
174
|
-
dot_ext = os.path.splitext(file_out)[1]
|
|
175
|
-
fmt = dot_ext.lower().strip('.')
|
|
176
|
-
if fmt in pyo_formats:
|
|
177
|
-
file_fmt = pyo_formats[fmt]
|
|
178
|
-
else:
|
|
179
|
-
msg = 'format `{0}` not supported'.format(file_out)
|
|
180
|
-
raise PyoFormatException(msg)
|
|
181
|
-
|
|
182
|
-
if fmt in ['sd2', 'flac']:
|
|
183
|
-
ok_dfmt = {'int16': 0, 'int24': 1}
|
|
184
|
-
else:
|
|
185
|
-
ok_dfmt = pyo_dtype
|
|
186
|
-
|
|
187
|
-
if dtype in ok_dfmt:
|
|
188
|
-
data_fmt = pyo_dtype[dtype]
|
|
189
|
-
else:
|
|
190
|
-
msg = 'data format `{0}` not supported for `{1}`'.format(
|
|
191
|
-
dtype, file_out)
|
|
192
|
-
raise PyoFormatException(msg)
|
|
193
|
-
return file_fmt, data_fmt
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def samples_from_table(table, start=0, stop=-1, rate=44100):
|
|
197
|
-
"""Return samples as a np.array read from a pyo table.
|
|
198
|
-
|
|
199
|
-
A (start, stop) selection in seconds may require a non-default rate.
|
|
200
|
-
"""
|
|
201
|
-
samples = np.array(table.getTable())
|
|
202
|
-
if (start, stop) != (0, -1):
|
|
203
|
-
if stop > start:
|
|
204
|
-
samples = samples[start * rate:stop * rate]
|
|
205
|
-
elif start:
|
|
206
|
-
samples = samples[start * rate:]
|
|
207
|
-
return samples
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
def table_from_samples(samples, start=0, stop=-1, rate=44100):
|
|
211
|
-
"""Return a pyo DataTable constructed from samples.
|
|
212
|
-
|
|
213
|
-
A (start, stop) selection in seconds may require a non-default rate.
|
|
214
|
-
"""
|
|
215
|
-
if type(samples) == np.ndarray:
|
|
216
|
-
samples = samples.tolist()
|
|
217
|
-
if type(samples) != list:
|
|
218
|
-
raise TypeError('samples should be a list or np.array')
|
|
219
|
-
if (start, stop) != (0, -1):
|
|
220
|
-
if stop > start:
|
|
221
|
-
samples = samples[start * rate:stop * rate]
|
|
222
|
-
elif start:
|
|
223
|
-
samples = samples[start * rate:]
|
|
224
|
-
table = pyo.DataTable(size=len(samples), init=samples)
|
|
225
|
-
return table
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def table_from_file(file_in, start=0, stop=-1):
|
|
229
|
-
"""Read data from files, any pyo format, returns (rate, pyo SndTable)
|
|
230
|
-
"""
|
|
231
|
-
table = pyo.SndTable()
|
|
232
|
-
try:
|
|
233
|
-
table.setSound(file_in, start=start, stop=stop)
|
|
234
|
-
except TypeError:
|
|
235
|
-
msg = 'bad file `{0}`, or format not supported'.format(file_in)
|
|
236
|
-
raise PyoFormatException(msg)
|
|
237
|
-
rate = pyo.sndinfo(file_in)[2]
|
|
238
|
-
return rate, table
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
def samples_from_file(file_in, start=0, stop=-1):
|
|
242
|
-
"""Read data from files, returns tuple (rate, np.array(.float64))
|
|
243
|
-
"""
|
|
244
|
-
if not os.path.isfile(file_in):
|
|
245
|
-
raise IOError('no such file `{0}`'.format(file_in))
|
|
246
|
-
rate, table = table_from_file(file_in, start=start, stop=stop)
|
|
247
|
-
return rate, np.array(table.getTable())
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def samples_to_file(samples, rate, file_out, fmt='', dtype='int16'):
|
|
251
|
-
"""Write data to file, using requested format or infer from file .ext.
|
|
252
|
-
|
|
253
|
-
Only integer `rate` values are supported.
|
|
254
|
-
|
|
255
|
-
See http://ajaxsoundstudio.com/pyodoc/api/functions/sndfile.html
|
|
256
|
-
|
|
257
|
-
"""
|
|
258
|
-
file_fmt, data_fmt = _get_pyo_codes(fmt, dtype, file_out)
|
|
259
|
-
if type(samples) == np.ndarray:
|
|
260
|
-
samples = samples.tolist()
|
|
261
|
-
if type(samples) != list:
|
|
262
|
-
raise TypeError('samples should be a list or np.array')
|
|
263
|
-
try:
|
|
264
|
-
pyo.savefile(samples, path=file_out, sr=int(rate), channels=1,
|
|
265
|
-
fileformat=file_fmt, sampletype=data_fmt)
|
|
266
|
-
except Exception:
|
|
267
|
-
msg = 'could not save `{0}`; permissions or other issue?'
|
|
268
|
-
raise IOError(msg.format(file_out))
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def table_to_file(table, file_out, fmt='', dtype='int16'):
|
|
272
|
-
"""Write data to file, using requested format or infer from file .ext.
|
|
273
|
-
"""
|
|
274
|
-
file_fmt, data_fmt = _get_pyo_codes(fmt, dtype, file_out)
|
|
275
|
-
try:
|
|
276
|
-
pyo.savefileFromTable(table=table, path=file_out,
|
|
277
|
-
fileformat=file_fmt, sampletype=data_fmt)
|
|
278
|
-
except Exception:
|
|
279
|
-
msg = 'could not save `{0}`; permissions or other issue?'
|
|
280
|
-
raise IOError(msg.format(file_out))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: psychopy
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.2.1
|
|
4
4
|
Summary: PsychoPy provides easy, precise, flexible experiments in behavioural sciences
|
|
5
5
|
Author-Email: Open Science Tools Ltd <support@opensciencetools.org>
|
|
6
6
|
Maintainer-Email: Open Science Tools Ltd <support@opensciencetools.org>
|
|
@@ -12,13 +12,14 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.8
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
16
|
Classifier: Topic :: Scientific/Engineering
|
|
16
17
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
17
18
|
Project-URL: Homepage, https://www.psychopy.org/
|
|
18
19
|
Project-URL: Download, https://github.com/psychopy/psychopy/releases/
|
|
19
|
-
Requires-Python: <3.
|
|
20
|
+
Requires-Python: <3.12,>=3.9
|
|
20
21
|
Requires-Dist: numpy
|
|
21
|
-
Requires-Dist: scipy
|
|
22
|
+
Requires-Dist: scipy<1.15
|
|
22
23
|
Requires-Dist: matplotlib
|
|
23
24
|
Requires-Dist: pyglet==1.4.11; platform_system == "Windows"
|
|
24
25
|
Requires-Dist: pyglet==1.5.27; platform_system != "Windows"
|
|
@@ -33,7 +34,9 @@ Requires-Dist: imageio
|
|
|
33
34
|
Requires-Dist: imageio-ffmpeg
|
|
34
35
|
Requires-Dist: psychtoolbox<3.0.20; platform_machine != "arm64"
|
|
35
36
|
Requires-Dist: pywinhook; platform_system == "Windows"
|
|
36
|
-
Requires-Dist:
|
|
37
|
+
Requires-Dist: zope.event==5.0
|
|
38
|
+
Requires-Dist: zope.interface==7.2
|
|
39
|
+
Requires-Dist: gevent==25.5.1
|
|
37
40
|
Requires-Dist: MeshPy
|
|
38
41
|
Requires-Dist: psutil
|
|
39
42
|
Requires-Dist: pyzmq>=22.2.1
|
|
@@ -44,7 +47,6 @@ Requires-Dist: pyyaml
|
|
|
44
47
|
Requires-Dist: freetype-py
|
|
45
48
|
Requires-Dist: python-bidi
|
|
46
49
|
Requires-Dist: arabic-reshaper
|
|
47
|
-
Requires-Dist: javascripthon
|
|
48
50
|
Requires-Dist: websockets
|
|
49
51
|
Requires-Dist: wxPython>=4.1.1
|
|
50
52
|
Requires-Dist: markdown-it-py
|
|
@@ -54,7 +56,6 @@ Requires-Dist: setuptools==70.3.0
|
|
|
54
56
|
Requires-Dist: python-gitlab
|
|
55
57
|
Requires-Dist: gitpython
|
|
56
58
|
Requires-Dist: cryptography
|
|
57
|
-
Requires-Dist: javascripthon>=0.12
|
|
58
59
|
Requires-Dist: astunparse
|
|
59
60
|
Requires-Dist: esprima
|
|
60
61
|
Requires-Dist: jedi>=0.16
|
|
@@ -65,9 +66,10 @@ Requires-Dist: opencv-python
|
|
|
65
66
|
Requires-Dist: python-vlc==3.0.11115; platform_system == "Windows"
|
|
66
67
|
Requires-Dist: python-vlc>=3.0.12118; platform_system != "Windows"
|
|
67
68
|
Requires-Dist: pypiwin32; platform_system == "Windows"
|
|
68
|
-
Requires-Dist: pyobjc-core
|
|
69
|
-
Requires-Dist: pyobjc-framework-Quartz
|
|
70
|
-
Requires-Dist: pyobjc
|
|
69
|
+
Requires-Dist: pyobjc-core>8.0; platform_system == "Darwin"
|
|
70
|
+
Requires-Dist: pyobjc-framework-Quartz>8.0; platform_system == "Darwin"
|
|
71
|
+
Requires-Dist: pyobjc>8.0; platform_system == "Darwin"
|
|
72
|
+
Requires-Dist: pyobjc-framework-ScriptingBridge>8.0; platform_system == "Darwin"
|
|
71
73
|
Requires-Dist: zeroconf; platform_system == "Darwin"
|
|
72
74
|
Requires-Dist: python-xlib; platform_system == "Linux"
|
|
73
75
|
Requires-Dist: distro; platform_system == "Linux"
|
|
@@ -75,6 +77,7 @@ Requires-Dist: tables!=3.9.2
|
|
|
75
77
|
Requires-Dist: packaging>=24.0
|
|
76
78
|
Requires-Dist: moviepy
|
|
77
79
|
Requires-Dist: pyarrow
|
|
80
|
+
Requires-Dist: beautifulsoup4
|
|
78
81
|
Provides-Extra: tests
|
|
79
82
|
Requires-Dist: pytest>=6.2.5; extra == "tests"
|
|
80
83
|
Requires-Dist: pytest-codecov; extra == "tests"
|
|
@@ -84,19 +87,22 @@ Requires-Dist: flake8; extra == "tests"
|
|
|
84
87
|
Requires-Dist: xmlschema; extra == "tests"
|
|
85
88
|
Provides-Extra: docs
|
|
86
89
|
Requires-Dist: sphinx; extra == "docs"
|
|
90
|
+
Requires-Dist: jinja2; extra == "docs"
|
|
87
91
|
Requires-Dist: sphinx-design; extra == "docs"
|
|
88
92
|
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
89
|
-
Requires-Dist:
|
|
93
|
+
Requires-Dist: myst-parser; extra == "docs"
|
|
94
|
+
Requires-Dist: sphinxcontrib.svg2pdfconverter; extra == "docs"
|
|
90
95
|
Requires-Dist: psychopy-sphinx-theme; extra == "docs"
|
|
91
96
|
Provides-Extra: building
|
|
92
97
|
Requires-Dist: bdist-mpkg>=0.5.0; platform_system == "Darwin" and extra == "building"
|
|
93
98
|
Requires-Dist: py2app; platform_system == "Darwin" and extra == "building"
|
|
94
99
|
Requires-Dist: dmgbuild; platform_system == "Darwin" and extra == "building"
|
|
100
|
+
Requires-Dist: polib; extra == "building"
|
|
95
101
|
Provides-Extra: suggested
|
|
96
102
|
Requires-Dist: sounddevice; extra == "suggested"
|
|
97
103
|
Requires-Dist: pylsl>=1.16.1; extra == "suggested"
|
|
98
104
|
Requires-Dist: xlwt; extra == "suggested"
|
|
99
|
-
Requires-Dist: h5py; extra == "suggested"
|
|
105
|
+
Requires-Dist: h5py<3.15.0; extra == "suggested"
|
|
100
106
|
Requires-Dist: tobii_research; extra == "suggested"
|
|
101
107
|
Requires-Dist: badapted>=0.0.3; extra == "suggested"
|
|
102
108
|
Requires-Dist: egi-pynetstation>=1.0.0; extra == "suggested"
|