2020年8月14日 更新
近日收到多位老师反应,刺激屏幕的按键存在延迟,按键后不会立即显示下一屏的内容。借此机会向大家解释一下问题的原因,顺便加深大家对 DisplayScreen 这个控件的理解。
您可以点击下面的传送门快速导航到更新的内容,但请保证在完全掌握本节内容的前提下再去查看下面传送门的内容。
1. 计算反应时
有机体对刺激的反应并不能在受到刺激的同时就发生,从刺激的呈现到反应的开始之间会有一段时间间距。反应时间(reaction time, RT)就是指从刺激呈现到有机体做出明显的反应所需要的时间。
1.1 执行逻辑
我们会通过一个非常简单的算式来计算各种各样的行为指标,以TextPage
的阅读用时为例:
假设Text Page
在第3秒时呈现,被试在第5秒时按下“空格”结束阅读,那么TextPage
的阅读的阅读时间为 5 - 3 = 2秒,即“阅读用时 = 被试按键的时间 - 刺激出现的时间”。
熟悉编程的人会了解如何通过代码定义和使用变量,大概的过程是:
定义一个名为“XX”的对象
-> 声明“XX”的类型
-> 对”XX“进行赋值
1.2 计算Text Page阅读用时
1.2.1 定义一个名为“RT_of_TextPage”的Variable
首先,我们将一个Variable
控件从控件库中拖入工作区。
修改Label
属性为“RT_of_TextPage”。
1.2.2 声明RT_of_TextPage
的变量类型
常用的变量类型有:
变量类型 | 解释 | 声明Value |
---|---|---|
String | 字符型(文字) | a |
Integer | 整型(整数) | 0 |
Double | 双浮点型(小数) | 0.0 |
Boolean | 布尔型(逻辑是/否) | true |
List | 列表(数组矩阵) | [] |
阅读TextPage
的时间RT_of_TextPage
大概是“xx.xx毫秒”,所以RT_of_TextPage
的数据类型为“Double”。所以我们应当声明RT_of_TextPage
的变量类型为“Double”。
在Variable
的Value
属性中输入什么类型的值,就可以将这个入Variable
声明为什么类型的变量。因此,输入在RT_of_TextPage
的Value
属性中输入“0.0”即可声明RT_of_TextPage
的类型为“Double”。
1.2.3 对RT_of_TextPage
进行赋值计算
对RT_of_TextPage
进行赋值计算我们需要用到一个新的控件——Update Attribute
。
首先拖拽一个Update_Attribute
控件到Recording
的工作区,更名为“Calculate_RT”。并将其连接到实验序列的最后。
双击Calculate_RT
打开Attribute-Value List for Calculate_RT窗口
,进行详细的赋值设置。
我们可以看到,Attribute-Value List for Calculate_RT窗口
分为左右两列,分别为”Attribute“和“Value”。在这个窗口中,我们可以将右边“Value”中填写的内容赋值给左边“Attribute”中所指向的变量。
已知RT_of_TextPage
= Time_of_Keyboard_of_TextPage_Triggered
- Time_of_TextPage_Displayed
。
即我们希望将“Time_of_Keyboard_of_TextPage_Triggered
- Time_of_TextPage_Displayed
”的值赋给RT_of_TextPage
。所以我们进行如下操作:
首先设置左侧“Attribute”,在列表中找到RT_of_TextPage
,选中“Value”。意为对RT_of_TextPage
进行赋值。
然后设置右边,因为是两个数值相减,所以要写成算式:
⚠️注意⚠️:所有的Trigger都有两个Time,第一个Time是Trigger开始等待被触发的时间,第二个在Trigger Data下面的Time才是被触发时的时间。大多数的时候我们都是使用Trigger Data里面的Time做计算。
1.3 计算Question反应时
同前一部分类似,用相同的方法计算Question
屏的回答反应时。
RT_of_Question
= Time_of_Keyboard_of_Question_Triggered
- Time_of_Question_Displayed
。
定义一个名为RT_of_Question
的Variable
并声明变量类型为“Double”。
双击Calculate_RT
打开Attribute-Value List for Calculate_RT窗口
,对RT_of_Question
进行赋值运算。
2. 记录Question回答结果
还是先说逻辑,记录回答结果的思路有很多:
- 第一种是直接记录被在作答时的按键是什么,直接记录“f”或者“j”。这种记录方法在编程时的操作相对简单,但是在数据处理的时候就需要对每个试次的答案进行正确比对,后期需要进行一些简单但是机械费时的工作;
- 第二种方法则是在实验运行过程中让计算机代替手动,直接根据已知的正确答案判断每道题的回答是否正确。在处理数据的时候则友好很多。
- ……
本文中我们将采用第二种方法来进行回答结果的记录。大致流程如下:
判断回答的对错
-> 记录对错信息
-> 保存到Result File
2.1 判断回答的对错
这里要用到一个控件Conditional Trigger
。首先我们先将一个Conditional Trigger
添加到工作区中,修改Label属性
为“Judge”。并连接到实验序列的最后。
Conditional Trigger
这个空间其实就是一个判断器。在使用时,我们会实现在Conditional Trigger
中预置一个条件,这个条件可能是一个等式,也可能是一个包含的逻辑关系。如果我们提前预置的这个逻辑关系成立,则从✔︎的一侧向后执行,反之则从×的一侧向下执行。如下图所示:
我们首先要在Judge
里面预置逻辑关系表达式,通过这个逻辑关系表达式来判断回答是否正确。详细解释一下则是将Keyboard_of_Question
中的按键(f/j)与Datasource
中已经预置的正确答案做对比,如果相同则回答正确,不相同则回答错误。所以我们预置的逻辑关系表达式是:
@Keyboard_of_Question.TriggeredData.Key@
== @Trail_Datasource.Correct_Answer@
选中Judge
,修改Evaluation 1
中的Attribute
为在Keyboard_of_Question
中的按键,修改Evaluation 1
中的Value
为Datasource
中的“Correct_Answer”这个Column。
设置完成后应如下图所示:
2.2 记录对错信息
在2.1的部分我们已经完成了对于对错的识别,在这一部分我们将完成对错的记录。
首先我们创建一个名为“ACC“的Variable
。如果回答正确的话,我们让ACC
等于1,如果回答错误的话,我们让ACC
等于0。
注意,在声明
ACC
变量类型的时候,我没有用0,而是用了2。这是因为0代表错误,1代表正确,初始化的时候应使用不同于前两者的数字来进行初始化声明,目的是防止出现回答超时等特殊情况来进行标记。
在Judge
分别链接两个UpdateAttribute
控件——Mistake
和Correct
,如果在Judge
中判断回答正确,执行Correct
让ACC
等于1,如果回答错误,则执行Mistake
让ACC
等于0。
2.3 保存到Result File
这一部分我们将使用两个新的控件:ResultsFile
和AddToResultsFile
。
ResultsFile
在控件库的Other分类下,只需将ResultsFile
拖入工作区,不用链接任何控件,即可命令EB创建一个.txt格式的Results File。在这个Results File中我们可以保存每个试次的运行条件和行为反馈等信息,例如我门在本章前一部分介绍的反应时和正确率。
AddToResultsFile
则是命令EB软件将我们指定的信息写入Results File。
Results File
的功能是为了non-Eyelink实验准本的,因为非眼动实验不会生成.edf
文件,数据无法保存在.edf
文件当中,就只能新建一个.txt
的结果文件来保存这些信息。在实际使用过程中,有些用户发现用Results File
的功能来记录眼动数据中的行为信息也很方便,于是就这样延续了下来。
所以我门首先将一个ResultsFile
控件添加至工作区。ResultsFile
的Label
属性即为.txt
文件的文件名,可以直接使用默认值。
随后我们向工作区中添加一个AddToResultsFile
控件,保持默认的Label
,将其添加至实验序列的末端。
选中AddToResultsFile
,修改其Results File
属性为刚刚添加的ResultsFile
。
这样在运行试验之后就会在.edf
文件相同的路径下生成一个制表符构成的.txt
结果文件,可以直接用excl读取。具体ResultsFile
中包含的信息内容有哪些,可以在ResultsFile
控件中的Columns
属性中查看。
Test Run
一下试试效果吧!
以上。