[R] Plotting labeled impulses: label collision
Jim Lemon
jim at bitwrit.com.au
Sat Jan 5 11:42:30 CET 2008
Johannes Graumann wrote:
> Dear all,
>
> As you can see from the attachment I'm using R to automatically annotate
> peptide fragmentation mass spectra, which are represented by impulse plots.
> I'd like to poll you on approaches of how to deal as generally as possible
> with the two biggest annotation issues I run into:
> 1) very close annotated masses (impulses) with similar y-axis dimensions -
> resulting in overlapping labels
> 2) very close annotated masses with widely differing y-axis dimensions -
> resulting in the label for the smaller one partially overplotting the
> impulse of the larger one
>
> Both cases can be seen in the appended png: for 1) see x of aprox. 1100, for
> 2) x of aprox. 575
>
> If one does this manually one would write the labels somewhere where there's
> plenty of space and then connect them with lines to the impulses/masses
> they actually represent ...
>
> Any insight in how to make this pretty(er) automatically is highly
> appreciated.
>
Hi Joh,
I would have loved to say that you could do this with the prettyR
package, but I'll have to settle for plotrix. I realized that the
spread.labels function would almost do what you want. With a minor
change, as in the function below, I think it might get you there.
spread.labels<-function (x,y,labels=NULL,spready=NA,
offsets,bg="white",border=FALSE,between=FALSE,
linecol=par("fg"),...) {
if(missing(x))
stop("Usage: spread.labels(x,y,labels,...)")
ny<-length(y)
if(between) {
if(length(linecol)==1) linecol<-rep(linecol,2)
nlabels<-length(labels)
newy<-seq(y[1],y[ny],length=nlabels)
# put the labels in the middle
labelx<-rep(mean(x),nlabels)
# do the left lines
segments(x[1:nlabels],y[1:nlabels],
labelx-strwidth(labels)/2,newy,col=linecol[1])
# now the right lines
segments(x[(nlabels+1):ny],y[(nlabels+1):ny],
labelx+strwidth(labels)/2,newy,col=linecol[2])
boxed.labels(labelx,newy,labels,bg=bg,
border=border,...)
}
else {
if(is.na(spready))
spready<-diff(range(x))<diff(range(y))
if(spready) {
sort.index<-sort.list(y)
x<-x[sort.index]
y<-y[sort.index]
newy<-seq(y[1],y[ny],length=length(labels))
if(missing(offsets)) {
offset<-diff(par("usr")[1:2])/4
offsets<-rep(c(offset, -offset), ny/2 + 1)[1:ny]
}
segments(x+offsets,newy,x,y)
boxed.labels(x+offsets,newy,labels[sort.index],
bg=bg,border=border,...)
}
else {
sort.index<-sort.list(x)
x<-x[sort.index]
y<-y[sort.index]
nx<-length(x)
newx <- seq(x[1],x[nx],length=length(labels))
if(missing(offsets)) {
offset<-diff(par("usr")[3:4])/4
offsets<-rep(c(offset,-offset),nx/2+1)[1:nx]
}
segments(newx,y+offsets,x,y)
boxed.labels(newx,y+offsets,labels[sort.index],
bg=bg,border=border,...)
}
}
}
Try calling it like this:
spread.labels(x=<x values>,y=<y values>,
labels=<your labels>,spready=FALSE,
offsets=rep(10000,<number of labels>),
srt=90)
By passing different offsets you may be able to fix some of the really
bad crowding on the labels.
Jim
More information about the R-help
mailing list