Bioconductor / IRanges

Foundation of integer range manipulation in Bioconductor
https://bioconductor.org/packages/IRanges
22 stars 10 forks source link

Add rescale() for IRanges objects #16

Open hpages opened 5 years ago

hpages commented 5 years ago
library(IRanges)

.zoom0 <- function(x, z=1)
{
    stopifnot(is(x, "Ranges"), is.numeric(z))
    if (length(z) > length(x) && length(z) != 1L)
        stop("'z' is longer than 'x'")
    if (anyNA(z) || min(z) <= -1L)
        stop("'z' contains NAs and/or negative values")
    new_start <- as.integer(start(x) * z)
    new_width <- as.integer(width(x) * z)
    BiocGenerics:::replaceSlots(x, start=new_start, width=new_width)
}

.normarg_scale <- function(scale)
{
    if (is(scale, "IRanges"))
        return(scale)
    if (is.numeric(scale))
        return(IRanges(1L, scale))
    as(scale, "IRanges")
}

## 'oldscale' and 'newscale': integer vectors or IRanges
## objects recycled to the length of 'x'.
rescale <- function(x, newscale=1L, oldscale=1L)
{
    if (!is(x, "IRanges"))
        x <- as(x, "IRanges")
    newscale <- .normarg_scale(newscale)
    oldscale <- .normarg_scale(oldscale)
    ans <- shift(x, -start(oldscale))
    ans <- .zoom0(ans, width(newscale) / width(oldscale))
    shift(ans, start(newscale))
}

Then:

> rescale("5-10", newscale=100, oldscale=10)
IRanges object with 1 range and 0 metadata columns:
          start       end     width
      <integer> <integer> <integer>
  [1]        41       100        60

> rescale("505-510", newscale=100, oldscale="501-510")
IRanges object with 1 range and 0 metadata columns:
          start       end     width
      <integer> <integer> <integer>
  [1]        41       100        60

> rescale("505-510", newscale="101-200", oldscale="501-510")
IRanges object with 1 range and 0 metadata columns:
          start       end     width
      <integer> <integer> <integer>
  [1]       141       200        60

There is a rescale() generic in ggbio. Should probably be moved to BiocGenerics and the above rescale() for IRanges turned into a method.

There is also a rescale() S3 generic in the scales package (with arguments x, to, from, ...) but there is nothing we can do about this (the conflicted package will help the end user deal with the name clash).

hpages commented 4 years ago

@FelixErnst Hi Felix, I was not sure where we stand on this. Do you still need this? Or maybe you came up with your own solution/implementation already? My feeling at this point is that it seems a little bit too specialized and probably lacks use cases to be a good fit for IRanges. What do you think?

H.

FelixErnst commented 4 years ago

@hpages Hi Herve,

I still like the idea quite a bit. If you think it doesn't make sense to be added to IRanges at this moment, it is fine for me. I have recylced the code snippets from Slack and GitHub and so that I can use these functions for testing.

I would suggest the following: If the package, for which I need this function (at least at this moment in time), is mature enough to be submitted to BioC, I will tag you in the submission. You can decide then, whether you want to move it into IRanges.

Felix