[R] image legend

Jonathan Rougier J.C.Rougier at durham.ac.uk
Tue Sep 21 09:56:30 CEST 1999

Hi Andy,

> Does anyone have a function for putting a legend on an image
> plot?  I couldn't locate an R equivalent of image.legend....has
> anyone written such a thing?

I'm attaching a couple of files for an `image.legend' that I wrote a few
weeks ago, although I have called it `image.scale' as it is not Splus
compatible. Because I am lazy it has lots of default options.  I am afraid
it falls a bit into the `crude but effective until shown otherwise'

Cheers, Jonathan.

Jonathan Rougier                       Science Laboratories
Department of Mathematical Sciences    South Road
University of Durham                   Durham DH1 3LE

"[B]egin upon the precept ... that the things we see are to be 
 weighed in the scale with what we know"  (Meredith, 1879, The Egoist)
-------------- next part --------------
"image.scale" <-
function (z, col, x, y = NULL, size = NULL, digits = 2, labels = c("breaks", 
    # sort out the location
    n <- length(col)
    usr <- par("usr")
    mx <- mean(usr[1:2]); my <- mean(usr[3:4])
    dx <- diff(usr[1:2]); dy <- diff(usr[3:4])
    if (missing(x))
        x <- mx + 1.05*dx/2	# default x to right of image
    else if (is.list(x)) {
        if (length(x$x) == 2) 
          size <- c(diff(x$x), -diff(x$y)/n)
        y <- x$y[1]
        x <- x$x[1]
    } else x <- x[1]
    if (is.null(size))
        if (is.null(y)) {
          size <- 0.618*dy/n	# default size, golden ratio
          y <- my + 0.618*dy/2	# default y to give centred scale
        } else size <- (y-my)*2/n
    if (length(size)==1)
        size <- rep(size, 2)	# default square boxes
    if (is.null(y))
        y <- my + n*size[2]/2
    # draw the image scale
    i <- seq(along = col)
    rect(x, y - i * size[2], x + size[1], y - (i - 1) * size[2], 
        col = rev(col), xpd = TRUE)
    # sort out the labels
    rng <- range(z, na.rm = TRUE)
    bks <- seq(from = rng[2], to = rng[1], length = n + 1)
    bks <- formatC(bks, format="f", digits=digits)
    labels <- match.arg(labels)
    if (labels == "breaks")
        ypts <- y - c(0, i) * size[2]
    else {
        bks <- paste(bks[-1], bks[-(n+1)], sep = " - ")
        ypts <- y - (i - 0.5) * size[2]
    text(x = x + 1.2 * size[1], y = ypts, labels = bks, adj =
        ifelse(size[1]>0, 0, 1), xpd = TRUE) 
-------------- next part --------------


\title{Provide scale to image plots}

image.scale(z, col, x, y=NULL, size=NULL, digits=2, labels=c("breaks", "ranges"))

 \item{z}{Data from image plot}
 \item{col}{Colours from image plot}
 \item{x}{Horizintal location of top-left corner of scale, or list with
\code{x} and \code{y} components}
 \item{y}{Vertical location of top-left corner of scale}
 \item{size}{1- or 2-vector of colour-box dimensions}
 \item{digits}{Number of digits after the decimal point in labels}
 \item{labels}{Type of labels}

Provides a vertical colour scale to accompany an image plot.  The
location defaults to the right of the plot, the colour-boxes
default to square, and the style of the labels defaults to giving
the breaks to the right of the scale.}

Use \code{x=locator(1)} or give both \code{x} and \code{y}
arguments to specify the top-left corner of the scale.  The
colour-boxes then default to squares, and the image is centred
around the vertical midpoint.  Use \code{x=locator(2)} for
complete control of the scale size and location.  The usual scale
(labels to the right) requires a top-left and bottom-right.  To
reverse the scale, go bottom-top.  To swith labels to the left,
go right-left.

The labels default to single values giving the breaks, centred
between colour-boxes.  For ranges centred vertically on each
colour-box (wider), specify \code{labels="ranges"}.}

\author{Jonathan Rougier}


# create an image plot
x <- seq(-0.5, 0.5, len = 31)
qform <- function(x, y) 3*x^2 + y^2 - 2*x*y
z <- outer(x, x, FUN = qform)

par("mar" = c(5, 4, 4, 10) + 0.1)	# wide righthand margin
image(x, x, z, col=gray(6:12/15))
image.scale(z, gray(6:12/15))		# the default

image(x, x, z, col=gray(6:12/15))
image.scale(z, gray(6:12/15), labels="range")	# with range labels

# play around with the following ...
image(x, x, z, col=gray(6:12/15))
image.scale(z, gray(6:12/15), x=locator(1))	# or locator(2)


More information about the R-help mailing list