Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stripe annotations? #80

Open
ksmetz opened this issue May 3, 2023 · 4 comments
Open

Stripe annotations? #80

ksmetz opened this issue May 3, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@ksmetz
Copy link

ksmetz commented May 3, 2023

Hi Nicole + plotgardener team! :)

I am trying to annotate stripes on a Hi-C map using rectangles. Since there didn't seem to be an existing function for this (annoPixels doesn't parse/plot the stripe coordinates quite right), I wrote my own little function that accomplished this using the grid.polygon function.

It requires a GInteractions object of stripe coordinates (stripeGI, i.e. read in from Stripenn results), the name of the viewport containing the pg plot to be annotated (pgPlot, i.e. "hicSquare1"), and a chr/start/stop position of the window you are plotting for. See here:

library(grid)
library(InteractionSet)

stripePlotter <- function(stripeGI, pgPlot, chr, start, stop){
  
  region = GRanges(chr, IRanges(start, stop))
  stripeOV = findOverlaps(stripeGI, region)
  
  if(length(stripeOV) > 0){
    stripeGI = stripeGI[queryHits(stripeOV),]
    
    lapply(1:length(stripeGI), function(n){
      grid.polygon(x = c(start(anchors(stripeGI, "first"))[n],
                         start(anchors(stripeGI, "first"))[n],
                         end(anchors(stripeGI, "first"))[n],
                         end(anchors(stripeGI, "first"))[n]),
                   y = c(start(anchors(stripeGI, "second"))[n],
                         end(anchors(stripeGI, "second"))[n],
                         end(anchors(stripeGI, "second"))[n],
                         start(anchors(stripeGI, "second"))[n]),
                   vp = pgPlot,
                   gp = gpar(fill = NA, col = 'red'),
                   default.units = "native")}
    )
  }
  
}

This is very basic and I'm working on adjusting it still, but the basic concept works fine.

However, there are a few downsides to this - for example, adjusting which side of the diagonal it plots on is a little tricky, and I'm not sure how to apply this to a rectangular Hi-C plot (since I'm not sure what the native y coordinates are there). I also worried that I was sort of reinventing the wheel, since it seems so close to other existing plotgardener functions.

I was wondering if it is possible to adapt annoPixels to be able to draw boxes with custom coordinates (instead of making a square box), in a way that would make it compatible with stripe calls? Or are there any current plans for a separate function for annotating stripes or similar features?

If not, I was wondering if you have any advice on how to improve my current approach, or how to apply something similar to rectangle plots? The current function only works with square plots because of the way it uses x/y coordinates.

Again since I've got a working function this isn't super urgent, more a matter of curiosity!

Thanks for your time and insights!

-Katie

@ksmetz
Copy link
Author

ksmetz commented Jun 2, 2023

Just a minor update: I did get around to updating my custom stripePlotter function slightly, to only plot to the upper half. I also added a color option (you could easily add others to the gpar bit to make it more customizable). It's still pretty hideous but it gets the job done haha.

It is still for square plots only, and you can't pick what side it plots to (it's always upper) - but for my specific use case it has been fine so far, so I'll still post it in case it is ever helpful to anyone.

stripePlotter <- function(stripeGI, pgPlot, chr, start, stop, col = "red"){
  
  # Find stripes in region
  region = GRanges(chr, IRanges(start, stop))
  stripeOV = findOverlaps(stripeGI, region)
  
  # If stripes in region...
  if(length(stripeOV) > 0){
    
    # Pull stripes from the region
    stripeGI = stripeGI[queryHits(stripeOV),]
    
    # Figure out orientation
    minX = start(ranges(anchors(stripeGI, "first")))
    minY = start(ranges(anchors(stripeGI, "second")))
    
    vert = which(minX == minY)
    horz = which(minX > minY)
    
    # These are stripes that by default would be plotted on the upper half of the plot
    if(length(vert) > 0){
      lapply(vert, function(n){
        grid.polygon(x = c(start(anchors(stripeGI, "first"))[n],
                           start(anchors(stripeGI, "first"))[n],
                           end(anchors(stripeGI, "first"))[n],
                           end(anchors(stripeGI, "first"))[n]),
                     y = c(start(anchors(stripeGI, "second"))[n],
                           end(anchors(stripeGI, "second"))[n],
                           end(anchors(stripeGI, "second"))[n],
                           start(anchors(stripeGI, "second"))[n]),
                     vp = pgPlot,
                     gp = gpar(fill = NA, col = col),
                     default.units = "native")}
      )
    }
    
    # These are stripes that by default would be plotted on the lower half of the plot
    # (now they are plotted on upper half, but are drawn horizontally)
    if(length(horz) > 0){
      lapply(horz, function(n){
        grid.polygon(x = c(start(anchors(stripeGI, "second"))[n],
                           start(anchors(stripeGI, "second"))[n],
                           end(anchors(stripeGI, "second"))[n],
                           end(anchors(stripeGI, "second"))[n]),
                     y = c(start(anchors(stripeGI, "first"))[n],
                           end(anchors(stripeGI, "first"))[n],
                           end(anchors(stripeGI, "first"))[n],
                           start(anchors(stripeGI, "first"))[n]),
                     vp = pgPlot,
                     gp = gpar(fill = NA, col = 'red'),
                     default.units = "native")}
      )
    }
    
  }
  
}

Here's an example where you can see a horizontal (red; previously would have been plotted vertically on the lower half of the plot) and vertical (blue) stripe.

image

@nekramer
Copy link
Member

nekramer commented Jun 2, 2023

Hi Katie!!!

Sorry I never got around to responding to this. This is an awesome feature, so thank you so much for getting it started. When I get the chance I would definitely like to incorporate this as a new feature (maybe as its own annotation function? that way it's not as confusing with annoPixels being boxes with a radius whereas these have a predefined region). The logic for rectangle Hi-C plots is a little tricky so no worries about not implementing it for that. I'm gonna label this and come back when I add it (which may be a little while, sorry).

@nekramer nekramer added the enhancement New feature or request label Jun 2, 2023
@ksmetz
Copy link
Author

ksmetz commented Jun 2, 2023

Hi Nicole!! :)

No problem at all! To be honest I'm not doing a ton with stripes so the little custom function has worked a-okay for me so far - it was more of a curiosity than a super required/deal-breaking feature for me haha. In general they seem to be a more niche area still (although I guess that could change with more Micro-C, but I still feel like TADs and loops will be king). That said, if you do make an official pg function for it'd I'd definitely be a user!

Btw I agree that having a separate function makes perfect sense so that the annoPixels can still always represent a given radius - seems super logical to me!

@RomeroMatt
Copy link

Hello! Thanks for the great tool. And thanks @ksmetz for generating these new functions. I am also trying to generate plots in plot gardener regarding stripes and I am having a hard time figuring out how to do so. Has any more progress been made on this front?
Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants