Cool, thanks! FYI: I'm pretty sure you want to change the default values for the symbreaks and symkey args to from min(x < 0, na.rm=TRUE) to min(x, na.rm=TRUE) < 0, no?
I often use heatmap.2 {gplots} because of its many improvements/options over the standard heatmap function. However, occasionally I require multiple color side bars (heatmap.2 only supports one on each axis). It is possible to do this with heatmap.plus. However, you then lose other features like the value color key, breaks, level trace, etc. Furthermore, beyond ~3 columns/rows of color sidebars, the bars are too squeezed together to see clearly, or to be able to read the labels. Any solutions out there?
I answered my own question by finding this post in the R-help mailing list. If you replace the corresponding blocks in heatmap.2 with blocks of code provided in that post you can get multiple color side bars in heatmap.2. The next message in the thread provides a solution for when you want more than two or three color side bars not too squished together. Using these changes I created a new heatmap.3 function that accepts number of row/column color side bars as a parameter and spaces them out appropriately. I also added a parameter for specifying a name for the color key besides "Value". Here is the code (github). You can just source this file and then call the heatmap.3 function with the new options as in the below example.
UPDATE: After several requests I created a fully functioning script on fake data. Of course, it is up to you to make sure you are setting up data and color side bars correctly when it comes to your own real data.
UPDATE: @Nachocab has made further improvements that allows a 1-dimensional data.frame for the annotations, and fixes the NA problem in the color key. I have modified my link above to point to his new improved version at github.
setwd("/Your/Working/Dir") #Put heatmap.3 code here
library("gplots")
#Create a fake dataset
prob_matrix=replicate(100, rnorm(20))
drug_names=paste("drug",letters[1:20],sep="_")
patient_ids=paste("patient",c(1:100),sep="_")
rownames(prob_matrix)=drug_names
colnames(prob_matrix)=patient_ids
#Create fake color side bars
drug_colors=sample(c("darkorchid","darkred"), length(drug_names), replace = TRUE, prob = NULL)
subtype_colors=sample(c("red","blue","cyan","pink","yellow","green"), length(patient_ids), replace = TRUE, prob = NULL)
Mcolors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
Ncolors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
Tcolors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
HER2colors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
PRcolors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
ERcolors=sample(c("black","white","grey"), length(patient_ids), replace = TRUE, prob = NULL)
rlab=cbind(drug_colors,drug_colors) #note, duplicated columns because function expects matrix of at least 2xn
clab=cbind(subtype_colors,Mcolors,Ncolors,Tcolors,HER2colors,PRcolors,ERcolors)
colnames(rlab)=c("Class","")
colnames(clab)=c("Subtype","M","N","T","HER2","PR","ER")
#Define custom dist and hclust functions for use with heatmaps
mydist=function(c) {dist(c,method="euclidian")}
myclust=function(c) {hclust(c,method="average")}
#Create heatmap using custom heatmap.3 source code
source("heatmap.3.R")
pdf(file="heatmap_example.pdf")
main_title="Drug Response Predictions"
par(cex.main=1)
heatmap.3(prob_matrix, hclustfun=myclust, distfun=mydist, na.rm = TRUE, scale="none", dendrogram="both", margins=c(4,10),
Rowv=TRUE, Colv=TRUE, ColSideColors=clab, RowSideColors=rlab, symbreaks=FALSE, key=TRUE, symkey=FALSE,
density.info="none", trace="none", main=main_title, labCol=FALSE, labRow=drug_names, cexRow=1, col=rev(heat.colors(75)),
NumColSideColors=7, KeyValueName="Prob. Response")
legend("topright",legend=c("Basal","LumA","LumB","Her2","Claudin","Normal","","Positive","Negative","NA","","Targeted","Chemo"),
fill=c("red","blue","cyan","pink","yellow","green","white","black","white","grey","white","darkorchid","darkred"), border=FALSE, bty="n", y.intersp = 0.7, cex=0.7)
dev.off()

Cool, thanks! FYI: I'm pretty sure you want to change the default values for the symbreaks and symkey args to from min(x < 0, na.rm=TRUE) to min(x, na.rm=TRUE) < 0, no?
Yes. I think you are correct. I just copied that default from heatmap.2 code. I can't say that I've noticed a problem with this. I usually have only positive values and don't scale. But, it looks like the default behavior is not working as stated in the documentation (i.e., symbreaks/symkey "Defaults to TRUE if the data includes negative values, and to FALSE otherwise"). Currently it defaults to TRUE if ALL values are negative or if scale!="none" is TRUE. Could also be fixed by changing to "max(x < 0, na.rm=TRUE)". Fixed in my uploaded file.
Here's a revision on @Obi Griffiths code that allows using a 1-dimensional data.frame for the annotations, and fixes the NA problem in the color key:
Here's how you would call it:
mat <- matrix(1:100, byrow=T, nrow=10)
column_annotation <- sample(c("red", "blue", "green"), 10, replace=T)
column_annotation <- as.matrix(column_annotation)
colnames(column_annotation) <- c("True")
heatmap.3(mat, ColSideColors=column_annotation)
Can you provide a code snippet? No matter how I try creating a 1-dimensional data.frame I get an error when trying to run your modified code. I assumed that something like "rlab=data.frame(Class=drugcolors)" would work. But that returns: "Error in heatmap.3(probmatrix, hclustfun = myclust, distfun = mydist, : 'RowSideColors' must be a character vector of length nrow(x)". If I try providing a character vector I get "Error in if (!is.character(RowSideColors) || dim(RowSideColors)[1] != : missing value where TRUE/FALSE needed". I also tried converting the 1-dimensional data.frame column to a character strings with (as.character) and also tried inputting a 1-dimensional matrix. But nothing worked. I must be missing something...
Nachocab. Still wondering if you can demonstrate how your code works with 1-dimensional data.
Hi Obi, I'm sorry I missed your message. I just added a snippet to my answer (I think you might have been missing the as.matrix() step). Send me an email next time
There is a package for that called Heatplus http://www.bioconductor.org/packages/release/bioc/html/Heatplus.html

Revisiting this old(er) q/a tutorial as I just came across the aheatmap function in the NMF package, which has slipped under my radar up until now and thought it might be useful to others since it does similar mojo.
The authors also have a nice vignette which is linked from their main page that shows off some of what it can do.
One added extra bonus is that it lets you plot multiple heatmaps in one plot as it is compatible with, for example, the par(mfrow=c(1,2)) mojo.
Thanks! That's really useful. BTW, could you provide a complete example to exactly reproduce your figure?
This should have been a comment. Not an answer. I have provided example R code. Unfortunately I am not able to provide a complete example because the data underlying this particular figure is very large and not available for public posting yet.