ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

影像转录组学:MRI与基因表达关联分析的MATLAB代码解析

2026/8/31 14:38:21 拓冰建站 浏览量
影像转录组学:MRI与基因表达关联分析的MATLAB代码解析 简介本资源是一套面向计算机、电子信息工程及数学等专业本科生的跨模态神经影像分析工具包聚焦于将结构MRI脑图与艾伦人类大脑图谱AHBA微阵列基因表达数据进行空间关联建模适用于课程设计、期末大作业及毕业设计等实践场景。压缩包共4个文件3个MATLAB脚本文件用于网络可视化、PLS回归建模与受体分布映射1个Markdown格式说明文档总大小仅24KB轻量易部署适配MATLAB 2014a至2021a多个版本。已有116人学习下载代码采用参数化编程范式关键参数集中定义、注释详尽、逻辑清晰附赠可直接运行的案例数据显著降低入门门槛。使用者可快速复现基因表达-脑结构关联分析流程掌握AHBA数据预处理、空间标准化、多模态对齐及统计建模等核心技能为后续开展脑连接组学或计算精神病学研究奠定实操基础。 看到“将MRI脑图与来自微阵列数据的基因表达艾伦人类大脑图谱相关联matlab代码.zip”这个标题我心想又是一个典型的影像转录组学项目。这种项目的本质是把MRI扫描看到的脑结构或功能指标与艾伦人类大脑图谱AHBA微阵列数据测到的基因表达放在同一个空间里做关联分析。代码用MATLAB写处理对象是AHBA的微阵列表达矩阵和预处理后的MRI脑图适合研究基因表达如何在大脑宏观尺度上塑造结构差异、或者反过来用影像指标反推分子机制的人参考。这套流程目前在神经影像与基因组学交叉领域已经不算新鲜但真要自己从零搭一遍坑比想象中多得多。1. 项目到底解决什么问题影像转录组学的核心思路1.1 什么是MRI与基因表达关联分析先给不熟悉这个方向的朋友解释一下背景。MRI在临床和科研里看的是脑的宏观属性灰质体积、皮层厚度、白质纤维走向、血氧信号变化、功能连接强度等等。这些属性归根到底受分子水平调控基因的表达差异会通过蛋白质合成、突触可塑性、髓鞘化等途径影响脑区的大小和活跃程度。艾伦人类大脑图谱Allen Human Brain AtlasAHBA把“基因表达”放进了三维脑空间里它用微阵列芯片在离体脑组织上按照立体定位坐标采集了大量样本点每个样本点测出全基因组范围的表达丰度。于是理论上你就能做这样一件事——把MRI图像放到同一个标准空间在每个AHBA样本点上提取MRI指标再跟该点的基因表达量做统计关联找出“哪些基因的表达模式与某种影像特征的空间分布最同步”。这类分析在文献里通常叫imaging transcriptomics影像转录组学也有人叫transcriptome-neuroimaging association核心就是建立宏观影像表型与微观转录组特征之间的桥梁。这类研究要回答的典型问题包括阿尔茨海默病中萎缩最严重的脑区是否恰好富集了某种炎症相关基因的表达精神分裂症的功能连接异常是否与突触相关基因的分布有重叠这些如果只做MRI或者只做基因表达都无法回答必须把两类数据放到同一个框架里对齐。1.2 这段MATLAB代码的实际价值标题里的代码包本质上就是把这条分析管线封装成了MATLAB实现。为什么要用MATLAB而不是Python很大的原因在于影像数据的读取、配准、体素操作在MATLAB里有SPM、FSL的MATLAB接口、BrainNet Viewer等比较成熟的生态如果研究者本身就习惯SPM批处理直接用MATLAB做完整条线省去跨语言导数据的心智负担。根据我拿这类代码的惯例我会先去解压看有没有完整的数据读取脚本、坐标对齐脚本、关联计算脚本和结果可视化脚本。这种项目你很难找到一版能“一键跑通所有数据集”的代码因为它依赖AHBA的原始文件路径、MRI数据的预处理产物、甚至MATLAB版本。代码包更常见的价值是逻辑参考它告诉你每一步应该怎么组织数据、怎么处理索引、怎么避免常见的坐标错位。2. 数据准备AHBA微阵列数据到底长什么样2.1 数据集核心文件与字段AHBA的人类微阵列数据一般从艾伦脑科学研究所官网human.brain-map.org下载或者从一些重新整理过的镜像包获取。你需要重点关注的文件有四类文件/变量作用关键字段MicroarrayExpression.csv表达量矩阵行是探针列是样本probe_id, 样本表达值SampleAnnot.csv每个样本的注释信息sample_id, donor, structure, mni_x, mni_y, mni_zProbes.csv探针注释描述每个探针对应哪个基因probe_name, gene_symbol, gene_id, chromosomePACall.csv探针检出概率present callprobe_id, 每个样本的检出概率这个数据集在脑区覆盖上很细整个大脑约3700个微阵列样本点探针数在6万左右注释到约2万个基因。第一个要记住的数字是这些样本只来自6个捐赠者的大脑其中2个捐赠者只提供了左半球数据所以它的左右半球覆盖并不对称。这个点后面做统计时会非常要命很多人忽略了它直接把3700个样本当作独立观测结果自由度被严重高估——这是这个领域被审稿人攻击最多的问题之一。另一个容易忽略的是表达矩阵没有做基因名的行标签探针和基因是多对一关系。同一个基因可能对应多个探针而不同探针的灵敏度和特异性不同选取策略直接决定下游结果。所以先不要急着算相关数据侧准备工作占了整个项目的工作量至少一半。2.2 MATLAB读取和探针过滤大CSV文件在MATLAB里读取我建议用readtable而不是csvread后者对混合字段无能为力。读取前可以先确认文件分隔符AHBA标准的导出文件是逗号分隔但偶尔有带引号的字符串readtable对这种格式更稳。% 读取表达矩阵假设已经解压到本地 exprTable readtable(MicroarrayExpression.csv, PreserveVariableNames, true); sampleAnnot readtable(SampleAnnot.csv, PreserveVariableNames, true); probeInfo readtable(Probes.csv, PreserveVariableNames, true); pacTable readtable(PACall.csv, PreserveVariableNames, true);读进来之后第一步通常是过滤探针。微阵列芯片上并不是所有探针都能可靠检出目标基因尤其对于离体脑组织RNA质量、杂交效率都会影响信号。PACall文件给出每个探针在每个样本中的检出概率取值0到1。一个常见策略是保留在所有样本中平均检出概率大于某个阈值的探针比如0.5或者0.4。pacMean mean(pacTable{:, 2:end}, 2); keepProbe pacMean 0.5; exprFilt exprTable{keepProbe, 2:end}; probeFilt exprTable{keepProbe, 1};这个步骤看起来简单但阈值选择会直接影响后续基因数量。阈值取得太高很多在特定脑区才表达的基因会被误杀取得太低又会带入大量噪声。我自己的习惯是先看表达量分布用0.5作为初筛然后单独检查目标基因是否被保留。如果你研究的是一组已知的候选基因甚至可以针对它们单独放宽阈值避免因为全局过滤太狠把关键基因丢掉。2.3 MRI数据侧的预处理要求MRI数据侧要做的事情其实很明确把它配准到AHBA样本坐标所在的标准空间。AHBA样本注释里的mni_x、mni_y、mni_z用的是MNI152立体定位空间如果你的MRI数据不是这个空间关联前必须完成空间标准化。在MATLAB里用SPM12的Coregister和Normalise模块可以做这件事。如果用的是CAT12处理的结构像输出通常会直接给到MNI空间且带灰质密度图mwp1开头。这种灰质密度图很适合做全脑关联因为它在体素水平表示局部灰质比例与AHBA样本点的组织学取材具有较好的对应关系。这里有一个实操建议MRI指标尽量选在MNI空间里平滑程度适中、且具有明确生物学意义的图。比如灰质密度、皮层厚度投影到体积空间后、ALFF静息态低频振幅都可以。尽量避免选对预处理参数极其敏感的指标比如未做平滑的原始T1加权强度这种图噪声大跟基因表达作相关时会得到一堆伪显著结果。3. 核心实现样本坐标与MRI体素的精准对应3.1 坐标对齐这一步为什么容易出错我在第一次做类似项目时花了大半天排查一个诡异问题左右半球的结果完全对称地反了。后来发现是MRI图像的体素到世界坐标的变换矩阵没有正确读取导致体素索引取到的位置发生了镜像翻转。AHBA样本坐标是毫米级的MNI空间坐标MRI图像在NIfTI格式里也带有4×4的仿射变换矩阵qform/sform从体素索引到世界坐标是线性关系。MATLAB里用niftiinfo和niftiread读取NIfTI时niftiinfo返回的Transform是体素到世界坐标的变换一定要用它而不是自己手写坐标映射。坐标对齐有两个层次的需求。第一种是“样本点取体素值”直接用AHBA给出的mni_x/y/z坐标借助interp3或者spm_sample_vol提取MRI在该位置的数值。第二种是“样本点归属到脑区”通常用AAL、Desikan-Killiany或DK-ROI模板把样本点投影到最近的脑区标号再求每个脑区内样本的平均表达量。大多数文献采用第二种方式做脑区水平分析因为脑区水平可以缓解单一取样点的测量噪声也更容易跟常用影像指标对齐。3.2 从探针表达量到基因表达矩阵探针过滤之后下一步是把探针水平数据聚合到基因水平。这个操作在MATLAB里用grpstats或者accumarray都能做逻辑很简单同一个基因名下的多个探针表达量取平均或者取在样本间变异最大的那个探针。两种策略的选择其实是有讲究的。取平均在信号稳定的时候表现好取最大变异探针能突出基因的区域差异但受离群样本影响大。文献里两类做法都有但如果你要跟已发表的结果做对比尽量对齐对方采用的聚合策略。我在代码里更常用的是取平均配合对每个基因做z-score标准化这样不同基因之间的表达量量纲差异不会影响后续相关计算。% 假设exprFilt的行与probeFilt一一对应 geneList probeInfo.gene_symbol(keepProbe); % 剔除空基因名 validGene ~cellfun(isempty, geneList); exprFilt exprFilt(validGene, :); geneList geneList(validGene); % 按基因名取均值 [uniGenes, ~, geneIdx] unique(geneList); geneExpr zeros(length(uniGenes), size(exprFilt, 2)); for g 1:length(uniGenes) geneExpr(g, :) mean(exprFilt(geneIdx g, :), 1); end如果你数据量大还可以用splitapply替代循环。但基因数通常在2万这个量级矩阵是2万×3700左右循环也不算慢。需要提醒的是这个循环里的mean是沿着样本维度的如果你误写成mean(exprFilt(geneIdx g, :))在MATLAB新版里会沿着第一个非单例维度计算结果就是每个探针在全部样本上的均值而不是每个样本在多个探针上的均值一不留神就错。3.3 构建“表达-影像”数据矩阵的MATLAB实现假设你已经有了基因表达矩阵geneExpr维度是基因数×样本数同时你从SampleAnnot里整理出了对应的样本坐标列表下一步就是把MRI指标按照同样的样本顺序取出来。% nifti读取 info niftiinfo(mwp1_gm.nii); V niftiread(info); % 坐标矩阵 coords [sampleAnnot.mni_x, sampleAnnot.mni_y, sampleAnnot.mni_z]; % 取体素值注意世界坐标-体素坐标的转换 vox worldToVoxel(info, coords); % 如果R2021a之后版本可用 x round(vox(:,1)); y round(vox(:,2)); z round(vox(:,3)); n size(coords, 1); mriAtSamples zeros(n, 1); for i 1:n mriAtSamples(i) V(x(i), y(i), z(i)); end如果你的MATLAB版本没有worldToVoxel可以用info.Transform的逆矩阵手动算T info.Transform; invT inv(T.T); vox round([coords, ones(n,1)] * invT);但这里有一个非常大的坑info.Transform是体素到世界坐标的变换行的向量表示方式要搞清楚。在MATLAB里[x,y,z,1]乘以变换矩阵得到世界坐标所以反过来需要用逆变换。我见过不少人把Transform直接拿过来乘坐标结果坐标全飞了。更稳健的方式是用SPM工具。如果你已经装了SPM12可以用spm_sample_vol它能直接处理坐标和插值不需要手动做体素索引转换。% 用SPM读取图像卷 Vg spm_vol(mwp1_gm.nii); mriAtSamples spm_sample_vol(Vg, coords(:,1), coords(:,2), coords(:,3), 1);第三个输入参数1表示三线性插值。我比较推荐这种方法因为它绕开了坐标精度问题而且代码可读性好。你只需要保证coords的列顺序是x、y、zSPM内部会处理仿射变换。唯一要注意的是MNI坐标方向AHBA用的是RAS坐标SPM同样遵循这个约定因此理论上一致但如果你的MRI是从别的软件导出的要确认一下是否也是RAS否则可能出现镜像翻转。4. 关联计算与统计检验不能只算一个相关性4.1 常用关联模型从皮尔逊相关到PLS数据矩阵构建好之后核心分析就是计算基因表达与影像指标的空间关联。最简单也最常用的是逐基因的皮尔逊相关对每个基因计算它在所有样本点上的表达向量与MRI指标向量的相关系数。r corr(geneExpr, mriAtSamples); % r维度基因数×1这里corr的输入需要每一列是一个观测所以要把geneExpr转置。得到的是每个基因与MRI指标的空间相关r值。如果你想做偏相关控制掉例如全脑体积、白质分数、甚至捐赠者身份等变量可以用partialcorr。covariates [donorIdx, brainVolume, age]; % 示例 [r_partial, p_partial] partialcorr(geneExpr, mriAtSamples, covariates);偏相关能减少一些已知混杂因素的影响但不要指望它能完全解决数据内在的非独立性因为样本来自6个捐赠者本来就不是独立观测。除了相关还有一种常见做法是偏最小二乘回归PLS思路是寻找基因表达矩阵与影像指标之间协方差最大的潜变量再解释哪些基因在这个潜变量上负载高。PLS的优势是能同时处理多个影像指标比如你不仅想看灰质体积还想看皮层厚度和白质分数PLS可以构建一个基因表达与多维影像表型之间的联合模式。MATLAB里用plsregress函数就能做但解释起来比相关复杂如果不是写论文先用相关把路走通更实际。4.2 置换检验与空间自相关校正的MATLAB思路算完相关之后必然要回答统计显著性。这里的核心困境是空间数据不满足独立观测假设。相邻脑区的基因表达高度相似MRI指标也高度平滑常规的t检验或者Fisher z变换都会给出膨胀的p值。换句说全脑3700个点其实有效自由度远小于这个数量。业内比较公认的校正策略是空间置换检验其中最流行的一种是“spin test”。基本想法是保留脑区或样本点的空间结构把表达谱对应的空间标签做球面旋转破坏表达值与空间位置的对应关系然后重算相关得到零分布。在MATLAB里实现一个简化版可以用球坐标旋转的方法% 将样本坐标单位化到球面 [Xs, Ys, Zs] sphere_coords; % 假设是每个样本点的球面单位向量 % 随机旋转三个欧拉角 phi rand*2*pi; theta rand*pi; psi rand*2*pi; Rx [1 0 0; 0 cos(phi) -sin(phi); 0 sin(phi) cos(phi)]; Ry [cos(theta) 0 sin(theta); 0 1 0; -sin(theta) 0 cos(theta)]; Rz [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1]; R Rz * Ry * Rx; rotated_coords [Xs, Ys, Zs] * R; % 用旋转后的坐标重新建立与表达谱的对应再计算相关但这里要注意spin test通常是在脑区层面做用于皮层表面坐标比较合理如果你用的是体积MNI坐标而不是球面坐标直接旋转会出问题。更保险的做法是保留样本坐标随机打乱样本与MRI值的对应关系做普通的置换检验。虽然这种置换没有显式建模空间自相关但它通过打乱空间位置关系能在一定程度上反映“如果基因表达模式在空间中随机重排还会不会得到这么强的相关量级”的问题。这种简单置换得到的p值通常比参数检验保守一些也更受审稿人认可。4.3 多重比较校正与结果可视化全基因组做关联基因数接近2万就算用置换检验也不能每个基因独立看p值。常用的做法是FDR控制MATLAB里可以用mafdr函数如果你有统计工具箱的话。p_perm zeros(length(r), 1); % ... 置换循环生成零分布 ... fdr_q mafdr(p_perm, BHFDR, true);置换次数一般至少1000次更稳是5000或10000次。你可以用parfor并行因为每个置换之间相互独立这一步能大幅缩短时间。结果的可视化方面MATLAB基本绘图组件够用但要画到脑表面上通常推荐把显著基因的关联结果投影到皮层表面或者体积脑模板上。如果你只是展示相关模式的总体形态可以用scatter3按样本坐标画点颜色映射r值比用切片图更直观。scatter3(coords(:,1), coords(:,2), coords(:,3), 20, r_selected, filled); colormap(jet); colorbar;如果想更专业一点可以导出到BrainNet Viewer或者用FSL的atlasquery做区域富集分析。不过那属于扩展功能了基础版代码到这个程度已经能回答“哪些基因与这个MRI指标显著相关”这个核心问题。5. 我踩过的坑和排查经验5.1 常见问题速查表现象可能原因解决办法左右半球结果完全镜像坐标方向约定不一致检查MRI数据是RAS还是LPS必要时翻转x轴大量NaN表达值未做探针过滤或基因匹配错误检查PACall剔除低检出探针相关r值普遍过高样本非独立、存在空间自相关用置换检验而不是直接看原始p值基因表达矩阵聚合后基因数减少过多探针过滤阈值太严单独检查目标基因适当放宽阈值读取CSV耗时极长文件太大几百MB用datastore或者先转成MAT文件再分析MRI体素值大量为0坐标落在脑外或灰质概率为0用interp3/spm_sample_vol的零填充处理注意脑外点排除第一个问题是最伤时间的。如果你发现左右半球关联模式高度对称但方向相反第一时间去查MRI世界坐标系的轴向AHBA用RAS坐标部分第三方软件输出的NIfTI可能是LPS需要把x取反。5.2 几点实操心得这个项目跑了几个数据集之后我有两个很深的体会。第一个是除非你明确要做体素水平的精细分析否则尽量先在脑区水平上做。把3700个样本点归并到AAL或Desikan脑区对每个脑区求平均表达量和平均MRI值然后以脑区为样本做关联。这样虽然样本数骤降但噪声也被压低了结果的可解释性反而更强而且spin test做起来也更顺滑。第二个是不要迷信全局最优的探针过滤策略。基因表达数据的预处理方法选择非常多不同方法算出来的显著基因列表可能只有一半重叠。唯一的建议是代码里要把预处理参数全部保留下来最好能在输出结果里带上基因版本的注释信息这样后来人包括你自己还能追溯。另外我强烈建议在代码里加入中间结果的保存。比如把过滤后的表达矩阵、样本坐标、MRI取样值都分别存成MAT文件这样你不需要每次重启分析都重新加载几百MB的原始CSV。MATLAB在大IO上是弱项一次性把数据整理成分析格式往往能省一半以上的时间。还有一个细节如果代码里用到了特定版本的MATLAB函数比如worldToVoxel是R2021a引入的spm_sample_vol则需要安装SPM12运行前最好在代码开头做一个环境检查try niftiinfo(example.nii); catch error(需要Image Processing Toolbox或SPM支持); end这些小检查看起来不起眼但在你换电脑、换实验室、隔半年再跑这份代码的时候能帮你快速定位环境问题而不是对着报错信息干瞪眼。6. 这个代码包还能往哪些方向扩展基础版本的MRI-基因表达关联算完之后后续还有几个非常值得做的扩展。第一个是基因集富集分析如果显著基因列表里富集了某个通路比如突触传递、免疫应答、线粒体代谢那你就不只是报一堆基因名而是能讲一个生物学故事。MATLAB里做富集分析不太方便通常是导出基因列表后用外部工具或者R包做但这属于标准的后续步骤。第二个扩展是反过来建立预测模型用基因表达模式去预测MRI指标的空间分布或者用MRI指标去反推基因表达特征。这类模型在临床上可能用于识别那些与疾病相关脑区变化最一致的分子标记物。但注意这种预测依然不能等同于因果关系毕竟宏观影像和基因表达只是相关关系。第三个是纳入更多模态的AHBA数据。AHBA除了微阵列数据还有RNA测序数据和人脑发育转录组数据。如果研究问题聚焦在发育阶段变化可以换用发育转录组图谱如果聚焦在神经精神疾病的精细分子分型RNA-seq的敏感度和动态范围可能更好。代码主体流程差不多只是数据解析格式不同。从我个人的使用体验讲这类代码包最大的价值不是算法多么高深而是把数据对齐这件枯燥容易出错的事情整理得清晰明了。只要坐标对齐、探针聚合、统计检验这三步做扎实后续任何高级分析都有稳固的地基。如果你准备在自己的数据上跑这套流程我建议先从单个候选基因入手把整条管线走通再扩展到全基因组分析否则中间一旦出问题排查的复杂度会乘十倍。本文还有配套的精品资源点击获取