ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

fNIRS光极可视化与通道坐标计算:NIRS-SPM实战指南

fNIRS光极可视化与通道坐标计算:NIRS-SPM实战指南 我是从生物医学工程转到脑功能成像方向的第一次处理 fNIRS 数据的时候兴致勃勃把采集到的原始信号预处理完准备画一张通道分布图放进论文里结果一运行 NIRS-SPM 的显示功能屏幕上弹出的光极坐标乱七八糟有些通道位置明显偏到了耳朵后面还有两个源和探测器距离只有 1 厘米。当时第一反应是设备坏了后来才明白问题出在我根本没搞懂 NIRS-SPM 里光极数据的组织方式和坐标计算逻辑。这个系列的文章就是想把这类问题一次讲透。本文作为【fNIRS 可视化学习】的第一篇聚焦两个最基础也最关键的操作基于 NIRS-SPM 做光极可视化以及计算每个通道的坐标。这两个操作听起来简单但它们决定了你后续所有统计结果的空间意义——通道放错位置后面跑出来的激活脑区再漂亮也是错的。适合刚开始接触 fNIRS 数据分析的硕博生、跨领域转到脑成像的研究人员以及被各种设备自带软件绕晕、想回到 MATLAB 生态里自己掌握数据的人。1. 为什么光极可视化和通道坐标是 fNIRS 分析里绕不开的第一步1.1 fNIRS 测量的空间位置由光极布局决定fNIRS功能性近红外光谱通过放置在头皮表面的光源Source和探测器Detector来测量大脑皮层血氧浓度的变化。近红外光从光源发出经过头皮、颅骨到达大脑皮层部分散射回来的光被探测器接收。一个光源和一个探测器之间的通路就构成了一个通道Channel这个通道记录的信号主要反映的是光路径上大脑皮层区域的血氧动力学变化。所以 fNIRS 对脑区的定位能力说白了就取决于光极贴在哪。通道覆盖的是额叶还是颞叶左半球还是右半球每一路信号对应什么脑区都是由光极位置决定的。如果光极位置错了那每一个通道的数据在空间上就没有意义。这也是为什么我在处理数据之前一定要先把光极可视化做出来确认一遍。这一步不需要花很多时间但能避免后面几个月都在错误的空间信息上做无用功。1.2 可视化暴露的问题比想象中多很多初学者觉得可视化只是画个图看看但实际上它承担了几件非常实际的检查工作确认光源和探测器是否覆盖了目标脑区。做前额叶认知实验结果光极全贴到头顶那数据再干净也没法回答你的科学问题。检查通道间距是否合理。fNIRS 光极间距通常在 2.5 到 4 厘米之间。如果两组光极之间距离突然变得很近或很远大概率是光极帽戴歪了或者记录标记时写错了位置。排查标记混淆。我自己就遇到过一次左右颠倒的情况设备记录里显示左边的通道实际上在右边。这种问题不通过可视化根本发现不了而一旦没发现最后统计结果显示的左右脑差异全是错的。为论文方法部分提供示意图。绝大多数 fNIRS 论文里都会放一张光极布局图把通道分布标注在脑模板上。这张图既是方法学上的必要信息也是审稿人第一眼会看的内容。1.3 通道坐标是连接个体数据和标准空间的桥梁每个人的头型、头围都不一样光极帽戴在不同人身上之后头皮上的绝对位置也会有差异。为了让不同被试的数据可以放在一起对比也为了能和 fMRI、EEG 的研究结果互相参照我们必须把一个被试的通道位置映射到一个标准空间中。这个标准空间最常用的就是 MNIMontreal Neurological Institute空间坐标用毫米表示三个方向分别是左右x、前后y、上下z。通道坐标算出来之后下游用途非常多在群体分析里做通道筛选比如只保留覆盖某个感兴趣脑区的通道、把激活结果和 fMRI 激活区做空间上的对比、用自动解剖标签比如 AAL 模板报告每个通道对应的脑区名称、以及在写论文时报告各通道的 MNI 坐标表。所有这些都依赖第一步做对每个通道的坐标本身要准确。2. NIRS-SPM 环境准备工具箱版本、路径设置与数据导入的隐性坑2.1 NIRS-SPM 在 fNIRS 分析生态里是什么地位NIRS-SPM 是伦敦大学学院相关团队开发、在 NITRC 页面持续维护的一套基于 MATLAB 的 fNIRS 数据分析工具箱。它把统计参数映射SPM的思路迁移到近红外数据上提供从数据导入、预处理、GLM 个体统计到群体统计的完整流程。它和 Homer 这类工具箱相比最大的特点就是统计部分非常强尤其是对 fNIRS 数据进行 GLM 建模时可以直接生成类似 SPM 风格的统计图。但很多中文社区的资料都集中在统计上反倒把光极可视化和通道坐标计算这两个最基础的功能给忽略了。实际上 NIRS-SPM 的这些基础功能同样稳定好用而且它的数据结构非常清晰你完全可以在它之上用 MATLAB 脚本做更灵活的操作。2.2 安装与路径设置以及我踩过的版本坑NIRS-SPM 的安装不复杂核心就三步。但是这三步里有个特别容易被忽略的坑我帮不少同学排查过相似的问题。第一步从 NITRC 项目页面下载最新版压缩包解压到某个不含中文也不含空格的路径下比如D:\Tools\NIRS-SPM。很多人在这一步会用默认路径解压到下载文件夹里而系统用户名如果是中文后面 MATLAB 加载东西就会出现各种莫名其妙的问题。第二步在 MATLAB 里把整个工具箱文件夹加入路径addpath(genpath(D:\Tools\NIRS-SPM)); savepath;注意genpath会把所有子文件夹都加进去这个很关键。因为 NIRS-SPM 内部有大量的函数分布在各个子目录中只addpath最高层文件夹的话运行一定报错。第三步检查工具箱是否能正常启动which nirs_spm如果返回了完整路径说明路径添加成功。如果返回未找到检查一下是不是文件夹名写错了或者 MATLAB 当前工作目录是不是被其他同名文件干扰了。版本方面老版本比如 v3.x对新设备的原始数据支持不太好尤其是 NIRx 的新格式文件读进去经常出现通道数量对不上、光极坐标是空矩阵这类问题。我建议直接用 NITRC 上发布的最新稳定版本。另外NIRS-SPM 依赖于 SPM 的部分主要是最后结果展示时的脑模板渲染如果你只做光极可视化和通道坐标计算不装 SPM 也能跑但如果你打算后面做漂亮的激活图还是提前装一个 SPM12 比较稳妥。2.3 数据导入从设备原始数据到 NIRS-SPM 结构NIRS-SPM 使用一种基于 MATLAB 的.mat结构体文件来管理数据。设备原始数据不能直接拖进去用先用工具箱的转换功能把数据转成这个结构。在 MATLAB 命令窗口运行nirs_spm会打开 GUI 主界面选择菜单里的Convert然后按提示选择你的原始数据文件。NIRS-SPM 支持很多常见设备的格式比如 NIRx 的.wl1和.csv、日立 ETG-4000/7000 的.csv、Artinis 的设备导出格式等。如果转换成功你会得到一个包含多个字段的.mat文件其中比较核心的字段包括字段含义nirs.CHG.optodes.pos光极的三维坐标单位通常是毫米nirs.CHG.optodes.sources每个光源对应的索引nirs.CHG.optodes.detectors每个探测器对应的索引nirs.CHG.prob通道source-detector 组合的对应关系我强烈建议你在转换完成后先仔细查看一下pos这个字段的尺寸。正常来说它应该是一个N×3的矩阵N等于光源数量加探测器数量。如果这个矩阵是空的或者行数对不上那说明原始数据里根本没有记录光极坐标后面所有可视化都做不了得回头从设备采集端重新导出带坐标的数据。2.4 这个阶段最容易踩的三个坑第一个坑是MATLAB 版本和工具箱版本不兼容。NIRS-SPM 有些版本在 R2020a 之后的高版本 MATLAB 里GUI 控件会显示比较奇怪甚至某些回调函数报错。遇到这种情况优先去 NITRC 检查有没有更新版本或者考虑用一个较老的 MATLABR2016b 到 R2019b 之间的版本通常最稳。第二个坑是数据的prob矩阵和光极列表不对应。prob矩阵的每一行代表一个通道第一列是光源索引第二列是探测器索引。如果这个矩阵里的索引值超出了pos矩阵的行数说明原始数据里的通道定义有问题。一个快速验证方法max(max(nirs.CHG.prob))应该小于等于size(nirs.CHG.optodes.pos, 1)。第三个坑是单位问题。不同设备导出的坐标单位可能不一样有的是厘米有的是毫米还有的设备导出的坐标已经经过了初步配准和原始头皮坐标混在一起。建议每次拿到数据先计算一下两个光极之间的欧氏距离如果不落在 20 到 50 毫米之间就要怀疑是不是单位换算出了问题。3. 光极可视化实操NIRS-SPM 界面操作与 MATLAB 脚本画图3.1 先搞清楚 NIRS-SPM 里光极信息的数据结构在动手画图之前必须把数据结构搞清楚。NIRS-SPM 在导入数据后所有光极相关的信息都在nirs.CHG这个结构里。以一套常见的光极布局为例假设有 8 个光源、8 个探测器那么pos矩阵就是一个 16×3 的矩阵前 8 行是光源坐标后 8 行是探测器坐标。sources和detectors两个向量则记录每一类光极的索引。比如sources [1 2 3 4 5 6 7 8]detectors [9 10 11 12 13 14 15 16]。而prob矩阵记录的是通道的定义方式。比如prob [ 1 9; 1 10; 2 9; 2 10; ... ]这就表示第 1 个光源和第 9 个探测器构成一个通道第 1 个光源和第 10 个探测器构成另一个通道以此类推。理解这个结构之后你可以直接用 MATLAB 画任何你想要的光极图而不用局限于 GUI 里那几个选项。3.2 NIRS-SPM GUI 里的可视化入口如果你不打算写脚本NIRS-SPM 的图形界面里也内置了查看光极位置的功能。方法是在主界面里载入一个被试的.mat数据文件然后找到菜单里的Display功能选Optodes Display或者类似的选项界面上会弹出一个 3D 散点图显示所有光极的位置。这个 GUI 在确认数据是否正常载入时很方便。它的局限也很明显没法自定义颜色、没法给每个通道编号、画出来的图分辨率不够高放进论文里基本不能用。所以我的建议是GUI 只用来快速检查数据正式画图还是用脚本。3.3 自写 MATLAB 脚本画出论文级的光极分布图我常用的一段脚本是这样的把光源、探测器、通道路径都画出来load(subject01.mat); opt_pos nirs.CHG.optodes.pos; srcIdx nirs.CHG.optodes.sources; detIdx nirs.CHG.optodes.detectors; figure(Color, w, Units, normalized, Position, [0.2 0.2 0.6 0.6]); % 光源用红色三角形 plot3(opt_pos(srcIdx, 1), opt_pos(srcIdx, 2), opt_pos(srcIdx, 3), ... r^, MarkerSize, 10, LineWidth, 1.5); hold on; % 探测器用蓝色圆形 plot3(opt_pos(detIdx, 1), opt_pos(detIdx, 2), opt_pos(detIdx, 3), ... bo, MarkerSize, 10, LineWidth, 1.5); % 画出每个通道的路径 for i 1:size(nirs.CHG.prob, 1) s nirs.CHG.prob(i, 1); d nirs.CHG.prob(i, 2); plot3(opt_pos([s d], 1), opt_pos([s d], 2), opt_pos([s d], 3), ... k-, LineWidth, 0.8); end xlabel(x (mm)); ylabel(y (mm)); zlabel(z (mm)); legend(Source, Detector, Location, best); axis equal; grid on; view([-90 90]); % 从头顶俯视方便看左右分布画完之后第一件事不是欣赏而是做两个检查。第一个检查是看左右分布。view([-90 90])这个视角是从头顶往下看此时 x 轴通常对应左右方向。用这个视角确认一下左侧半球的通道是不是在你的左手边右侧半球的通道是不是在右手边。如果你发现通道的左右和你的实验布局相反优先怀疑是pos矩阵的行顺序和实际光极编号不一致。第二个检查是看通道间距。写一个小循环计算每个 channel 两端光极的距离dist zeros(size(nirs.CHG.prob, 1), 1); for i 1:length(dist) s nirs.CHG.prob(i, 1); d nirs.CHG.prob(i, 2); dist(i) norm(opt_pos(s, :) - opt_pos(d, :)); end disp([min(dist) max(dist) mean(dist)]);如果 min 值小于 15 毫米或者 max 值大于 55 毫米基本都是数据有问题的信号。前者可能是探测器贴太近后者可能是有两个光极标记反了。别急着往后分析先把这一步调对。4. 从光极坐标到通道坐标中点计算与 MNI 配准的原理和实现4.1 通道坐标为什么取光源和探测器的中点很多新手都有这个疑问一个通道明明是一条通路为什么最后落成一个点这其实是 fNIRS 空间分析的一个常见近似处理。近红外光从光源出发到探测器接收其光路径呈现一个香蕉形状banana-shaped最敏感的区域在光源和探测器连线下方的中间部分大约对应皮层表面下 1 到 3 厘米的位置。为了在标准空间里表示这个通道最通行的做法就是取光源和探测器的三维坐标的中点作为该通道的坐标。这个中点坐标不是测量出来的而是从光极坐标推导出来的。所以光极坐标本身的质量直接决定通道坐标的质量。这也就是为什么我在上一节反复强调画图之后一定要先检查光极坐标有没有问题。4.2 用自己的脚本批量计算通道坐标在 NIRS-SPM 的数据结构下计算所有通道坐标的代码非常简洁nCh size(nirs.CHG.prob, 1); ch_pos zeros(nCh, 3); for i 1:nCh src nirs.CHG.prob(i, 1); det nirs.CHG.prob(i, 2); ch_pos(i, :) (nirs.CHG.optodes.pos(src, :) ... nirs.CHG.optodes.pos(det, :)) / 2; end算完之后ch_pos就是一个nCh × 3的矩阵每一行就是对应通道的三维坐标。这个坐标的位置是基于被试真实头皮空间的还不能跨被试直接比较。你可以先在一个被试上画一下这些中点观察通道空间覆盖是否均匀。4.3 为什么要配准到 MNI 空间以及配准的核心逻辑个体头皮坐标不能直接用于群体统计因为人的头型差异太大了。一个头围 60 厘米的成年男性和一个头围 54 厘米的女性即使光极帽佩戴位置一模一样同一个通道对应的真实脑区也可能有差异。所谓的配准registration就是通过一些解剖标志点把个体头皮坐标映射到一个标准参考空间。NIRS-SPM 里最常见的做法是用三个 fiducial 点鼻根nasion、左耳前点、右耳前点。通过仿射变换把这三个点对齐到 MNI 模板上对应的位置从而得到一个变换矩阵再用这个矩阵把所有的光极坐标和通道坐标都变换到 MNI 空间。在 NIRS-SPM GUI 中这个功能在Spatial菜单里一般叫做Registration或类似选项。界面会让你选择三个 landmark 对应的坐标输入之后工具箱会自动完成配准。要注意的是如果你使用的设备在采集时已经用三维定位仪比如 Polhemus记录过 fiducial 点的 MNI 坐标那配准过程就简单很多因为坐标参照系已经和 MNI 对齐了。4.4 NIRS-SPM 界面配准操作要点以常见的 NIRx 数据为例设备软件导出的.mat文件里通常已经包含了光极位置和 fiducial 信息。在 NIRS-SPM 中做配准基本就是这个流程通过nirs_spm启动工具箱。载入转换好的.mat文件。进入Spatial相关的配准菜单。按界面要求输入鼻根、左耳前、右耳前三个点的坐标。运行配准工具箱会输出变换矩阵并更新pos字段。配准完成后我再跑一遍 4.2 的代码算出来的ch_pos就是 MNI 空间下的通道坐标了。拿到这个坐标之后就可以做脑区标签匹配、跨被试对比等后续操作了。4.5 手动验证配准是否合理配准算法不会报错不代表结果就一定正确。我每次配准完都会做一个简单的验证看配准后的三个 landmark 坐标和 MNI 模板上对应位置的数值是否接近。鼻根在 MNI 空间大约在[0, 85, -30]附近左右耳前点大约在[±80, -20, -10]附近具体值因模板而异。如果配准后的坐标偏差超过 20 毫米就要回头检查输入坐标是否标错或者光极帽佩戴时整体偏移太多。5. 坐标算完别急着做统计先验证通道位置靠不靠谱5.1 把通道坐标叠加到标准脑模板上拿到 MNI 空间下的通道坐标后第一步不是赶紧跑 GLM而是把坐标画到标准脑模板上看看位置对不对。如果你装了 SPM12可以很轻松地在一个标准模板上叠加散点% 以 SPM 的 T1 模板为底图 spm(defaults, fmri); spm_jobman(initcfg); % 显示模板 spm_check_registration(T1.nii);但更轻量级的办法是在 MATLAB 里直接画一个简单的头部轮廓辅助判断。很多实验室不用 SPM 也能完成这一步直接把通道坐标点画在三维空间里用一个半透明的标准头模型文件叠加可以从 NIRS-SPM 自带模板里提取用alpha函数调整透明度就能看出通道是否落在头皮表面附近。5.2 用脑区标签核对通道对应的解剖位置坐标画在模板上只是第一步更严谨的验证是看每个通道落在哪个解剖脑区。常用的模板包括 AAL、Brodmann、Desikan-Killiany 等。NIRS-SPM 里有相关的工具或函数可以把 MNI 坐标映射到 AAL 脑区标签上。举个最简单的例子在 MATLAB 中使用 SPM 提供的spm_atlas相关函数输入一个 MNI 坐标返回对应的脑区名称。如果你预期 8 号通道覆盖的是背外侧前额叶DLPFC但查询结果显示它在感觉运动皮层那说明你的光极帽位置可能整体偏后了。这种问题在单个被试上还好但在群体数据里如果不纠正会导致不同被试的通道覆盖区域不一致统计时就会混入大量噪声。5.3 常见的异常模式与排查方法这个阶段常见的异常模式我归纳一下现象可能原因排查方法坐标整体偏移到模板外配准参数错误或 landmark 标错重新检查三个 fiducial 点坐标左右颠倒光源/探测器索引顺序错误对照设备记录逐一核对通道间距异常prob矩阵中光极配对错误确认prob每一行的 source-detector 组合是否与实验设计一致坐标全都挤在一个很小的区域单位不一致厘米 vs 毫米检查pos数值范围毫米应在 ±150 之间其中左右颠倒这个坑我印象太深了。有一回我用一套 16 通道设备采数据按照设备软件导出的列表通道顺序应该从左到右排列结果实际画出来之后发现左右完全反了。最后发现是当初光极帽佩戴时i 号光源的编号顺序和设备软件默认的相反这个问题如果不通过可视化发现后面统计分析里左右脑的对比就全反了。5.4 为论文整理通道坐标表当所有坐标验证通过后下一步就是把它们整理成论文需要的格式。fNIRS 论文里通常会有一个通道信息表列出每个通道的编号、对应的 source-detector 对、MNI 坐标x, y, z以及对应的脑区标签。我建议直接在 MATLAB 里生成一个表格方便导出到 Excel 或者在论文里排版T table((1:nCh), nirs.CHG.prob(:,1), nirs.CHG.prob(:,2), ... ch_pos(:,1), ch_pos(:,2), ch_pos(:,3), ... VariableNames, {Channel, Source, Detector, MNI_x, MNI_y, MNI_z}); writetable(T, channel_coordinates.xlsx);这个表格不仅是论文方法部分的素材也会成为后续分析时筛选通道的依据。6. 没有 3D 定位仪的实验室用什么替代方案估算通道坐标6.1 现实情况不是每个实验室都有 Polhemus很多刚开始做 fNIRS 的课题组设备是最基础的两波长便携式系统采集时确实没有用三维定位仪记录光极坐标。这种情况下NIRS-SPM 的完整配准流程就没办法直接跑因为缺少个体的 landmark 坐标。但这不意味着通道坐标完全没法做还是有几条务实的路可以走。6.2 方案一基于 10-20 标准位置做近似映射大多数 fNIRS 光极帽都是按照 10-20 系统设计的每个光极的位置基本对应某个标准脑电电极位置比如 F3、F4、P5 等。这时你可以查一个 MNI 空间下的 10-20 坐标表把光极帽上的每个位置对应到标准 MNI 坐标上。具体操作是记录每只光极帽上的 10-20 标签位置。找一份公开的 10-20 系统 MNI 坐标表很多论文的补充材料里都有或者从 EEG 社区的工具箱里提取。用这些坐标代替实际测量坐标作为pos填入 NIRS-SPM 结构。通道坐标仍按中点法计算。这个方案的优点是成本为零、操作简单缺点是精度有限个体间差异被完全忽略了。但如果你的研究问题涉及的是大尺度脑区比如前额叶和颞叶的对比这个精度基本够用。6.3 方案二参考 AtlasViewer 的配准管线如果你所在的团队已经在用 Homer 处理数据那恭喜你你其实已经有一个更专业的配准工具了。AtlasViewer它是 Homer2/3 配套的光极配准可视化软件可以把光极坐标配准到 ICBM152 模板上配准后导出的坐标可以直接用在 NIRS-SPM 之后的统计流程里。流程大致是在 AtlasViewer 里加载被试的光极位置文件手动或半自动标记 fiducial 点运行配准导出 MNI 空间下的通道坐标再把这些坐标整理回 NIRS-SPM 的.mat结构里。这个方案比纯 10-20 映射要精确但操作门槛也更高。6.4 没有定位仪的情况下哪些地方可以适当妥协我的个人建议是如果没有定位仪就别追求个体级别的精确配准而是把重点放在保证所有被试使用同一个模板坐标上。也就是说既然大家都没有个体坐标那每个被试都使用标准 10-20 位置对应的 MNI 坐标作为光极坐标。这样至少保证了群体定位的一致性统计分析时通道覆盖区域之间的偏差是系统性的而不是随机的。另外在论文中一定要如实报告坐标的来源是标准模板近似而非个体测量。审稿人通常能接受这种说明只要你在实验方法里写清楚坐标获取方式。6.5 延迟到采集阶段能做的补救措施如果你手头的实验设计还没开始采集那我强烈建议你至少购买一个便携式三维数字化仪或者联系学校平台的脑电实验室借用在每次采集前花十分钟记录被试的 landmark 和光极坐标。这笔时间的投入会在数据分析阶段省掉大量坐标对不对的纠结。如果确实无法购买设备一个折中办法是每次采集前在同一位置拍摄颅骨标志点的照片记录光极帽边缘与鼻根、耳前点的相对位置。后期即使只能用模板坐标近似你至少能判断被试间光极帽佩戴位置的偏移程度从而评估通道定位误差的大小。写在最后的一点提醒坐标相关的教训越早重视越好回到我开头那个翻车经历。后来我仔细排查发现那次问题有两个来源一是设备软件导出的坐标单位是厘米而不是毫米二是我自己在整理prob矩阵时把两个探测器的索引写反了。两个问题叠加画出来的通道分布图才会那么离谱。从那之后我给自己定了一个固定流程任何一批 fNIRS 数据在预处理之前先把光极坐标导出来画一遍图确认左右方向、通道间距、坐标范围都正常再继续往下走。这套流程看着多花了十分钟但多次帮我避免在错误数据分析上浪费好几天时间。如果你刚开始接触 NIRS-SPM别急着直接跑统计功能。先学会把光极和通道的坐标掌握在自己手里你会对整个 fNIRS 空间定位的逻辑有更扎实的理解。下一篇我会接着写 NIRS-SPM 里数据预处理和 GLM 建模的那些坑等到统计结果能叠加到这些验证过的通道坐标上时你会觉得前面的功夫都值得。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进