3、空间转录组数据格式介绍(H5、mtx、TIFF)
做 Visium 分析,你首先得搞明白数据长什么样。说白了,空间转录组的数据不是单一文件,而是一套「组合拳」——你拿到手的往往是个文件夹,里面混着图像、表达矩阵和元数据。我最早接触时也被绕晕过,后来摸清了三种核心格式:H5、mtx 和 TIFF。嗯,今天我就把它们的门道给你捋清楚。
3.1 H5(HDF5)— 大而全的容器
H5 是 HDF5 的简写,一种层级化的二进制文件格式。Space Ranger 输出的 filtered_feature_bc_matrix.h5 就是典型代表。我个人习惯把它看作「数据衣柜」——里面用 group 和 dataset 把基因表达、barcode、特征信息分门别类挂好。
之前有个项目,同事拿到 H5 后直接硬着头皮用 pandas 读,结果内存爆了。其实根本不需要,H5 支持随机读取,你完全可以选择只加载某个 barcode 集合的数据。我常用的命令是:
h5ls filtered_feature_bc_matrix.h5
# 输出示例:
# /matrix Group
# /matrix/features Group
# /matrix/barcodes Dataset {5000}
# /matrix/data Dataset {1200000}
# /matrix/indices Dataset {1200000}
# /matrix/indptr Dataset {5001}
# /matrix/shape Dataset {2}
你会发现表达矩阵按压缩稀疏列(CSC)格式存储——data 存非零值,indices 存行号,indptr 存列偏移。我建议你直接用 scanpy.read_10x_h5() 或 Seurat::Read10X_h5() 解析,比自己造轮子靠谱。
h5ls -r 列出完整路径,再按需读取。
3.2 mtx(Matrix Market)— 轻量级稀疏格式
mtx 是 Matrix Market 格式的文本文件,专门存稀疏矩阵。Visium 的原始数据包里,matrix.mtx 常和 barcodes.tsv、features.tsv(或 genes.tsv)三件套放在 filtered_feature_bc_matrix/ 目录下。
它的结构极其简单:前三行是注释,第四行开始每行三个值——row col value。我曾经遇到过团队把 mtx 用 Excel 打开,结果超长行被截断,最后基因表达全乱了。千万别踩这个坑,mtx 不是给人眼看的,老老实实让程序读。
你看,一个典型的 mtx 长这样:
%%MatrixMarket matrix coordinate integer general
%metadata_json: {"software_version": "2.0.0", "format_version": 2}
1200000 5000 31000
1 1 5
1 2 0
1 3 12
2 1 3
3 5 7
第三行 1200000 5000 31000 表示总非零元素 120 万、5000 个 barcode、31000 个基因。嗯,注意行列索引是 1-based(从 1 开始),不像 Python 的 0-based。我刚开始用 scipy.io.mmread() 时没注意这细节,一度以为数据被篡改了。
3.3 TIFF — 组织图像的原生载体
TIFF(Tagged Image File Format)在 Visium 里承载的是 H&E 染色后的组织切片扫描图。别小看它,它不仅是“图片”,还内嵌了空间坐标、焦距、缩放层级等元数据。Space Ranger 依赖 TIFF 中的 Spot 位置信息才能把基因表达映射到物理坐标上。
我记得有一次,交付方给的是 JPEG 压过的图,结果组织边界模糊,下游聚类直接把背景和实际组织混在一起。后来强制要求对方提供未压缩的 TIFF(≥ 300 DPI),问题才解决。
TIFF 文件的典型入口文件是 tissue_hires_image.png(低分辨率预览)和 tissue_lowres_image.png,但真正的原始文件是 *.tif。用 Python 读取时,libvips 比 OpenCV 快一个数量级:
import tifffile
img = tifffile.imread('sample.tif')
print(img.shape) # (高度, 宽度, 通道数)
# 通常输出 (20000, 20000, 3) 或更大
Image.open() 打开巨型 TIFF(超过 1GB),它会直接解压到内存,导致 OOM。优先用 tifffile 或 pyvips 做流式读取。
3.4 格式对比一览
| 维度 | H5 | mtx | TIFF |
|---|---|---|---|
| 数据类型 | 基因表达(含barcode、特征) | 基因表达(仅矩阵) | 组织图像 |
| 存储方式 | 二进制,层级结构 | 文本,稀疏坐标 | 二进制,标签/压缩 |
| 大小 | 中等(压缩率好) | 小(仅非零值) | 极大(通常数GB) |
| 随机读取 | 支持(按group) | 不支持(全文加载) | 支持(按tile) |
| 典型工具 | h5py, scanpy | scipy.io, Seurat | tifffile, libvips |
| 我踩过的坑 | 忘记Sparse格式 | Excel截断 | JPEG压缩丢细节 |
3.5 三种格式如何协同工作?
搞清楚各自的定位后,你就能看懂 Visium 分析的上下游了。下面这张图是我自己画的,帮你把数据流转关系可视化:
你看,H5 和 mtx 都包含基因表达信息,但 H5 更“完整”(含 barcode 和特征名),mtx 更“纯粹”(仅矩阵坐标)。TIFF 则提供位置信息。我们做容器化部署时,通常会把 H5 作为统一输入,因为 scanpy 和 Seurat 都原生支持,减少格式转换的麻烦。
h5py、tifffile、scipy 这三个库,能覆盖 95% 的 Visium 数据读取场景。另外,一定不要把 TIFF 文件塞进数据库——放到对象存储里,通过挂载卷传递,否则容器镜像会胖到不可理喻。