# Clean up to ensure reproducible workspace ----------------------------------
rm(list = ls(all.names = TRUE))
# Packages -------------------------------------------------------------------
library(hyperSpec)
library(latticeExtra)
library(ggplot2)
# library(rgl)

# Functions ------------------------------------------------------------------
source("vignette-functions.R", encoding = "UTF-8")

# Settings -------------------------------------------------------------------
source("vignette-default-settings.R", encoding = "UTF-8")

# Temporaty options ----------------------------------------------------------
# Change the value of this option in "vignette-default-settings.R"
show_reviewers_notes <- getOption("show_reviewers_notes", TRUE)
dir.create("resources", showWarnings = FALSE)

knitr::write_bib(
  c(
    "hyperSpec",
    "lattice",
    "latticeExtra",
    "rgl",
    "ggplot2",
    "plotrix"
  ),
  file = "resources/plotting-pkg.bib",
  prefix = "R-"
)

Suggested Packages and Setup {-}

```{block, type="note", echo=TRUE} Reproducing the examples in this vignette.

All spectra used in this manual are installed automatically with package hyperSpec.

***

> **Terminology**
> Throughout the documentation of the package, the following terms are used:
>
> - **wavelength** indicates any type of spectral abscissa.
> - **intensity**  indicates any type of spectral ordinate.
> - **extra data** indicates non-spectroscopic data.


```r
msg <- function(...) system(sprintf("echo '%s'", paste(...)))

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

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

for (p in required.pkgs [!required.pkgs %in% c("latticeExtra")]) {
  check.req.pkg(p, donothing = "")
}
library(hyperSpec)
library(latticeExtra)
library(ggplot2)
# library(rgl)

par(mar = c(4.1, 4.1, 1, .6))

set.seed(2020)

Preliminary Calculations {-}

For some plots of the faux_cell{.r} dataset, the pre-processed spectra and their cluster averages $\pm$ one standard deviation are more suitable:

set.seed(1)
faux_cell <- generate_faux_cell()

faux_cell_preproc <- faux_cell - spc_fit_poly_below(faux_cell)
faux_cell_preproc <- faux_cell_preproc / rowMeans(faux_cell)
faux_cell_preproc <- faux_cell_preproc - quantile(faux_cell_preproc, 0.05)

cluster_cols   <- c("dark blue", "orange", "#C02020")
cluster_meansd <- aggregate(faux_cell_preproc, faux_cell$region, mean_pm_sd)
cluster_means  <- aggregate(faux_cell_preproc, faux_cell$region, mean)

Predefined Functions

Package hyperSpec comes with 6 major predefined plotting functions:

plot(){.r} : main switchyard for most plotting tasks. More details in section \@ref(fun-plot).

plot_spc(){.r} : plots spectra. More details in sections \@ref(exm-plot-spc), \@ref(arg-spc), and \@ref(fun-plot-spc).

plot_c(){.r} : calibration plot, time series, depth profile. More details in sections \@ref(exm-plot-c), \@ref(arg-c), \@ref(arg-ts), \@ref(arg-depth), and \@ref(fun-plot-c). (plot_c(){.r} is a package lattice function)

levelplot(){.r} : package hyperSpec has a method for package lattice[r cite_pkg("lattice")] function levelplot(){.r}. More details in sections \@ref(exm-levelplot), and \@ref(fun-levelplot).

plot_matrix(){.r} : plots the spectra matrix. More details in sections \@ref(exm-plot-matrix), \@ref(arg-mat), and \@ref(fun-plot-matrix).

plot_map(){.r} : more specialized version of levelplot(){.r} for map or image plots. More details in sections \@ref(exm-plot-map), \@ref(arg-map), and \@ref(fun-plot-map). (plot_map(){.r} is a package lattice function)

plot_voronoi(){.r} : more specialized version of plot_map(){.r} that produces Voronoi tesselations. More details in sections \@ref(exm-plot-voronoi), and \@ref(arg-voronoi). (plot_voronoi(){.r} is a package lattice function)

``{block, type="note", echo=TRUE} **NOTE.** Functionsplot_map(){.r},plot_voronoi(){.r}, andlevelplot(){.r} are package **lattice** functions. Therefore, in loops, functions, R Markdown chunks, etc. lattice objects need to be printed explicitly by, e.g.,print(plot_map(object))`{.r} (R FAQ: Why do lattice/trellis graphics not work?).

## Function `plot_spc()`{.r} {#exm-plot-spc}

Function `plot_spc()`{.r} plots the spectra (Fig. \@ref(fig:plot-spc)), i.e., the intensities (`$spc`{.r}) over the wavelengths (`@wavelength`{.r}).

```r
CAPTION <- "Spectra in dataset `flu`.  "
plot_spc(flu)

Function plot_matrix(){.r} {#exm-plot-matrix}

Function plot_matrix(){.r} plots the spectra, i.e., the colour coded intensities ($spc{.r}) over the wavelengths (@wavelength{.r}) and the row number (Fig. \@ref(fig:plot-matrix-flu)).

CAPTION <- "Matrix of spectra: the colour coded intensities over the wavelengths and the row number.  "
plot_matrix(flu)

Function plot_c(){.r} {#exm-plot-c}

Function plot_c(){.r} plots an intensity over a single other data column, e.g., concentration (calibration plot, e.g., Fig. \@ref(fig:plotflu)), depth (depth profile plot), or time (time series plot).

CAPTION <- "Calibration plot: an intensity over concentration.  "
plot_c(flu)

The following warning is expected: Intensity at first wavelengh only is used.

Function levelplot(){.r} {#exm-levelplot}

Function levelplot(){.r} plots a false colour map, defined by a formula (Fig. \@ref(fig:levelplot)).

CAPTION <- "False colour map (1).  "
levelplot(spc ~ x * y, faux_cell[, , 1200], aspect = "iso")

The following warning is expected: Only first wavelength is used for plotting.

Function plot_map(){.r} {#exm-plot-map}

Function plot_map(){.r} is a specialized version of levelplot(){.r}. It uses a single value (e.g., average intensity or cluster membership) over two data columns (default are $x{.r} and $y{.r}) to plot a false colour map (Fig. \@ref(fig:plot_map)).

CAPTION <- "False colour map created with `plot_map()`{.r}.  "
plot_map(faux_cell[, , 1200])

Function plot_voronoi(){.r} {#exm-plot-voronoi}

Function plot_voronoi(){.r} is a special version of plot_map(){.r} that produces Voronoi diagram of the hyperSpec object (Fig. \@ref(fig:voronoi)).

CAPTION <- "Voronoi diagram: an example with `faux_cell` dataset.  "
plot_voronoi(sample(faux_cell, 300), region ~ x * y)

Arguments for plot(){.r} {#fun-plot}

The hyperSpec's plot(){.r} 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.

Argument "spc"{.r} {#arg-spc}

Command plot(x, "spc"){.r} is equivalent to plot_spc(flu){.r} (Fig. \@ref(fig:plot-spcflu)).

CAPTION <- "All spectra of dataset `flu`.  "
plot(flu, "spc")

Argument "spcmeansd"{.r} {#arg-spcmeansd}

Command plot(x, "spcmeansd"){.r} plots mean spectrum $\pm$ 1 standard deviation (Fig. \@ref(fig:plotchomean)).

CAPTION <- "Summary spectra: mean $\\pm$ one standard deviation at each wavelength (wavenumber).  "
plot(faux_cell_preproc, "spcmeansd")

Argument "spcprctile"{.r} {#arg-spcprctile}

Code plot(x, "spcprctile"){.r} plots median, 16^th^ and 84^th^ percentile for each wavelength (Fig. \@ref(fig:plotchoprctl)). For Gaussian distributed data, 16^th^, 50^th^ and 84^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.

CAPTION <- "Summary spectra: median, 16^th^ and 84^th^ percentiles at each wavelength (wavenumber).  "
plot(faux_cell_preproc, "spcprctile")

Argument "spcprctl5"{.r} {#arg-spcprctl5}

The code plot(x, "spcprctl5"){.r} is like "spcprctile"{.r} plus 5^th^ and 95^th^ percentile (Fig. \@ref(fig:plotchoprctl5)).

CAPTION <- "Summary spectra: median, 5^th^, 16^th^, 84^th^, 95^th^ percentiles at each wavelength (wavenumber).  "
plot(faux_cell_preproc, "spcprctl5")

Argument "c"{.r} {#arg-c}

Command plot(x, "c"){.r} is equivalent to plot_c(flu){.r} (Fig. \@ref(fig:plotflu2)).

CAPTION <- "Calibration plot: spectra intensities over concentration.  "
plot(flu, "c")

Argument "ts"{.r} {#arg-ts}

Function plot(x, "ts"){.r} plots a time series plot and is equivalent to plot_c(laser, spc ~ t){.r} (Fig. \@ref(fig:plotts)).

CAPTION <- "Time series plot: spectra intensities over time.  "
plot(laser[, , 405], "ts")

Argument "depth"{.r} {#arg-depth}

Code plot(x, "depth"){.r} plots a depth profile plot and is the same as plot_c(laser, spc ~ z){.r} (Fig. \@ref(fig:plotdepth)).

CAPTION <- "Depth profile plot.  "
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")

Argument "mat"{.r} {#arg-mat}

Code plot(x, "mat"){.r} plots the spectra matrix (Fig. \@ref(fig:plot-matrix)).

CAPTION <- "Spectra matrix.  "
plot(laser, "mat")

The code is equivalent to:

plot_matrix(laser)

A lattice alternative is:

levelplot(spc ~ .wavelength * .row, data = laser)

Argument "map"{.r} {#arg-map}

Code plot(x, "map"){.r} is equivalent to plot_map(faux_cell){.r} (Fig. \@ref(fig:plotmapcho2)).

CAPTION <- "False color map: alternative R syntax.   "
plot(faux_cell[, , 1200], "map")

Argument "voronoi"{.r} {#arg-voronoi}

Use plot(x, "voronoi"){.r} for a Voronoi plot (Fig. \@ref(fig:plot_voronoi)).

CAPTION <- "Voronoi plot: alternative R syntax.  "
plot(sample(faux_cell[, , 1200], 300), "voronoi")

See ?plot_voronoi{.r} and ?latticeExtra::panel.voronoi{.r}.

Customized Plots of Spectra: plot_spc(){.r} {#fun-plot-spc}

Function plot_spc(){.r} offers a variety of parameters for customized plots.

Plot Particular Wavelength Range

If only one wavelength range is needed (Fig. \@ref(fig:wavelength)), the extract command is handiest.

CAPTION <- "Plot of wavelength (wavenumber) range from 700 to 1200 $cm^{-1}.$  "
plot_spc(paracetamol[, , 700 ~ 1200])

Numbers connected with the tilde (~) are interpreted as having the same units as the wavelengths. If wl.range{.r} already contains indices use wl.index = TRUE{.r}. For more details refer to vignette("hyperspec", package = "hyperSpec"){.r}.

Plot Several Wavelength Ranges

To plot severel wavelength ranges (Fig. \@ref(fig:wavelength-2)), use wl.range = list (600 ~ 1800, 2800 ~ 3100){.r}. Cut the wavelength axis appropriately with xoffset = 750{.r}. If available, the package package plotrix[r cite_pkg("plotrix")] is used to produce the cut mark.

CAPTION <- "Plot of several wavelength (wavenumber) ranges.  "
plot_spc(paracetamol,
  wl.range = c(300 ~ 1800, 2800 ~ max),
  xoffset = 750
)

Plot with Reversed Abscissa

To create a plot with reversed abscissa (Fig. \@ref(fig:abscissa)), use wl.reverse = TRUE{.r}

CAPTION <- "Plot with reversed/descending wavelength (wavenumber) range.  "
plot_spc(paracetamol, wl.reverse = TRUE)

Plot in Different Colours

To have different colours of spectra (Fig. \@ref(fig:colours)), use col = vector_of_colours{.r}.

CAPTION <- "Spectra plotted in different colours.  "
plot_spc(flu, col = palette_matlab_dark(6))

Plot Dots Instead of Lines

To plot dots instead of lines (Fig. \@ref(fig:dots)), use, e.g., lines.args = list (pch = 20, type = "p"){.r}

CAPTION <- "Spectrum with dots instead of lines.  "
plot_spc(paracetamol[, , 2800 ~ 3200],
  lines.args = list(pch = 20, type = "p")
)

Plot Mass Spectra

TO plot mass spectra (Fig. \@ref(fig:mass)), use lines.args = list(type = "h"){.r}

CAPTION <- "An example of mass spectrum.  "
plot(barbiturates[[1]], lines.args = list(type = "h"))

Add More Spectra into an Existing Plot

To plot additional spectra onto an existing plot (Fig. \@ref(fig:add)), use add = TRUE{.r}

CAPTION <- "A spectrum added to an existing plot.  "
plot_spc(faux_cell[30, , ])
plot_spc(faux_cell[35, , ], add = TRUE, col = "blue")

Plot Summary Characteristics

Argument func{.r} may be used to calculate summary characteristics before plotting. To plot, e.g., the standard deviation of the spectra, use plot_spc(..., func = sd){.r} (Fig. \@ref(fig:sd)).

CAPTION <- "A spectrum of summary statistics calculated via `func` parameter.
In the example, the standard deviation is used.  "
plot_spc(faux_cell_preproc, func = sd)

Plot Different Line at $I = 0$

To plot a different line at zero intensity $(I = 0)$, argument zeroline{.r} may be used (Fig. \@ref(fig:diffline)). Argument zeroline{.r} takes a list with parameters that are passed to function abline(){.r}, NA{.r} suppresses the line.

CAPTION <- "Spectrum with added zero-intensity line.  "
plot_spc(paracetamol,
  zeroline = list(col = "red")
)

Adding Annotations to a Spectra Plot

Function plot_spc(){.r} uses base graphics. After plotting the spectra, more content may be added to the graphic by abline(){.r}, lines(){.r}, points(){.r}, etc. (Fig. \@ref(fig:add-line)).

CAPTION <- "A summary spectrum with annotation lines.  "
plot(laser, "spcmeansd")
abline(
  v = c(405.0063, 405.1121, 405.2885, 405.3591),
  col = c("black", "blue", "red", "darkgreen")
)

Stacked Spectra {#sec:stacked-spectra}

Simple Stacking

To stack spectra, use stacked = TRUE{.r} (Fig. \@ref(fig:stacked1)).

CAPTION <- "Stacked spectra of means.  "
plot_spc(
  cluster_means,
  col = cluster_cols,
  stacked = TRUE
)

Stacking Groups of Spectra

``{block2, type="note-t", echo=show_reviewers_notes} **V. Gegzna's notes**plotting-2`

  1. FIXME:{.r} grammatical structure of these sentences makes them difficult to understand:

    The spectra to be stacked can be grouped: stacked = "factor"{.r}. Alternatively, the name of an extra data column can be used for grouping (Fig. \@ref(fig:stacked2)).

    Would this alternative formulation reflect the idea of the sub-chapter well enough:

    Argument stacked = "factor"{.r} can be used to stack groups of spectra (Fig. \@ref(fig:stacked2)). Here "factor"{.r} is a column name of factor variable in extra data.

<!-- ======================================================================= -->



The spectra to be stacked can be grouped: `stacked = "factor"`{.r}.
Alternatively, the name of an extra data column can be used for grouping (Fig. \@ref(fig:stacked2)).

```r
CAPTION <- "Stacked summary spectra (mean $\\pm$ one standard deviation).  "
op <- par(las = 1, mgp = c(3.1, .7, 0))

plot(
  cluster_meansd,
  stacked = ".aggregate",
  fill    = ".aggregate",
  col     = cluster_cols
)

Manually Giving yoffset

Stacking values can also be given manually as numeric values in yoffset{.r} (Fig. \@ref(fig:stacked3)).

CAPTION <- "Stacked spectra with customized y offset.  "
plot_spc(
  cluster_meansd,
  yoffset = rep(0:2, each = 3),
  col = rep(cluster_cols, each = 3)
)

Dense Stacking

It is possible to obtain a denser stacking (Fig. \@ref(fig:stacked4)).

CAPTION <- "Dense-stacked spectra.  "
yoffsets <- apply(cluster_means[[]], 2, diff)
yoffsets <- -apply(yoffsets, 1, min)
plot(cluster_means,
  yoffset = c(0, cumsum(yoffsets)),
  col = cluster_cols
)

Elaborate Example

Function plot_spc(){.r} allows fine grained customization of almost all aspects of the plot (see example in Fig. \@ref(fig:stacked5)). This is possible by giving arguments to the functions that actually perform the plotting plot(){.r} for setting up the plot area, lines(){.r} for the plotting of the lines, axis(){.r} for the axes, etc. The arguments for these functions should be given in lists as plot.args{.r}, lines.args{.r}, axis.args{.r}, etc.

CAPTION <- "An example of highly customized spectra.  "
yoffset <- apply(faux_cell_preproc, 2, quantile, c(0.05, 0.95))
yoffset <- range(yoffset)
plot(faux_cell_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(faux_cell_preproc, "spcprctl5",
    yoffset = yoffset[i],
    col = "gray", add = TRUE
  )
  plot(faux_cell_preproc[i],
    yoffset = yoffset[i],
    col = palette_matlab_dark(3) [i], add = TRUE,
    lines.args = list(lwd = 2)
  )
}

Calibration, (Depth) Profile, and Time Series Plots: plot_c(){.r} {#fun-plot-c}

Intensities over Concentration

Spectra intensities of one wavelength can be plotted over the concentration for univariate calibration (Fig. \@ref(fig:lin-cal-1)).

CAPTION <- "Intensities at 450 nm over concentration.  "
plot_c(flu[, , 450])

The default is to use the first intensity only.

Summary Intensities over Concentration

A function to compute a summary of the intensities before the drawing can be used via argument func (Fig. \@ref(fig:lin-cal-3)).

CAPTION <- "The summary (minimum and maximum) of intensities at each measured concentration.  "
plot_c(flu, func = range, groups = .wavelength)

If func(){.r} returns more than one value, the different results are accessible by .wavelength.

Conditioning: Plotting More Traces Separately

Lattice conditioning (operator |) can be used to plot more traces separately (Fig. \@ref(fig:plotc2)).

CAPTION <- "Conditioning: several calibration spectra on separate subplots.  "
plot_c(flu[, , c(405, 445)], spc ~ c | .wavelength,
  cex = .3, scales = list(alternating = c(1, 1))
)

Grouping: Plot More Traces in One Panel

Argument groups{.r} may be used as a grouping parameter to plot more traces in one panel (Fig. \@ref(fig:plotc3)).

CAPTION <- "Grouping: several calibration spectra on one plot.  "
plot_c(flu[, , c(405, 445)], groups = .wavelength)

Changing Axis Labels (and Other Parameters)

Arguments of lattice function xyplot(){.r} can be given to plot_c(){.r} (Fig. \@ref(fig:lin-cal-4)).

CAPTION <- "Modified axis labels and point characters.  "
plot_c(flu[, , 450],
  ylab = expression(I["450 nm"] / a.u.),
  xlim = range(0, flu$c + .01),
  ylim = range(0, flu$spc + 10),
  pch = 4
)

Adding Things to the Plot: Customized Panel Function

As plot_c(){.r} uses the package lattice function xyplot(){.r}, additions to the plot must be made via the panel function (Fig. \@ref(fig:lin-cal-5)).

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")
}
CAPTION <- "Plot that uses a customized paanel function.  "
plot_c(flu[, , 405],
  panel = panelcalibration,
  pch = 4, clim = c(0, 0.35), level = .99
)

Time Series and Other Plots of the Type "Intensity-over-Something" {#sec:time-series}

Abscissae other than c may be specified by explicitly giving the model formula (Fig. \@ref(fig:plotc4)).

CAPTION <- "Plot with abscissae explicitly indicated by model formula.  "
plot_c(laser[, , c(405.0063, 405.1121, 405.2885, 405.3591)],
  spc ~ t,
  groups = .wavelength,
  type   = "b",
  col    = c("black", "blue", "red", "darkgreen")
)

Levelplot: levelplot(){.r} {#fun-levelplot}

Package hyperSpec's function levelplot(){.r} can use two special column names:

Besides that, it behaves exactly like lattice levelplot(){.r}. Particularly, the data is given as the second argument (Fig. \@ref(fig:levelplot)).

CAPTION <- "An example of a levelplot.  "
levelplot(spc ~ x * y, data = faux_cell[, , 800])

If the colour-coded value is a factor, the display is adjusted to this fact (Fig. \@ref(fig:levelplot-factor)).

CAPTION <- "Levelplot when colour-coded value is a factor.  "
levelplot(region ~ x * y, data = faux_cell)

Spectra Matrix: plot_matrix(){.r} {#fun-plot-matrix}

It is often useful to plot the spectra against an additional coordinate, e.g., the time for time series, the depth for depth profiles, etc. This can be done by plot(object, "mat"){.r}. The actual plotting is done by image(){.r}, but levelplot(){.r} can produce spectra matrix plots as well and these plots can be grouped or conditioned.

Different Palette

Argument col can be used to provide a different colour palette (Fig. \@ref(fig:plotmat1)).

CAPTION <- "Spectra matrix with non-default palette.  "
plot(laser, "mat", col = heat.colors(20))

This is the same as:

plot_matrix(laser, col = heat.colors(20))

Different Y-Axis

Different extra data column can be used as y-axis (Fig. \@ref(fig:plotmat2)).

CAPTION <- "Spectra matrix with time (in column `t`) on y axis.    "
plot_matrix(laser, y = "t")

Alternatively, y values and axis label can be given separately.

plot_matrix(laser, y = laser$t, ylab = labels(laser, "t"))

Contour Lines

Contour lines may also be added (Fig. \@ref(fig:plotmat3)).

CAPTION <- "Spectra matrix with added contour lines.  "
plot_matrix(flu, col = palette_matlab_dark(20))
plot_matrix(flu, col = "white", contour = TRUE, add = TRUE)

Colour-Coded Points: Special Panel Function

In levelplot(){.r}, colour-coded points may be set via special panel function (Fig. \@ref(fig:plot-map-barb)).

library("latticeExtra")

barb <- collapse(barbiturates)
barb <- wl_sort(barb)
CAPTION <- "Colour-coded points via special panel function.  "
levelplot(spc ~ .wavelength * z, barb,
  panel = panel.levelplot.points,
  cex = .33, col.symbol = NA,
  col.regions = palette_matlab
)

False-Colour Maps: plot_map(){.r} {#fun-plot-map}

Plotting map {#plot-map}

Function plot_map(){.r} is a specialized version of levelplot(){.r} (Fig. \@ref(fig:plot-map-clu)). The spectral intensities may be summarized by a function before plotting (default: mean(){.r}). The same scale is used for x and y axes (aspect = "iso"{.r}).

CAPTION <- "An example of a false colour map.  "
plot_map(faux_cell[, , 1200])

Plotting Maps with Manually Specified X and Y Axes {#plot-map-manual-xy}

Specify the colour-coded variable, abscissa and ordinate as formula: colour.coded ~ abscissa * ordinate{.r} (Fig. \@ref(fig:plot-map-yx)).

CAPTION <- "False colour map with an explicit specification of x and y axes.  "
plot_map(faux_cell[, , 1200], spc ~ y * x)

Discrete Colours

Factor variables may be used for discrete colour coding (Fig. \@ref(fig:plot-map-clu)).

CAPTION <- "False colour map with colours defined by a factor variable.  "
plot_map(faux_cell, region ~ x * y)

If the colour-coded variable is a factor, each level gets its own colour, and the legend is labelled accordingly.

Different Palette

To use a different palette, use argument col.regions{.r} (Fig. \@ref(fig:plot-map-col)).

CAPTION <- "False colour map with non-default colour palette.  "
plot_map(faux_cell, region ~ x * y, col.regions = cluster_cols)

Fine-Tuning lattice Parameters

The plotting of colour maps is done via R package lattice (aka Trellis graphic approach), which is highly customizable. Use function trellis.par.get(){.r} and trellis.par.set(){.r} to get/set the settings for the current graphics device.

my_theme <- trellis.par.get()
names(my_theme) # note how many parameters are tunable

Any of these parameters can be fine-tuned to produce the desired output. For example, parameter my_theme$region{.r} is responsible for the appearance of color maps, and it contains elements $alpha{.r} and $col{.r}. By changing these parameters you can create your own theme for plotting and pass it to the plotting function via par.settings{.r}.

Changed Palette

Fig. \@ref(fig:plot-map-col-default) uses a customized lattice theme.

CAPTION <- "A false-colour map that uses `terrain.colors` palette.   "
my_theme$regions$col <- grDevices::terrain.colors
plot_map(faux_cell[, , 1200], par.settings = my_theme)

It is possible to persistently (i.e. inside of the current R session) set lattice parameters, so they would apply to all further plots. This is done via a call to trellis.par.set(){.r}, for example trellis.par.set(my_theme){.r}.

The current settings can be visualized via a call to show.settings(){.r}

Show Current lattice Settings

Graphical parameters for trellis may be displayed via show.settings(){.r} (Fig. \@ref(fig:lattice-settings)).

CAPTION <- "Show **lattice** settings.  "

```{block, type="note-t", echo=show_reviewers_notes}

# FIXME:{.r} padding in these figures must be fixed!

```r
# Display current trellis parameters
show.settings()
show.settings(my_theme)

An overview of different colour palettes, and ways to create your own, can be found in the R colour cheatsheet.

Defined Wavelengths

A map of the average intensity at particular wavelengths can be plotted if the wavelengths of interested are explicitly extracted (Fig. \@ref(fig:plot-map-wave)).

CAPTION <- "A map of average intensity at explicitly indicated wavelengths.  "
plot_map(
  faux_cell_preproc[, , c(800, 1500)],
  col.regions = palette_matlab
)

Conditioning

Logical conditions may be used to create subplots (Fig. \@ref(fig:plot-map-pca)).

CAPTION <- "Subplots created by logical conditions.  "
plot_map(
  faux_cell[, , 1500],
  spc ~ y * x | x > 5,
  col.regions = palette_matlab(20)
)

Conditioning on .wavelength{.r}

Function plot_map(){.r} automatically applies the function in func{.r} before plotting. Argument func{.r} defaults to function mean(){.r}. In order to suppress this, use func = NULL{.r}. This allows conditioning on the wavelengths.

Fig. \@ref(fig:plot-map-pca2) demonstrates an example to plot the maps of principal components scores.

CAPTION <- "The maps of the scores of the first two principal components (I).  "
pca <- prcomp(~spc, data = faux_cell_preproc$.)

scores <- decomposition(faux_cell, pca$x,
  label.wavelength = "PC",
  label.spc = "score /  a.u."
)

plot_map(
  scores[, , 1:3],
  spc ~ y * x | as.factor(.wavelength),
  func = NULL,
  col.regions = palette_matlab(20)
)

Alternatively, use levelplot(){.r} directly (Fig. \@ref(fig:plot-map-pca3)).

CAPTION <- "The maps of the scores of the first two principal components (II).  "
levelplot(
  spc ~ y * x | as.factor(.wavelength),
  scores[, , 1:3],
  aspect = "iso",
  col.regions = palette_matlab(20)
)

Voronoi Plot

Fig. \@ref(fig:voronoi-2) shows an example of a Voronoi plot. Voronoi uses panel.voronoi(){.r} from package latticeExtra[r cite_pkg("latticeExtra")].

CAPTION <- "Voronoi plot that uses non-default discrette colour palette.  "
plot_voronoi(
  sample(faux_cell, 300), region ~ x * y,
  col.regions = palette_matlab(20)
)

Mark Missing Spectra

If the spectra come from a rectangular grid, missing positions can be marked with the following panel function:

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, ...)
}

Fig. \@ref(fig:missing) shows the result.

CAPTION <- "Marks of missing spectra in a false-colour map.  "
plot_map(sample(faux_cell[, , 1200], length(faux_cell) - 20),
  col.regions = palette_matlab(20),
  col = "black",
  panel = mark.missing
)

Unevenly Spaced Measurement Grid

The panel function used by plot_map(){.r} defaults to panel.levelplot.raster(){.r} which assumes an evenly spaced measurement grid. Even if the spectra are measured on a nominally evenly spaced grid, the actual stage position may slightly vary due to positioning inaccuracy and some manufacturers (e.g., Kaiser) record the position reported by the stage rather than the position requested by the stage control. This leads to weird-looking output with holes, and possibly wrong columns (Fig. \@ref(fig:uneven-I)).

uneven <- faux_cell[, , 1200]
uneven$x <- uneven$x + round(rnorm(nrow(uneven), sd = 0.05), digits = 1)
uneven$y <- uneven$y + round(rnorm(nrow(uneven), sd = 0.05), digits = 1)
CAPTION <- "Unevenly spaced measurement grid: example I.
Note warnings `values are not equispaced; output may be wrong`."
plot_map(uneven)

The symptom of this situation are warnings about values in x and/or y not being equispaced; and that the output, therefore, may be wrong.

One possibility to obtain a correct map is using plot_voronoi(){.r} instead which will construct a mosaic-like image with the respective "pixel" areas being centred around the actually recorded $x and $y position (Fig. \@ref(fig:uneven-II)).

CAPTION <- "Unevenly spaced measurement grid: example II.  "
plot_voronoi(uneven, backend = "deldir")

Another possibility that underlines a point shape of the measurements is switching to latticeExtra::panel.levelplot.points(){.r} (Fig. \@ref(fig:uneven-III)).

CAPTION <- "Unevenly spaced measurement grid: example III.  "
plot_map(
  uneven,
  panel = panel.levelplot.points,
  cex = 0.75,
  col.symbol = NA
)

Alternatively, the measurement raster positions can be rounded to their nominal raster (e.g. Fig. \@ref(fig:uneven-IV)).

CAPTION <- "Unevenly spaced measurement grid: example IV.  "
rx <- raster_make(uneven$x, startx = -11.55, d = 1, tol = 0.3)
uneven$x <- rx$x

ry <- raster_make(uneven$y, startx = -4.77, d = 1, tol = 0.3)
uneven$y <- ry$x

plot_map(uneven)

3D Plots (with package rgl) {#plots-3d}

Package rgl[r cite_pkg("rgl")] offers fast 3d plotting in R. As package rgl's axis annotations are sometimes awkward, they may better be set manually:

library(rgl)

laser <- laser [, , 404.8 ~ 405.6] / 10000
laser$t <- laser$t / 3600
cols <- rep(palette_matlab(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("lambda / nm", "y--", line = 2.5)
mtext3d("I / a.u.", edge = "z--", line = 2.5)
CAPTION <- "A snapshot of an **rgl** plot.  "
knitr::include_graphics("plotting--fig-3D-01.png")

``{block, type="note-t", echo=show_reviewers_notes} **V. Gegzna's notes**plotting-3`

  1. FIXME:{.r} Is the block below needed?
<!-- ======================================================================= -->

```r
# FIXME: is this code block still needed?

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()
}

Interactive Graphics {#interactive-plots}

Package hyperSpec offers basic interaction, identify_spc(){.r} for spectra plots, and map.identify(){.r} and map.sel.poly(){.r} for maps. The first two identify points in spectra plots and map plots, respectively. Function map.sel.poly(){.r} selects the part of a hyperSpec{.r} object that lies inside the user defined polygon.

identify_spc(){.r} Finding Out Wavelength, Intensity and Spectrum {#sec:identify_spc}

Function identify_spc(){.r} allows to measure points in graphics produced by plot_spc(){.r}. It works correctly with reversed and cut wavelength axes.

identify_spc(plot_spc(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.

map.identify(){.r} finding a spectrum in a map plot {#sec:map.identify}

Function map.identify(){.r} returns the spectra indices of the clicked points.

map.identify(faux_cell[, , 1200])

map.sel.poly(){.r} selecting spectra inside a polygon in a map plot {#sec:map.sel.poly}

Function map.sel.poly(){.r} returns a logical indicating which spectra are inside the polygon drawn by the user:

map.sel.poly(faux_cell[, , 1200])

Related Functions Provided by Base Graphics and lattice {#sec:identify-other}

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

For lattice graphics, grid.locator(){.r} may be used instead. If it is not called in the panel function, a preceding call to trellis.focus(){.r} is needed:

plot(laser, "mat")
trellis.focus()
grid.locator()

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

Troubleshooting {#sec:troubleshooting}

No Output Is Produced {#sec:no-output-produced}

Methods plot_map{.r}, plot_voronoi{.r}, levelplot{.r}, and plot_c{.r} use package lattice functions. Therefore, in loops, functions, Sweave, R Markdown chunks, etc. the lattice object needs to be printed explicitly by print(plot_map(object)){.r} (R FAQ: Why do lattice/trellis graphics not work?). The same holds for package ggplot2 graphics.

Session Info {-}

sessioninfo::session_info("hyperSpec")

References {-}



r-hyperspec/hyperSpec documentation built on May 31, 2024, 5:53 p.m.