基于Psychopy的语音感知实验操作示例
PsychoPy 是一个功能强大的工具,用于创建和运行心理学实验。它提供了直观的图形用户界面(Builder)和灵活的编程环境(Coder),使得无论是没有编程经验的初学者,还是需要高级控制的研究者,都能够方便地设计复杂的实验。本文将介绍PsychoPy的主要页面及其功能,并且给出一个基于Psychopy的语音感知实验操作示例。
页面介绍
1. 启动PsychoPy
当你启动PsychoPy时,会看到以下界面:
- Builder视图:用于图形化地创建实验。
- Coder视图:用于编写自定义代码。
- Runner视图:用于运行和监控实验。
默认情况下,PsychoPy会打开Builder视图。
2. Builder视图
Builder视图是PsychoPy的核心功能区,提供了一个直观的图形化界面,用户可以通过拖放组件来设计实验。
2.1 工具栏
工具栏提供了一些常用功能的快捷方式。
2.2 流程(Flow)
流程区域显示实验的整体结构,通过将例程或循环 拖放到流程中,用户可以设置实验的顺序和循环。每个例程代表实验中的一个步骤或阶段。
2.3 例程编辑器(Routine Editor)
例程编辑器用于设计每个实验阶段的具体内容。用户可以在例程中添加各种刺激和响应组件,例如文本、图片、声音、键盘响应等。每个组件都有详细的属性设置,可以精确控制其显示和行为。
3. 主要组件介绍
PsychoPy的Builder视图提供了多种组件,用于创建不同类型的实验内容。以下是一些常用组件的介绍:
- 文本组件(Text)用于在屏幕上显示文本。
- 图片组件(Image)用于在屏幕上显示图片。
- 声音组件(Sound)用于播放声音。
- 键盘响应组件(Keyboard)用于记录参与者的按键响应。
- 代码组件(Code)用于设置一些复杂的实验逻辑。
这些组件一般都涉及以下基础设置:
名称(Name):组件的名称,用于在代码和其他设置中引用该组件。
- 起始时间(Start):
- 时间(s):组件开始的时间,以秒为单位。
- 结束时间(Stop):
- 持续时间(s):组件的持续时间。
在此处不展开叙述各个组件的特性设置,在后文操作步骤中会详细叙述。
屏幕单位
在PsychoPy中,坐标系统的设置取决于你选择的单位和实验的需求。PsychoPy支持多种单位系统,包括像素('pix')、归一化('norm')、高度('height')和度('deg')等,每种单位系统对坐标的解释都有所不同。下面是关于这些单位系统及其坐标设置的一些详细信息:
-
像素 ('pix'):
- 这是最直接的单位,坐标原点在窗口中心,向右和向上为正方向。例如,一个1920x1080的窗口中,原点为(0, 0),右上角为(960, 540)。
-
归一化 ('norm'):
- 在这个单位系统中,坐标原点同样位于窗口中心,但每个轴的范围从-1到1,不论窗口的实际尺寸。例如,右上角的坐标是(1, 1),左下角是(-1, -1)。
-
高度 ('height')⭐:
- 这个单位基于窗口的高度,保持高度为1单位,宽度根据窗口比例自动调整。原点位于窗口中心,顶部中心坐标为(0, 0.5)。
-
度 ('deg'):
- 用于视觉实验,假设观察者位于屏幕的正中央,屏幕距离适当。单位是视觉角度,常用于视觉刺激的呈现。
设置坐标时,你可以根据实验的设计和需要选择最合适的单位。例如,如果你正在做一个视觉搜索任务,可能会使用'pix'或'deg'单位以获得更精确的控制。一般来说,使用height或norm对不同屏幕的兼容性最好。
使用 norm
或height
作为单位时,字符高度设置为0.05表示字符高度为屏幕高度的5%。norm
单位通常用于定义相对于屏幕尺寸的位置和尺寸,使得实验在不同分辨率下具有一致的比例。
更改默认单位
如果你需要更改默认单位,可以按照以下步骤操作:
-
在PsychoPy Builder中:
- 打开实验设置(Experiment Settings)。
-
在“通用” 选项卡中,你可以找到“Units” 设置。
-
从下拉菜单中选择所需的单位,本案例选择
height
。
收集参与者信息
设置实验信息对话框
-
打开实验设置
- 在PsychoPy Builder模式中,点击顶部菜单栏中的“实验设置”按钮(齿轮图标)。
-
添加实验信息字段
-
在弹出的对话框中,找到“实验信息”部分。
-
在“Field”列中添加需要收集的信息字段名称,例如“sex”(性别)和“age”(年龄)。
-
在“默认”列中可以设置默认值或者留空。
配置实验信息字段
-
性别字段设置
- 在“Field”中添加
sex
,表示需要收集被试的性别。 - 默认值可以留空。
- 在“Field”中添加
-
年龄字段设置
- 在“Field”中添加
age
,表示需要收集被试的年龄。 - 默认值同样可以留空。
- 在“Field”中添加
实操:一个辨认实验的预实验流程
本实验旨在研究参与者在不同刺激条件下的反应时间。实验流程包括指示页面、凝视点显示、实验刺激呈现和反馈阶段。以下是实验各个步骤的详细描述。
流程概述
- Instruction 1 (指示页面):
- 参与者首先看到一段指示文字,解释实验任务并指导他们按空格键开始实验。
- 这个阶段使用了文本刺激(
instruction_1
)和键盘响应(key_intro_start
)来控制实验开始。
- Fixation Point (注视点):
- 在每个实验试次开始前,屏幕中央会显示一个凝视点“+”,确保参与者的注意力集中。
- 这个阶段持续2秒左右,包含一个声音提示(
beep
),视觉凝视点(fixation
)和一个预实验声音(sound_pre
)。
- Pre-experiment Trials (预实验试次):
- 在正式实验开始前,参与者会进行一些预实验试次,以熟悉实验流程和任务。
- 这一阶段包括两个文本刺激(
leftText_pre
和rightText_pre
)分别显示在屏幕的左侧和右侧,以及一个键盘响应(practice_resp
)来记录参与者的反应。 - 代码组件(
code_pre
)用于计算和评估参与者的反应时间,并生成反馈信息。
- Feedback (反馈):
- 每个试次结束后,参与者会收到基于其反应时间的反馈。
- 反馈阶段持续1秒,通过文本刺激(
feedback
)呈现反馈信息,会显示“按键太慢了”或“很棒”
- familiar_check
- 询问参与者是否已经熟悉流程了流程,如果参与者已经熟悉,则继续后面的实验,如果不熟悉,则继续进行预实验循环。
详细步骤
1.创建新的实验
- 打开PsychoPy。
- 创建一个新的实验文件,可以命名为
demo.psyexp
。
2.创建说明页面
- 在
Flow
标签下,点击插入例程
按钮,命名为instruction1
。 - 在
instruction1
例程中,添加一个文本刺激(Text)和一个键盘响应(Keyboard)。
-
文本刺激的基础设置:
-
名称
: instruction_1 -
文本
: "(自行设置你的实验介绍)……如果准备好了,请按空格键开始,开始练习。" -
起始
: 0.0 -
终止-持续时间
: 设置为空白(空白表示持续到按键响应为止)
文本刺激的布局设置: -
位置
[x, y] (Position [x, y]): 这里显示的值是 (-0.5, 0),表示刺激在屏幕上的横纵坐标位置。横坐标 (x) 为 -0.5,表示相对于屏幕中心向左移动0.5个单位。纵坐标 (y) 为 0,表示不在垂直方向上移动。单位取决于 “Spatial units” 设定。 -
Spatial units
: 这里的选项为 “从实验设置 ”,表示位置的单位是根据实验的全局设置来决定的。常见单位有像素 (pixels)、度 (degrees)、norm (标准化坐标) 等。 -
朝向
(Orientation): 这里的值为 0,表示刺激没有旋转,即保持初始方向。 -
换行宽度
(Wrap width): 这里的值为 0.5,通常用于文本刺激,表示文本在屏幕上换行的宽度。 -
翻转(镜像)
(Flip): 这里的选项为 “None”,表示不对刺激进行镜像翻转。
后文各种组件的“布局”设置与此相同,后文中不再详细解释。 -
键盘响应:
-
Name
: key_intro_start -
Start
: 0.0 -
Force end of Routine
: 勾选,表示操作后就结束该例程,进入下个页面。 -
允许的按键
:'space',即空格键。
3.创建注视点页面
在 Flow
标签下,点击 插入例程
按钮,命名为 Fixation_point
。
添加“beep”组件
- 在右侧页面选择“Sound组件”。
-
将新添加的声音组件命名为“beep”。
-
设置“beep”组件的属性:
- 名称(Name):组件的名称“beep”。
- 起始时间(Start):
- 时间(s):在本例中,beep组件从0秒开始。
- 结束时间(Stop):
- 持续时间(s):在本例中,beep组件持续1秒。
- 声音:设置声音的频率或选择声音文件。在本例中,输入200,即输入一个200 Hz的声音。
- 同步屏幕开始(Sync start with screen):勾选后,声音组件将与屏幕刷新同步开始,从而提高实验结果的准确性和一致性。
添加“sound_pre”组件
- 在右侧页面选择“Sound组件”。
- 将新添加的声音组件命名为“sound_pre”。
- 设置“sound_pre”组件的属性:
- 起始(s):1.1
- 持续(s):1.2
- 声音文件:$sound(需要在循环中的条件文件中定义这些变量,见后文)。
- 勾选“Sync start with screen”选项。
添加“fixation”组件
- 在右侧页面选择“Polygon组件”。
- 将新添加的图形组件命名为“fixation”。
- 设置“fixation”组件的属性:
- 起始时间(s):0.0
- 持续时间(s):2.3,这里的数值和音频长度有关。
- 形状:组件的形状,可以选择十字(Cross)、圆点(Dot)等。在本例中,选择的是十字。
例程概览
4.创建预实验例程
在 Flow
标签下,点击 插入例程
按钮,命名为 Pre_experiment
。
添加“leftText_pre”组件和“rightText_pre”组件:
-
在右侧页面选择“Text组件”。
-
将新添加两个文本组件,分别命名为“leftText_pre”和“rightText_pre”。
-
设置它们的属性:
- 名称(Name):组件的名称,。
- 起始时间(Start Time):0.0 秒。
- 持续时间(Duration):
- 文本内容(Text):$text1 和 text2(需要在循环中的条件文件中定义这些变量,见后文)。
添加“practice_resp”组件:
- 在右侧页面选择“Keyboard组件”。
- 设置它的属性:
- 名称(Name):practice_resp,
- 起始时间(Start Time):0.0 秒。
- 持续时间(Duration):设置为空。
- 允许的按键(Allowed keys):'f', 'j'。
- 结束例程(Force end routine):勾选后,当按下允许的按键时,例程将结束。
添加代码组件
- 添加“code_pre”组件:
-
在右侧页面选择“Code”
-
将新添加的代码组件命名为“code_pre”。
-
在“结束例程(End routine)”选项卡中,输入以下代码以检查响应时间并设置反馈文本:
-
# 检查practice_resp.rt是否为列表
if isinstance(practice_resp.rt, list):
rt = practice_resp.rt[0] # 获取第一个反应时间
else:
rt = practice_resp.rt # 直接使用反应时间
# 检查反应时间是否小于或等于4秒
if rt is not None and rt <= 4.0:
feedback_text = "很棒" #变量feedback_text会在后面的feedback页面中引用。
else:
feedback_text = "太慢了"
例程概览
5.创建feedback页面
-
在
Flow
标签下,点击插入例程
按钮,命名为feedback
。 -
在右侧页面选择“Text组件”。
-
设置属性:
例程概览
6.创建小循环trials_pre
在 Flow
标签下,点击 插入循环
按钮,命名为 trials_pre
,包括以下内容:
- 名称(Name):用于指定该循环的名称,方便在代码和其他设置中引用该循环。
- 示例:trials_pre
- 循环类型(Loop type):用于选择循环的类型,有以下选项:
- 顺序(sequential):按顺序进行循环。
- 随机(random):随机选择条件进行循环。
- 完全随机(fullRandom):每次完全随机选择条件。
- 本例选择random
- Is Trials(in trials):用于指定该循环是否为试验循环。勾选后,PsychoPy会将该循环视为试验循环,每一行条件对应一个试验。
- 示例:勾选
- 循环次数(Number of repeats):用于设置循环应重复的次数,本例输入1次,因为是预实验阶段,只是让被试熟悉步骤,不需要循环很多次。
- 选择行(Selected rows):用于指定要选择的行。可以输入特定的行号或行号范围。如果为空,则选择所有行。如输入
0:5
表示选择第0到第4行。 - 随机种子(Random seed):用于设置随机种子,确保实验的随机选择可以重复。如果为空,则每次运行实验时随机选择会不同。
- 条件(Conditions):用于选择包含实验条件的文件。通常是一个Excel文件或CSV文件,其中每一行定义了一组试验条件。本案例填写的是lib/condition/pre_experiment1.xlsx
本案例的条件文件 pre_experiment1.xlsx
,其中包含以下列:
text1
:左侧文本的内容,所以leftText_pre填入$text1text2
:右侧文本的内容,所以rightText_pre填入$text2sound
:声音文件的路径,所以sound_pre里填入了$sound。并且可以观察到,sound里面是声音文件的路径,而且使用了相对路径。sound_type
:声音类型(这一列没有用到,和本次实验无关。但是最终数据文件导出的时候也会随之导出,有时候这样做可以减少后期分类的工作量。)
关于相对路径
在之前的步骤中,我们会发现条件文件和声音文件都使用了lib文件夹,这里涉及相对路径的格式,也就是引用的文件的路径是相对于你保存的 .psyexp
实验文件所在的目录的。
这是本案例项目文件结构:
可以发现lib和psyexp文件是同级的,此时就可以直接引用类似lib/sound/a10.wav的格式。普遍来说,相对路径有如下格式:
- 当前目录:使用相对路径中的
.
表示当前目录,此处的.
可以省略。- 示例:
./filename.xlsx
- 示例:
- 子目录:如果文件在当前目录的子目录中,使用相对路径从当前目录指向子目录,此处的
.
可以省略,本案例就是这种情况。- 示例:
./subdir/filename.xlsx
- 示例:
- 父目录:使用相对路径中的
..
表示上一级目录,可以用来访问上一级目录。- 示例:
../filename.xlsx
(上一级目录中的文件) - 示例:
../subdir/filename.xlsx
(上一级目录的子目录中的文件)
- 示例:
- 多层目录:可以组合多个相对路径符号访问多层目录。
- 示例:
../../subdir/filename.xlsx
(上两级目录中的子目录中的文件)
- 示例:
使用相对路径的好处是它提高了实验的可移植性,无论是在不同的计算机上还是在不同的文件系统结构中,实验文件都可以正确找到所需的资源文件。确保你的相对路径是基于你的 .psyexp
文件所在的目录的相对位置。
7.添加熟悉度检查例程
在 Flow
标签下,点击 插入例程
按钮,命名为 familiar_check
。
添加“key_resp_check”组件
- 在PsychoPy的时间轴中,右键点击选择“添加”->“键盘响应组件”。
- 将新添加的键盘响应组件命名为“key_resp_check”。
- 设置“key_resp_check”组件的属性:
- 名称(Name):key_resp_check
- 起始时间(Start Time):0.0 秒。
- 持续时间(Duration):保持默认值,表示组件在整个例程中都有效。
- 允许的按键(Allowed keys):'y', 'n'。
- 结束例程(Force end routine):不勾选,以便根据代码组件的判断来结束例程。
添加“text”组件
-
在PsychoPy的时间轴中,右键点击选择“添加”->“文本组件”。
-
将新添加的文本组件命名为“text”。
-
设置“text”组件的属性:
- 名称(Name):text
- 起始时间(Start Time):0.0 秒。组件开始的时间,以秒为单位。
- 持续时间(Duration):保持默认值,表示组件在整个例程中都显示。
- 文本内容(Text):
你是否已经熟悉按键操作? 如果要再练习一遍,请按N。 如果开始正式实验,请按Y。
添加“code_familiar_check”代码组件
-
在PsychoPy的时间轴中,右键点击选择“添加”->“代码组件”。
-
将新添加的代码组件命名为“code_familiar_check”。
-
在“每帧(Each Frame)”选项卡中,输入以下代码以检查按键响应并设置循环控制:
# Each Frame - 选项卡中的代码
# 检查按键响应
keys = key_resp_check.getKeys(['y', 'n'])
# 如果有响应
if keys:
if 'y' in [key.name for key in keys]: # 'y'表示熟悉
trials_familiar.finished = True # 结束大循环
else:
trials_familiar.finished = False # 继续大循环
continueRoutine = False # 结束当前例程
例程概览
大循环
在 PsychoPy Builder 中设置一个外部大循环,包含上文中的预实验循环trials_pre和熟悉度检查familiar_check。即在小循环结束后,进入熟悉度检查阶段,判断是否熟悉操作,如果不熟悉则继续大循环,否则退出大循环并继续后续实验。
在 Flow
标签下,点击 插入循环
按钮,创建外部大循环 trials_familiar
:
- 包含
trials_pre
里的各个例程 和familiar_check
。
- 设置 nReps 为一个很大的数(例如 100)。
步骤7:运行实验
- 在菜单栏中选择
Run
->Run Experiment
或按快捷键Ctrl+R
(Windows)或Cmd+R
(Mac)。 - 实验会开始运行,将看到文本指示、凝视点、实验刺激和反馈。
总结
通过以上步骤,我们创建了一个简单的PsychoPy实验,包含指令页面、凝视点、实验刺激和反馈页面,可以根据实验需求进行进一步扩展和修改。
进阶技巧
音频结束后立刻结束routine(音频长度未知)
在PsychoPy中,要实现音频播放完毕后自动跳转到下一个routine,你需要在当前routine的最后一个组件中设置结束条件为"音频结束"。具体步骤如下:
- 选择音频组件:在你的routine中选择最后一个音频组件(假设是
sound_pre
)。 - 设置音频结束:
- 在
Duration (s)
栏中,不填任何数值。 - 在
Stop
栏中选择Duration
,然后填写音频的实际持续时间。如果你想直接通过音频的结束事件来控制,你可以使用condition
,并设置条件为sound_pre.status == FINISHED
。
- 在
如果你的音频组件没有明确的持续时间,可以按以下步骤设置:
- 在代码组件中设置音频结束条件:
-
添加一个代码组件到routine的最后。
-
在代码组件的
Each Frame
标签中,添加以下代码:if sound_pre.status == FINISHED: continueRoutine = False
-
这段代码会在每一帧检查sound_pre
音频是否播放结束,如果结束则跳转到下一个routine。
- 在
Experiment Settings
中设置End Routine
:- 打开
Experiment Settings
,在End Routine
选项中确保勾选了Force end of Routine on component finish
。
- 打开
只需确保sound_pre
的播放时间和routine的总时间一致,这样在音频播放结束后即可自动跳转。
如果音频长度是未知的,并且需要在 sound_e1
播放结束后立即播放 sound_e2
,可以使用 Python 代码来动态控制这些组件的播放和停止。以下是如何实现的步骤:
- 在 routine 中,添加一个 Code 组件。
- 在 Code 组件中,选择 "Each Frame" 选项卡。
- 输入以下代码:
if t >= sound_e1.status == FINISHED and not sound_e2_played:
sound_e2.play()
sound_e2_played = True
# 停止整个 routine
if sound_e2.status == FINISHED:
continueRoutine = False
- 在 "Begin Routine" 选项卡中,初始化
sound_e2_played
变量:
sound_e2_played = False
上述代码解释:
- 在每一帧(
Each Frame
)中,检查sound_e1
是否已经播放结束(sound_e1.status == FINISHED
)。 - 如果
sound_e1
播放结束且sound_e2
尚未播放,则播放sound_e2
并将sound_e2_played
设置为True
。 - 如果
sound_e2
播放结束(sound_e2.status == FINISHED
),则将continueRoutine
设置为False
,从而结束这个 routine。
通过这种方式,可以确保在 sound_e1
播放结束后立即播放 sound_e2
,并在 sound_e2
播放结束后结束这个 routine。