diff --git a/R/gisticOncoPlot.R b/R/gisticOncoPlot.R index 4dd1071..7c7e0e3 100644 --- a/R/gisticOncoPlot.R +++ b/R/gisticOncoPlot.R @@ -39,7 +39,7 @@ gisticOncoPlot = function(gistic = NULL, top = NULL, bands = NULL, - showTumorSampleBarcodes = FALSE, gene_mar = 5, barcode_mar = 6, sepwd_genes = 0.5, sepwd_samples = 0.25, clinicalData = NULL, clinicalFeatures = NULL, sortByAnnotation = FALSE, sampleOrder = NULL, + showTumorSampleBarcodes = FALSE, gene_mar = 5, barcode_mar = 6, right_mar = 2.5, sepwd_genes = 0.5, sepwd_samples = 0.25, clinicalData = NULL, clinicalFeatures = NULL, sortByAnnotation = FALSE, sampleOrder = NULL, annotationColor = NULL, bandsToIgnore = NULL, removeNonAltered = TRUE, colors = NULL, SampleNamefontSize = 0.6, fontSize = 0.8, legendFontSize = 1.2, annotationFontSize = 1.2, borderCol = "white", bgCol = "#CCCCCC") { @@ -133,15 +133,15 @@ gisticOncoPlot = function(gistic = NULL, top = NULL, bands = NULL, if(is.null(clinicalFeatures)){ if(showTumorSampleBarcodes){ - par(mar = c(barcode_mar, gene_mar, 1, 2.5), xpd = TRUE) + par(mar = c(barcode_mar, gene_mar, 1, right_mar), xpd = TRUE) }else{ - par(mar = c(0.5, gene_mar, 1, 2.5), xpd = TRUE) + par(mar = c(0.5, gene_mar, 1, right_mar), xpd = TRUE) } }else{ if(showTumorSampleBarcodes){ - par(mar = c(barcode_mar, gene_mar, 1, 5), xpd = TRUE) + par(mar = c(barcode_mar, gene_mar, 1, right_mar), xpd = TRUE) }else{ - par(mar = c(0.5, gene_mar, 1, 5), xpd = TRUE) + par(mar = c(0.5, gene_mar, 1, right_mar), xpd = TRUE) } } @@ -207,7 +207,7 @@ gisticOncoPlot = function(gistic = NULL, top = NULL, bands = NULL, annotation = annotation[colnames(numMat), ncol(annotation):1, drop = FALSE] - par(mar = c(0, gene_mar, 0, 5), xpd = TRUE) + par(mar = c(0, gene_mar, 0, right_mar), xpd = TRUE) image(x = 1:nrow(annotation), y = 1:ncol(annotation), z = as.matrix(annotation), axes = FALSE, xaxt="n", yaxt="n", bty = "n", diff --git a/R/oncomatrix.R b/R/oncomatrix.R index d825826..67338c0 100644 --- a/R/oncomatrix.R +++ b/R/oncomatrix.R @@ -167,6 +167,7 @@ sortByAnnotation <-function(numMat,maf, anno, annoOrder = NULL, group = TRUE, is #anno.spl = split(anno, as.numeric(as.character(anno[,1]))) #sorting only first annotation mat_samps = colnames(numMat)[colnames(numMat) %in% rownames(anno)] anno = anno[mat_samps,, drop = FALSE] + anno[,1] = as.numeric(as.character(anno[,1])) anno = anno[order(anno[,1], na.last = TRUE),, drop = FALSE] numMat.sorted = numMat[,rownames(anno)] }else{ @@ -575,19 +576,24 @@ parse_annotation_dat = function(annotationDat = NULL, clinicalFeatures = NULL){ return(annotation) } -get_anno_cols = function(ann, numericAnnoCol = NULL){ +get_anno_cols = function(ann, numericAnnoCol = "YlOrBr"){ ann_cols = list() - if(is.null(numericAnnoCol)){ - numericAnnoCol = RColorBrewer::brewer.pal(n = 9, name = "YlOrBr") - }else{ - numericAnnoCol = RColorBrewer::brewer.pal(n = 9, name = numericAnnoCol) - } + col_class = c() + for(i in 1:ncol(ann)){ if(is.numeric(ann[,i])){ - x = ann[,i] - ann_lvls_cols = colorRampPalette(numericAnnoCol)(length(x)) - names(ann_lvls_cols) = x[order(x, na.last = TRUE)] + x = as.numeric(as.character(ann[,i])) + x_unique = unique(x) + numericAnnoCol = sample(x = c("Blues", "BuGn", "BuPu", "GnBu", "Greens", "Greys", "Oranges", + "OrRd", "PuBu", "PuBuGn", "PuRd", "Purples", "RdPu", "Reds", + "YlGn", "YlGnBu", "YlOrBr", "YlOrRd"), size = 1) + #message("Using ", numericAnnoCol) + numericAnnoCol = RColorBrewer::brewer.pal(n = 9, name = numericAnnoCol) + ann_lvls_cols = colorRampPalette(numericAnnoCol)(length(x_unique)) + names(ann_lvls_cols) = x_unique[order(x_unique, na.last = TRUE)] + ann_lvls_cols = ann_lvls_cols[as.character(x)] ann_cols[[i]] = ann_lvls_cols + col_class = c(col_class, "numeric") }else{ ann_lvls = unique(as.character(ann[,i])) if(length(ann_lvls) <= 9){ @@ -595,12 +601,15 @@ get_anno_cols = function(ann, numericAnnoCol = NULL){ }else{ ann_lvls_cols = colors()[sample(x = 1:100, size = length(ann_lvls), replace = FALSE)] } + names(ann_lvls_cols) = ann_lvls + ann_lvls_cols = ann_lvls_cols[as.character(ann[,i])] ann_cols[[i]] = ann_lvls_cols - names(ann_cols[[i]]) = ann_lvls + col_class = c(col_class, "char") } } names(ann_cols) = colnames(ann) + attr(ann_cols, "class") = col_class return(ann_cols) } diff --git a/R/oncoplot.R b/R/oncoplot.R index e34cb17..b7c6950 100644 --- a/R/oncoplot.R +++ b/R/oncoplot.R @@ -962,55 +962,55 @@ oncoplot = oncoplot = function(maf, top = 20, minMut = NULL, genes = NULL, alter #06: Plot annotations if any if(!is.null(clinicalFeatures)){ - #clini_lvls = as.character(unlist(lapply(annotation, function(x) unique(as.character(x))))) - clini_lvls = lapply(annotation, function(x) unique(as.character(x))) + annotation = annotation[colnames(numMat), ncol(annotation):1, drop = FALSE] if(is.null(annotationColor)){ + #In case no-color codes are provided annotationColor = get_anno_cols(ann = annotation) - } - annotationColor = annotationColor[colnames(annotation)] - - annotationColor = lapply(annotationColor, function(x) { - na_idx = which(is.na(names(x))) - x[na_idx] = "gray70" - names(x)[na_idx] = "NA" - x - }) - - anno_cols = c() - for(i in 1:length(annotationColor)){ - anno_cols = c(anno_cols, annotationColor[[i]]) - } - - #clini_lvls = clini_lvls[!is.na(clini_lvls)] - clini_lvls = lapply(clini_lvls, function(cl){ - temp_names = suppressWarnings(sample( - x = setdiff(x = 1:1000, y = as.numeric(as.character(cl))), - size = length(cl), - replace = FALSE - )) - names(cl) = temp_names#1:length(clini_lvls) - cl - }) + }else{ + #If provided - generate a continuous palette for continuous variables + annotationColor = annotationColor[colnames(annotation)] + + annotationColor_temp = lapply(seq_along(annotationColor), function(idx){ + if(is.numeric(annotation[,idx])){ + #print(annotationColor[[idx]]) + seq_col_pal = c("Blues", "BuGn", "BuPu", "GnBu", "Greens", "Greys", "Oranges", + "OrRd", "PuBu", "PuBuGn", "PuRd", "Purples", "RdPu", "Reds", + "YlGn", "YlGnBu", "YlOrBr", "YlOrRd") + col_match = annotationColor[idx] %in% seq_col_pal + + if(!col_match){ + stop("numeric annotation color for ", names(annotationColor)[idx] , " must be a sequential color palette!\n", paste(seq_col_pal, collapse = " ")) + } + x = annotation[,idx] + x_unique = unique(x) + numericAnnoCol = RColorBrewer::brewer.pal(n = 9, name = annotationColor[[idx]]) + ann_lvls_cols = colorRampPalette(numericAnnoCol)(length(x_unique)) + names(ann_lvls_cols) = x_unique[order(x_unique, na.last = TRUE)] + ann_lvls_cols = ann_lvls_cols[as.character(x)] + }else{ + ann_lvls_cols = annotationColor[[idx]] + ann_lvls_cols = ann_lvls_cols[as.character(annotation[,idx])] + } + ann_lvls_cols + }) + names(annotationColor_temp) = names(annotationColor) - temp_rownames = rownames(annotation) - annotation = data.frame(lapply(annotation, as.character), - stringsAsFactors = FALSE, row.names = temp_rownames) - - annotation_color_coded = data.frame(row.names = rownames(annotation), stringsAsFactors = FALSE) - for(i in 1:length(clini_lvls)){ - cl = clini_lvls[[i]] - clname = names(clini_lvls)[i] - cl_vals = annotation[,clname] #values in column - for(i in 1:length(cl)){ - cl_vals[cl_vals == cl[i]] = names(cl[i]) + #dirty way to check which columns are of numeric + temp_col_class = c() + for(i in 1:ncol(annotation)){ + if(is.numeric(annotation[,i])){ + temp_col_class = c(temp_col_class, "numeric") + }else{ + temp_col_class = c(temp_col_class, "char") + } } - annotation_color_coded = cbind(annotation_color_coded, cl_vals, stringsAsFactors = FALSE) + annotationColor = annotationColor_temp + attr(annotationColor, "class") = temp_col_class } - names(annotation_color_coded) = names(clini_lvls) - annotation = data.frame(lapply(annotation_color_coded, as.numeric), stringsAsFactors=FALSE, row.names = temp_rownames) - annotation = annotation[colnames(numMat), ncol(annotation):1, drop = FALSE] + ann_classes = attributes(annotationColor)$class + #return(list(annotation, annotationColor)) if(!is.null(leftBarData)){ plot.new() @@ -1022,40 +1022,43 @@ oncoplot = oncoplot = function(maf, top = 20, minMut = NULL, genes = NULL, alter par(mar = c(0, gene_mar, 0, 3), xpd = TRUE) } - image(x = 1:nrow(annotation), y = 1:ncol(annotation), z = as.matrix(annotation), + image(x = 1:nrow(annotation), y = 1:ncol(annotation), z = matrix(data = 0, nrow = nrow(annotation), ncol = ncol(annotation)), axes = FALSE, xaxt="n", yaxt="n", bty = "n", - xlab="", ylab="", col = "white") #col = "#FC8D62" - - #Plot for all variant classifications - for(i in 1:length(clini_lvls)){ - cl = clini_lvls[[i]] - clnames = names(clini_lvls)[i] - cl_cols = annotationColor[[clnames]] - for(i in 1:length(names(cl))){ - anno_code = cl[i] - col = cl_cols[anno_code] - temp_anno = as.matrix(annotation) - #Handle NA's - if(is.na(col)){ - col = "gray70" - temp_anno[is.na(temp_anno)] = as.numeric(names(anno_code)) - } - temp_anno[temp_anno != names(anno_code)] = NA + xlab="", ylab="", col = "gray90") #col = "#FC8D62" + for(i in 1:ncol(annotation)){ + temp_anno = annotation + + if(ncol(temp_anno) > 1){ + rm_idx = setdiff(y = i, x = 1:ncol(temp_anno)) + temp_anno[,rm_idx] = NA + } + + if(ann_classes[i] == "numeric"){ + temp_anno = apply(temp_anno, 2, as.numeric) suppressWarnings(image(x = 1:nrow(temp_anno), y = 1:ncol(temp_anno), z = temp_anno, - axes = FALSE, xaxt="n", yaxt="n", xlab="", ylab="", col = col, add = TRUE)) + axes = FALSE, xaxt="n", yaxt="n", xlab="", ylab="", col = annotationColor[[i]], add = TRUE)) + }else{ + temp_lvls = unique(names(annotationColor[[i]])) #unique(temp_anno[,i]) + temp_lvls = temp_lvls[complete.cases(temp_lvls)] #Remove NAs + temp_lvls_cols = annotationColor[[i]][temp_lvls] + temp_anno[,i] = match(x = temp_anno[,i], table = unique(temp_lvls), nomatch = NA) + temp_anno = apply(temp_anno, 2, as.numeric) + suppressWarnings(image(x = 1:nrow(temp_anno), y = 1:ncol(temp_anno), z = temp_anno, + axes = FALSE, xaxt="n", yaxt="n", xlab="", ylab="", col = temp_lvls_cols, add = TRUE)) } } - #Add grids - rect(xleft = 0.5, ybottom = (0:(ncol(annotation))) + 0.5, xright = nrow(annotation)+0.5, ytop = (0:(ncol(annotation))) + 0.5, border = annoBorderCol, lwd = 0.7) - abline(v = (0:(nrow(nm))) + 0.5, col = annoBorderCol, lwd = sepwd_samples) - mtext(text = colnames(annotation), side = 4, - font = 1, line = 0.4, cex = fontSize, las = 2, at = 1:ncol(annotation)) + #Add grids + rect(xleft = 0.5, ybottom = (0:(ncol(annotation))) + 0.5, xright = nrow(annotation)+0.5, ytop = (0:(ncol(annotation))) + 0.5, border = annoBorderCol, lwd = 0.7) + abline(v = (0:(nrow(nm))) + 0.5, col = annoBorderCol, lwd = sepwd_samples) + mtext(text = colnames(annotation), side = 4, + font = 1, line = 0.4, cex = fontSize, las = 2, at = 1:ncol(annotation)) + + if(drawRowBar){ + plot.new() + } - if(drawRowBar){ - plot.new() - } } #07: Draw TiTv plot @@ -1161,32 +1164,29 @@ oncoplot = oncoplot = function(maf, top = 20, minMut = NULL, genes = NULL, alter x_axp = 0+lep$rect$w - #print(annotation) - #return(annotationColor) - if(!is.null(clinicalFeatures)){ #Check which of the clinicalFeatures are of numeric - ann_classes = lapply(names(annotationColor), function(ac){ - temp_anno = data.table::copy(maf@clinical.data) - data.table::setDF(temp_anno) - ac_idx = which(colnames(temp_anno) == ac) - is.numeric(temp_anno[,ac_idx]) - }) + ann_classes = attributes(annotationColor)$class num_start = 0.1 #numeric legend starts from here num_width = 0.1 num_incr = 0.2 - for(i in 1:ncol(annotation)){ + for(i in seq_along(ann_classes)){ #x = unique(annotation[,i]) + temp_lvls = unique(names(annotationColor[[i]])) + temp_lvls = temp_lvls[complete.cases(temp_lvls)] + temp_lvls_cols = annotationColor[[i]][temp_lvls] x = annotationColor[[i]] - is_num = ann_classes[[i]] + is_num = ann_classes[i] == "numeric" xt = names(x) if(is_num){ - x_range = as.numeric(names(x)) - x_range = x_range[!is.na(x_range)] - x_range = x_range[!is.infinite(x_range)] - x_range = range(x_range) + xt = as.numeric(xt) + xt = xt[!is.na(xt)] + xt = xt[!is.infinite(xt)] + xt = sort(xt) + x = x[as.character(xt)] + x_range = round(range(xt), 2) image( y = c(0.1, 0.2), @@ -1195,31 +1195,21 @@ oncoplot = oncoplot = function(maf, top = 20, minMut = NULL, genes = NULL, alter col = x, xlim = c(0, 1), ylim = c(0, 1), axes = FALSE, xlab = NA, ylab = NA, add = TRUE ) text(x = c(num_start, num_start+num_width), y = 0.2, labels = x_range, pos = 3) - text(x = num_start+(num_width/2), y = 0.1, labels = clinicalFeatures[i], pos = 1, adj = 1) + text(x = num_start+(num_width/2), y = 0.1, labels = names(annotationColor)[i], pos = 1, adj = 1) num_start = num_start + num_incr }else{ - if("NA" %in% xt){ - xt = xt[!xt %in% "NA"] - xt = sort(xt, decreasing = FALSE) - xt = c(xt, "NA") - x = x[xt] - }else{ - xt = sort(xt, decreasing = FALSE) - x = x[xt] - } - if(length(x) <= 4){ + if(length(temp_lvls_cols) <= 4){ n_col = 1 }else{ - n_col = (length(x) %/% 4)+1 + n_col = (length(temp_lvls_cols) %/% 4)+1 } - names(x)[is.na(names(x))] = "NA" - lep = legend(x = x_axp, y = 1, legend = names(x), - col = x, border = NA, + lep = legend(x = x_axp, y = 1, legend = names(temp_lvls_cols), + col = temp_lvls_cols, border = NA, ncol= n_col, pch = 15, xpd = TRUE, xjust = 0, bty = "n", - cex = annotationFontSize, title = rev(names(annotation))[i], + cex = annotationFontSize, title = names(annotationColor)[i], title.adj = 0) x_axp = x_axp + lep$rect$w @@ -1229,12 +1219,6 @@ oncoplot = oncoplot = function(maf, top = 20, minMut = NULL, genes = NULL, alter n_mut_samps = length(which(colSums(numMat) != 0)) altStat = paste0("Altered in ", n_mut_samps, " (", round(n_mut_samps/totSamps, digits = 4)*100, "%) of ", totSamps, " samples.") - # if(removeNonMutated){ - # #mutSamples = length(unique(unlist(genesToBarcodes(maf = maf, genes = rownames(mat), justNames = TRUE)))) - # }else{ - # mutSamples = length(unique(unlist(genesToBarcodes(maf = maf, genes = rownames(numMat), justNames = TRUE, verbose = FALSE)))) - # altStat = paste0("Altered in ", mutSamples, " (", round(mutSamples/totSamps, digits = 4)*100, "%) of ", totSamps, " samples.") - # } if(showTitle){ if(is.null(titleText)){ diff --git a/R/readSegs.R b/R/readSegs.R index 6c6e64c..128f648 100644 --- a/R/readSegs.R +++ b/R/readSegs.R @@ -160,7 +160,7 @@ plotCBS = function(segData, tsb, build = 'hg19', chr.colors = NULL, y_lims = NUL chr.labels= c(1:22, 'X', 'Y') chr.lvls = levels(seg.spl.transformed[,Chromosome]) - print(chr.colors) + #print(chr.colors) if(is.null(chr.colors)){ chr.colors = c('gray70', 'midnightblue') } @@ -171,6 +171,8 @@ plotCBS = function(segData, tsb, build = 'hg19', chr.colors = NULL, y_lims = NUL data.table::setkey(seg.spl.transformed, "Chromosome") N <- seg.spl.transformed[levels(Chromosome), .N, .EACHI][, N] + colnames(seg.spl.transformed)[1:6] = c("Sample", "Chromosome", "Start_Position", "End_Position", "Num_Probes", "Segment_Mean") + if(is.null(y_lims)){ y_lims = pretty(round(range(seg.spl.transformed$Segment_Mean, na.rm = TRUE, finite = TRUE), digits = 2)) } diff --git a/inst/NEWS.md b/inst/NEWS.md index 87750f4..09ebf24 100644 --- a/inst/NEWS.md +++ b/inst/NEWS.md @@ -9,14 +9,18 @@ - MAJOR: `read.maf` by default coerces clinical data columns to character. This bug fix avoids it and is auto detected. Issue: [997](https://github.com/PoisonAlien/maftools/issues/997) ## ENHANCEMENTS +- Better handling of color codes for continuous variable annotations [1053](https://github.com/PoisonAlien/maftools/issues/1053) +- Add `right_mar` to `gisticOncoPlot`[1043](https://github.com/PoisonAlien/maftools/issues/1043) - Added `PPDPFL` to protein domain database Issue: [1025](https://github.com/PoisonAlien/maftools/issues/1025) - Better sorting of oncoplot with `collapsePathway` - Changed default background for oncoplot from `gray` to `#ecf0f1` - Changed default signature database to SBS_v3.4 (from legacy) -- Update tmb function +- Update `tmb` function + ## NEW FUNCTIONS - `gisticCompare()` for comparing two GISTIC objects +- `segSummarize()` for summarizing DNAcopy segments # CHANGES IN VERSION 2.18.0 (Bioconductor release branch - 2.20.0) diff --git a/man/gisticOncoPlot.Rd b/man/gisticOncoPlot.Rd index bc54d0a..6f54871 100644 --- a/man/gisticOncoPlot.Rd +++ b/man/gisticOncoPlot.Rd @@ -11,6 +11,7 @@ gisticOncoPlot( showTumorSampleBarcodes = FALSE, gene_mar = 5, barcode_mar = 6, + right_mar = 2.5, sepwd_genes = 0.5, sepwd_samples = 0.25, clinicalData = NULL,