跳转至

肿瘤克隆进化分析

一句话概述

使用PyClone、SciClone、PhyloWGS等工具从肿瘤体细胞突变数据中推断亚克隆结构、估计克隆细胞比例(CCF),重建肿瘤进化树以揭示肿瘤异质性和演化历程。


核心知识点总览

知识点关键内容重要程度
克隆与亚克隆肿瘤异质性/克隆结构概念⭐⭐⭐⭐⭐
VAF与CCF变异等位基因频率→细胞克隆频率转换⭐⭐⭐⭐⭐
PyClone-VI贝叶斯聚类推断克隆结构⭐⭐⭐⭐⭐
SciClone变分贝叶斯Beta混合模型/仅用CN中性区域⭐⭐⭐⭐
PhyloWGS整合SNV+CNV构建进化树⭐⭐⭐⭐
拷贝数整合CN状态对VAF→CCF转换的影响⭐⭐⭐⭐
多区域/纵向采样时空异质性揭示进化动态⭐⭐⭐
进化模型线性/分支/中性进化模式⭐⭐⭐

各步骤详解

第一步:肿瘤克隆进化的概念基础

白话解释: 肿瘤不是一坨均匀的坏细胞,而是由多个不同的"子群"(克隆/亚克隆)混合而成。这些子群有共同的祖先,但在进化过程中积累了不同的突变,就像一棵树从一个根分出很多枝一样。了解肿瘤的克隆结构有助于理解耐药机制和指导治疗策略。

技术细节: 关键概念: - VAF (Variant Allele Frequency):测序数据中突变reads占总reads的比例 - CCF (Cancer Cell Fraction):携带该突变的肿瘤细胞比例 - Clonal mutation:存在于所有肿瘤细胞中(CCF≈1) - Subclonal mutation:只存在于部分肿瘤细胞中(CCF<1) - Tumor purity:样本中肿瘤细胞的比例

VAF到CCF的转换需要考虑:肿瘤纯度、局部拷贝数、突变所在等位基因的拷贝数。

# VAF → CCF 转换公式
# CCF = VAF × (purity × CN_total + (1-purity) × 2) / (purity × CN_mutant)
#
# purity: 肿瘤纯度
# CN_total: 突变位点的总拷贝数
# CN_mutant: 携带突变的等位基因拷贝数(通常为1)
#
# 例:纯度=0.8, 二倍体区域(CN=2), 杂合突变
# CCF = VAF × (0.8×2 + 0.2×2) / (0.8×1) = VAF × 2/0.8 = 2.5 × VAF
# 如果 VAF=0.4, 则 CCF=1.0(克隆突变)
# 如果 VAF=0.2, 则 CCF=0.5(亚克隆,50%肿瘤细胞携带)

第二步:输入数据准备

白话解释: 克隆分析需要两类关键输入:(1) 体细胞突变的VAF信息(从肿瘤-正常配对测序中获得);(2) 拷贝数信息(告诉我们每个突变位点的基因组拷贝状态)。还需要肿瘤纯度估计。

技术细节:

# === 输入数据准备 ===

# 1. 体细胞突变检测(Mutect2)
gatk Mutect2 \
    -R reference.fasta \
    -I tumor.bam \
    -I normal.bam \
    -normal normal_sample_name \
    -O somatic.vcf.gz \
    --f1r2-tar-gz f1r2.tar.gz

# 过滤
gatk FilterMutectCalls \
    -R reference.fasta \
    -V somatic.vcf.gz \
    -O somatic.filtered.vcf.gz

# 2. 拷贝数分析(FACETS / Sequenza / ASCAT)
# FACETS示例
Rscript run_facets.R tumor.bam normal.bam

# 3. 肿瘤纯度估计(从FACETS/ASCAT获得)
# purity通常从拷贝数分析中同时估计

# 4. 准备PyClone输入
# 从VCF提取必要信息
bcftools query -f '%CHROM\t%POS\t%REF\t%ALT\t[%AD]\n' \
    somatic.filtered.vcf.gz > mutations_for_pyclone.txt
# 准备PyClone-VI输入文件
import pandas as pd
import numpy as np

# 读取突变信息
mutations = pd.read_csv("mutations_for_pyclone.txt", sep="\t",
                         header=None, names=['chrom', 'pos', 'ref', 'alt', 'AD'])

# 解析AD字段(ref_count,alt_count)
mutations[['ref_counts', 'alt_counts']] = mutations['AD'].str.split(',', expand=True).astype(int)
mutations['total_counts'] = mutations['ref_counts'] + mutations['alt_counts']
mutations['vaf'] = mutations['alt_counts'] / mutations['total_counts']

# 读取拷贝数信息(从FACETS/Sequenza)
cn_segments = pd.read_csv("copy_number_segments.txt", sep="\t")

# 为每个突变匹配CN信息
def get_cn(row, cn_df):
    seg = cn_df[(cn_df['chrom'] == row['chrom']) &
                 (cn_df['start'] <= row['pos']) &
                 (cn_df['end'] >= row['pos'])]
    if len(seg) > 0:
        return seg.iloc[0]['major_cn'], seg.iloc[0]['minor_cn']
    return 1, 1

mutations[['major_cn', 'minor_cn']] = mutations.apply(
    lambda row: pd.Series(get_cn(row, cn_segments)), axis=1)
mutations['total_cn'] = mutations['major_cn'] + mutations['minor_cn']

# 过滤:只保留有足够深度的位点
mutations_filtered = mutations[mutations['total_counts'] >= 20].copy()

# 生成PyClone-VI输入
pyclone_input = pd.DataFrame({
    'mutation_id': mutations_filtered['chrom'] + ':' + mutations_filtered['pos'].astype(str),
    'sample_id': 'tumor_sample',
    'ref_counts': mutations_filtered['ref_counts'],
    'alt_counts': mutations_filtered['alt_counts'],
    'major_cn': mutations_filtered['major_cn'],
    'minor_cn': mutations_filtered['minor_cn'],
    'normal_cn': 2,
    'tumour_content': 0.75  # 肿瘤纯度
})
pyclone_input.to_csv("pyclone_input.tsv", sep="\t", index=False)

第三步:PyClone-VI克隆推断

白话解释: PyClone-VI把所有突变根据它们的CCF相似性聚成几个"簇"(cluster),每个簇代表一个克隆或亚克隆。同一簇中的突变被认为是在进化过程中同一时间点产生的,因此存在于同一比例的肿瘤细胞中。

技术细节: PyClone-VI使用变分贝叶斯推断(比原版PyClone的MCMC快10-100倍),通过Beta-Binomial混合模型对突变reads count建模,考虑了拷贝数状态和肿瘤纯度对观测VAF的影响。已在PCAWG(1,717例患者)和TRACERx(100例患者)数据上验证。

# === PyClone-VI 运行 ===
pip install pyclone-vi

# 运行PyClone-VI
pyclone-vi fit \
    -i pyclone_input.tsv \
    -o pyclone_results.h5 \
    -c 40 \
    -d beta-binomial \
    -r 10

# 参数说明:
# -c 40: 最大簇数(算法会自动选择实际簇数)
# -d beta-binomial: 数据分布模型(推荐)
# -r 10: 重启次数(取最优ELBO)

# 输出结果
pyclone-vi write-results-file \
    -i pyclone_results.h5 \
    -o pyclone_clusters.tsv
# PyClone-VI 结果解析与可视化
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 读取结果
results = pd.read_csv("pyclone_clusters.tsv", sep="\t")

# 查看克隆结构
cluster_summary = results.groupby('cluster_id').agg(
    n_mutations=('mutation_id', 'count'),
    mean_ccf=('cellular_prevalence', 'mean'),
    std_ccf=('cellular_prevalence', 'std')
).sort_values('mean_ccf', ascending=False)

print("Clone structure:")
print(cluster_summary)

# 可视化:CCF分布
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# 左:CCF密度图
for cluster in results['cluster_id'].unique():
    subset = results[results['cluster_id'] == cluster]
    axes[0].hist(subset['cellular_prevalence'], alpha=0.5,
                 label=f"Cluster {cluster} (n={len(subset)})", bins=20)
axes[0].set_xlabel("Cellular Prevalence (CCF)")
axes[0].set_ylabel("Number of mutations")
axes[0].legend()

# 右:簇大小 vs 平均CCF
axes[1].scatter(cluster_summary['mean_ccf'], cluster_summary['n_mutations'],
                s=100, alpha=0.7)
for idx, row in cluster_summary.iterrows():
    axes[1].annotate(f"C{idx}", (row['mean_ccf'], row['n_mutations']))
axes[1].set_xlabel("Mean CCF")
axes[1].set_ylabel("Number of mutations")
plt.tight_layout()
plt.savefig("clone_structure.pdf")

第四步:SciClone亚克隆分析

白话解释: SciClone特别适合从全外显子组(WES)数据中检测亚克隆。它的独特之处在于只使用拷贝数中性区域(CN=2的区域)的突变,避免了CN异常对VAF解释的复杂影响。SciClone使用变分贝叶斯Beta混合模型(VBBMM)自动推断聚类数目,计算效率远高于MCMC方法。注意:在多区域测序时,如果CN异常区域较多,可用突变数可能很少,此时PyClone-VI可能更合适。

技术细节:

# === SciClone 分析 ===
library(sciClone)

# 准备输入
# 1. VAF表(chr, pos, ref_reads, var_reads, vaf)
vafs <- read.table("sample_vafs.txt", header = TRUE)
# 列:chr, pos, ref_count, var_count, vaf

# 2. 拷贝数segments
cn_segs <- read.table("copy_number_segs.txt", header = TRUE)
# 列:chr, start, end, segment_mean (log2ratio)

# 3. 需排除的区域(LOH区域)
loh_regions <- read.table("loh_regions.txt", header = TRUE)

# 运行SciClone
sc <- sciClone(
  vafs = vafs,
  copyNumberCalls = cn_segs,
  sampleNames = "Tumor_Sample",
  regionsToExclude = loh_regions,
  minimumDepth = 20,
  maximumClusters = 10,
  clusterMethod = "bmm"  # beta mixture model
)

# 输出结果
writeClusterTable(sc, "sciclone_clusters.txt")

# 可视化
sc.plot1d(sc, "sciclone_1d.pdf")
sc.plot2d(sc, "sciclone_2d.pdf")  # 需要多区域采样

# 多区域采样分析(2个区域)
sc_multi <- sciClone(
  vafs = list(vafs_region1, vafs_region2),
  copyNumberCalls = list(cn_region1, cn_region2),
  sampleNames = c("Region1", "Region2"),
  minimumDepth = 20
)
sc.plot2d(sc_multi, "multi_region_2d.pdf")

第五步:PhyloWGS进化树重建

白话解释: PyClone和SciClone告诉我们"有几个克隆、各含多少突变",但没有告诉我们这些克隆之间的进化关系(谁是谁的祖先?)。PhyloWGS通过贝叶斯方法同时推断克隆结构和进化树拓扑,告诉你肿瘤是如何一步步进化的。

技术细节: PhyloWGS使用树结构先验和MCMC采样,整合SNV和CNV信息,推断最可能的进化树。它的输出是一组可能的进化树及其后验概率。

# === PhyloWGS 运行 ===

# 准备SSM(Simple Somatic Mutations)文件
# 格式:id, gene, a(var_reads), d(total_reads), mu_r, mu_v
python parser/create_phylowgs_inputs.py \
    --vcf-type mutect \
    --tumor-sample TUMOR \
    --cnvs cnv_data.txt \
    --output-variants ssm_data.txt \
    --output-params params.json \
    somatic.filtered.vcf.gz

# 运行PhyloWGS
python multievolve.py \
    --num-chains 4 \
    --ssms ssm_data.txt \
    --cnvs cnv_data.txt \
    --params params.json \
    --output-dir phylowgs_output

# 解析结果
python write_results.py \
    phylowgs_output/trees.zip \
    phylowgs_output/results \
    --include-ssm-names
# PhyloWGS结果可视化
import json
import numpy as np

# 读取最优树
with open("phylowgs_output/results/best_tree.json") as f:
    tree = json.load(f)

# 打印克隆结构
for node_id, node_data in tree['populations'].items():
    print(f"Clone {node_id}:")
    print(f"  CCF: {node_data['cellular_prevalence']:.3f}")
    print(f"  Num SSMs: {len(node_data['ssms'])}")
    print(f"  Num CNVs: {len(node_data['cnvs'])}")
    print(f"  Children: {node_data.get('children', [])}")
    print()

# 使用ETE3绘制进化树
from ete3 import Tree, TreeStyle

def build_newick(tree_data, node_id="0"):
    children = tree_data['populations'][node_id].get('children', [])
    if not children:
        return f"Clone_{node_id}"
    child_strs = [build_newick(tree_data, str(c)) for c in children]
    return f"({','.join(child_strs)})Clone_{node_id}"

newick = build_newick(tree) + ";"
t = Tree(newick)
t.render("evolution_tree.pdf")

第六步:多区域/纵向取样的克隆进化分析

白话解释: 从肿瘤的一个位置采样只能看到"快照",无法直接观察进化过程。如果从肿瘤的多个空间位置采样(多区域),或在治疗前后多次采样(纵向),就能直接观察克隆的时空动态——哪些克隆在扩张,哪些在治疗后消失。

技术细节:

# === 多区域/纵向分析 ===

# 使用CITUP(Clonality Inference in Tumors Using Phylogenetics)
# 或 CliP(Clonality in Pairwise samples)

# 方法1:PyClone多样本联合分析
# 准备多样本输入(同一个病人的多个样本)
# pyclone_input_multisample.tsv 包含多个sample_id

# PyClone-VI 自动处理多样本
pyclone-vi fit \
    -i multisample_input.tsv \
    -o multisample_results.h5 \
    -c 40 \
    -d beta-binomial \
    -r 10

# 方法2:使用fishplot可视化克隆动态
library(fishplot)

# 定义时间点
timepoints <- c(0, 30, 100, 200)  # 天数

# 定义各克隆在各时间点的细胞比例
# 行=克隆, 列=时间点
frac.table <- matrix(
  c(100, 50, 10, 0,     # Clone A (对治疗敏感)
     30, 80, 90, 95,    # Clone B (耐药克隆)
     0,  10, 20, 5),    # Clone C (新出现)
  ncol = 4, byrow = TRUE
)

# 定义父子关系
parents <- c(0, 1, 1)  # Clone B和C都从Clone A衍生

# 创建fishplot
fish <- createFishObject(frac.table, parents, timepoints = timepoints,
                          clone.labels = c("Clone A", "Clone B", "Clone C"))
fish <- setCol(fish, c("#E41A1C", "#377EB8", "#4DAF4A"))
fishPlot(fish, shape = "spline", title.btm = "Clonal Evolution Under Treatment",
         vlines = c(30), vlab = c("Treatment Start"))

第七步:结果解释与临床意义

白话解释: 克隆进化分析的最终目的是指导临床决策:理解耐药机制(哪个亚克隆携带耐药突变?)、预测复发(治疗后残存的亚克隆是什么?)、设计联合治疗策略。

技术细节:

# === 克隆进化结果的临床解读 ===

# 1. 驱动突变与克隆归属
# 确定每个驱动突变属于哪个克隆
driver_genes <- c("TP53", "KRAS", "PIK3CA", "PTEN")
driver_mutations <- results[results$gene %in% driver_genes, ]
driver_clone_assignment <- merge(driver_mutations, cluster_results,
                                  by = "mutation_id")

# 2. 克隆的时间顺序推断
# 克隆型(CCF≈1)突变:早期/创始突变
# 亚克隆(CCF<1)突变:晚期/进展相关突变
early_mutations <- results[results$cellular_prevalence > 0.9, ]
late_mutations <- results[results$cellular_prevalence < 0.5, ]

# 3. 治疗相关克隆动态
# 比较治疗前后的CCF变化
pre_treatment <- read.csv("pre_treatment_ccf.csv")
post_treatment <- read.csv("post_treatment_ccf.csv")
ccf_change <- merge(pre_treatment, post_treatment, by = "cluster_id",
                     suffixes = c("_pre", "_post"))
ccf_change$delta_ccf <- ccf_change$ccf_post - ccf_change$ccf_pre
# delta_ccf > 0: 耐药克隆扩张
# delta_ccf < 0: 对治疗敏感

实战命令速查

# 完整克隆进化分析流程
# 1. 变异检测
gatk Mutect2 -I tumor.bam -I normal.bam -normal NORMAL -O somatic.vcf.gz
# 2. 拷贝数
Rscript run_facets.R tumor.bam normal.bam
# 3. 准备输入
python prepare_pyclone_input.py somatic.vcf.gz cn_segments.txt 0.75
# 4. 克隆推断
pyclone-vi fit -i input.tsv -o results.h5 -c 40 -d beta-binomial -r 10
pyclone-vi write-results-file -i results.h5 -o clusters.tsv
# 5. 进化树
python phylowgs/multievolve.py --ssms ssm.txt --cnvs cnv.txt

面试常问点

Q1: VAF和CCF的关系是什么?为什么不能直接用VAF代表克隆比例?

A: VAF是观测值(突变reads/总reads),CCF是生物学量(携带突变的肿瘤细胞比例)。VAF受三个因素影响:(1) 肿瘤纯度——正常细胞稀释突变信号;(2) 局部拷贝数——基因组扩增/缺失改变expected VAF;(3) 突变等位基因拷贝数。只有在纯度100%、二倍体、杂合突变的理想情况下,CCF = 2×VAF。

Q2: PyClone和SciClone的主要区别?

A: PyClone-VI使用所有突变(包括CN异常区域),通过Beta-Binomial混合模型显式建模CN和纯度对VAF的影响,使用变分贝叶斯推断(比原版PyClone的MCMC快10-100倍)。SciClone只使用CN中性区域(CN=2)的突变,采用变分贝叶斯Beta混合模型(VBBMM)聚类VAF,简化了模型但损失了CN异常区域的数据。SciClone的2D/3D VAF图直观展示多区域采样的克隆结构。实际中,SciClone在多区域测序时可用突变数可能很少(因为要求所有区域都是CN中性),PyClone-VI适用性更广。Benchmarking研究推荐 Mutect2 + FACETS + PyClone-VI 为最优组合。

Q3: 什么是肿瘤的中性进化模式?

A: 中性进化假说认为肿瘤一旦建立,后续多数亚克隆是被动"搭便车"(passenger)扩张,而非被正选择驱动。其特征是:VAF分布遵循1/f幂律分布,没有明显的亚克隆peak。检测方法包括Williams等2016年提出的1/f拟合检验。非中性进化则表现为明显的亚克隆VAF peak。

Q4: 多区域采样如何改善克隆分析?

A: 单点采样面临采样偏差——可能遗漏空间异质的亚克隆。多区域采样可以:(1) 发现空间受限的亚克隆;(2) 通过突变在不同区域的存在/缺失模式更准确地推断进化树拓扑;(3) 区分平行进化(convergent evolution)和线性进化。ITH(Intra-Tumor Heterogeneity)TRACERx项目就是基于多区域采样的大型研究。

Q5: 克隆进化分析对精准医疗有什么价值?

A: (1) 指导靶向治疗——如果耐药突变在亚克隆中,提前设计联合方案可防止耐药克隆扩张;(2) 液体活检监测——ctDNA中追踪特定克隆的VAF变化可早期预警复发;(3) 预后预测——高ITH通常预示更差预后;(4) 新抗原疫苗设计——优先选择克隆性新抗原(存在于所有肿瘤细胞)以避免免疫逃逸。


易错点

1. 忽略拷贝数对VAF的影响

在CN扩增区域(如chr8p gain),相同CCF的突变其VAF会被稀释;在LOH区域,VAF会升高。不校正CN直接聚类VAF会产生虚假的亚克隆。

2. 肿瘤纯度估计不准

纯度估计偏低会使所有CCF被高估,纯度偏高会使CCF被低估。建议用多种方法(FACETS/ASCAT/ABSOLUTE)估计纯度并取共识值。

3. 测序深度不足导致CCF不准

低深度测序(<100x)时,VAF的采样方差大,小的亚克隆难以可靠检测。WGS(30x)只能检测>10% CCF的克隆;深度靶向测序(>500x)可检测低至1%的亚克隆。

4. 聚类数过度解读

PyClone可能因数据噪声产生额外的小簇。不应过度解读含<5个突变的小簇。建议结合生物学先验(如驱动突变分布)评估簇的可靠性。

5. 忽略克隆之间的树约束

多个亚克隆之间必须满足进化树约束(如"嵌套"关系——子克隆的CCF不能超过其父克隆)。如果聚类结果违反树约束,说明存在模型假设错误或数据问题。


补充知识

其他克隆分析工具

  • ABSOLUTE (Broad):联合估计纯度、倍性和CCF
  • DPClust:PCAWG项目使用的DP混合模型
  • CloneFinder:快速聚类方法
  • Canopy:贝叶斯方法同时推断CNA和进化树
  • CITUP:使用整数线性规划推断进化树

工具推荐(基于2021年Nature Communications benchmarking)

最优亚克隆解卷积流程:Mutect2(突变检测) + FACETS(拷贝数) + PyClone-VI(克隆聚类)。该组合在多种模拟和真实数据集上表现最优。

液体活检中的克隆追踪

  • ctDNA中突变的动态监测可实时追踪克隆进化
  • 分子残留病灶(MRD)检测使用clone-specific突变
  • 治疗过程中出现新突变提示耐药克隆出现

引用推荐

  • PyClone-VI: Gillis & Roth, BMC Bioinformatics, 2020(非2021年,发表于2020年12月10日,DOI: 10.1186/s12859-020-03919-2)
  • SciClone: Miller et al., PLoS Computational Biology, 2014
  • PhyloWGS: Deshwar et al., Genome Biology, 2015
  • TRACERx: Jamal-Hanjani et al., NEJM, 2017
  • 最优流程推荐: Benchmarking研究(2021, Nature Communications)推荐 Mutect2 + FACETS + PyClone-VI 组合