空间转录组数据获取与预处理:常见平台、数据格式、质量控制
空间转录组这两年有多火,不用我多说。但很多人拿到数据就急着跑模型,结果发现结果一团糟。原因在哪?数据预处理没做好。说白了,空间转录组的数据比单细胞数据多了一个空间坐标维度,质量控制也要跟着变。今天我就把数据获取、格式转换和质控这一套流程帮你理清楚。
一、常见平台:你选哪个?
市面上主流的空间转录组平台大概有五六种。每个平台的数据结构、分辨率、通量都不一样。我个人经验是:选平台之前先想清楚你要回答什么生物学问题。
| 平台 | 分辨率 | 通量 | RNA捕获方式 | 特点 |
|---|---|---|---|---|
| 10x Visium | ~55 μm 点 | 中等(~5000 点/切片) | poly-A 捕获 | 最成熟,分析生态好 |
| Slide-seq V2 | ~10 μm 珠子 | 高(~100k 珠子) | 随机引物 | 分辨率高,但文库复杂 |
| MERFISH | 亚细胞级 | 中等(~10000 基因) | 原位杂交 + 成像 | 单分子分辨率,需定制探针 |
| STARmap | 亚细胞级 | 低(~1000 基因) | 原位测序 | 无需解离,适合神经科学 |
| Seq-scope | ~1 μm 点 | 极低 | 随机引物 | 超高点阵,适合精细结构 |
威宁:其实选平台还要看你的预算和样本类型。比如组织切片质量不好,MERFISH的背景荧光会比较刺眼,我踩过这个坑。
二、数据格式:别被后缀名吓住
拿到数据的第一步,先搞清楚文件从哪来、后缀名啥意思。10x Visium 输出的一组文件最常见:filtered_feature_bc_matrix.h5、spatial/tissue_hires_image.png、spatial/tissue_positions_list.csv。这里有个小陷阱:h5版本和mtx版本在内存使用上有区别,我建议你直接用h5,省空间。
核心数据文件类型
- h5 (HDF5):存储表达矩阵+特征+条形码,单文件方便
- mtx (Market Matrix):三个文件 (matrix.mtx, barcodes.tsv, features.tsv) 古老但兼容
- CSV/TSV:文本格式,可读但体积大
- JSON/GeoJSON:空间坐标和元数据,Slide-seq常用
- TIFF/OME-TIFF:组织染色图或荧光图像
我曾经遇到一个团队,给了我一堆CSV文件每个超过2GB,光读取就崩了。后来发现他们用了一个非标准封装。建议你先用h5ls查看h5结构,确认key名。
下面是一个简单的读取示例,我一般用scanpy来加载Visium数据:
import scanpy as sc
adata = sc.read_visium(
path="path_to_data_directory",
count_file="filtered_feature_bc_matrix.h5",
load_images=True
)
print(adata)
# AnnData object with n_obs × n_vars = 4433 × 34553
# obs: 'in_tissue', 'array_row', 'array_col'
# var: 'gene_ids', 'feature_types', 'genome'
# obsm: 'spatial'
对于Slide-seq的数据,我习惯先用pip install slidseq(注意不是官方包,是社区工具),然后读取重格式。嗯,这里需要留个心眼:每个平台的坐标系统不一样,Visium是array_row/array_col + 像素坐标,Slide-seq是beads_coords,混着用会搞混空间关系。
三、质量控制:别让垃圾数据毁掉模型
空间转录组的QC和单细胞有相似之处,但多了空间层面的检查。我个人习惯把质控分成三个步骤:分子水平、点/珠子水平、空间一致性。千万别漏掉空间一致性检查,很多异常点虽然分子数正常,但空间分布明显与组织边界不齐。
3.1 常用指标
| 指标 | 含义 | 筛选范围 |
|---|---|---|
| n_genes_by_counts | 每个点检测到的基因数 | 通常 >200, <5000 |
| total_counts | 每个点的UMI总数 | 通常 >1000, <= 数据95%分位 |
| pct_counts_mt | 线粒体基因占比 | 一般 <20% |
| doublet_score | 双胞可能性(非必需) | 依赖方法,scrublet可做 |
| spot_density | 相邻点表达相关性 | 低密度点需排除 |
3.2 实战:10x Visium 过滤流程
我通常这样操作:
import scanpy as sc
import matplotlib.pyplot as plt
# 1. 计算QC指标
sc.pp.calculate_qc_metrics(adata, expr_type='counts',
qc_vars=['mt'],
percent_top=None,
log1p=False)
# 2. 定义过滤
adata.obs['mt_frac'] = adata.obs['pct_counts_mt']
adata = adata[adata.obs['mt_frac'] < 20, :]
adata = adata[adata.obs['n_genes_by_counts'] > 200, :]
adata = adata[adata.obs['total_counts'] > 1000, :]
# 3. 空间一致性检查:计算局部莫兰指数
import squidpy as sq
sq.gr.spatial_autocorr(adata,
genes=['Hpca', 'Tbr1'],
n_perms=100)
# 低显著性区域(p值>0.05)可能有问题
遇到低表达区域,不要急着删,先看看组织染色图。我有一次发现某个区域基因数很低,但所有点都在同一血管周围,最后确认是血管周围存在大量RNA降解。这时候应该保留但不能参与后续建模。
3.3 平台特有的“雷区”
- Visium:注意
in_tissue列,只有标签为1的点是有效组织区域。 - Slide-seq:空珠子容易误判为有信号,建议用总UMI阈值 + 背景模型剔除。
- MERFISH:背景荧光导致假阳编码,需要用spot quality筛选。
- STARmap:成像漂移导致坐标偏移,必须做配准。
四、知识体系总览:一张图看懂
下面这张流程图总结了从数据获取到预处理、质控的完整链路。我工作时都会贴在墙上当备忘录。
这张图里我把质量控制拆成三个互相独立但需要交叉验证的步骤。分子QC关注点的测序深度、线粒体占比;空间QC看点的空间邻居关系;一致性QC则跨模态对比组织轮廓。我的经验是:永远先跑一次全流程,再根据第一次的QC统计量调整阈值,至少迭代两轮。
五、常见坑及避坑指南
- 坑一:直接过滤低基因数点——组织边缘点基因数低但包含重要边界信息。
避坑:结合HE染色图像做视觉验证。 - 坑二:忽略批次效应——同一个实验不同切片之间也有批次效应,需要在QC阶段做初步校正。
避坑:运行sc.pp.regress_out()去除切片ID变量。 - 坑三:5万个点全保留——计算代价高,且大量无信号点会稀释空间信号。
避坑:先去除in_tissue=0或背景珠子,再降采样到合理数量。
我曾经接手一个项目,10x Visium数据里有30%的点在组织外,但是因为当初没有标记in_tissue,结果聚类时这些点自成一群。折腾了两周才发现。所以拿到数据第一件事就是看obsm['spatial']里每个点的坐标是否落在组织轮廓内。
- 确认平台和版本(10x Visium v1 vs v2 差异大)
- 读取所有文件并生成汇总报告
- 运行标准QC指标(n_genes, total_counts, mt%)
- 手动检查前100个异常点空间分布
- 保存两个版本:原始备份 & 过滤后备份
嗯,基本上预处理到这个程度就够喂给下游模型了。后续模型搭建阶段,你还会遇到批次校正、数据标准化这些事,但那是后话。数据干净了,模型至少赢了一半。