
做近红外数据分析这几年我经常被同行问到底该用 Homer 还是 Brainstorm 我的答案很直接如果目标是快速上手、能随时看到数据、又在同一个界面里把 fNIRS 和 MEG/EEG 结果放在一起比较那 Brainstorm 绝对值得认真用起来。Brainstorm 是一个在脑成像领域相当知名的开源分析平台最近几年把 fNIRS 模块补得越来越完整从原始光强到血氧浓度、再到 GLM 统计都能在图形界面里点出来。这篇是Brainstorm 简单分析近红外数据fNIRS系列的第一篇我按照自己完整跑通一个任务态 fNIRS 实验的顺序把从安装、数据导入到单被试激活结果的链路写清楚适合刚接触 fNIRS、正在纠结怎么搭分析流程的同学参考。1. 为什么我建议用 Brainstorm 处理 fNIRS 而不是一把梭 Homer1.1 近红外数据分析的主流工具都有哪些实验室早期用 Homer2 比较多它在运动伪影处理上非常扎实尤其是 tMotion 检测加样条插值几乎是我们处理便携式 fNIRS 数据的标配方法。但 Homer 的使用方式更偏向脚本和命令行每次换一个新的实验范式都要重新读一遍源码、拼接函数流程数据可视化基本靠自己在 MATLAB 里画图通道空间位置、皮层配准、GLM 结果叠加这些操作都谈不上顺手。后来我把基于 Brainstorm 的流程重新搭了一遍出发动机特别朴素我想在处理过程中直接看到每一级处理前后的信号长什么样通道在头皮上的位置是否合理GLM 跑出来的 t 值能不能直观地铺到通道布局上。这些需求在图形界面里实现起来会高效很多。标题里说的简单分析并不是指分析内容简单而是说把流程理清之后整个分析过程会变得非常可控不容易被脚本细节带偏。1.2 Brainstorm 和其他工具的实际对比下面这个表是根据我自己用过的工具总结的不一定覆盖所有功能但能帮你快速定位需求工具界面导入格式支持预处理能力统计/建模可视化适合场景BrainstormGUI 脚本NIRx、Artinis、.nirs 等中偏强内置 GLM、非参检验通道/头皮/皮层/时频全流程探索、与 MEG/EEG 联合分析Homer2/Homer3脚本为主.nirs 为主强运动伪影校正是强项需要额外组合偏弱预处理算法研究、批量处理MNE-NIRSPython 接口NIRx 等常见格式强可组合 scikit-learn/statsmodelsMatplotlib/Pyvista熟悉 Python 的科研用户NIRS-SPMSPM 插件多种中GLM 体系完整SPM 风格想在 SPM 生态里做组分析的人Brainstorm 给我最大的感受是数据管理做得好。所有被试、条件、处理结果都在同一个协议树下面每一次处理都会生成新的文件节点原始数据永远不被覆盖想回退到任何一步都很方便。这对初学者尤其重要因为分析过程中难免会做错一步能找回中间结果会省掉大量重跑的时间。1.3 什么情况下应该优先选它如果只是做常规的 block 设计实验、看通道水平的任务激活或者想把 fNIRS 激活和同被试的 EEG/MEG 结果对照Brainstorm 基本是效率最高的方案。它也有自己的弱项比如对非常规自行搭建的分析流程定制不够灵活某些最新的预印制算法更新没有 Homer3 快。但作为第一遍把数据看明白的主工作台它非常称职。我个人的建议是把 Brainstorm 当作主操作台把 Homer3 当作预处理算法备选库。先用 Brainstorm 建立起对数据的直观理解再按需去 Homer 里做更精细的校正两者可以结合不必非此即彼。2. 安装与数据准备先把环境和工作台搭好2.1 MATLAB 环境与下载方式Brainstorm 基于 MATLAB 开发官方推荐直接获取源码运行对 MATLAB 版本要求比较宽松我现在用的 R2022a 跑起来没有任何问题。如果你没有 MATLAB 授权可以下载带 MATLAB Runtime 的独立安装包启动会稍微慢一点但功能几乎一致Windows、macOS、Linux 都有对应版本。下载地址是 Brainstorm 官网的下载页可以拿正式发布包也可以用 GitHub 上的开发版。我自己长期用开发版原因是 fNIRS 模块这几年的迭代速度很快正式发布版往往比开发版落后不少一些新设备格式的支持也是先在开发版里出现。提示解压路径和存放数据的工作目录尽量不要出现中文也不要用嵌套过深的路径。MATLAB 在底层文件读写上对中文路径的兼容性偶尔会出问题到时候排查起来非常头疼。2.2 从启动到创建协议的完整操作在 MATLAB 里运行以下命令addpath(genpath(你的解压路径/brainstorm3)); brainstorm第一次启动会弹窗让你选择一个数据目录这个目录专门用来存放所有 Protocol 数据。Protocol 可以理解成一个实验项目的总容器一个 Protocol 下可以建立多个 Subject每个 Subject 下面再按 Condition 组织数据整体层级和 MEG/EEG 数据分析完全统一。创建新协议的方式是菜单 Protocol Create new protocol协议名称我一般用英文比如 fNIRS_demo。创建完成后左侧文件树会出现 Anatomy 和 Data 两个默认分组。在 Data 分组里右键就能导入数据后续生成的预处理文件、GLM 结果也会挂在这个协议树下结构一目了然。2.3 需要准备的数据与事件文件近红外设备品牌很多NIRx、Artinis、Hitachi 都有对应的导入插件。我手里主要是 NIRx 的系统所以重点说通用的 .nirs 格式。一个标准的 .nirs 文件通常包含这几部分原始信号矩阵 data维度是采样点数 × 通道数 × 波长数波长列表 wavelengths比如 760 nm 和 850 nm 两个波长源-探测量距离和空间排列信息有些文件会直接带坐标事件标记矩阵 s以采样点为单位记录刺激触发位置如果设备导出的不是 .nirs也可以走 Brainstorm 的导入向导选对应的厂商格式。事件标记我建议额外保留一份行为实验的 log 文件因为部分设备生成的事件记录只写了触发点没有条件标签后面做 GLM 还要手动补条件归属。3. 数据导入Brainstorm 如何把 .nirs 文件变成可操作的数据结构3.1 导入流程与关键选项在协议树的 Data 分组右键选择 Import data files文件类型选 NIRS。导入向导会让你指定 Subject 和 Condition如果之前没有建 Subject可以在向导里直接新建。导入完成后左侧会生成一个原始数据文件双击能在时间序列浏览器里看到完整的信号。有一点很容易踩坑有些 .nirs 文件里的通道顺序不是按空间邻近关系排列的而是按设备采集顺序排列的。如果后面要做拓扑图或皮层投影必须保证通道文件里的坐标正确。所以导入之后第一件事不是急着处理而是先检查通道位置和通道类型确认每一个源-探对都对应到了正确的位置。3.2 检查通道与布局右键通道节点选择 Edit channel file可以逐个查看通道的类型、组别和坐标。在 fNIRS 里通道类型会标成 NIRS 或其他相关类型组别通常就是源-探对编号。对于只有二维拓扑图的 .nirs 文件Brainstorm 也能用平面布局近似展示通道位置这个二维图在单被试分析阶段足够用来检查空间分布。如果系统包含短距通道也就是源探距离小于 15 mm、信号主要来自头皮表层血流的通道导入后最好单独设一个组名比如 Short。后面做全局噪声回归时靠这个组名可以一次性选中所有短距通道不用手动一个个挑。3.3 事件标记的导入与整理数据里自带的事件标记一般会出现在事件列表里但如果看到 Stimulus 区域是空的可以考虑手动导入事件文件。Brainstorm 支持从 CSV、EVT 或 MATLAB 的 mat 文件导入事件标记。导入后我习惯把同一条件的所有刺激合并成一个事件组例如实验有 A、B 两个条件就分别建立 A 和 B 两个事件组而不是让每个刺激单独成为一组否则后续 GLM 设计矩阵会非常混乱。注意事件时间单位一定要确认清楚。部分导出的标记时间用的是采样点导入 Brainstorm 后要正确设置采样率才能换算成秒。单位一旦错了后面所有锁时分析和 GLM 都会偏差而且这种错很难一眼看出来。4. 预处理链路从原始光强到血氧浓度变化4.1 先转光学密度再做运动伪影校正很多教程上来就直接滤波或转浓度我建议按这个顺序走原始光强 - 光学密度 - 运动伪影校正 - 带通滤波 - 转浓度/短距回归。原因是运动伪影在光学密度数据里更容易被检测出来如果先做了滤波尖峰会被抹平一些检测难度反而变大。在 Brainstorm 的 Process 列表里NIRS 分类下可以找到类似转换为光学密度的进程。选中数据文件运行后就会生成一个新的光学密度数据文件原始数据文件保持不变。这一步看似简单却是后续所有定量分析的基础因为只有光学密度才和浓度变化之间满足线性近似关系。4.2 运动伪影的检测与校正fNIRS 最让人头疼的就是运动伪影。无论是自然语言任务里的头部小动作还是被试坐久了姿势微调都会让信号出现尖峰或台阶。Brainstorm 提供配套的运动检测与校正进程思路和 Homer 类似通过计算每个通道在滑动窗口内的信号突变幅度把超过阈值的时段标记为运动事件。阈值的设定需要结合自己的数据反复试。头部运动明显的数据阈值要调低一些信号本身比较毛糙的数据阈值则要调高一些。建议先用默认阈值跑一遍看标记出来的运动段是否合理再逐步向两端调整直到标记结果和你在原始时间序列里肉眼看到的尖峰位置基本吻合。校正进程会用样条插值把标记时段替换掉避免尖峰进入后面的统计。我自己的经验是校正后必须再看一遍数据因为样条插值对持续时间特别长的运动段效果不好。如果连续运动超过 2 秒直接把这个 trial 剔除往往比硬插值更安全插值等于在一段完全无效的数据上画了一条平滑的线反而可能给后续统计引入虚假信号。4.3 带通滤波与短距通道回归滤波方面任务态 fNIRS 我一般用 0.01~0.1 Hz 的带通但这个范围要结合实验设计调整。如果 block 设计的任务周期比较长比如单个条件持续 20 秒以上低频截止可以放宽到 0.008 Hz如果是短事件相关设计用 0.01~0.2 Hz 更合适。除了滤波短距通道回归是近年来越来越被强调的一步。原理不复杂短距通道搜到的主要是头皮表层血流信号和长距通道里关心的皮层血流不是一回事把短距信号作为回归量放进 GLM可以去掉大部分全身性的生理噪声比如心跳、呼吸和梅耶波。Brainstorm 可以在预处理阶段把短距通道单独提取出来也可以到 GLM 阶段再把短距均值作为协变量放进去两种做法我都试过后者更灵活因为可以在模型里同时看到噪声项对结果的贡献。如果实验系统本身没有采集短距通道还有一个临时补救办法把某些长距通道里离头皮表面近的高频成分近似当作生理噪声。这个方法并不可靠只适用于没有硬件条件的早期探索正式分析时还是建议实验阶段就把短距通道设计进去。4.4 Modified Beer-Lambert Law 与浓度换算光学密度最终要换算成氧合血红蛋白 HbO 和脱氧血红蛋白 HbR 的相对浓度变化这一步用到的是修正的比尔-朗伯定律。简单地说就是利用两个波长的光衰减差异通过消光系数矩阵反解出两种色团的浓度变化。近红外光在组织中传播时氧合和脱氧血红蛋白对两个波长的吸收比例不同所以一双波长就能同时估计出两种浓度。实际使用时Brainstorm 会把 DPF差分路径因子考虑进去。不同脑区、不同年龄的 DPF 数值不完全一样大多数研究直接采用默认值但如果你对定量精度有要求最好在分析方案里写明 DPF 的来源这也是目前 fNIRS 研究报告规范里要求的基本信息。转换完成后时间序列浏览器里会同时看到 HbO 和 HbR 两条曲线。通常 HbO 的变化幅度比 HbR 更大、更稳定这也是很多文献把 HbO 作为主要指标的原因。看到曲线之后不要急着做下一步先放大检查一下任务窗口内是否有明显的响应形状如果有完全反向的变化要回头检查运动校正和滤波参数。5. 个体水平的 GLM 分析把任务相关激活扣出来5.1 为什么要用 GLM 而不是只看平均曲线不少初学者拿到 fNIRS 数据之后第一反应是做事件相关平均。平均曲线确实直观但实验里同时存在多个事件条件、低频漂移、运动残留和生理噪声时单纯平均很难把这些方差的来源分清楚。GLM 通过设计矩阵把任务条件、基线漂移、噪声回归量放在同一个模型里能够更干净地估计每个条件独立贡献的效应。Brainstorm 的 GLM 进程在 NIRS 分析相关分类下。选定数据之后主要需要设置下面几项每个刺激条件对应的事件组、血流动力学响应函数、想加入的协变量、要输出的统计量。血流动力学响应函数一般保持默认的 SPM canonical HRF如果你的任务窗口比较长也可以考虑加入时间导数用来吸收血氧响应峰值时间的个体差异。5.2 设计矩阵的理解与检查任务态 fNIRS 最简单的设计矩阵就是每个条件的 boxcar 函数与 HRF 做卷积。Boxcar 只在任务呈现时段取 1其余时间为 0卷积之后得到一条类似任务诱发血氧响应的理想波形。多个条件就是多列这样的波形再加上常数项和漂移项组成完整的设计矩阵。在 Brainstorm 的 GLM 界面里可以直接预览设计矩阵。跑模型之前一定要看一遍这个矩阵确认各条件列之间没有严重的共线性。Block 设计里如果条件间隔太短设计矩阵的列之间会变得高度相关beta 估计就不稳定。这种情况在实验设计阶段就要尽量避免至少保证 ITI 足够长不要短于一个血氧响应恢复到基线的时间。5.3 结果的解读与交叉验证GLM 跑完之后结果文件里包含每个通道的 beta 值和 t 值。把 t 值在 2D 通道布局上画出来能快速找出哪些通道在任务条件下更活跃。但我的建议是不要只盯着 t 值最大的通道还要回到平均曲线里人工确认一遍这个通道的 HbO 是否在任务窗口内上升HbR 是否呈现下降趋势。如果两者方向不符合经典血氧响应模式就要警惕这是运动伪影或通道噪声造成的假阳性。这个交叉验证的步骤虽然花时间但非常值得。我之前有一次 GLM 跑出一个很漂亮的激活通道簇结果回到平均曲线里仔细看才发现那个通道正好贴在颞浅动脉附近信号变化完全是心跳驱动的全身性振荡和任务一点关系都没有。如果没有这一步这个假阳性通道很可能就会混进组分析结果里。6. 结果可视化与导出怎么看、怎么存、怎么验证6.1 通道水平的 2D 显示与 3D 投影单被试分析阶段我使用最频繁的是二维通道布局图。把 GLM 得到的 t 值映射到通道位置用颜色深浅表示统计量大小激活的空间分布一目了然。这个布局图在 Brainstorm 里可以直接保存为 PNG 或 SVG组会展示完全够用。如果数据有可靠的通道三维坐标还可以把通道投到三维头皮模型上。Brainstorm 内置了 ICBM152 模板头皮曲面导入坐标文件后可以把每个通道的位置对应到模板头皮上直观检查通道覆盖区域。这一步对于后续做皮层投影很有用但对单被试通道水平分析来说不是必需没有坐标也可以先用二维布局图完成大部分判断。6.2 时间序列与统计量的导出导出这一步经常被忽略但它决定了你后续组水平分析是否顺畅。数据文件上右键选择 Export to file可以把时间序列矩阵导出成 CSV 或 MATGLM 输出的 beta、t、p 值也可以一并导出。我一般会把每个被试的 beta、t 值、以及 HbO 峰值时间整理成 CSV然后到 Python 里再整理成宽表方便后续做组水平 t 检验或非参检验。如果是团队协作把整个 Protocol 备份出来也非常方便。Brainstorm 的数据目录里保留了所有处理步骤和中间结果换一台电脑也能继续分析。这个特性在多人长期项目中非常实用不用每次交接都重新跑一遍流程。6.3 最后一步永远是回到数据本身在我的分析流程里最后一步始终是回到原始时间序列上看一眼处理后的数据。我会把带通滤波后的 HbO/HbR 和原始光强并排显示确认没有滤波边缘效应、没有运动校正留下的插值痕迹、没有明显的通道断连。这一步看着很基础却是排除大量低级错误最有效的手段。近红外的噪声源实在太复杂了探头松动、头发遮挡、皮肤血流变化、设备轻微位移任何一个都足以制造出看起来很漂亮但实际错误的激活模式。图形界面工具最大的价值就是迫使你在每个环节都看到数据只要每次都认真瞟一眼假阳性率就会明显下降。这篇先把单被试 fNIRS 分析的主要流程讲到这里。我自己第一次用 Brainstorm 跑 fNIRS 时在导入和通道检查上花的时间比预处理还要多所以如果你正卡在这些早期步骤上不用担心那是非常正常的。下一篇我打算写组水平分析多个被试的 beta 怎么合并、通道水平的 t 检验和非参检验怎么做、结果如何在组层面展示到时候可以直接接在这篇后面往下走。