#' @title Stitch Ranges within a given distance
#'
#' @description
#' Stitch together ranges within a given distance, using excluded ranges as
#' barriers that cannot be crossed
#'
#' @details
#' Stitches together ranges within a given distance, using any ranges provided
#' for exclusion as barriers between stitched ranges. This may be particularly
#' useful if wanting to stitch enhancers whilst excluding promoters.
#'
#' All inputs and outputs are Genomic Ranges objects
#'
#' @param x Ranges to be stitched together
#' @param exclude Ranges to exclude
#' @param maxgap The maximum distance between ranges to be stitched
#' @param ignore.strand logical
#'
#' @return
#' A GRanges object
#'
#' @examples
#' x <- GRanges(c("chr1:1-10", "chr1:101-110", "chr1:201-210", "chr2:1-10"))
#' y <- GRanges("chr1:200:+")
#' stitchRanges(x, exclude = y, maxgap = 100)
#'
#' @importFrom forcats fct_explicit_na
#' @importFrom S4Vectors splitAsList subjectHits
#' @importFrom IRanges overlapsAny
#' @import GenomicRanges
#' @export
stitchRanges <- function(x, exclude, maxgap = 12500L, ignore.strand = TRUE) {
## Argument checks
stopifnot(is(x, "GRanges"))
if (missing(exclude)) exclude <- GRanges()
stopifnot(is(exclude, "GRanges"))
stopifnot(is.numeric(maxgap))
stopifnot(is.logical(ignore.strand))
if (any(overlapsAny(x, exclude))) {
warning("Ranges provided in 'x' overlap barrier ranges")
x <- GenomicRanges::setdiff(x, exclude, ignore.strand = ignore.strand)
}
## Add point ranges to the end of the `exclude` object to ensure no NA
## values are returned by precede
## Although this should use seqinfo objects, this is more pragmatic and
## allows for a missing seqinfo on either object. Perhaps this should be
## added as a check at some point. Enforcing strict compatibility is a good
## thing
all_gr <- c(x, exclude)
all_gr <- range(all_gr, ignore.strand = ignore.strand)
chr_lim <- resize(
all_gr, width = 1, fix = "end", ignore.strand = ignore.strand
)
chr_lim <- shift(chr_lim, 1)
exclude <- sort(c(exclude, chr_lim), ignore.strand = ignore.strand)
hits <- precede(x, exclude, ignore.strand = ignore.strand)
out <- splitAsList(x, hits)
out <- GenomicRanges::reduce(out, min.gapwidth = maxgap)
out <- unlist(out)
names(out) <- c()
out
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.