FEATURED · 精选文章

DTI数据预处理实战:eddy与topup原理及完整流程解析

发布时间 / 2026/9/20 14:51:45
来源 / 创域科博编辑部
栏目 / 资讯中心
DTI数据预处理实战:eddy与topup原理及完整流程解析 1. 为什么DTI数据非做eddy_topup不可看不见的畸变正在毁掉你的纤维追踪我先讲一个自己踩过的坑。几年前我处理一批小鼠DTI数据FA图怎么看怎么漂亮各向异性分布也符合预期可一旦做纤维追踪胼胝体纤维在到达皮层之前就莫名其妙地「转弯」跟解剖结构完全对不上。排查了大半个月最后发现罪魁祸首根本不是追踪算法参数而是数据预处理阶段漏掉了涡流校正——DW图像在读出方向上被压缩/拉伸了十几个像素纤维方向估计自然全盘皆错。这个教训让我养成了一个习惯任何DTI数据不管来自哪个厂家、不管被试是人是鼠、不管b值大小先过一遍eddy_topup这个pipeline再说。先交代清楚一个概念。DTI采集时你得到的不是一张图而是一大摞一个或多个b0无扩散加权参考像加上几十个甚至上百个不同梯度方向的扩散加权像DW images。每个梯度方向激活的扩散梯度线圈组合不同会在组织内感应出大小方向各异的涡流eddy current导致DW图产生几何形变与此同时空气/骨骼/组织交界处的磁化率差异会让主磁场变得不均匀这种不均匀在EPI读出过程中被放大造成信号移位和信号丢失再叠加受试者不可避免的头动三种伪影混合在一起DTI参数估计就是在一堆错位的图像上做毫无意义的拟合。为什么偏偏是FSL的eddy_topup这套流程成了事实标准因为它把两个核心问题分开治理了topup负责管磁化率畸变eddy负责管涡流和头动两者通过一个位移场无缝衔接。而且FSL是开源的有完善的文档和active的社区你不用去赌商业软件里的黑盒算法。这篇我就按照自己实际跑通项目的顺序把从原始DICOM到最终FA、纤维方向图的完整处理链路掰开揉碎讲清楚。2. 体系搭建与数据组织90%的失败其实发生在正式命令之前2.1 FSL安装和运行环境准备eddy_topup这套工具链依赖FSL主程序因此第一步是把FSL装好。官方提供Linux和macOS版本Windows用户我建议用Windows Subsystem for LinuxWSL2或Ubuntu虚拟机否则会踩到大量路径和权限的暗坑。安装方式有几种通过FSL官方安装脚本推荐会自动处理依赖用包管理器安装如apt install fsl或conda install -c conda-forge fsl直接用官方提供的Docker/Singularity容器镜像。无论哪种方式装完后要让环境变量生效检查一下是否装到位# 确保FSLDIR被正确设置 echo $FSLDIR # 查看eddy、topup这些核心可执行文件是否存在 which eddy_openmp topup applytopup eddy_quad dtifit如果你拿到的是老版本FSL6.0.5之前建议升级到6.0.5以上因为eddy在后续版本里引入了outlier detection那套基于高斯过程预测的方法校正效果提升明显。另外eddy有两个版本CPU版本eddy_openmp和GPU版本eddy_cuda。只要有NVIDIA显卡强烈建议用CUDA版速度能快5到20倍——DTI几十个方向的数据CPU版本往往要跑三四个小时GPU版本十几分钟就结束。2.2 原始数据的目录结构与命名规范磨刀不误砍柴工我先说数据组织因为它直接决定你后面能少踩多少雷。拿到一张被试的DICOM数据后我一般都会先按下面这个方式整理analysis/ ├── sub-01/ │ ├── raw_diffusion/ │ │ ├── DW_MR_0001.dcm ... 所有扩散序列的DICOM │ │ └── AP和PA相位编码方向的b0目录如果有 │ ├── dwi.nii.gz # DICOM转出的4D NIfTI │ ├── bvecs │ ├── bvals │ ├── AP_b0.nii.gz # 单独提取的AP方向b0 │ ├── PA_b0.nii.gz # 单独提取的PA方向b0 │ ├── acqparams.txt │ └── index.txt这个命名规范不是强迫症而是为后面的第3、4节做铺垫。尤其注意不要把所有原始文件一股脑堆到一个目录里topup和eddy中间会产生一堆中间产物如果文件名没有规划好一个不小心就会把之前的输出覆盖掉。2.3 DICOM转NIfTI方向信息不对后面全白做DTI数据从扫描仪导出后通常是一堆DICOM文件需要把它转成FSL能识别的NIfTI格式及配套的bvecs、bvals文件。我在项目里习惯用dcm2niix做转换因为它在处理扩散梯度方向表方面非常可靠。dcm2niix -f %p_%s -o sub-01/raw_diffusion sub-01/raw_diffusion/转换完成后务必立刻检查两件事方向信息是否正确运行fslreorient2std dwi.nii.gz dwi_reorient.nii.gz把图像reorient到标准轴向同时用fslhd查看qform和sform确保它们一致且符合预期。FSL很多工具在做配准时依赖sform如果这里的矩阵有问题后续配准会直接翻车。bvecs/bvals内容是否与图像一一对应打开bvals看扩散梯度b值如果不是整数要确认是否包含在b0中打开bvecs看梯度方向是否已经做了范数归一化。有一个细节在这里提前提醒如果扫描时用了多次采集比如隔了几分钟扫描了两次dcm2niix产生的bvecs会把不同tag的数据拼在一起你需要结合扫描protocol确认bvec的顺序没有被打乱。顺序一旦对错位所有方向编码全部乱套eddy跑得再漂亮也救不回来。2.4 反向相位编码b0的采集设计topup的地基前面说了topup要做的事是通过比较两个「互补」的b0图像来估算磁化率引起的位移场。这两个b0必须满足一个条件除了相位编码方向相反或者读出方向相反其他成像参数完全一致。具体来说良好的采集方案是每个b0至少采集2~3个volume这样topup在估计位移场时有更充足的信噪比AP和PA方向b0的位置、层数、分辨率、TE、TR都要完全一致如果协议允许尽量把AP/PA b0紧挨着采集减少被试移动造成的误差扩散加权像本身采用AP方向采集而单独加一段PA方向的b0或者反过来这是最标准的结构。如果你的扫描协议只有单一方向b0没有reverse phase encoding b0那么topup这条路基本走不通——不要试图硬跑老老实实回去补扫数据或者申请同批次的其它被试扫描结果作为模板。有人尝试用T1配准来近似效果都很勉强我不推荐。3. topup实战用一对反向b0算出全脑位移场3.1 acqparams.txt的写法这是topup最容易出错的地方topup需要知道两件事每张b0图像的相位编码方向以及对应的总读出时间TotalReadoutTime。这些信息要写进acqparams.txt格式是四列或五列。我们项目中最常见的写法是这样0 -1 0 0.0624354 0 1 0 0.0624354这四列的含义分别是x方向、y方向、z方向的相位编码梯度幅值最后一列是TotalReadoutTime单位秒。第一行0 -1 0表示相位编码沿前-后方向PA即从身体前方到后方采集第二行0 1 0表示后-前方向AP。FSL的官方约定是1代表正方向-1代表负方向在标准的神经影像学坐标系中-1在y方向代表PA1代表AP。如果你用的是横断面扫描且相位编码沿左右方向x轴那就把某一行改成1 0 0或-1 0 0。有些序列读出方向是左右方向比如某些3T系统为了配合匀场那就需要和序列工程师确认然后按实际写。TotalReadoutTime从哪来两种渠道直接从DICOM头文件里读不同厂商字段名不同Siemens通常在Protocol Name或者dcm2niix会输出ReadoutTime从扫描参数的Bandwidth Per Pixel Phase Encode、EPI factor等算出TotalReadoutTime (EPI_factor - 1) * dwell_time。其中dwell_time可以从DICOM头Pixel Bandwidth转化过来。如果你确实拿不到这个值可以在FSL的topup里用--readout0.05这类合理估计值做初评但最终要用QC来确认形变是否合理过于离谱就说明数值不对。顺便说一个验证的小技巧如果采集时做了多个b0重复你可以在acqparams里列出多行相同方向topup会把所有b0一起纳入计算增强鲁棒性。把两行重复三次的写法是0 -1 0 0.0624354 0 -1 0 0.0624354 0 -1 0 0.0624354 0 1 0 0.0624354 0 1 0 0.0624354 0 1 0 0.06243543.2 准备输入把b0从原始dwi中分离在跑topup前需要从4D的dwi文件里把b0 volume提取出来。我的方法是用fslroi或fslselectvols按volume索引截取而不是直接用fslmaths -Tmean对所有b0求平均——因为你在后续的eddy里还要用原始多volume b0作为配准参考这个阶段只需要为topup生成一个高信噪比的文件。# 假设b0排在扫描序列的最前面且共有5个volume fslroi dwi_reorient.nii.gz b0_AP_only.nii.gz 0 5 # 如果b0不是连续排列的用fslselectvols更灵活 fslselectvols -i dwi_reorient.nii.gz -o b0_AP_only.nii.gz --vols0,4,5如果有独立的PA方向b0序列同样提取前几个volumefslroi PA_b0_raw.nii.gz b0_PA_only.nii.gz 0 3然后把两个b0纵向堆叠成一个4D文件一路喂给topupfslmerge -t b0_all.nii.gz b0_AP_only.nii.gz b0_PA_only.nii.gz合并后的b0_all.nii.gz必须有对应的acqparams.txt——有多少个volume就写多少行顺序要和merge时的顺序完全一致。这里是我的血泪教训merge的顺序和acqparams的顺序错位topup会把AP当成PA来算输出的fieldmap完全反号eddy里所有图像都会被推得更歪。3.3 运行topup与结果解读正式运行topuptopup --imainb0_all.nii.gz \ --datainacqparams.txt \ --configb02b0.cnf \ --outtopup_results \ --foutfieldmap_hz \ --ioutunwarped_b0几个关键参数说明--configb02b0.cnfFSL自带的一个配置文件它定义了B-spline的spacing、正则化权重等通常不需要修改--outtopup_results会生成一个包含位移场系数的4D文件后续eddy和applytopup都要用到--foutfieldmap_hz输出的fieldmap单位Hz你可以把这张图在FSLeyes里load出来看一眼——它在脑实质区域应该呈现平滑的空间梯度在鼻窦、耳道附近出现剧烈变化是正常的但如果全脑都是噪声般的剧烈跳动说明输入b0配准得不好或者acqparams写错了--ioutunwarped_b0校正后的b0用于快速QC。跑完之后一个简单但有效的QC方式是把原始b0与unwarped_b0叠加在FSLeyes里切换融合显示。正常情况下脑轮廓在unwarped_b0里应当前后对称颞叶底部的信号丢失磁化率伪影造成的高信号空洞会有明显的修复。如果你的数据本身磁化率畸变很轻这个差异可能不大但不要因此就跳过topup——eddy需要一个统一的空间基准。3.4 applytopup把位移场应用到你真正的b0上topup输出的位移场是基于你提供的多个b0联合估计的。但真正要用于eddy的是整个4D扩散数据尤其要以高信噪比的b0作为参考。所以需要先用applytopup把你最完整的那个b0通常是原始4D数据中所有b0的均值unwarp一下fslroi dwi_reorient.nii.gz b0_for_ref.nii.gz 0 5 fslmaths b0_for_ref.nii.gz -Tmean b0_ref_mean.nii.gz applytopup --imainb0_ref_mean.nii.gz \ --datainacqparams.txt \ --inindex1 \ --topuptopup_results \ --outb0_ref_unwarped \ --methodjac解释一下参数--inindex1告诉applytopup输入图像对应acqparams.txt里的第1行也就是AP方向--methodjac在重采样时使用Jacobian调制来修正强度。通常我建议加上因为它能补偿由畸变导致的信号拉伸或压缩对后续FA估计有好处。到这里topup链路就完成了。你得到了两个关键产物topup_results位移场和b0_ref_unwarped做eddy的参考b0。下面进入eddy主战场。4. eddy实操一步到位处理涡流、头动和离群值4.1 eddy到底做了什么给每张DW图像纠正变形的世界eddy的设计初衷是估计并校正三类问题涡流变形不同梯度方向产生的涡流会带来不同的几何形变理论上可以用简单模型描述但实际会受具体扫描仪和梯度硬件影响头动和生理运动被试不会像石头一样一动不动几毫米的移动在几十个方向里会累积出可观的误差outlier离群值比如被试突然咳嗽、吞咽某一张图整体毁掉如果不检测出来它会破坏模型的参数估计。eddy的核心思路是把所有DW图像配准到一个参考空间通常是topup校正后的b0同时利用DTI本身的重建模型来预测每张图的强度这样既能让几何对齐有据可依又能剔除非刚体的异常值。它输出的不仅有校正后的图像还有一套描述运动的参数文件方便你检查被试头动情况——这在做临床研究或儿童被试时格外重要。4.2 运行前的数据准备index.txt和eddy参数逐项讲运行eddy前首先要确认输入数据已经满足它的胃口--imain完整的4D扩散加权数据可以是被topup处理前的原始数据eddy内部会自己调用applytopup逻辑做结合--mask一个二值化的脑mask建议基于b0_ref_unwarped生成--acqpacqparams.txt--index一个和4D volume数量等长的文本文件每个数字代表这一volume对应的相位编码方向在acqparams.txt里的行号--bvecs/--bvals梯度方向表--topuptopup结果的basename--out输出前缀。生成index.txt有一个方便的命令# 假设你的4D数据共有70个volume其中前5个是b0其余65个是DW且全部为AP方向采集 indx for ((i1; i70; i)); do indx$indx 1; done echo $indx index.txt # 然后用文本编辑器检查是不是每个数字都是1如果相位编码方向不止一个比如你采集了交织的AP/PA方向stored bvecs和bvals顺序需要一致index.txt里对应位置填对应的行号不能全填1。脑mask我一般这样生成bet b0_ref_unwarped.nii.gz b0_brain -f 0.3 -m mv b0_brain_mask.nii.gz mask.nii.gz这里的-f阈值需要根据图像信噪比微调。对于高b值数据比如b3000以上b0本身SNR就不差-f 0.3基本够用。但如果你发现mask把皮层薄片都剔掉了调低f到0.2如果发现包含了脑外脂肪信号调高到0.4。一个over-inclusive的mask比under-inclusive好因为eddy内部会再约束。然后是eddy的核心命令我这里以GPU版本为例eddy_cuda10.2 --imaindwi_reorient.nii.gz \ --maskmask.nii.gz \ --acqpacqparams.txt \ --indexindex.txt \ --bvecsbvecs \ --bvalsbvals \ --topuptopup_results \ --outeddy_corrected \ --data_is_shelled \ --repol \ --mporder6 \ --slice_to_vol \ --fwhm10 \ --flmquadratic \ --ol_typeboth \ --nvoxhp1000 \ --verbose参数太多容易懵我按重要性拆开讲和模型拟合相关的--flmquadratic这是涡流场模型的阶数。linear模型假设涡流只随梯度幅度线性变化quadratic增加了一个二次项能更好地刻画高阶非线性涡流。只要数据量够超过30个方向建议都用quadratic。--data_is_shelled如果你的数据是单壳即所有DW的b值基本一致就加这个如果用多壳数据比如同时有b1000和b2000不要加eddy会自己估计每个壳的参数。--repol与--ol_typeboth这会打开outlier detection和替换both表示同时检测slice outlier和volume outlier。开了它之后eddy会预测每张图在每个slice位置的理论强度如果实际强度偏离预测超过一个阈值就把这个slice标记为outlier并用预测值替换。这个功能对实验中有突发运动的场景极其有用代价是计算量略有增加。--mporder6与--slice_to_vol这是针对slice-level头动的校正尤其适用于被试有明显呼吸/心跳导致的层面内位移。加上后计算量显著增大但对数据质量提升明显。如果你处理的是动物固定头部数据或者被试头动极小的数据可以考虑不开启以节省时间。--nvoxhp1000控制用来估计模型参数的体素数默认是1000对于大数据量可以适当加大到2000但收益有限。跑完eddy后如果你开了--verbose在日志里会看到每一轮迭代的meandisp、size和 RMS movement。一个参考范围正常成年志愿者eddy输出里的平均位移值一般在0.2~1.5mm之间如果超过3mm说明被试头动比较严重需要留意图中的质量必要时把--mporder加大或考虑剔除部分volume。4.3 eddy产出的关键文件与QC别只盯着eddy_corrected.nii.gzeddy结束后会输出一堆文件核心包括eddy_corrected.nii.gz校正后的4D数据这是你下一步跑dtifit的输入eddy_movement_rms每个volume相对前一个volume的位移RMS可以画出来看有没有突变eddy_restricted_movement_rms不考虑旋转只考虑平移的RMSeddy_outlier_report文本报告列了被标记为outlier的slice数、volume编号eddy_parameters每个volume的6个运动参数3个平移3个旋转。QC是这一环的重中之重。我会做三件事1. 看运动曲线。把eddy_movement_rms画成图如果有某个volume位移突然超过前一个好几倍结合outlier report看它是否是同一时段。如果是考虑在后续分析中剔除这些坏volume或者对它们做额外修复。2. 看outlier报告。eddy_outlier_report里会输出每个volume中outlier slice的百分比。一般来说10%以内可接受超过30%就要高度警惕。处理方式如果确实只坏了一个volume可以在dtifit前用fslroi剔掉它并同步更新bvecs/bvals和index如果很多volume都坏了说明被试完全不配合只能考虑重新扫描。3. 跑eddy_quad。FSL 6.0之后的标配工具能生成一张HTML报告里面包括eddy_quad eddy_corrected -idx index.txt -par acqparams.txt -m mask.nii.gz -b bvals -g bvecs报告中我最常看的是两幅图qc_Figure_FA.png校正后的FA图是否有明显残留伪影和qc_Figure_motion.png运动参数的轨迹。另外它还能算出一个“outlier significant voxel map”某种程度可以帮你定位那些运动伪影严重的区域。4.4 eddy与topup的衔接原理为什么需要一个参考b0eddy的工作不是团成一次把所有事情都干完它的内部流程其实分两步先用topup算出的位移场把原始DW图像unwarp一次再通过比对当前DW图与预测的无畸变图像来估计头动和残余涡流。这就是为什么eddy要求你把--topup参数指向topup结果同时要求你把DW图像保持原始的几何位置不要提前做任何其它形式的配准。这个设计有一个非常现实的好处你不用担心校正后的图像被配准到哪个空间因为eddy的输出天然就和你的b0对齐。这个b0是你做diffusion tensor fitting的空间后续做T1配准时也以它作为中间桥梁。所以topup出来的topup_results不要删eddy全程都要用它但你也不用担心它的格式有多复杂只要路径别乱就是。5. 把pipeline串起来一条命令从原始数据到FA、纤维方向图5.1 我常用的完整流程脚本当一次项目要用到几十个被试时我不会每个被试都手动敲命令而是写一个shell脚本一次性把上述步骤串联起来。这里分享一个我项目中使用且验证过的简化版脚本供你参考#!/bin/bash sub$1 # Step 1: 进入目录 cd ${sub} # Step 2: DICOM转NIfTI假设已有dcm2niix和bvecs/bvals dcm2niix -f %f_%p -o . raw_diffusion/ # Step 3: Reorient到标准 fslreorient2std dwi.nii.gz dwi_reorient.nii.gz cp dwi_reorient.nii.gz dwi.nii.gz # 覆盖简化后续命名 # Step 4: 提取AP/PA b0用于topup fslroi dwi.nii.gz b0_AP.nii.gz 0 5 # 若b0在最前 fslroi PA_b0_raw.nii.gz b0_PA.nii.gz 0 3 fslmerge -t b0_all.nii.gz b0_AP.nii.gz b0_PA.nii.gz # Step 5: 写acqparams注意与merge顺序对应 # 这里以AP为正方向第一行PA为第二行为例 printf 0 1 0 0.062\n0 -1 0 0.062\n acqparams.txt # Step 6: 运行topup topup --imainb0_all.nii.gz --datainacqparams.txt \ --configb02b0.cnf --outtopup_results \ --foutfieldmap_hz --ioutunwarped_b0 # Step 7: 生成mask用topup校正后的b0来跑bet bet unwarped_b0.nii.gz b0_brain -m -f 0.3 # Step 8: 运行eddy eddy_cuda10.2 --imaindwi.nii.gz --maskb0_brain_mask.nii.gz \ --acqpacqparams.txt --indexindex.txt \ --bvecsbvecs --bvalsbvals --topuptopup_results \ --outeddy_corrected --data_is_shelled --repol \ --mporder6 --slice_to_vol --fwhm10 --flmquadratic \ --ol_typeboth # Step 9: 结构像配准可选用于后续T1空间分析 # 先将b0参考像和T1配准获得从dwi到t1的变换 epi_reg --epib0_ref_unwarped.nii.gz --t1T1_brain.nii.gz \ --t1brainT1_brain.nii.gz --outdwi2t1 # Step 10: 计算张量 dtifit -k eddy_corrected.nii.gz -m b0_brain_mask.nii.gz \ -r bvecs -b bvals -o dti这里有一个细节dtifit直接使用eddy_corrected都要配合同一套mask和bvecs/bvals顺序千万不能错。dti输出里dti_FA.nii.gz和dti_V1.nii.gz就是下游统计和纤维追踪的输入。5.2 阶段化拆解与断点续跑我并不是建议所有人都一次跑到底。对每个被试先跑前6步topup链路QC通过后再跑eddy链路这比一股脑全跑完再回看要稳得多。原因很简单eddy如果用了错误的mask或acqparams产生的错误可能会在后面的QC里完全暴露不出来——运动参数看起来正常FA图看起来也大体对但纤维方向已经是错的。所以我的实际建议是两条腿走路一条腿是快速流水线顺手把topup和eddy都跑完然后从头到尾质量检查一遍另一条腿是严谨方式每个环节都输出中间产物并QC结束后再进入下一步。如果你用严谨方式在每个阶段需要在代码里记录eddy或topup的具体调用时间方便对比不同时期运行的结果比如换参数重新跑。5.3 常见报错和踩坑速查表这里按照我自己项目里遇到的频率排一个表方便以后直接对照现象原因处理方案topup报错Implausible brain maskb0里可能没有足够的脑组织或者mask生成参数太紧检查bet的-f值重新生成maskeddy运行极慢但CPU占用低没有用GPU版本或CUDA库问题换成eddy_cuda检查nvidia-smieddy报错Index file has wrong number of entriesindex.txt的行数与4D volume数不一致用fslinfo dwi.nii.gz查看第四维大小重新生成index校正后FA图出现大面积条状伪影--mporder过大或--slice_to_vol导致过度拟合降低--mporder或去掉--slice_to_vol重跑bvecs方向和图像方向不对应dcm2niix转换时方向矩阵错误或旋转过图像但未更新bvecs用fslreorient2std后再fslcpgeom校正bvecs5.4 关于GPU资源和批处理执行的一些经验eddy是这套pipeline里最吃算力的一环。我自己的工作站是两张NVIDIA RTX 3080处理一个64方向、2mm各向同性分辨率、约5分钟扫描的成人大脑数据eddy全程大概10~15分钟如果不开GPU同一份数据用eddy_openmp要跑4~6小时。所以有条件的话GPU是刚需。对大批量数据别手动一个个敲命令。写一个循环脚本把每个被试当成参数传进去for sub in sub-01 sub-02 sub-03; do bash run_eddy_topup.sh ${sub} done同时可以在每个被试的目录下生成一个log子目录把eddy的输出导进去eddy_cuda10.2 ... ${sub}_eddy.log 21这样哪一步挂了、为什么挂回溯起来非常方便。6. 进阶调参与备选方案什么时候改参数、什么时候换路子6.1 根据数据特点调整eddy参数默认参数是FSL作者用大量成人脑数据调出来的但人的数据千差万别至少这几个场景你应该会用到数据是婴儿或儿童头动通常更大但体积更小我会把--fwhm从10降到6~8让配准更敏感同时--repol必须开着因为孩子配合度低outlier出现的频率更高。数据是病人可能有白质病变如果病变区域的信号本身异常dtifit前后的FA计算需要谨慎eddy里--flm可以保留quadratic但要注意不要让病变的异常信号过度影响全局参数--nvoxhp可以适当增加到2000让模型更稳健。高b值b≥3000数据DW图像SNR天然低此时--data_is_shelled仍然要开着但--repol的outlier检测可能把一些真实低SNR的点误判为outlier。建议把--ol_typeboth里对volume的阈值放宽比如设置--ol_threshold3默认2.5。多壳数据不要加--data_is_shelled并且建议用--fwhm较小的配准方式因为不同壳对比度差异大默认参数容易出现过拟合。6.2 如果采集时没有反向b0备选方案与局限现实中的确会遇到老数据或历史项目没有reverse phase encoding b0的情况。此时topup没有输入你有几条路直接用eddy的--topup留空eddy可以只做涡流和运动校正不做磁化率畸变校正。对磁化率伪影不重的区域比如皮层影响不大但颞叶底部、眶额叶这些伪影重灾区会保留明显的几何失真纤维追踪在这些区域会有系统性偏差。用T1像配准来估算b0的位移FSL有一个工具epi_reg --dwi可以把DW图像配到T1上理论上能部分纠正几何变形但它的精度远不如topup直接估计位移场尤其在磁化率变化剧烈的区域很容易过拟合。用其它工具做替代比如TORTOISE它有自己的一套DRBUDDI算法用双向b0和结构像结合或者ANTs中的antsRegistration配合SyN做b0到T1的配准。这些方法在某些场景效果不错但都默认你的b0数据本身没有严重畸变——如果你的b0扭曲很厉害光靠配准很难完全纠正。我的判断是如果项目允许重扫优先重扫补一个反向b0。CT和磁共振扫描时间不便宜但在数据质量上一分钱一分货后面数据分析省掉的大量返工成本往往远超补扫的时间成本。6.3 位移场可视化别等到FA图出来才发现问题有经验的同行会习惯在拿到fieldmap_hz.nii.gz后先用fslview或者FSLeyes做一次系统性检查。我会通过下面三步看位移场看fieldmap的空间分布在脑皮质区域fieldmap应该是一个平滑变化的场靠近颅底、鼻窦附近显示强烈的信号无论是正负都有可能这是正常的如果全脑都出现高频噪声说明topup的B-spline拟合过度了。看unwarped_b0与原始b0的差异重点看脑轮廓、脑室边界、颞叶底部的形状差异。矫正后的图像应该有更对称的脑前后径脑干和颞叶位置更接近T1像。看fieldmap与b0的配准程度Fieldmap的强信号边缘应该在颅骨、空气交界处和b0的脑表面对齐。如果fieldmap的强信号跑到了脑内说明acqparams或配置有问题。这一步发现问题比等eddy全部跑完再回头debug能节省几个小时。7. 后处理小贴士把eddy_topup的成果对接进下游分析eddy校正完的4D数据和对应的bvecs/bvals是几乎所有下游分析的起点。我就大致梳理几个常见方向张量拟合和FA/MD计算dtifit或者dtifit_VD一步到位输出FA、MD、V1、V2、V3等纤维追踪probtrackx2或fdt需要用到bedpostX的结果bedpostX的输入就是eddy_corrected的mask和bvecs/bvals中间不需要再做其它校正TBSS做群体统计时通常先把每个被试的FA图配准到FMRIB58_FA模板模板对齐过程会把eddy校正后的个体FA空间扭曲到模板空间直接使用即可用MRtrix做的替代流程很多人也会用dwi2response、dwi2fod这些MRtrix工具同样以eddy_corrected为输入。如果你要同时跑两大平台务必注意bvecs的轴方向约定不同MRtrix默认要求bvecs按行排列FSL也是按行但如果以前的脚本用了转置需要仔细核对。根据我的经验做完eddy_topup之后再优化很多此前让人头疼的坏数据往往还有救。比如某些被试在扫描时抖动导致1~2个volume完全废掉--repol会自动识别并替换如果--repol没识别到你还可以手动把那些volume从4D里删除同步更新bvecs、bvals、indexdtifit依然能出结果——这就是eddy pipeline的容错性所在。8. 写在最后参数是死的但你的数据是活的eddy_topup这套工具链看似命令多、参数杂核心逻辑其实就两句话用反向b0估计磁场畸变用DTI模型自约束估计涡流和运动。只要理解了这两条主线绝大多数参数其实都是在调节“对数据做多少假设”的程度。从我这些年处理DTI数据的体会来说最容易翻车的永远不是命令本身而是对数据的一知半解。比如不同厂家的序列默认设置不同同样的acqparams写法在一台机器上跑得很好换一台机器却惨不忍睹根本原因多半是readout time算错了再比如你自以为拿到了AP/PA b0但后处理的DICOM里其实混合了其它序列提取b0时把不必要的volume塞进去导致topup估计出伪影。最后分享一个我每次交付数据前都会做的“终审”操作把每个被试的eddy运动参数、outlier报告、FA图、fieldmap四样东西放在同一个文件夹里用脚本生成一个总览PDF。哪怕你不是强迫症这么做也能让你在写方法部分时节省巨量时间——审稿人问起数据质量你直接把这个PDF发过去什么问题都清楚了。这个习惯我保留到现在每次做一批新数据都不例外。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻