[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