总览
为了检测差异甲基化,在每个CpG位点进行统计测试,然后根据指定的阈值进行差异甲基化位点(DML)或差异甲基化区域(DMR)分析。 严格的统计测试应考虑重复样本之间的生物学差异和测序深度,而大多数现有的差异甲基化检测手段都是基于hoc方法。 例如,使用Fisher精确值会忽略生物学变异,使用t检验来估计甲基化水平则会忽略测序深度。 在一些情况下,有些不期望发生的过滤却会发生:当一个过滤阈值被随意的设置后,一些深度达不到硬性标准的基因座将会被过滤,这从而导致了信息的丢失。
DSS中实施的差异甲基化检测程序系针对β-二项分布的严格Wald检验。测试统计基于生物学差异(通过离散参数表征)以及测序深度来实现。 作为DSS实施算法的重要部分,离散参数估计是通过基于贝叶斯层次模型的收缩估计器实现的。 DSS的优点是可以在没有生物学重复的条件下进行。 这是因为通过平滑处理,相邻的CpG位点可以被视为伪复制,基于此离散度仍可以在合理的精度下被估算。
DSS对于一般的实验设计也是有效的,这是通过基于具有反正弦函数的beta-二项式回归模型来实现的。 使用广义最小二乘法对变换后的数据进行模型拟合,与基于广义线性模型的方法相比,可以大大提高计算性能。
DSS依赖于Bioconductor的bsseq软件包,该软件包对数据结构的定义清晰,并且具有许多有用的实用功能。 为了使用DM检测功能,需要预先安装bsseq。
输入数据准备
DSS上游的数据来自于bismark软件的结果,这里通过转换bismark_methylation_extractor的cov结果文件来获得输入文件。
这是bismark_methylation_extractor的cov结果文件:
$ head speciman_pe.deduplicated.bismark.cov | column -t
rCRS 33 33 0 0 15
rCRS 34 34 1.2987012987013 5 380
rCRS 61 61 0 0 42
rCRS 62 62 0.283687943262411 2 703
rCRS 78 78 3.50877192982456 2 55
rCRS 79 79 2.08768267223382 20 938
rCRS 80 80 3.44827586206897 2 56
rCRS 81 81 2.02634245187437 20 967
rCRS 91 91 0 0 62
rCRS 92 92 1.95167286245353 21 1055
这是DSS所需要读取的输入文件:
$ head specimen.dss.input.txt | column -t
chr pos N X
rCRS 33 15 0
rCRS 34 385 5
rCRS 61 42 0
rCRS 62 705 2
rCRS 78 57 2
rCRS 79 958 20
rCRS 80 58 2
rCRS 81 987 20
rCRS 91 62 0
用于格式转换的Python脚本代码:
# -*- coding:utf-8 -*-
import glob
import gzip
import logging
import os
import sys
import pandas as pd
logging.basicConfig(format='%(asctime)s\t%(name)s\t%(levelname)s : %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
if __name__ == '__main__':
dirs_path = sys.argv[1]
dir_paths = glob.glob(os.path.join(dirs_path, '*'))
for path in dir_paths:
sp_name = os.path.basename(path)
fp = os.path.join(os.path.join(path, 'result/{}_pe.deduplicated.bismark.cov'.format(sp_name)))
if not os.path.isfile(fp) and os.path.isfile('{}.gz'.format(fp)):
logger.debug('Unzip {}.gz'.format(fp))
with gzip.GzipFile('{}.gz'.format(fp)) as gz_file:
open(fp, 'wb+').write(gz_file.read())
logger.debug('Process {}'.format(fp))
df = pd.read_table(fp, header=None)
df[6] = df[4] + df[5]
df.rename({0: 'chr', 1: 'pos', 4: 'X', 6: 'N'}, axis=1, inplace=True)
df = df.reindex(['chr', 'pos', 'N', 'X'], axis=1)
output_dir = os.path.join(path, 'output')
if not os.path.isdir(output_dir):
os.mkdir(output_dir)
df.to_csv(os.path.join(output_dir, '{}.dss.input.txt'.format(sp_name)), sep='\t', index=False)
从两两组间比较中进行DML/DMR检测
DML: Differential Methylation Loci
DMR: Differential Methylation Regions
Step 1. 加载文库。读取输入的文本数据并创建BSseq类的对象。
library(DSS)
require(bsseq)
dat1A <- read.table("specimen1A.dss.input.txt", header = T)
dat1B <- read.table("specimen1B.dss.input.txt", header = T)
dat1C <- read.table("specimen1C.dss.input.txt", header = T)
dat2A <- read.table("specimen2A.dss.input.txt", header = T)
dat2B <- read.table("specimen2B.dss.input.txt", header = T)
dat2C <- read.table("specimen2C.dss.input.txt", header = T)
BSobj <- makeBSseqData(
list(dat1A, dat1B, dat1C, dat2A, dat2B, dat2C),
c("specimen1A", "specimen1B", "specimen1C",
"specimen2A", "specimen2B", "specimen2C")
)
Step 2. 调用DMLtest函数对DML执行统计测试。DMLtest函数将基本上执行以下步骤:(1)估算所有CpG位点的平均甲基化水平;(2)估算每个CpG位点的离散度; (3)进行瓦尔德检验。我们在函数参数中可以选择是否进行平滑处理。因为甲基化水平显示出很强的空间相关性,所以当数据中的CpG位点密集时(such as from the whole-genome BS-seq),平滑处理有助于更好地估计平均甲基化。但是,对于CpG稀疏的数据(such as from RRBS or hydroxyl-methylation),不建议进行平滑处理。
本次分析是WGBS,因此进行平滑处理。
dmlResult <- DMLtest(BSobj, group1 = c("specimen1A", "specimen1B", "specimen1C"), group2 = c("specimen2A", "specimen2B", "specimen2C"), smoothing = T)
注意:我们可以选择是否平滑处理甲基化水平,默认不做处理。对于WGBS数据,建议进行平滑处理,如此可以合并CpG位点附近的信息以改善对甲基化水平的估计效果。在RRBS中,由于CpG覆盖范围很稀疏,平滑处理可能不会对结果产生太大影响。如果要求做平滑处理,则平滑跨度将是一个重要参数,该参数能显著影响DMR的检测效果;DSS的DMLtest函数没有开放该参数,并将500 bp作为默认值,作者认为该参数在实际数据测试中也会获得良好的表现。
Step 3. 使用callDML函数做DML检测。 结果按将显著性排序。
dmls <- callDML(dmlResult, delta = 0.1, p.threshold = 0.05)
Step 4. 我们将基于DML检测结果来调用callDMR函数进行DMR检测。DMR系具有许多统计上显着CpG位点的区域。此外,我们还能使用一些规定限制条件的参数来做DMR的显著性检测,包括最小长度,最小CpG站点数,该区域中CpG站点的百分比等等。不仅如此,还有一些后续的方法能一快区域内的DMR片段合并为一段更长的DMR。
dmrs <- callDMR(dmlResult, delta = 0.1, p.threshold = 0.05)