% -*- mode: noweb; noweb-default-code-mode: R-mode; -*- 
\documentclass[english, a4paper, 10pt, headings=small, DIV11]{scrartcl}
\usepackage[utf8]{inputenc} % Sweave doesn't find the encoding definition in vignettes.defs
\SweaveInput{vignettes.defs}
\usepackage{longtable}
\usepackage{array}

\hypersetup{pdftitle={hyperSpec plotting functions},
 pdfauthor={C. Beleites},
 pdfsubject={Introduction on the hyperSpec plotting functions},
 pdfkeywords={hyperSpec}}

% \VignetteIndexEntry{hyperSpec plotting functions}
% \VignetteKeywords{hyperspec}
% \VignettePackage{hyperSpec}
% \VignetteDepends{latticeExtra, tripack, deldir, rgl, ggplot2, playwith, latticist}

\newcommand{\plottab}[2]{
\vspace{1ex}\tabularnewline
  \multicolumn{2}{l}{\textbf{#1}}\tabularnewline\nopagebreak
\vtop{%
  \vskip-0.9\baselineskip
  \hbox{%
    \includegraphics[width = .40\textwidth]{fig/fig-#2}%
  }%
} &
}
\begin{document}
\newlength{\plotcol}
\newlength{\textcol}
\setlength{\plotcol}{0.4\textwidth}
\setlength{\textcol}{\textwidth}
\addtolength{\textcol}{-\plotcol}
\title{\Rpackage{hyperSpec} Plotting functions }
\maketitle
\warnbox{Vignette under Development}{
This file is currently undergoing a thorough revision. Changes may happen frequently.
}
\warnbox{Reproducing the Examples in this Vignette}{
All spectra used in this manual are installed automatically with \phy. 

Note that some definitions are executed in \texttt{vignette.defs}, and others invisibly at the
beginning of the file in order to have the code as similar as possible to interactive sessions.
}

\tableofcontents{}

\warnbox[blue!50!black]{Suggested Packages}{
\begin{labeling}{latticeExtra}
<<check-required, echo = FALSE, results = tex>>=
msg <- function (...) system (sprintf ("echo '%s'", paste (...)))

required.pkgs <- c("latticeExtra", "deldir", "rgl", "ggplot2")

dummies <- check.req.pkg ("latticeExtra", griderrors = "panel.levelplot.points",
                          hynsgrid = "plotvoronoi")
for (i in seq_along (dummies))
  eval (dummies [[i]])

check.req.pkg ("deldir", hynsgrid = "plotvoronoi")

for (p in required.pkgs [! required.pkgs %in% c("latticeExtra", "deldir")])
  check.req.pkg (p, donothing = "")
@
\end{labeling}
In addition \Rpackage{tripack}, \Rpackage{playwith}, and \Rpackage{latticist} are mentioned, but not
used in this vignette.
}
\section*{Preliminary Calculations}
For some plots of the \Robject{chondro} dataset, the pre-processed spectra and their cluster
averages $\pm$ one standard deviation are more suitable:
<<preproc-chondro>>=
chondro.preproc <- chondro - spc.fit.poly.below (chondro)
chondro.preproc <- sweep (chondro.preproc, 1, mean, "/")
chondro.preproc <- sweep (chondro.preproc, 2, apply (chondro.preproc, 2, quantile, 0.05), "-")

cluster.cols <- c ("dark blue", "orange", "#C02020")
cluster.meansd <- aggregate (chondro.preproc, chondro$clusters, mean_pm_sd)
cluster.means  <- aggregate (chondro.preproc, chondro$clusters, mean)
@
For details about the pre-processing, please refer to the example work flow in \verb+vignette ("chondro")+, or the help \verb+? chondro+.

\section{Predefined functions}
\Rpackage{hyperSpec} comes with 6 major predefined plotting functions.

\begin{labeling}{\Rfunction{levelplot}}
\item[\Rfunction{plot}] main switchyard for most plotting tasks
\item[\Rfunction{levelplot}] \chy has a method for \Rpackage{lattice}\Sexpr{cite.pkg ("lattice")} function \Rfunction{levelplot}
\vspace*{1em}
\item[\Rfunction{plotspc}] plots spectra
\item[\Rfunction{plotc}] calibration plot, time series, depth profile\\
  \Rfunction{plotc} is a \Rpackage{lattice} function
\item[\Rfunction{plotmap}] more specialized version of \Rfunction{levelplot} for map or image plots.\\
  \Rfunction{plotmap} is a \Rpackage{lattice} function
\item[\Rfunction{plotvoronoi}] more specialized version of \Rfunction{plotmap} that produces Voronoi tesselations.\\
  \Rfunction{plotvoronoi} is a \Rpackage{lattice} function 
\end{labeling}

\Rcode{plotmap}, \Rfunction{plotvoronoi}, and \Rcode{levelplot} are \Rpackage{lattice} functions.
Therefore, in loops, functions, Sweave chunks, etc. the lattice object needs to be printed explicitly
by e.\,g. \Rcode{print (plotmap (object))}
(\href{http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f}{R
  FAQ: Why do lattice/trellis graphics not work?}).


\setkeys{Gin}{width = \textwidth}

\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{plotspc}{plotspc}
plots the spectra, \ie the intensities \Rcode{\$spc} over the wavelengths \Rcode{@wavelength}.
<<plotspc, fig = TRUE, width = 4, height = 2.6, include = FALSE >>=
plotspc (paracetamol)
@ 
\\
\plottab{plotc}{plotflu}
    plots an intensity over a single other data column, \eg
    \begin{itemize}
    \item calibration
    \item time series
    \item depth profile
    \end{itemize}
<<plotflu, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotc (flu)
@
\\
\plottab{levelplot}{levelplot}
  plots a false colour map, defined by a formula.
<<levelplot, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
levelplot (spc ~ x * y, chondro, aspect = "iso")
@
Warning: \verb+Only first wavelength is used for plotting+
\\
\plottab{plotmap}{plotmap}
  plotmap is a specialized version of levelplot. It uses a single value (\eg average intensity or cluster membership) over two data columns (default \Rcode{\$x} and \Rcode{\$y})
<<plotmap, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro)
@
\\
\plottab{plotvoronoi}{voronoi}
  plotmap is a specialized version of levelplot. It uses a single value (\eg average intensity or cluster membership) over two data columns (default \Rcode{\$x} and \Rcode{\$y})
<<voronoi, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotvoronoi (sample (chondro, 300), clusters ~ x * y)
@
\end{longtable}


% \begin{description}
% %\setlength{\labelwidth}{2.5cm}
% %\setlength{\itemindent}{1.7cm}

% \item [{\Rcode{plotmap}}] plots a false colour map: a single value (e.\,g. average intensity or 
%    cluster membership) over two data columns (default \Rcode{\$x} and \Rcode{\$y}).
% \item [{\Rcode{plotc}}] plots a time series or calibration plot: e.\,g. an intensity over a single % other data column (like concentration, depth, or time).
% \end{description}

\section{Arguments for \Rmethod{plot} }
\label{sec:argum-rmeth}
\chy 's \Rfunction{plot} method uses its second argument to determine which of the
 specialized plots to produce. This allows some handy abbreviations.
 All further arguments are handed over to the function actually producing the plot.

%\begin{tabular}{@{}p{.45\textwidth} p{.55\textwidth}}
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{plot (x, \textquotedbl{}spc\textquotedbl{})}{plotspcflu} 
is equivalent to \Rcode{plotspc (flu)}
<<plotspcflu, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (flu, "spc")
@ 
\\ 
 \plottab{plot (x, \textquotedbl{}spcmeansd\textquotedbl{})}{plotchomean}
plots mean spectrum $\pm$ 1 standard deviation
<<plotchomean, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (chondro.preproc, "spcmeansd")
@
\\
\plottab{plot (x, \textquotedbl{}spcprctile\textquotedbl{})}{plotchoprctl}%
plots median, 16\textsuperscript{th} and 84\textsuperscript{th} percentile for each wavelength. For
Gaussian distributed data, 16\textsuperscript{th}, 50\textsuperscript{th} and 84\textsuperscript{th}
percentile are equal to mean $\pm$ standard deviation. Spectroscopic data frequently are not Gaussian
distributed. The percentiles give a better idea of the true distribution. They are also less
sensitive to outliers.
<<plotchoprctl, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (chondro.preproc, "spcprctile")
@
\\
\plottab{plot (x, \textquotedbl{}spcprctl5\textquotedbl{})}{plotchoprctl5}
like \Rcode{\textquotedbl{}spcprctl\textquotedbl{}} plus 5\textsuperscript{th} and 95\textsuperscript{th}percentile.
<<plotchoprctl5, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (chondro.preproc, "spcprctl5")
@
\\
\plottab{plot (x, \textquotedbl{}c\textquotedbl{})}{plotflu2}
<<plotflu2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (flu, "c")
@
is equivalent to \Rcode{plotc (flu)}
\\
\plottab{plot (x, \textquotedbl{}ts\textquotedbl{})}{plotts}
plots a time series plot
<<plotts, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (laser [,, 405], "ts")
@
equivalent to \Rcode{plotc (laser, spc \textasciitilde ~t)}
\\
\plottab{plot (x, \textquotedbl{}depth\textquotedbl{})}{plotdepth}
plots a depth profile plot
<<plotdepth, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
depth.profile <- new ("hyperSpec",
    spc = as.matrix (rnorm (20) + 1:20),
    data = data.frame (z = 1 : 20),
    labels = list (spc = "I / a.u.", 
       z = expression (`/` (z, mu*m)),
       .wavelength = expression (lambda)))
plot (depth.profile, "depth")
@
the same as \Rcode{plotc (laser, spc \textasciitilde ~z)}
\\
\plottab{plot (x, \textquotedbl{}mat\textquotedbl{})}{plotmat}
plots the spectra matrix.
<<plotmat, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (laser, "mat")
@
Equivalent to 
<<include = FALSE>>=
levelplot (spc ~ .wavelength * .row, laser)
@
\\
\plottab{plot (x, \textquotedbl{}map\textquotedbl{})}{plotmapcho2}
is equivalent to \Rcode{plotmap (chondro)}
<<plotmapcho2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (chondro, "map")
@
\\
\plottab{plot (x, \textquotedbl{}voronoi\textquotedbl{})}{plotvoronoi}
<<plotvoronoi, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (sample (chondro, 300), "voronoi")
@
See \Rfunction{plotvoronoi}
\end{longtable}

\section{Spectra}\mFun{\Rfunction{plotspc}}

\Rfunction{plotspc} offers a variety of parameters for customized
plots. To plot ... 
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
  \plottab{particular wavelength range}{wavelength} if only one wavelength range is needed, the
  extract command (see \verb+vignette ("introduction")+) is handiest:
<<wavelength, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (paracetamol [,, 700 ~ 1200])
@ Numbers connected with the tilde (\verb+~+) are interpreted as having the same units as the
wavelengths. If \Rcode{wl.range} already contains indices use \Rcode{wl.index = TRUE}.
\\
\plottab{more wavelength ranges}{wavelength-2} use \Rcode{wl.range = list (600 \textasciitilde{}
  1800, 2800 \textasciitilde{} 3100)}.  Cut the wavelength axis appropriately with \Rcode{xoffset =
  750}
<<wavelength-2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (paracetamol, 
         wl.range = c (300 ~ 1800, 2800 ~ max), 
         xoffset = 750)
@
%
If available, the package \Rpackage{plotrix}\Sexpr{cite.pkg("plotrix")} is used to produce the cut
mark.
\\
\plottab{with reversed abscissa}{abscissa} use \Rcode{wl.reverse = TRUE}
<<abscissa, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (paracetamol, wl.reverse = TRUE )
@
\\
\plottab{in different colours}{colours}
use \Rcode{col = vector.of.colours}
<<colours, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (flu, col = matlab.dark.palette (6))
@
\\
\plottab{dots instead of lines }{dots}
use \Rcode{lines.args = list (pch = 20, type = \textquotedbl{}p\textquotedbl{})}
<<dots, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (paracetamol [,, 2800 ~ 3200], 
         lines.args = list (pch = 20, type = "p"))
@
\\
\plottab{mass spectra }{mass}
use \Rcode{lines.args = list (type = \textquotedbl{}h\textquotedbl{})}
<<mass, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (barbiturates [[1]], lines.args = list (type = "h"))
@
\\
\plottab{more spectra into an existing plot}{add}
use \Rcode{add = TRUE}
<<add, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (chondro [ 30,,])
plotspc (chondro [300,,], add = TRUE, col = "blue")
@
\\
\plottab{Summary characteristics}{sd} \Rfunarg{func} may be used to calculate summary
characteristics prior to plotting. To plot \eg the standard deviation of the spectra, use:
<<sd, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (chondro.preproc, func = sd)
@
\\
\plottab{with different line at $I =0$}{diffline}
\Rfunarg{zeroline} takes a list with parameters to \Rfunction{abline},
\Rcode{NA} suppresses the line.
<<diffline, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (paracetamol, 
         zeroline = list (col = "red"))
@
\\
\plottab{adding to a spectra plot}{add-line} \Rfunction{plotspc} uses base graphics. After plotting
the spectra, more content may be added to the graphic by \Rfunction{abline}, \Rfunction{lines}, \Rfunction{points}, etc.
<<add-line, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (laser, "spcmeansd")
abline (v = c(405.0063, 405.1121, 405.2885, 405.3591), 
        col = c("black", "blue", "red", "darkgreen"))
@
\end{longtable}

\subsection{Stacked spectra}
\label{sec:stacked-spectra}

\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{stacked}{stacked1}
use \Rcode{stacked = TRUE}
<<stacked1, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (cluster.means, 
         col = cluster.cols,
         stacked = TRUE)
@
\\
\plottab{Stacking groups of spectra}{stacked2} The spectra to be stacked can be grouped:
\Rcode{stacked = \emph{factor}}. Alternatively, the name of the grouping extra data column can be
used:
<<stacked2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (cluster.meansd, 
      stacked = ".aggregate",
      fill = ".aggregate",
      col = cluster.cols)
@
\\
\plottab{Manually giving yoffset}{stacked3}
Stacking values can also be given manually as numeric values in \Rfunarg{yoffset}:
<<stacked3, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotspc (cluster.meansd, 
         yoffset = rep (0:2, each = 3), 
         col = rep (cluster.cols, each = 3))
@
\\
\plottab{Dense stacking}{stacked4}
To obtain a denser stacking:
<<stacked4, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
yoffsets <- apply (cluster.means [[]], 2, diff)
yoffsets <- - apply (yoffsets, 1, min) 
plot (cluster.means, yoffset = c (0, cumsum (yoffsets)), 
      col = cluster.cols)
@
\\
\plottab{Elaborate example}{stacked5}
<<stacked5, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
yoffset <- apply (chondro.preproc, 2, quantile, c(0.05, 0.95))
yoffset <- range (yoffset)
plot(chondro.preproc[1], 
     plot.args = list (ylim = c (0, 2) * yoffset),
     lines.args = list( type = "n"))
yoffset <- (0:1) * diff (yoffset)
for (i in 1 : 3){
  plot(chondro.preproc, "spcprctl5", yoffset = yoffset [i],
       col = "gray", add = TRUE)
  plot (chondro.preproc [i], yoffset = yoffset [i], 
        col = matlab.dark.palette (3) [i], add = TRUE, 
        lines.args = list (lwd = 2))
}
@
\end{longtable}


\section{Calibration Plots, (Depth) Profiles, and Time Series Plots}\mFun{\Rfunction{plotc}}


\subsection{Calibration plots}
\label{sec:line-calibr-plots}

\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{Intensities over concentration}{lin-cal-1}
Plotting the Intensities of one wavelength over the concentration for univariate calibration:
<<lin-cal-1, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
plotc (flu [,, 450])
@
The default is to use the first intensity only.
\\
\plottab{Summary Intensities over concentration}{lin-cal-3}
A function to compute a summary of the intensities before drawing can be used:
<<lin-cal-3, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
plotc (flu, func = range, groups = .wavelength)
@
If \Rfunction{func} returns more than one value, the different results are accessible by
\verb+.wavelength+.
\\
\plottab{Conditioning: plotting more traces separately}{plotc2}
<<plotc2, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
plotc (flu [,, c (405, 445)], spc ~ c | .wavelength, 
       cex = .3, scales = list (alternating = c(1, 1)))
@
\\
\plottab{Grouping: plot more traces in one panel}{plotc3}
<<plotc3, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
 plotc (flu [,, c (405, 445)], groups = .wavelength)
@
\\
\plottab{Changing Axis Labels (and other parameters)}{lin-cal-4}
Arguments for \Rfunction{xyplot} can be given to \Rfunction{plotc}:
<<lin-cal-4, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
plotc (flu [,, 450], 
       ylab = expression (I ["450 nm"] / a.u.),
       xlim = range (0, flu$c + .01), 
       ylim = range (0, flu$spc + 10),
       pch = 4)
@
\\
\plottab{Adding things to the plot: customized panel function}{lin-cal-5} 
As \Rfunction{plotc} uses the \Rpackage{lattice} function \Rfunction{xyplot}, additions to 
the plot must be made via the panel function:
<<lincal-panel>>=
panelcalibration <- function (x, y, ..., clim = range (x), level = .95) {
  panel.xyplot (x, y, ...)
  lm <- lm (y ~ x)
  panel.abline (coef (lm), ...)
  cx <- seq (clim [1], clim [2], length.out = 50)
  cy <- predict (lm, data.frame (x = cx), 
                 interval = "confidence", 
                 level = level) 
  panel.lines (cx, cy [,2], col = "gray")
  panel.lines (cx, cy [,3], col = "gray")
}
@
<<lin-cal-5, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
plotc (flu [,,405], panel = panelcalibration,
       pch = 4, clim = c (0, 0.35), level = .99)
@
\end{longtable}
%\pagebreak
\subsection{Time series and other Plots of the Type Intensity-over-Something}
\label{sec:time-series}

\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{Abscissae other than c}{plotc4}
 Other abscissae may be specified by explicitly giving the model formula:
<<plotc4, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
 plotc (laser [,, c(405.0063, 405.1121, 405.2885, 405.3591)], 
        spc ~ t, 
        groups = .wavelength, 
        type = "b", 
        col = c ("black", "blue", "red", "darkgreen"))
@
\end{longtable}

\section{Levelplot}
\label{sec:levelplot}

\phy's \Rmethod{levelplot} can use two  special column names:
\begin{labeling}{.wavelength}
\item[.wavelength] for the wavelengths
\item[.row] for the row index (\ie spectrum number) in the data
\end{labeling}

Besides that, it behaves exactly like \Rmethod{levelplot}. Particularly, the data is given as the \emph{second} argument:
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{levelplot}{levelplot}
<<levelplot, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
 levelplot (spc ~ x * y, chondro)
@
\\
\plottab{factors as z}{levelplot-factor}
If the colour-coded value is a factor, the display is adjusted to this fact:
<<levelplot-factor, fig = TRUE, width = 4, height = 2.6,include = FALSE>>=
 levelplot (clusters ~ x * y, chondro)
@
\\
\end{longtable}

\section{Spectra Matrix}
\label{sec:plotmat}
It is often useful to plot the spectra against an additional coordinate, \eg the time for time
series, the depth for depth profiles, etc.

This can be done by \Rcode{plot (object, "mat")}. The actual plotting is done by
\Rfunction{levelplot}, so the plots can be grouped or conditioned.

\begin{longtable}{@{}p{\plotcol} p{\textcol}}
\plottab{different palette}{plotmat1}
<<>>=
plot (laser, "mat", 
      col.regions = matlab.palette (20) )
@
is the same as 
<<plotmat1, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
levelplot (spc ~ .wavelength * .row, 
           laser,
           col.regions = matlab.palette (20))
@
\\
\plottab{different y axis}{plotmat1a}
 Changing the y axis is only possible with levelplot:
<<plotmat1a, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
levelplot (spc ~ .wavelength * t, laser)
@
\\
\plottab{colour-coded points: different panel function}{plotmap-barb}
<<plotmap-barb, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
require ("latticeExtra")
barb <- do.call (collapse, barbiturates[1:50])
barb <- orderwl (barb)
levelplot (spc ~ .wavelength * z, barb, 
           panel = panel.levelplot.points,
           cex = .33, col.symbol = NA,
           col.regions = matlab.palette)
@
\\
\plottab{contour lines}{plotmat2}
Contour lines may be added to all \Rfunction{levelplot} based plots:
<<plotmat2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plot (flu, "mat", 
      contour = TRUE, 
      labels = TRUE, 
      col = "#00000080",
      at = seq (0, 700, by = 50))
@
\end{longtable}


\section{False-Colour Maps: \Rfunction{plotmap}}

\Rfunction{plotmap} is a specialized version of \Rfunction{levelplot}. The spectral intensities may
be summarized by a function before plotting (default: \Rfunction{mean}). The same scale is
used for x and y axes (\Rfunarg{aspect = "iso"}).
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
 \plottab{plotting map}{plotmap-clu}
<<plotmap-chondro, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro)
@
\\
 \plottab{plotting maps with other than x and y}{plotmap-yx}
 specify the colour-coded variable, abscissa and ordinate as formula:
\Rcode{colour.coded \textasciitilde\ abscissa * ordinate}
<<plotmap-yx, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro, spc ~ y * x)
@
\\
\plottab{colour-coded factors}{plotmap-clu}
<<plotmap-clu, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro, clusters ~ x * y)
@ 
If the colour-coded variable is a factor, each level gets its own colour, and the legend is labeled
accordingly.
\\
\plottab{different palette}{plotmap-col} 
To plot with a different palette, use \Rcode{trellis.args = list (col.regions = palette)}.
<<plotmap-col, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
print (plotmap (chondro, clusters ~ x * y,
                col.regions = cluster.cols))
@
\\
\plottab{defined wavelengths}{plotmap-wave}
To plot a map of the average intensity at particular wavelengths use extraction:  
<<plotmap-wave, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro.preproc [, , c(728, 782, 1098, 
                                1240, 1482, 1577)],
         col.regions = matlab.palette)
@ 
\\
\plottab{Conditioning}{plotmap-pca}
<<plotmap-pca, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotmap (chondro, 
         spc ~ y * x | x > 5, 
         col.regions = matlab.palette(20))
@
\\
\plottab{Conditioning on \Rcode{.wavelength}}{plotmap-pca2} %
\Rfunction{plotmap} automatically applies the function in \Rfunarg{func} before plotting. This
defaults to the \Rfunction{mean}. In order to suppress this, use \Rcode{func = NULL}. This allows
conditioning on the wavelengths.

To plot \eg the first two score maps of a principal component analysis:
<<plotmap-pca2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
pca <- prcomp (~ spc, data = chondro.preproc$.)
scores <- decomposition (chondro, pca$x, 
                         label.wavelength = "PC", 
                         label.spc = "score /  a.u.")
plotmap (scores [,,1:2], 
         spc ~ y * x | as.factor(.wavelength), 
         func = NULL,
         col.regions = matlab.palette(20))
@ 
\\
\plottab{Conditioning on \Rcode{.wavelength} II}{plotmap-pca3}
Alternatively, use \Rfunction{levelplot} directly:
<<plotmap-pca3, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
levelplot (spc ~ y * x | as.factor(.wavelength), 
           scores [,,1:2], 
           aspect = "iso",
           col.regions = matlab.palette(20))
@ 
\\
\plottab{Voronoi plot}{voronoi-2}
<<voronoi-2, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
plotvoronoi (sample (chondro, 300), clusters ~ x * y, 
             col.regions = matlab.palette(20))
@
%
Voronoi uses \Rfunction{panel.voronoi} from
\Rpackage{latticeExtra}\Sexpr{cite.pkg("latticeExtra")}. The tesselation is calculated by default
using \Rpackage{deldir}\Sexpr{cite.pkg("deldir")}, but \Rpackage{tripack}\Sexpr{cite.pkg("tripack")}
can also be used. \Rpackage{tripack} seems to faster in general, but may ``hang'' with certain data
sets (particularly regular grids with missing spectra as in this example). Furthermore, it is not
FOSS (free and open source software).
\\
\plottab{Mark missing spectra}{missing} If the spectra come from a rectangular grid, missing
positions can be marked with this panel function:
<<missing, fig = TRUE, width = 4, height = 2.6,include = FALSE >>=
mark.missing <- function (x, y, z, ...){
  panel.levelplot (x, y, z, ...)

  miss <- expand.grid (x = unique (x), y = unique (y))
  miss <- merge (miss, data.frame (x, y, TRUE), 
                 all.x = TRUE)
  miss <- miss [is.na (miss[, 3]),]
  panel.xyplot (miss [, 1], miss [, 2], pch = 4, ...)
}

plotmap (sample (chondro, 865), 
         col.regions = matlab.palette(20),
         col = "black",
         panel = mark.missing)
@ 
\end{longtable}



\section{3 D (with \Rpackage{rgl})}
\label{sec:3-d}

3D plots with \Rpackage{rgl}
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
  \vspace{1ex}\tabularnewline
  \multicolumn{2}{l}{\}}\tabularnewline\nopagebreak
\vtop{%
  \vskip-0.9\baselineskip
  \hbox{%
    \includegraphics[width = .40\textwidth]{fig-3D}%
  }%
} &
\Rpackage{rgl}\Sexpr{cite.pkg("rgl")} offers fast 3d
  plotting in R. As \Rpackage{rgl}'s axis annotations are sometimes awkward, they may better be set
  manually:
<<rgl-plot, eval = FALSE>>=  evaluation in rgl-do
laser <- laser [,,404.8 ~ 405.6] / 10000
laser$t <- laser$t / 3600
cols <- rep (matlab.palette (nrow (laser)), nwl (laser))
surface3d (y = wl (laser), x = laser$t, 
           z = laser$spc, col =  cols)
aspect3d (c (1, 1, 0.25))
axes3d (c ('x+-', 'y--', 'z--'))
axes3d ('y--', nticks = 25, labels= FALSE)
mtext3d ("t / h", 'x+-', line = 2.5)
mtext3d ("λ / nm", 'y--', line = 2.5)
mtext3d ("I / a.u.", edge = 'z--', line = 2.5)
@
\end{longtable}
<<rgl-do, echo = FALSE, results = hide>>=
if (exists (".rgl") && .rgl){        # use extra argument to turn on rgl only on local machine as it doesn't work on r-forge.
  if (require (rgl)){
    open3d (windowRect=c(20,20,600, 350))  # this is needed only for automatically 
                                        # producing the snapshot
<<rgl-plot>>
     par3d (userMatrix = matrix (c (-0.52,  0.4, -0.75, 0, 
                                    -0.85, -0.28, 0.44, 0, 
                                    -0.04,  0.87, 0.49, 0, 
                                    -0.75,  0.75,     0, 1), ncol = 4L),
            scale = c (2.75, 5, 0.175),
            windowRect = c(20L, 50L, 520L, 330L),
            zoom = 0.75)
    rgl.snapshot ("fig-3D.png", fmt="png", top=TRUE )
    rgl.quit ()
  } else {
    png ("fig-3D.png")
    ploterrormsg ("", "rgl")
    dev.off ()
  }
}
@



\section{Using \Rpackage{ggplot2} with \phy objects}
\label{sec:ggplot2}
\chy objects do not yet directly support plotting with \Rpackage{ggplot2}
\Sexpr{cite.pkg("ggplot2")}. Nevertheless, \Rpackage{ggplot2} graphics can easily be obtained.

In general, \Rfunction{as.long.df} transforms a \chy object into a long-form \df that is suitable for
\Rfunction{qplot}, \Rfunction{ggplot}, etc:
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
  \plottab{plot spectra with \Rfunction{as.long.df}}{ggplotspc} 
<<ggplotspc, eval = FALSE>>=
df <- as.long.df (flu, rownames = TRUE)
ggplot (df, aes (x = .wavelength, y = spc, 
                 colour = c, groups = .rownames)) + 
  geom_line () +
  xlab (labels (flu)$.wavelength) +
  ylab (labels (flu)$spc) 
@ 
The two special columns \Rcode{.wavelength} and \Rcode{.rownames} contain the wavelength axis and
allow to distinguish the spectra.
\end{longtable}

Note however, that long \df{}s can be \emph{very} memory consuming as they are of size $nrow \cdot
nwl \times (ncol + 2)$ with respect to the dimensions of the \chy object. Thus, \eg the
\Robject{chondro} data set (\Sexpr{round (object.size (chondro) / 1048576, digits = 0)}\,MB) as \chy
object) needs
\Sexpr{round (object.size (as.long.df (chondro, rownames = TRUE)) / 1048576, digits = 0)}\,MB as
long-format \df. It is therefore highly recommended to calculate the particular data to be plotted
beforehand. Moreover, depending on the particular plot \Rfunction{as.data.frame} or
\Rfunction{as.t.df} may be more suitable than \Rfunction{as.long.df}:
\begin{longtable}{@{}p{\plotcol} p{\textcol}}
  \plottab{Map with \Rpackage{ggplot2}}{ggplotmap} 
<<ggplotmap, eval = FALSE>>=
df <- as.long.df (apply (chondro, 1, mean))
ggplot (df,aes (x = x, y = y, fill = spc)) +
  geom_tile() + 
  scale_fill_continuous ("spc", matlab.palette ()) +
  scale_x_continuous (expand = c (0, 0)) +
  scale_y_continuous (expand = c (0, 0)) +
  coord_equal ()
@
\\
  \plottab{Mean $\pm$ standard deviation with \Rpackage{ggplot2}}{ggplotmeansd} 
<<ggplotmeansd, eval = FALSE>>=
df <- as.t.df (apply (chondro, 2, mean_pm_sd))
ggplot (df, aes (x = .wavelength)) +
  geom_ribbon (aes (ymin = mean.minus.sd, 
                    ymax = mean.plus.sd), 
               fill = "#00000040") +
  geom_line (aes (y = mean)) +
  xlab (labels (chondro)$.wavelength) +
  ylab (labels (chondro)$spc) 
@
\\\plottab{Cut spectra with \Rpackage{ggplot2}}{ggplotspccut} %
Cut axes can be simulated by faceting. A factor is needed that indicates the respective ranges:
<<ggplotspccut, eval = FALSE>>=
df <- paracetamol [,, c( min ~ 1800, 2800 ~ max)] / 1e4
df <- as.long.df (df)
df$range <- factor (df$.wavelength > 2000)
ggplot (df, aes (x = .wavelength, y = spc)) +
  geom_line () + 
  facet_grid (. ~ range, labeller = function (...) "",
              scales = "free", space = "free") +
  scale_x_continuous (breaks = seq (0, 3200, 400)) +
  opts (strip.background = theme_blank ())
@
\end{longtable}
<<ggplot2-do, echo = FALSE, results = hide>>=
if (require (ggplot2)){
<<ggplotspc>>
  ggsave("fig/fig-ggplotspc.pdf", width = 4, height = 2.6)
<<ggplotmap>>
  ggsave("fig/fig-ggplotmap.pdf", width = 4, height = 2.6)
<<ggplotmeansd>>
  ggsave("fig/fig-ggplotmeansd.pdf", width = 4, height = 2.6)
<<ggplotspccut>>
  ggsave("fig/fig-ggplotspccut.pdf", width = 4, height = 2.6)
} else {
  for (f in c ("ggplotspc", "ggplotmap", "ggplotmeansd", "ggplotspccut")){
    pdf (sprintf ("fig/fig-%s.pdf", f), width = 4, height = 2.6) 
    ploterrormsg ("", "ggplot2")
    dev.off ()
  }
}
@

\section{Troubleshooting}
\label{sec:troubleshooting}
\subsection{No output is produced}
\label{sec:no-output-produced}

\Rcode{plotmap}, \Rcode{plotvoronoi}, \Rcode{levelplot}, and \Rcode{plotc} use \Rpackage{lattice}
functions.  Therefore, in loops, functions, Sweave chunks, etc. the lattice object needs to be
printed explicitly by \Rcode{print (plotmap (object))}
(\href{http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f}{R
  FAQ: Why do lattice/trellis graphics not work?}). The same holds for \Rpackage{ggplot2} graphics.

For suggestions how the lattice functions can be redefined so that the result is printed without
external print command, see the file \texttt{vignettes.defs}.

\section{Interactive Graphics}
\label{sec:interactive-graphics}

\phy offers basic interaction, \Rfunction{spc.identify} for spectra plots, and
\Rfunction{map.identify} and \Rfunction{map.sel.poly} for maps. The first two identify points in
spectra plots and map plots, respectively. \Rfunction{map.sel.poly} selects the part of a \chy object
that lies inside the user defined polygon.

\subsection{\Rfunction[]{spc.identify}: finding out wavelength, intensity and spectrum}
\label{sec:spc.identify}

\Rfunction{spc.identify} allows to measure points in graphics produced by \Rfunction{plotspc}. It
works correctly with reversed and cut wavelength axes.

<<eval = FALSE>>=
spc.identify (plotspc (paracetamol, wl.range = c (600 ~ 1800, 2800 ~ 3200), xoffset = 800))
@
The result is a data.frame with the indices of the spectra, the wavelength, and its intensity. 

\subsection{\Rfunction{map.identify}: finding a spectrum in a map plot}
\label{sec:map.identify}

\Rfunction{map.identify} returns the spectra indices of the clicked points.
<<eval = FALSE>>=
map.identify (chondro)
@

\subsection{\Rfunction{map.sel.poly}: selecting spectra inside a polygon in a map plot}
\label{sec:map.sel.poly}

\Rfunction{map.sel.poly} returns a logical indicating which spectra are inside the polygon drawn by the user:
<<eval = FALSE>>=
map.sel.poly (chondro)
@


\subsection{Related functions provided by base graphics and lattice}
\label{sec:identify-other}

For base graphics (as produced by \Rfunction{plotspc}), \Rfunction{locator} may be useful as well. It
returns the clicked coordinates. Note that these are \emph{not} transformed according to xoffset \&
Co.

For lattice graphics, \Rfunction{grid.locator} may be used instead. If it is not called in the panel
function, a preceding call to \Rfunction{trellis.focus} is needed:
<<eval = FALSE>>=
plot (laser, "mat")
trellis.focus ()
grid.locator ()
@

\Rfunction{identify} (or \Rfunction{panel.identify} for lattice graphics) allows to identify points
of the plot directly. Note that the returned indices correspond to the plotted object.

\subsection{Interactively changing graphics}
\label{sec:inter-chang-graph}

\phy's lattice functions work with \Rpackage{playwith}\Sexpr{cite.pkg("playwith")} and
\Rpackage{latticist} \Sexpr{cite.pkg("latticist")}. These packages allow easy customization of the
plots and also identification of points.

\bibliographystyle{unsrtnat}
\bibliography{plotting-pkg}
 
\section*{Session Info}
\begin{footnotesize}
<<bib, echo = FALSE>>=
make.bib (c("latticeExtra", "rgl", "ggplot2", "playwith", "latticist", "plotrix", "deldir", "tripack"), 
          file = "plotting-pkg.bib")
print (as.matrix(Sys.info()))
<<cleanup>>
@
\end{footnotesize}
\end{document}
