Python中MNE库模拟原始脑电数据

2023-11-16

研究脑电算法的时候发现了一个问题,如何评价模型的准确性? 之前的工作流程都是先用公开数据集的数据训练好模型,然后放到实测数据上进行参数微调。在公开数据集上进行模型的选择主要是因为公开数据集的数据质量较好,可以排除硬件的影响,从而专心于算法的研究。但有些时候,尽管在公开数据集上计算模型得到的结果也不是很理想,可是还想进一步分析算法,这时候就需要保证数据的不受其他因素的影响了,可是实测的数据总是会受到各种外界因素的干扰,难以对一些计算细节进行分析。要是能有模拟的脑电信号就好了,这样就可以不受其他因素干扰了,查了一下,MNE中还真有这方面的库。

里面有一个例子包含的内容比较全面,,,,,,,,,,,,,,,,,

以此为例进行学习:

第一步:导入数据模板,利用模板中的电极信息。

import numpy as np
import matplotlib.pyplot as plt
import mne
from mne import find_events, Epochs, compute_covariance, make_ad_hoc_cov
from mne.datasets import sample
from mne.simulation import (simulate_sparse_stc, simulate_raw,add_noise, add_ecg, add_eog)
# 打印开头的函数说明,这里没有添加说明也就没有内容需要打印
print(__doc__)

# 设置数据路径,MNE下载的数据保存路径
data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_raw.fif'
fwd_fname = data_path + '/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif'

# 加载数据作为模板,主要是为了使用电极位置等一系列相关信息
raw = mne.io.read_raw_fif(raw_fname)
# 设置参考电极,默认为average,这里projection为Ture说明只是添加了参考,但并没有进行运算
raw.set_eeg_reference(projection=True)

 

第二步:生成源的波形数据


# 创建的偶极子数
n_dipoles = 4
# 每一个epoch/event的持续时间
epoch_duration = 2.
# 谐波数
n = 0
# 获取随机状态,主要是为了使每次运行的结果相同,方便调试,如果不设置固定状态,每次的结果会不一样
rng = np.random.RandomState(0)
# 数据生成函数,在10赫兹谐波下产生时间交错的正弦波,函数中的n为全局变量,这里有4个偶极子会调用4次,
# 也就是生成10hz,20hz,30hz,40hz的正弦波
def data_fun(times):
    # 全局变量n
    global n
    # 时间序列长度
    n_samp = len(times)
    # 时间窗,主要为了后面生成时间交错的波形
    window = np.zeros(n_samp)
    # 时间窗的起始和结束范围,谐波间隔出现
    start, stop = [int(ii * float(n_samp) / (2 * n_dipoles))
                   for ii in (2 * n, 2 * n + 1)]
    # 对想保留的范围赋值为1
    window[start:stop] = 1.
    # 全局变量加一
    n += 1
    # 正弦波函数sin(2*pi*w*t)
    data = 25e-9 * np.sin(2. * np.pi * 10. * n * times)
    # 保留时间窗内对应的数据,也可以理解为滤波
    data *= window
    # 返回生成的波形数据
    return data

# 获取时间序列,前面我们读取了sample_audvis_raw.fif作为模板,获取其采样频率,其对应的epoch_duration(2秒钟)的时间序列如下。
times = raw.times[:int(raw.info['sfreq'] * epoch_duration)]
# 获取位置正解信息,我的理解也就是信号源的位置信息
fwd = mne.read_forward_solution(fwd_fname)
# 获取源位置
src = fwd['src']
# 利用data_fun函数生成4个偶极子离散源的时间序列
stc = simulate_sparse_stc(src, n_dipoles=n_dipoles, times=times,
                          data_fun=data_fun, random_state=rng)
# 绘制4个偶极子源的时间序列图像
fig, ax = plt.subplots(1)
ax.plot(times, 1e9 * stc.data.T)
ax.set(ylabel='Amplitude (nAm)', xlabel='Time (sec)')
mne.viz.utils.plt_show()

 

第三步:模拟原始数据

在simulate_raw函数的实现中,提到了一篇参考文献,尝试了很多途径都没有找到,要是谁有希望能分享下。

[1] Larson E, Taulu S (2017). "The Importance of Properly Compensating
       for Head Movements During MEG Acquisition Across Different Age
       Groups." Brain Topogr 30:172–181
# 模拟原始数据,[stc]*10指的是时间序列,上面设置的[stc]长度为2秒(epoch_duration)
# raw.info中的events有些是在两秒后的,这里相当于模拟了10个epoch长的的数据也就是20秒的数据
raw_sim = simulate_raw(raw.info, [stc] * 10, forward=fwd, cov=None,verbose=True)
# 生成噪声的协方差
cov = make_ad_hoc_cov(raw_sim.info)
# 添加噪音
add_noise(raw_sim, cov, iir_filter=[0.2, -0.2, 0.04], random_state=rng)
# 添加心电(ECG)信号
add_ecg(raw_sim, random_state=rng)
# 添加眼电(EOG)信号
add_eog(raw_sim, random_state=rng)
# 绘制添加噪声后的数据
raw_sim.plot()

 

第四步:绘制白化后的evoke数据

# 提取事件
events = find_events(raw_sim)
# 根据事件生成epochs
epochs = Epochs(raw_sim, events, 1, tmin=-0.2, tmax=epoch_duration)
# 计算epoch的经验协方差
cov = compute_covariance(epochs, tmax=0., method='empirical', verbose='error')
# epoch求取均值得到evoke
evoked = epochs.average()
# 绘制evoke白化后的数据
evoked.plot_white(cov, time_unit='s')

 

其它一些个人理解

按照示例程序走了一遍,对整个过程大概理解了,但是为啥看起来和源的波形差距那么大呢?

1、噪声、心电、眼电对数据的影响。

提取其中的一个epoch数据进行分析,这是没加噪声前EEG 001的数据

EEG001的检测数据->添加噪声后的数据,添加心电和眼电后的数据,

 

2、不加噪声的数据

如果不添加噪声数据会是什么样子呢?注释掉add_noise()。

 

不加噪声的脑电信号,不加噪声的时候还是可以看出源的波形图的。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python中MNE库模拟原始脑电数据 的相关文章

  • 监控神器-普罗米修斯Prometheus的安装

    最近看了些AIOPS的资料 对于里面提及的一个普罗米修斯Prometheus起了兴趣 首先是联想到异形 哈哈 去看了一下 普罗米修斯还真是厉害 而且还是开源的 真是搬砖党的福音 功能 在业务层用作埋点系统 Prometheus支持多种语言
  • 面向对象和面向过程的区别,Java为什么说它性能低

    面向对象相比于面向过程 面向对象的代码延展性更好 拿上面的例子举例如果现在要把存储的对象不是大象了而是狮子 那么很明显 面向过程要的方法要所有大象为狮子 面向对象的方法只要改一下关于这个改动的方法也就是 存储 内容 不仅仅是修改 添加删除等

随机推荐

  • C++:模拟实现string类

    文章目录 Iterator类 capacity类 Element access 类 Modifiers类 String operations类 类外成员函数 头文件总括 本篇主要介绍模拟实现string类 string中有相当多的内容 这里
  • AIX6.1 源码编译方式安装 zabbix3.4 代理

    1 aix机器上创建zabbix用户 mkuser zabbix 2 上传zabbix 3 4 11 targz 3 解压 gunzip zabbix 3 4 11 tar gz tar xvf zabbix 3 4 11 tar 4 安装
  • C语言实现DFT计算

    文章目录 一 DFT计算公式 二 DFT程序实现 一 DFT计算公式 这里就不对DFT概念进行叙述 直接上计算公式 其中N为DFT点数 公式如此 但是在程序中并非如此运算 而是利用欧拉公式对DFT的计算公式进行了转化 转换后公式变为 利用转
  • 为什么在控制台输入var name = Symbol();会报错?VM3436:1 Uncaught TypeError: Cannot convert a Symbol value to a str

    问题复现 var name Symbol VM3436 1 Uncaught TypeError Cannot convert a Symbol value to a string 解释每一个部分 var 定义的变量会把它提升到当前函数作用
  • 踩坑vue中嵌套iframe项目,嵌套在iframe中的项目无法登录!

    解决方案原文 这个我试了下是谷歌浏览器做了限制 在edge上可以正常登录 我遇到这种情况主要是我的项目用的是cookie存储的登录状态 需要设置cookie的域名 使其在嵌入的网站和网站域名下都能访问cookie 但是我设置了还是没用 我最
  • go cli脚手架开发利器——cobra库的初体验

    文章目录 关于 说明 cobra 简介 cobra 概念 Commands Flags Args 教程正文 demo1 快速了解 demo 知识点 Command创建命令 demo2 使用参数验证器 钩子函数 demo 知识点 参数验证方法
  • 最新xmind2022版思维导图如何使用详解教程

    前段时间和大家盘点了五种高效的学习方法 没有看过的小伙伴戳这里 最科学的学习方法盘点 讲到思维导图笔记法的时候 本狗子给大家推荐了一款免费的思维导图软件 xmind软件 然后好多小伙伴都加我问关于思维导图的使用方法 于是今天我就做了一份关于
  • 微信小程序编译bug---Hbuilderx编译时一直卡在编译界面

    项目场景 微信小程序新增某功能模块 问题描述 使用Hbuilderx开发微信小程序 正常开发中 在某次重新保存代码并编译后一直卡在编译界面 如图 图为Hbuilderx界面 因为此时没有编译完成 所以微信开发者工具界面一片空白 报错为 ap
  • Python,OpenCV使用KNN来构建手写数字及字母识别OCR

    Python OpenCV使用KNN来构建手写数字及字母识别OCR 1 原理 1 1 手写数字识别 1 2 字母识别 2 源码 2 1 手写数字OCR 2 2 字母OCR 参考 这篇博客将介绍如何借助OpenCV提供的手写数字及字母数据集
  • Linux用户空间与内核空间

    Linux用户空间与内核空间 2012 08 30 15 39 1969人阅读 评论 1 收藏 举报 linux linux内核 struct user system allocation Linux 操作系统和驱动程序运行在内核空间 应用
  • 2.Xaml 停靠框架

    1 运行效果图片 2 Xaml程序
  • ChatGPT实现知识图谱生成

    知识图谱生成 在之前章节中 我们尝试过让 ChatGPT 对一段文本做实体识别和词性分析 结果很不错 但如果是需要长期留存下来 后续在不同场景下快速查询分析 最好还是要把数据存入到专门的图数据库中 才能方便随时读取 本节 我们试试让 Cha
  • 《计算机网络原理》(谢希仁)笔记——第二章

    此为本人观看韩立刚老师视频所做笔记与总结 下面为视频连接 https www bilibili com video av10921041 from search seid 733222547867341420 第二章 物理层 主要知识点为数
  • Verilog对数据进行四舍五入(round)与饱和(saturation)截位

    重点 1 正数截位 直接看截掉的最高位是不是一 是的话进一 负数截位 截的最高位为1且其它位不全是0进一 2 饱和 也就是大于求的结果 整数变为符号位为0 其它位为1 负数变成第一位为1 其它位为0 一 引言 在利用Verilog写数字信号
  • Python入门到放弃(一)

    介绍python和库文件管理 python是解释型语言 Python的特点 简单 易学 速度快 免费开源 高层语言 可移植性 解释性 面向对象 也支持面向过程 可扩展性 可嵌入性 丰富的库 规范的代码 在cmd中退出python 输入exi
  • Tomcat优化相关问题

    1 你怎样给 tomcat 去调优 JVM 参数调优 Xms 表示 JVM 初始化堆的大小 Xmx表示 JVM 堆的最大值 这两个值的大小一般根据需要进行设置 当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出 并且导致应用服务崩溃
  • Spark(七)——累加器和广播变量

    5 累加器 通过在驱动器中调用SparkContext accumulator initialValue 方法 创建出存有初始值的累加器 返回值为org apache spark Accumulator T 对象 其中 T 是初始值 ini
  • ObjectARX编程(八) --------有名对象字典、用户字典和字典中的对象

    在AutoCAD数据库中 对象字典是字典类型数据库对象的总称 按其层次关系可分为两类 一是有AutoCAD数据库直接管理的第一层对象字典 二是有第一层对象字典管理的第二层对象字典 为了便于区别 我们把第一层对象字典称为有名对象字典 用于在应
  • 浅谈std::move和std::forward原理

    前言 本文主要整理了C 11中std move和std forward的原理 这对理解C 的移动拷贝有很重的意义 一 左值和右值 左值 一般来说 能在内存中取得其地址 即是左值 右值 在内存在无取得其地址的 即是右值 note 左值持久 右
  • Python中MNE库模拟原始脑电数据

    研究脑电算法的时候发现了一个问题 如何评价模型的准确性 之前的工作流程都是先用公开数据集的数据训练好模型 然后放到实测数据上进行参数微调 在公开数据集上进行模型的选择主要是因为公开数据集的数据质量较好 可以排除硬件的影响 从而专心于算法的研