预处理:10x 数据读取与质量控制(Cell Ranger)
这一节,我们聊聊 10x 数据最关键的预处理环节——Cell Ranger。不少朋友拿到原始 BCL 文件后,第一反应就是跑 cellranger count,但实际项目中我见过太多因为参数不对、参考基因组版本搞混、或者直接忽略质控报告导致后面分析全崩的情况。说白了,Cell Ranger 不只是跑个命令,更像是一个流水线质检员——你给它正确的输入,它给你可靠的表达矩阵;你给它脏数据,它只会产出误导性的结果。
Cell Ranger 的核心流程
先看整体结构。下面这张图概括了从 BCL 到基因表达矩阵的全过程:
整个流水线其实就三步:BCL 转 FASTQ、比对定量、生成矩阵与报告。但每一步都有坑,我给大家拆开讲。
BCL 转换与 FASTQ 生成
如果你拿到的数据是 Illumina 原始的 BCL 格式,第一步需要用 cellranger mkfastq 拆分成 FASTQ。这步其实很简单,但要注意两个点:
- 样本 index 的配置:必须提供正确的样本 index 序列,否则会拆错样本。我之前就见过有人把 i7 和 i5 搞反,结果所有 reads 都标成了 unknown。
- barcode 长度:默认 10x 的 barcode 是 16bp,UMI 是 12bp。如果你用的是较新版本的 10x 试剂盒(如 3' v3),barcode 长度是 28bp,需要在 mkfastq 的参数里显式指定
--barcode-length=16,12(实际是 read1 的组成)。
命令示例:
cellranger mkfastq --id=Sample1 \
--run=/path/to/BCL_dir \
--samplesheet=samplesheet.csv \
--barcode-length=16,12 \
--localcores=8 --localmem=32
RunInfo.xml 确认 index 和 read 结构,不然直接 count 可能报错。
cellranger count 的主要参数
接下来是重头戏。我个人习惯把参数分成两类:必选参数和调优参数。
| 参数 | 作用 | 典型值 |
|---|---|---|
--id | 输出文件夹名 | sample_01 |
--transcriptome | 参考基因组路径(含 STAR 索引) | refdata-cellranger-GRCh38-3.0.0 |
--fastqs | FASTQ 所在目录 | ./fastq_path |
--sample | 样本名(匹配 FASTQ 前缀) | Sample1 |
--expect-cells | 预期捕获细胞数 | 5000 |
--localcores | CPU 核心数 | 8 |
--localmem | 内存(GB) | 32 |
运行命令一般是:
cellranger count --id=MySample \
--transcriptome=/ref/hg38/3.0.0 \
--fastqs=/data/FASTQ \
--sample=MY_SAMPLE \
--expect-cells=5000 \
--localcores=16 --localmem=64
核心质控指标解读
跑完后,outs/ 目录下会生成 web_summary.html(交互报告)和 metrics_summary.csv(数值表格)。我通常先看以下几个关键指标:
- Valid barcodes(有效 barcode 比例):正常 > 90%。如果低于 80%,可能是 barcode 长度设置错误,或者测序质量太差。
- Q30 bases in barcode & UMI:barcode 和 UMI 的碱基 Q30 比例,一般要求 > 90%。太低说明测序质量差,校正后有效 reads 会大量丢失。
- Fraction reads in cells:分配到细胞中的 reads 占比。我常看到新手只关注这个数字,其实它和期望细胞数有关,过高(> 95%)说明估计的细胞数偏少,可以适当调高
--expect-cells重新跑。 - Median genes per cell:每个细胞的中位基因数。人 PBMC 样本一般在 1000-2000 之间。如果是组织样本(如肝脏、肾脏),可能在 500-1500。特别低(< 300)提示细胞活性差或测序深度不足。
- Sequencing saturation:测序饱和度。这个指标很实用——如果低于 40%,说明测序深度不够,可以增加 reads;如果高于 90%,说明已经饱和,再加测序也测不到更多新基因,纯属浪费钱。
下面是一个相对健康的指标示例:
Estimated Number of Cells: 5,216
Fraction Reads in Cells: 0.92
Mean Reads per Cell: 42,518
Median Genes per Cell: 1,804
Median UMI Counts per Cell: 7,231
Sequencing Saturation: 0.65
Q30 Bases in Barcode: 0.96
Q30 Bases in UMI: 0.94
过滤参数调整与避坑
Cell Ranger 自动跑的过滤已经挺成熟,但有些场景需要手动调整。比如多细胞样本或低质量样本,系统可能把真正的低质量细胞判为空液滴而剔除。我个人经验是:先看 barcode 秩图(barcode rank plot),在 web_summary.html 的“Cells”部分可以下载。
如果你发现曲线拐点不明显,说明细胞/空液滴区分模糊。这时可以尝试:
- 调整
--expect-cells为更合理的数值(常见错误是随便填个 3000,实际样本有 8000 个细胞)。 - 运行完后再用
cellranger reanalyze调整过滤参数,比如修改min_umis和min_genes阈值。
示例 reanalyze 命令:
cellranger reanalyze --id=Reanalyze1 \
--matrix=../MySample/outs/filtered_feature_bc_matrix \
--params=params.json
params.json 内容可手动指定:
{
"min_umis": 500,
"min_genes": 200,
"min_confidence": 0.5
}
min_genes 设成 300,结果把一大群真正的低表达白血病细胞给剔除了,导致下游肿瘤亚群分析完全失真。过滤参数需要结合领域知识来设。
多样本重复(Aggr)前的准备
如果你要对多个 10x 样本做批次校正,通常先单独跑每个样本的 cellranger count,然后用 cellranger aggr 合并。但要注意:各个样本的过滤参数不同,合并前需统一。
我习惯的做法:
- 对所有样本用相同的
--expect-cells(比如取所有样本中位数)。 - 用
cellranger count跑完后,检查每个样本的metrics_summary.csv中的“Estimated Number of Cells”是否合理。 - 如果某个样本细胞数明显偏离预期(比如只有期望的一半),我会手动用 reanalyze 重新过滤,再导出整合矩阵。
这样到了下一讲做批次整合时,各个样本的细胞数和质量基线就比较一致了。
metrics_summary.csv 可以合并到一个表格里快速对比。我通常写个 Python 脚本把指标拉平,一次扫过去就看到哪个样本需要重跑。
最后一句
预处理的质量直接决定下游整合的成败。如果你在跑完 Cell Ranger 后,发现某个样本的基因检测中位数只有 300,而其他样本都是 2000,别急着往下做——先确认是技术问题(测序深度、barcode 指定错误)还是生物问题(样本本身细胞脆弱)。这一点,值得多花一天排查。