psychopy 2024.2.1__py3-none-any.whl → 2024.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of psychopy might be problematic. Click here for more details.
- psychopy/.DS_Store +0 -0
- psychopy/GIT_SHA +1 -1
- psychopy/VERSION +1 -1
- psychopy/__init__.py +10 -1
- psychopy/__init__.py.orig +65 -0
- psychopy/app/{locale/ar_001/.DS_Store → .DS_Store} +0 -0
- psychopy/app/Resources/.DS_Store +0 -0
- psychopy/app/_psychopyApp.py +11 -3
- psychopy/app/appData.spec +1 -1
- psychopy/app/builder/builder.py +1 -1
- psychopy/app/builder/builder.py.orig +3932 -0
- psychopy/app/builder/dialogs/__init__.py.orig +1679 -0
- psychopy/app/builder/dialogs/paramCtrls.py +1 -1
- psychopy/app/builder/dialogs/paramCtrls.py.orig +713 -0
- psychopy/app/colorpicker/__init__.py.orig +411 -0
- psychopy/app/cortex.log +0 -0
- psychopy/app/jobs.py +8 -1
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +2452 -1731
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN.po +6127 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.po +7366 -0
- psychopy/app/plugin_manager/dialog.py +9 -7
- psychopy/app/ribbon.py +2 -1
- psychopy/app/runner/runner.py +7 -5
- psychopy/clock.py +8 -4
- psychopy/core.py.orig +169 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/index.html +23 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks-legacy-browsers.js +423 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks.js +427 -0
- 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 +330 -0
- psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks_lastrun.py +330 -0
- psychopy/demos/builder/Feature Demos/eyetracking/eyetracking.xml +298 -0
- psychopy/demos/builder/Feature Demos/eyetracking/eyetracking.xsd +120 -0
- psychopy/demos/builder/Tools/.DS_Store +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/.DS_Store +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.csv +38 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.log +3418 -0
- 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 +2 -0
- psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.log +15 -0
- 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 +323 -0
- psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual.py +562 -0
- psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual_lastrun.py +562 -0
- psychopy/demos/builder/Tools/gammaCalibration/questStairs.xlsx +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/readme.md +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/resources/low_contrast.png +0 -0
- psychopy/demos/builder/Tools/gammaCalibration/resources/make_2nd_order_tex.py +59 -0
- 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 +1 -0
- psychopy/demos/coder/iohub/eyetracking/.iohpid +1 -0
- psychopy/demos/coder/iohub/wintab/.DS_Store +0 -0
- psychopy/demos/coder/stimuli/.DS_Store +0 -0
- psychopy/demos/coder/stimuli/radialGratingContracting.py +29 -0
- psychopy/experiment/_experiment.py.orig +1032 -0
- psychopy/experiment/components/.DS_Store +0 -0
- psychopy/experiment/components/_base.py +13 -4
- psychopy/experiment/components/_base.py.orig +823 -0
- psychopy/experiment/components/form/.DS_Store +0 -0
- psychopy/experiment/components/microphone/__init__.py +10 -1
- psychopy/experiment/components/microphone/__init__.py.orig +490 -0
- psychopy/experiment/components/polygon/__init__.py +21 -22
- psychopy/experiment/components/settings/__init__.py +13 -14
- psychopy/experiment/components/settings/__init__.py.orig +1337 -0
- psychopy/experiment/components/textbox/__init__.py.orig +310 -0
- psychopy/experiment/components/webcam/.DS_Store +0 -0
- psychopy/experiment/components/webcam/light/.DS_Store +0 -0
- psychopy/experiment/flow.py +10 -8
- psychopy/experiment/loops.py.orig +829 -0
- psychopy/experiment/params.py +8 -3
- psychopy/experiment/params.py.orig +408 -0
- psychopy/experiment/routine.py.orig +503 -0
- psychopy/experiment/routines/_base.py +15 -6
- psychopy/experiment/routines/counterbalance/__init__.py +1 -0
- psychopy/gui/qtgui.py +14 -7
- psychopy/gui/util.py +10 -14
- psychopy/gui/wxgui.py +10 -4
- psychopy/hardware/.DS_Store +0 -0
- psychopy/hardware/brainproducts.py.orig +680 -0
- psychopy/hardware/iolab.py.orig +238 -0
- psychopy/hardware/manager.py +1 -1
- psychopy/hardware/photodiode.py +59 -27
- psychopy/hardware/serialport.py +51 -0
- psychopy/hardware/speaker.py +4 -4
- psychopy/iohub/datastore/__init__.py.orig +443 -0
- psychopy/iohub/datastore/util.py.orig +692 -0
- psychopy/iohub/devices/mouse/darwin.py.orig +427 -0
- psychopy/iohub/devices/mouse/linux2.py.orig +198 -0
- psychopy/preferences/.DS_Store +0 -0
- psychopy/projects/pavlovia.py +10 -3
- psychopy/projects/pavlovia.py.orig +1295 -0
- psychopy/sound/backend_ptb.py +22 -5
- psychopy/sound/transcribe.py +24 -4
- 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 +16 -0
- psychopy/tests/data/corrFullRandom_local.tsv +6 -0
- psychopy/tests/data/correctScript/.DS_Store +0 -0
- psychopy/tests/data/dots_height_local.png +0 -0
- psychopy/tests/data/dots_normAddBlend_local.png +0 -0
- psychopy/tests/data/dots_normHexbackground_local.png +0 -0
- psychopy/tests/data/dots_normNoShade_local.png +0 -0
- psychopy/tests/data/dots_norm_local.png +0 -0
- psychopy/tests/data/dots_stencil_local.png +0 -0
- psychopy/tests/data/elarray1_height_local.png +0 -0
- psychopy/tests/data/elarray1_normAddBlend_local.png +0 -0
- psychopy/tests/data/elarray1_normHexbackground_local.png +0 -0
- psychopy/tests/data/elarray1_norm_local.png +0 -0
- psychopy/tests/data/elarray1_stencil_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_height_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_norm_local.png +0 -0
- psychopy/tests/data/envelopeandrcos_stencil_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_height_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_norm_local.png +0 -0
- psychopy/tests/data/envelopepowerandrcos_stencil_local.png +0 -0
- psychopy/tests/data/gabor1_height_local.png +0 -0
- psychopy/tests/data/gabor1_normAddBlend_local.png +0 -0
- psychopy/tests/data/gabor1_normHexbackground_local.png +0 -0
- psychopy/tests/data/gabor1_normNoShade_local.png +0 -0
- psychopy/tests/data/gabor1_norm_local.png +0 -0
- psychopy/tests/data/gabor1_stencil_local.png +0 -0
- psychopy/tests/data/greyscale_normHexbackground_local.png +0 -0
- psychopy/tests/data/imageAndGauss_height_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normAddBlend_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normHexbackground_local.png +0 -0
- psychopy/tests/data/imageAndGauss_normNoShade_local.png +0 -0
- psychopy/tests/data/imageAndGauss_norm_local.png +0 -0
- psychopy/tests/data/imageAndGauss_stencil_local.png +0 -0
- psychopy/tests/data/movFrame1_stencil_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_height_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_normNoShade_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_norm_local.png +0 -0
- psychopy/tests/data/noiseAndRcos_stencil_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_height_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normAddBlend_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normHexbackground_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_normNoShade_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_norm_local.png +0 -0
- psychopy/tests/data/noiseFiltersAndRcos_stencil_local.png +0 -0
- psychopy/tests/data/numpyImage_height_local.png +0 -0
- psychopy/tests/data/numpyImage_normAddBlend_local.png +0 -0
- psychopy/tests/data/numpyImage_normHexbackground_local.png +0 -0
- psychopy/tests/data/numpyImage_normNoShade_local.png +0 -0
- psychopy/tests/data/numpyImage_norm_local.png +0 -0
- psychopy/tests/data/numpyImage_stencil_local.png +0 -0
- psychopy/tests/data/shape2_1_normAddBlend_local.png +0 -0
- psychopy/tests/data/shape2_1_normHexbackground_local.png +0 -0
- psychopy/tests/data/shape2_1_normNoShade_local.png +0 -0
- psychopy/tests/data/shape2_1_norm_local.png +0 -0
- psychopy/tests/data/shape2_1_stencil_local.png +0 -0
- psychopy/tests/data/testLoopsBlocks.psyexp_local.py +328 -0
- psychopy/tests/data/text1_height_local.png +0 -0
- psychopy/tests/data/text1_normAddBlend_local.png +0 -0
- psychopy/tests/data/text1_normHexbackground_local.png +0 -0
- psychopy/tests/data/text1_norm_local.png +0 -0
- psychopy/tests/data/text1_stencil_local.png +0 -0
- psychopy/tests/data/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 +9 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.log +177 -0
- 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 +9 -0
- psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.log +168 -0
- 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.orig +68 -0
- psychopy/tests/test_tools/test_arraytools.py +112 -0
- psychopy/tests/test_visual/test_image.py.orig +219 -0
- psychopy/tools/arraytools.py +47 -0
- psychopy/tools/versionchooser.py +1 -1
- psychopy/visual/backends/pygletbackend.py +26 -8
- psychopy/visual/basevisual.py.orig +1723 -0
- psychopy/visual/form.py.orig +1181 -0
- psychopy/visual/text.py.orig +752 -0
- psychopy/visual/textbox2/textbox2.py.orig +1315 -0
- psychopy/visual/window.py +13 -5
- psychopy/visual/windowwarp.py.orig +463 -0
- {psychopy-2024.2.1.dist-info → psychopy-2024.2.4.dist-info}/METADATA +9 -9
- {psychopy-2024.2.1.dist-info → psychopy-2024.2.4.dist-info}/RECORD +244 -78
- {psychopy-2024.2.1.dist-info → psychopy-2024.2.4.dist-info}/WHEEL +1 -1
- {psychopy-2024.2.1.dist-info → psychopy-2024.2.4.dist-info}/entry_points.txt +2 -0
- psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
- 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/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_ES/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
- 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/he_IL/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
- 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/ja_JP/LC_MESSAGE/messages.mo +0 -0
- 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/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/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/tr_TR/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
- psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
- psychopy-2024.2.1.dist-info/licenses/AUTHORS.md +0 -138
- /psychopy/{app/locale/ar_001/LC_MESSAGE → demos/builder}/.DS_Store +0 -0
- /psychopy/{app/locale/es_ES/LC_MESSAGE → demos/builder/Experiments}/.DS_Store +0 -0
- /psychopy/{visual → demos/builder/Tools/gammaCalibration/data}/.DS_Store +0 -0
- {psychopy-2024.2.1.dist-info → psychopy-2024.2.4.dist-info}/licenses/LICENSE +0 -0
|
Binary file
|
|
@@ -48,6 +48,10 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
48
48
|
onlineTranscribers = {
|
|
49
49
|
"Google": "google",
|
|
50
50
|
}
|
|
51
|
+
# dict mapping transcriber names to importable paths
|
|
52
|
+
transcriberPaths = {
|
|
53
|
+
'google': "psychopy.sound.transcribe:GoogleCloudTranscriber"
|
|
54
|
+
}
|
|
51
55
|
|
|
52
56
|
def __init__(self, exp, parentName, name='mic',
|
|
53
57
|
startType='time (s)', startVal=0.0,
|
|
@@ -352,13 +356,18 @@ class MicrophoneComponent(BaseDeviceComponent):
|
|
|
352
356
|
|
|
353
357
|
def writeRunOnceInitCode(self, buff):
|
|
354
358
|
inits = getInitVals(self.params)
|
|
359
|
+
# get transcriber path
|
|
360
|
+
if inits['transcribeBackend'].val in MicrophoneComponent.transcriberPaths:
|
|
361
|
+
inits['transcriberPath'] = MicrophoneComponent.transcriberPaths[inits['transcribeBackend'].val]
|
|
362
|
+
else:
|
|
363
|
+
inits['transcriberPath'] = inits['transcribeBackend'].val
|
|
355
364
|
# check if the user wants to do transcription
|
|
356
365
|
if inits['transcribe'].val:
|
|
357
366
|
code = (
|
|
358
367
|
"# Setup speech-to-text transcriber for audio recordings\n"
|
|
359
368
|
"from psychopy.sound.transcribe import setupTranscriber\n"
|
|
360
369
|
"setupTranscriber(\n"
|
|
361
|
-
" '%(
|
|
370
|
+
" '%(transcriberPath)s'")
|
|
362
371
|
|
|
363
372
|
# handle advanced config options
|
|
364
373
|
if inits['transcribeBackend'].val == 'Whisper':
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
# Part of the PsychoPy library
|
|
5
|
+
# Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2021 Open Science Tools Ltd.
|
|
6
|
+
# Distributed under the terms of the GNU General Public License (GPL).
|
|
7
|
+
|
|
8
|
+
# Author: Jeremy R. Gray, 2012
|
|
9
|
+
|
|
10
|
+
from __future__ import absolute_import, print_function
|
|
11
|
+
from builtins import super # provides Py3-style super() using python-future
|
|
12
|
+
|
|
13
|
+
from os import path
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from psychopy.alerts import alert
|
|
17
|
+
from psychopy.experiment.components import BaseComponent, Param, getInitVals, _translate
|
|
18
|
+
from psychopy.sound.microphone import Microphone, _hasPTB
|
|
19
|
+
from psychopy.sound.audiodevice import sampleRateQualityLevels
|
|
20
|
+
from psychopy.sound.audioclip import AUDIO_SUPPORTED_CODECS
|
|
21
|
+
from psychopy.localization import _localized as __localized
|
|
22
|
+
|
|
23
|
+
_localized = __localized.copy()
|
|
24
|
+
_localized.update({'stereo': _translate('Stereo'),
|
|
25
|
+
'channel': _translate('Channel')})
|
|
26
|
+
from psychopy.tests import _vmTesting
|
|
27
|
+
|
|
28
|
+
if _hasPTB and not _vmTesting:
|
|
29
|
+
devices = {d.deviceName: d for d in Microphone.getDevices()}
|
|
30
|
+
else:
|
|
31
|
+
devices = {}
|
|
32
|
+
sampleRates = {r[1]: r[0] for r in sampleRateQualityLevels.values()}
|
|
33
|
+
devices['default'] = None
|
|
34
|
+
|
|
35
|
+
onlineTranscribers = {
|
|
36
|
+
"Google": "GOOGLE",
|
|
37
|
+
"Microsoft Azure": "AZURE",
|
|
38
|
+
}
|
|
39
|
+
localTranscribers = {
|
|
40
|
+
<<<<<<< HEAD
|
|
41
|
+
"Built-In": "built-in",
|
|
42
|
+
"Google": "google",
|
|
43
|
+
"Microsoft Azure": "azure",
|
|
44
|
+
=======
|
|
45
|
+
"Google": "googleCloud",
|
|
46
|
+
"Microsoft Azure": "azure",
|
|
47
|
+
"Built-in": "sphinx",
|
|
48
|
+
>>>>>>> 31b648a29f77d0927dc5de635816423c07eaeb69
|
|
49
|
+
}
|
|
50
|
+
allTranscribers = {**localTranscribers, **onlineTranscribers}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class MicrophoneComponent(BaseComponent):
|
|
54
|
+
"""An event class for capturing short sound stimuli"""
|
|
55
|
+
categories = ['Responses']
|
|
56
|
+
targets = ['PsychoPy', 'PsychoJS']
|
|
57
|
+
iconFile = Path(__file__).parent / 'microphone.png'
|
|
58
|
+
tooltip = _translate('Microphone: basic sound capture (fixed onset & '
|
|
59
|
+
'duration), okay for spoken words')
|
|
60
|
+
|
|
61
|
+
def __init__(self, exp, parentName, name='mic',
|
|
62
|
+
startType='time (s)', startVal=0.0,
|
|
63
|
+
stopType='duration (s)', stopVal=2.0,
|
|
64
|
+
startEstim='', durationEstim='',
|
|
65
|
+
channels='auto', device="default",
|
|
66
|
+
sampleRate='Voice (16kHz)', maxSize=24000,
|
|
67
|
+
outputType='default', speakTimes=True, trimSilent=False,
|
|
68
|
+
<<<<<<< HEAD
|
|
69
|
+
transcribe=True, transcribeBackend="BUILT-IN", transcribeLang="en-US", transcribeWords="",
|
|
70
|
+
=======
|
|
71
|
+
transcribe=True, transcribeBackend="Built-in", transcribeLang="en-US", transcribeWords="",
|
|
72
|
+
>>>>>>> 31b648a29f77d0927dc5de635816423c07eaeb69
|
|
73
|
+
#legacy
|
|
74
|
+
stereo=None, channel=None):
|
|
75
|
+
super(MicrophoneComponent, self).__init__(
|
|
76
|
+
exp, parentName, name=name,
|
|
77
|
+
startType=startType, startVal=startVal,
|
|
78
|
+
stopType=stopType, stopVal=stopVal,
|
|
79
|
+
startEstim=startEstim, durationEstim=durationEstim)
|
|
80
|
+
|
|
81
|
+
self.type = 'Microphone'
|
|
82
|
+
self.url = "https://www.psychopy.org/builder/components/microphone.html"
|
|
83
|
+
self.exp.requirePsychopyLibs(['sound'])
|
|
84
|
+
|
|
85
|
+
self.order += []
|
|
86
|
+
|
|
87
|
+
self.params['stopType'].allowedVals = ['duration (s)']
|
|
88
|
+
msg = _translate(
|
|
89
|
+
'The duration of the recording in seconds; blank = 0 sec')
|
|
90
|
+
self.params['stopType'].hint = msg
|
|
91
|
+
|
|
92
|
+
# params
|
|
93
|
+
msg = _translate("What microphone device would you like the use to record? This will only affect local "
|
|
94
|
+
"experiments - online experiments ask the participant which mic to use.")
|
|
95
|
+
self.params['device'] = Param(
|
|
96
|
+
device, valType='str', inputType="choice", categ="Basic",
|
|
97
|
+
allowedVals=list(devices),
|
|
98
|
+
hint=msg,
|
|
99
|
+
label=_translate("Device")
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
msg = _translate(
|
|
103
|
+
"Record two channels (stereo) or one (mono, smaller file). Select 'auto' to use as many channels "
|
|
104
|
+
"as the selected device allows.")
|
|
105
|
+
if stereo is not None:
|
|
106
|
+
# If using a legacy mic component, work out channels from old bool value of stereo
|
|
107
|
+
channels = ['mono', 'stereo'][stereo]
|
|
108
|
+
self.params['channels'] = Param(
|
|
109
|
+
channels, valType='str', inputType="choice", categ='Hardware',
|
|
110
|
+
allowedVals=['auto', 'mono', 'stereo'],
|
|
111
|
+
hint=msg,
|
|
112
|
+
label=_translate('Channels'))
|
|
113
|
+
|
|
114
|
+
msg = _translate(
|
|
115
|
+
"How many samples per second (Hz) to record at")
|
|
116
|
+
self.params['sampleRate'] = Param(
|
|
117
|
+
sampleRate, valType='num', inputType="choice", categ='Hardware',
|
|
118
|
+
allowedVals=list(sampleRates),
|
|
119
|
+
hint=msg,
|
|
120
|
+
label=_translate('Sample Rate (Hz)'))
|
|
121
|
+
|
|
122
|
+
msg = _translate(
|
|
123
|
+
"To avoid excessively large output files, what is the biggest file size you are likely to expect?")
|
|
124
|
+
self.params['maxSize'] = Param(
|
|
125
|
+
maxSize, valType='num', inputType="single", categ='Hardware',
|
|
126
|
+
hint=msg,
|
|
127
|
+
label=_translate('Max Recording Size (kb)'))
|
|
128
|
+
|
|
129
|
+
msg = _translate(
|
|
130
|
+
"What file type should output audio files be saved as?")
|
|
131
|
+
self.params['outputType'] = Param(
|
|
132
|
+
outputType, valType='code', inputType='choice', categ='Data',
|
|
133
|
+
allowedVals=["default"] + AUDIO_SUPPORTED_CODECS,
|
|
134
|
+
hint=msg,
|
|
135
|
+
label=_translate("Output File Type")
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
msg = _translate(
|
|
139
|
+
"Tick this to save times when the participant starts and stops speaking")
|
|
140
|
+
self.params['speakTimes'] = Param(
|
|
141
|
+
speakTimes, valType='bool', inputType='bool', categ='Data',
|
|
142
|
+
hint=msg,
|
|
143
|
+
label=_translate("Speaking Start / Stop Times")
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
msg = _translate(
|
|
147
|
+
"Trim periods of silence from the output file")
|
|
148
|
+
self.params['trimSilent'] = Param(
|
|
149
|
+
trimSilent, valType='bool', inputType='bool', categ='Data',
|
|
150
|
+
hint=msg,
|
|
151
|
+
label=_translate("Trim Silent")
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Transcription params
|
|
155
|
+
self.order += [
|
|
156
|
+
'transcribe',
|
|
157
|
+
'transcribeBackend',
|
|
158
|
+
'transcribeLang',
|
|
159
|
+
'transcribeWords',
|
|
160
|
+
]
|
|
161
|
+
self.params['transcribe'] = Param(
|
|
162
|
+
transcribe, valType='bool', inputType='bool', categ='Transcription',
|
|
163
|
+
hint=_translate("Whether to transcribe the audio recording and store the transcription"),
|
|
164
|
+
label=_translate("Transcribe Audio")
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
for depParam in ['transcribeBackend', 'transcribeLang', 'transcribeWords']:
|
|
168
|
+
self.depends.append({
|
|
169
|
+
"dependsOn": "transcribe",
|
|
170
|
+
"condition": "==True",
|
|
171
|
+
"param": depParam,
|
|
172
|
+
"true": "enable", # what to do with param if condition is True
|
|
173
|
+
"false": "disable", # permitted: hide, show, enable, disable
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
self.params['transcribeBackend'] = Param(
|
|
177
|
+
transcribeBackend, valType='code', inputType='choice', categ='Transcription',
|
|
178
|
+
allowedVals=list(allTranscribers),
|
|
179
|
+
hint=_translate("What transcription service to use to transcribe audio?"),
|
|
180
|
+
label=_translate("Transcription Backend")
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
self.params['transcribeLang'] = Param(
|
|
184
|
+
transcribeLang, valType='str', inputType='single', categ='Transcription',
|
|
185
|
+
hint=_translate("What language you expect the recording to be spoken in, e.g. en-GB for English"),
|
|
186
|
+
label=_translate("Transcription Language")
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
self.params['transcribeWords'] = Param(
|
|
190
|
+
transcribeWords, valType='list', inputType='single', categ='Transcription',
|
|
191
|
+
hint=_translate("Set list of words to listen for - if blank will listen for all words in chosen language"),
|
|
192
|
+
label=_translate("Expected Words")
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
def writeStartCode(self, buff):
|
|
196
|
+
inits = getInitVals(self.params)
|
|
197
|
+
# Use filename with a suffix to store recordings
|
|
198
|
+
code = (
|
|
199
|
+
"# Make folder to store recordings from %(name)s\n"
|
|
200
|
+
"%(name)sRecFolder = filename + '_%(name)s_recorded'\n"
|
|
201
|
+
"if not os.path.isdir(%(name)sRecFolder):\n"
|
|
202
|
+
)
|
|
203
|
+
buff.writeIndentedLines(code % inits)
|
|
204
|
+
buff.setIndentLevel(1, relative=True)
|
|
205
|
+
code = (
|
|
206
|
+
"os.mkdir(%(name)sRecFolder)\n"
|
|
207
|
+
)
|
|
208
|
+
buff.writeIndentedLines(code % inits)
|
|
209
|
+
buff.setIndentLevel(-1, relative=True)
|
|
210
|
+
|
|
211
|
+
def writeStartCodeJS(self, buff):
|
|
212
|
+
inits = getInitVals(self.params)
|
|
213
|
+
code = (
|
|
214
|
+
"// Define folder to store recordings from %(name)s"
|
|
215
|
+
"%(name)sRecFolder = filename + '_%(name)s_recorded"
|
|
216
|
+
)
|
|
217
|
+
buff.writeIndentedLines(code % inits)
|
|
218
|
+
|
|
219
|
+
def writeInitCode(self, buff):
|
|
220
|
+
inits = getInitVals(self.params)
|
|
221
|
+
# Substitute sample rate value for numeric equivalent
|
|
222
|
+
inits['sampleRate'] = sampleRates[inits['sampleRate'].val]
|
|
223
|
+
# Substitute channel value for numeric equivalent
|
|
224
|
+
inits['channels'] = {'mono': 1, 'stereo': 2, 'auto': None}[self.params['channels'].val]
|
|
225
|
+
# Substitute device name for device index
|
|
226
|
+
device = devices[self.params['device'].val]
|
|
227
|
+
if hasattr(device, "deviceIndex"):
|
|
228
|
+
inits['device'] = device.deviceIndex
|
|
229
|
+
else:
|
|
230
|
+
inits['device'] = None
|
|
231
|
+
# Create Microphone object and clips dict
|
|
232
|
+
code = (
|
|
233
|
+
"%(name)s = sound.microphone.Microphone(\n"
|
|
234
|
+
)
|
|
235
|
+
buff.writeIndentedLines(code % inits)
|
|
236
|
+
buff.setIndentLevel(1, relative=True)
|
|
237
|
+
code = (
|
|
238
|
+
"device=%(device)s, channels=%(channels)s, \n"
|
|
239
|
+
"sampleRateHz=%(sampleRate)s, maxRecordingSize=%(maxSize)s\n"
|
|
240
|
+
)
|
|
241
|
+
buff.writeIndentedLines(code % inits)
|
|
242
|
+
buff.setIndentLevel(-1, relative=True)
|
|
243
|
+
code = (
|
|
244
|
+
")\n"
|
|
245
|
+
)
|
|
246
|
+
buff.writeIndentedLines(code % inits)
|
|
247
|
+
|
|
248
|
+
def writeInitCodeJS(self, buff):
|
|
249
|
+
inits = getInitVals(self.params)
|
|
250
|
+
inits['sampleRate'] = sampleRates[inits['sampleRate'].val]
|
|
251
|
+
# Alert user if non-default value is selected for device
|
|
252
|
+
if inits['device'].val != 'default':
|
|
253
|
+
alert(5055, strFields={'name': inits['name'].val})
|
|
254
|
+
# Write code
|
|
255
|
+
code = (
|
|
256
|
+
"%(name)s = new sound.Microphone({\n"
|
|
257
|
+
)
|
|
258
|
+
buff.writeIndentedLines(code % inits)
|
|
259
|
+
buff.setIndentLevel(1, relative=True)
|
|
260
|
+
code = (
|
|
261
|
+
"win : psychoJS.window, \n"
|
|
262
|
+
"name:'%(name)s',\n"
|
|
263
|
+
"sampleRateHz : %(sampleRate)s,\n"
|
|
264
|
+
"channels : %(channels)s,\n"
|
|
265
|
+
"maxRecordingSize : %(maxSize)s,\n"
|
|
266
|
+
"loopback : true,\n"
|
|
267
|
+
"policyWhenFull : 'ignore',\n"
|
|
268
|
+
)
|
|
269
|
+
buff.writeIndentedLines(code % inits)
|
|
270
|
+
buff.setIndentLevel(-1, relative=True)
|
|
271
|
+
code = (
|
|
272
|
+
"});\n"
|
|
273
|
+
)
|
|
274
|
+
buff.writeIndentedLines(code % inits)
|
|
275
|
+
|
|
276
|
+
def writeFrameCode(self, buff):
|
|
277
|
+
"""Write the code that will be called every frame"""
|
|
278
|
+
inits = getInitVals(self.params)
|
|
279
|
+
inits['routine'] = self.parentName
|
|
280
|
+
# Start the recording
|
|
281
|
+
code = (
|
|
282
|
+
"\n"
|
|
283
|
+
"# %(name)s updates"
|
|
284
|
+
)
|
|
285
|
+
buff.writeIndentedLines(code % inits)
|
|
286
|
+
self.writeStartTestCode(buff)
|
|
287
|
+
code = (
|
|
288
|
+
"# start recording with %(name)s\n"
|
|
289
|
+
"%(name)s.start()\n"
|
|
290
|
+
"%(name)s.status = STARTED\n"
|
|
291
|
+
)
|
|
292
|
+
buff.writeIndentedLines(code % inits)
|
|
293
|
+
buff.setIndentLevel(-1, relative=True)
|
|
294
|
+
# Get clip each frame
|
|
295
|
+
code = (
|
|
296
|
+
"if %(name)s.status == STARTED:\n"
|
|
297
|
+
)
|
|
298
|
+
buff.writeIndentedLines(code % inits)
|
|
299
|
+
buff.setIndentLevel(1, relative=True)
|
|
300
|
+
code = (
|
|
301
|
+
"# update recorded clip for %(name)s\n"
|
|
302
|
+
"%(name)s.poll()\n"
|
|
303
|
+
)
|
|
304
|
+
buff.writeIndentedLines(code % inits)
|
|
305
|
+
buff.setIndentLevel(-1, relative=True)
|
|
306
|
+
# Stop recording
|
|
307
|
+
self.writeStopTestCode(buff)
|
|
308
|
+
code = (
|
|
309
|
+
"# stop recording with %(name)s\n"
|
|
310
|
+
"%(name)s.stop()\n"
|
|
311
|
+
"%(name)s.status = FINISHED\n"
|
|
312
|
+
)
|
|
313
|
+
buff.writeIndentedLines(code % inits)
|
|
314
|
+
buff.setIndentLevel(-2, relative=True)
|
|
315
|
+
|
|
316
|
+
def writeFrameCodeJS(self, buff):
|
|
317
|
+
inits = getInitVals(self.params)
|
|
318
|
+
inits['routine'] = self.parentName
|
|
319
|
+
# Start the recording
|
|
320
|
+
self.writeStartTestCodeJS(buff)
|
|
321
|
+
code = (
|
|
322
|
+
"await %(name)s.start();\n"
|
|
323
|
+
)
|
|
324
|
+
buff.writeIndentedLines(code % inits)
|
|
325
|
+
buff.setIndentLevel(-1, relative=True)
|
|
326
|
+
code = (
|
|
327
|
+
"}"
|
|
328
|
+
)
|
|
329
|
+
buff.writeIndentedLines(code % inits)
|
|
330
|
+
if self.params['stopVal'].val not in ['', None, -1, 'None']:
|
|
331
|
+
# Stop the recording
|
|
332
|
+
self.writeStopTestCodeJS(buff)
|
|
333
|
+
code = (
|
|
334
|
+
"%(name)s.pause();\n"
|
|
335
|
+
)
|
|
336
|
+
buff.writeIndentedLines(code % inits)
|
|
337
|
+
buff.setIndentLevel(-1, relative=True)
|
|
338
|
+
code = (
|
|
339
|
+
"}"
|
|
340
|
+
)
|
|
341
|
+
buff.writeIndentedLines(code % inits)
|
|
342
|
+
|
|
343
|
+
def writeRoutineEndCode(self, buff):
|
|
344
|
+
inits = getInitVals(self.params)
|
|
345
|
+
# Alter inits
|
|
346
|
+
if len(self.exp.flow._loopList):
|
|
347
|
+
inits['loop'] = self.exp.flow._loopList[-1].params['name']
|
|
348
|
+
inits['filename'] = f"'recording_{inits['name']}_{inits['loop']}_%s.{inits['outputType']}' % {inits['loop']}.thisTrialN"
|
|
349
|
+
else:
|
|
350
|
+
inits['loop'] = "thisExp"
|
|
351
|
+
inits['filename'] = f"'recording_{inits['name']}'"
|
|
352
|
+
transcribe = inits['transcribe'].val
|
|
353
|
+
if inits['transcribe'].val == False:
|
|
354
|
+
inits['transcribeBackend'].val = None
|
|
355
|
+
if inits['outputType'].val == 'default':
|
|
356
|
+
inits['outputType'].val = 'wav'
|
|
357
|
+
# Warn user if their transcriber won't work locally
|
|
358
|
+
if inits['transcribe'].val:
|
|
359
|
+
if inits['transcribeBackend'].val in localTranscribers:
|
|
360
|
+
inits['transcribeBackend'].val = localTranscribers[self.params['transcribeBackend'].val]
|
|
361
|
+
else:
|
|
362
|
+
alert(4605, strFields={"transcriber": inits['transcribeBackend'].val})
|
|
363
|
+
inits['transcribeBackend'].val = list(localTranscribers.values())[0]
|
|
364
|
+
# Store recordings from this routine
|
|
365
|
+
code = (
|
|
366
|
+
"# tell mic to keep hold of current recording in %(name)s.clips and transcript (if applicable) in %(name)s.scripts\n"
|
|
367
|
+
"# this will also update %(name)s.lastClip and %(name)s.lastScript\n"
|
|
368
|
+
"%(name)sClip, %(name)sScript = %(name)s.bank(\n"
|
|
369
|
+
)
|
|
370
|
+
buff.writeIndentedLines(code % inits)
|
|
371
|
+
buff.setIndentLevel(1, relative=True)
|
|
372
|
+
code = (
|
|
373
|
+
"tag='%(loop)s', transcribe='%(transcribeBackend)s',\n"
|
|
374
|
+
)
|
|
375
|
+
buff.writeIndentedLines(code % inits)
|
|
376
|
+
if transcribe:
|
|
377
|
+
code = (
|
|
378
|
+
"language=%(transcribeLang)s, expectedWords=%(transcribeWords)s\n"
|
|
379
|
+
)
|
|
380
|
+
else:
|
|
381
|
+
code = (
|
|
382
|
+
"config=None\n"
|
|
383
|
+
)
|
|
384
|
+
buff.writeIndentedLines(code % inits)
|
|
385
|
+
buff.setIndentLevel(-1, relative=True)
|
|
386
|
+
code = (
|
|
387
|
+
")\n"
|
|
388
|
+
"%(loop)s.addData('%(name)s.clip', os.path.join(%(name)sRecFolder, %(filename)s))\n"
|
|
389
|
+
)
|
|
390
|
+
buff.writeIndentedLines(code % inits)
|
|
391
|
+
if transcribe:
|
|
392
|
+
code = (
|
|
393
|
+
"%(loop)s.addData('%(name)s.script', %(name)sScript)\n"
|
|
394
|
+
)
|
|
395
|
+
buff.writeIndentedLines(code % inits)
|
|
396
|
+
# Write base end routine code
|
|
397
|
+
BaseComponent.writeRoutineEndCode(self, buff)
|
|
398
|
+
|
|
399
|
+
def writeRoutineEndCodeJS(self, buff):
|
|
400
|
+
inits = getInitVals(self.params)
|
|
401
|
+
inits['routine'] = self.parentName
|
|
402
|
+
if len(self.exp.flow._loopList):
|
|
403
|
+
inits['loop'] = self.exp.flow._loopList[-1].params['name']
|
|
404
|
+
inits['filename'] = f"'recording_{inits['name']}_{inits['loop']}_' + {inits['loop']}.thisN"
|
|
405
|
+
else:
|
|
406
|
+
inits['loop'] = ""
|
|
407
|
+
inits['filename'] = f"'recording_{inits['name']}'"
|
|
408
|
+
if inits['transcribeBackend'].val in allTranscribers:
|
|
409
|
+
inits['transcribeBackend'].val = allTranscribers[self.params['transcribeBackend'].val]
|
|
410
|
+
# Warn user if their transcriber won't work online
|
|
411
|
+
if inits['transcribe'].val and inits['transcribeBackend'].val not in onlineTranscribers.values():
|
|
412
|
+
alert(4605, strFields={"transcriber": inits['transcribeBackend'].val})
|
|
413
|
+
inits['transcribeBackend'].val = list(onlineTranscribers.values())[0]
|
|
414
|
+
|
|
415
|
+
# Write base end routine code
|
|
416
|
+
BaseComponent.writeRoutineEndCodeJS(self, buff)
|
|
417
|
+
# Store recordings from this routine
|
|
418
|
+
code = (
|
|
419
|
+
"// stop the microphone (make the audio data ready for upload)\n"
|
|
420
|
+
"await %(name)s.stop();\n"
|
|
421
|
+
"// get the recording\n"
|
|
422
|
+
"%(name)s.lastClip = await %(name)s.getRecording({\n"
|
|
423
|
+
)
|
|
424
|
+
buff.writeIndentedLines(code % inits)
|
|
425
|
+
buff.setIndentLevel(1, relative=True)
|
|
426
|
+
code = (
|
|
427
|
+
"tag: %(filename)s,\n"
|
|
428
|
+
"flush: false\n"
|
|
429
|
+
)
|
|
430
|
+
buff.writeIndentedLines(code % inits)
|
|
431
|
+
buff.setIndentLevel(-1, relative=True)
|
|
432
|
+
code = (
|
|
433
|
+
"});\n"
|
|
434
|
+
"psychoJS.experiment.addData('%(name)s.clip', %(filename)s);\n"
|
|
435
|
+
"// start the asynchronous upload to the server\n"
|
|
436
|
+
"%(name)s.lastClip.upload();\n"
|
|
437
|
+
)
|
|
438
|
+
buff.writeIndentedLines(code % inits)
|
|
439
|
+
if self.params['transcribe'].val:
|
|
440
|
+
code = (
|
|
441
|
+
"// transcribe the recording\n"
|
|
442
|
+
"const transcription = await %(name)s.lastClip.transcribe({\n"
|
|
443
|
+
)
|
|
444
|
+
buff.writeIndentedLines(code % inits)
|
|
445
|
+
buff.setIndentLevel(1, relative=True)
|
|
446
|
+
code = (
|
|
447
|
+
"languageCode: %(transcribeLang)s,\n"
|
|
448
|
+
"engine: sound.AudioClip.Engine.%(transcribeBackend)s,\n"
|
|
449
|
+
"wordList: %(transcribeWords)s\n"
|
|
450
|
+
)
|
|
451
|
+
buff.writeIndentedLines(code % inits)
|
|
452
|
+
buff.setIndentLevel(-1, relative=True)
|
|
453
|
+
code = (
|
|
454
|
+
"});\n"
|
|
455
|
+
"%(name)s.lastScript = transcription.transcript;\n"
|
|
456
|
+
"%(name)s.lastConf = transcription.confidence;\n"
|
|
457
|
+
"psychoJS.experiment.addData('%(name)s.transcript', %(name)s.lastScript);\n"
|
|
458
|
+
"psychoJS.experiment.addData('%(name)s.confidence', %(name)s.lastConf);\n"
|
|
459
|
+
)
|
|
460
|
+
buff.writeIndentedLines(code % inits)
|
|
461
|
+
|
|
462
|
+
def writeExperimentEndCode(self, buff):
|
|
463
|
+
"""Write the code that will be called at the end of
|
|
464
|
+
an experiment (e.g. save log files or reset hardware)
|
|
465
|
+
"""
|
|
466
|
+
inits = getInitVals(self.params)
|
|
467
|
+
if len(self.exp.flow._loopList):
|
|
468
|
+
currLoop = self.exp.flow._loopList[-1] # last (outer-most) loop
|
|
469
|
+
else:
|
|
470
|
+
currLoop = self.exp._expHandler
|
|
471
|
+
inits['loop'] = currLoop.params['name']
|
|
472
|
+
if inits['outputType'].val == 'default':
|
|
473
|
+
inits['outputType'].val = 'wav'
|
|
474
|
+
# Save recording
|
|
475
|
+
code = (
|
|
476
|
+
"# save %(name)s recordings\n"
|
|
477
|
+
"for tag in %(name)s.clips:"
|
|
478
|
+
)
|
|
479
|
+
buff.writeIndentedLines(code % inits)
|
|
480
|
+
buff.setIndentLevel(1, relative=True)
|
|
481
|
+
code = (
|
|
482
|
+
"for i, clip in enumerate(%(name)s.clips[tag]):\n"
|
|
483
|
+
)
|
|
484
|
+
buff.writeIndentedLines(code % inits)
|
|
485
|
+
buff.setIndentLevel(1, relative=True)
|
|
486
|
+
code = (
|
|
487
|
+
"clip.save(os.path.join(%(name)sRecFolder, 'recording_%(name)s_%%s_%%s.%(outputType)s' %% (tag, i)))\n"
|
|
488
|
+
)
|
|
489
|
+
buff.writeIndentedLines(code % inits)
|
|
490
|
+
buff.setIndentLevel(-2, relative=True)
|
|
@@ -293,28 +293,27 @@ class PolygonComponent(BaseVisualComponent):
|
|
|
293
293
|
if self.params['interpolate'].val != 'linear':
|
|
294
294
|
interpolate = 'false'
|
|
295
295
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
296
|
+
# make a util.Color object for non-transparent
|
|
297
|
+
for key in ("fillColor", "lineColor"):
|
|
298
|
+
if inits[key].val != "undefined":
|
|
299
|
+
inits[key].val = "new util.Color(%s)" % inits[key]
|
|
300
|
+
inits[key].valType = "code"
|
|
301
|
+
# add other params
|
|
302
|
+
code += (
|
|
303
|
+
" ori: {ori}, \n"
|
|
304
|
+
" pos: {pos}, \n"
|
|
305
|
+
" draggable: {draggable}, \n"
|
|
306
|
+
" anchor: {anchor}, \n"
|
|
307
|
+
" lineWidth: {lineWidth}, \n"
|
|
308
|
+
" lineColor: {lineColor}, \n"
|
|
309
|
+
" fillColor: {fillColor}, \n"
|
|
310
|
+
" colorSpace: {colorSpace}, \n"
|
|
311
|
+
" opacity: {opacity}, \n"
|
|
312
|
+
" depth: {depth}, \n"
|
|
313
|
+
" interpolate: {interpolate}, \n"
|
|
314
|
+
"}});\n"
|
|
315
|
+
"\n"
|
|
316
|
+
)
|
|
318
317
|
buff.writeIndentedLines(code.format(name=inits['name'],
|
|
319
318
|
unitsStr=unitsStr,
|
|
320
319
|
anchor=inits['anchor'],
|
|
@@ -1881,11 +1881,11 @@ class SettingsComponent:
|
|
|
1881
1881
|
" # if not given a window to setup, make one\n"
|
|
1882
1882
|
" win = visual.Window(\n"
|
|
1883
1883
|
" size=_winSize, fullscr=_fullScr, screen=%(screenNumber)s,\n"
|
|
1884
|
-
" winType=%(winType)s, allowStencil=%(allowStencil)s,\n"
|
|
1884
|
+
" winType=%(winType)s, allowGUI=%(allowGUI)s, allowStencil=%(allowStencil)s,\n"
|
|
1885
1885
|
" monitor=%(Monitor)s, color=%(color)s, colorSpace=%(colorSpace)s,\n"
|
|
1886
1886
|
" backgroundImage=%(backgroundImg)s, backgroundFit=%(backgroundFit)s,\n"
|
|
1887
1887
|
" blendMode=%(blendMode)s, useFBO=%(useFBO)s,\n"
|
|
1888
|
-
" units=%(Units)s
|
|
1888
|
+
" units=%(Units)s,\n"
|
|
1889
1889
|
" checkTiming=False # we're going to do this ourselves in a moment\n"
|
|
1890
1890
|
" )\n"
|
|
1891
1891
|
"else:\n"
|
|
@@ -1914,12 +1914,6 @@ class SettingsComponent:
|
|
|
1914
1914
|
)
|
|
1915
1915
|
buff.writeIndentedLines(code % params)
|
|
1916
1916
|
|
|
1917
|
-
# Show/hide mouse according to param
|
|
1918
|
-
code = (
|
|
1919
|
-
"win.mouseVisible = %s\n"
|
|
1920
|
-
)
|
|
1921
|
-
buff.writeIndentedLines(code % allowGUI)
|
|
1922
|
-
|
|
1923
1917
|
# Reset splash message
|
|
1924
1918
|
code = (
|
|
1925
1919
|
"win.hideMessage()\n"
|
|
@@ -2194,12 +2188,17 @@ class SettingsComponent:
|
|
|
2194
2188
|
buff.writeIndentedLines(code)
|
|
2195
2189
|
|
|
2196
2190
|
# Write End Experiment code component
|
|
2197
|
-
for thisRoutine in
|
|
2198
|
-
#
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
thisComp
|
|
2202
|
-
|
|
2191
|
+
for thisRoutine in self.exp.flow:
|
|
2192
|
+
# write for regular Routines
|
|
2193
|
+
if isinstance(thisRoutine, Routine):
|
|
2194
|
+
for thisComp in thisRoutine:
|
|
2195
|
+
if hasattr(thisComp, "writeExperimentEndCodeJS"):
|
|
2196
|
+
thisComp.writeExperimentEndCodeJS(buff)
|
|
2197
|
+
# write for standalone Routines
|
|
2198
|
+
if isinstance(thisRoutine, BaseStandaloneRoutine):
|
|
2199
|
+
if hasattr(thisRoutine, "writeExperimentEndCodeJS"):
|
|
2200
|
+
thisRoutine.writeExperimentEndCodeJS(buff)
|
|
2201
|
+
|
|
2203
2202
|
code = ("psychoJS.window.close();\n"
|
|
2204
2203
|
"psychoJS.quit({message: message, isCompleted: isCompleted});\n\n"
|
|
2205
2204
|
"return Scheduler.Event.QUIT;\n")
|