Mercurial > repos > artbio > ngsplot
comparison lib/plotlib.r @ 0:3ca58369469c draft
planemo upload for repository https://github.com/ARTbio/tools-artbio/tree/master/tools/ngsplot commit b'e9fcc157a7f2f2fa9d6ac9a58d425ff17c975f5c\n'
| author | artbio |
|---|---|
| date | Wed, 06 Dec 2017 19:01:53 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:3ca58369469c |
|---|---|
| 1 #### plotlib.r #### | |
| 2 # This contains the library for plotting related functions. | |
| 3 # | |
| 4 # Authors: Li Shen, Ningyi Shao | |
| 5 # | |
| 6 # Created: Feb 19, 2013 | |
| 7 # Last updated: May 21, 2013 | |
| 8 # | |
| 9 | |
| 10 SetupHeatmapDevice <- function(reg.list, uniq.reg, ng.list, pts, font.size=12, | |
| 11 unit.width=4, reduce.ratio=30) { | |
| 12 # Configure parameters for heatmap output device. The output is used by | |
| 13 # external procedures to setup pdf device ready for heatmap plotting. | |
| 14 # Args: | |
| 15 # reg.list: region list as in config file. | |
| 16 # uniq.reg: unique region list. | |
| 17 # ng.list: number of genes per heatmap in the order as config file. | |
| 18 # pts: data points (number of columns of heatmaps). | |
| 19 # font.size: font size. | |
| 20 # unit.width: image width per heatmap. | |
| 21 # reduce.ratio: how compressed are genes in comparison to data points? This | |
| 22 # controls image height. | |
| 23 | |
| 24 # Number of plots per region. | |
| 25 reg.np <- sapply(uniq.reg, function(r) sum(reg.list==r)) | |
| 26 | |
| 27 # Number of genes per region. | |
| 28 reg.ng <- sapply(uniq.reg, function(r) { | |
| 29 ri <- which(reg.list==r)[1] | |
| 30 ng.list[ri] | |
| 31 }) | |
| 32 | |
| 33 # Adjustment ratio. | |
| 34 origin.fs <- 12 # default font size. | |
| 35 fs.adj.ratio <- font.size / origin.fs | |
| 36 # Margin size (in lines) adjusted by ratio. | |
| 37 m.bot <- fs.adj.ratio * 2 | |
| 38 m.lef <- fs.adj.ratio * 1.5 | |
| 39 m.top <- fs.adj.ratio * 2 | |
| 40 m.rig <- fs.adj.ratio * 1.5 | |
| 41 key.in <- fs.adj.ratio * 1.0 # colorkey in inches. | |
| 42 m.lef.diff <- (fs.adj.ratio - 1) * 1.5 | |
| 43 m.rig.diff <- (fs.adj.ratio - 1) * 1.5 | |
| 44 # Setup image size. | |
| 45 hm.width <- (unit.width + m.lef.diff + m.rig.diff) * max(reg.np) | |
| 46 ipl <- .2 # inches per line. Obtained from par->'mai', 'mar'. | |
| 47 # Convert #gene to image height. | |
| 48 reg.hei <- sapply(reg.ng, function(r) { | |
| 49 c(key.in, # colorkey + margin. | |
| 50 r * unit.width / pts / reduce.ratio + | |
| 51 m.bot * ipl + m.top * ipl) # heatmap + margin. | |
| 52 }) | |
| 53 reg.hei <- c(reg.hei) | |
| 54 hm.height <- sum(reg.hei) | |
| 55 | |
| 56 # Setup layout of the heatmaps. | |
| 57 lay.mat <- matrix(0, ncol=max(reg.np), nrow=length(reg.np) * 2) | |
| 58 fig.n <- 1 # figure plotting number. | |
| 59 for(i in 1:length(reg.np)) { | |
| 60 row.upper <- i * 2 - 1 | |
| 61 row.lower <- i * 2 | |
| 62 for(j in 1:reg.np[i]) { | |
| 63 lay.mat[row.upper, j] <- fig.n; | |
| 64 fig.n <- fig.n + 1 | |
| 65 lay.mat[row.lower, j] <- fig.n; | |
| 66 fig.n <- fig.n + 1 | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 list(reg.hei=reg.hei, hm.width=hm.width, hm.height=hm.height, | |
| 71 lay.mat=lay.mat, heatmap.mar=c(m.bot, m.lef, m.top, m.rig) * ipl) | |
| 72 } | |
| 73 | |
| 74 SetPtsSpline <- function(pint, lgint) { | |
| 75 # Set data points for spline function. | |
| 76 # Args: | |
| 77 # pint: tag for point interval. | |
| 78 # Return: list of data points, middle data points, flanking data points. | |
| 79 | |
| 80 pts <- 100 # data points to plot: 0...pts | |
| 81 if(pint){ # point interval. | |
| 82 m.pts <- 1 # middle part points. | |
| 83 f.pts <- pts / 2 # flanking part points. | |
| 84 } else { | |
| 85 if(lgint) { | |
| 86 m.pts <- pts / 5 * 3 + 1 | |
| 87 f.pts <- pts / 5 + 1 | |
| 88 } else { | |
| 89 m.pts <- pts / 5 + 1 | |
| 90 f.pts <- pts / 5 * 2 + 1 | |
| 91 } | |
| 92 } | |
| 93 list(pts=pts, m.pts=m.pts, f.pts=f.pts) | |
| 94 } | |
| 95 | |
| 96 CreatePlotMat <- function(pts, ctg.tbl) { | |
| 97 # Create matrix for avg. profiles. | |
| 98 # Args: | |
| 99 # pts: data points. | |
| 100 # ctg.tbl: configuration table. | |
| 101 # Return: avg. profile matrix initialized to zero. | |
| 102 | |
| 103 regcovMat <- matrix(0, nrow=pts + 1, ncol=nrow(ctg.tbl)) | |
| 104 colnames(regcovMat) <- ctg.tbl$title | |
| 105 regcovMat | |
| 106 } | |
| 107 | |
| 108 CreateConfiMat <- function(se, pts, ctg.tbl){ | |
| 109 # Create matrix for standard errors. | |
| 110 # Args: | |
| 111 # se: tag for standard error plotting. | |
| 112 # pts: data points. | |
| 113 # ctg.tbl: configuration table. | |
| 114 # Return: standard error matrix initialized to zero or null. | |
| 115 | |
| 116 if(se){ | |
| 117 confiMat <- matrix(0, nrow=pts + 1, ncol=nrow(ctg.tbl)) | |
| 118 colnames(confiMat) <- ctg.tbl$title | |
| 119 } else { | |
| 120 confiMat <- NULL | |
| 121 } | |
| 122 confiMat | |
| 123 } | |
| 124 | |
| 125 col2alpha <- function(col2use, alpha){ | |
| 126 # Convert a vector of solid colors to semi-transparent colors. | |
| 127 # Args: | |
| 128 # col2use: vector of colors. | |
| 129 # alpha: represents degree of opacity - [0,1] | |
| 130 # Return: vector of transformed colors. | |
| 131 | |
| 132 apply(col2rgb(col2use), 2, function(x){ | |
| 133 rgb(x[1], x[2], x[3], alpha=alpha*255, maxColorValue=255) | |
| 134 }) | |
| 135 } | |
| 136 | |
| 137 smoothvec <- function(v, radius, method=c('mean', 'median')){ | |
| 138 # Given a vector of coverage, return smoothed version of coverage. | |
| 139 # Args: | |
| 140 # v: vector of coverage | |
| 141 # radius: fraction of org. vector size. | |
| 142 # method: smooth method | |
| 143 # Return: vector of smoothed coverage. | |
| 144 | |
| 145 stopifnot(is.vector(v)) | |
| 146 stopifnot(length(v) > 0) | |
| 147 stopifnot(radius > 0 && radius < 1) | |
| 148 | |
| 149 halfwin <- ceiling(length(v) * radius) | |
| 150 s <- rep(NA, length(v)) | |
| 151 | |
| 152 for(i in 1:length(v)){ | |
| 153 winpos <- (i - halfwin) : (i + halfwin) | |
| 154 winpos <- winpos[winpos > 0 & winpos <= length(v)] | |
| 155 if(method == 'mean'){ | |
| 156 s[i] <- mean(v[winpos]) | |
| 157 }else if(method == 'median'){ | |
| 158 s[i] <- median(v[winpos]) | |
| 159 } | |
| 160 } | |
| 161 s | |
| 162 } | |
| 163 | |
| 164 smoothplot <- function(m, radius, method=c('mean', 'median')){ | |
| 165 # Smooth the entire avg. profile matrix using smoothvec. | |
| 166 # Args: | |
| 167 # m: avg. profile matrix | |
| 168 # radius: fraction of org. vector size. | |
| 169 # method: smooth method. | |
| 170 # Return: smoothed matrix. | |
| 171 | |
| 172 stopifnot(is.matrix(m) || is.vector(m)) | |
| 173 | |
| 174 if(is.matrix(m)) { | |
| 175 for(i in 1:ncol(m)) { | |
| 176 m[, i] <- smoothvec(m[, i], radius, method) | |
| 177 } | |
| 178 } else { | |
| 179 m <- smoothvec(m, radius, method) | |
| 180 } | |
| 181 m | |
| 182 } | |
| 183 | |
| 184 genXticks <- function(reg2plot, pint, lgint, pts, flanksize, flankfactor, | |
| 185 Labs) { | |
| 186 # Generate X-ticks for plotting. | |
| 187 # Args: | |
| 188 # reg2plot: string representation of region. | |
| 189 # pint: point interval. | |
| 190 # lgint: tag for large interval. | |
| 191 # pts: data points. | |
| 192 # flanksize: flanking region size in bps. | |
| 193 # flankfactor: flanking region factor. | |
| 194 # Labs: character vector of labels of the genomic region. | |
| 195 # Return: list of x-tick position and label. | |
| 196 | |
| 197 if(pint){ # point interval. | |
| 198 mid.lab <- Labs[1] | |
| 199 tick.pos <- c(0, pts / 4, pts / 2, pts / 4 * 3, pts) | |
| 200 tick.lab <- as.character(c(-flanksize, -flanksize/2, mid.lab, | |
| 201 flanksize/2, flanksize)) | |
| 202 }else{ | |
| 203 left.lab <- Labs[1] | |
| 204 right.lab <- Labs[2] | |
| 205 tick.pos <- c(0, pts / 5, pts / 5 * 2, pts / 5 * 3, pts / 5 * 4, pts) | |
| 206 if(lgint){ # large interval: fla int int int fla | |
| 207 if(flankfactor > 0){ # show percentage at x-tick. | |
| 208 tick.lab <- c(sprintf("%d%%", -flankfactor*100), | |
| 209 left.lab, '33%', '66%', right.lab, | |
| 210 sprintf("%d%%", flankfactor*100)) | |
| 211 } else{ # show bps at x-tick. | |
| 212 tick.lab <- c(as.character(-flanksize), | |
| 213 left.lab, '33%', '66%', right.lab, | |
| 214 as.character(flanksize)) | |
| 215 } | |
| 216 } else { # small interval: fla fla int fla fla. | |
| 217 if(flankfactor > 0){ | |
| 218 tick.lab <- c(sprintf("%d%%", -flankfactor*100), | |
| 219 sprintf("%d%%", -flankfactor*50), | |
| 220 left.lab, right.lab, | |
| 221 sprintf("%d%%", flankfactor*50), | |
| 222 sprintf("%d%%", flankfactor*100)) | |
| 223 } else { | |
| 224 tick.lab <- c(as.character(-flanksize), | |
| 225 as.character(-flanksize/2), | |
| 226 left.lab, right.lab, | |
| 227 as.character(flanksize/2), | |
| 228 as.character(flanksize)) | |
| 229 } | |
| 230 } | |
| 231 } | |
| 232 list(pos=tick.pos, lab=tick.lab) | |
| 233 } | |
| 234 | |
| 235 plotmat <- function(regcovMat, title2plot, plot.colors, bam.pair, xticks, | |
| 236 pts, m.pts, f.pts, pint, shade.alp=0, confiMat=NULL, mw=1, | |
| 237 misc.options=list(yscale='auto', legend=T, box=T, vline=T, | |
| 238 xylab=T, line.wd=3)) { | |
| 239 # Plot avg. profiles and standard errors around them. | |
| 240 # Args: | |
| 241 # regcovMat: matrix for avg. profiles. | |
| 242 # title2plot: profile names, will be shown in figure legend. | |
| 243 # plot.colors: vector of color specifications for all curves. | |
| 244 # bam.pair: boolean for bam-pair data. | |
| 245 # xticks: X-axis ticks. | |
| 246 # pts: data points | |
| 247 # m.pts: middle part data points | |
| 248 # f.pts: flanking part data points | |
| 249 # pint: tag for point interval | |
| 250 # shade.alp: shading area alpha | |
| 251 # confiMat: matrix for standard errors. | |
| 252 # mw: moving window size for smoothing function. | |
| 253 # misc.options: list of misc. options - y-axis scale, legend, box around plot, | |
| 254 # verticle lines, X- and Y-axis labels, line width. | |
| 255 | |
| 256 # Smooth avg. profiles if specified. | |
| 257 if(mw > 1){ | |
| 258 regcovMat <- as.matrix(runmean(regcovMat, k=mw, alg='C', | |
| 259 endrule='mean')) | |
| 260 } | |
| 261 | |
| 262 # Choose colors. | |
| 263 if(any(is.na(plot.colors))) { | |
| 264 ncurve <- ncol(regcovMat) | |
| 265 if(ncurve <= 8) { | |
| 266 suppressMessages(require(RColorBrewer, warn.conflicts=F)) | |
| 267 col2use <- brewer.pal(ifelse(ncurve >= 3, ncurve, 3), 'Dark2') | |
| 268 col2use <- col2use[1:ncurve] | |
| 269 } else { | |
| 270 col2use <- rainbow(ncurve) | |
| 271 } | |
| 272 } else { | |
| 273 col2use <- plot.colors | |
| 274 } | |
| 275 col2use <- col2alpha(col2use, 0.8) | |
| 276 | |
| 277 # Plot profiles. | |
| 278 ytext <- ifelse(bam.pair, "log2(Fold change vs. control)", | |
| 279 "Read count Per Million mapped reads") | |
| 280 xrange <- 0:pts | |
| 281 y.lim <- NULL | |
| 282 if(length(misc.options$yscale) == 2) { | |
| 283 y.lim <- misc.options$yscale | |
| 284 } | |
| 285 matplot(xrange, regcovMat, | |
| 286 xaxt='n', type="l", col=col2use, ylim=y.lim, | |
| 287 lty="solid", lwd=misc.options$line.wd, frame.plot=F, ann=F) | |
| 288 if(misc.options$xylab) { | |
| 289 title(xlab="Genomic Region (5' -> 3')", ylab=ytext) | |
| 290 } | |
| 291 axis(1, at=xticks$pos, labels=xticks$lab, lwd=3, lwd.ticks=3) | |
| 292 if(misc.options$box) { | |
| 293 # box around plot. | |
| 294 box() | |
| 295 } | |
| 296 | |
| 297 # Add shade area. | |
| 298 if(shade.alp > 0){ | |
| 299 for(i in 1:ncol(regcovMat)){ | |
| 300 v.x <- c(xrange[1], xrange, xrange[length(xrange)]) | |
| 301 v.y <- regcovMat[, i] | |
| 302 v.y <- c(0, v.y, 0) | |
| 303 col.rgb <- col2rgb(col2use[i]) | |
| 304 p.col <- rgb(col.rgb[1, 1], col.rgb[2, 1], col.rgb[3, 1], | |
| 305 alpha=shade.alp * 255, maxColorValue=255) | |
| 306 polygon(v.x, v.y, density=-1, border=NA, col=p.col) | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 # Add standard errors. | |
| 311 if(!is.null(confiMat)){ | |
| 312 v.x <- c(xrange, rev(xrange)) | |
| 313 for(i in 1:ncol(confiMat)){ | |
| 314 v.y <- c(regcovMat[, i] + confiMat[, i], | |
| 315 rev(regcovMat[, i] - confiMat[, i])) | |
| 316 col.rgb <- col2rgb(col2use[i]) | |
| 317 p.col <- rgb(col.rgb[1, 1], col.rgb[2, 1], col.rgb[3, 1], | |
| 318 alpha=0.2 * 255, maxColorValue=255) | |
| 319 polygon(v.x, v.y, density=-1, border=NA, col=p.col) | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 if(misc.options$vline) { | |
| 324 # Add gray lines indicating feature boundaries. | |
| 325 if(pint) { | |
| 326 abline(v=f.pts, col="gray", lwd=2) | |
| 327 } else { | |
| 328 abline(v=f.pts - 1, col="gray", lwd=2) | |
| 329 abline(v=f.pts + m.pts - 2, col="gray", lwd=2) | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 if(misc.options$legend) { | |
| 334 # Legend. | |
| 335 legend("topright", title2plot, text.col=col2use) | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 spline_mat <- function(mat, n=100){ | |
| 340 # Calculate splined coverage for a matrix. | |
| 341 # Args: | |
| 342 # mat: each column represents a profile to be interpolated. | |
| 343 # n: number of data points to be interpolated. | |
| 344 | |
| 345 foreach(r=iter(mat, by='row'), | |
| 346 .combine='rbind', .multicombine=T) %dopar% { | |
| 347 spline(1:length(r), r, n)$y | |
| 348 } | |
| 349 } | |
| 350 | |
| 351 RankNormalizeMatrix <- function(mat, low.cutoff) { | |
| 352 # Rank-based normalization for a data matrix. | |
| 353 # Args: | |
| 354 # mat: data matrix. | |
| 355 # low.cutoff: low value cutoff. | |
| 356 # Return: rank normalized matrix. | |
| 357 | |
| 358 stopifnot(is.matrix(mat)) | |
| 359 | |
| 360 concat.dat <- c(mat) | |
| 361 low.mask <- concat.dat < low.cutoff | |
| 362 concat.r <- rank(concat.dat) | |
| 363 concat.r[low.mask] <- 0 | |
| 364 | |
| 365 matrix(concat.r, nrow=nrow(mat)) | |
| 366 } | |
| 367 | |
| 368 OrderGenesHeatmap <- function(enrichList, lowCutoffs, | |
| 369 method=c('total', 'max', 'prod', 'diff', 'hc', | |
| 370 'none', 'km'), | |
| 371 go.paras=list(knc=5, max.iter=20, nrs=30)) { | |
| 372 # Order genes with a list of heatmap data. | |
| 373 # Args: | |
| 374 # enrichList: heatmap data in a list. | |
| 375 # lowCutoffs: low count cutoff for normalized count data. | |
| 376 # method: algorithm used to order genes. | |
| 377 # go.paras: gene ordering parameters. | |
| 378 # Returns: a vector of REVERSED gene orders. | |
| 379 # NOTE: due to the design of image function, the order needs to be reversed | |
| 380 # so that the genes will be shown correctly. | |
| 381 | |
| 382 rankList <- mapply(RankNormalizeMatrix, | |
| 383 mat=enrichList, low.cutoff=lowCutoffs, SIMPLIFY=F) | |
| 384 np <- length(enrichList) | |
| 385 | |
| 386 if(method == 'hc') { | |
| 387 rankCombined <- do.call('cbind', rankList) | |
| 388 # Clustering and order genes. | |
| 389 hc <- hclust(dist(rankCombined, method='euclidean'), | |
| 390 method='complete') | |
| 391 memb <- cutree(hc, k = go.paras$knc) | |
| 392 list(rev(hc$order), memb) # reversed! | |
| 393 } else if(method == 'km') { | |
| 394 rankCombined <- do.call('cbind', rankList) | |
| 395 km <- kmeans(rankCombined, centers=go.paras$knc, | |
| 396 iter.max=go.paras$max.iter, nstart=go.paras$nrs) | |
| 397 list(rev(order(km$cluster)), km$cluster) # reversed! | |
| 398 } else if(method == 'total' || method == 'diff' && np == 1) { | |
| 399 list(order(rowSums(rankList[[1]])), NULL) | |
| 400 } else if(method == 'max') { # peak enrichment value of the 1st profile. | |
| 401 list(order(apply(rankList[[1]], 1, max)), NULL) | |
| 402 } else if(method == 'prod') { # product of all profiles. | |
| 403 rs.mat <- sapply(rankList, rowSums) | |
| 404 g.prod <- apply(rs.mat, 1, prod) | |
| 405 list(order(g.prod), NULL) | |
| 406 } else if(method == 'diff' && np > 1) { # difference between 2 profiles. | |
| 407 list(order(rowSums(rankList[[1]]) - rowSums(rankList[[2]])), NULL) | |
| 408 } else if(method == 'none') { # according to the order of input gene list. | |
| 409 # Because the image function draws from bottom to top, the rows are | |
| 410 # reversed to give a more natural look. | |
| 411 list(rev(1:nrow(enrichList[[1]])),NULL) | |
| 412 } else { | |
| 413 # pass. | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 | |
| 418 plotheat <- function(reg.list, uniq.reg, enrichList, v.low.cutoff, go.algo, | |
| 419 go.paras, title2plot, bam.pair, xticks, flood.q=.02, | |
| 420 do.plot=T, hm.color="default", color.distr=.6, | |
| 421 color.scale='local') { | |
| 422 # Plot heatmaps with genes ordered according to some algorithm. | |
| 423 # Args: | |
| 424 # reg.list: factor vector of regions as in configuration. | |
| 425 # uniq.reg: character vector of unique regions. | |
| 426 # enrichList: list of heatmap data. | |
| 427 # v.low.cutoff: low count cutoff for normalized count data. | |
| 428 # go.algo: gene order algorithm. | |
| 429 # go.paras: gene ordering parameters. | |
| 430 # title2plot: title for each heatmap. Same as the legends in avgprof. | |
| 431 # bam.pair: boolean tag for bam-pair. | |
| 432 # xticks: info for X-axis ticks. | |
| 433 # flood.q: flooding percentage. | |
| 434 # do.plot: boolean tag for plotting heatmaps. | |
| 435 # hm.color: string for heatmap colors. | |
| 436 # color.distr: positive number for color distribution. | |
| 437 # color.scale: string for the method to adjust color scale. | |
| 438 # Returns: ordered gene names for each unique region as a list. | |
| 439 | |
| 440 # Setup basic parameters. | |
| 441 ncolor <- 256 | |
| 442 if(bam.pair) { | |
| 443 if(hm.color != "default") { | |
| 444 tri.colors <- unlist(strsplit(hm.color, ':')) | |
| 445 neg.color <- tri.colors[1] | |
| 446 if(length(tri.colors) == 2) { | |
| 447 neu.color <- 'black' | |
| 448 pos.color <- tri.colors[2] | |
| 449 } else { | |
| 450 neu.color <- tri.colors[2] | |
| 451 pos.color <- tri.colors[3] | |
| 452 } | |
| 453 enrich.palette <- colorRampPalette(c(neg.color, neu.color, | |
| 454 pos.color), | |
| 455 bias=color.distr, | |
| 456 interpolate='spline') | |
| 457 } else { | |
| 458 enrich.palette <- colorRampPalette(c('blue', 'black', 'yellow'), | |
| 459 bias=color.distr, | |
| 460 interpolate='spline') | |
| 461 } | |
| 462 } else { | |
| 463 if(hm.color != "default") { | |
| 464 enrich.palette <- colorRampPalette(c('snow', hm.color)) | |
| 465 } else { | |
| 466 enrich.palette <- colorRampPalette(c('snow', 'red2')) | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 hm_cols <- ncol(enrichList[[1]]) | |
| 471 | |
| 472 # Adjust X-axis tick position. In a heatmap, X-axis is [0, 1]. | |
| 473 # Assume xticks$pos is from 0 to N(>0). | |
| 474 xticks$pos <- xticks$pos / tail(xticks$pos, n=1) # scale to the same size. | |
| 475 | |
| 476 # Define a function to calculate color breaks. | |
| 477 ColorBreaks <- function(max.e, min.e, bam.pair, ncolor) { | |
| 478 # Args: | |
| 479 # max.e: maximum enrichment value to be mapped to color. | |
| 480 # min.e: minimum enrichment value to be mapped to color. | |
| 481 # bam.pair: boolean tag for bam-pair. | |
| 482 # ncolor: number of colors to use. | |
| 483 # Returns: vector of color breaks. | |
| 484 | |
| 485 # If bam-pair is used, create breaks for positives and negatives | |
| 486 # separately. If log2 ratios are all positive or negative, use only | |
| 487 # half of the color space. | |
| 488 if(bam.pair) { | |
| 489 max.e <- ifelse(max.e > 0, max.e, 1) | |
| 490 min.e <- ifelse(min.e < 0, min.e, -1) | |
| 491 c(seq(min.e, 0, length.out=ncolor / 2 + 1), | |
| 492 seq(0, max.e, length.out=ncolor / 2 + 1)[-1]) | |
| 493 } else { | |
| 494 seq(min.e, max.e, length.out=ncolor + 1) | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 if(grepl(",", color.scale)) { | |
| 499 scale.pair <- unlist(strsplit(color.scale, ",")) | |
| 500 scale.min <- as.numeric(scale.pair[1]) | |
| 501 scale.max <- as.numeric(scale.pair[2]) | |
| 502 if(scale.min >= scale.max) { | |
| 503 warning("Color scale min value is >= max value.\n") | |
| 504 } | |
| 505 flood.pts <- c(scale.min, scale.max) | |
| 506 brk.use <- ColorBreaks(scale.max, scale.min, bam.pair, ncolor) | |
| 507 } | |
| 508 | |
| 509 # If color scale is global, calculate breaks and quantile here. | |
| 510 if(color.scale == 'global') { | |
| 511 flood.pts <- quantile(c(enrichList, recursive=T), c(flood.q, 1-flood.q)) | |
| 512 brk.use <- ColorBreaks(flood.pts[2], flood.pts[1], bam.pair, ncolor) | |
| 513 } | |
| 514 | |
| 515 # Go through each unique region. | |
| 516 # Do NOT use "dopar" in the "foreach" loops here because this will disturb | |
| 517 # the image order. | |
| 518 go.list <- vector('list', length(uniq.reg)) | |
| 519 go.cluster <- vector('list', length(uniq.reg)) | |
| 520 | |
| 521 names(go.list) <- uniq.reg | |
| 522 names(go.cluster) <- uniq.reg | |
| 523 | |
| 524 for(ur in uniq.reg) { | |
| 525 # ur <- uniq.reg[i] | |
| 526 plist <- which(reg.list==ur) # get indices in the config file. | |
| 527 | |
| 528 # Combine all profiles into one. | |
| 529 # enrichCombined <- do.call('cbind', enrichList[plist]) | |
| 530 enrichSelected <- enrichList[plist] | |
| 531 | |
| 532 # If color scale is region, calculate breaks and quantile here. | |
| 533 if(color.scale == 'region') { | |
| 534 flood.pts <- quantile(c(enrichSelected, recursive=T), | |
| 535 c(flood.q, 1-flood.q)) | |
| 536 brk.use <- ColorBreaks(flood.pts[2], flood.pts[1], bam.pair, ncolor) | |
| 537 } | |
| 538 | |
| 539 # Order genes. | |
| 540 if(is.matrix(enrichSelected[[1]]) && nrow(enrichSelected[[1]]) > 1) { | |
| 541 if(bam.pair) { | |
| 542 lowCutoffs <- 0 | |
| 543 } else { | |
| 544 lowCutoffs <- v.low.cutoff[plist] | |
| 545 } | |
| 546 g.order.list <- OrderGenesHeatmap(enrichSelected, lowCutoffs, | |
| 547 go.algo, go.paras) | |
| 548 g.order <- g.order.list[[1]] | |
| 549 g.cluster <- g.order.list[[2]] | |
| 550 if(is.null(g.cluster)) { | |
| 551 go.cluster[[ur]] <- NA | |
| 552 } else{ | |
| 553 go.cluster[[ur]] <- rev(g.cluster[g.order]) | |
| 554 } | |
| 555 go.list[[ur]] <- rev(rownames(enrichSelected[[1]][g.order, ])) | |
| 556 } else { | |
| 557 go.cluster[[ur]] <- NULL | |
| 558 go.list[[ur]] <- NULL | |
| 559 } | |
| 560 | |
| 561 if(!do.plot) { | |
| 562 next | |
| 563 } | |
| 564 | |
| 565 # Go through each sample and do plot. | |
| 566 for(pj in plist) { | |
| 567 if(!is.null(g.order)) { | |
| 568 enrichList[[pj]] <- enrichList[[pj]][g.order, ] | |
| 569 } | |
| 570 | |
| 571 # If color scale is local, calculate breaks and quantiles here. | |
| 572 if(color.scale == 'local') { | |
| 573 flood.pts <- quantile(c(enrichList[[pj]], recursive=T), | |
| 574 c(flood.q, 1-flood.q)) | |
| 575 brk.use <- ColorBreaks(flood.pts[2], flood.pts[1], bam.pair, | |
| 576 ncolor) | |
| 577 } | |
| 578 | |
| 579 # Flooding extreme values. | |
| 580 enrichList[[pj]][ enrichList[[pj]] < flood.pts[1] ] <- flood.pts[1] | |
| 581 enrichList[[pj]][ enrichList[[pj]] > flood.pts[2] ] <- flood.pts[2] | |
| 582 | |
| 583 # Draw colorkey. | |
| 584 image(z=matrix(brk.use, ncol=1), col=enrich.palette(ncolor), | |
| 585 breaks=brk.use, axes=F, useRaster=T, main='Colorkey') | |
| 586 axis(1, at=seq(0, 1, length.out=5), | |
| 587 labels=format(brk.use[seq(1, ncolor + 1, length.out=5)], | |
| 588 digits=1), | |
| 589 lwd=1, lwd.ticks=1) | |
| 590 | |
| 591 # Draw heatmap. | |
| 592 image(z=t(enrichList[[pj]]), col=enrich.palette(ncolor), | |
| 593 breaks=brk.use, axes=F, useRaster=T, main=title2plot[pj]) | |
| 594 | |
| 595 axis(1, at=xticks$pos, labels=xticks$lab, lwd=1, lwd.ticks=1) | |
| 596 } | |
| 597 } | |
| 598 list(go.list,go.cluster) | |
| 599 } | |
| 600 | |
| 601 trim <- function(x, p){ | |
| 602 # Trim a numeric vector on both ends. | |
| 603 # Args: | |
| 604 # x: numeric vector. | |
| 605 # p: percentage of data to trim. | |
| 606 # Return: trimmed vector. | |
| 607 | |
| 608 low <- quantile(x, p) | |
| 609 hig <- quantile(x, 1 - p) | |
| 610 x[x > low & x < hig] | |
| 611 } | |
| 612 | |
| 613 CalcSem <- function(x, rb=.05){ | |
| 614 # Calculate standard error of mean for a numeric vector. | |
| 615 # Args: | |
| 616 # x: numeric vector | |
| 617 # rb: fraction of data to trim before calculating sem. | |
| 618 # Return: a scalar of the standard error of mean | |
| 619 | |
| 620 if(rb > 0){ | |
| 621 x <- trim(x, rb) | |
| 622 } | |
| 623 sem <- sd(x) / sqrt(length(x)) | |
| 624 ifelse(is.na(sem), 0, sem) | |
| 625 # NOTE: this should be improved to handle exception that "sd" calculation | |
| 626 # emits errors. | |
| 627 } | |
| 628 | |
| 629 | |
| 630 | |
| 631 | |
| 632 ## Leave for future reference. | |
| 633 # | |
| 634 # Set the antialiasing. | |
| 635 # type <- NULL | |
| 636 # if (capabilities()["aqua"]) { | |
| 637 # type <- "quartz" | |
| 638 # } else if (capabilities()["cairo"]) { | |
| 639 # type <- "cairo" | |
| 640 # } else if (capabilities()["X11"]) { | |
| 641 # type <- "Xlib" | |
| 642 # } | |
| 643 # Set the output type based on capabilities. | |
| 644 # if (is.null(type)){ | |
| 645 # png(plot.name, width, height, pointsize=pointsize) | |
| 646 | |
| 647 # } else { | |
| 648 # png(plot.name, width, height, pointsize=pointsize, type=type) | |
| 649 # } |
