如何用WGDI进行共线性分析(一)

多倍化以及后续的基因丢失和二倍化现象存在于大部分的物种中, 是物种进化的重要动力。如果一个物种在演化过程中发生过多倍化,那么在基因组上就会存在一些共线性区域(即两个区域之间的基因是旁系同源基因,其基因的排布顺序基本一致)。

例如拟南芥经历了3次古多倍化,包括2次二倍化,一次3倍化 (Tang. et.al 2008 Science).

..For example, Arabidopsis thaliana (thale cress) has undergone three paleo-polyploidies, including two doublings (5) and one tripling (12), resulting in ~12 copies of its ancestral chromosome set in a ~160-Mb genome…

当然之前只是记住了结论,现在我想的是,如何复现出这个分析结果呢?

前期准备

首先,我们需要使用conda安装wgdi。 我一般会新建一个环境避免新装软件和其他软件产生冲突

1
2
3
4
# 安装软件
conda create -c bioconda -c conda-forge -n wgdi wgdi
# 启动环境
conda activate wgdi

之后,我们从ENSEMBL上下载基因组,CDS, 蛋白和GFF文件

1
2
3
4
5
6
7
8
9
#Athaliana
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/arabidopsis_thaliana/dna/Arabidopsis_thaliana.TAIR10.dna.toplevel.fa.gz
gunzip Arabidopsis_thaliana.TAIR10.dna.toplevel.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/arabidopsis_thaliana/cds/Arabidopsis_thaliana.TAIR10.cds.all.fa.gz
gunzip Arabidopsis_thaliana.TAIR10.cds.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/arabidopsis_thaliana/pep/Arabidopsis_thaliana.TAIR10.pep.all.fa.gz
gunzip Arabidopsis_thaliana.TAIR10.pep.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/gff3/arabidopsis_thaliana/Arabidopsis_thaliana.TAIR10.44.gff3.gz
gunzip Arabidopsis_thaliana.TAIR10.44.gff3.gz

注意: cDNA和CDS并不相同,CDS只包括起始密码子到终止密码子之间的序列,而cDNA还会包括UTR.

数据预处理

数据的预处理是用时最长的步骤,因为软件要求的输入格式并非是你手头所拥有的格式,你通常都需要进行一些转换才能得到它所需的形式。

wgdi需要三种信息,分别是BLAST, 基因的位置信息和染色体长度信息,要求格式如下

  1. BLAST 的 -outfmt 6输出的文件

  2. 基因的位置信息: 以tab分隔,分别为chr,id,start,end,strand,order,old_id。(并非真正意义上的GFF格式)

  3. 染色体长度信息和染色体上的基因个数,格式为 chr, length, gene number

同时,对于每个基因我们只需要一个转录本,我通常使用最长的转录本作为该基因的代表。之前我写过一个脚本 (get_the_longest_transcripts.py) 提取每个基因的最长转录本,我在此处上写了一个新的脚本用来根据参考基因组和注释的GFF文件生成wgdi的两个输入文件,脚本地址为https://github.com/xuzhougeng/myscripts/blob/master/comparative/generate_conf.py

1
pytho generate_conf.py -p ath Arabidopsis_thaliana.TAIR10.dna.toplevel.fa Arabidopsis_thaliana.TAIR10.44.gff3

输出文件是ath.gff 和 ath.len.

由于ENSEMBL上GFF的ID编号和pep.fa 和cds.fa 不太一致,简单的说就是,编号之前中有一个 “gene:” 和 “transcript:” . 如下

1
2
3
4
5
6
7
8
9
10
11
12
$ head ath.gff 
1 gene:AT1G01010 3631 5899 + 1 transcript:AT1G01010.1
1 gene:AT1G01020 6788 9130 - 2 transcript:AT1G01020.1
1 gene:AT1G01030 11649 13714 - 3 transcript:AT1G01030.1
1 gene:AT1G01040 23416 31120 + 4 transcript:AT1G01040.2
1 gene:AT1G01050 31170 33171 - 5 transcript:AT1G01050.1
1 gene:AT1G01060 33379 37757 - 6 transcript:AT1G01060.3
1 gene:AT1G01070 38444 41017 - 7 transcript:AT1G01070.1
1 gene:AT1G01080 45296 47019 - 8 transcript:AT1G01080.2
1 gene:AT1G01090 47234 49304 - 9 transcript:AT1G01090.1
1 gene:AT1G01100 49909 51210 - 10 transcript:AT1G01100.2

于是我用 sed 删除了这些信息

1
sed -i -e 's/gene://' -e 's/transcript://' ath.gff

另外,pep.fa, cds.fa里面包含所有的基因,且命名特别的长, 同时我们也不需要基因中的 “.1”, “.2” 这部分信息

1
2
3
4
5
6
7
$ head -n 5 Arabidopsis_thaliana.TAIR10.cds.all.fa 
>AT3G05780.1 cds chromosome:TAIR10:3:1714941:1719608:-1 gene:AT3G05780 gene_biotype:protein_coding transcript_biotype:protein_coding gene_symbol:LON3 description:Lon protease homolog 3, mitochondrial [Source:UniProtKB/Swiss-Prot;Acc:Q9M9L8]
ATGATGCCTAAACGGTTTAACACGAGTGGCTTTGACACGACTCTTCGTCTACCTTCGTAC
TACGGTTTCTTGCATCTTACACAAAGCTTAACCCTAAATTCCCGCGTTTTCTACGGTGCC
CGCCATGTGACTCCTCCGGCTATTCGGATCGGATCCAATCCGGTTCAGAGTCTACTACTC
TTCAGGGCACCGACTCAGCTTACCGGATGGAACCGGAGTTCTCGCGATTTATTGGGTCGTb

借助于seqkit, 我对原来的数据进行了筛选和重命名

1
2
seqkit grep -f <(cut -f 7 ath.gff ) Arabidopsis_thaliana.TAIR10.cds.all.fa | seqkit seq --id-regexp "^(.*?)\\.\\d" -i > ath.cds.fa
seqkit grep -f <(cut -f 7 ath.gff ) Arabidopsis_thaliana.TAIR10.pep.all.fa | seqkit seq --id-regexp "^(.*?)\\.\\d" -i > ath.pep.fa

通过NCBI的BLASTP 或者DIAMOND 进行蛋白之间相互比对,输出格式为 -outfmt 6

1
2
makeblastdb -in ath.pep.fa -dbtype prot
blastp -num_threads 50 -db ath.pep.fa -query ath.pep.fa -outfmt 6 -evalue 1e-5 -num_alignments 20 -out ath.blastp.txt &

共线性分析

绘制点阵图

在上面步骤结束后,其实绘制点阵图就非常简单了,只需要创建配置文件,然后修改配置文件,最后运行wgdi。

基本wgdi的其他分析也都是三部曲,创建配置,修改配置,运行程序。

第一步,创建配置文件

1
2
wgdi -d \? > ath.conf

配置文件的信息如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[dotplot]
blast = blast file
gff1 = gff1 file
gff2 = gff2 file
lens1 = lens1 file
lens2 = lens2 file
genome1_name = Genome1 name
genome2_name = Genome2 name
multiple = 1 # 最好的同源基因数, 用输出结果中会用红点表示
score = 100 # blast输出的score 过滤
evalue = 1e-5 # blast输出的evalue 过滤
repeat_number = 20 # genome2相对于genome1的最多同源基因数
position = order
blast_reverse = false
ancestor_left = none
ancestor_top = none
markersize = 0.5 # 点的大小
figsize = 10,10 # 图片大小
savefig = savefile(.png,.pdf)

第二步,修改配置文件。因为是自我比对,所以 gff1和gff2内容一样, lens1和lens2内容一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[dotplot]
blast = ath.blastp.txt
gff1 = ath.gff
gff2 = ath.gff
lens1 = ath.len
lens2 = ath.len
genome1_name = A. thaliana
genome2_name = A. thaliana
multiple = 1
score = 100
evalue = 1e-5
repeat_number = 5
position = order
blast_reverse = false
ancestor_left = none
ancestor_top = none
markersize = 0.5
figsize = 10,10
savefig = ath.dot.png

最后运行如下命令

1
wgdi -d ath.conf

输出的png如下所示

点阵图

从图中,我们很容易地就能观察到三种颜色,分别是红色,蓝色,和灰色。在WGDI中,红色表示genome2的基因在genome1中的最优同源(相似度最高)的匹配,次好的四个基因是蓝色,而剩余部分是为灰色。图中对角线出现的片段并非是自身比对,因为WGDI已经过滤掉自身比自身的结果。那么问题来了,这些基因是什么呢?这个问题会在后续的分析中进行解答。

如果基因组存在加倍事件,那么对于一个基因组的某个区域可能会存在另一个区域与其有着相似的基因(同源基因),并且这些基因的排布顺序较为一致。反应到点阵图上,就是能够观察到有多个点所组成的”线”。这里的线需要有一个引号,因为当你放大之后,你会发现其实还是点而已。

部分区域放大

由于进一步鉴定共线性区域就建立在这些”点”的基础上,那么影响这些点是否为同源基因的参数就非常重要了,即配置文件中的score,evalue,repeat_number。

共线性分析和Ks计算

对于同线性(synteny)和共线性(collinearity),一般认为同线性指的是两个区域有一定数量的同源基因,对基因顺序排布无要求。共线性是同线性的特殊形式,要求同源基因的排布顺序也相似。

wgdi开发了-icl模块(Improved version of ColinearScan)用于进行共线性分析,使用起来非常简单,也是先建立配置文件。

1
wgdi -icl \? >> ath.conf

然后对配置文件进行修改.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[collinearity]
gff1 = ath.gff
gff2 = ath.gff
lens1 = ath.len
lens2 = ath.len
blast = ath.blastp.txt
blast_reverse = false
multiple = 1
process = 8
evalue = 1e-5
score = 100
grading = 50,40,25
mg = 40,40
pvalue = 0.2
repeat_number = 10
positon = order
savefile = ath.collinearity.txt

其中的evalue, score和BLAST文件的过滤有关,用于筛选同源基因对。multiple确定最佳比对基因,repeat_number表示最多允许多少基因是潜在的同源基因, grading根据同源基因的匹配程度进行打分, mg 指的是共线性区域中所允许最大空缺基因数。

运行结果后,会得到ath.collinearity.txt,记录共线性区域。以 # 起始的行记录共线性区域的元信息,例如得分(score),显著性(pvalue),基因对数(N)等。

1
2
grep '^#' ath.collinearity.txt | tail -n 1
# Alignment 959: score=778.0 pvalue=0.0003 N=16 Pt&Pt minus

紧接着,我们就可以根据共线性结果来计算Ks。

同样的也是先生成配置文件

1
wgdi -ks \? >> ath.conf

然后修改配置文件。我们需要提供cds和pep文件,共线性分析输出文件(支持MCScanX的共线性分析结果)。WGDI会用muscle根据蛋白序列进行联配,然后使用pal2pal.pl 基于cds序列将蛋白联配转成密码子联配,最后用paml中的yn00计算ka和ks。

1
2
3
4
5
6
7
[ks]
cds_file = ath.cds.fa
pep_file = ath.pep.fa
align_software = muscle
pairs_file = ath.collinearity.txt
ks_file = ath.ks

ks计算需要一段时间,那么不妨在计算时了解下Ka和Ks。Ka和Ks分别指的是非同义替换位点数,和同义替换位点数。根据中性演化假说,基因的变化大多是中性突变,不会影响生物的生存,那么当一对同源基因分开的时间越早,不影响生存的碱基替换数就越多(Ks),反之越多。

运行结果后,输出的Ks文件共有6列,对应的是每个基因对的Ka和Ks值。

1
2
3
4
5
6
7
8
9
10
11
$ head ath.ks
id1 id2 ka_NG86 ks_NG86 ka_YN00 ks_YN00
AT1G72300 AT1G17240 0.1404 0.629 0.1467 0.5718
AT1G72330 AT1G17290 0.0803 0.5442 0.079 0.6386
AT1G72350 AT1G17310 0.3709 0.9228 0.3745 1.071
AT1G72410 AT1G17360 0.2636 0.875 0.2634 1.1732
AT1G72450 AT1G17380 0.2828 1.1068 0.2857 1.5231
AT1G72490 AT1G17400 0.255 1.2113 0.2597 2.0862
AT1G72520 AT1G17420 0.1006 0.9734 0.1025 1.0599
AT1G72620 AT1G17430 0.1284 0.7328 0.1375 0.603
AT1G72630 AT1G17455 0.0643 0.7608 0.0613 1.2295

鉴于共线性和Ks值输出结果信息量太大,不方便使用,更好的方法是将两者进行聚合,得到关于各个共线性区的汇总信息。

WGDI提供 -bi 参数帮助我们进行数据整合。同样也是生成配置文件

1
wgdi -bi ? >> ath.conf

修改配置文件. 其中collinearity 和ks是我们前两步的输出文件,而 ks_col 则是声明使用ks文件里的哪一列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[blockinfo]
blast = ath.blastp.txt
gff1 = ath.gff
gff2 = ath.gff
lens1 = ath.len
lens2 = ath.len
collinearity = ath.collinearity.txt
score = 100
evalue = 1e-5
repeat_number = 20
position = order
ks = ath.ks
ks_col = ks_NG86
savefile = ath_block_information.csv

运行即可

1
2
wgdi -bi ath.conf

输出文件以csv格式进行存放,因此可以用EXCEL直接打开,共11列。

  1. id 即共线性的结果的唯一标识
  2. chr1,start1,end1 即参考基因组(点图的左边)的共线性范围
  3. chr2,start2,end2 即参考基因组(点图的上边)的共线性范围
  4. pvalue 即共线性结果评估,常常认为小于0.01的更合理些
  5. length 即共线性片段长度
  6. ks_median 即共线性片段上所有基因对ks的中位数(主要用来评判ks分布的)
  7. ks_average 即共线性片段上所有基因对ks的平均值
  8. homo1,homo2,homo3,homo4,homo5multiple参数有关,即一共有homo+multiple列

主要规则是:基因对如果在点图中为红色,赋值为1,蓝色赋值为0,灰色赋值为-1(颜色参考前述 wgdi 点图 相关推文)。共线性片段上所有基因对赋值后求平均值,这样就赋予该共线性一个-1,1的值。如果共线性的点大部分为红色,那么该值接近于1。可以作为共线性片段的筛选。

  1. block1,block2分别为共线性片段上基因order的位置。
  2. ks共线性片段的上基因对的ks
  3. density1,density2 共线性片段的基因分布密集程度。值越小表示稀疏

这个表格是后续探索分析的一个重点,比如说我们可以用它来分析我们点图中出现在对角线上的基因。下面的代码就是提取了第一个共线性区域的所有基因,然后进行富集分析,绘制了一个气泡图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
df <- read.csv("ath_block_information.csv")

tandem_length <- 200

df$start <- df$start2 - df$start1
df$end <- df$end2 - df$end1

df_tandem <- df[abs(df$start) <= tandem_length |
abs(df$end) <= tandem_length,]

gff <- read.table("ath.gff")

syn_block1 <- df_tandem[1,c("block1", "block2")]

gene_order <- unlist(
lapply(syn_block1, strsplit, split="_", fixed=TRUE, useBytes=TRUE)
)

gene_order <- unique(as.numeric(gene_order))


syn_block1_gene <- gff[ gff$V6 %in% gene_order, "V2"]

#BiocManager::install("org.At.tair.db")
library(org.At.tair.db)
library(clusterProfiler)

ego <- enrichGO(syn_block1_gene,
OrgDb = org.At.tair.db,
keyType = "TAIR",ont = "BP"
)
dotplot(ego)

气泡图

进一步观察这些基因,可以发现这些基因的编号都是前后相连,说明这个基因簇和花粉识别有一定关系。

1
2
3
4
5
6
7
8
9
> as.data.frame(ego)[1,]
ID Description GeneRatio BgRatio pvalue
GO:0048544 GO:0048544 recognition of pollen 11/560 43/21845 7.794138e-09
p.adjust qvalue
GO:0048544 8.121073e-06 7.95418e-06
geneID
GO:0048544 AT1G61360/AT1G61370/AT1G61380/AT1G61390/AT1G61400/AT1G61420/AT1G61440/AT1G61480/AT1G61490/AT1G61500/AT1G61550
Count
GO:0048544 11

A gene cluster is a group of two or more genes found within an organism’s DNA that encode similar polypeptides, or proteins, which collectively share a generalized function and are **often located within a few thousand base pairs **of each other. –维基百科

接下来,我们还可以根据这个表格中的Ks对点阵图进行上色, 以及正确的计算Ks峰值。

「小技巧」如何让IGV更快的加载GTF和GFF注释文件

很简单,就下面3行命令

1
2
3
gff=
(grep ^"#" $gff; grep -v ^"#" $gff | sort -k1,1 -k4,4n) | bgzip > sorted.gff.gz;
tabix -p gff sorted.gff.gz;

第一行的gff是定义输入文件。第二行是对GFF文件进行排序。第三行是利用HTSLIB中的tabix工具建立索引,得到一个sorted.gff.gz.tbi 索引文件。

后续IGV在加载文件时,会根据索引文件直接读取给定区域的信息,不但可以降低内存的占用,还可以提高加载速度。

如何给bioconda贡献recipes

bioconda是conda中专门用来管理生物信息相关软件的频道。

绝大部分的用户都是利用bioconda安装软件,绝大部分的教程也都是教大家如何去使用bioconda安装软件。但是bioconda的便利性并不是从天而降的,而是无数的软件开发者持续的不断的贡献和更新一些软件的recipe (菜谱) 的结果。这篇教程就是教大家如何在一个软件没有bioconda的安装方式时,自己动手写一个菜谱。

准备工作

首先,我们在https://github.com/bioconda/bioconda-recipes 上fork该项目到自己的GitHub项目下,然后将其clone到本地

1
2
3
git clone https://github.com/xuzhougeng/bioconda-recipes.git
cd bioconda-recipes

如果一不小心克隆使用了官方的项目或者我的项目,也可以通过如下命令进行修改

1
2
git remote rm origin
git remote add origin 你的github地址

由于bioconda是建立在conda基础上的频道,因此我们还需要预先安装好 conda,关于conda 的安装、配置和使用可以看我上传到哔哩哔哩的视频。之后安装 conda-build, 用于创建conda软件包的框架。

1
2
3
# 安装conda-build, 后续用于创建模板
conda install conda-build

实际流程

向bioconda贡献一个软件的菜谱大致分为6步:

  1. 创建分支

  2. 编辑recipes

  3. 推送修改

  4. 创建pull请求

  5. 删除你的分支

  6. 安装你的包

第一步: 创建分支

我们需要先切换到主分支(master), 并保证你的主分支处于最新状态

1
2
3
git checkout master
git pull upstream master
git push origin master

接下来,我们创建新的分支,用于处理当前的菜谱,避免影响主分支

1
git checkout -b update_My_recipes

我建议这里的 update_My_recipes 修改成具体的软件名,这样更有标识性。

第二步: 编辑recipe

我们使用 conda skeleton 创建一个软件包框架, 这里pypi指的是软件托管在pypi上,wgdi则是软件名。

1
2
3
# bioconda-recipes目录下
cd recipes
conda skeleton pypi wgdi

因为wgdi存在一些依赖环境,如PAML, MAFFT, MUSCLE, PAL2NAL, 所以我们需要修改 wgdi/meta.yaml 文件,在其中加入这些软件。

1
2
3
4
5
6
7
8
9
10
11
12
run:
- biopython
- matplotlib
- numpy
- pandas >=1.1.0
- python
- scipy
- paml
- mafft
- muscle
- pal2nal

事实上,conda skeleton 只是做了一小部分事情,我目前的meta.yaml 还不完整,直到后续的递交中修改了数十次才知道出问题的地方以及如何修改。

因此建议后还需要查阅 https://docs.conda.io/projects/conda-build/en/latest/resources/define-metadata.html 了解meta.yaml的更多知识。

第三步: 向GitHub上推送更新

这里就是用git命令将我们的修改推送到GitHub上

1
2
3
4
# bioconda-recipes目录下
git add recipes/wgdi
git commit -m "add wgdi recipes"
git push origin update_My_recipes

第四步: 创建pull 请求

此时,让我们回到GitHub 中我们fork的bioconda-recipes页面。我们可以看到该修改已经被推送到GitHub上。

compare & pull request

我们点击 Compare & pull request, 接着就会弹出一个页面,介绍如何书写提交申请。

Add title

这里写了4点要求,分别为

  1. 在PR中加入Add或者update 作为用于说明目的,必须是第一个词

  2. 如果该项目和生物学领域无关,建议换个地方。

  3. 一旦通过了审核,需要在后续的issue中加入 @BiocondaBot please add label, 具体区别在后面的命令说明中有提到。

  4. 如果有问题,你可以到Gitter或者在评论中用 @bioconda/core 提出自己的问题。

当你提出PR之后,bioconda 的构建系统就会测试我们提交的菜谱。如果通过了测试,我们就可以跳转到下一步,否则需要重复第二~四步,直到通过为止。

我们发现在提交之后,构建系统就提示了一个问题。

lint problem

点开Details,会出现如下的界面。我们可以点击View more details on CircleCI Checks 去聊了解更加详细的信息。

view problem

lint问题的修改建议可在bioconda的对应页面为 https://bioconda.github.io/contributor/linting.html 进行查找。我把自己遇到的问题放在文末,毕竟是第一次,对于自动化测试系统并不了解,所以我反复修改了十多次。

当我们的菜谱最终通过了自动化测试后,接下来就可以在我们的issue中留言 @bioconda-bot add label ,让机器人增加标签,然后等待管理员review同意你的PR,当然也需要你进行修改才行。

add label

第五步: 删除分支

当我们的Pull Request被合并之后,我们就可以在GitHub上删除我们的分支,或者在本地删除

1
2
3
4
# Delete local branch
git branch -D update_My_recipes
# Delete branch in your fork via the remote named "origin"
git push origin -d update_My_recipes

第六步: 安装你的包

经过前面五步之后,你需要再等待一会,才能让你的包被加入到bioconda频道中。一旦被加入到bioconda频道,那么所有人都可以非常容易的通过conda来安装你得工具了。

1
conda install -c bioconda wgdi

其他

在我配置 wgdi包的时候,遇到了如下几种错误

1
2
3
ERROR: recipes/wgdi/meta.yaml:0: uses_matplotlib: The recipe uses `matplotlib`, but `matplotlib-base` is recommended
ERROR: recipes/wgdi/meta.yaml:16: should_be_noarch_generic: The recipe should be build as `noarch`
ERROR: recipes/wgdi/meta.yaml:4: folder_and_package_name_must_match: The recipe folder and package name do not match.

根据我的错误,我在原来的yaml文件中做了如下的更改

  • uses_matplotlib: 将原来的matplotlib 替换成matplobtlib-base

  • should_be_noarch_generic: 在build下增加 noarch: generic (这一步有问题,请继续往后阅读找到正确答案,此处保留时为了记录我的思考过程)

  • folder_and_package_name_must_match: 在配置文件开头增加 {% set name = "wgdi" %}

之后在test-linu时,我遇到了 ModuleNotFoundError: No module named 'wgdi'报错。这个问题和之前的 should_be_noarch_generic密切相关。noarch指的是平台无关,也就是这个软件不需要额外的编译就可以使用。一般这类软件通常是Java编译后的包,而非Python包。我最初根据提示的 should_be_noarch_generic 增加的 noarch: generic 实际并不正确,实际应该是 noarch: python, 也就是表示我们包依赖的Python平台。

参考资料:

通过X11转发在服务器上用IGV

通常情况下,我们无法是直接在服务器上打开IGV,因为它既要求服务器上安装X服务,本地也要安装X服务,才能将服务器上的图形信息转发到本地。

事实上是要配置好X11转发,就可以在服务器上运行其他的图形界面程序。

第一步: 在服务器上配置Xserver(需要管理员权限)

1
sudo yum install  xorg-x11-server-Xorg xorg-x11-xauth xorg-x11-apps -y

第二步: 在windows上配置X服务

我们从 https://sourceforge.net/projects/xming/ 下载Xming

Xming

安装完成后,右下角有Xming Server的地址信息,一般会是0.0或者1.0

Xnubg Server

第三步: 设置Xshell或Putty

!配置Xshell](https://halo-1252249331.cos.ap-shanghai.myqcloud.com/upload/2021/01/image-8dbd12df088e4b688b71f4b72f86ecd2.png)

配置Putty

第四步: 下载IGV并解压缩

1
2
wget https://data.broadinstitute.org/igv/projects/downloads/2.8/IGV_Linux_2.8.13_WithJava.zip
unzip IGV_Linux_2.8.13_WithJava.zip

运行该目录下的 igv_hidpi.sh igv.sh即可

使用ArchR分析单细胞ATAC-seq数据(第十六章)

第16章 使用ArchR进行轨迹分析

ArchR在ArchRProject中低维子空间对细胞进行排序来创建细胞轨迹,实现伪时间中细胞排序。我们之前已经在二维UMAP子空间中执行了这种排序,但是ArchR改进了这种方法,使其能够在N维子空间(即LSI)内进行对齐。

  • 首先,ArchR需要用户提供一个轨迹骨架描述细胞分组/聚类的大致分化方向。例如,用户提供的细胞编号为HSC, GMP, Monocyte,这表示细胞以干细胞作为起点,然后是祖细胞,最后是分化细胞。这种分化方向信息来自于已有的生物学相关的细胞轨迹发育的背景知识。
  • 其次,ArchR计算每个聚类在N维空间的平均坐标,对于聚类里的每个细胞,计算其相对于平均指标的欧几里得距离,最后只保留前5%的细胞。
  • 然后,ArchR根据轨迹计算cluster i里的每个细胞和cluster i+1平均坐标的距离,根据距离计算拟时间向量。之后依次遍历所有的cluster执行运算。根据每个细胞相对于细胞分组/聚类平均坐标的欧几里得距离,ArchR能够为每个细胞确定N维坐标和它的拟时间值从而成为轨迹的一部分。
  • 然后,ArchR使用smooth.spline函数根据拟时间值讲连续的轨迹拟合到N维坐标中。
  • 接着,ArchR根据欧氏距离最近细胞沿着流形依次将所有细胞对齐到轨迹上。
  • 最后,ArchR将对其后的值缩放到100,并将其保存在ArchRProject中用于下游分析。

ArchR可以根据Arrow文件里的特征创建拟时间趋势矩阵。例如,ArchR可以分析随着拟时间发生变化的TF deviation, 基因得分,整合基因表达量,从而鉴定随着细胞轨迹动态变化的调节因子或调控元素。

  • 首先,ARchR将细胞沿着细胞轨迹进行分组,组数由用户定义(默认是1/100)
  • 然后,ArchR使用用户定义平滑滑窗(默认是9/100)对矩阵的特征进行平滑处理(调用data.table::frollmean函数)
  • 最后,ArchR会返回一个SummarizedExperiment对象,它是一个平滑后的拟时间 X 特征矩阵,用于下游分析。

ArchR还可以根据以下信息对任意两个平滑后拟时间 X 特征矩阵进行关联分析,例如匹配的命名(如chromVAR TF deviations的正向调控因子和基因得分/整合谱),之前章节提到的利用低重叠细胞聚集的基因组位置重叠方法(例如 peak-to-gene 关联)。最终,ArchR能为细胞轨迹的整合分析提供帮助,解释多组学之间动态调控关系。

16.1 髓系轨迹-单核细胞分化

这一节,我们会创建一个细胞估计用以模拟HSC发育成分化后单核细胞的过程。 在开始之前,我们先来检查保存在cellColData中的聚类和之前定义的细胞类型,分别是”Clusters”和”Clusters2”。我们通过UMAP来进行展示,从中找到我们感兴趣的细胞类型。

1
2
3
p1 <- plotEmbedding(ArchRProj = projHeme5, colorBy = "cellColData", name = "Clusters", embedding = "UMAP")
p2 <- plotEmbedding(ArchRProj = projHeme5, colorBy = "cellColData", name = "Clusters2", embedding = "UMAP")
ggAlignPlots(p1, p2, type = "h")

Plot-UMAP-Clusters12-Combined

16.1.1 拟时间UMAP和特征单独作图

我们接下来会用到”Clusters2”里面定义的细胞类型。和之前提到的那样,我们会以干细胞(“Progenitor”)-骨髓祖细胞(“GMP”)-单核细胞(“Mono”)这个分化过程创建轨迹。

第一步,我们需要以用一个向量记录轨迹骨干,里面按顺序记录发育各过程中细胞分组的标签。

1
trajectory <- c("Progenitor", "GMP", "Mono")

第二步,我们使用addTrajectory()创建轨迹,并加入到ArchRProject中。我们将其命名为”MyeloidU”。该函数的作用就是在cellColData中新建一列,命名为”MyeloidU”,然后记录每个细胞在轨迹中拟时间值。不在轨迹中的细胞记做NA

1
2
3
4
5
6
7
8
projHeme5 <- addTrajectory(
ArchRProj = projHeme5,
name = "MyeloidU",
groupBy = "Clusters2",
trajectory = trajectory,
embedding = "UMAP",
force = TRUE
)

我们可以检查下该信息,你会发现每个细胞都有一个唯一值,值的取值范围是0-100。我们将NA的细胞过滤掉,因为它们不属于轨迹。

1
2
head(projHeme5$MyeloidU[!is.na(projHeme5$MyeloidU)])
# [1] 46.07479 53.75027 44.82834 43.18828 47.49617 43.21015

我们使用plotTrajectory()函数绘制轨迹,它会用UMAP进行可视化,用拟时间值进行上色,箭头标识轨迹的发育方向。非轨迹的细胞会以灰色标识。在这个例子中,我们使用colorBy = "cellColData"name="MyeloidU"让ArchR使用cellColData里”MyeloidU”作为拟时间轨迹。参数中trajectoryname都是”MyeloidU”,可能不太容易理解,ArchR根据trajectory来提取细胞,根据name来对细胞进行着色。

1
2
p <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "cellColData", name = "MyeloidU")
p[[1]]

Plot-MyeloidU-Traj-UMAP

使用plotPDF()保存为可编辑的矢量图

1
plotPDF(p, name = "Plot-MyeloidU-Traj-UMAP.pdf", ArchRProj = projHeme5, addDOC = FALSE, width = 5, height = 5)

我们还可以在UMAP嵌入图中展示轨迹和其他特征。这可以用来展示和我们轨迹有关的特征。

如果你还没有在projHeme5项目中加入推测权重,请先运行下面的代码

1
projHeme5 <- addImputeWeights(projHeme5)

然后我们绘制”MyeloidU”轨迹,只不过颜色来自于”CEBPB”的基因得分,这是一个已知的调控单核细胞功能的基因,会随着发育而活跃。我们通过colorBy参数来指定表达量矩阵,使用name来指定特征

1
p1 <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "GeneScoreMatrix", name = "CEBPB", continuousSet = "horizonExtra")

重复上面的代码,只不过这次使用的是GeneIntegrationMatrix作为基因表达量矩阵

1
p2 <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "GeneIntegrationMatrix", name = "CEBPB", continuousSet = "blueYellow")

plotTrajectory函数实际上返回了一系列图。列表中第一个图是UMAP嵌入图,根据函数调用进行上色。

通过比较基因得分和基因表达量的UMAP图,不难发现CEBPB基因在单核细胞中特异性表达,出现在你时序轨迹的后半部分。

1
ggAlignPlots(p1[[1]], p2[[1]], type = "h")

Plot-UMAP-CEBPB-Combined

plotTrajectory()函数返回的是一个点图,x轴是拟时间,y轴是对应特征的值,此处是CEBPB的基因得分或基因表达量。下图中的细胞以拟时间进行着色

1
ggAlignPlots(p1[[2]], p2[[2]], type = "h")

Plot-UMAP-CEBPB-Combined2

16.1.2 拟时间热图

我们可以用热图的形式对特征随着拟时间变化进行可视化。首先我们用getTrajectory()函数从ArchRProject中提取感兴趣的轨迹,它会返回一个SummarizedExperiment对象。通过设置useMatrix参数,我们可以用motif,基因得分,基因表达量,peak开放性来创建拟时间热图

1
trajMM  <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "MotifMatrix", log2Norm = FALSE)

接着将SummarizedExperiment传给plotTrajectoryHeatmap()函数

1
p1 <- plotTrajectoryHeatmap(trajMM, pal = paletteContinuous(set = "solarExtra"))

Plot-MyeloidU-Traj-Heatmaps

同样的分析可以使用基因得分绘制拟时间热图,只需要设置useMatrix = "GeneScoreMatrix"

1
2
trajGSM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "GeneScoreMatrix", log2Norm = TRUE)
p2 <- trajectoryHeatmap(trajGSM, pal = paletteContinuous(set = "horizonExtra"))

Plot-MyeloidU-Traj-Heatmaps_2

同样的,还可以绘制基因表达量的拟时间热图,设置useMatrix = "GeneIntegrationMatrix".

1
2
trajGIM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "GeneIntegrationMatrix", log2Norm = FALSE)
p3 <- plotTrajectoryHeatmap(trajGIM, pal = paletteContinuous(set = "blueYellow"))

Plot-MyeloidU-Traj-Heatmaps_3

最后,我们可以通过设置useMatrix = "PeakMatrix"绘制peak开放性的拟时间热图

1
2
trajPM  <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "PeakMatrix", log2Norm = TRUE)
p4 <- plotTrajectoryHeatmap(trajPM, pal = paletteContinuous(set = "solarExtra"))

Plot-MyeloidU-Traj-Heatmaps_4

使用plotPDF()保存可编辑的矢量图

1
plotPDF(p1, p2, p3, p4, name = "Plot-MyeloidU-Traj-Heatmaps.pdf", ArchRProj = projHeme5, addDOC = FALSE, width = 6, height = 8)

16.1.3 整合拟时间分析

我们也可以进行整合分析,例如整合基因得分/基因表达量和motif开发状态,鉴定随拟时间变化的正向TF调控因子。这是一个非常有效的手段,例如鉴定分化相关的驱动因子。我们可以用correlateTrajectories()函数进行该分析,它接受两个SummarizedExperiment对象,该对象可以用getTrajectories()函数获取。

首先,让我们找到开放状态随拟时间和TF基因的基因得分相关的motif

1
corGSM_MM <- correlateTrajectories(trajGSM, trajMM)

correlateTrajectories()函数的主要输出是一个列表,第一个是DataFrame对象。DataFrame的列名分别是idx1, matchname1, name1VarAssay1, 对应索引,匹配名,原名,传递给correlateTrajectories()函数的第一个轨迹的特征的方差分位数(variance quantile)。方差分位数是给定特征的标准化值,能用于比较不同来源assay里的相关值。该DataFrame包括所有符合correlateTrajectories()函数里阈值的特征。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
corGSM_MM[[1]]
## DataFrame with 36 rows and 12 columns
## idx1 idx2 matchname1 matchname2 name1 name2
##
## 1 82 1081 PRDM16 PRDM16 chr1:PRDM16 z:PRDM16_211
## … … … … … … …
## 36 22097 1565 RXRA RXRA chr9:RXRA z:RXRA_695
## Correlation VarAssay1 VarAssay2 TStat
##
## 1 0.859588836579798 0.999783802481948 0.860344827586207 16.6530781620713
## … … … … …
## 36 0.59509316489084 0.88640982401522 0.890229885057471 7.33039570155334
## Pval FDR
##
## 1 2.47466579579935e-30 4.04855324192774e-27
## … … …
## 36 6.60626612679289e-11 1.25672690505037e-09

我们然后从SummarizedExperiment提取相应的轨迹,

1
2
trajGSM2 <- trajGSM[corGSM_MM[[1]]$name1, ]
trajMM2 <- trajMM[corGSM_MM[[1]]$name2, ]

为了更好的对这些特征排序,我们创建新的轨迹,它的值来自于原先的轨迹的相乘。这可以让我们的热图根据行进行排序

1
2
trajCombined <- trajGSM2
assay(trajCombined) <- t(apply(assay(trajGSM2), 1, scale)) + t(apply(assay(trajMM2), 1, scale))

我们可以从plotTrajectoryHeatmap()函数返回的结果提取最优的行序。

1
2
combinedMat <- plotTrajectoryHeatmap(trajCombined, returnMat = TRUE, varCutOff = 0)
rowOrder <- match(rownames(combinedMat), rownames(trajGSM2))

有了这个之后,我们就可以创建配对热图。

首先,我们根据基因得分轨迹创建热图。在rowOrder参数中设置给定的行序

1
ht1 <- plotTrajectoryHeatmap(trajGSM2,  pal = paletteContinuous(set = "horizonExtra"),  varCutOff = 0, rowOrder = rowOrder)

然后,我们根据motif轨迹创建热图。在rowOrder参数中设置给定的行序

1
ht2 <- plotTrajectoryHeatmap(trajMM2, pal = paletteContinuous(set = "solarExtra"), varCutOff = 0, rowOrder = rowOrder)

通过将两个热图并排排列,我们可以看到两个热图的行是匹配的。你可能会发现该分析同时捕获了GATA3和GATA3-AS1(一个GATA3的反义转录本)。这是由于特征匹配所导致的,我们需要在后续分析时进行手动过滤。

1
ht1 + ht2

Plot-MyeloidU-GS-TF

我们可以重复以上的分析,但这次使用GeneIntegrationMatrix而非基因得分。因为这是相同的分析流程,因此代码就不再过多解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
corGIM_MM <- correlateTrajectories(trajGIM, trajMM)
trajGIM2 <- trajGIM[corGIM_MM[[1]]$name1, ]
trajMM2 <- trajMM[corGIM_MM[[1]]$name2, ]

trajCombined <- trajGIM2
assay(trajCombined) <- t(apply(assay(trajGIM2), 1, scale)) + t(apply(assay(trajMM2), 1, scale))

combinedMat <- plotTrajectoryHeatmap(trajCombined, returnMat = TRUE, varCutOff = 0)

rowOrder <- match(rownames(combinedMat), rownames(trajGIM2))

ht1 <- plotTrajectoryHeatmap(trajGIM2, pal = paletteContinuous(set = "blueYellow"), varCutOff = 0, rowOrder = rowOrder)
ht2 <- plotTrajectoryHeatmap(trajMM2, pal = paletteContinuous(set = "solarExtra"), varCutOff = 0, rowOrder = rowOrder)

ht1 + ht2

Plot-MyeloidU-GEx-T

16.2 淋巴轨迹-B细胞分化

第二个例子会根据祖细胞-淋巴祖细胞-前B细胞-分化后B细胞来构建B细胞的分化轨迹。由于该分析从本质上是重复之前单核细胞轨迹分析,因此这里只介绍关键性的代码不同。

第一处是trajectory变量的赋值。

1
trajectory <- c("Progenitor", "CLP", "PreB", "B")

第二处是使用addTrajectory()创建轨迹,参数name=LymphoidU

1
2
3
4
5
6
7
8
projHeme5 <- addTrajectory(
ArchRProj = projHeme5,
name = "LymphoidU",
groupBy = "Clusters2",
trajectory = trajectory,
embedding = "UMAP",
force = TRUE
)

第三处, 我们需要注意plotTrajectory里的参数trajectoryname需要改成”LymphoidU”

1
p <- plotTrajectory(projHeme5, trajectory = "LymphoidU", colorBy = "cellColData", name = "LymphoidU")

后续的代码基本上可以照搬上一节。

使用ArchR分析单细胞ATAC-seq数据(第十五章)

第15章 使用ArchR进行整合分析

ArchR的一个优势能够整合多种水平的信息从而提供新的洞见。我们可以只用ATAC-seq数据进行分析,如识别peak之间的共开放性来预测调控相互作用,或整合scRNA-seq数据,如通过peak-基因的连锁分析预测增性子活性。无论是哪种情况,ArchR都可以很容易地从scATAC seq数据中获得更深入的见解。

15.1 创建细胞低重叠聚集

ArchR能方便许多特征间相关性的分析。在这些相关分析中,使用稀疏的单细胞数据进行这些计算会导致大量的噪声。为规避这一挑战,我们采用了一种由Cicero引入的方法,在这些分析之前创建单细胞的低重叠聚集。我们过滤与任何其他聚集重叠超过80%的聚集以减少偏差。同时为提升该方法的速度,我们开发了一个优化的迭代重叠检查流程,借由”Rcpp”包通过C++实现了快速特征相关性运算。在ArchR中,这些优化方法被用于计算peak共开放性、peak-基因连锁和其他连锁分析。这些低重叠聚集运算都是在内部完成,为清楚起见,我们先在这里对其介绍。

15.2 ArchR共开放分析

共开放是多个单细胞种的两个peak之间开放性的相关性。换句话说,当peak A在某个单细胞中是开放状态时,peak B通常也是开放状态。下图可以直观地说明了这一概念,说明增强子E3通常与启动子P是共开放的。

ArchR_Coaccessibility

有一点需要注意,共开放分析找到的peak通常都是细胞类型特异的peak。这是因为这些peak在一种细胞类型中都是开放的,而另一种细胞类型通常都是关闭的。虽然这些peak之间有很强的相关性,但是不意味着这些peak之间存在调控关系。

在ArchR中,我们使用addCoAccessibility()函数计算共开放性,计算结束得到的开放性信息保存在ArchRProject

1
2
3
4
projHeme5 <- addCoAccessibility(
ArchRProj = projHeme5,
reducedDims = "IterativeLSI"
)

使用getCoAccessibility()函数可以从ArchRProject对象中提取共开放性信息,当设置returnLoops=FALSE时会返回一个DataFrame对象。

1
2
3
4
5
6
cA <- getCoAccessibility(
ArchRProj = projHeme5,
corCutOff = 0.5,
resolution = 1,
returnLoops = FALSE
)

DataFrame对象包含几个重要的信息。queryHitssubjectHits列记录的是两个存在相关性的peak的索引。correlation则是两个peak之间的开放状态相关的数值。

1
2
3
4
5
6
7
cA
# DataFrame with 64824 rows and 4 columns
# queryHits subjectHits seqnames correlation
#
# 1 5 10 chr1 0.63855416236086
# … … … … …
# 64823 143977 143978 chrX 0.550319862774772

这个共开放DataFrame还有一个元数据成员,包含一个相关peak的GRanges对象。上面提到的queryHitssubjectHits的索引适用于这个GRanges对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
metadata(cA)[[1]]
# GRanges object with 144009 ranges and 0 metadata columns:
# seqnames ranges strand
#
# Mono chr1 752499-752999 *
# NK chr1 762651-763151 *
# B chr1 801006-801506 *
# B chr1 805039-805539 *
# CLP chr1 845325-845825 *
# … … … …
# Erythroid chrX 154664540-154665040 *
# NK chrX 154807324-154807824 *
# PreB chrX 154840785-154841285 *
# PreB chrX 154842404-154842904 *
# NK chrX 154862017-154862517 *
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

如果我们设置retureLoops=TRUE, 那么getCoAccessibility()会以loop track的形式返回共开放数据。在这个GRanges对象中,IRanges的起始和结束对应的是每个存在互作关系中两个共开放peak的位置。resolution参数设置这些loop的碱基对分辨率。当resolution=1时,它会输出连接每个peak中心的loop.

1
2
3
4
5
6
cA <- getCoAccessibility(
ArchRProj = projHeme5,
corCutOff = 0.5,
resolution = 1,
returnLoops = TRUE
)

我们比较下GRangesDataFrame这两个对象

1
2
3
4
5
6
7
8
cA[[1]]
# GRanges object with 32412 ranges and 1 metadata column:
# seqnames ranges strand | value
# [1] chr1 845575-856640 * | 0.63855416236086
# … … … … . …
# [32412] chrX 153980218-153990364 * | 0.550319862774772
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

如果我们将loops的分辨率调整为resolution = 1000, 这能够避免绘制过多的共开放互作事件。从下面的输出的GRanges对象中,我们可以看到条目少了很多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cA <- getCoAccessibility(
ArchRProj = projHeme5,
corCutOff = 0.5,
resolution = 1000,
returnLoops = TRUE
)

cA[[1]]
# GRanges object with 30997 ranges and 1 metadata column:
# seqnames ranges strand | value
# |
# [1] chr1 845500-856500 * | 0.63855416236086
# … … … … . …
# [30997] chrX 153980500-153990500 * | 0.550319862774772
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

同样的,如果我们进一步降低分辨率resolution = 10000,我们会得到更少共开放交互事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cA <- getCoAccessibility(
ArchRProj = projHeme5,
corCutOff = 0.5,
resolution = 10000,
returnLoops = TRUE
)

cA[[1]]
# GRanges object with 21142 ranges and 1 metadata column:
# seqnames ranges strand | value
# |
# [1] chr1 845000-855000 * | 0.63855416236086
# … … … … . …
# [21142] chrX 153985000-153995000 * | 0.550319862774772
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

15.2.1 在browser track中绘制共开放

当我们在ArchRProject里增加共开放信息后,我们可以用这个信息在基因组浏览器里绘制loop track。具体做法就是在plotBrowserTrack()函数中设置loops参数。我们这里以getCoAccessibility()默认参数输出结果为例,即corCutOff = 0.5, resolution = 1000, returnLoops = TRUE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
markerGenes  <- c(
"CD34", #Early Progenitor
"GATA1", #Erythroid
"PAX5", "MS4A1", #B-Cell Trajectory
"CD14", #Monocytes
"CD3D", "CD8A", "TBX21", "IL7R" #TCells
)

p <- plotBrowserTrack(
ArchRProj = projHeme5,
groupBy = "Clusters2",
geneSymbol = markerGenes,
upstream = 50000,
downstream = 50000,
loops = getCoAccessibility(projHeme5)
)

最后用grid.draw函数绘制结果,通过$选择特定的标记基因。

1
2
grid::grid.newpage()
grid::grid.draw(p$CD14)

Plot-Tracks-Marker-Genes-with-CoAccessibility

使用plotPDF()保存可编辑的矢量图

1
2
3
4
plotPDF(plotList = p, 
name = "Plot-Tracks-Marker-Genes-with-CoAccessibility.pdf",
ArchRProj = projHeme5,
addDOC = FALSE, width = 5, height = 5)

15.3 ArchR Peak2GeneLinkages分析

和共开放分析类似,ArchR也能分析所谓的”peak-to-gene”关联, 也就是分析peak和基因的相关性。共开放分析和peak-to-gene关联分析的主要不同在于,共开放分析只需要用到ATAC-seq数据,寻找的是peak之间的共开放关系,而peak-to-gene关联分析则会整合scRNA-seq数据,寻找peak开放状态和基因表达量的关系。这其实是相似问题的两种方法。只不过因为peak-to-gene关联分析使用的是scATAC-seq和scRNA-seq数据,我们会认为这个关联更能反应基因调控关系。

在ArchR中,我们使用addPeak2GeneLinks()函数鉴定peak-to-gene的关联。

1
2
3
4
projHeme5 <- addPeak2GeneLinks(
ArchRProj = projHeme5,
reducedDims = "IterativeLSI"
)

我们以上一节类似方式提取这些peak-to-gene的关联信息,只不过这里用的是getPeak2GeneLinks()函数。和之前一样,用户可以设置相关性阈值和关联之间的分辨率。

1
2
3
4
5
6
p2g <- getPeak2GeneLinks(
ArchRProj = projHeme5,
corCutOff = 0.45,
resolution = 1,
returnLoops = FALSE
)

returnLoops=FALSE, 该函数返回一个DataFrame对象,和之前getCoAccessibility()返回的DataFrame相似。主要的不同在于scATAC-seq的索引 peak存放在idxATAC列,而scRNA-seq基因的索引是存放在idxRNA列中

1
2
3
4
5
6
7
8
9
10
11
p2g
# DataFrame with 43754 rows and 6 columns
# idxATAC idxRNA Correlation FDR
#
# 1 47 5 0.549552663393716 1.34094093110629e-38
# 2 3 6 0.487418258348982 2.1460798658766e-29
...
# VarQATAC VarQRNA
#
# 1 0.948753202924817 0.793290683296597
# 2 0.253206396822421 0.445890005913661

peak-to-gene关联DataFrame对象同样也有一个GRanges对象记录对应peak的元信息。上面提到的idxATAC索引能用于GRanges对象中。

1
2
3
4
5
6
7
8
metadata(p2g)[[1]]
# GRanges object with 144009 ranges and 0 metadata columns: ## seqnames ranges strand
#
# [1] chr1 752499-752999 *
# … … … …
# [144009] chrX 154862017-154862517 *
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

如果们设置returnLoop=TRUE,那么getPeak2GeneLinks()会返回一个记录loop track的GRanges对象,链接peak和基因。和之前共开放分析一样,IRanges对象里记录着关联着的peak和基因的位置。当resolution=1, 这连接的是peak的中心和基因的单碱基TSS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
p2g <- getPeak2GeneLinks(
ArchRProj = projHeme5,
corCutOff = 0.45,
resolution = 1,
returnLoops = TRUE
)

p2g[[1]]
# GRanges object with 43695 ranges and 2 metadata columns: ## seqnames ranges strand | value
# |
# [1] chr1 762901-948847 * | 0.533350285896763
# … … … … . …
# [43695] chrX 154444701-154664790 * | 0.493389088498317
# FDR
#
# [1] 5.20045729958651e-36
# … …
# [43695] 3.37643947034054e-30
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

我们可以将loops的分辨率调整为resolution = 1000, 输出结果主要用于在基因组浏览器中绘制这些连接。因为相同的基因对应的peak过多时,可视化效果会很差。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
p2g <- getPeak2GeneLinks(
ArchRProj = projHeme5,
corCutOff = 0.45,
resolution = 1000,
returnLoops = TRUE
)

p2g[[1]]
# GRanges object with 42126 ranges and 2 metadata columns:
# seqnames ranges strand | value
# |
# [1] chr1 762500-948500 * | 0.533350285896763
# … … … … . …
# [42126] chrX 154444500-154664500 * | 0.493389088498317
# FDR
#
# [1] 5.20045729958651e-36
# … …
# [42126] 3.37643947034054e-30
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

进一步降低分辨率,也会降低peak-to-gene连接的总数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
p2g <- getPeak2GeneLinks(
ArchRProj = projHeme5,
corCutOff = 0.45,
resolution = 10000,
returnLoops = TRUE
)

p2g[[1]]
# GRanges object with 33645 ranges and 2 metadata columns:
# seqnames ranges strand | value
# |
# [1] chr1 765000-945000 * | 0.533350285896763
# … … … … . …
# [33645] chrX 154445000-154665000 * | 0.493389088498317
# FDR
#
# [1] 5.20045729958651e-36
# … …
# [33645] 3.37643947034054e-30
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths

15.3.1 在browser track中绘制peak-to-gene连接

我们可以采用之前共开放分析流程中的相同方法,使用plotBrowserTrack()函数在基因组浏览器上绘制peak-to-gene 连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
markerGenes  <- c(
"CD34", #Early Progenitor
"GATA1", #Erythroid
"PAX5", "MS4A1", #B-Cell Trajectory
"CD14", #Monocytes
"CD3D", "CD8A", "TBX21", "IL7R" #TCells
)

p <- plotBrowserTrack(
ArchRProj = projHeme5,
groupBy = "Clusters2",
geneSymbol = markerGenes,
upstream = 50000,
downstream = 50000,
loops = getPeak2GeneLinks(projHeme5)
)

grid.draw函数绘制结果,通过$选择特定的标记基因。

1
2
grid::grid.newpage()
grid::grid.draw(p$CD14)

Plot-Tracks-Marker-Genes-with-Peak2GeneLinks

使用plotPDF()保存可编辑的矢量图

1
2
3
4
plotPDF(plotList = p, 
name = "Plot-Tracks-Marker-Genes-with-Peak2GeneLinks.pdf",
ArchRProj = projHeme5,
addDOC = FALSE, width = 5, height = 5)

15.3.2 绘制Peak-to-gene连接热图

我们还可以通过绘制peak-to-gene热图的方式展示我们的peak-to-gene连接。热图分为两个部分,一个是scATAC-seq数据,一个是scRNA-seq数据。绘图使用plotPeak2GeneHeatmap()函数

1
p <- plotPeak2GeneHeatmap(ArchRProj = projHeme5, groupBy = "Clusters2")

热图的行是k-means聚类结果,其中k由我们进行设置,默认是25.

1
p

Peak2GeneHeatmap

15.4 正向TF-调控因子鉴定

ATAC-seq还可以无偏好的鉴定TF,这些TF所对应的染色质区域(存在该TF结合的motif DNA序列 )表现出很大改变。此外,从聚集的位置权重矩阵(Position Weight Matrices, PWM)中也能看到这些TF家族在其集合位点上有相似的特征(例如 GATA因子)。

GATA_Motif_PWMs

这种motif的相似性使得识别特定的TF充满了挑战性,这些TF可能在其预测的结合位点驱动染色质开放状态发生改变。为了规避这一挑战,我们之前用ATAC-seq和RNA-seq来鉴定TF,这些TF的基因表达和对应motif的开放状态呈正相关。我们将这些TF命名为”正向调节因子”。然而,这种分析依赖于匹配的基因表达数据,而这些数据并不是所有实验中都有。ArchR可以识别其推断基因得分与其chromVAR TF偏差z-score相关的TF来克服这种依赖性。实现方式为,ArchR利用低重叠细胞聚集将TF motif的chromVAR deviation z-scroe和TF基因的基因活跃得分相关联。当ArchR整合scRNA-seq时,TF的基因表达可以代替推测的基因活性评分。

15.4.1 第一步: 鉴定偏离TF motif

鉴定正向TF调控因子的第一步就是鉴定存在偏离的TF motif。我们在之前的章节进行过该分析,为所有的motif创建了一个MotifMatrix,记录着chromVAR deviations 和deviation z-scores。使用getGroupSE()函数可以获取基于聚类平均后的数据,返回的是一个SummarizedExperiment.

1
seGroupMotif <- getGroupSE(ArchRProj = projHeme5, useMatrix = "MotifMatrix", groupBy = "Clusters2")

因为SummarizedExperiment对象来自于MotifMatrix, 所以它有两个seqnames, “deviation”和”z”,对应chromVAR里原始的偏离值和偏离值的z-scores.

1
2
3
4
5
6
7
8
9
seGroupMotif
# class: SummarizedExperiment
# dim: 1740 11
# metadata(0):
# assays(1): MotifMatrix
# rownames(1740): f1 f2 … f1739 f1740
# rowData names(3): seqnames idx name
# colnames(11): B CD4.M … PreB Progenitor
# colData names(16): TSSEnrichment ReadsInTSS … FRIP nCells

我们可以从SummarizedExperiment中只提取deviation z-scores.

1
seZ <- seGroupMotif[rowData(seGroupMotif)$seqnames=="z",]

然后,我们计算该z-score在所有聚类中最大变化值。根据motif在不同聚类中观察到的差异程度,我们可以对其分层。

1
2
3
rowData(seZ)$maxDelta <- lapply(seq_len(ncol(seZ)), function(x){
rowMaxs(assay(seZ) - assay(seZ)[,x])
}) %>% Reduce("cbind", .) %>% rowMaxs

15.4.2 第二步: 鉴定相关的TF motif和TF基因得分/表达值

接着我们使用correlateMatrices()函数来获取motif开放状态矩阵和基因活跃矩阵(基因得分或基因表达量),在这里就是GeneScoreMatrixMotifMatrix. 它们将用于鉴定一类motif开放状态和其自身基因活跃相关的TF。正如之前所提到,我们使用许多低重叠细胞聚集在低维空间里(对应reducedDims参数)来计算相关性。

1
2
3
4
5
6
corGSM_MM <- correlateMatrices(
ArchRProj = projHeme5,
useMatrix1 = "GeneScoreMatrix",
useMatrix2 = "MotifMatrix",
reducedDims = "IterativeLSI"
)

该函数返回一个DataFrame对象,记录着GeneScoreMatrixMotifMatrix,以及它们在低重叠细胞聚类中的相关性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
corGSM_MM
# DataFrame with 825 rows and 14 columns
# GeneScoreMatrix_name MotifMatrix_name cor
#
# 1 HES4 HES4_95 0.154455056755803
# … … … …
# 825 MECP2 MECP2_645 0.0629645419544807
# padj pval GeneScoreMatrix_seqnames
#
# 1 0.48577773775473 0.000593860315103582 chr1
# … … … …
# 825 1 0.163611488297825 chrX
# GeneScoreMatrix_start GeneScoreMatrix_end GeneScoreMatrix_strand
#
# 1 935552 934342 2
# … … … …
# 825 153363188 153287264 2
# GeneScoreMatrix_idx GeneScoreMatrix_matchName MotifMatrix_seqnames
#
# 1 15 HES4 z
# … … … …
# 825 874 MECP2 z
# MotifMatrix_idx MotifMatrix_matchName
#
# 1 95 HES4
# … … …
# 825 645 MECP2

同样的分析还可以使用GeneIntegrationMatrix, 用于替代GeneScoreMatrix

1
2
3
4
5
6
corGIM_MM <- correlateMatrices(
ArchRProj = projHeme5,
useMatrix1 = "GeneIntegrationMatrix",
useMatrix2 = "MotifMatrix",
reducedDims = "IterativeLSI"
)

15.4.3 第三步: 在相关性DataFrame中添加极大偏差值

对于每个相关性分析,我们使用第一步计算的极大偏差值(maximum delta )来注释每个motif

1
2
corGSM_MM$maxDelta <- rowData(seZ)[match(corGSM_MM$MotifMatrix_name, rowData(seZ)$name), "maxDelta"]
corGIM_MM$maxDelta <- rowData(seZ)[match(corGIM_MM$MotifMatrix_name, rowData(seZ)$name), "maxDelta"]

15.4.4 第四步: 鉴定正向TF调控因子

我们可以利用所有这些信息来识别正向TF调控因子。在下面的例子中,正向调控因子的标准为

  • motif和基因得分(或基因表达)之间的相关性大于0.5
  • 调整后的p值小于0.01
  • deviation z-score的最大组间差异位于前四分位。

我们应用这些过滤标准,并且做一些文本调整来分离TF名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
corGSM_MM <- corGSM_MM[order(abs(corGSM_MM$cor), decreasing = TRUE), ]
corGSM_MM <- corGSM_MM[which(!duplicated(gsub("\\-.*","",corGSM_MM[,"MotifMatrix_name"]))), ]
corGSM_MM$TFRegulator <- "NO"
corGSM_MM$TFRegulator[which(corGSM_MM$cor > 0.5 & corGSM_MM$padj < 0.01 & corGSM_MM$maxDelta > quantile(corGSM_MM$maxDelta, 0.75))] <- "YES"
sort(corGSM_MM[corGSM_MM$TFRegulator=="YES",1])
# [1] “ATOH1” “BCL11A” “CEBPA-DT” “CEBPB” “CEBPD” “CREB1”
# [7] “CREB3L4” “EBF1” “EGR2” “EOMES” “ERF” “ESR1”
# [13] “ETS1” “ETV3” “FUBP1” “GATA1” “GATA2” “GATA5”
# [19] “GATA6” “IRF1” “JDP2” “KLF11” “KLF2” “LYL1”
# [25] “MECOM” “MITF” “NFE2” “NFIA” “NFIB” “NFIC”
# [31] “NFIX” “NHLH1” “POU2F1” “RUNX2” “SIX5” “SMAD1”
# [37] “SMAD9” “SP4” “SPI1” “SPIB” “TAL1” “TCF15”
# [43] “TCF23” “TCF4” “TFAP2C” “TWIST1” “TWIST2” “YY1”
# [49] “ZEB1-AS1”

在从基因得分和motif deviation z-scores鉴定到正向TF调控因子后,我们可以在点图中突出展示

1
2
3
4
5
6
7
8
9
10
11
12
13
p <- ggplot(data.frame(corGSM_MM), aes(cor, maxDelta, color = TFRegulator)) +
geom_point() +
theme_ArchR() +
geom_vline(xintercept = 0, lty = "dashed") +
scale_color_manual(values = c("NO"="darkgrey", "YES"="firebrick3")) +
xlab("Correlation To Gene Score") +
ylab("Max TF Motif Delta") +
scale_y_continuous(
expand = c(0,0),
limits = c(0, max(corGSM_MM$maxDelta)*1.05)
)

p

TF-Regulators-GeneScores

使用相同的分析策略处理GeneIntegrationMatrix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
corGIM_MM <- corGIM_MM[order(abs(corGIM_MM$cor), decreasing = TRUE), ]
corGIM_MM <- corGIM_MM[which(!duplicated(gsub("\\-.*","",corGIM_MM[,"MotifMatrix_name"]))), ]
corGIM_MM$TFRegulator <- "NO"
corGIM_MM$TFRegulator[which(corGIM_MM$cor > 0.5 & corGIM_MM$padj < 0.01 & corGIM_MM$maxDelta > quantile(corGIM_MM$maxDelta, 0.75))] <- "YES"
sort(corGIM_MM[corGIM_MM$TFRegulator=="YES",1])

p <- ggplot(data.frame(corGIM_MM), aes(cor, maxDelta, color = TFRegulator)) +
geom_point() +
theme_ArchR() +
geom_vline(xintercept = 0, lty = "dashed") +
scale_color_manual(values = c("NO"="darkgrey", "YES"="firebrick3")) +
xlab("Correlation To Gene Expression") +
ylab("Max TF Motif Delta") +
scale_y_continuous(
expand = c(0,0),
limits = c(0, max(corGIM_MM$maxDelta)*1.05)
)

p

TF-Regulators-GeneExpression

使用ArchR分析单细胞ATAC-seq数据(第十四章)

第十四章 ArchR的足迹分析

转录因子(Transcripts factor, TF)足迹分析使得我们能够预测特定位点中TF的精确结合位置。这是因为该位置被TF结合避免了转座酶的切割,而TF结合位点的邻近位置处于开放状态。

image.png

理想情况下,TF足迹分析需要在单个位置上分析从而确定TF的准确结合位置。但实际上,这需要非常高的测序深度,甚至超过混池ATAC-seq或者scATAC-seq的所有数据。为了解决这个问题,我们可以把和待预测的TF结合相关的Tn5插入位置进行合并。例如,我们可以提取所有包含CTCF motif的peak,制作一个全基因组的CTCF的聚合TF足迹。

为了保证足迹的可靠性,我们需要确保能够可靠的预测出目标TF所对应的结合位点。ArchR使用自带的addMotifAnnotations()函数对peak区域进行搜索,寻找能够匹配的DNA序列。考虑到motif的简并性,无法保证每个motif都有足够的peak。添加到ArchRProject的motif注释以二值矩阵表示(0=无motif, 1=有motif)。一旦你有了这些motif注释,ArchR使用getFootPrints()函数分析足迹,它以一个ArchRProject对象和一个GenomicRanges对象(记录motif的位置)作为输入。可以使用getPositions()函数从ArchRProject中提取这些位置。之后足迹可以使用plotFootprints()函数可视化。

或许更重要的是,ArchR的足迹分析能够抵消已知的Tn5插入序列偏好性。ArchR使用一个hexmer位置频率矩阵和一个目标Tn5插入位置上的k-mer频率矩阵来实现该功能。

foot printing Methods

最终,该流程输出考虑到Tn5插入偏好性的足迹图。

ArchR支持motif足迹分析和用户提供特征的足迹分析,在后续都会讨论。

14.1 motif足迹分析

由于教程用到的数据集比较小,因此利用该数据集得到足迹并不是那么的清晰。使用更大的数据会得到较小变异的足迹。

在分析足迹时,我们要先获取和motif相关的所有位置。这可以通过getPositions函数完成。该函数有一个可选参数, name,用于传入peakAnnotation对象中我们想要获取位置的变量名。如果name=NULL, 那么ArchR会使用peakAnnotation槽(slot)的第一个条目(entry)。在下面的例子中,我们没有指定name, ArchR使用的第一个条目为CIS-BP motifs.

1
motifPositions <- getPositions(projHeme5)

这会创建一个GRangesList对象,每个TF motif以不同的GRanges对象进行区分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
motifPositions
# GRangesList object of length 870:
# $TFAP2B_1
# GRanges object with 16773 ranges and 1 metadata column:
# seqnames ranges strand | score
# |
# [1] chr1 852468-852479 + | 8.17731199746359
# [2] chr1 873916-873927 + | 8.32673820065588
# [3] chr1 873916-873927 - | 8.32673820065588
# [4] chr1 896671-896682 + | 9.96223327271814
# [5] chr1 896671-896682 - | 8.92408377606486
# … … … … . …
# [16769] chrX 153991101-153991112 + | 8.39549159740639
# [16770] chrX 154299568-154299579 + | 8.90119825654299
# [16771] chrX 154664929-154664940 - | 8.16690864294221
# [16772] chrX 154807684-154807695 + | 9.57636587154549
# [16773] chrX 154807684-154807695 - | 10.6117355833828
# ——-
# seqinfo: 23 sequences from an unspecified genome; no seqlengths
#
# …
# <869 more elements>

我们提取部分感兴趣的TF motifs用于展示。在我们提取”EBF1”会附带”SREBF1”, 因此我们需要用%ni%显式将其过滤。%ni%函数是R自带函数%in%的相反函数。

1
2
3
4
5
motifs <- c("GATA1", "CEBPA", "EBF1", "IRF4", "TBX21", "PAX5")
markerMotifs <- unlist(lapply(motifs, function(x) grep(x, names(motifPositions), value = TRUE)))
markerMotifs <- markerMotifs[markerMotifs %ni% "SREBF1_22"]
markerMotifs
# [1] “GATA1_383” “CEBPA_155” “EBF1_67” “IRF4_632” “TBX21_780” “PAX5_709”

为了准确找到TF足迹,我们需要大量的reads。因此,细胞需要进行分组生成拟混池ATAC-seq谱才能用于TF足迹分析。这些拟混池谱之前在peak鉴定时就已经保存为分组覆盖文件。 如果没有在ArchRProject添加分组覆盖信息,则运行如下命令

1
projHeme5 <- addGroupCoverages(ArchRProj = projHeme5, groupBy = "Clusters2")

在计算分组覆盖度后,我们可以为之前getFootprints()挑选的一组标记motif计算足迹。即便ArchR已经优化了足迹分析流程,我们也建议先对一部分motif分析足迹,而不是直接分析所有motif。 我们通过positions参数来选择motif。

1
2
3
4
5
seFoot <- getFootprints(
ArchRProj = projHeme5,
positions = motifPositions[markerMotifs],
groupBy = "Clusters2"
)

当我们获取了这些足迹,我们可以使用plotFootprints()函数进行展示。该函数能够同时以多种方式对足迹进行标准化。下一节,我们会讨论标准化和实际的足迹图。

14.2 Tn5偏好的足迹标准化

使用ATAC-seq数据分析TF足迹的一大挑战就是Tn5转座酶的插入序列偏好性,这会导致TF足迹的错误分类。为了降低Tn5插入偏好性的影响,ArchR识别每个Tn5插入位置附近的k-mer序列(k由用户提供,默认是6).

对于该项分析,ArchR为每个拟混池识别单碱基分辨率的Tn5插入位点,将这些1-bp位点调整为k-bp窗口(-k/2和+(k/2-1)bp),然后使用Biostrings包中的oligonucleotidefrequency(w=k, simplify.as="collapse")函数创建k-mer频率表。然后,ArchR使用与BSgenome相关的基因组文件,以相同的函数计算出全基因组范围预期的k-mers。

为了计算拟混池足迹的插入偏差,ArchR创建了一个k-mer频率矩阵,该矩阵表示为从motif中心到窗口+/-N bp(用户定义,默认为250 bp)的所有可能k-mer。然后,遍历每个motif位点,ArchR将定位的k-mer填充到k-mer频率矩阵中。然后在全基因组范围内计算每个motif位置。利用样本的k-mer频率表,ArchR可以通过将k-mer位置频率表乘以观察/期望 Tn5 k-mer频率来计算预期的Tn5插入。

以上所有这些发生在plotFootprints()函数中。

14.2.1 减去Tn5偏好

一个标准化方式就是从足迹信号中减去Tn5偏好。该标准化方法通过设置plotFootprints()normMethod = "Subtract"实现

1
2
3
4
5
6
7
8
plotFootprints(
seFoot = seFoot,
ArchRProj = projHeme5,
normMethod = "Subtract",
plotName = "Footprints-Subtract-Bias",
addDOC = FALSE,
smoothWindow = 5
)

默认,这些图保存在ArchRProject的outputDirectory。如果你需要绘制所有motif, 可以将其返回为ggplot2对象,需要注意这个ggplot对象会非常大。下面是一个从motif足迹中减去Tn5偏好信号的结果

Footprints-Subtract-Bias

14.2.2 除以Tn5偏好

第二种标准化方法就是将足迹除以Tn5偏好信号。该标准化方法通过设置plotFootprints()normMethod = "Divide"实现

1
2
3
4
5
6
7
8
plotFootprints(
seFoot = seFoot,
ArchRProj = projHeme5,
normMethod = "Divide",
plotName = "Footprints-Divide-Bias",
addDOC = FALSE,
smoothWindow = 5
)

下面是一个从motif足迹中除以Tn5偏好信号的结果

Footprints-Divide-Bias

14.2.3 无Tn5偏好标准化的足迹

尽管我们高度推荐将足迹根据Tn5序列插入偏好性进行标准化,当然你可以通过设置plotFootprints()normMethod = "None"来省去标准化。

1
2
3
4
5
6
7
8
plotFootprints(
seFoot = seFoot,
ArchRProj = projHeme5,
normMethod = "None",
plotName = "Footprints-No-Normalization",
addDOC = FALSE,
smoothWindow = 5
)

Footprints-No-Normalization

14.3 特征足迹

除了motif足迹分析,ArchR还允许用户分析任意定义的特征数据集。为了对功能进行说明,我们将会使用plotFootprints()函数创建TSS插入谱(在之前数据质量控制一节中引入)。一个TSS插入谱本质上就是特殊的足迹。

我们在之前小节讨论过,足迹会用到来源于拟混池重复的分组覆盖文件。我们在之前peak鉴定时创建过这些文件。如果你没有在ArchRProject加入分组覆盖信息, 那么需要运行如下代码

1
projHeme5 <- addGroupCoverages(ArchRProj = projHeme5, groupBy = "Clusters2")

我们接着创建一个没有经过Tn5偏好性校正的TSS插入谱。和之前分析一个主要不同是,我们设置了flank=2000, 将TSS向前向后分别延伸2000 bp.

1
2
3
4
5
6
seTSS <- getFootprints(
ArchRProj = projHeme5,
positions = GRangesList(TSS = getTSS(projHeme5)),
groupBy = "Clusters2",
flank = 2000
)

我们接着用plotFootprints()对每个细胞分组绘制TSS插入谱。

1
2
3
4
5
6
7
8
9
plotFootprints(
seFoot = seTSS,
ArchRProj = projHeme5,
normMethod = "None",
plotName = "TSS-No-Normalization",
addDOC = FALSE,
flank = 2000,
flankNorm = 100
)

TSS-No-Normalization

基于igv.js的一个小工具

当我想查看软件运行结束后得到的BAM, BigWig, BED和GTF文件时,我都需要先把他们下载到本地,然后用IGV打开。每每这个时候,我就会非常痛苦,因为我懒得下载。

为了解决这个问题,我基于igv.js 写了一个Python脚本,可以根据提供的参考基因组,bam文件输出一个网页,然后通过利用 node.js 或者 Python的网页服务器打开一个端口,直接在网页上进行查看。

代码地址: https://github.com/xuzhougeng/myscripts/blob/master/igv_web.py

可以下面这行代码进行下载脚本, 例如我放在了家目录

1
wget https://raw.githubusercontent.com/xuzhougeng/myscripts/master/igv_web.py
1
python3 ~/igv_web.py  -r ref/genome.fa -m 01-read-align/*.bam -b feature.bed

接着用python的 SimpleHTTPServer 模块启动一个网页服务器

1
/usr/bin/python -m SimpleHTTPServer 9999

当然更加推荐使用npm的http-server,通过网页进行访问

1
npx http-server ./ -p 9999 -a 0.0.0.0

效果如下

image.png

如何安装JCVI

使用conda安装

1
conda create -y -c bioconda -n jcvi jcvi 

使用时需要启动环境

1
conda activate jcvi

在此基础上可以更新到最新版的JCVI (Github版本会不断的增加新功能并修订bug)

1
pip install git+git://github.com/tanghaibao/jcvi.git

安装额外的依赖环境

  • Kent tools

  • BEDTOOLS

  • EMBOSS

  • LAST

  • LaTex

依赖环境中,BEDTOOLS, EMBOSS和LAST可以用conda安装

1
2
3
# BEDTOOLS 和 EMBOSS
conda install -y -n jcvi -c bioconda bedtools emboss last

Kent tools需要编译, 并且依赖MySQL,暂时不需要安装。

1
2
3
4
5
# Kent tools, 134M
wget http://hgdownload.cse.ucsc.edu/admin/jksrc.zip
unzip jksrc.zip
cd kent/src/lib
make

对于Latex,conda的安装版本 ( texlive-core )在我后续的测试中各种出问题, 我最后根据根据官方的quickinstall.html 进行了安装,具体的安装过程见 LaTex

建议通过root进行安装(或者手工安装)。

1
2
3
4
# ubuntu
sudo apt-get install -y texlive texlive-latex-extra texlive-latex-recommended
# centos
sudo yum install -y texlive texlive-latex texlive-xetex texlive-collection-latexrecommended

最终通过Python版的MCscan对安装结果进行测试 (需要用conda安装seqkit)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mkdir -p test && cd test
#Athaliana
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/arabidopsis_thaliana/cdna/Arabidopsis_thaliana.TAIR10.cdna.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/arabidopsis_thaliana/pep/Arabidopsis_thaliana.TAIR10.pep.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/gff3/arabidopsis_thaliana/Arabidopsis_thaliana.TAIR10.44.gff3.gz
#Osativa
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/oryza_sativa/cdna/Oryza_sativa.IRGSP-1.0.cdna.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/fasta/oryza_sativa/pep/Oryza_sativa.IRGSP-1.0.pep.all.fa.gz
wget ftp://ftp.ensemblgenomes.org/pub/plants/release-44/gff3/oryza_sativa/Oryza_sativa.IRGSP-1.0.44.gff3.gz
# convert gff to bed
python -m jcvi.formats.gff bed --type=mRNA --key=transcript_id Arabidopsis_thaliana.TAIR10.44.gff3.gz > ath.bed
python -m jcvi.formats.gff bed --type=mRNA --key=transcript_id Oryza_sativa.IRGSP-1.0.44.gff3.gz > osa.bed
# deduplication
python -m jcvi.formats.bed uniq ath.bed
python -m jcvi.formats.bed uniq osa.bed
# Athaliana
seqkit grep -f <(cut -f 4 ath.uniq.bed ) Arabidopsis_thaliana.TAIR10.cdna.all.fa.gz | seqkit seq -i > ath.cds
seqkit grep -f <(cut -f 4 ath.uniq.bed ) Arabidopsis_thaliana.TAIR10.pep.all.fa.gz | seqkit seq -i > ath.pep
# Osativa
seqkit grep -f <(cut -f 4 osa.uniq.bed ) Oryza_sativa.IRGSP-1.0.cdna.all.fa.gz | seqkit seq -i > osa.cds
seqkit grep -f <(cut -f 4 osa.uniq.bed ) Oryza_sativa.IRGSP-1.0.pep.all.fa.gz | seqkit seq -i > osa.pep
# create a new directory
mkdir -p cds && cd cds
ln -s ../ath.cds ath.cds
ln -s ../ath.uniq.bed ath.bed
ln -s ../osa.cds osa.cds
ln -s ../osa.uniq.bed osa.bed
# compara
python -m jcvi.compara.catalog ortholog --no_strip_names ath osa

如果顺利,当前目录下会有一个 ath.osa.pdf 文件

我测试的时候遇到了两个不顺利,都是和LaTex有关的报错。

第一个是latex没有安装导致的报错

1
2
3
FileNotFoundError: [Errno 2] No such file or directory: 'latex': 'latex'
RuntimeError: Failed to process string with tex because latex could not be found

第二个是用conda安装texlive-core后,出现的第二个问题,还是得手工安装LaTex才解决。

1
2
kpathsea: Running mktexfmt latex.fmt
Can't locate mktexlsr.pl in @INC