资讯详情

abagen 实战指南:从 AHBA 微阵列数据到脑区基因表达矩阵

📅 2026/10/16 20:37:24 | 华诺云谱 👁 阅读
abagen 实战指南:从 AHBA 微阵列数据到脑区基因表达矩阵
简介abagen 是一个面向神经影像与计算神经科学领域的 Python 工具箱用于获取、处理并准备艾伦人脑图谱AHBA微阵列表达数据。它解决的核心问题是原始 AHBA 数据在折叠到感兴趣脑区、跨供体组合等环节存在大量分析选择差异导致结果难以复现。该包提供可重现的工作流适合具备一定 Python 基础、需要开展人脑基因表达与脑区关联分析的研究者。资源包共 131 个文件约 3.85MB以 52 个 py 源码文件为主体辅以 27 个 gz 压缩数据、19 个 rst 文档、11 个 png 示意图及 yml、csv、json 等配置与数据文件覆盖源码、文档、示例数据与构建脚本。目前已有 1798 人学习下载。借助该工具箱读者可获得从原始 AHBA 数据到区域化、跨供体整合表达矩阵的完整处理链路理解不同分析选择对下游结果的影响并直接复用其模块化代码与示例数据提升人脑转录组研究的可复现性与效率。1. abagen 到底解决什么问题从“基因表达 × 脑区”说起做脑影像遗传学或者跨尺度建模的人迟早会撞上一个需求手里有一堆脑区比如 HCP 的 360 个皮层分区、Schaefer 的 200/400 分区想给每个脑区配一个“基因表达指纹”然后拿去做关联分析、做机器学习特征、做受体分布约束。问题在于人脑转录组数据不是随便就能拿到的——公开可用的主要来源是艾伦人脑图谱Allen Human Brain Atlas, AHBA的微阵列表达数据而它原始形态是 6 个捐献者、几千个采样点、几万条探针坐标、注释、归一化各成一摊。直接上手处理光是“把采样点映射到脑区”这一步就能耗掉一周。abagen 就是把这个流程工具化的一个 Python 工具箱。它做的事情可以一句话概括把 AHBA 的微阵列表达数据按你指定的脑图谱分区聚合成“每个脑区一个表达向量”的矩阵。中间它替你处理了探针到基因的映射、样本到脑区的空间分配、跨捐献者的归一化、缺失基因的插补。对做脑区基因表达关联的从业者来说这相当于把一条容易翻车的流水线封装成了几个函数调用。它适合谁如果你在做脑网络与基因表达的耦合分析、在构建脑区的转录组特征、在复现别人论文里的“基因表达-脑区属性”关联abagen 基本是绕不开的起点。新手可以跟着默认参数跑通最小流程熟手则需要理解它每一步的取舍因为默认值不一定适合你的图谱和样本量。下面按“先立住概念、再动手复现、最后讲坑”的顺序拆开讲。2. 微阵列数据到脑区矩阵abagen 的四个核心步骤2.1 为什么不能直接对原始探针做平均AHBA 微阵列数据的原始结构是每个捐献者一份表达矩阵行是探针probe列是采样组织块sample值是表达强度。一个基因可能对应多个探针不同探针测的是同一基因的不同区域表达值可能差出好几倍。如果你直接把所有探针按脑区平均等于把噪声和真实信号混在一起后续关联分析基本不可信。abagen 的处理逻辑是先把探针映射到基因对同一基因的多个探针做选择或聚合再进入空间映射。这个顺序很关键——先基因级聚合再脑区级聚合而不是反过来。常见做法是取每个基因表达值最高的探针max probe也有用中位数或平均的。abagen 默认用的是“差异稳定性”策略对每个基因选在不同捐献者之间表达模式最一致的探针。这个选择直接影响最终矩阵的可靠性后面避坑章节会展开。2.2 采样点怎么落到你的脑图谱分区里AHBA 的采样点是立体定位坐标MNI 空间而你的脑图谱是一组分区标签。abagen 要做的就是把每个采样点的 MNI 坐标分配到对应的分区标签上。这一步的难点在于采样点不一定落在灰质内也不一定落在你图谱覆盖的范围内边界附近的点归属还可能模棱两可。abagen 提供了几种分配策略核心参数是atlas_info和tolerance。tolerance控制采样点离分区边界的容忍距离单位毫米默认是 2mm。意思是如果一个采样点离某个分区边界在 2mm 以内它仍可能被分配给该分区。这个值调大纳入的采样点更多但归属更模糊调小归属更严格但可能丢掉大量采样点。实际用的时候我一般会先跑默认值看每个脑区最终有多少采样点支撑如果某些脑区采样点数为零或个位数就要考虑放宽 tolerance 或换图谱。2.3 跨捐献者归一化为什么必须做AHBA 有 6 个捐献者每个人的表达值量纲和分布都不一样。如果直接把 6 个人的数据拼在一起做脑区平均相当于假设他们的表达水平可以直接比较这显然不成立。abagen 默认对每个捐献者单独做归一化用的是样本间的秩变换rank-based或 z-score把每个人的表达分布拉到可比的尺度上。这里有个容易忽略的点归一化是在“样本”层面做的不是“脑区”层面。也就是说先对每个捐献者的所有采样点做归一化再按脑区聚合。如果你反过来先按脑区平均再归一化跨捐献者的可比性会打折扣。abagen 的normalize参数控制这一步默认是True用的方法是zscore。如果你的数据本身已经做过标准化或者你想保留原始量纲做特定分析可以关掉但大多数关联分析场景下建议保持开启。2.4 缺失基因和缺失脑区怎么补即使做完上面三步你拿到的矩阵大概率还是有缺失值某些基因在某些脑区没有采样点覆盖或者某些脑区的采样点太少导致表达值不可靠。abagen 提供了插补选项核心参数是missing。默认是centroids意思是对于缺失的脑区-基因对用该基因在所有脑区的均值来填充。还有interpolate选项用空间上邻近脑区的表达值做插值。选哪个取决于你的分析目标。如果缺失比例很低比如低于 5%用centroids简单填充影响不大。如果缺失比例高或者你关心空间连续性interpolate更合理但它假设表达值在空间上是平滑的这个假设不一定对所有基因成立。我的习惯是先跑一遍看缺失比例超过 10% 就回头检查图谱和 tolerance 设置而不是急着插补。3. 用 abagen 跑通最小流程从安装到拿到表达矩阵3.1 环境准备与数据获取abagen 是纯 Python 包依赖 numpy、pandas、nibabel、scipy 这些常规科学计算库。安装本身不复杂但数据获取是第一个门槛。AHBA 的微阵列数据需要从公开数据源下载abagen 提供了fetch_microarray函数来拉取。注意这个函数默认会把数据缓存到本地目录第一次运行会下载几百 MB 的文件网络不稳的话容易中断。# 安装 abagen建议在虚拟环境里做 # pip install abagen import abagen # 拉取 AHBA 微阵列数据指定缓存目录 # data_dir 建议设在一个空间充足的路径下 microarray abagen.fetch_microarray( data_dir./ahba_data, # 缓存目录首次下载后复用 donorsall, # 使用全部 6 个捐献者 verbose1 # 打印下载进度 )这段代码的逻辑是fetch_microarray会检查data_dir下是否已有数据没有就去下载。donorsall表示用全部捐献者你也可以指定单个捐献者做敏感性分析。verbose1会输出下载和解析的进度第一次跑建议开着方便判断是否卡住。下载完成后microarray是一个字典键是捐献者 ID值是该捐献者的表达数据和样本信息。3.2 指定脑图谱并生成表达矩阵拿到数据后下一步是告诉 abagen 你要用哪个脑图谱。abagen 内置了一些常用图谱的获取接口也支持你传入自己的分区文件。下面以常用的皮层分区为例走一遍完整流程。import abagen # 获取一个内置的脑图谱这里以某常用分区方案为例 # 实际使用时替换成你手头的图谱名称或本地文件路径 atlas abagen.fetch_atlas( schaefer_2018, # 图谱名称 n_rois200, # 分区数量 data_dir./ahba_data ) # 生成脑区 × 基因的表达矩阵 expression abagen.get_expression_data( atlasatlas[image], # 图谱的 NIfTI 文件路径 atlas_infoatlas[info], # 图谱的分区标签信息 data_dir./ahba_data, tolerance2, # 采样点归属的边界容忍距离mm normalizeTrue, # 跨捐献者归一化 missingcentroids, # 缺失值用基因均值填充 verbose1 ) # expression 是一个 DataFrame # 行是脑区列是基因值是表达水平 print(expression.shape)这段代码的关键参数需要逐个说清楚。atlas传的是图谱图像路径atlas_info是分区标签的元信息哪个标签对应哪个脑区名称。tolerance2是默认值前面讲过它的作用。normalizeTrue开启跨捐献者归一化。missingcentroids是缺失填充策略。verbose1会打印每个步骤的进展包括有多少采样点被分配到每个脑区这个信息在排查问题时很有用。跑完之后expression的行数应该等于你的分区数比如 200列数是基因数大约 1 万多到 2 万取决于探针映射结果。如果行数不对说明图谱标签和图像不匹配如果列数远少于预期说明探针映射或基因过滤出了问题。3.3 检查输出质量三个必看的指标拿到矩阵不等于能用。我一般会先看三个东西每个脑区的采样点数、缺失值比例、以及表达值的分布范围。import numpy as np # 检查每个脑区的采样点覆盖情况 # abagen 在 verbose 输出里会打印也可以从返回的中间结果拿 # 这里假设你已经有了 expression 矩阵 # 缺失值比例 missing_ratio expression.isna().mean().mean() print(f整体缺失比例: {missing_ratio:.4f}) # 每个脑区的有效基因数 valid_per_region expression.notna().sum(axis1) print(f有效基因数最少的脑区: {valid_per_region.min()}) print(f有效基因数最多的脑区: {valid_per_region.max()}) # 表达值的整体分布 print(f表达值范围: {np.nanmin(expression.values):.3f} 到 {np.nanmax(expression.values):.3f})缺失比例低于 5% 通常可以接受高于 10% 就要回头查。有效基因数最少的脑区如果只有几百说明该脑区采样点太少后续分析里这个脑区的表达特征不可靠。表达值范围如果出现极端值比如超过 10 个标准差可能是归一化没做好或者有异常采样点混入。4. 参数怎么调tolerance、normalize、missing 的取舍4.1 tolerance 调大还是调小先看采样点覆盖tolerance是 abagen 里最需要根据数据实际情况调整的参数。它的单位是毫米控制采样点离分区边界的容忍距离。默认 2mm 是一个折中值但不是万能值。如果你的图谱分区比较细比如 400 个分区分区边界密集2mm 的容忍距离可能导致大量采样点被分配到错误的分区或者一个采样点同时落在多个分区的容忍范围内。这时候应该把 tolerance 调小比如 1mm 甚至 0.5mm让归属更严格。代价是采样点利用率下降某些小分区可能没有采样点。反过来如果你的图谱分区比较粗比如 100 个分区以内分区面积大2mm 可能过于严格导致边界附近的采样点被丢弃。这时候可以调到 3mm 或 4mm提高采样点利用率。但要注意调得太大采样点的空间特异性就下降了相当于用更模糊的空间信息换更多的样本量。我的做法是先用默认值跑一遍看 verbose 输出里每个分区的采样点数。如果超过 20% 的分区采样点数少于 3 个就逐步调大 tolerance每次加 1mm直到采样点覆盖改善但缺失比例不显著上升。如果采样点覆盖很好但缺失比例很高反而要检查是不是 tolerance 太大导致归属混乱。4.2 normalize 关掉的场景normalizeTrue是默认值适用于大多数跨捐献者分析。但有两种情况我会考虑关掉一是我的分析只针对单个捐献者不需要跨人可比二是我后续要用自己的归一化流程不想让 abagen 先做一遍。关掉之后表达值保留原始量纲不同捐献者的数据直接拼接。这时候你必须自己处理跨捐献者的尺度差异否则脑区平均会被某个捐献者的量纲主导。一个常见的补救做法是在 abagen 输出之后对每个捐献者的数据单独做 z-score再合并。但这相当于把 abagen 内部做的事搬到外面做容易出错除非你有明确理由否则不建议关。4.3 missing 策略对下游分析的影响missingcentroids和missinginterpolate的区别本质上是“用全局均值填充”还是“用空间邻域填充”。前者简单后者假设空间平滑。如果你的下游分析是脑区之间的关联比如基因表达相似性和功能连接相似性的关系用centroids填充会引入一个常数偏移可能人为拉高所有脑区之间的相似性。这时候interpolate更合理因为它保留了空间结构。但如果缺失比例很低两者的差异可以忽略。还有一个选项是missingNone即不填充保留 NaN。这适合你后续要用自己的插补方法或者你的分析框架能处理缺失值。但要注意很多机器学习模型不接受 NaN你得在进入模型前处理好。5. 避坑指南abagen 使用中的五个血泪教训5.1 图谱标签和图像不匹配导致脑区数对不上现象跑完get_expression_data输出的行数不是你的分区数或者某些脑区全是 NaN。原因atlas传的图像和atlas_info传的标签信息不是同一套。比如图像是 200 分区标签信息却是 400 分区的或者标签的编号方式和图像的强度值不对应。解决先单独加载图谱图像和标签信息检查图像的唯一强度值是否和标签信息里的分区 ID 一一对应。可以用 nibabel 读图像用 numpy 看唯一值再和标签表比对。确认一致后再传入 abagen。5.2 采样点归属为零某些脑区完全没有数据现象verbose 输出里某些脑区的采样点数为 0最终矩阵里这些脑区全是 NaN。原因这些脑区在 MNI 空间里的位置可能超出了 AHBA 采样点的覆盖范围或者 tolerance 太小导致边界附近的采样点没被纳入。解决先确认这些脑区是否在 AHBA 的覆盖范围内AHBA 主要覆盖皮层和部分皮层下结构不是全脑。如果在覆盖范围内但采样点为 0逐步调大 tolerance。如果调大后仍然为 0考虑换一个分区方案或者接受这些脑区没有表达数据的事实在下游分析里排除它们。5.3 探针映射后基因数远少于预期现象最终矩阵的列数只有几千而 AHBA 原始数据有 2 万多个基因。原因探针映射过程中大量探针因为质量过滤被丢弃或者多个探针映射到同一基因后只保留了一个导致基因数减少。这是正常的但如果减少得太厉害可能是过滤阈值太严。解决检查 abagen 的探针过滤参数。默认会过滤掉表达值过低或变异过小的探针。如果你的数据质量本身不高可以适当放宽过滤阈值。但要注意放宽过滤会引入更多噪声需要在基因数和数据质量之间权衡。5.4 归一化后表达值出现极端值现象归一化后的表达值范围异常大或者某些脑区的表达值明显偏离其他脑区。原因可能是某个捐献者的数据有异常采样点比如组织质量差、表达值整体偏高或偏低归一化没有完全消除这种偏差。也可能是 tolerance 设置不当导致某个采样点被错误地分配到多个脑区。解决先检查每个捐献者的表达值分布看是否有异常。如果有考虑排除该捐献者或对该捐献者做额外的稳健归一化。同时检查 tolerance 设置确保采样点归属合理。极端值如果只出现在少数脑区可以在下游分析里做 winsorize 处理。5.5 内存不足导致处理中断现象跑get_expression_data时程序崩溃报内存错误。原因AHBA 原始数据加上中间计算过程内存占用可能达到几个 GB。如果你的机器内存不足或者同时跑了其他任务容易崩。解决减少同时使用的捐献者数量donors参数或者分批次处理。也可以先把数据缓存到本地避免重复下载和解析。如果内存实在紧张考虑用missingNone减少插补计算量或者换一台内存更大的机器。6. 进阶技巧把 abagen 输出接入你的分析流水线6.1 用自定义图谱替换内置图谱abagen 内置的图谱有限实际研究里你很可能有自己的分区方案。接入自定义图谱的关键是准备好两个东西图谱的 NIfTI 文件以及一个包含分区 ID 和分区名称的 DataFrame。分区 ID 必须和图像里的强度值对应分区名称可以自定义。import pandas as pd import abagen # 自定义图谱信息 # atlas_info 必须包含 id 和 name 两列 # id 要和 NIfTI 图像里的强度值一致 custom_info pd.DataFrame({ id: [1, 2, 3, 4], # 分区 ID name: [region_A, region_B, region_C, region_D], hemisphere: [L, L, R, R] }) # 传入自定义图谱 expression_custom abagen.get_expression_data( atlas./my_atlas.nii.gz, # 你的图谱文件 atlas_infocustom_info, # 自定义标签信息 data_dir./ahba_data, tolerance2, normalizeTrue, missingcentroids )这里的关键是atlas_info的列名必须匹配 abagen 的预期。id列对应图像强度值name列是分区名称。如果你的图谱有左右半球区分可以加hemisphere列abagen 会在输出里保留这个信息。跑之前建议先用 nibabel 确认图像的强度值和id列完全一致否则会出现分区错位。6.2 把表达矩阵转成脑区相似性矩阵拿到脑区 × 基因的表达矩阵后常见的下游分析是计算脑区之间的表达相似性然后和功能连接、结构连接做关联。这一步可以用 pandas 和 scipy 快速完成。import pandas as pd import numpy as np from scipy.spatial.distance import pdist, squareform # 假设 expression 是脑区 × 基因的 DataFrame # 先处理缺失值如果还有的话 expr_filled expression.fillna(expression.mean()) # 计算脑区之间的相关性表达相似性 # 用皮尔逊相关也可以换成斯皮尔曼 corr_matrix np.corrcoef(expr_filled.values) # 如果要做距离矩阵用 1 - 相关 dist_matrix 1 - corr_matrix # 转成 DataFrame 方便后续使用 corr_df pd.DataFrame( corr_matrix, indexexpression.index, columnsexpression.index ) print(corr_df.shape)这段代码的逻辑是先确保没有 NaN然后对脑区 × 基因矩阵按行计算相关系数。np.corrcoef默认按行计算所以每一行是一个脑区结果矩阵的 (i, j) 元素是脑区 i 和脑区 j 的表达相似性。如果你要做的是脑区聚类或者网络分析这个相似性矩阵就是输入。注意如果基因数远大于脑区数相关矩阵可能不稳定可以考虑先做降维比如 PCA再算相似性。6.3 验证表达矩阵可靠性的一个实用方法怎么判断你拿到的表达矩阵是否可靠一个实用的方法是做“留一捐献者”验证每次排除一个捐献者用剩下的捐献者生成表达矩阵然后看不同版本之间的相关性。如果相关性很高比如 0.9说明结果对单个捐献者不敏感可靠性较好。如果相关性低说明某个捐献者对结果影响过大需要检查该捐献者的数据质量。import abagen import numpy as np donors [donor_1, donor_2, donor_3, donor_4, donor_5, donor_6] matrices [] for holdout in donors: # 用除 holdout 之外的捐献者生成矩阵 remaining [d for d in donors if d ! holdout] expr abagen.get_expression_data( atlasatlas[image], atlas_infoatlas[info], data_dir./ahba_data, donorsremaining, tolerance2, normalizeTrue, missingcentroids, verbose0 ) matrices.append(expr.values) # 计算不同版本之间的平均相关性 correlations [] for i in range(len(matrices)): for j in range(i 1, len(matrices)): # 展平后计算相关 r np.corrcoef(matrices[i].flatten(), matrices[j].flatten())[0, 1] correlations.append(r) print(f留一验证平均相关: {np.mean(correlations):.4f}) print(f最低相关: {np.min(correlations):.4f})这个验证的代价是计算量翻倍每个捐献者跑一次但能帮你判断结果是否稳健。如果最低相关低于 0.8说明某个捐献者的数据可能有问题值得单独检查。我一般会在正式分析前跑一次这个验证确认矩阵可靠后再往下做。6.4 一个容易忽略的细节基因过滤的阈值abagen 在探针映射阶段会做基因过滤默认会去掉在一些脑区表达值恒定的基因。这个过滤的阈值会影响最终基因数。如果你的分析对基因数敏感比如要做基因集富集分析建议显式检查过滤后的基因列表确认没有丢掉你关心的基因。可以在get_expression_data之后用expression.columns查看保留的基因和你预期的基因列表比对。如果发现关键基因被过滤掉了回头调整探针过滤参数或者手动把该基因加回来。说到底abagen 是一个把复杂流程标准化的工具但标准化不等于万能。它的默认参数是为“通用场景”设计的你的数据、你的图谱、你的分析目标都可能需要微调。我自己的习惯是每次用 abagen 之前先花十分钟确认图谱和标签匹配、采样点覆盖合理、缺失比例可接受再往下跑。这三步做完后面翻车的概率会低很多。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑