---
title: "User Guide: 3 Plotting transformed data"
subtitle: "'ggspectra' `r packageVersion('ggspectra')`"
author: "Pedro J. Aphalo"
date: "`r Sys.Date()`"
output: 
  rmarkdown::html_vignette:
    toc: yes
vignette: >
  %\VignetteIndexEntry{User Guide: 3 Plotting transformed data}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

## Introduction

Package `ggspectra` extends `ggplot2` with stats, geoms, scales and annotations suitable for light spectra. It also defines `ggplot()` and  `autoplot()` methods specialized for the classes defined in package `photobiology` for storing different types of spectral data. The `autoplot()` methods are described separately in vignette _User Guide: 2 Autoplot Methods_ and the `ggplot()` methods, statistics, and scales in _User Guide: 1 Grammar of Graphics_.

The new elements can be freely combined with methods and functions defined in packages 'ggplot2', `scales`, `ggrepel`, `cowplot` and other extensions to 'ggplot2'.

This third part of the User Guide describes how to combine manipulation of spectral data with plotting. This streamlined coding is made possible by the enhancement implemented in 'ggspectra' (>= 0.3.5). In addition, some of the examples make use of methods available only in 'photobiology' (>= 0.10.0).

In 'ggspectra' (>= 0.3.5) the data member of `gg` (ggplot) objects remains as an object of the classes for spectral data defined in 'photobiology' instead of being converted into a plain `data.frame`. This makes it possible data manipulations in layers to be done with methods specific to spectral data.

The examples in this vignette depend conditionally on packages 'rlang' and 
'magrittr'. If these packages are not avialble when the vignette is built, the
code chunks that require them are not evaluated.

## Set up 

```{r}
library(ggplot2)
library(photobiology)
library(photobiologyWavebands)
library(ggspectra)
# if suggested packages are available
magrittr_installed <- requireNamespace("magrittr", quietly = TRUE)
rlang_installed <- requireNamespace("rlang", quietly = TRUE)
eval_chunks <- magrittr_installed && rlang_installed
if (eval_chunks) {
  library(magrittr)
  library(rlang)
} else {
  message("Please, install packages 'rlang' and 'magrittr'.")
}
```

```{r, include=FALSE, echo=FALSE}
library(knitr)
opts_chunk$set(fig.align = 'center', 
               fig.show = 'hold', fig.width = 7, fig.height = 4,
               cache = FALSE)
options(warnPartialMatchArgs = FALSE)
```

Create a collection of two source_spct objects.

```{r}
two_suns.mspct <- source_mspct(list(sun1 = sun.spct, sun2 = sun.spct / 2))
```

We bind the two spectra in the collection into a single spectral object. This object
includes an indexing factor, by default named `spct.idx`. We use this new object to 
later on demonstrate grouping in ggplots.

```{r}
two_suns.spct <- rbindspct(two_suns.mspct)
```

We change the default theme.

```{r}
theme_set(theme_bw())
```

## Visualizing the effect of methods

In the past we needed to pass to the `data` parameter of layer functions always a data frame. A simple example passing spectral data to each layer function follows.

```{r, eval=eval_chunks}
ggplot() + 
  geom_line(data = sun.spct, mapping = aes(w.length, s.e.irrad)) + 
  geom_line(data = smooth_spct(sun.spct, method = "supsmu"), 
            mapping = aes(w.length, s.e.irrad), 
            colour = "red", linewidth = 1.2)
```

With this approach we can use R's own pipe operator to make it easier to see the intention of the code.

```{r, eval=eval_chunks}
ggplot() + 
  geom_line(data = sun.spct, mapping = aes(w.length, s.e.irrad)) + 
  geom_line(data = sun.spct |> smooth_spct(method = "supsmu"), 
            mapping = aes(w.length, s.e.irrad), 
            colour = "red", linewidth = 1.2)
```

The class of the spectral objects stored by calls to `ggplot()` methods specific
to them is not stripped, neither are other attributes used by package
'photobiology'. Consequently, transformations in layers using default `data` can
use methods from package 'photobiology'.

```{r, eval = eval_chunks}
p <- ggplot(sun.spct) + geom_line()
class(p$data)
```
To ensure that the same data are used in both plot layers the code can be simplified using `.` to refer to the default data in the ggplot object (`p$data` in the example above). The mapping to aesthetics remains valid because `smooth_spct()` returns a new `source_spct` object with the same column names as `sun.spct`, which was passed as argument to `data`. 

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_line() + 
  geom_line(data = . %>% smooth_spct(method = "supsmu"), 
            colour = "red", linewidth = 1.2)
```

The easiest approach to plotting photon spectral irradiance instead of spectral energy irradiance is to temporarily change the default radiation unit. An alternative approach is to replace the first two lines in the code chunk below by: `ggplot(sun.spct, unit.out = "photon")`.)

```{r, eval = eval_chunks}
photon_as_default()
ggplot(sun.spct) + 
  geom_line() + 
  geom_line(data = . %>% smooth_spct(method = "supsmu"), 
            colour = "red", linewidth = 1.2)
unset_radiation_unit_default()
```

Obviously, the default data does not need to be plotted, so this provides a roundabout way of applying methods,

```{r, eval=FALSE}
ggplot(sun.spct) + 
  geom_line(data = . %>% smooth_spct(method = "supsmu"), 
            colour = "red", linewidth = 1.2)
```
 
which is equivalent to doing the transformation ahead of plotting, which might be preferable.
 
```{r, eval=eval_chunks}
sun.spct |> 
  smooth_spct(method = "supsmu") |>
  ggplot() + 
  geom_line(colour = "red", linewidth = 1.2)
```

However, when using different transformations in different layers we need to apply them at each layer. 

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_line() + 
  geom_line(data = . %>% smooth_spct(method = "custom"), 
            colour = "blue", linewidth = 1) +
  geom_line(data = . %>% smooth_spct(method = "lowess"), 
            colour = "green", linewidth = 1) +
  geom_line(data = . %>% smooth_spct(method = "supsmu"), 
            colour = "red", linewidth = 1)
```

Of course, this approach works both with _geoms_ and _stats_, but one should remember that these layer functions do not "see" the original data object, but instead a new data frame containing the mapped variables in columns named according to _aesthetics_. The next example demostrates this and illustrates that smoothing displaces the wavelength of maximum spectral irradiance.

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_line() + 
  stat_peaks(size = 3, span = NULL) +
  stat_peaks(geom = "vline", linetype = "dotted", span = NULL) +
  geom_line(data = . %>% smooth_spct(method = "supsmu"), 
            colour = "red", linewidth = 1.2) +
  stat_peaks(data = . %>% smooth_spct(method = "supsmu"),
             colour = "red", size = 3, span = NULL) +
  stat_peaks(data = . %>% smooth_spct(method = "supsmu"),
             geom = "vline", colour = "red", 
             linetype = "dotted", span = NULL)
```

We can easily highlight a wavelength range by overplotting the line in a different color.

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_line() + 
  geom_line(data = . %>% trim_wl(range = PAR()), colour = "red")
```

We can highlight a range of wavelengths by plotting the points using colors matching human color vision.

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_line() + 
  geom_point(data = . %>% trim_wl(range = VIS()) %>% tag(),
            mapping = aes(color = wl.color),
            shape = "circle", size = 1.3) +
  scale_color_identity()
```

In the plot above, spectral irradiance is taken into account when computing the colors, while below, only the wavelength at the centre of each waveband is used.

```{r, eval = eval_chunks}
ggplot(sun.spct) + 
  geom_area(data = . %>% trim_wl(range = VIS()) %>% tag(w.band = VIS_bands()),
            mapping = aes(fill = wb.color)) +
  geom_line() + 
  scale_fill_identity()
```

Some of the methods from 'photobiology' are also defined for `data.frame` and can be used as summary functions with data that are not radiation spectra, such as any `data` _seen_ by layer functions including `stat_summary()`. Furthermore, on-the-fly summaries and transformation can be used in any ggplot layer function and with any suitable function acepting data frames as input.

