BCI Competition IV 2a数据集.gdf文件读取与预处理

BCI Competition IV 2a 2b 数据集.gdf文件读取与预处理

数据集简介

数据集网站:https://bbci.de/competition/iv/
Data sets 2a: ‹4-class motor imagery›
EEG, cued motor imagery (left hand, right hand, feet, tongue)
[22 EEG channels (0.5-100Hz; notch filtered 陷波滤波), 3 EOG channels, 250Hz sampling rate, 4 classes, 9 subjects]

Data sets 2b: ‹motor imagery› (description)
EEG, cued motor imagery (left hand, right hand)
[3 bipolar EEG channels (0.5-100Hz; notch filtered), 3 EOG channels, 250Hz sampling rate, 2 classes, 9 subjects]

眼电图(Electrooculogram,EOG)信号与脑电图(Electroencephalogram,EEG)信号是不同的。EEG记录的是大脑神经活动产生的电位变化,而EOG记录的是眼睛肌肉活动和眼球运动引起的电位变化。因此,在脑电图研究或实验中,通常会同时记录EOG信号以帮助检测和纠正眼动对脑电图的影响。

数据集官方文档

BCI Competition IV 2a 官方文档:https://www.bbci.de/competition/iv/desc_2a.pdf

Experimental paradigm 实验范式

数据集由9名受试者的EEG数据组成,受试者在实验过程中需要进行四种不同的运动想象任务,即左手(1类)、右手(2类)、双脚(3类)和舌头(4类)运动想象。每名受试者均在不同的日期进行了两个session,两个session所得数据分别用于分类器的训练(T)和测试(E)。因此每个受试者将拥有两个数据文件,以一号受试者为例将两份文件命名为A01T和A01E,数据集共有18份文件。对于每一次session,可以细分为6次runs,每一次run包含有48次trials(测试)。即一个session中包含288个trials。每个MI类型的trials次数相同(均为72次)且顺序打乱。

在每个session开始时,进行大约5分钟的记录,以估计EOG的影响。录音被分成3个片段:(1)两分钟睁着眼睛(看着屏幕上的固定十字),(2)一分钟闭着眼睛,(3)一分钟眼球运动。其中一个session的定时方案如图1所示。注意,由于技术问题,注:受试者A04T的EOG块较短,仅包含眼球运动情况(所有受试者列表见表1)。

在这里插入图片描述

在每一个测试中,受试者都坐在一个舒适的扶椅上,面前是电脑屏幕。测试开始时(t=0s),一个固定的十字会出现在黑色的屏幕上。此外还有简短的声音提示音。两秒过后(t=2s),一个作为提示指向左、右、下或者上(对应于四个类别左手运动、右手运动,双脚运动以及舌头运动)的箭头会出现在屏幕上约1.25s。促使受试者想象与图片对应的运动。每个受试者需要完成这个想象任务直到屏幕上的十字消失(t=6s)。然后是短暂休息直到屏幕再次变黑。每一次测试的平均时间大约为8秒。
注:记录MI的event事件开始时间first sample是从Cue开始的

在这里插入图片描述

Data recording数据记录

数据共有25个通道,其中22个通道为EEG,3个通道为EOG,其中EOG三通道的数据不参与分类。以250 Hz对信号进行采样(每秒250次采样),并在0.5 Hz和100 Hz之间进行带通滤波。放大器的灵敏度设置为100 µV。使能额外的50 Hz陷波滤波器以抑制线路噪声。采样电极分布如下(左图为EEG采样点,右图为EOG采样点):

在这里插入图片描述

Data file description数据文件描述

所有数据集以生物医学信号通用数据格式(GDF)存储,每个 session 和 subject 一个文件。然而,只有一个会话包含所有试验的类标签,而另一个会话将用于测试分类器,从而评估性能。表1列出了所有文件。请注意,评估集将在竞赛截止日期后提供(主题A01的一个文件除外,作为示例)。

注意:由于技术问题,受试者A04T的EOG块较短,仅包含眼球运动情况。

事件类型列表 (第一列包含十进制值,第二列包含十六进制值)。主要需要注意的事件即MI数据:769, 770, 771, 772。

在这里插入图片描述

注意:运行由100个缺失值分隔,这些缺失值默认情况下被编码为非数字(NaN)。(可以通过将nan变为mean来将数据变为连续的)

工作空间将包含两个变量,即signals s和header structure h。信号变量包含25个通道(前22个是EEG信号,后3个是EOG信号)。头结构包含描述数据随时间变化的结构的 event 信息。以下字段为评估该数据集提供了重要信息:

示例中事件的 位置position 包含在h.EVENT.POS中。相应的 类型type 可以在h.EVENT.TYP中找到。特定事件的 持续时间duration 存储在h.EVENT.DUR中。表2描述了该数据集中使用的类型(十六进制值,括号内的十进制表示)。注意,类标签(即事件类型769、770、771、772对应的1、2、3、4)只提供给训练数据,不提供给测试数据。

数据集读取

主要使用python中的mne库,调用read_raw_gdf函数进行读取 .gdf 文件:
mne库官方文档:https://mne.tools/stable/index.html

代码示例

读取.gdf文件的代码示例:

import matplotlib.pyplot as plt
import mne
import numpy as np

filename = "../dataset/BCICIV_2a_gdf/A01T.gdf"

raw_gdf = mne.io.read_raw_gdf(filename, stim_channel="auto", verbose='ERROR',
                              exclude=(["EOG-left", "EOG-central", "EOG-right"]))

# 将原通道重命名为10-20系统中,常用的64个电极位置
raw_gdf.rename_channels(
            {'EEG-Fz': 'Fz', 'EEG-0': 'FC3', 'EEG-1': 'FC1', 'EEG-2': 'FCz', 'EEG-3': 'FC2', 'EEG-4': 'FC4',
             'EEG-5': 'C5', 'EEG-C3': 'C3', 'EEG-6': 'C1', 'EEG-Cz': 'Cz', 'EEG-7': 'C2', 'EEG-C4': 'C4', 'EEG-8': 'C6',
             'EEG-9': 'CP3', 'EEG-10': 'CP1', 'EEG-11': 'CPz', 'EEG-12': 'CP2', 'EEG-13': 'CP4',
             'EEG-14': 'P1', 'EEG-15': 'Pz', 'EEG-16': 'P2', 'EEG-Pz': 'POz'})
# Pre-load the data
raw_gdf.load_data()
# correct nan values
data = raw_gdf.get_data()

for i_chan in range(data.shape[0]):  # 遍历 22 channel
    # 将数组中的所有值设置为nan,然后将这些NaN值替换为该数组的均值。
    this_chan = data[i_chan]
    data[i_chan] = np.where(
        this_chan == np.min(this_chan), np.nan, this_chan
    )
    mask = np.isnan(data[i_chan])
    chan_mean = np.nanmean(data[i_chan])
    data[i_chan, mask] = chan_mean

# 获取事件时间位置,返回事件和事件下标
events, events_id = mne.events_from_annotations(raw_gdf)
print('Number of events:', len(events))
print(events_id)
print(events)

# 利用mne.io.RawArray类重新创建Raw对象,已经没有nan数据了
raw_gdf = mne.io.RawArray(data, raw_gdf.info, verbose="ERROR")
print(raw_gdf.info)

# 画出EEG通道图
raw_gdf.plot()
plt.show()

代码运行结果:

在这里插入图片描述

画出的EEG脑电图如下:

在这里插入图片描述

数据分析

以 A01T.gdf 为例,可以看到,事件类型共有十种,对应事件类型列表中的事件。没有包含783,因为其为训练集,没有 unknown 的 event 。其中,事件id: events_id 为:

{‘1023’: 1, ‘1072’: 2, ‘276’: 3, ‘277’: 4, ‘32766’: 5, ‘768’: 6, ‘769’: 7, ‘770’: 8, ‘771’: 9, ‘772’: 10}

四分类的 event 分别为 [7, 8, 9, 10],对应的 MI 为:左手(1类)、右手(2类)、双脚(3类)和舌头(4类)。events 的数据结构为ndarray: (n_events, 3),共有603个事件,事件的第一个列为起始时间 first_samp,第三列为事件类型 event id。

在这里插入图片描述

上图为上述代码读取的 events 和 events_id 的数据。我们进行逐一分析:

  • 事件0:events_id = 5 对应事件类型为32766,解释为 Start of a new run。
  • 事件1:events_id = 3 对应事件类型为276,解释为 Idling EEG (eyes open)。
  • 事件3:events_id = 4 对应事件类型为277,解释为 Idling EEG (eyes closed)。
  • 事件5:events_id = 2 对应事件类型为1072,解释为 Eye movements。

从事件6开始,才是带有trial的run,上面的三个run都为获取EOG的信号。

  • 事件7:events_id = 6 对应事件类型为768,解释为 Start of a trial。
  • 事件8:events_id = 10 对应事件类型为772,解释为 Cue onset tongue (class 4)。
  • 事件9:events_id = 6 对应事件类型为768,解释为 Start of a trial。
  • 事件10:events_id = 9 对应事件类型为771,解释为 Cue onset foot (class 3)

以此类推。
可以发现,每个trial的start和cue之间频次相差500,对应了250Hz频率采样2s。第一个和第二个trial之间相差2003,对应了250Hz频率采样8s。我们的目标是提取 MI 数据,将无关的数据去掉。故需要提取从 Cue 开始的 1s 到 4s 的数据。
在这里插入图片描述

提取的方法为使用 mne.Epochs 函数,官方文档的函数参数介绍如下:

在这里插入图片描述

在脑电图(EEG)和其他生理信号处理中,Epochs(时期)是一种数据类型,用于表示从原始连续信号中提取的固定时间段的数据。

Epochs可以看作是对原始信号进行切片的结果,将连续数据分割为多个定长的时间段。每个Epochs包含一段时间内的信号数据,通常是在实验或研究中与特定事件相关的时间段。

Epochs数据通常由一个多维数组或矩阵表示,其中每个维度对应于不同的数据维度,例如时间、通道和试验等。通常,Epochs数据的维度顺序是(试验数,通道数,时间点数)。

数据提取

代码为:

# 选择范围为Cue后 1s - 4s 的数据
tmin, tmax = 1., 4.
# 四类 MI 对应的 events_id
event_id = dict({'769': 7, '770': 8, '771': 9, '772': 10})

epochs = mne.Epochs(raw_gdf, events, event_id, tmin, tmax, proj=True, baseline=None, preload=True)
print(epochs)

在这里插入图片描述

提取的 epochs 中的每类 event_id 的数量都为72。使用 get_data 函数获取epochs中已经划分好的 data 数据

在这里插入图片描述

# 切片,获取 events 的最后一列
labels = epochs.events[:, -1]
# Get all epochs as a 3D array.
data = epochs.get_data()
print(labels)
print(data.shape)

结果如下,获取的数据为 ndarray:(288, 22, 751),表示(trials, channels, times)

在这里插入图片描述

至此,就可以使用提取的数据用作训练了。

读取EEG数据流程

通过上述流程,大致可以整理使用python提取EEG数据并预处理的流程(参考https://blog.csdn.net/zyb228/article/details/106216744/):

  1. 读取EEG数据:mne.io.read_raw_gdf
  2. 定位通道数据:将原通道重命名为10-20系统中,常用的64个电极位置
  3. 删除无用数据:如将无用的EOG通道数据exclude
  4. 处理NaN数据:将NaN->mean
  5. 获取events, events_id:使用mne.events_from_annotations
  6. 分段:使用mne.Epochs获取需求的MI数据
  7. 切片,获取最终的ndarray类型数据:epochs.get_data()

除此之外还可以增加滤波、基线校正等操作。

参考:
1、记录第一次ANN跑BCI Competition iv 2a过程
2、手把手教你EEG脑电数据预处理-原理篇

  • 10
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值