psychopy 2024.1.4__py3-none-any.whl → 2024.2.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/.DS_Store +0 -0
- psychopy/CHANGELOG.txt +206 -0
- psychopy/GIT_SHA +1 -0
- psychopy/VERSION +1 -0
- psychopy/__init__.py +77 -15
- psychopy/app/Resources/classic/plugin16.png +0 -0
- psychopy/app/Resources/classic/plugin16@2x.png +0 -0
- psychopy/app/Resources/dark/plugin16.png +0 -0
- psychopy/app/Resources/dark/plugin16@2x.png +0 -0
- psychopy/app/Resources/light/plugin16.png +0 -0
- psychopy/app/Resources/light/plugin16@2x.png +0 -0
- psychopy/app/__init__.py +76 -2
- psychopy/app/_psychopyApp.py +126 -101
- psychopy/app/builder/builder.py +14 -10
- psychopy/app/builder/dialogs/__init__.py +8 -8
- psychopy/app/builder/dialogs/dlgsConditions.py +12 -13
- psychopy/app/builder/dialogs/paramCtrls.py +24 -57
- psychopy/app/builder/validators.py +2 -2
- psychopy/app/coder/codeEditorBase.py +8 -8
- psychopy/app/coder/coder.py +4 -4
- psychopy/app/connections/sendusage.py +2 -2
- psychopy/app/connections/updates.py +9 -9
- psychopy/app/dialogs.py +34 -2
- psychopy/app/idle.py +31 -0
- psychopy/app/jobs.py +21 -3
- psychopy/app/linuxconfig/__init__.py +9 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +4602 -2540
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +56 -54
- psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +53 -43
- psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_US/LC_MESSAGE/messages.po +56 -54
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +1011 -942
- psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +9415 -5
- psychopy/app/pavlovia_ui/_base.py +33 -3
- psychopy/app/pavlovia_ui/search.py +0 -1
- psychopy/app/plugin_manager/dialog.py +104 -51
- psychopy/app/plugin_manager/packages.py +5 -0
- psychopy/app/plugin_manager/plugins.py +145 -67
- psychopy/app/preferencesDlg.py +8 -8
- psychopy/app/psychopyApp.py +11 -5
- psychopy/app/ribbon.py +124 -14
- psychopy/app/runner/runner.py +6 -1
- psychopy/app/stdout/stdOutRich.py +27 -11
- psychopy/app/themes/icons.py +52 -2
- psychopy/assets/__init__.py +0 -0
- psychopy/assets/click.png +0 -0
- psychopy/assets/clicknext.png +0 -0
- psychopy/assets/next.png +0 -0
- psychopy/assets/psychopy.ico +0 -0
- psychopy/assets/psychopy.png +0 -0
- psychopy/assets/templates/__init__.py +0 -0
- psychopy/assets/touch.png +0 -0
- psychopy/assets/touchnext.png +0 -0
- psychopy/assets/window.ico +0 -0
- psychopy/changes/2023.1.0.md +9 -0
- psychopy/changes/2024.1.0.md +16 -0
- psychopy/changes/__init__.py +0 -0
- psychopy/clock.py +2 -2
- psychopy/colors.py +2 -1
- psychopy/compatibility.py +53 -1
- psychopy/contrib/.DS_Store +0 -0
- psychopy/contrib/configobj/__init__.py +10 -8
- psychopy/data/__init__.py +3 -2
- psychopy/data/base.py +5 -5
- psychopy/data/experiment.py +130 -4
- psychopy/data/routine.py +56 -0
- psychopy/data/staircase.py +2 -2
- psychopy/data/trial.py +559 -97
- psychopy/data/utils.py +56 -21
- psychopy/demos/.DS_Store +0 -0
- psychopy/demos/builder/.DS_Store +0 -0
- psychopy/demos/builder/Design Templates/.DS_Store +0 -0
- psychopy/demos/builder/Experiments/.DS_Store +0 -0
- psychopy/demos/builder/Feature Demos/.DS_Store +0 -0
- psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +375 -0
- psychopy/demos/builder/Feature Demos/buttonBox/readme.md +5 -0
- psychopy/demos/builder/Feature Demos/pilotMode/pilotMode.psyexp +433 -0
- psychopy/demos/builder/Feature Demos/pilotMode/readme.md +7 -0
- psychopy/demos/builder/Hardware/.DS_Store +0 -0
- psychopy/demos/builder/Helper Tools/.DS_Store +0 -0
- psychopy/demos/coder/.DS_Store +0 -0
- psychopy/demos/coder/hardware/testSoundLatency.py +2 -2
- psychopy/demos/coder/iohub/.DS_Store +0 -0
- psychopy/demos/coder/misc/hdf5_2_csv +33 -0
- psychopy/event.py +30 -29
- psychopy/experiment/.DS_Store +0 -0
- psychopy/experiment/_experiment.py +6 -6
- psychopy/experiment/components/.DS_Store +0 -0
- psychopy/experiment/components/__init__.py +6 -3
- psychopy/experiment/components/_base.py +286 -131
- psychopy/experiment/components/aperture/.DS_Store +0 -0
- psychopy/experiment/components/brush/.DS_Store +0 -0
- psychopy/experiment/components/button/.DS_Store +0 -0
- psychopy/experiment/components/button/__init__.py +5 -1
- psychopy/experiment/components/buttonBox/.DS_Store +0 -0
- psychopy/experiment/components/camera/.DS_Store +0 -0
- psychopy/experiment/components/code/.DS_Store +0 -0
- psychopy/experiment/components/dots/.DS_Store +0 -0
- psychopy/experiment/components/eyetracker_record/.DS_Store +0 -0
- psychopy/experiment/components/eyetracker_record/__init__.py +92 -30
- psychopy/experiment/components/form/.DS_Store +0 -0
- psychopy/experiment/components/form/__init__.py +6 -2
- psychopy/experiment/components/grating/.DS_Store +0 -0
- psychopy/experiment/components/grating/__init__.py +14 -3
- psychopy/experiment/components/image/.DS_Store +0 -0
- psychopy/experiment/components/image/__init__.py +14 -3
- psychopy/experiment/components/joyButtons/.DS_Store +0 -0
- psychopy/experiment/components/joystick/.DS_Store +0 -0
- psychopy/experiment/components/keyboard/.DS_Store +0 -0
- psychopy/experiment/components/keyboard/__init__.py +22 -10
- psychopy/experiment/components/microphone/.DS_Store +0 -0
- psychopy/experiment/components/microphone/__init__.py +59 -39
- psychopy/experiment/components/mouse/.DS_Store +0 -0
- psychopy/experiment/components/mouse/__init__.py +44 -29
- psychopy/experiment/components/movie/.DS_Store +0 -0
- psychopy/experiment/components/movie/__init__.py +1 -1
- psychopy/experiment/components/panorama/.DS_Store +0 -0
- psychopy/experiment/components/parallelOut/.DS_Store +0 -0
- psychopy/experiment/components/patch/.DS_Store +0 -0
- psychopy/experiment/components/polygon/.DS_Store +0 -0
- psychopy/experiment/components/polygon/__init__.py +26 -6
- psychopy/experiment/components/progress/.DS_Store +0 -0
- psychopy/experiment/components/ratingScale/.DS_Store +0 -0
- psychopy/experiment/components/resourceManager/.DS_Store +0 -0
- psychopy/experiment/components/roi/.DS_Store +0 -0
- psychopy/experiment/components/roi/__init__.py +5 -0
- psychopy/experiment/components/routineSettings/.DS_Store +0 -0
- psychopy/experiment/components/routineSettings/__init__.py +57 -10
- psychopy/experiment/components/serialOut/.DS_Store +0 -0
- psychopy/experiment/components/settings/.DS_Store +0 -0
- psychopy/experiment/components/settings/__init__.py +117 -42
- psychopy/experiment/components/slider/.DS_Store +0 -0
- psychopy/experiment/components/sound/.DS_Store +0 -0
- psychopy/experiment/components/sound/__init__.py +54 -19
- psychopy/experiment/components/static/.DS_Store +0 -0
- psychopy/experiment/components/static/__init__.py +1 -1
- psychopy/experiment/components/text/.DS_Store +0 -0
- psychopy/experiment/components/text/__init__.py +28 -3
- psychopy/experiment/components/textbox/.DS_Store +0 -0
- psychopy/experiment/components/textbox/__init__.py +12 -2
- psychopy/experiment/components/unknown/.DS_Store +0 -0
- psychopy/experiment/components/unknown/__init__.py +1 -2
- psychopy/experiment/components/unknownPlugin/.DS_Store +0 -0
- psychopy/experiment/components/unknownPlugin/__init__.py +2 -2
- psychopy/experiment/components/variable/.DS_Store +0 -0
- psychopy/experiment/flow.py +11 -4
- psychopy/experiment/loops.py +85 -37
- psychopy/experiment/params.py +74 -32
- psychopy/experiment/py2js_transpiler.py +8 -1
- psychopy/experiment/routines/.DS_Store +0 -0
- psychopy/experiment/routines/_base.py +102 -22
- psychopy/experiment/routines/counterbalance/.DS_Store +0 -0
- psychopy/experiment/routines/counterbalance/__init__.py +5 -1
- psychopy/experiment/routines/eyetracker_calibrate/.DS_Store +0 -0
- psychopy/experiment/routines/eyetracker_validate/.DS_Store +0 -0
- psychopy/experiment/routines/pavlovia_survey/.DS_Store +0 -0
- psychopy/experiment/routines/photodiodeValidator/.DS_Store +0 -0
- psychopy/experiment/routines/photodiodeValidator/__init__.py +6 -5
- psychopy/experiment/routines/unknown/.DS_Store +0 -0
- psychopy/gui/wxgui.py +4 -4
- psychopy/hardware/.DS_Store +0 -0
- psychopy/hardware/__init__.py +1 -1
- psychopy/hardware/base.py +12 -0
- psychopy/hardware/camera/__init__.py +1 -15
- psychopy/hardware/cedrus.py +10 -11
- psychopy/hardware/crs/colorcal.py +13 -22
- psychopy/hardware/crs/optical.py +10 -20
- psychopy/hardware/emulator.py +17 -14
- psychopy/hardware/eyetracker.py +42 -118
- psychopy/hardware/gammasci.py +4 -15
- psychopy/hardware/keyboard.py +102 -10
- psychopy/hardware/listener.py +3 -0
- psychopy/hardware/microphone.py +148 -18
- psychopy/hardware/minolta.py +8 -15
- psychopy/hardware/photodiode.py +191 -16
- psychopy/hardware/photometer/__init__.py +11 -19
- psychopy/hardware/pr.py +8 -15
- psychopy/hardware/speaker.py +39 -4
- psychopy/info.py +0 -71
- psychopy/iohub/.DS_Store +0 -0
- psychopy/iohub/__init__.py +1 -1
- psychopy/iohub/client/__init__.py +30 -20
- psychopy/iohub/client/keyboard.py +24 -24
- psychopy/iohub/datastore/__init__.py +2 -2
- psychopy/iohub/datastore/util.py +2 -2
- psychopy/iohub/default_config.yaml +1 -1
- psychopy/iohub/devices/.DS_Store +0 -0
- psychopy/iohub/devices/__init__.py +112 -25
- psychopy/iohub/devices/deviceConfigValidation.py +2 -1
- psychopy/iohub/devices/experiment/default_experiment.yaml +12 -1
- psychopy/iohub/devices/experiment/supported_config_settings.yaml +5 -1
- psychopy/iohub/devices/eyetracker/.DS_Store +0 -0
- psychopy/iohub/devices/eyetracker/__init__.py +46 -0
- psychopy/iohub/devices/eyetracker/calibration/procedure.py +2 -2
- psychopy/iohub/devices/eyetracker/hw/gazepoint/__init__.py +14 -2
- psychopy/iohub/devices/eyetracker/hw/mouse/eyetracker.py +3 -4
- psychopy/iohub/server.py +2 -2
- psychopy/iohub/start_iohub_process.py +3 -0
- psychopy/iohub/util/__init__.py +62 -70
- psychopy/layout.py +5 -5
- psychopy/logging.py +8 -1
- psychopy/microphone.py +10 -37
- psychopy/platform_specific/__init__.py +0 -2
- psychopy/platform_specific/darwin.py +1 -3
- psychopy/platform_specific/linux.py +31 -33
- psychopy/platform_specific/win32.py +38 -13
- psychopy/plugins/__init__.py +148 -116
- psychopy/plugins/util.py +39 -0
- psychopy/preferences/Darwin.spec +4 -2
- psychopy/preferences/FreeBSD.spec +4 -2
- psychopy/preferences/Linux.spec +4 -2
- psychopy/preferences/Windows.spec +4 -2
- psychopy/preferences/baseNoArch.spec +4 -2
- psychopy/preferences/preferences.py +47 -24
- psychopy/projects/pavlovia.py +47 -4
- psychopy/scripts/psyexpCompile.py +0 -4
- psychopy/session.py +153 -21
- psychopy/sound/__init__.py +31 -21
- psychopy/sound/_base.py +20 -3
- psychopy/sound/audioclip.py +320 -33
- psychopy/sound/backend_ptb.py +47 -58
- psychopy/sound/backend_pygame.py +1 -1
- psychopy/sound/backend_pysound.py +6 -15
- psychopy/sound/transcribe.py +53 -0
- psychopy/tests/.DS_Store +0 -0
- psychopy/tests/data/.DS_Store +0 -0
- psychopy/tests/data/TestUnknownPluginComponent_load_resave.psyexp +135 -0
- psychopy/tests/data/Test_textbox/test_ori_0_bottom right.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_0_center.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_0_top left.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_120_bottom right.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_120_center.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_120_top left.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_180_bottom right.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_180_center.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_180_top left.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_240_bottom right.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_240_center.png +0 -0
- psychopy/tests/data/Test_textbox/test_ori_240_top left.png +0 -0
- psychopy/tests/data/correctScript/.DS_Store +0 -0
- psychopy/tests/data/test_components/testClearKeyboard/testClearKeyboard.psyexp +200 -0
- psychopy/tests/data/test_session/.DS_Store +0 -0
- psychopy/tests/data/test_session/root/testFutureTrials/testFutureTrials.psyexp +155 -0
- psychopy/tests/data/test_session/root/testTrialNav/trialNav.psyexp +158 -0
- psychopy/tests/test_app/.DS_Store +0 -0
- psychopy/tests/test_app/conftest.py +2 -2
- psychopy/tests/test_app/test_speed.py +4 -1
- psychopy/tests/test_data/test_TrialHandler2.py +146 -1
- psychopy/tests/test_experiment/.DS_Store +0 -0
- psychopy/tests/test_experiment/needs_wx/genComponsTemplate.py +3 -3
- psychopy/tests/test_experiment/needs_wx/test_components.py +2 -2
- psychopy/tests/test_experiment/test_components/test_KeyboardComponent.py +28 -0
- psychopy/tests/test_experiment/test_components/test_UnknownPluginComponent.py +27 -0
- psychopy/tests/test_experiment/test_components/test_base_components.py +58 -0
- psychopy/tests/test_experiment/test_py2js.py +1 -1
- psychopy/tests/test_hardware/test_keyboard.py +31 -0
- psychopy/tests/test_hardware/test_ports.py +1 -11
- psychopy/tests/test_liaison/test_Liaison.py +47 -0
- psychopy/tests/test_misc/test_core.py +5 -0
- psychopy/tests/test_session/test_Session.py +5 -1
- psychopy/tests/test_tools/test_versionchooser.py +39 -8
- psychopy/tests/test_visual/test_all_stimuli.py +0 -97
- psychopy/tests/test_visual/test_image.py +6 -5
- psychopy/tests/test_visual/test_textbox.py +36 -0
- psychopy/tests/utils.py +4 -0
- psychopy/tools/filetools.py +1 -1
- psychopy/tools/pkgtools.py +160 -137
- psychopy/tools/versionchooser.py +10 -10
- psychopy/tools/wizard.py +3 -3
- psychopy/visual/.DS_Store +0 -0
- psychopy/visual/backends/pygletbackend.py +24 -13
- psychopy/visual/basevisual.py +5 -11
- psychopy/visual/button.py +2 -14
- psychopy/visual/helpers.py +5 -5
- psychopy/visual/line.py +1 -2
- psychopy/visual/movie2.py +7 -816
- psychopy/visual/movie3.py +7 -589
- psychopy/visual/movies/__init__.py +8 -11
- psychopy/visual/movies/frame.py +5 -2
- psychopy/visual/movies/players/ffpyplayer_player.py +5 -2
- psychopy/visual/noise.py +8 -7
- psychopy/visual/patch.py +7 -16
- psychopy/visual/radial.py +9 -7
- psychopy/visual/ratingscale.py +8 -1415
- psychopy/visual/secondorder.py +10 -9
- psychopy/visual/shape.py +7 -2
- psychopy/visual/text.py +1 -1
- psychopy/visual/textbox2/textbox2.py +28 -5
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/METADATA +8 -13
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/RECORD +307 -213
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/WHEEL +1 -1
- psychopy/app/Resources/click.png +0 -0
- psychopy/app/Resources/next.png +0 -0
- psychopy/experiment/components/patch/__init__.py +0 -121
- psychopy/experiment/components/patch/classic/patch.png +0 -0
- psychopy/experiment/components/patch/dark/patch.png +0 -0
- psychopy/experiment/components/patch/dark/patch@2x.png +0 -0
- psychopy/experiment/components/patch/light/patch.png +0 -0
- psychopy/experiment/components/patch/light/patch@2x.png +0 -0
- psychopy/experiment/components/ratingScale/__init__.py +0 -337
- psychopy/experiment/components/ratingScale/classic/ratingscale.png +0 -0
- psychopy/experiment/components/ratingScale/classic/ratingscale@2x.png +0 -0
- psychopy/experiment/components/ratingScale/dark/ratingScale@2x.png +0 -0
- psychopy/experiment/components/ratingScale/dark/ratingscale.png +0 -0
- psychopy/experiment/components/ratingScale/light/ratingScale@2x.png +0 -0
- psychopy/experiment/components/ratingScale/light/ratingscale.png +0 -0
- psychopy/platform_specific/posix.py +0 -16
- psychopy/tests/test_sound/test_microphone.py +0 -217
- psychopy/tests/test_visual/test_ratingScale.py +0 -299
- /psychopy/{app/Resources → assets}/Psychopy Window Favicon@16w.png +0 -0
- /psychopy/{app/Resources → assets}/Psychopy Window Favicon@32w.png +0 -0
- /psychopy/{app/Resources → assets}/USB-C.png +0 -0
- /psychopy/{app/Resources → assets}/USB.png +0 -0
- /psychopy/{app/Resources → assets}/creditCard.png +0 -0
- /psychopy/{app/Resources → assets}/default.mp3 +0 -0
- /psychopy/{app/Resources → assets}/default.mp4 +0 -0
- /psychopy/{app/Resources → assets}/default.png +0 -0
- /psychopy/{app/Resources → assets/templates}/instruct1.png +0 -0
- /psychopy/{app/Resources → assets/templates}/instruct2.png +0 -0
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/entry_points.txt +0 -0
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/licenses/AUTHORS.md +0 -0
- {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -178,7 +178,9 @@ class ButtonComponent(BaseVisualComponent):
|
|
|
178
178
|
"text=%(text)s, font=%(font)s,\n"
|
|
179
179
|
"pos=%(pos)s," + unitsStr + "\n"
|
|
180
180
|
"letterHeight=%(letterHeight)s,\n"
|
|
181
|
-
"size=%(size)s,
|
|
181
|
+
"size=%(size)s, \n"
|
|
182
|
+
"ori=%(ori)s\n,"
|
|
183
|
+
"borderWidth=%(borderWidth)s,\n"
|
|
182
184
|
"fillColor=%(fillColor)s, borderColor=%(borderColor)s,\n"
|
|
183
185
|
"color=%(color)s, colorSpace=%(colorSpace)s,\n"
|
|
184
186
|
"opacity=%(opacity)s,\n"
|
|
@@ -216,6 +218,7 @@ class ButtonComponent(BaseVisualComponent):
|
|
|
216
218
|
"pos: %(pos)s,\n"
|
|
217
219
|
"letterHeight: %(letterHeight)s,\n"
|
|
218
220
|
"size: %(size)s,\n"
|
|
221
|
+
"ori: %(ori)s\n,\n"
|
|
219
222
|
"depth: %(depth)s\n"
|
|
220
223
|
)
|
|
221
224
|
buff.writeIndentedLines(code % inits)
|
|
@@ -272,6 +275,7 @@ class ButtonComponent(BaseVisualComponent):
|
|
|
272
275
|
indented = self.writeStartTestCode(buff)
|
|
273
276
|
if indented:
|
|
274
277
|
code = (
|
|
278
|
+
"win.callOnFlip(%(name)s.buttonClock.reset)\n"
|
|
275
279
|
"%(name)s.setAutoDraw(True)\n"
|
|
276
280
|
)
|
|
277
281
|
buff.writeIndentedLines(code % self.params)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -28,7 +28,8 @@ class EyetrackerRecordComponent(BaseComponent):
|
|
|
28
28
|
stopType='duration (s)', stopVal=1.0,
|
|
29
29
|
startEstim='', durationEstim='',
|
|
30
30
|
actionType="Start and Stop",
|
|
31
|
-
|
|
31
|
+
stopWithRoutine=False,
|
|
32
|
+
# legacy
|
|
32
33
|
save='final', configFile='myTracker.yaml'):
|
|
33
34
|
BaseComponent.__init__(self, exp, parentName, name=name,
|
|
34
35
|
startType=startType, startVal=startVal,
|
|
@@ -38,7 +39,8 @@ class EyetrackerRecordComponent(BaseComponent):
|
|
|
38
39
|
self.url = "https://www.psychopy.org/builder/components/eyetracker.html"
|
|
39
40
|
self.exp.requirePsychopyLibs(['iohub', 'hardware'])
|
|
40
41
|
|
|
41
|
-
self.params['actionType'] = Param(
|
|
42
|
+
self.params['actionType'] = Param(
|
|
43
|
+
actionType,
|
|
42
44
|
valType='str', inputType='choice', categ='Basic',
|
|
43
45
|
allowedVals=["Start and Stop", "Start Only", "Stop Only"],
|
|
44
46
|
hint=_translate("Should this Component start and / or stop eye tracker recording?"),
|
|
@@ -63,11 +65,50 @@ class EyetrackerRecordComponent(BaseComponent):
|
|
|
63
65
|
}
|
|
64
66
|
)
|
|
65
67
|
|
|
68
|
+
self.params['stopWithRoutine'] = Param(
|
|
69
|
+
stopWithRoutine,
|
|
70
|
+
valType='bool', inputType="bool", updates='constant', categ='Basic',
|
|
71
|
+
hint=_translate(
|
|
72
|
+
"Should eyetracking stop when the Routine ends? Tick to force stopping "
|
|
73
|
+
"after the Routine has finished."),
|
|
74
|
+
label=_translate('Stop with Routine?'))
|
|
75
|
+
|
|
76
|
+
self.depends.append(
|
|
77
|
+
{
|
|
78
|
+
"dependsOn": "actionType", # must be param name
|
|
79
|
+
"condition": "in ('Start and Stop', 'Stop Only')", # val to check for
|
|
80
|
+
"param": "stopWithRoutine", # param property to alter
|
|
81
|
+
"true": "show", # what to do with param if condition is True
|
|
82
|
+
"false": "hide", # permitted: hide, show, enable, disable
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
|
|
66
86
|
# TODO: Display actionType control after component name.
|
|
67
87
|
# Currently, adding params before start / stop time
|
|
68
88
|
# in .order has no effect
|
|
69
89
|
self.order = self.order[:1]+['actionType']+self.order[1:]
|
|
70
90
|
|
|
91
|
+
def getStartAndDuration(self):
|
|
92
|
+
""" Due to the different action types hiding either the start or stop
|
|
93
|
+
field parameters, we need to force the start and stop criteria to correct
|
|
94
|
+
types and values, make sure the component is displayed accurately on the
|
|
95
|
+
timeline reflecting the status of EyetrackerRecordComponent instead of
|
|
96
|
+
the eyetracker device, and ensure proper nonSlip timing determination
|
|
97
|
+
"""
|
|
98
|
+
# make a copy of params so we can change stuff harmlessly
|
|
99
|
+
params = self.params.copy()
|
|
100
|
+
# check if the actionType is 'Start Only' or 'Stop Only'
|
|
101
|
+
if params['actionType'].val == 'Start Only':
|
|
102
|
+
# if only starting, pretend stop is 0
|
|
103
|
+
params['stopType'].val = 'duration (s)'
|
|
104
|
+
params['stopVal'].val = 0.0
|
|
105
|
+
elif params['actionType'].val == 'Stop Only':
|
|
106
|
+
# if only stopping, pretend start was 0
|
|
107
|
+
params['startType'].val = 'time (s)'
|
|
108
|
+
params['startVal'].val = 0.0
|
|
109
|
+
|
|
110
|
+
return super().getStartAndDuration(params)
|
|
111
|
+
|
|
71
112
|
def writeInitCode(self, buff):
|
|
72
113
|
inits = self.params
|
|
73
114
|
# Make a controller object
|
|
@@ -94,35 +135,56 @@ class EyetrackerRecordComponent(BaseComponent):
|
|
|
94
135
|
if self.exp.eyetracking == "None":
|
|
95
136
|
alert(code=4505)
|
|
96
137
|
|
|
97
|
-
|
|
138
|
+
buff.writeIndented("\n")
|
|
98
139
|
buff.writeIndentedLines("# *%s* updates\n" % self.params['name'])
|
|
99
140
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
if "start" in self.params['actionType'].val.lower():
|
|
142
|
+
# if this Component can start recording, write start test code
|
|
143
|
+
indented = self.writeStartTestCode(buff)
|
|
144
|
+
# write code to start
|
|
145
|
+
code = (
|
|
146
|
+
"%(name)s.start()\n"
|
|
147
|
+
)
|
|
148
|
+
buff.writeIndentedLines(code % self.params)
|
|
149
|
+
# dedent
|
|
150
|
+
buff.setIndentLevel(-indented, relative=True)
|
|
151
|
+
else:
|
|
152
|
+
# if this Component can't start recording, make sure it reads as already started
|
|
153
|
+
code = (
|
|
154
|
+
"if %(name)s.status == NOT_STARTED:\n"
|
|
155
|
+
" %(name)s.frameNStart = frameN # exact frame index\n"
|
|
156
|
+
" %(name)s.tStart = t # local t and not account for scr refresh\n"
|
|
157
|
+
" %(name)s.tStartRefresh = tThisFlipGlobal # on global time\n"
|
|
158
|
+
" win.timeOnFlip(%(name)s, 'tStartRefresh') # time at next scr refresh\n"
|
|
159
|
+
" %(name)s.status = STARTED\n"
|
|
160
|
+
)
|
|
161
|
+
buff.writeIndentedLines(code % self.params)
|
|
162
|
+
|
|
163
|
+
if "stop" in self.params['actionType'].val.lower():
|
|
164
|
+
# if this Component can stop recording, write stop test code
|
|
165
|
+
indented = self.writeStopTestCode(buff)
|
|
166
|
+
# write code to stop
|
|
167
|
+
code = (
|
|
168
|
+
"%(name)s.stop()\n"
|
|
169
|
+
)
|
|
170
|
+
buff.writeIndentedLines(code % self.params)
|
|
171
|
+
# dedent
|
|
172
|
+
buff.setIndentLevel(-indented, relative=True)
|
|
173
|
+
else:
|
|
174
|
+
# if this Component can't stop recording, mark as finished as soon as recording has started
|
|
175
|
+
code = (
|
|
176
|
+
"if %(name)s.status == STARTED:\n"
|
|
177
|
+
" %(name)s.tStop = t # not accounting for scr refresh\n"
|
|
178
|
+
" %(name)s.tStopRefresh = tThisFlipGlobal # on global time\n"
|
|
179
|
+
" %(name)s.frameNStop = frameN # exact frame index\n"
|
|
180
|
+
" %(name)s.status = FINISHED\n"
|
|
181
|
+
)
|
|
182
|
+
buff.writeIndentedLines(code % self.params)
|
|
114
183
|
|
|
115
184
|
def writeRoutineEndCode(self, buff):
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
buff.writeIndentedLines(code % self.params)
|
|
123
|
-
buff.setIndentLevel(1, relative=True)
|
|
124
|
-
code = (
|
|
125
|
-
"%(name)s.status = FINISHED\n"
|
|
126
|
-
)
|
|
127
|
-
buff.writeIndentedLines(code % self.params)
|
|
128
|
-
buff.setIndentLevel(-1, relative=True)
|
|
185
|
+
if self.params['stopWithRoutine']:
|
|
186
|
+
# stop at the end of the Routine, if requested
|
|
187
|
+
code = (
|
|
188
|
+
"%(name)s.stop() # ensure eyetracking has stopped at end of Routine\n"
|
|
189
|
+
)
|
|
190
|
+
buff.writeIndentedLines(code % self.params)
|
|
Binary file
|
|
@@ -27,7 +27,7 @@ class FormComponent(BaseVisualComponent):
|
|
|
27
27
|
|
|
28
28
|
def __init__(self, exp, parentName,
|
|
29
29
|
name='form',
|
|
30
|
-
items='
|
|
30
|
+
items='',
|
|
31
31
|
textHeight=0.03,
|
|
32
32
|
font="Open Sans",
|
|
33
33
|
randomize=False,
|
|
@@ -76,7 +76,11 @@ class FormComponent(BaseVisualComponent):
|
|
|
76
76
|
items, valType='file', inputType="table", allowedTypes=[], categ='Basic',
|
|
77
77
|
updates='constant',
|
|
78
78
|
hint=_translate("The csv filename containing the items for your survey."),
|
|
79
|
-
label=_translate("Items")
|
|
79
|
+
label=_translate("Items"),
|
|
80
|
+
ctrlParams={
|
|
81
|
+
'template': Path(__file__).parent / "formItems.xltx"
|
|
82
|
+
}
|
|
83
|
+
)
|
|
80
84
|
|
|
81
85
|
self.params['Text Height'] = Param(
|
|
82
86
|
textHeight, valType='num', inputType="single", allowedTypes=[], categ='Formatting',
|
|
Binary file
|
|
@@ -22,7 +22,8 @@ class GratingComponent(BaseVisualComponent):
|
|
|
22
22
|
def __init__(self, exp, parentName, name='grating', image='sin',
|
|
23
23
|
mask='', sf='', interpolate='linear',
|
|
24
24
|
units='from exp settings', color='$[1,1,1]', colorSpace='rgb',
|
|
25
|
-
contrast=1.0, pos=(0, 0), size=(0.5, 0.5), anchor="center",
|
|
25
|
+
contrast=1.0, pos=(0, 0), size=(0.5, 0.5), anchor="center",
|
|
26
|
+
ori=0, phase=0.0, texRes='128', draggable=False,
|
|
26
27
|
startType='time (s)', startVal=0.0,
|
|
27
28
|
stopType='duration (s)', stopVal=1.0, blendmode='avg',
|
|
28
29
|
startEstim='', durationEstim=''):
|
|
@@ -83,6 +84,14 @@ class GratingComponent(BaseVisualComponent):
|
|
|
83
84
|
updates='constant',
|
|
84
85
|
hint=_translate("Which point on the stimulus should be anchored to its exact position?"),
|
|
85
86
|
label=_translate("Anchor"))
|
|
87
|
+
self.params['draggable'] = Param(
|
|
88
|
+
draggable, valType="code", inputType="bool", categ="Layout",
|
|
89
|
+
updates="constant",
|
|
90
|
+
label=_translate("Draggable?"),
|
|
91
|
+
hint=_translate(
|
|
92
|
+
"Should this stimulus be moveble by clicking and dragging?"
|
|
93
|
+
)
|
|
94
|
+
)
|
|
86
95
|
|
|
87
96
|
msg = _translate("Spatial positioning of the image on the grating "
|
|
88
97
|
"(wraps in range 0-1.0)")
|
|
@@ -135,7 +144,7 @@ class GratingComponent(BaseVisualComponent):
|
|
|
135
144
|
code = ("%s = visual.GratingStim(\n" % inits['name'] +
|
|
136
145
|
" win=win, name='%s',%s\n" % (inits['name'], unitsStr) +
|
|
137
146
|
" tex=%(tex)s, mask=%(mask)s, anchor=%(anchor)s,\n" % inits +
|
|
138
|
-
" ori=%(ori)s, pos=%(pos)s, size=%(size)s, " % inits +
|
|
147
|
+
" ori=%(ori)s, pos=%(pos)s, draggable=%(draggable)s, size=%(size)s, " % inits +
|
|
139
148
|
"sf=%(sf)s, phase=%(phase)s,\n" % inits +
|
|
140
149
|
" color=%(color)s, colorSpace=%(colorSpace)s,\n" % inits +
|
|
141
150
|
" opacity=%(opacity)s, contrast=%(contrast)s, blendmode=%(blendmode)s,\n" % inits +
|
|
@@ -169,7 +178,9 @@ class GratingComponent(BaseVisualComponent):
|
|
|
169
178
|
" win : psychoJS.window,\n"
|
|
170
179
|
" name : '{inits[name]}', {units}\n"
|
|
171
180
|
" tex : {inits[tex]}, mask : {inits[mask]},\n"
|
|
172
|
-
" ori : {inits[ori]},
|
|
181
|
+
" ori : {inits[ori]}, \n"
|
|
182
|
+
" pos : {inits[pos]},\n"
|
|
183
|
+
" draggable: {inits[draggable]},\n"
|
|
173
184
|
" anchor : {inits[anchor]},\n"
|
|
174
185
|
" sf : {inits[sf]}, phase : {inits[phase]},\n"
|
|
175
186
|
" size : {inits[size]},\n"
|
|
Binary file
|
|
@@ -22,7 +22,7 @@ class ImageComponent(BaseVisualComponent):
|
|
|
22
22
|
interpolate='linear', units='from exp settings',
|
|
23
23
|
color='$[1,1,1]', colorSpace='rgb', pos=(0, 0),
|
|
24
24
|
size=(0.5, 0.5), anchor="center", ori=0, texRes='128', flipVert=False,
|
|
25
|
-
flipHoriz=False,
|
|
25
|
+
flipHoriz=False, draggable=False,
|
|
26
26
|
startType='time (s)', startVal=0.0,
|
|
27
27
|
stopType='duration (s)', stopVal=1.0,
|
|
28
28
|
startEstim='', durationEstim=''):
|
|
@@ -106,6 +106,14 @@ class ImageComponent(BaseVisualComponent):
|
|
|
106
106
|
updates='constant',
|
|
107
107
|
hint=_translate("Which point on the stimulus should be anchored to its exact position?"),
|
|
108
108
|
label=_translate("Anchor"))
|
|
109
|
+
self.params['draggable'] = Param(
|
|
110
|
+
draggable, valType="code", inputType="bool", categ="Layout",
|
|
111
|
+
updates="constant",
|
|
112
|
+
label=_translate("Draggable?"),
|
|
113
|
+
hint=_translate(
|
|
114
|
+
"Should this stimulus be moveble by clicking and dragging?"
|
|
115
|
+
)
|
|
116
|
+
)
|
|
109
117
|
|
|
110
118
|
del self.params['fillColor']
|
|
111
119
|
del self.params['borderColor']
|
|
@@ -123,7 +131,7 @@ class ImageComponent(BaseVisualComponent):
|
|
|
123
131
|
" win=win,\n"
|
|
124
132
|
" name='{inits[name]}', {units}\n"
|
|
125
133
|
" image={inits[image]}, mask={inits[mask]}, anchor={inits[anchor]},\n"
|
|
126
|
-
" ori={inits[ori]}, pos={inits[pos]}, size={inits[size]},\n"
|
|
134
|
+
" ori={inits[ori]}, pos={inits[pos]}, draggable={inits[draggable]}, size={inits[size]},\n"
|
|
127
135
|
" color={inits[color]}, colorSpace={inits[colorSpace]}, opacity={inits[opacity]},\n"
|
|
128
136
|
" flipHoriz={inits[flipHoriz]}, flipVert={inits[flipVert]},\n"
|
|
129
137
|
# no newline - start optional parameters
|
|
@@ -164,7 +172,10 @@ class ImageComponent(BaseVisualComponent):
|
|
|
164
172
|
" name : '{inits[name]}', {units}\n"
|
|
165
173
|
" image : {inits[image]}, mask : {inits[mask]},\n"
|
|
166
174
|
" anchor : {inits[anchor]},\n"
|
|
167
|
-
" ori : {inits[ori]},
|
|
175
|
+
" ori : {inits[ori]}, \n"
|
|
176
|
+
" pos : {inits[pos]}, \n"
|
|
177
|
+
" draggable: {inits[draggable]},\n"
|
|
178
|
+
" size : {inits[size]},\n"
|
|
168
179
|
" color : new util.Color({inits[color]}), opacity : {inits[opacity]},\n"
|
|
169
180
|
" flipHoriz : {inits[flipHoriz]}, flipVert : {inits[flipVert]},\n"
|
|
170
181
|
# no newline - start optional parameters
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -170,10 +170,23 @@ class KeyboardComponent(BaseDeviceComponent):
|
|
|
170
170
|
buff.writeIndentedLines(code % self.params)
|
|
171
171
|
|
|
172
172
|
def writeRoutineStartCode(self, buff):
|
|
173
|
-
code = (
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
code = (
|
|
174
|
+
"# create starting attributes for %(name)s\n"
|
|
175
|
+
"%(name)s.keys = []\n"
|
|
176
|
+
"%(name)s.rt = []\n"
|
|
177
|
+
"_%(name)s_allKeys = []\n"
|
|
178
|
+
)
|
|
176
179
|
buff.writeIndentedLines(code % self.params)
|
|
180
|
+
# if allowedKeys looks like a variable, load it from global
|
|
181
|
+
allowedKeys = str(self.params['allowedKeys'])
|
|
182
|
+
allowedKeysIsVar = valid_var_re.match(str(allowedKeys)) and not allowedKeys == 'None'
|
|
183
|
+
if allowedKeysIsVar:
|
|
184
|
+
code = (
|
|
185
|
+
"# allowedKeys looks like a variable, so make sure it exists locally\n"
|
|
186
|
+
"if '%(allowedKeys)s' in globals():\n"
|
|
187
|
+
" %(allowedKeys)s = globals()['%(allowedKeys)s']\n"
|
|
188
|
+
)
|
|
189
|
+
buff.writeIndentedLines(code % self.params)
|
|
177
190
|
|
|
178
191
|
def writeRoutineStartCodeJS(self, buff):
|
|
179
192
|
code = ("%(name)s.keys = undefined;\n"
|
|
@@ -203,13 +216,12 @@ class KeyboardComponent(BaseDeviceComponent):
|
|
|
203
216
|
# if it looks like a variable, check that the variable is suitable
|
|
204
217
|
# to eval at run-time
|
|
205
218
|
stringType = 'str'
|
|
206
|
-
code = (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
.format(allowedKeys, stringType))
|
|
219
|
+
code = (
|
|
220
|
+
"# allowed keys looks like a variable named `{0}`\n"
|
|
221
|
+
"if not type({0}) in [list, tuple, np.ndarray]:\n"
|
|
222
|
+
" if not isinstance({0}, {1}):\n"
|
|
223
|
+
" {0} = str({0})\n"
|
|
224
|
+
).format(allowedKeys, stringType)
|
|
213
225
|
|
|
214
226
|
code += (
|
|
215
227
|
" elif not ',' in {0}:\n"
|
|
Binary file
|
|
@@ -30,15 +30,6 @@ except (ImportError, ModuleNotFoundError):
|
|
|
30
30
|
# Get list of sample rates
|
|
31
31
|
sampleRates = {r[1]: r[0] for r in sampleRateQualityLevels.values()}
|
|
32
32
|
|
|
33
|
-
onlineTranscribers = {
|
|
34
|
-
"Google": "GOOGLE"
|
|
35
|
-
}
|
|
36
|
-
localTranscribers = {
|
|
37
|
-
"Google": "google",
|
|
38
|
-
"Whisper": "whisper",
|
|
39
|
-
}
|
|
40
|
-
allTranscribers = {**localTranscribers, **onlineTranscribers}
|
|
41
|
-
|
|
42
33
|
|
|
43
34
|
class MicrophoneComponent(BaseDeviceComponent):
|
|
44
35
|
"""An event class for capturing short sound stimuli"""
|
|
@@ -50,14 +41,22 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
50
41
|
'duration), okay for spoken words')
|
|
51
42
|
deviceClasses = ['psychopy.hardware.microphone.MicrophoneDevice']
|
|
52
43
|
|
|
44
|
+
# dict of available transcribers (plugins can add entries to this)
|
|
45
|
+
localTranscribers = {
|
|
46
|
+
"Google": "google",
|
|
47
|
+
}
|
|
48
|
+
onlineTranscribers = {
|
|
49
|
+
"Google": "google",
|
|
50
|
+
}
|
|
51
|
+
|
|
53
52
|
def __init__(self, exp, parentName, name='mic',
|
|
54
53
|
startType='time (s)', startVal=0.0,
|
|
55
54
|
stopType='duration (s)', stopVal=2.0,
|
|
56
55
|
startEstim='', durationEstim='',
|
|
57
56
|
channels='auto', device=None,
|
|
58
57
|
sampleRate='DVD Audio (48kHz)', maxSize=24000,
|
|
59
|
-
outputType='default', speakTimes=
|
|
60
|
-
transcribe=False, transcribeBackend="
|
|
58
|
+
outputType='default', speakTimes=False, trimSilent=False,
|
|
59
|
+
transcribe=False, transcribeBackend="none",
|
|
61
60
|
transcribeLang="en-US", transcribeWords="",
|
|
62
61
|
transcribeWhisperModel="base",
|
|
63
62
|
transcribeWhisperDevice="auto",
|
|
@@ -110,6 +109,15 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
110
109
|
"local experiments - online experiments ask the participant which mic to use."
|
|
111
110
|
)
|
|
112
111
|
)
|
|
112
|
+
# grey out device settings when device is default
|
|
113
|
+
for depParam in ("channels", "sampleRate"):
|
|
114
|
+
self.depends.append({
|
|
115
|
+
"dependsOn": "device", # if...
|
|
116
|
+
"condition": "== 'None'", # is...
|
|
117
|
+
"param": depParam, # then...
|
|
118
|
+
"true": "hide", # should...
|
|
119
|
+
"false": "show", # otherwise...
|
|
120
|
+
})
|
|
113
121
|
if stereo is not None:
|
|
114
122
|
# If using a legacy mic component, work out channels from old bool value of stereo
|
|
115
123
|
channels = ['mono', 'stereo'][stereo]
|
|
@@ -154,7 +162,7 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
154
162
|
msg = _translate(
|
|
155
163
|
"Tick this to save times when the participant starts and stops speaking")
|
|
156
164
|
self.params['speakTimes'] = Param(
|
|
157
|
-
speakTimes, valType='bool', inputType='bool', categ='
|
|
165
|
+
speakTimes, valType='bool', inputType='bool', categ='Transcription',
|
|
158
166
|
hint=msg,
|
|
159
167
|
label=_translate("Speaking start / stop times")
|
|
160
168
|
)
|
|
@@ -186,7 +194,8 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
186
194
|
'transcribeLang',
|
|
187
195
|
'transcribeWords',
|
|
188
196
|
'transcribeWhisperModel',
|
|
189
|
-
'transcribeWhisperDevice'
|
|
197
|
+
'transcribeWhisperDevice',
|
|
198
|
+
'speakTimes'
|
|
190
199
|
]
|
|
191
200
|
|
|
192
201
|
for depParam in whisperParams:
|
|
@@ -200,7 +209,8 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
200
209
|
|
|
201
210
|
self.params['transcribeBackend'] = Param(
|
|
202
211
|
transcribeBackend, valType='code', inputType='choice', categ='Transcription',
|
|
203
|
-
|
|
212
|
+
allowedVals=list(self.allTranscribers.values()),
|
|
213
|
+
allowedLabels=list(self.allTranscribers),
|
|
204
214
|
direct=False,
|
|
205
215
|
hint=_translate("What transcription service to use to transcribe audio?"),
|
|
206
216
|
label=_translate("Transcription backend")
|
|
@@ -248,7 +258,13 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
248
258
|
"true": "show", # what to do with param if condition is True
|
|
249
259
|
"false": "hide", # permitted: hide, show, enable, disable
|
|
250
260
|
})
|
|
251
|
-
|
|
261
|
+
self.depends.append({
|
|
262
|
+
"dependsOn": "transcribeBackend",
|
|
263
|
+
"condition": "=='Whisper'",
|
|
264
|
+
"param": "speakTimes",
|
|
265
|
+
"true": "show", # what to do with param if condition is True
|
|
266
|
+
"false": "hide", # permitted: hide, show, enable, disable
|
|
267
|
+
})
|
|
252
268
|
# settings for whisper we might want, we'll need to get these from the
|
|
253
269
|
# plugin itself at some point
|
|
254
270
|
self.params['transcribeWhisperDevice'] = Param(
|
|
@@ -266,7 +282,14 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
266
282
|
"true": "show", # what to do with param if condition is True
|
|
267
283
|
"false": "hide", # permitted: hide, show, enable, disable
|
|
268
284
|
})
|
|
269
|
-
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def allTranscribers(self):
|
|
288
|
+
"""
|
|
289
|
+
Dict of all available transcribers (combines MicrophoneComponent.localTranscribers and
|
|
290
|
+
MicrophoneComponent.onlineTranscribers)
|
|
291
|
+
"""
|
|
292
|
+
return {'None': "none", **self.localTranscribers, **self.onlineTranscribers}
|
|
270
293
|
|
|
271
294
|
def writeDeviceCode(self, buff):
|
|
272
295
|
"""
|
|
@@ -291,9 +314,14 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
291
314
|
" deviceClass='psychopy.hardware.microphone.MicrophoneDevice',\n"
|
|
292
315
|
" deviceName=%(deviceLabel)s,\n"
|
|
293
316
|
" index=%(device)s,\n"
|
|
317
|
+
" maxRecordingSize=%(maxSize)s,\n"
|
|
318
|
+
)
|
|
319
|
+
if self.params['device'].val not in ("None", "", None):
|
|
320
|
+
code += (
|
|
294
321
|
" channels=%(channels)s, \n"
|
|
295
322
|
" sampleRateHz=%(sampleRate)s, \n"
|
|
296
|
-
|
|
323
|
+
)
|
|
324
|
+
code += (
|
|
297
325
|
")\n"
|
|
298
326
|
)
|
|
299
327
|
buff.writeOnceIndentedLines(code % inits)
|
|
@@ -469,10 +497,10 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
469
497
|
inits['transcribeBackend'].val = None
|
|
470
498
|
# Warn user if their transcriber won't work locally
|
|
471
499
|
if inits['transcribe'].val:
|
|
472
|
-
if
|
|
473
|
-
inits['transcribeBackend'].val = localTranscribers[self.params['transcribeBackend'].val]
|
|
500
|
+
if self.params['transcribeBackend'].val in self.localTranscribers:
|
|
501
|
+
inits['transcribeBackend'].val = self.localTranscribers[self.params['transcribeBackend'].val]
|
|
474
502
|
else:
|
|
475
|
-
default = list(localTranscribers.values())[0]
|
|
503
|
+
default = list(self.localTranscribers.values())[0]
|
|
476
504
|
alert(4610, strFields={"transcriber": inits['transcribeBackend'].val, "default": default})
|
|
477
505
|
# Store recordings from this routine
|
|
478
506
|
code = (
|
|
@@ -519,26 +547,18 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
519
547
|
"%(loop)s.addData('%(name)s.script', %(name)sScript)\n"
|
|
520
548
|
)
|
|
521
549
|
buff.writeIndentedLines(code % inits)
|
|
522
|
-
if inits['speakTimes'] and inits['transcribeBackend'].val == "
|
|
550
|
+
if inits['speakTimes'] and inits['transcribeBackend'].val == "Whisper":
|
|
551
|
+
|
|
523
552
|
code = (
|
|
524
553
|
"# save transcription data\n"
|
|
525
554
|
"with open(os.path.join(%(name)sRecFolder, 'recording_%(name)s_%%s.json' %% tag), 'w') as fp:\n"
|
|
526
555
|
" fp.write(%(name)sScript.response)\n"
|
|
527
556
|
"# save speaking start/stop times\n"
|
|
528
|
-
"%(name)
|
|
529
|
-
"%(name)
|
|
530
|
-
"
|
|
531
|
-
"
|
|
532
|
-
"
|
|
533
|
-
" # append word data\n"
|
|
534
|
-
" %(name)sWordData.append(thisWord)\n"
|
|
535
|
-
"# if there were any words, store the start of first & end of last \n"
|
|
536
|
-
"if len(%(name)sWordData):\n"
|
|
537
|
-
" thisExp.addData('%(name)s.speechStart', %(name)sWordData[0]['start'])\n"
|
|
538
|
-
" thisExp.addData('%(name)s.speechEnd', %(name)sWordData[-1]['end'])\n"
|
|
539
|
-
"else:\n"
|
|
540
|
-
" thisExp.addData('%(name)s.speechStart', '')\n"
|
|
541
|
-
" thisExp.addData('%(name)s.speechEnd', '')\n"
|
|
557
|
+
"%(name)sSpeechInterval = %(name)s.lastScript.getSpeechInterval()\n"
|
|
558
|
+
"%(name)sSpeechOnset = %(name)sSpeechInterval[0]\n"
|
|
559
|
+
"%(name)sSpeechOffset = %(name)sSpeechInterval[1]\n"
|
|
560
|
+
"thisExp.addData('%(name)s.speechStart', %(name)sSpeechOnset)\n"
|
|
561
|
+
"thisExp.addData('%(name)s.speechEnd', %(name)sSpeechOffset)\n"
|
|
542
562
|
)
|
|
543
563
|
buff.writeIndentedLines(code % inits)
|
|
544
564
|
# Write base end routine code
|
|
@@ -547,11 +567,11 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
547
567
|
def writeRoutineEndCodeJS(self, buff):
|
|
548
568
|
inits = getInitVals(self.params)
|
|
549
569
|
inits['routine'] = self.parentName
|
|
550
|
-
if
|
|
551
|
-
inits['transcribeBackend'].val = allTranscribers[self.params['transcribeBackend'].val]
|
|
570
|
+
if self.params['transcribeBackend'].val in self.allTranscribers:
|
|
571
|
+
inits['transcribeBackend'].val = self.allTranscribers[self.params['transcribeBackend'].val]
|
|
552
572
|
# Warn user if their transcriber won't work online
|
|
553
|
-
if inits['transcribe'].val and inits['transcribeBackend'].val not in onlineTranscribers.values():
|
|
554
|
-
default = list(onlineTranscribers.values())[0]
|
|
573
|
+
if inits['transcribe'].val and inits['transcribeBackend'].val not in self.onlineTranscribers.values():
|
|
574
|
+
default = list(self.onlineTranscribers.values())[0]
|
|
555
575
|
alert(4605, strFields={"transcriber": inits['transcribeBackend'].val, "default": default})
|
|
556
576
|
|
|
557
577
|
# Write base end routine code
|
|
Binary file
|