## BARCODEPLOT.R
barcodeplot <- function (statistics, index = NULL, index2 = NULL, gene.weights = NULL, weights.label = "Weight", labels = c("Down", "Up"), quantiles = c(-1,1)*sqrt(2), col.bars = NULL, alpha = 0.4, worm = TRUE, span.worm = 0.45, xlab = "Statistic", ...)
# Barcode plot of one or two gene sets.
# Gordon Smyth, Di Wu and Yifang Hu
# 20 October 2008. Last revised 25 Oct 2019.
{
# Check statistics
if(!is.vector(statistics, mode = "numeric")) stop("statistics should be a numeric vector")
nstat <- length(statistics)
# Check index
if(is.null(index)) {
if(is.null(gene.weights)) {
stop("Must specify at least one of index or gene.weights")
} else {
if(length(gene.weights) == nstat) {
index <- rep_len(TRUE, nstat)
index2 <- NULL
} else {
stop("No index and length(gene.weights) doesn't equal length(statistics)")
}
}
} else {
if(anyNA(index)) stop("Need to provide index without NAs")
if(is.logical(index)) if(length(index) != nstat) stop("Length of index disagrees with statistics")
if(length(index) > nstat) stop("Length of index disagrees with statistics")
}
# Check index2
if(!is.null(index2)) {
if(!is.null(gene.weights)) warning("gene.weights ignored")
gene.weights <- statistics
gene.weights[] <- 0
gene.weights[index] <- 1
gene.weights[index2] <- -1
index <- rep_len(TRUE, nstat)
index2 <- NULL
}
# Check gene.weights
if(!is.null(gene.weights)){
if(!is.vector(gene.weights, mode = "numeric")) stop("gene.weights should be a numeric vector")
if(anyNA(gene.weights)) stop("Need to provide gene.weights without NAs")
if(all(gene.weights == 0)) stop("gene.weights equal to zero: no selected genes to plot")
if(length(gene.weights) != length(statistics[index])) stop("Length of gene.weights disagrees with size of set")
one <- all(gene.weights >= 0) | all(gene.weights <= 0)
if(one){
index2 <- NULL
gene.weights1 <- rep_len(0, nstat)
names(gene.weights1) <- names(statistics)
gene.weights1[index] <- gene.weights
index <- rep_len(FALSE, nstat)
names(index) <- names(statistics)
index[gene.weights1 != 0] <- TRUE
gene.weights1 <- gene.weights1[gene.weights1 != 0]
gene.weights <- gene.weights1
} else {
gene.weights12 <- rep_len(0, nstat)
names(gene.weights12) <- names(statistics)
gene.weights12[index] <- gene.weights
index <- index2 <- rep_len(FALSE, nstat)
names(index) <- names(index2) <- names(statistics)
index[gene.weights12 > 0] <- TRUE
index2[gene.weights12 < 0] <- TRUE
gene.weights1 <- gene.weights12[gene.weights12 > 0]
gene.weights2 <- gene.weights12[gene.weights12 < 0]
gene.weights <- gene.weights1
}
}
# Are there up and down sets?
TWO <- !is.null(index2)
# Convert indexes to logical and add weights
if(is.logical(index))
idx <- index
else {
idx <- rep_len(FALSE,nstat)
names(idx) <- names(statistics)
idx[index] <- TRUE
}
set1 <- data.frame(idx = idx, weight = NA, wt = NA)
if(TWO) {
if(is.logical(index2))
idx2 <- index2
else {
idx2 <- rep_len(FALSE,nstat)
names(idx2) <- names(statistics)
idx2[index2] <- TRUE
}
set2 <- data.frame(idx = idx2, weight = NA, wt = NA)
}
if(length(gene.weights)) {
set1$weight <- 0
set1$weight[index] <- gene.weights
set1$wt <- abs(set1$weight)/sum(abs(set1$weight))
if(TWO) {
set2$weight <- 0
set2$weight[index2] <- gene.weights2
SUM <- sum(abs(set1$weight), abs(set2$weight))
set1$wt <- abs(set1$weight)/SUM
set2$wt <- abs(set2$weight)/SUM
}
}
# Sort statistics and indexes
ostat <- order(statistics, na.last = TRUE, decreasing=FALSE)
statistics <- statistics[ostat]
set1 <- set1[ostat,]
if(TWO) set2 <- set2[ostat,]
# Trim off missing values
n <- sum(!is.na(statistics))
if(n==0L) {
message("No valid statistics")
return(invisible())
}
if (n < nstat) {
statistics <- statistics[1:n]
set1 <- set1[1:n,]
if (TWO) set2 <- set2[1:n,]
}
# Convert indexes to integer
r <- which(set1$idx)
if (TWO) {
r2 <- which(set2$idx)
if(!length(r2)) TWO <- FALSE
}
# Check there is something to plot
if(!length(r))
if(TWO) {
r <- r2
set1 <- set2
TWO <- FALSE
} else {
message("No selected genes to plot")
return(invisible())
}
# Are there unequal weights?
WTS <- FALSE
wt1 <- set1$wt[r]
len.up <- 1
if(!anyNA(wt1)) {
len.up <- set1$weight[r]/max(abs(set1$weight[r]))
anydifferent <- function(x) {
if(length(x) < 2) return(FALSE)
r <- range(x)
(r[2] > r[1])
}
if(!TWO) if(anydifferent(wt1)) WTS <- TRUE
if(TWO){
wt12 <- c(set1$wt[r], abs(set2$wt[r2]))
if(anydifferent(wt12)) WTS <- TRUE
max.wt <- max(set1$wt[r], set2$wt[r2])
len.up <- set1$wt[r]/max.wt
len.down <- set2$wt[r2]/max.wt
}
}
pos.dir <- all(len.up > 0)
# Plot setting
if(WTS) shift <- 0.1 else shift <- 0
# Check other arguments
quantiles <- sort(quantiles)
# check transparency settting for vertical bars
ALP <- alpha
ALP <- min(ALP,1)
ALP <- max(ALP,0.1)
if (is.null(col.bars)) {
if (TWO) {
col.bars <- c("red", "blue")
if(WTS) col.bars.alpha <- c(rgb(1,0,0,alpha=ALP), rgb(0,0,1,alpha=ALP))
else col.bars.alpha <- col.bars
} else {
col.bars <- "black"
if(WTS) col.bars.alpha <- rgb(0,0,0,alpha=ALP)
else col.bars.alpha <- col.bars
}
} else {
if(TWO) {
if(length(col.bars) == 1) col.bars <- rep(col.bars, 2)
RGB <- col2rgb(col.bars)/255
red <- RGB[1,1]
green <- RGB[2,1]
blue <- RGB[3,1]
red2 <- RGB[1,2]
green2 <- RGB[2,2]
blue2 <- RGB[3,2]
if(WTS) col.bars.alpha <- c(rgb(red, green, blue, alpha=ALP), rgb(red2, green2, blue2, alpha=ALP))
else col.bars.alpha <- col.bars
} else {
RGB <- col2rgb(col.bars)/255
red <- RGB[1,1]
green <- RGB[2,1]
blue <- RGB[3,1]
if(WTS) col.bars.alpha <- rgb(red, green, blue, alpha=ALP)
else col.bars.alpha <- col.bars
}
}
# worm plot setting
ylim.worm <- ylim <- c(-1, 1)
ylab.worm <- ""
xlab.worm <- xlab
if(!TWO) ylim.worm <- c(0, 1)
if(worm) {
ylim.worm <- c(-2.1, 2.1)
if(!TWO) ylim.worm <- c(0, 2.1)
}
ylim[2] <- ylim[2] + 0.5
if (TWO) ylim[1] <- ylim[1] - 0.5
if(TWO) plot(1:n, xlim=c(0,n), ylim=c(ylim.worm[1]-shift, ylim.worm[2]+shift), type="n", axes=FALSE, xlab=xlab.worm, ylab=ylab.worm, ...)
if(!TWO) plot(1:n, xlim=c(0,n), ylim=c(ylim.worm[1]-shift*(!pos.dir), ylim.worm[2]+shift*pos.dir), type="n", axes=FALSE, xlab=xlab.worm,ylab=ylab.worm, ...)
npos <- sum(statistics > quantiles[2])
nneg <- sum(statistics < quantiles[1])
lwd <- 50/length(r)
lwd <- min(1.9, lwd)
lwd <- max(0.2, lwd)
if(TWO){
lwd2 <- 50/length(r2)
lwd2 <- min(1.9, lwd2)
lwd2 <- max(0.2, lwd2)
lwd <- lwd2 <- min(lwd, lwd2)
}
barlim <- ylim[2] - c(1.5, 0.5)
if(!pos.dir) {
rect.yb <- 0.5
rect.yt <- 1
rect(nneg + 0.5, rect.yb, n - npos + 0.5, rect.yt, col = "lightgray", border = NA)
if (nneg) rect(0.5, rect.yb, nneg + 0.5, rect.yt, col = "lightblue", border = NA)
if (npos) rect(n - npos + 0.5, rect.yb, n + 0.5, rect.yt, col = "pink", border = NA)
segments(r, barlim[2]/2, r, barlim[2], lwd = lwd, col = col.bars.alpha[1])
segments(r, barlim[2]/2-shift, r, barlim[2]/2*(1+len.up)-shift, lwd = lwd, col = col.bars[1])
}
if(pos.dir) {
rect.yb <- -0.5
if(!TWO) rect.yb <- 0
rect.yt <- 0.5
rect(nneg + 0.5, rect.yb, n - npos + 0.5, rect.yt, col = "lightgray", border = NA)
if (nneg) rect(0.5, rect.yb, nneg + 0.5, rect.yt, col = "lightblue", border = NA)
if (npos) rect(n - npos + 0.5, rect.yb, n + 0.5, rect.yt, col = "pink", border = NA)
segments(r, barlim[1], r, barlim[2]/2, lwd = lwd, col = col.bars.alpha[1])
segments(r, barlim[2]/2+shift, r, barlim[2]/2*(1+len.up)+shift, lwd = lwd, col = col.bars[1])
}
if(TWO) {
barlim2 <- ylim[1] + c(0.5, 1.5)
segments(r2, barlim2[1]/2, r2, barlim2[2], lwd = lwd2, col = col.bars.alpha[2])
segments(r2, barlim2[1]/2*(1+len.down)-shift, r2, barlim2[1]/2-shift, lwd = lwd2, col = col.bars[2])
}
lab.at <- 0
if(!TWO) lab.at <- 0.5
axis(side = 2, at = lab.at, padj = 3.8, cex.axis = 0.85, labels = labels[1], tick = FALSE)
axis(side = 4, at = lab.at, padj = -3.8, cex.axis = 0.85, labels = labels[2], tick = FALSE)
# label statistics on x axis
prob <- (0:10)/10
axis(at = seq(1,n,len=11), side = 1, cex.axis = 0.7, las = 2, labels = format(quantile(statistics, p = prob), digits = 1))
# create worm
if(worm) {
# rescale x to new range
rescale <- function(x, newrange, oldrange=range(x)) {
newrange[1] + (x-oldrange[1]) / (oldrange[2]-oldrange[1]) * (newrange[2] - newrange[1])
}
# calculate enrichment
if(!WTS){
ave.enrich1 <- length(r)/n
worm1 <- tricubeMovingAverage(set1$idx, span = span.worm)/ave.enrich1
if(TWO) {
ave.enrich2 <- length(r2)/n
worm2 <- tricubeMovingAverage(-set2$idx, span = span.worm)/ave.enrich2
}
}
# calculate weighted enrichment
if(WTS){
ave.enrich1 <- mean(set1$wt)
worm1 <- tricubeMovingAverage(set1$wt, span = span.worm)/ave.enrich1
if(TWO) {
ave.enrich2 <- mean(set2$wt)
worm2 <- tricubeMovingAverage(-set2$wt, span = span.worm)/ave.enrich2
}
}
# rescale worm
max.worm1 <- max(worm1)
r.worm1 <- c(0,max.worm1)
worm1.scale <- rescale(worm1, newrange=c(1.1+shift*pos.dir,2.1+shift*pos.dir), oldrange=r.worm1)
if(TWO) {
min.worm2 <- min(worm2)
r.worm2 <- c(min.worm2,0)
worm2.scale <- rescale(worm2, newrange=c(-2.1-shift,-1.1-shift), oldrange=r.worm2)
}
# plot worms
if(!TWO) {
lines(x = 1:n, y = worm1.scale, col = col.bars[1], lwd = 2)
abline(h = rescale(1,newrange=c(1.1+shift*pos.dir,2.1+shift*pos.dir),oldrange=r.worm1), lty=2)
axis(side = 2, at = c(1.1+shift*pos.dir, 2.1+shift*pos.dir), cex.axis = 0.8, labels = c(0, format(max.worm1, digits = 2)))
axis(side = 2, labels = "Enrichment", at = 1.6+shift*pos.dir, padj = -0.6, tick = FALSE, cex.axis = 0.8)
}
if(TWO) {
lines(x = 1:n, y = worm1.scale, col = col.bars[1], lwd = 2)
abline(h = rescale(1,newrange=c(1.1+shift,2.1+shift),oldrange=r.worm1), lty=2)
lines(x = 1:n, y = worm2.scale, col = col.bars[2], lwd = 2)
abline(h = rescale(-1,newrange=c(-2.1-shift,-1.1-shift),oldrange=r.worm2), lty=2)
axis(side = 2, at = c(1.1+shift, 2.1+shift), cex.axis = 0.7, labels = c(0, format(max.worm1, digits = 2)))
axis(side = 2, at = c(-1.1-shift, -2.1-shift), cex.axis = 0.7, labels = c(0, format(-min.worm2, digits = 2)))
axis(side = 2, labels = "Enrichment", at = 1.6+shift, tick = FALSE, padj = -0.6, cex.axis = 0.7)
axis(side = 2, labels = "Enrichment", at = -1.6-shift, tick = FALSE, padj = -0.6, cex.axis = 0.7)
}
}
# add gene.weights axis
if(WTS){
if(!TWO){
if(pos.dir){
axis(side = 2, at = c(0.5+shift, 1+shift), cex.axis = 0.48, padj = 1.6, labels = c(0, format(max(set1$weight[r]), digits = 2)))
axis(side = 2, labels = weights.label[1], at = 0.75+shift, padj = 1, tick = FALSE, cex.axis = 0.5)
}
if(!pos.dir){
axis(side = 2, at = c(0-shift, 0.5-shift), cex.axis = 0.48, padj = 1.6, labels = c(format(min(set1$weight[r]), digits = 2), 0))
axis(side = 2, labels = weights.label[1], at = 0.25-shift, padj = 1, tick = FALSE, cex.axis = 0.5)
}
}
if(TWO){
max.weight <- max(set1$weight[r], abs(set2$weight[r2]))
axis(side = 2, at = c(0.5+shift, 1+shift), cex.axis = 0.43, labels = c(0, format(max.weight, digits = 2, scientific = FALSE)), padj = 1.6)
axis(side = 2, labels = weights.label[1], at = 0.75+shift, padj = 1, tick = FALSE, cex.axis = 0.46)
axis(side = 2, at = c(-0.5-shift, -1-shift), cex.axis = 0.43, labels = c(0, format(-max.weight, digits = 2, scientific = FALSE)), padj = 1.6)
axis(side = 2, labels = weights.label[1], at = -0.75-shift, padj = 1, tick = FALSE, cex.axis = 0.46)
}
}
invisible()
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.