前言
容我想想要从哪开始写啊……
前一阵子因为各种机缘巧合,接触到了 PsychoPy 这个工具,而且真用它完整做完了一整套从设计到分析数据出结论的实验流程。用完之后的感受是:比 EPrime 高到不知道哪里去了.jpg
在这之后,又因为一些其他的机缘巧合,就有了写这篇指南的想法,希望能帮助一些后来的朋友了解、使用 PsychoPy。
所以,这篇文章意在使 0 基础的朋友快速了解、上手使用 PsychoPy,并掌握使用 PsychoPy 完整进行一次实验的能力。
开始吧!
0. 什么是 PsychoPy?
能吃吗?怎么吃?好不好吃?
当然在具体进入教程之前,首先要介绍一下这个工具本身。
PsychoPy 是一款基于 Python 开发的心理学工具包,旨在提供一套足够强大、现代化的工具,帮助各界心理学者设计、开展实验。
略去开发者啊,开发历程之类的东西,直接跳到“PsychoPy 的特殊之处”,也就是为什么我们会选择 PsychoPy 的问题上:
它的能力足够强大:从简单的文本、图像到视频、量表;从静止刺激到动态刺激,从普通的按键反应到滑动条、输入框等交互式程序,甚至还支持脑电眼动仪等复杂实验仪器;
它上手足够简单:对普通用户,提供现代化的图形设计界面,实验流程一目了然、简单明了;对高级开发者,也提供了代码编辑界面,可轻松修改程序;
如果只有这两个优势的话,PsychoPy 只是一个大号的、现代化的 E-Prime (其实本来也是),真正让它不同于 E-Prime 的是下面三点:
它具有良好的跨平台兼容性与可迁移性:底层架构基于 Python,可以在任何搭载了 Python 的平台上使用、运行,不会遇到奇奇怪怪的兼容性问题
(反观 E-Prime 程序,随便换台电脑就运行不起来了);它拥有运行线上实验的能力:PsychoPy 可以将程序转译为 Javascript 脚本,从而可以在浏览器中在线运行实验程序;
它是开源的自由程序:无需任何门槛与费用,任何人均可使用;如有需要,任何人均可直接修改其底层代码;
与其他目前常用且流行的心理学实验开发工具进行比较的话,大概是这样:
工具名 | 上手难度 | 可迁移性 | 自由度 | 在线实验 |
---|---|---|---|---|
MATLAB | 高(纯代码环境) | 中(需配置环境) | 高 | 难以实现 |
E-Prime | 中 (可视化编辑器+代码编辑器) | 低(换个机器就炸了) | 低 | 几乎无法实现 |
Inquisit | 高(纯代码环境) | 高(仅需浏览器插件) | 中 | 完全支持 |
jsPsych | 高(纯代码环境) | 高(基于网页开发) | 高 | 完全支持 |
PsychoPy | 中(可视化编辑器+代码编辑器) | 高(需配置环境) | 高 | 完全支持 |
当然,上面这张表取决于我的主观经验,可能有失偏颇,大致做个参考。
总而言之,如果你满足以下的条件的话:
- 想要使用相对简单的办法制作实验程序
- 想要使用较为轻量的实验环境
(MATLAB 实在是太大了) - 想要实现跨平台的线上实验
- 不希望与底层代码结构打太多交道
我会建议你尝试 PsychoPy。
1. 安装并配置 PsychoPy
那么,这么好的东西,在哪里才能买得到呢?
既然到了这里,可能得先说:
本文希望做到的是能让阅读者快速了解这一工具,可以在较短时间内掌握其使用方法。
如在开发、使用过程中遇到问题,官方文档与搜索引擎是更好的资料来源。
在最开始,先介绍几个 PsychoPy 开发过程中最重要的网站:
- PsychoPy 官网:https://www.psychopy.org/
- PsychoPy GitHub 页面:https://github.com/psychopy/psychopy
- PsychoPy 论坛:https://discourse.psychopy.org/
- PsychoPy 问答:https://www.google.com/ (如无法访问,可使用 https://www.bing.com 代替)
首先前往 PsychoPy 项目的 GitHub 发布页(https://github.com/psychopy/psychopy/releases),根据版本与系统下载对应的安装包(通常 400-700 MB 不等)。
2021.2.3
版本,该版本为脑岛支持的最高版本。如果无此类需求,仅在本地或自建网站开展实验,则推荐下载带有 latest
标签的最新版(图上为 2022.2.2
)。
我反正两个版本都装了, 如果同时安装多个版本的 PsychoPy,请注意区分安装文件夹。
Windows 与 MacOS 环境下,PsychoPy 安装时会自动安装独立的 Python 环境,因此无需额外配置,安装完成后开箱即用。如果是 Linux 用户,请参考官方文档(https://www.psychopy.org/download.html)进行安装与配置。
安装完毕,打开 PsychoPy,你会看到如下的界面:
2. 认识 PsychoPy——界面篇
这是啥?那是啥?我是啥?
随着这个窗口出现的应该还有两个窗口。这三个窗口分别是:
- PsychoPy Builder:图形化编辑界面,之后要讲的大部分的操作都会在这里完成;
- PsychoPy Coder:代码编辑界面,有需要时,可以在这里加载代码,进行更加直接的修改;
- PsychoPy Runner:程序运行器,在本地运行程序时,会通过它记录程序中发生的所有事件,并输出日志。
我们绝大多数操作都会在 Builder 里完成,所以我们先把目光看向 Builder。
- ① 为操作栏,和其他软件里顶上的按钮类似,这些都是针对文件本身的操作,包括新建、保存、调整设置、运行等功能;
- ② 为 Routines 面板,在这里会显示当前 Routine 的所有组件,在后面的章节中会详细介绍;
- ③ 为 Components 面板,这里列出了 PsychoPy 里可用的所有组件,点击组件即可将其添加到左边的 Routines 面板;
- ④ 为 Flow 面板,这里会显示当前实验的整个流程。
整个界面非常简洁,相信很多人看到这里就已经知道 PsychoPy 大致的编程流程了,因为界面很直观嘛。
从下面开始,就会涉及到 PsychoPy 编程的核心概念了。
3. 认识 PsychoPy——Routine 篇
道理我都懂,但是我还是不会啊。
从界面上可以看出,PsychoPy 程序是一个“组块式”进行的结构。不同的组块按照时间顺序安排,并在某些条件下循环出现,以此构成整个实验的流程。
其中,图上的每一个彩色小方块就是一个 Routine,而右边灰色的practice
则代表了一处循环(Loop)。
Routine 和 Loop 是构建 PsychoPy 程序的核心概念,所有的实验程序设计都围绕着安排 Routine 和 Loop 展开。
先来认识一下 Routine。来做个小实验吧!有条件的话可以打开 PsychoPy,跟着一起做。
实验一:简单认识 Routine
运行程序后,在第一个页面显示“Hello, world!”。
按空格进入第二个页面,在第二个页面显示“Welcome to psychology!”。
程序已经默认提供了一个 Routine,叫做trial
,我们可以就把它作为第一个页面。
首先,向trial
中添加一个文本组件。在右边的 Stimuli 菜单中找到 Text,点击它,会弹出一个设置面板:
- Name(变量名):组件的名字,和其他编程工具一样,只能以字母开头,只能包含字母、数字、下划线,并且整个程序中不能重复;
- Start(开始时间):该组件从什么时候开始加载,默认为 0(Routine 开始时加载);
- Stop(结束时间):该组件持续多少时间,默认为 1(刺激持续 1 秒),留空表示不结束;
- Text(文本内容):文本组件的内容。
另外,Expected start 和 Expected duration 表示你预估的开始时间和持续时间,填写后对程序运行没有影响,可以作为笔记使用。
将 Name 设置为 hello
,Stop 一栏留空(不填写任何内容),将 Text 中的内容改为Hello, world!
,点击 OK,一个名叫 hello 的组件就会出现在你的界面上:
接下来,我们添加第二个 routine。点击 Insert Routine 按钮,选择(new),输入welcome
作为名称,就新建了一个名为 welcome 的 routine。
但是,现在它并没有出现在我们的 Flow 面板中。你还需要手动指定它的位置(也就是图上的灰点,会跟随你的鼠标移动)。
在trial
的后面单击它,它就被插入到了trial
后面。和前面一样,我们设置一个文本组件,就不重复展示了。
接下来,找个地方保存一下你的实验文件(控制栏里的 💾 Save current experiment file 按钮),然后点击 ▶ Run experiment,程序跑起来了!
……然后你发现不管怎么按,你都没法进入下一页。恭喜你,被我坑了(
很简单,因为我们压根还没设置键盘反馈,程序不知道我们按了空格键。
按 ESC 强制退出实验程序,回到 Builder,往trial
里面新增一个 Keyboard 组件(在 Responses 分类里)。
- Name、Start、Stop:同理,略;
- Force end of Routine(强制 Routine 结束):默认勾选,当接收到符合条件的反应时结束 routine,进入下一步;
- Allowed keys(允许的按键):仅接收在此处定义的按键,其他按键会被忽略。
$
符号。在 PsychoPy 里,$
符号代表其后续的内容为 Python 语法,程序将使用 Python 进行解析。可以看到,这里的按键定义是字符串的形式。
后续还会用到它,此处仅作讲解。
同样,将 Stop 一栏清空,将 Allowed keys 改成只剩下'space'
一项,然后单击 OK。
你肯定猜到了,为了正常结束程序,在welcome
里面也需要一个键盘组件,如法炮制即可。
那么,再次运行程序,这次就应该一切正常了——
按两下空格,程序就应该正常退出了。
恭喜你,写完了第一个 PsychoPy 程序!
4. 认识 PsychoPy——文件篇
菜做好了,盘子呢?
刚搞了这么多,先休息一下。不妨趁现在打开你保存实验程序的文件夹,看看里面都有什么:
当然我忘了给实验文件取名字了,所以这里是 untitled(未命名)。目前,这个文件夹里有三个东西:
- untitled.psyexp 文件:PsychoPy 的程序文件,也就是你刚刚编辑的东西;
- untitled.lastrun.py 文件:刚刚运行实验时,PsychoPy 编译的 Python 脚本代码,每次运行都会更新一次;
- data 文件夹:储存了所有运行时的数据,包括我们刚刚试运行的那几次;
点开 data 文件夹,会出现三类文件:
- .csv 文件:大家喜闻乐见的表格文件(或者更严谨地说,“逗号分隔符文件”),保存了实验过程中产生的各种变量和对应的值;
- .log 文件:日志文件,记录了程序运行期间发生的所有事件;
- .psydat 文件:PsychoPy 独有的数据文件,将实验程序和其中的内容直接作为 Python 对象保存下来,最大限度地保留了原始数据。
当然,我这里调整过设置,各位可能会有其他文件出现,具体的设置可以在 Builder 窗口里点击 ⚙️ Edit experiment settings 按钮,选择 Data 查看:
一般情况下,这三个文件就足够我们使用了。
如果要在线上进行实验,情况会变得完全不同,线上实验环境下程序只会生成 .csv 文件,后续将会详细说明。
同时,.psydat 是一个需要使用 Python 才能解析的文件。根据官方文档,一般在“常规数据文件没有保存所有数据(通常是忘了设置)”的情况下才会用到它。读取这个文件的方法请参考:https://www.psychopy.org/general/dataOutputs.html#psychopy-data-file-psydat。
打开最新的那个 .csv 文件,然后……
在数据文件中,每一行对应了实验中的一个 Routine;这一行里的数据则表明了“在这个 Routine 里发生了什么”。
这里的每一个变量都单独成列,比如hello.started
的意思是名为hello
的组件在什么时候加载成功,而key_resp.rt
则是名为key_resp
的组件记录下的反应时。大致知道就行了,在这里还不需要详细了解。
而文件后面的participant
session
date
expName
psychoPyVersion
frameRate
这些变量就是实验的元数据,记录了被试、被试编号、实验日期、实验名、程序版本、显示器帧率等数据。
还是挺直观的,不是吗?
5. 认识 PsychoPy——Loop 篇
门前大桥下,游过一群鸭,快来快来数一数,二四六七八🎶
来做一点比较像真正的心理学实验的东西吧!
实验二:简单认识 Loop
在每个试次里,屏幕上首先呈现 200 毫秒注视点,随后空屏 300 毫秒,再出现字母 A,被试需要在出现 A 之后按键盘上的 A 进入下一个试次。
相信大家也都知道我想介绍什么了,这里就讲得简略一点了。我们首先创建三个 Routine,分别是Intro
、trial
和Ending
。
随后,我们在 Intro
和Ending
中加入一些指导语,并设置好按键反馈。
又因为变量名直接关系到我们进行数据分析时的质量,因此我建议起名时起一些易于分辨的名称。
以我自己的方法举例,假如我的 routine 叫Intro
,那么我就会把里面的文本称作Intro_text
,把键盘组件称作Intro_key_resp
,这样既可以知道组件是什么,也知道组件对应的 routine 是什么。
接下来我们看向trial
,在里面设置注视点、空屏和刺激:
注视点trial_fixation
从trial
开始时呈现,持续 0.2 秒;刺激条件trial_stimuli
与按键反馈trial_key_resp
都从 0.5 秒时开始,不限持续时间。
那么接下来,点击Insert Loop
插入循环:
- Name(变量名):略;
- loopType(循环类型):在循环中,刺激条件如何呈现,此处暂时不设置;
- Is trials(是试次):这个循环表示的是正式的试次,而不是练习或其他用途,会在数据文件中输出对应的标签;
- nReps(重复次数):循环内的内容重复的次数;
- Selected rows(选择行数):从条件文件中选择一部分行载入,而不是全部载入,此处暂时不设置;
- random seed(随机种子):输入种子,可以使每次程序运行时输出相同的顺序,即“伪随机”——看似随机,但每一次运行都是相同的;
- conditions(条件文件):载入一个文件,将文件内容作为循环运行的条件,此处暂时不设置。
在这里,我们只需要勾上 Is trials,然后将 nReps 设置为10
即可。这样程序应该就能运行了。
在这里,我们创建了一个名为trials
的循环。大功告成!
……是不是少了什么?
6. 真正的心理学实验——条件文件
……我好像不是来学 Excel 和 MATLAB 的?
到这里,你已经明白了 PsychoPy 编程的大致流程,唯一没有解决的问题是:它不是个实验。
真正的心理学实验,包括各种各样的条件、各种各样的随机化,不是简简单单的一个 A 就能代表的。
实验三:注入灵魂——条件文件的载入
试次包含五个小写字母 a,五个大写字母 A,被试看到 a 时按下 F 键,看到 A 时按下 J 键。如果按错,则记录为错误反应,也进入下一个试次。
我想了很久要怎么不突兀地引入这个“条件文件”的存在,但是想来想去都觉得很突兀,所以直接还是直接说了(
条件文件是 PsychoPy 主程序外的一个文件,可以被 PsychoPy 读取,用以创建实验内需要用到的各种条件。
而条件文件支持的格式是——.csv 或 .xlsx。
打开 Excel 吧。
条件文件的第一行是变量名,后面的每行都代表一个条件。
这里的条件文件相对简单,所以我们可以手写。我在这里写了三列:stimuli
即刺激,correct
即正确的答案,type
即类型。除开第一行,一共有 10 行,也就是 10 个条件。
PsychoPy 会将条件文件的每一列都作为一个变量读入,因此添加分类变量可以帮助你快速从数据文件中筛选数据。
把它保存为conditions.xlsx
,和 PsychoPy 程序文件放在同一个文件夹底下。
随后再次进入trials
的编辑面板,单击它,在刚刚被我们忽略的 Conditions 一栏选中我们做好的刺激文件:
可以看到,PsychoPy 读取到了 10 个条件,3 个变量。
下一步是把试次里的刺激改成我们在条件文件里定义好的东西,点击trial
,进入trial_stimuli
的编辑界面:
如图所示,先把文本修改成$stimuli
。
这里是前面提到的$
代表变量的知识。这里告诉程序,每次把变量stimuli
里的内容展示到屏幕上——也就是 a 或者 A。
第二步——这次不坑人了,把右边方框里的 constant 改为 set every repeat,告诉程序“在每次重复时更新”。
如果不这样设置,那么你输入的内容会被视作常量,trial 仅接收第一次的输入,后面的循环和第一次循环显示的内容完全一致。
接下来,修改键盘输入的相关内容,点击trial_key_resp
:
首先修改 Allowed Keys,改为我们需要的:'f','j'
。
第二步,在 Data 中,勾选 Store correct 选项,告诉程序“保存正确结果”。同时在下面的 Correct Answer 里输入$correct
,我们刚刚在条件文件中设置的正确答案。
这样做之后,数据文件中会新增一列,以 0 或 1 的形式保存每次按键的正确与否,可以省去手动对比答案的时间。
点击 OK,大功告成,运行实验试试吧?
……好像还有哪不对?怎么做了十一次实验?后面怎么还有?
相信你已经猜到了。
nReps 实际表示的是,条件文件中每一个条件的重复次数。刚刚的意思是,一共载入了 10 个条件,每个条件重复 10 次,也就是 100 个试次。
因此,把这里改成 1 就行了。
不过都到这里了,你肯定也想到了……
两个条件,每个条件重复五次,效果也是一样的。完全可以。
loopType 分为五种,假设我们现在有 [a, b, c] 三种条件,每种条件重复三次(nReps = 3),则有:
random:随机,但在条件文件内不会重复
- 会出现类似 [a b c, b c a, c a b] 的序列,在每组 3 个条件都呈现过一次之前不会重复
sequential:序列化,会按照条件文件的顺序依次读入
- 即 [a, b, c, a, b, c, a, b, c]
full random:全随机序列,会打乱组间不重复的规则
- 会出现类似 [a, a, b, c, c, b, b, a, c] 的序列,即完全将所有试次全部打乱
- staircase:阶梯化,会在每次循环中产出一个
level
变量,帮助有自适应需求的用户开发程序,使得程序可以动态调节 - interleaved staircases:交叉阶梯化,存在多个变量同时进行变化时使用
对于一般的实验来说,从前两个随机化方法中选择即可。如果实验对试次的呈现顺序、呈现方式、同一刺激连续次数等方面有要求的话,推荐还是用 MATLAB 写一个完整的、随机化的、固定的条件文件,随后用 sequintial 方法读取。
到这里,你已经成功使用 PsychoPy 编写了一个看起来很心理学的实验程序 (虽然不知道能拿来干嘛)。可以为自己鼓鼓掌,花了半个小时一个小时两个小时看到这里也辛苦了(
最后做点总结吧。
7. 小结
下课了!
PsychoPy 编程建立于三个基础:Routine、Loop、条件文件。
通过串联 Routine 和 Loop,可以把实验的流程勾画出来,安排各个试次、各个刺激的呈现顺序;而屏幕上具体呈现什么,从设备上接收什么,则可以通过外置的条件文件进行定义与管理。
后记
我先睡会.jpg
怎么小结就两句话啊,总感觉得多写点,但是不知道要写什么了。
作为一个入门篇的内容,这篇文章主要就是介绍最基本的“怎么用”的问题,如果说读到这里让你感觉“啊,我的脑子会了”,那其实这篇文章就成功了。
当然,脑子会了不代表手会了,更多的东西需要在实践中逐渐摸索出来,所以如果想真正掌握这个工具——还得真用起来才知道。
写到这里我的字数统计器告诉我我已经写了一万三千个字了,太长了,所以我们把其他的一些东西——随机时间啊、线上实验啊、数据分析啊,都安排到后面吧。