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

Secondary axis disappears when modifying range of y axis #26

Closed nickhir closed 1 month ago

nickhir commented 1 month ago

Dear Myles,

thank you once again for this amazing package, I am using it very extensively! With that being said, I noticed, that if I modify the range of the y axis values, the secondary axis with the recombination rate disappears.

This is the code that I use:

library(locuszoomr)
data(SLE_gwas_sub)  ## limited subset of data from SLE GWAS
library(EnsDb.Hsapiens.v75)

loc <- locus(gene = 'UBE2L3', SLE_gwas_sub, flank = 1e5, ens_db = "EnsDb.Hsapiens.v75")%>%
    link_recomb(., genome = "hg19")

gg_scatter(loc)+ scale_y_continuous(expand = expansion(mult=c(0, 0.1))) # I add this because I prefer it if the dots dont "float" above the xaxis

I am pretty sure it has something todo with this code in gg_scatter: https://github.com/myles-lewis/locuszoomr/blob/ac8922d70a13cacdf28552978ef539b829221229/R/gg_scatter.R#L318-L320

However, I can think of any easy "quickfix" because the code uses quite a few values which are calculated as part of the gg_scatter call.

Any insights are much appreciated!

myles-lewis commented 1 month ago

Hi @nickhir , You can do this but you'll have to calculate the y axis range for the 1st y axis manually outside the call to gg_scatter. Here is code to do it:

yrange <- range(loc$data$logP)
ymult <- 100 / diff(yrange)
gg_scatter(loc) +
  scale_y_continuous(expand = expansion(mult=c(0, 0.1)),
                     sec.axis = sec_axis(~(. - yrange[1]) * ymult,
                                         name = "Recombination rate (%)"))

The reason you have to do this is that your addition of a call to scale_y_continuous replaces the code in lines to 318-320 of ggscatter().

BTW for the most part, many people want to fix yrange[1] as 0, so that the lower limit of the y axis always starts from 0. You can control that manually.

Bw, Myles

nickhir commented 1 month ago

Amazing, thank you for the quick answer! This did the trick

nickhir commented 1 month ago

Actually, I have a quick follow-up question. I specific "style" function that I add to all my locus zoom plots (for example, makes the legend transparent). Do you know how I could expand it, so it automatically caculates ymult?

This is what it looks like right now:

library(locuszoomr)
data(SLE_gwas_sub)  ## limited subset of data from SLE GWAS
library(EnsDb.Hsapiens.v75)

theme_locuszoom <- function() {
    list(
        theme(
            plot.title = element_text(hjust = 0.5, face = "bold", size = 11),
            axis.title.y = ggtext::element_markdown(),
            legend.key.height = unit(0.05, "cm"),
            legend.text = element_text(size = 7),
            legend.title = element_text(size = 8),
            legend.background = element_rect(colour = "#FFFFFFAA", fill = "#FFFFFFAA"),
            axis.title.x = element_blank(),
            axis.text.x = element_blank(),
            axis.ticks.x = element_blank(),
            plot.margin = margin(t = 5.5, r = 5.5, b = 0, l = 5.5, unit = "pt")
        ),
        scale_y_continuous(
            name = "-log<sub>10</sub>P.val",
            expand = expansion(mult = c(0, 0.1)),
            sec.axis = sec_axis(~ (. - 0),
                name = "Recombination rate (%)"
            )
        )
    )
}

loc <- locus(gene = 'UBE2L3', SLE_gwas_sub, flank = 1e5, ens_db = "EnsDb.Hsapiens.v75")%>%
    link_recomb(., genome = "hg19")

gg_scatter(loc) + theme_locuszoom()

However, this messes up the secondary axis because ymult is missing.

myles-lewis commented 1 month ago

Hi @nickhir

I suggest you calculate ymult manually for each locus plot and then define your theme fresh each time and pass into your call to gg_scatter(). ymult is defined by gg_scatter() as 100 / diff(yrange).

ymult <- 100 / diff(range(loc$data$logP))

# then redefine your custom theme each time
# then do
gg_scatter(loc) + theme_locuszoom()

Hope that works!

I think that's the simplest - that's what I would do. You could also play around with something of the form:

theme_locuszoom <- function(loc) {
  ymult <- 100 / diff(range(loc$data$logP))
  # return your usual output but this time with ymult inserted correctly
}

# then try
gg_scatter(loc) + theme_locuszoom(loc)

But I'm not sure whether this will work with the ggplot2 + syntax.

Bw, Myles

nickhir commented 1 month ago

Actually, what you suggested works perfectly fine!

library(locuszoomr)
data(SLE_gwas_sub)  ## limited subset of data from SLE GWAS
library(EnsDb.Hsapiens.v75)

theme_locuszoom <- function(loc) {
  ymult <- 100 / diff(range(loc$data$logP))
  list(
        theme(
            plot.title = element_text(hjust = 0.5, face = "bold", size = 11),
            axis.title.y = ggtext::element_markdown(),
            legend.key.height = unit(0.05, "cm"),
            legend.text = element_text(size = 7),
            legend.title = element_text(size = 8),
            legend.background = element_rect(colour = "#FFFFFFAA", fill = "#FFFFFFAA"),
            axis.title.x = element_blank(),
            axis.text.x = element_blank(),
            axis.ticks.x = element_blank(),
            plot.margin = margin(t = 5.5, r = 5.5, b = 0, l = 5.5, unit = "pt")
        ),
        scale_y_continuous(
            name = "-log<sub>10</sub>P.val",
            expand = expansion(mult = c(0, 0.1)),
            sec.axis = sec_axis(~ (. - 0) * ymult,
                name = "Recombination rate (%)"
            )
        )
    )
}

loc <- locus(gene = 'UBE2L3', SLE_gwas_sub, flank = 1e5, ens_db = "EnsDb.Hsapiens.v75")%>%
    link_recomb(., genome = "hg19")

gg_scatter(loc) + theme_locuszoom(loc)