Tool: EnhancedVolcano: Publication-ready volcano plots with enhanced colouring and labeling
30
gravatar for Kevin Blighe
13 months ago by
Kevin Blighe50k
Kevin Blighe50k wrote:

last update: June 2, 2019

EnhancedVolcano

EnhancedVolcano is now on Bioconductor. The function was well received here on Biostars (primarily here: A: Volcano plot help code ), which originally gave me the impetus to go for a Bioconductor submission.

INSTALLATION

Devel (catch most recent changes):

devtools::install_github('kevinblighe/EnhancedVolcano')

Release (from Bioconductor):

BiocManager::install('EnhancedVolcano')

---------------------------------------------

ex12-1 ex10-1 ex13-1

---------------------------------------------

GitHub

https://github.com/kevinblighe/EnhancedVolcano

Bioconductor

https://bioconductor.org/packages/release/bioc/html/EnhancedVolcano.html

Vignette

https://bioconductor.org/packages/release/bioc/vignettes/EnhancedVolcano/inst/doc/EnhancedVolcano.html


Should anyone wish to provide feedback and / or suggestions for future development, please do so. Credit will always be given where it is due.

Kevin

ADD COMMENTlink modified 6 weeks ago by bhanu.chandra120 • written 13 months ago by Kevin Blighe50k
1

Great tool, thanks for putting it together!

My DEseqDataSet is actually a set of peaks instead of transcripts that all have a unique identifier going out to 6 figures, I was wondering if there was a way to use selectLab() to create custom labels such as TF names for factors I know to bind within those peaks or even small representations of their PWMs - though the former would be sufficient for the moment - or does that have to come from an additional metadata column in DEseqDataSet? Thanks!

ADD REPLYlink modified 10 months ago • written 10 months ago by rbronste280
2

Hey, thanks for the comments. My colleague Myles back in London deserves the credit for the initial idea of putting this together. selectLab() will just match up to whatever you have passed to the required lab parameter. So, it can be anything really, but there is no functionality to automatically pull in TF names. That is a good idea, though, and it would show in a nice way which TFs were up- or down-regulated.

I mean, this package is only released for a few weeks at this stage, and I'm fairly open as to where it could be developed further. I was hoping to build something as comprehensive as the ComplexHeatmap package.

ADD REPLYlink written 10 months ago by Kevin Blighe50k
1

Hi Kevin,

Thanks again for the amazing tool!

Can I use EnhancedVolcano with plotly? I assume it's built using ggplot2, and I've tried to do:

ggplotly(plot) where plot is a volcano plot made using EnhancedVolcano.

I get the following error message though:

Error in unique.default(x) :
unique() applies only to vectors
In addition: Warning messages:
1: In if (nchar(axisTitleText) > 0) { :
  the condition has length > 1 and only the first element will be used
2: In if (nchar(axisTitleText) > 0) { :
  the condition has length > 1 and only the first element will be used

Being able to use these volcano plots with plotly would be super useful! Especially when there are too many DEGs and it really makes labeling messy.

Thanks!

ADD REPLYlink modified 7 weeks ago by RamRS24k • written 7 months ago by unawaz50

EnhancedVolcano does indeed return a ggplot2 object, on which extra features can be added. It also utilises ggrepel - perhaps that is the missing link? I have not tried with plotly but will make an attempt later to see how to coerce the volcano object to work with plotly.

I believe there are a few tutorials around where plotly is used to generate a volcano, though. I think that Stephen Turner had one, but cannot find it right now.

ADD REPLYlink modified 7 months ago • written 7 months ago by Kevin Blighe50k
1

Aha! Thank you so much, it's working now :)

ADD REPLYlink written 6 weeks ago by s.muroy10
1

Please use Add Comment or Add Reply as appropriate instead of Add Answer.

ADD REPLYlink written 6 weeks ago by RamRS24k

and i already used it....

ADD REPLYlink written 13 months ago by krushnach80590
1

Good work dude!

ADD REPLYlink written 13 months ago by Kevin Blighe50k

Hi Kevin,

Great tool! I've been pretty much using it for all my volcano plots. I wanted to know if there was a way to use EnhancedVolcanos with results from sleuth?

cheers!

ADD REPLYlink written 9 months ago by unawaz50

You're welcome. Yes, most likely there is a way. What are the columns in the output of Sleuth?

ADD REPLYlink written 9 months ago by Kevin Blighe50k

This is the output for sleuth, where b is equivalent to Log2FC

ens_gene    ext_gene    target_id   pval    qval      b se_b    mean_obs    var_obs tech_var    sigma_sq    smooth_sigma_sq final_sigma_sq
ADD REPLYlink modified 6 weeks ago by RamRS24k • written 9 months ago by unawaz50

Hey, well, you have at least 2 required columns:

  • ens_gene (label)
  • pval (y)

What is missing is the fold-change for x! I have never used Sleuth, however, I searched the Web forums and am surprised to see that the Sleuth developers do not output a fold-change for Sleuth's results. You may consider using a different differential expression analysis program.

ADD REPLYlink modified 9 months ago • written 9 months ago by Kevin Blighe50k

That's unfortunate. Thanks for looking though!

ADD REPLYlink written 9 months ago by unawaz50

You could likely still use the b value, in which case you should change the x-axis label too. You may want to read through this thread on Google Groups: https://groups.google.com/forum/#!topic/kallisto-sleuth-users/kWodd7CQejE (Harold Pimentel is Sleuth developer)

ADD REPLYlink written 9 months ago by Kevin Blighe50k

Hi Kevin, Thanks for this great package. A basic question: you specify in the vignette that the default p-value cut-off is 0.05, but from the default plot, it looks to me as if it were 0.005. Is this a misunderstanding on my part? Best wishes, Patrick

ADD REPLYlink written 4 months ago by patrick.kraetschmer10

Hey Patrick, thanks for noticing that. The default is actually:

pCutoff = 10e-6

I just need to update the text in the vignette!

ADD REPLYlink written 4 months ago by Kevin Blighe50k
1

Thanks, Kevin, I've just seen that, having read through the whole vignette: all makes sense!

ADD REPLYlink written 4 months ago by patrick.kraetschmer10

I am updating that part of the vignette right now, so, the change will come through on the Vignette on GitHub in the next few minutes: https://github.com/kevinblighe/EnhancedVolcano

It will be until Bioc 3.10 before it is changed on the main Bioconductor branch.

ADD REPLYlink written 4 months ago by Kevin Blighe50k

Awesome package, Kevin! Is it possible to remove the log2FC cutoff and lines?

ADD REPLYlink written 4 months ago by mehul.kumar0
1

Hey, thank you!

To remove all cut-off lines, you just need to do:

EnhancedVolcano(..., gridlines.major = FALSE, gridlines.minor = FALSE, ...)

If you want to disable the actual cut-off itself (and, thus, the colouring of the points based on the cut-off), then I may recommend the use of colCustom ? - there is an example in the vignette:

Another possibility is to set FCcutoff to something crazy like 1 000 000 such that nothing passes it.

ADD REPLYlink written 4 months ago by Kevin Blighe50k

Is there any chance to change tick intervals for both horizontal and vertical axes? And thanks a lot this is awsome!

ADD REPLYlink written 12 weeks ago by fr100

Hey, EnhancedVolcano is [thankfully] fully compatible with ggplot2 functionality. So, to modify, e.g., the y-axis, you can do:

p <- EnhancedVolcano(res1,
    lab = rownames(res1),
    x = 'log2FoldChange',
    y = 'pvalue',
    xlim = c(-5, 8))

p + scale_y_continuous(
  name = bquote(~-Log[10]~italic(P)),
  limits=c(0, 100),
  breaks=c(0, 33, 40, 49, 77, 88))

ddd

Hopefully this helps!

ADD REPLYlink written 12 weeks ago by Kevin Blighe50k

Hi Kevin, EnhancedVolcano package was really helpful. I have two doubts:

  1. when I used the below option legend=c('NS','Log (base 2) fold-change','P value', 'P value & Log (base 2) fold-change') it has printed Log (base 2) but not the Log2 (subscript). May I know how to do it.

  2. when I have modified pointSize = c(ifelse(res$log2FoldChange>2, 8, 1)) as pointSize = c(ifelse(res$log2FoldChange>2 & res$padj>0.05, 8, 1)) it worked. But when I have used pointSize = c(ifelse(res$log2FoldChange>2 & res$log2FoldChange<-2 & res$padj>0.05, 8, 1)) it did not work. May I know how to do it.

Thanks in advance!

ADD REPLYlink written 8 weeks ago by bhanu.chandra120
1

when I used the below option legend=c('NS','Log (base 2) fold-change','P value', 'P value & Log (base 2) fold-change') it has printed Log (base 2) but not the Log2 (subscript). May I know how to do it.

I implemented that a few days ago, so, it is only currently in the development version, which you can install via:

devtools::install_github('kevinblighe/EnhancedVolcano')

Note: you may have to install the devtools package There are now 2 parameters for the legend:

legend = c("NS","Log2 FC","P","P & Log2 FC")
legendLabels = c('NS', expression(Log[2]~FC),
    "p-value", expression(p-value~and~log[2]~FC))

Expressions (equations, super- and sub-script, etc) can only be used in legendLabels. This may seem silly to have 2 parameters for legend, but it relates to how ggplot2 (which is the underlying 'engine' behind EnhancedVolcano) utilises legends.

---------------------------

---------------------------

when I have modified pointSize = c(ifelse(res$log2FoldChange>2, 8, 1)) as pointSize = c(ifelse(res$log2FoldChange>2 & res$padj>0.05, 8, 1)) it worked. But when I have used pointSize = c(ifelse(res$log2FoldChange>2 & res$log2FoldChange<-2 & res$padj>0.05, 8, 1)) it did not work. May I know how to do it.

I think that you may want to do:

pointSize = c(ifelse(abs(res$log2FoldChange)>2 & res$padj>0.05, > 8, 1))
ADD REPLYlink modified 8 weeks ago • written 8 weeks ago by Kevin Blighe50k

Hi Kevin,

Thank you for the response.

Both of your suggestions worked :)

pointSize = c(ifelse(abs(res$log2FoldChange)>2 & res$padj>0.05, > 8, 1))

I guess, there should not be '>' before 8.

Thank you!

ADD REPLYlink modified 29 days ago by RamRS24k • written 7 weeks ago by bhanu.chandra120

Great. Oh, yes, not sure why I put the > there.

ADD REPLYlink written 7 weeks ago by Kevin Blighe50k

Hi Kevin,

I have two questions:

  1. When I plot with results object (after shrinkage), the number of genes (visible on the plot) passing the cutoff criteria are relatively less when compared to the plot with results object (without shrinkage). The graph looks nice with shrinkage and much more dispersed without shrinkage. May I know how to overcome this issue.

  2. When we use FCcuoff = 1.2, it represents log2FC (x-axis). But I want to set the cutoff for upregulation as log2FC = 0.585 (FC is >1.5) and downregulation as log2FC = -1 (FC < 0.5). Is it possible to give different log2FC cutoff values for up and downregulation?

Thanks in advance and looking forward to hearing from you.

ADD REPLYlink written 6 weeks ago by bhanu.chandra120

Hey Bhanu,

The first question is more for the DESeq2 developer. However, the idea of lfcshrink() is, generally, to produce more realistic fold changes

For the second part, you would have to avail of the colCustom parameter and assign the colours before running the EnhancedVolcano() function. You could then also draw your own custom cutoff fold change lines with the following:

vline
vlineType
vlineCol
vlineWidth

To get rid of the main cut-off lines, just set cutoffLineType = 'blank'

There are many examples in the vignette: https://github.com/kevinblighe/EnhancedVolcano

ADD REPLYlink written 5 weeks ago by Kevin Blighe50k
1

Hi Kevin,

Thank you for the response. Now I could use the colCustom parameter and do the required by following the examples in the Github. Thank you again!

ADD REPLYlink written 4 weeks ago by bhanu.chandra120

Hi Kevin,

Thank you so much for the EnhancedVolcano package - it's great! I have a quick question, I need to generate a high-res image of my volcano plot for publication and was wondering how to do that from EnhancedVolcano. I'm an R newbie and would very much appreciate any tips! I apologize if this is a bit off-topic.

Thank you! Sandra

ADD REPLYlink written 7 weeks ago by s.muroy10

Hey Sandra, I would generate the figure as a pdf with the pdf() function. PDFs are vector-based, not pixelated, so, they look 'perfect; when zoomed in and can also be easily manipulated by a journal graphics team. Also make use of the width and height arguments that are passed to the pdf() function.

pdf(out.pdf, width = 6, height = 9)
  EnhancedVolcano(...)
dev.off()

Alternatively, I show how one can generate multiple volcanos side-by-side in the vignette via grid and gridExtra, e.g., HERE.

ADD REPLYlink modified 7 weeks ago • written 7 weeks ago by Kevin Blighe50k

Hi Kevin, Thank you so much for the quick reply. The pdf looks beautiful! I have another question, I'm trying to add connectors (to fit more gene name labels)

EnhancedVolcanobaseline.no.NA,
               lab=baseline.no.NA[, 1],
                x = 'log2FoldChange',
                y = 'padj',
                xlim = c(-11, 11),
                xlab = bquote(~Log[2]~ 'fold change'),
                ylab = bquote(~-Log[10]~adjusted~italic(P)),
                pCutoff = 0.01, #padj 
                FCcutoff = 1.5,
                transcriptPointSize = 2.0,
                transcriptLabSize = 3.0,
                legend=c('NS','Log2 FC','Adjusted p-value',
                         'Adjusted p-value & Log2 FC'),
                legendPosition = 'top',
                legendLabSize = 12,
                legendIconSize = 3.0,
                gridlines.major = FALSE,
                gridlines.minor = FALSE,
                drawConnectors = TRUE,
                widthConnectors = 0.2,
                colConnectors = 'grey30')

but it gives me an error message:

Error in EnhancedVolcanobaseline.no.NA, lab = baseline.no.NA[, 1], x = "log2FoldChange",  : 
  unused argument (drawConnectors = TRUE)

Not sure what I'm doing wrong. Works great otherwise. Thanks again!

ADD REPLYlink modified 7 weeks ago by Kevin Blighe50k • written 7 weeks ago by s.muroy10

Great! Oh, which version are you using? - I changed the name of that argument. In your version, it may be DrawConnectors.

You can install the most up to date version of the package with:

devtools::install_github('kevinblighe/EnhancedVolcano')
ADD REPLYlink written 7 weeks ago by Kevin Blighe50k

aha! thank you so much, it's working now :)

ADD REPLYlink written 6 weeks ago by s.muroy10

Hi Kevin,

I frequently face the following error:

Error in grid.Call(C_convert, x, as.integer(whatfrom), as.integer(whatto),  : 
  Viewport has zero dimension(s)

Can you please suggest on how to rectify it?

ADD REPLYlink modified 29 days ago by RamRS24k • written 29 days ago by bhanu.chandra120

Hey, which code are you running, exactly?

ADD REPLYlink written 29 days ago by Kevin Blighe50k
# set the base colour as 'black'
keyvals <- rep('#000000', nrow(res_A_W_lfc))

# set the base name/label as 'NS'
names(keyvals) <- rep('NS', nrow(res_A_W_lfc))

# modify keyvals for variables with fold change > 1.5
keyvals[which(res_A_W_lfc$log2FoldChange > 0.585 &
                res_A_W_lfc$padj < 0.05)] <- '#E50000'
names(keyvals)[which(res_A_W_lfc$log2FoldChange > 0.585 &
                       res_A_W_lfc$padj < 0.05)] <- 'Up'

# modify keyvals for variables with fold change < -0.66
keyvals[which(res_A_W_lfc$log2FoldChange < -0.585 &
                res_A_W_lfc$padj < 0.05)] <- '#3C84FF'
names(keyvals)[which(res_A_W_lfc$log2FoldChange < -0.585 &
                       res_A_W_lfc$padj < 0.05)] <- 'Down'

# Selected genes to represent
s_genes <- c('abo', 'Ace')

# Volcano plots
EnhancedVolcano(res_A_W_lfc,
                x = 'log2FoldChange', y = 'padj',
                lab = rownames(res_A_W_lfc), selectLab = s_genes,
                xlim = c(-4, 4), ylim = c(0, 25),
                xlab = bquote(~Log[2]~ 'Fold Change'),
                ylab = bquote(~-Log[10]~italic(P)),
                axisLabSize = 75,
                title = 'Adult_A_W', subtitle = ' ',
                titleLabSize = 75,
                caption = bquote(~Log[2]~ 'FC cutoff, 0.585; padj cutoff, 0.05'), captionLabSize = 40,
                pCutoff = 0.05, pLabellingCutoff = pCutoff,
                FCcutoff = 0.585,
                cutoffLineType = 'longdash', cutoffLineCol = 'black',
                cutoffLineWidth = 1,
                pointSize = c(ifelse(abs(res_A_W_lfc$log2FoldChange) > 0.585 & res_A_W_lfc$padj < 0.05, 8, 4)),
                labSize = 30,
                labCol = c('black', 'black'),
                labFace = 'plain',
                colCustom = keyvals,
                colAlpha = 0.6,
                legend=c("NS", "Log2 FC", "padj", "padj & Log2 FC"),
                legendLabels = c('NS', expression(Log[2]~FC),
                                 "padj", expression(padj~and~Log[2]~FC)),
                legendPosition = 'right',
                legendLabSize = 50, legendIconSize = 30,
                gridlines.major = F, gridlines.minor = F,
                border = 'full', borderWidth = 5, borderColour = 'black',
                drawConnectors = T, widthConnectors = 4,
                colConnectors = 'yellow')
ADD REPLYlink modified 29 days ago by RamRS24k • written 29 days ago by bhanu.chandra120
2

Please use the formatting bar (especially the code option) to present your post better. You can use backticks for inline code (`text` becomes text), or select a chunk of text and use the highlighted button to format it as a code block. I've done it for you this time.
code_formatting

ADD REPLYlink written 29 days ago by RamRS24k

Thank you Ram :). I will take it as a learning experience.

ADD REPLYlink written 29 days ago by bhanu.chandra120

Whoa! I think that I saw the problem instantly when I re-ran using my own dataset. Here is what I got:

a

Your label sizes are way too large. Here it is with smaller label sizes:

EnhancedVolcano(res_A_W_lfc,
  x = 'log2FoldChange', y = 'padj',
  lab = rownames(res_A_W_lfc), selectLab = s_genes,
  xlim = c(-4, 4), #ylim = c(0, 25),
  xlab = bquote(~Log[2]~ 'Fold Change'),
  ylab = bquote(~-Log[10]~italic(P)),
  axisLabSize = 12,
  title = 'Adult_A_W', subtitle = ' ',
  titleLabSize = 12,
  caption = bquote(~Log[2]~ 'FC cutoff, 0.585; padj cutoff, 0.05'), captionLabSize = 10,
  pCutoff = 0.05, pLabellingCutoff = pCutoff,
  FCcutoff = 0.585,
  cutoffLineType = 'longdash', cutoffLineCol = 'black',
  cutoffLineWidth = 1,
  pointSize = c(ifelse(abs(res_A_W_lfc$log2FoldChange) > 0.585 & res_A_W_lfc$padj < 0.05, 5, 1)),
  labSize = 6,
  labCol = c('black', 'black'),
  labFace = 'plain',
  colCustom = keyvals,
  colAlpha = 0.6,
  legend=c("NS", "Log2 FC", "padj", "padj & Log2 FC"),
  legendLabels = c('NS', expression(Log[2]~FC),
    "padj", expression(padj~and~Log[2]~FC)),
  legendPosition = 'right',
  legendLabSize = 12, legendIconSize = 12,
  gridlines.major = F, gridlines.minor = F,
  border = 'full', borderWidth = 2, borderColour = 'black',
  drawConnectors = T, widthConnectors = 2,
  colConnectors = 'gold')

hhh

ADD REPLYlink modified 29 days ago • written 29 days ago by Kevin Blighe50k
1

Hi Kevin, Thank you! It is working now. Regards, Bhanu

ADD REPLYlink written 18 days ago by bhanu.chandra120
Please log in to add an answer.

Help
Access

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.
Powered by Biostar version 2.3.0
Traffic: 1898 users visited in the last hour