Loading... <div class="tip share">请注意,本文编写于 440 天前,最后修改于 437 天前,其中某些信息可能已经过时。</div> <div class='handsome_aplayer player-content' data-preload="auto" data-autoplay="false" data-listMaxHeight="340px" data-order="list"> <div class="handsomePlayer-tip-loading"><span></span> <span></span> <span></span> <span></span><span></span></div><div class="handsome_aplayer_music" data-id="35470288" data-server="netease" data-type="song" data-auth="74c5ecf3ea9d8f536743aef9e4114793"></div> </div> ## 前言 > 容我想想要从哪开始写啊…… 前一阵子因为各种机缘巧合,接触到了 PsychoPy 这个工具,而且真用它完整做完了一整套从设计到分析数据出结论的实验流程。用完之后的感受是:比 EPrime 高到不知道哪里去了.jpg 在这之后,又因为一些其他的机缘巧合,就有了写这篇指南的想法,希望能帮助一些后来的朋友了解、使用 PsychoPy。 所以,这篇文章意在使 0 基础的朋友快速了解、上手使用 PsychoPy,并掌握使用 PsychoPy 完整进行一次实验的能力。 开始吧! ## 0. 什么是 PsychoPy? > 能吃吗?怎么吃?好不好吃? 当然在具体进入教程之前,首先要介绍一下这个工具本身。 PsychoPy 是一款基于 Python 开发的心理学工具包,旨在提供一套足够强大、现代化的工具,帮助各界心理学者设计、开展实验。 略去开发者啊,开发历程之类的东西,直接跳到“PsychoPy 的特殊之处”,也就是**为什么我们会选择 PsychoPy** 的问题上: 1. 它的能力足够强大:从简单的文本、图像到视频、量表;从静止刺激到动态刺激,从普通的按键反应到滑动条、输入框等交互式程序,甚至还支持脑电眼动仪等复杂实验仪器;  2. 它上手足够简单:对普通用户,提供现代化的图形设计界面,实验流程一目了然、简单明了;对高级开发者,也提供了代码编辑界面,可轻松修改程序;  如果只有这两个优势的话,PsychoPy 只是一个大号的、现代化的 E-Prime ~~(其实本来也是)~~,真正让它不同于 E-Prime 的是下面三点: 3. 它具有良好的跨平台兼容性与可迁移性:底层架构基于 Python,可以在任何搭载了 Python 的平台上使用、运行,不会遇到奇奇怪怪的兼容性问题 ~~(反观 E-Prime 程序,随便换台电脑就运行不起来了)~~;  4. 它拥有运行线上实验的能力:PsychoPy 可以将程序转译为 Javascript 脚本,从而可以在浏览器中在线运行实验程序;  5. 它是开源的自由程序:无需任何门槛与费用,任何人均可使用;如有需要,任何人均可直接修改其底层代码;  与其他目前常用且流行的心理学实验开发工具进行比较的话,大概是这样: | 工具名 | 上手难度 | 可迁移性 | 自由度 | 在线实验 | | :--------: | :------------------------------: | :--------------------: | :------: | :------------: | | MATLAB | 高(纯代码环境) | 中(需配置环境) | 高 | 难以实现 | | E-Prime | 中 (可视化编辑器+代码编辑器) | 低(换个机器就炸了) | 低 | 几乎无法实现 | | Inquisit | 高(纯代码环境) | 高(仅需浏览器插件) | 中 | 完全支持 | | jsPsych | 高(纯代码环境) | 高(基于网页开发) | 高 | 完全支持 | | PsychoPy | 中(可视化编辑器+代码编辑器) | 高(需配置环境) | 高 | 完全支持 | 当然,上面这张表取决于我的主观经验,可能有失偏颇,大致做个参考。 总而言之,如果你满足以下的条件的话: * 想要使用相对简单的办法制作实验程序 * 想要使用较为轻量的实验环境 ~~(MATLAB 实在是太大了)~~ * 想要实现跨平台的线上实验 * 不希望与底层代码结构打太多交道 我会建议你尝试 PsychoPy。 ## 1. 安装并配置 PsychoPy > 那么,这么好的东西,在哪里才能买得到呢? 既然到了这里,可能得先说: <div class="tip inlineBlock warning"> 本文无意成为一篇全面详尽的 PsychoPy 指南,本文作者也并不具有这样的实力与能力。 本文希望做到的是能让阅读者快速了解这一工具,可以在较短时间内掌握其使用方法。 如在开发、使用过程中遇到问题,官方文档与搜索引擎是更好的资料来源。 </div> 在最开始,先介绍几个 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 不等)。  <div class="tip inlineBlock info"> 如果希望对接国内脑岛平台(https://naodao.com/)进行在线实验,推荐下载 `2021.2.3` 版本,该版本为脑岛支持的最高版本。 如果无此类需求,仅在本地或自建网站开展实验,则推荐下载带有 `latest`标签的最新版(图上为 `2022.2.2`)。 ~~我反正两个版本都装了,~~ 如果同时安装多个版本的 PsychoPy,请注意区分安装文件夹。 </div> 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 <div class="tip inlineBlock success"> 制作一个简单的测试程序。 运行程序后,在第一个页面显示“Hello, world!”。 按空格进入第二个页面,在第二个页面显示“Welcome to psychology!”。 </div> 程序已经默认提供了一个 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(允许的按键):仅接收在此处定义的按键,其他按键会被忽略。 <div class="tip inlineBlock info"> 在 Allowed keys 一栏,前面带有一个固定的`$`符号。 在 PsychoPy 里,`$`符号代表其后续的内容为 Python 语法,程序将使用 Python 进行解析。可以看到,这里的按键定义是字符串的形式。 后续还会用到它,此处仅作讲解。 </div> 同样,将 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 查看:  一般情况下,这三个文件就足够我们使用了。 <div class="tip inlineBlock info"> 以上是在本地使用 Python 环境运行程序时会产生的数据文件。 如果要在线上进行实验,情况会变得完全不同,线上实验环境下程序只会生成 .csv 文件,后续将会详细说明。 同时,.psydat 是一个需要使用 Python 才能解析的文件。根据官方文档,一般在“常规数据文件没有保存所有数据(通常是忘了设置)”的情况下才会用到它。读取这个文件的方法请参考:https://www.psychopy.org/general/dataOutputs.html#psychopy-data-file-psydat。 </div> 打开最新的那个 .csv 文件,然后……  在数据文件中,每一行对应了实验中的一个 Routine;这一行里的数据则表明了“在这个 Routine 里发生了什么”。 这里的每一个变量都单独成列,比如`hello.started`的意思是名为`hello`的组件在什么时候加载成功,而`key_resp.rt`则是名为`key_resp`的组件记录下的反应时。大致知道就行了,在这里还不需要详细了解。 而文件后面的`participant` `session` `date` `expName` `psychoPyVersion` `frameRate`这些变量就是实验的元数据,记录了被试、被试编号、实验日期、实验名、程序版本、显示器帧率等数据。 还是挺直观的,不是吗? ## 5. 认识 PsychoPy——Loop 篇 > 门前大桥下,游过一群鸭,快来快来数一数,二四六七八? 来做一点比较像真正的心理学实验的东西吧! ### 实验二:简单认识 Loop <div class="tip inlineBlock success"> 创建一个程序,包含一个指导语页面、十个试次、一个结束语页面。 在每个试次里,屏幕上首先呈现 200 毫秒注视点,随后空屏 300 毫秒,再出现字母 A,被试需要在出现 A 之后按键盘上的 A 进入下一个试次。 </div> 相信大家也都知道我想介绍什么了,这里就讲得简略一点了。我们首先创建三个 Routine,分别是`Intro`、`trial`和`Ending`。 随后,我们在 `Intro`和`Ending`中加入一些指导语,并设置好按键反馈。 <div class="tip inlineBlock info"> 相信你也注意到了,因为变量名不能重复的关系,如果不加以控制,整个程序的变量名就会非常混乱。 又因为变量名直接关系到我们进行数据分析时的质量,因此我建议起名时起一些易于分辨的名称。 以我自己的方法举例,假如我的 routine 叫`Intro`,那么我就会把里面的文本称作`Intro_text`,把键盘组件称作`Intro_key_resp`,这样既可以知道组件是什么,也知道组件对应的 routine 是什么。 </div> 接下来我们看向`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 就能代表的。 ### 实验三:注入灵魂——条件文件的载入 <div class="tip inlineBlock success"> 在实验二的基础上,修改实验。 试次包含五个小写字母 a,五个大写字母 A,被试看到 a 时按下 F 键,看到 A 时按下 J 键。如果按错,则记录为错误反应,也进入下一个试次。 </div> 我想了很久要怎么不突兀地引入这个“条件文件”的存在,但是想来想去都觉得很突兀,所以直接还是直接说了( 条件文件是 PsychoPy 主程序外的一个文件,可以被 PsychoPy 读取,用以创建实验内需要用到的各种条件。 而条件文件支持的格式是——.csv 或 .xlsx。 打开 Excel 吧。  条件文件的第一行是变量名,后面的每行都代表一个条件。 这里的条件文件相对简单,所以我们可以手写。我在这里写了三列:`stimuli`即刺激,`correct`即正确的答案,`type`即类型。除开第一行,一共有 10 行,也就是 10 个条件。 <div class="tip inlineBlock info"> 添加额外的分类变量与标记变量对分析数据非常有帮助。 PsychoPy 会将条件文件的每一列都作为一个变量读入,因此添加分类变量可以帮助你快速从数据文件中筛选数据。 </div> 把它保存为`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 就行了。 不过都到这里了,你肯定也想到了……  两个条件,每个条件重复五次,效果也是一样的。完全可以。 <div class="tip inlineBlock info"> 其实不一样。取决于顶上 loopType 的设定。 loopType 分为五种,假设我们现在有 [a, b, c] 三种条件,每种条件重复三次(nReps = 3),则有: * random:随机,但在条件文件内不会重复 * 会出现类似 [<U>a b c,</u> <u>b c a,</u> <u>c a b</u>] 的序列,在每组 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 方法读取。 </div> 到这里,你已经成功使用 PsychoPy 编写了一个看起来很心理学的实验程序 ~~(虽然不知道能拿来干嘛)~~。可以为自己鼓鼓掌,花了半个小时一个小时两个小时看到这里也辛苦了( 最后做点总结吧。 ## 7. 小结 > 下课了! PsychoPy 编程建立于三个基础:Routine、Loop、条件文件。 通过串联 Routine 和 Loop,可以把实验的流程勾画出来,安排各个试次、各个刺激的呈现顺序;而屏幕上具体呈现什么,从设备上接收什么,则可以通过外置的条件文件进行定义与管理。 ## 后记 > 我先睡会.jpg 怎么小结就两句话啊,总感觉得多写点,但是不知道要写什么了。 作为一个入门篇的内容,这篇文章主要就是介绍最基本的“怎么用”的问题,如果说读到这里让你感觉“啊,我的脑子会了”,那其实这篇文章就成功了。 当然,脑子会了不代表手会了,更多的东西需要在实践中逐渐摸索出来,所以如果想真正掌握这个工具——还得真用起来才知道。 写到这里我的字数统计器告诉我我已经写了一万三千个字了,太长了,所以我们把其他的一些东西——随机时间啊、线上实验啊、数据分析啊,都安排到后面吧。 <div class="preview"> <div class="post-inser post box-shadow-wrap-normal"> <a href="https://www.bcmonomial.xyz/shelf/PsychoPy_Tutorial_Advanced.html" target="_blank" class="post_inser_a no-external-link no-underline-link"> <div class="inner-image bg" style="background-image: url(https://www.bcmonomial.xyz/usr/uploads/2022/07/3178193729.png);background-size: cover;"></div> <div class="inner-content" > <p class="inser-title">PsychoPy 简明扼要上手指南——进阶篇</p> <div class="inster-summary text-muted"> 开始之前建议在基本掌握 PsychoPy 操作后阅读本文。可参考前述的入门篇指南。前言前略,这一篇主要是作为 Ps... </div> </div> </a> <!-- .inner-content #####--> </div> <!-- .post-inser ####--> </div> 最后修改:2022 年 07 月 22 日 © 允许规范转载 赞 8 虽然点赞什么的确实没什么意义但是也可以点一个再走呗?(