myles-lewis / locuszoomr

A pure R implementation of locuszoom for plotting genetic data at genomic loci accompanied by gene annotations.
GNU General Public License v3.0
18 stars 5 forks source link

Legend #27

Closed alicexrz closed 1 month ago

alicexrz commented 1 month ago

Hi @myles-lewis,

Thank you very much for creating this wonderful package to make locuszoom plots in R!

I have a question regarding the legend. In my plot, the points have no borders, but in the legend, they still appear with borders. My example code is provided below.

  1. Is there a way to remove the point borders in the legend so they match the plot?
  2. Additionally, is it possible to customize the legend to display a color gradient, similar to the first plot here, instead of showing five separate points?
data(SLE_gwas_sub)

if (require(EnsDb.Hsapiens.v75)) {
  loc <- locus(data = SLE_gwas_sub, gene = 'UBE2L3', flank = 1e5,
               ens_db = "EnsDb.Hsapiens.v75", LD = "r2")
  summary(loc)
  locus_plot(loc, 
             cex = 1,
             cex.text = 0.7,
             border = T, 
             col = NA, # border of the points
             legend_pos = "topleft", # "topright"
             pcutoff = NULL,
             ylab = expression("-log"[10] ~ italic("P")),
             LD_scheme = c('black', '#D3D3D3', '#46b8daff', '#5cb85cff', '#eea236ff', '#d43f3aff', '#9632b8ff'))
}

Best, Alice

myles-lewis commented 1 month ago

Hi Alice,

Does this produce something closer to what you wanted to achieve?

# setup a custom legend
pl <- quote(
  legend("topright", legend = c("0.8 - 1.0", "0.6 - 0.8", "0.4 - 0.6", "0.2 - 0.4",
                                "0.0 - 0.2", "NA"),
         title = expression(R^2),
         bty = "n",
         fill = rev(c('Black', '#D3D3D3', '#46b8daff', '#5cb85cff',
                      '#eea236ff', '#d43f3aff')))
)

oldpar <- set_layers(1)  # manually set up a layered plot with just 1 scatter plot
scatter_plot(loc, 
             border = TRUE, 
             col = NA,  # border of the points
             legend_pos = NULL,  # manual legend
             pcutoff = NULL,
             xticks = FALSE,
             LD_scheme = c('black', '#D3D3D3', '#46b8daff', '#5cb85cff',
                           '#eea236ff', '#d43f3aff', '#9632b8ff'),
             panel.last = pl)  # panel.last passes the legend in

genetracks(loc, border = TRUE)
par(oldpar)  # reset par

If you want the legend coloured filled boxes to be adjoining, I'm not sure how that can be easily done in base graphics. might be easier to do it using ggplot2. You could manually make a ggplot2 scatter plot to your liking and then put the gene tracks underneath with gg_genetracks. Something like this might be close to what you want:

library(ggplot2)
library(cowplot)

loc$data$pos2 <- loc$data$pos / 1e6
p1 <- ggplot(loc$data, aes(x = pos2, y = logP, color = ld)) +
  geom_point(na.rm = TRUE) +
  binned_scale(aesthetics = "color",
    breaks = seq(0, 1, 0.2),
                     palette = function(x) c('#D3D3D3', '#46b8daff', '#5cb85cff', 
                                '#eea236ff', '#d43f3aff'),
    guide = "colorsteps",
    name = expression({r^2})) +
  xlab("") + ylab(expression("-log"[10] ~ "P")) +
  theme_classic() +
  theme(axis.text = element_text(colour = "black"),
        legend.justification = c(1, 1),
        legend.position = c(0.99, 0.99))

p2 <- gg_genetracks(loc)

plot_grid(p1, p2, ncol = 1, rel_heights = c(0.6, 0.4), align = "v")

Hope either of these methods help.

Best wishes, Myles

alicexrz commented 1 month ago

Hi Myles,

Thank you so much! The ggplot option you provided worked perfectly. I was also able to tweak the base graphics option, specifically pl, and got it to work as well:

# Custom legend with matching fill and border color
pl <- quote(
  legend("topleft", 
         legend = c("0.8 - 1.0", "0.6 - 0.8", "0.4 - 0.6", 
                    "0.2 - 0.4", "0.0 - 0.2", "NA"),
         title = expression(R^2),
         y.intersp = 0.5, # Adjust vertical spacing
         bty = "n", # No box around the legend
         pch = 22, # Filled square with border
         pt.bg = rev(c('Black', '#D3D3D3', '#46b8daff', '#5cb85cff',
                       '#eea236ff', '#d43f3aff')), # Fill color for the squares
         col = rev(c('Black', '#D3D3D3', '#46b8daff', '#5cb85cff',
                     '#eea236ff', '#d43f3aff')), # Border color to match fill
         pt.cex = 2, # Size of the boxes
         cex = 0.8) # Text size
)

Thank you again, Alice

alicexrz commented 1 month ago

One follow-up question, Myles: For the ggplot option, how to add the recombination rate to the plot? I didn't see an example of doing this on the website.