ggspectra 0.2.1
Plot Methods

Pedro J. Aphalo

2017-03-20

Introduction

Package ggspectra extends ggplot2 with stats, geoms and annotations suitable for light spectra. It also defines ggplot() and plot() methods specialized for the classes defined in package photobiology for storing different types of spectral data. This vignette describes the use of these plot methods.

Although the package uses internally ggplot2, photobiology and photobiologyWavebands it does not re-export these packages, which need to loaded if used.

library(ggplot2)
library(photobiology)
library(photobiologyWavebands)
library(ggspectra)

We bind two spectra into an object to be used later to demonstrate grouping.

two_suns.spct <- rbindspct(list(sun1 = sun.spct, sun2 = sun.spct * 2))

We change the default theme.

theme_set(theme_bw(10))

Plotting spectra

The most automatic way of plotting spectral data stored in one of the classes defined in package photobiology is to use the plot()methods. These go much further than the plot() method defined in base-R for numeric data, as these classes store metadata that allows the automatic construction of axis labels as quantities and units are well defined.

Here we use the same example source_spct object from package photobiology used in the User Guide. In contrast to the examples in the User Guide, here we obtain with a very simple statement a complete annotated plot of the solar spectrum at ground level.

plot(sun.spct)

Although the defaults provide a useful plot, the plot() methods accepts arguments for several parameters that allow to tweak the looks and contents of the plots without explicit manipulation of the spectral data.

Summary quantities in labels

In this first example we pass "mean" as argument to label.qty, to print means instead of integrals in the labels. Note that the units and quantity labels for the waveband summaries have also changed.

plot(sun.spct, label.qty = "mean")

Two label.qty values need explanation. The first one, "relative" displays in labels the relative contribution of the integral of each waveband, to the sum of the integrals of all wavebands. The second one, "contribution" displays in labels the integral of each waveband divided by the integral of the whole spectrum. Consequently, this second option should be interpreted with caution, as the spectral data is unlikely in many cases to include the whole emission or absorption spectrum of a source.

plot(sun.spct, label.qty = "contribution")

plot(sun.spct, label.qty = "relative")

plot(sun.spct, label.qty = "mean", unit.out = "photon")

plot(sun.spct, label.qty = "relative.pc")

We can change the basis of expression of spectral irradiance and irradiance from "energy" to "photon". Be aware that by design, all values, summaries and spectral data will always use the same base of expression.

plot(sun.spct, unit.out = "photon")

Automatic annotations

Which annotations are included can be controlled through parameter annotations. These are passed as a vector of character strings, with three values with special meaning for the first element (with index = 1): "=" means use only the annotations that follow in the vector, "+" means add to the default the annotations that follow, and "-" means remove the annotations that follow from the defaults. A NULL value means use defaults as is, "" means no annotations, and "reserve.space" means no annotations, but expand axis limits and set identity scales ready for mannually adding annotations.

annotation default for classes overrides
“boxes” all
“segments” none “boxes”
“color.guide” all
“peaks” all
“peak.labels” none “peaks”
“valleys” none
“valley.labels” none “valleys”
“labels” all
“summaries” source_spct, response_spct, filter_spct, reflector_spct

We can list all the annotations to be included in the plot, in which case "=" is optional so as to maintain compatibility with earlier versions.

plot(sun.spct, 
     annotations = c("=", "segments", "labels", "summaries", "color.guide", "peaks"))

The same plot can be obtained by simply adding "segments", as these override the default "boxes".

plot(sun.spct, 
     annotations = c("+", "segments"))

We can also remove some of the default annotations.

plot(sun.spct, annotations = c("-", "summaries", "peaks"))

We add "valleys" as annotations, and control with span how near peaks and valleys are found.

plot(sun.spct, annotations = c("+", "valleys"), span = 41)

The annotations "peak.labels" and "valley.labels" overridde "peaks" and "valleys". They use the repulsive geometry geom_label_repel from package ‘ggrepel’.

plot(sun.spct, annotations = c("+", "peak.labels", "valley.labels"), span = 41)

Passing "" as argument to annotations results in a plot with no annotations, and no scales set.

plot(sun.spct, annotations = "")

Passing "reserve.space" as argument to annotations results in a plot with no annotations, but scales set and expanded so as to receive annotations.

plot(sun.spct, annotations = "reserve.space")

The size of the font used for the annotations is controlled by argument text.size.

plot(sun.spct, annotations = c("=", "segments", "labels", "color.guide"), 
     text.size = 3.5)

Arguments range and w.band play very different roles. The first one determines the range of wavelengths to include in the data plotted, which is slightly different to the effect of ggplot2::xlim() as range is used to trim the spectral data before passing it to ggplot, using interpolation when needed (see photobiology::trim_wl()). The second one, w.band is only used for the annotations and decorations. It should be however noted, that a waveband object is a valid argument for both range and w.band.

plot(sun.spct, range = VIS())

plot(sun.spct, w.band = PAR())

plot(sun.spct, w.band = CIE())

NULL as argument for w.band is replaced by a waveband covering the full range of the spectral datat.

plot(sun.spct, w.band = NULL)

The whole range is the range plotted, which is controlled by the argument passed to range.

plot(sun.spct, w.band = NULL, range = c(400,700))

The argument passed to range can be a waveband or and spectrum, in which case their wavelength range is used.

plot(sun.spct, w.band = NULL, range = PAR())

plot(sun.spct, w.band = PAR(), range = PAR())

plot(sun.spct, w.band = VIS_bands(), range = VIS())

The time unit is also stored in the metadata, as demonstrated here. The units in axis labels have changed to the units used in the spectral data.

getTimeUnit(sun.daily.spct)
## [1] "day"
plot(sun.daily.spct)

Even though the plot() methods can return a finished plot, the returned object is a ggplot object and can be built upon by adding additional elements like facets, aesthetics and even additional layers.

plot(two_suns.spct, label.qty = "mean") + facet_wrap(~spct.idx)

When using grouping the "summaries" annotation would be overplotted, and needs to be suppressed.

plot(two_suns.spct, annotations = c("-", "summaries")) + 
  aes(linetype = spct.idx)

It is possible to construct and bind the spectra on-the-fly.

plot(rbindspct(list(sun = sun.spct, filtered = yellow_gel.spct * sun.spct)),
     annotations = c("-", "summaries")) + 
  aes(linetype = spct.idx)

In the examples above the source_spct object sun.spct was used. The plot() methods for other spectral classes have slight differences. We show some examples for filter_spct objects.

plot(yellow_gel.spct, annotations = c("-", "peaks"))

By default transmittance, reflectance and absorptance are expressed as fractions of one, as in the plot above, but optionally percents can be plotted.

plot(yellow_gel.spct, pc.out = TRUE, annotations = c("-", "peaks"))

In many cases it is possible to convert on-the-fly the quantity plotted.

plot(yellow_gel.spct, plot.qty = "absorbance", annotations = c("-", "peaks"))

We add a guessed spectral reflectance to the data object to allow the estimation of internal absorptance.

yellow_gel.spct$Rfr <- 1 - max(yellow_gel.spct$Tfr)
plot(yellow_gel.spct, plot.qty = "absorptance", annotations = c("-", "peaks"))

If one really needs to, one can add a suitable stat using ‘local’ data. A peak annotaion could be added manually.

plot(sun.spct) + geom_spct(fill = color(sun.spct)) + 
  geom_spct(data = yellow_gel.spct * sun.spct, color = "black", 
            fill = color(yellow_gel.spct * sun.spct))

Ploting collections of spectra

two_suns.mspct <- source_mspct(list(sun1 = sun.spct, sun2 = sun.spct * 2))

Plot as separate plots. This approach is specially useful with heterogeneous generic_mspct objects, although it works with any collection of spectra.

multiplot(plotlist = mslply(two_suns.mspct, plot))

Plot with one panel per spectrum by first converting the collection-of-spectra into a spectrum object.

plot(rbindspct(two_suns.mspct)) + facet_wrap(~spct.idx, ncol = 1)

Plot using grouping by first converting the collection-of-spectra into a spectrum object.

plot(rbindspct(two_suns.mspct), 
     annotations = c("-", "summaries")) + 
  aes(linetype = spct.idx)

Using colors is slightly more involved as the identity scale is in use. For this same reason no color key in generated automatically, and a single peak is found unless we change the default span. (In the case of more than two spectra it is easier to use plyr::mapvalues instead of several nested ifelse calls.)

plot(rbindspct(two_suns.mspct), 
     annotations = c("-", "summaries"), span = 301) + 
  aes(color = ifelse(spct.idx == "sun1", "darkgreen", "darkred"))

Plots created with plot() method can be used as the starting point for customizations.

plot(rbindspct(two_suns.mspct), annotations = "") + 
  aes(linetype = spct.idx) +
  wl_guide(ymax = -0.05)

Here we replace the default peaks annotations with a custom one, but still take advantage of other defaults like nice axis labels and other annotations.

plot(sun.spct, annotations = c("-", "peaks")) +
  stat_peaks(span = NULL, color = "red") +
  stat_peaks(span = NULL, geom = "text", 
             label.fmt = "max at %3.1f nm",
             vjust = -0.4, color = "red")

Plot using “lower-level” functions. See the ‘User Guide’ for additional details.

ggplot(rbindspct(two_suns.mspct)) + 
  aes(linetype = spct.idx) +
  wl_guide(ymax = -0.05) +
  geom_line()

Ploting wavebands

A plot() method for waveband objects is also provided.

plot(VIS())

plot(CIE(), range = CIE(), annotations = c("-", "color.guide"))

plot(DNA_N(), range = c(270, 420), annotations = c("-", "color.guide"))