【发布时间】:2017-08-11 18:47:09
【问题描述】:
我正在开展一个项目,在该项目中迭代小鼠基因组的 bin 并使用 GenomicRanges/rtracklayer 计算一些重叠。 bin 已经以 150 个基数/位置增量计算。对于那些不熟悉的人来说,这意味着对于恰好是最短的小鼠染色体之一的 Y 染色体,大约有 106,000 个 bin,而较大的染色体则包含大约 1,300,000 个 bin! 这里的目标是遍历这些 bin,在两个方向上将 bin 的范围扩大 100,000 个位置,然后找出哪些基因与这些窗口重叠。我想计算从 bin 中心到扩展 bin 窗口中包含的基因开始的距离。
好的,这就是我写到这里的代码。它运行没有错误,并准确计算出我需要的东西。 这里的问题是它很慢,并且需要很长时间才能遍历 1M+ 个 bin。
progress <- function(w) {
# just a function that prints out the window being processed
cat(sprintf(paste0(as.character(Sys.time()), ": Window ", w, " completed!\n")))
}
extend <- function(x, upstream=0, downstream=0) {
# this will expand a `GenomicRanges` object range
if (any(strand(x) == "*"))
warning("'*' ranges were treated as '+'")
on_plus <- strand(x) == "+" | strand(x) == "*"
new_start <- start(x) - ifelse(on_plus, upstream, downstream)
new_end <- end(x) + ifelse(on_plus, downstream, upstream)
ranges(x) <- IRanges(new_start, new_end)
trim(x)
}
feature.overlap <- function(x, window, genes, extend.upstream=100000, extend.downstream=100000) {
# # test case
# x = chrY; window = 2668 ; genes = gene; extend.upstream = 100000 ; extend.downstream = 100000
# extend window of signal in both directions
x.window = extend(x[window], extend.upstream, extend.downstream)
names(x.window) <- window
# compute signal window overlap with genes
overlaps <- subsetByOverlaps(genes, x.window)
if(length(overlaps) == 0){
values <- data.frame(signal_window=names(x.window),
signal_start=max(0, start(x.window)),
signal_center=max(0, start(x.window)) + floor((width(x.window) - 1)/2),
signal_end=end(x.window),
signal_score=x.window$score,
symbol=NA,
gene_id=NA,
gene_chr=NA,
gene_start=NA,
gene_end=NA,
gene_strand=NA)
} else {
hits <- findOverlaps(x.window, genes)
s.idx <- unique(subjectHits(hits))
q.idx <- unique(queryHits(hits))
values <- data.frame(signal_window=names(x.window)[q.idx],
signal_start=max(0, start(x.window)[q.idx]),
signal_center=max(0, start(x.window)[q.idx]) + floor((width(x.window)[q.idx] - 1)/2),
signal_end=end(x.window)[q.idx],
signal_score=x.window$score[q.idx],
mcols(overlaps)[,c(2,1)],
gene_chr=chrom(genes)[s.idx],
gene_start=ifelse(strand(genes)[s.idx] == '+', start(genes)[s.idx], end(genes)[s.idx]) ,
gene_end=end(genes)[s.idx],
gene_strand=strand(genes)[s.idx])
}
return(values)
}
# Import data
library(rtracklayer)
merged_wig <- import.wig('~/file/linked/below.wig', format='wig', genome='mm9')
merged_wig <- keepSeqlevels(merged_wig, paste0('chr', c(seq(1,19), 'X', 'Y')))
chrY <- merged_wig[seqnames(merged_wig) == 'chrY']
# Generate gene info needed for computing overlap
library(TxDb.Mmusculus.UCSC.mm9.knownGene); library(Mus.musculus)
gene <- genes(TxDb.Mmusculus.UCSC.mm9.knownGene)
values(gene) <- merge(values(gene), as.data.frame(org.Mm.egSYMBOL), by='gene_id', all.x=T)
gene <- keepSeqlevels(gene, paste0('chr', c(seq(1,19), 'X', 'Y')))
# BEGIN LOOP GENOME WINDOWS *** TIME CONSUMING ***
window.overlaps <- list()
ptm <- proc.time()
for(i in 1:100) { # ideally 1:length(chrY) but this takes very long so I've only posted a few windows
result = feature.overlap(chrY, i, gene, extend.upstream=100000, extend.downstream=100000)
window.overlaps[[i]] <- result
progress(i)
}
proc.time() - ptm
all.overlaps = do.call(rbind, window.overlaps)
上面的代码将在带有this 文件(88mb)的盒子中运行。
这是我尝试使用 foreach 和 doParallel 库来加速外观:
library(foreach)
library(doParallel)
cl<-makeCluster(8)
registerDoParallel(cl)
ptm <- proc.time()
ls<-foreach(i = 1:100, chrY=chrY, gene=gene, .packages=c('rtracklayer', 'GenomicRanges')) %dopar% {
result = feature.overlap(chrY, i, gene, extend.upstream=100000, extend.downstream=100000)
progress(i)
result
}
proc.time() - ptm
stopCluster(cl)
但是,此代码不起作用。返回的错误是Error: this S4 class is not subsettable,并且没有从progress() 产生输出。 已修复错误 - 请参阅编辑
同样,这里的目标是以更有效的方式编写此代码。一旦我有了values,我就可以轻松计算出我需要的指标。
任何帮助将不胜感激!谢谢!
编辑:我已经用 dopar 实现了一个有效的 foreach 循环,但它似乎比上面的实现还要慢。
library(foreach)
library(doParallel)
cl<-makeCluster(8)
registerDoParallel(cl)
ptm <- proc.time()
ls <- foreach(i = 1:100, .combine='rbind', .packages=c('rtracklayer', 'GenomicRanges')) %dopar% {
result = feature.overlap(chrY, i, gene, counts, extend.upstream=100000, extend.downstream=100000)
progress(i)
result
}
proc.time() - ptm
stopCluster(cl)
对于 100 个窗口,这大约需要 10 秒,而使用上述 for 循环处理的相同窗口需要 6 秒。
【问题讨论】:
-
解决方案必须使用 foreach 包还是可以使用任何并行包?您是否尝试过使用与 *apply 系列语法相同的 snowfall 包?
-
我还没有尝试过降雪包,但会研究一下。理想情况下,我想尝试使用并行包。
-
什么是
idx?尝试使用与 for 循环相同的索引,因为我认为您可能对i = 1:100进行了一些非法访问。 -
我真的很讨厌 Bioconductor 封装。安装 3 个软件包已经 15 分钟。有些超过60MB。还有
TxDb.Mmusculus.UCSC.mm9.knownGene,这真的是包名吗? -
您为此使用了错误的工具,因为它们没有针对这种规模的集合操作进行优化。使用 BEDOPS:
bedops --everything --range 100000 foo.bed | bedops --element-of 1 genes.bed - > answer.bed
标签: r for-loop foreach parallel-processing