肿瘤转移克隆分析¶
一句话说明¶
肿瘤转移不是所有细胞一起跑,而是某个"精英亚克隆"获得了转移能力,克隆分析就是通过追踪突变来重建肿瘤演化树,找出哪个克隆在什么时候发生了转移。
核心知识点¶
1. 克隆演化基本概念¶
- 创始突变(trunk mutation):所有肿瘤细胞共有的早期突变(白话:家族的"始祖"突变)
- 分支突变(branch mutation):只在部分亚克隆中出现的后期突变
- 克隆(clone):共享一组突变的细胞群体
- 亚克隆(subclone):肿瘤内部的分支群体
- 白话类比:肿瘤演化像一棵树,树干是早期突变,树枝是后期分化出的亚群
2. 转移模型¶
| 模型 | 特点 |
|---|---|
| 线性模型 | 原发灶 → 单一克隆 → 转移灶 |
| 平行模型 | 原发和转移从共同祖先早期分化 |
| 自播种模型 | 转移灶的细胞回到原发灶 |
| 多克隆播种 | 多个克隆一起转移 |
3. 分析方法¶
- 突变聚类:将突变按 VAF 分组,每组代表一个克隆(PyClone, SciClone)
- 克隆树重建:推断克隆之间的祖先-后代关系(CITUP, ClonEvol)
- 多区域测序:对肿瘤多个部位取样,比较突变差异
- 配对分析:原发灶 + 转移灶的突变对比
4. Cancer Cell Fraction (CCF)¶
- 定义:携带某突变的肿瘤细胞比例
- 计算:CCF = VAF × (纯度校正因子)
- 克隆突变:CCF ≈ 1(所有肿瘤细胞都有)
- 亚克隆突变:CCF < 1(只有部分肿瘤细胞有)
实战代码¶
# === PyClone-VI 克隆结构推断 ===
import subprocess # 命令执行
# 1. 准备输入文件(TSV格式)
# 列:mutation_id, sample_id, ref_counts, alt_counts,
# major_cn, minor_cn, normal_cn, tumour_content
input_columns = """mutation_id\tsample_id\tref_counts\talt_counts\tmajor_cn\tminor_cn\tnormal_cn\ttumour_content
mut_1\tprimary\t100\t50\t2\t1\t2\t0.7
mut_1\tmetastasis\t120\t45\t2\t1\t2\t0.6
mut_2\tprimary\t90\t30\t2\t0\t2\t0.7
mut_2\tmetastasis\t110\t5\t2\t0\t2\t0.6
"""
# 2. 运行 PyClone-VI
cmd = (
"pyclone-vi fit " # 拟合模型
"-i input.tsv " # 输入文件
"-o pyclone_results.h5 " # 输出文件
"-c 40 " # 最大簇数
"-d beta-binomial " # 分布模型
"-r 10" # 重启次数
)
# subprocess.run(cmd, shell=True)
# 3. 提取结果
cmd2 = (
"pyclone-vi write-results-file " # 写出结果
"-i pyclone_results.h5 " # 输入
"-o pyclone_results.tsv" # 输出TSV
)
# subprocess.run(cmd2, shell=True)
# === ClonEvol 克隆演化可视化 ===
library(clonevol) # 克隆演化分析包
# 1. 准备输入数据(PyClone结果整理)
clone_data <- data.frame(
cluster = c(1, 1, 2, 2, 3, 3), # 克隆簇编号
sample = c("primary", "met", # 样本来源
"primary", "met",
"primary", "met"),
ccf = c(0.95, 0.90, # 克隆细胞比例
0.45, 0.70, # 克隆2在转移灶中扩增!
0.30, 0.05) # 克隆3在转移灶中缩小
)
# 2. 推断克隆树
tree <- infer.clonal.models(
variants = clone_data, # 克隆数据
cluster.col.name = "cluster", # 簇列名
ccf.col.name = "ccf", # CCF列名
sample.names = c("primary", "met"), # 样本名
cancer.initiation.model = "monoclonal", # 单克隆起源
subclonal.test = "bootstrap", # 自助法检验
num.boots = 1000 # 自助次数
)
# 3. 可视化克隆演化(鱼图)
plot.clonal.models(
tree, # 克隆树
matched = NULL, # 匹配参数
variants = clone_data, # 数据
box.plot = TRUE, # 箱线图模式
out.format = "pdf", # 输出格式
out.dir = "clonevol_output/" # 输出目录
)
# 鱼图(fishplot)展示克隆随时间/空间的演变
# 原发灶 vs 转移灶突变比较分析
import pandas as pd # 数据处理
import matplotlib.pyplot as plt # 绑图
from matplotlib_venn import venn2 # 韦恩图
# 读取两个样本的突变
primary = pd.read_csv("primary_mutations.vcf.gz",
sep="\t", comment="#",
usecols=[0,1,3,4],
names=["chr","pos","ref","alt"])
met = pd.read_csv("metastasis_mutations.vcf.gz",
sep="\t", comment="#",
usecols=[0,1,3,4],
names=["chr","pos","ref","alt"])
# 创建突变ID
primary["mut_id"] = primary.apply(
lambda r: f"{r['chr']}:{r['pos']}:{r['ref']}>{r['alt']}", axis=1)
met["mut_id"] = met.apply(
lambda r: f"{r['chr']}:{r['pos']}:{r['ref']}>{r['alt']}", axis=1)
# 集合比较
shared = set(primary["mut_id"]) & set(met["mut_id"]) # 共有突变(trunk)
primary_only = set(primary["mut_id"]) - set(met["mut_id"]) # 原发独有
met_only = set(met["mut_id"]) - set(primary["mut_id"]) # 转移独有
print(f"共有突变(trunk): {len(shared)}")
print(f"原发灶独有: {len(primary_only)}")
print(f"转移灶独有: {len(met_only)}")
# 韦恩图可视化
plt.figure(figsize=(8, 6))
venn2([set(primary["mut_id"]), set(met["mut_id"])],
set_labels=("原发灶", "转移灶")) # 两组标签
plt.title("原发灶 vs 转移灶突变对比")
plt.savefig("primary_vs_met_venn.png", dpi=150)
面试常问点¶
★ 怎么从测序数据推断肿瘤的克隆结构?¶
参考答案:核心是利用突变的 VAF(变异等位基因频率)。首先校正纯度和拷贝数,将 VAF 转换为 CCF(cancer cell fraction)。然后用聚类算法(如 PyClone 的贝叶斯模型)将 CCF 相似的突变分到同一个簇——每个簇代表一个克隆。最后根据"嵌套关系"(如果克隆 A 的 CCF 总是高于克隆 B,且 A 的突变包含 B 的所有突变,那么 B 是 A 的后代)重建克隆进化树。
★ 什么是鱼图(fishplot)?¶
参考答案:鱼图是一种可视化肿瘤克隆演化的方式,横轴是时间或空间(如治疗前/后、原发灶/转移灶),纵轴是每个克隆的细胞比例。形状像一条鱼的横截面——祖先克隆在底层最宽,后代克隆嵌套在里面。通过鱼图可以直观看到哪个克隆在治疗后扩增了(可能是耐药克隆)、哪个克隆缩小了。
速查卡片¶
| 问题 | 答案 |
|---|---|
| CCF | Cancer Cell Fraction,突变的肿瘤细胞占比 |
| 克隆聚类工具 | PyClone-VI, SciClone |
| 克隆树重建 | ClonEvol, CITUP |
| 可视化方法 | fishplot 鱼图 |
| trunk 突变 | 所有细胞共有的早期突变 |
| branch 突变 | 仅部分亚克隆有的晚期突变 |
| 多区域测序 | 同一肿瘤多点取样测序 |
| 转移播种模式 | 线性、平行、自播种、多克隆 |
| 耐药克隆 | 治疗后CCF上升的亚克隆 |
| 输入数据 | VAF + 拷贝数 + 纯度 |