单细胞测序从样本采集到最终分析报告,中间有多少步骤?每个步骤需要多长时间?这篇文章带你梳理完整时间线,帮你做好项目规划。
一、单细胞转录组分析完整时间线
| 阶段 | 内容 | 周期 |
|---|---|---|
| 样本准备 | 组织解离、细胞活率检测 | 1-2天 |
| 文库构建 | 10x Chromium 建库 | 1天 |
| 测序 | NovaSeq/NovaSeq X | 1-2天 |
| 原始数据处理 | Cell Ranger / cellranger mkfastq | 0.5-1天 |
| 质量控制 | 细胞过滤、基因过滤、双细胞检测 | 0.5-1天 |
| 标准化与降维 | Log归一化、PCA、UMAP/t-SNE | 0.5天 |
| 聚类与注释 | Leiden聚类、Marker基因、细胞类型注释 | 1-2天 |
| 差异表达分析 | 组间差异基因鉴定 | 0.5-1天 |
| 功能富集分析 | GO/KEGG 通路富集 | 0.5天 |
| 报告撰写 | 图表整理、结果解读 | 1-2天 |
| 合计 | 7-14天 |
二、用 Scanpy 搭建标准化分析 Pipeline
以下是可复用的完整流程代码:
import scanpy as sc import pandas as pd import numpy as np import matplotlib.pyplot as plt # ========== Step 1: 读取数据 ========== # 支持 10x h5 / mtx / 已有 h5ad adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5") # 或 from cellranger: adata = sc.read("filtered_feature_bc_matrix.h5ad") print(f"原始: {adata.n_obs} 细胞 × {adata.n_vars} 基因") # ========== Step 2: 质量控制 ========== # 计算每个细胞的 QC 指标 adata.var['mt'] = adata.var_names.str.startswith('MT-') adata.var['ribo'] = adata.var_names.str.startswith(('RPL', 'RPS')) sc.pp.calculate_qc_metrics( adata, qc_vars=['mt', 'ribo'], percent_top=None, log1p=False, inplace=True ) # 可视化 QC 指标 sc.pl.violin(adata, ['n_genes_by_counts', 'total_counts', 'pct_counts_mt'], jitter=0.4, multi_panel=True, save='_qc_violin.pdf') # 过滤阈值(根据数据调整) adata = adata[adata.obs['pct_counts_mt'] < 20].copy() adata = adata[adata.obs['n_genes_by_counts'] > 200].copy() adata = adata[adata.obs['n_genes_by_counts'] < 6000].copy() print(f"过滤后: {adata.n_obs} 细胞 × {adata.n_vars} 基因") # ========== Step 3: 标准化 ========== sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) # ========== Step 4: 高变基因识别 ========== sc.pp.highly_variable_genes(adata, min_mean=0.0125, max_mean=3, min_disp=0.5) sc.pl.highly_variable_genes(adata, save='_hvgs.pdf') adata = adata[:, adata.var['highly_variable']].copy() # ========== Step 5: 回归技术噪声 ========== sc.pp.regress_out(adata, ['total_counts', 'pct_counts_mt']) sc.pp.scale(adata, max_value=10) # ========== Step 6: PCA 降维 ========== sc.tl.pca(adata, svd_solver='arpack') sc.pl.pca_variance_ratio(adata, n_pcs=50, save='_pca_variance.pdf') # ========== Step 7: 近邻图构建 ========== sc.pp.neighbors(adata, n_neighbors=10, n_pcs=40) # ========== Step 8: UMAP 可视化 ========== sc.tl.umap(adata, random_state=42) sc.pl.umap(adata, color='n_genes_by_counts', save='_umap_n_genes.pdf') # ========== Step 9: 聚类 ========== sc.tl.leiden(adata, resolution=0.5, random_state=42) sc.pl.umap(adata, color='leiden', legend_loc='on data', save='_umap_clusters.pdf') # ========== Step 10: Marker 基因鉴定 ========== sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon') sc.pl.rank_genes_groups(matplotlib=True, n_genes=25, save='_rank_genes.pdf') # ========== Step 11: 细胞类型注释 ========== # 手动注释(根据文献 Marker) marker_dict = { 'T cells': ['CD3D', 'CD3E', 'IL7R'], 'B cells': ['CD79A', 'MS4A1', 'CD19'], 'Monocytes': ['FCGR3A', 'LYZ', 'CST3'], 'NK cells': ['NKG7', 'GNLY', 'CD56'], 'Dendritic cells': ['FCER1A', 'CST3'], } adata.obs['cell_type'] = 'Unknown' for ct, markers in marker_dict.items(): mask = adata[:, [g for g in markers if g in adata.var_names]].X.mean(axis=1) > 0.5 adata.obs['cell_type'] = adata.obs['cell_type'].cat.add_categories([ct]) adata.obs.loc[mask, 'cell_type'] = ct sc.pl.umap(adata, color='cell_type', save='_umap_celltype.pdf') # ========== Step 12: 保存结果 ========== adata.write('scanpy_analysis_result.h5ad') print("分析完成,结果已保存为 scanpy_analysis_result.h5ad")三、项目管理的 5 个关键要点
1. 样本元数据管理
# 用 obs 字段记录样本信息 adata.obs['sample_id'] = ['S1', 'S1', ..., 'S2', 'S2', ...] adata.obs['condition'] = ['Control', 'Control', ..., 'Treatment', 'Treatment', ...] adata.obs['batch'] = ['Batch1', 'Batch1', ..., 'Batch2', 'Batch2', ...] adata.obs['patient_id'] = [...]
2. 批次效应校正
# 多样本整合 import scanpy as sc import harmonypy as hm # 方法1:Harmony(推荐) sc.tl.pca(adata, svd_solver='arpack') harmony_results = hm.run_harmony(adata.obsm['X_pca'], adata.obs, 'batch') adata.obsm['X_pca_harmony'] = harmony_results.Z_corr.T sc.pp.neighbors(adata, use_rep='X_pca_harmony') sc.tl.umap(adata) sc.tl.leiden(adata, resolution=0.5)
3. 结果可复现性
# 固定随机种子 import random import numpy as np random.seed(42) np.random.seed(42) sc.settings.seed = 42
4. 矢量图输出(直接用于论文)
# 所有图表输出为矢量格式 sc.settings.figdir = './figures/' sc.pl.umap(adata, color='cell_type', save='_celltype.pdf', dpi=300) # PDF 矢量图 sc.pl.umap(adata, color='cell_type', save='_celltype.svg', dpi=300) # SVG 矢量图
5. 分析报告自动生成
# 用 Jupyter Notebook + nbconvert 自动生成报告 # 配合 Papermill 实现参数化报告批量生成 import papermill as pm pm.execute_notebook( 'analysis_template.ipynb', 'report_sample1.ipynb', parameters=dict(sample_id='S1', min_cells=3) )
四、为什么标准化流程很重要?
| 问题 | 影响 | 标准化解决方案 |
|---|---|---|
| 过滤阈值随意 | 细胞数量差异大,结论不可比 | 制定统一 QC 标准 |
| 参数不记录 | 结果无法复现 | 用 YAML 配置文件管理参数 |
| 图表分辨率低 | 论文返修要求重画 | 默认输出 300dPI 矢量图 |
| 分析路径混乱 | 交付周期不可控 | 标准化 Pipeline + 时间估算 |
五、不想自己搭 Pipeline?
如果你是课题组的 PI 或生物背景的研究者,花大量时间调试代码、处理报错,其实是在消耗本该用于科学问题思考的时间。
Run2AI 运智(run2ai.open2ai.cn)提供从原始数据到可发表图表的标准化全流程分析,Python/Scanpy + R/Seurat 双引擎,所有图表默认 300dPI 矢量格式,直接用于论文投稿。
时间线的意义不在于自己把每个步骤都做一遍,而在于知道每个步骤应该花多少时间、产出什么质量的结果。
把技术执行交给专业团队,把科学洞察留给自己。
https://run2ai.open2ai.cn