Skip to content

Commit

Permalink
feat: find_overlaps(_directed)
Browse files Browse the repository at this point in the history
  • Loading branch information
js2264 committed Sep 12, 2023
1 parent 785e801 commit addde05
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 1 deletion.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Collate:
'arrange.R'
'count.R'
'filter.R'
'find-overlaps.R'
'flank.R'
'ginteractions-construct.R'
'ginteractions-env.R'
Expand Down
10 changes: 10 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ S3method(as_ginteractions,data.frame)
S3method(as_ginteractions,default)
S3method(count,GInteractions)
S3method(filter,GInteractions)
S3method(find_overlaps,GInteractions)
S3method(find_overlaps,PinnedGInteractions)
S3method(find_overlaps_directed,GInteractions)
S3method(find_overlaps_directed,PinnedGInteractions)
S3method(flank_downstream,PinnedGInteractions)
S3method(flank_downstream,Ranges)
S3method(flank_left,PinnedGInteractions)
Expand Down Expand Up @@ -68,6 +72,8 @@ export(count)
export(end1)
export(end2)
export(filter)
export(find_overlaps)
export(find_overlaps_directed)
export(flank_downstream)
export(flank_left)
export(flank_right)
Expand Down Expand Up @@ -140,10 +146,12 @@ importFrom(BiocGenerics,width)
importFrom(GenomeInfoDb,seqinfo)
importFrom(GenomeInfoDb,seqnames)
importFrom(GenomicRanges,GRanges)
importFrom(GenomicRanges,granges)
importFrom(IRanges,IRanges)
importFrom(IRanges,ranges)
importFrom(InteractionSet,GInteractions)
importFrom(InteractionSet,anchors)
importFrom(InteractionSet,findOverlaps)
importFrom(InteractionSet,regions)
importFrom(S4Vectors,"first<-")
importFrom(S4Vectors,"mcols<-")
Expand Down Expand Up @@ -194,6 +202,8 @@ importFrom(plyranges,anchor_5p)
importFrom(plyranges,anchor_center)
importFrom(plyranges,anchor_end)
importFrom(plyranges,anchor_start)
importFrom(plyranges,find_overlaps)
importFrom(plyranges,find_overlaps_directed)
importFrom(plyranges,flank_downstream)
importFrom(plyranges,flank_left)
importFrom(plyranges,flank_right)
Expand Down
210 changes: 210 additions & 0 deletions R/find-overlaps.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#' Find overlaps between a query GInteractions and a GRanges
#'
#' @details
#'
#' `find_overlaps()` will search for any overlap between `GInteractions`
#' in `x` and `GRanges` in `y`. It will return a `GInteractions` object of length
#' equal to the number of times `x` overlaps `y`. This `GInteractions` will
#' have additional metadata columns corresponding to the metadata from `y`.
#' `find_overlaps_directed()` takes the strandness of each object into account.
#'
#' @param x A (Pinned)GInteractions object
#' @param y A GRanges object
#' @param maxgap,minoverlap See \code{?\link[GenomicRanges]{findOverlaps}}
#' in the \pkg{GenomicRanges} package for a description of these arguments
#' @param suffix Suffix to add to metadata
#' columns (character vector of length 2, default to `c(".x", ".y")`).
#'
#' @importFrom GenomicRanges granges
#' @importFrom plyranges find_overlaps
#' @importFrom plyranges find_overlaps_directed
#' @importFrom InteractionSet findOverlaps
#'
#' @return a GInteractions object with rows corresponding to the GInteractions
#' in `x` that overlap `y`.
#'
#' @name ginteractions-find-overlaps
#'
#' @examples
#' gi <- read.table(text = "
#' chr1 11 20 - chr1 21 30 +
#' chr1 11 20 - chr1 51 55 +
#' chr1 21 30 - chr1 51 55 +
#' chr1 21 30 - chr2 51 60 +",
#' col.names = c("seqnames1", "start1", "end1", "strand1", "seqnames2", "start2", "end2", "strand2")
#' ) |> as_ginteractions() |> mutate(id = 1:4, type = 'gi')
#'
#' gr <- GenomicRanges::GRanges(c("chr1:20-30:+", "chr2:55-65:-")) |> plyranges::mutate(id = 1:2, type = 'gr')
#'
#' gi
#'
#' gr
#'
#' ####################################################################
#' # 1. Find overlaps between GInteractions and a subject GRanges
#' ####################################################################
#'
#' find_overlaps(gi, gr)
#'
#' find_overlaps_directed(gi, gr)
#'
#' ####################################################################
#' # 1. Find overlaps between PinnedGInteractions and a subject GRanges
#' ####################################################################
#'
#' gi |> pin_by("first") |> find_overlaps(gr)
#'
#' gi |> pin_by("second") |> find_overlaps(gr)
#'
#' gi |> pin_by("first") |> find_overlaps_directed(gr)
#'
#' gi |> pin_by("second") |> find_overlaps_directed(gr)
NULL

#' @rdname ginteractions-find-overlaps
#' @export
find_overlaps.PinnedGInteractions <- function(
x, y, maxgap = -1L, minoverlap = 0L, suffix = c(".x", ".y")
) {

hits <- InteractionSet::findOverlaps(
query = y,
subject = unpin(x),
maxgap = maxgap,
minoverlap = minoverlap,
type = 'any',
select = 'all',
ignore.strand = TRUE,
use.region = switch(
as.character(pin(x)),
"1" = "first",
"2" = "second"
)
)
left <- unpin(x)[S4Vectors::subjectHits(hits), ]
right <- y[S4Vectors::queryHits(hits), ]
mcols(left) <- .mcols_overlaps_update(left, right, suffix)
return(left)

}

#' @rdname ginteractions-find-overlaps
#' @export
find_overlaps.GInteractions <- function(
x, y, maxgap = -1L, minoverlap = 0L, suffix = c(".x", ".y")
) {

hits <- InteractionSet::findOverlaps(
query = y,
subject = x,
maxgap = maxgap,
minoverlap = minoverlap,
type = 'any',
select = 'all',
ignore.strand = TRUE,
use.region = 'both'
)
left <- x[S4Vectors::subjectHits(hits), ]
right <- y[S4Vectors::queryHits(hits), ]
mcols(left) <- .mcols_overlaps_update(left, right, suffix)
return(left)

}

#' @rdname ginteractions-find-overlaps
#' @export
find_overlaps_directed.PinnedGInteractions <- function(
x, y, maxgap = -1L, minoverlap = 0L, suffix = c(".x", ".y")
) {

hits <- InteractionSet::findOverlaps(
query = y,
subject = unpin(x),
maxgap = maxgap,
minoverlap = minoverlap,
type = 'any',
select = 'all',
ignore.strand = FALSE,
use.region = switch(
as.character(pin(x)),
"1" = "first",
"2" = "second"
)
)
left <- unpin(x)[S4Vectors::subjectHits(hits), ]
right <- y[S4Vectors::queryHits(hits), ]
mcols(left) <- .mcols_overlaps_update(left, right, suffix)
return(left)

}

#' @rdname ginteractions-find-overlaps
#' @export
find_overlaps_directed.GInteractions <- function(
x, y, maxgap = -1L, minoverlap = 0L, suffix = c(".x", ".y")
) {

hits <- InteractionSet::findOverlaps(
query = y,
subject = x,
maxgap = maxgap,
minoverlap = minoverlap,
type = 'any',
select = 'all',
ignore.strand = FALSE,
use.region = 'both'
)
left <- x[S4Vectors::subjectHits(hits), ]
right <- y[S4Vectors::queryHits(hits), ]
mcols(left) <- .mcols_overlaps_update(left, right, suffix)
return(left)

}

.mcols_overlaps_update <- function(left, right, suffix, return_data_frame = FALSE) {

left_names <- names(mcols(left))
right_names <- names(mcols(right))
common_name <- intersect(left_names, right_names)
lname_inx <- left_names %in% common_name
rname_inx <- right_names %in% common_name
if (any(lname_inx)) {
names(mcols(left))[lname_inx] <- paste0(left_names[lname_inx], suffix[1])
}

if (any(rname_inx)) {
names(mcols(right))[rname_inx] <- paste0(right_names[rname_inx], suffix[2])
}

if (!is.null(mcols(left))) {
additional_mcols <- mcols(left)
} else {
additional_mcols <- NULL
}

if (!is.null(mcols(right))) {
if (is.null(additional_mcols)) {
additional_mcols <- mcols(right)
} else {
additional_mcols <- cbind(additional_mcols, mcols(right))
}
}

if (return_data_frame) {
if (is(left, "GenomicRanges")) {
ranges_df <- DataFrame(granges.x = GenomicRanges::granges(left),
granges.y = GenomicRanges::granges(right))
} else {
ranges_df <- DataFrame(ranges.x = ranges(left),
ranges.y = ranges(right))
}
names(ranges_df) <- paste0(gsub("\\..*", "" , names(ranges_df)), suffix)
if (!is.null(additional_mcols)) {
additional_mcols <- cbind(ranges_df, additional_mcols)
} else {
return(ranges_df)
}
}

additional_mcols
}
10 changes: 10 additions & 0 deletions R/reexports-plyranges.R
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ plyranges::anchor_5p
#' @importFrom plyranges stretch
#' @export
plyranges::stretch

#' @rdname reexports
#' @importFrom plyranges find_overlaps
#' @export
plyranges::find_overlaps

#' @rdname reexports
#' @importFrom plyranges find_overlaps_directed
#' @export
plyranges::find_overlaps_directed
3 changes: 3 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ reference:
- title: "`plyranges` verbs"
contents:
- starts_with("plyranges-")
- title: "Overlapping GInteractions"
contents:
- ginteractions-find-overlaps
- title: "Pinning GInteractions"
contents:
- pin
Expand Down
90 changes: 90 additions & 0 deletions man/ginteractions-find-overlaps.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion man/reexports.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit addde05

Please sign in to comment.