---
title: "User Guide: 1 Data and their use"
subtitle: "Package 'photobiologyLEDs' `r packageVersion('photobiologyLEDs')` "
author: "Pedro J. Aphalo"
date: "`r Sys.Date()`"
output: 
  rmarkdown::html_vignette:
    toc: yes
vignette: >
  %\VignetteIndexEntry{User Guide: 1 Data and their use}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, echo=FALSE}
knitr::opts_chunk$set(fig.width=8, fig.height=4)
```

## Introduction

This package, is a data only package, part of a suite, which has package 
'photobiology' at its core. Please visit (https://www.r4photobiology.info/) 
for more details. For more details on plotting spectra, please consult the 
documentation for package 'ggspectra', and for information on the calculation 
of summaries and maths operations  between spectra, please, consult the 
documentation for package 'photobiology'.

As packages 'photobiologyWavebands' and 'ggspectra' are only suggested, in this
vignette they are loaded and used conditionally on its availability.

```{r, message=FALSE}
library(photobiology)
library(photobiologyLEDs)
# Are the packages used in examples installed?
eval_bands <- requireNamespace("photobiologyWavebands", quietly = TRUE)
if (eval_bands) library(photobiologyWavebands)
eval_plots <- eval_bands && requireNamespace("ggspectra", quietly = TRUE)
if (eval_plots) library(ggspectra)
```

In this brief User Guide we describe how to re-scale the normalized
spectra, and how to access individual spectra or subsets of spectra.

## The data

The spectral data have been acquired mostly with one instrument, an array
spectrometer. However, some spectra have been measured with another 
spectrometer that has lower wavelength resolution. This difference in
resolution and slit function can give, for the same LED, measured peaks 
of slightly different width. This is an inevitable artefact of spectral 
measurements, but as LEDs have relatively wide peaks the distortion is small.
With well calibrated spectrometers, the area under a peak should not be
affected by the difference in wavelength resolution.

The spectral data in this package are stored in three R objects, each of them a
collection of spectra of class `source_spct`. Most of the spectra are in data
object `leds.mspct`. Data object `COB_reflectors.mspct` contains spectra for a
single COB LED combined with different reflectors while data object
`COB_dimming.mspct` contains a collection of spectra from the same LED when
driven at different currents.

Individual or subsets of spectra can be retrieved by _name_. The package
includes also several `character` vectors of _names_, each one containing names
for LEDs of a given _colour_, from a given _manufacturer_ or intended mainly for
a specific use. These are listed in the help index for the package. The _names_
used are in most cases the codes used by the manufacturers for the given type.
Any dashes in these codes have been replaced by underscores.

```{r}
blue_leds
```

```{r}
LedEngin_leds
```

## Accessing individual spectra

The `source_spct` member objects in `leds.mspct` can be accessed through their
names or through a numeric index. As the numeric indexes are likely to change 
with updates to the package, their use is discouraged. Names as character
strings should be used instead. The names are listed in the documentation
and also available through the "Data Catalogue" vignette. They can also be
listed with method `names()`.


```{r}
names(COB_reflectors.mspct)
```

```{r}
names(COB_dimming.mspct)
```

```{r}
names(leds.mspct)
```

```{r}
names(led_arrays.mspct)
```

We can use a character string as index to extract an individual `source_spct`
object.

```{r}
leds.mspct$Roithner_UV395
```

```{r}
leds.mspct[["Roithner_UV395"]]
```

Be aware that according to R's rules, using single square brackets will return
a `source_mspct` object, a collection of spectra, possibly of length one. This 
statement is not equivalent to the one in the chunk immediately above.

```{r}
leds.mspct["Roithner_UV395"]
```

Of course, with this syntax it is possible to use a vector of member names.

## Accessing subsets of spectra

We can subset the `source_mspct` object by indexing with vectors of character
strings. The package provides some predefined ones, and users can easily
define their own, either as constants or through computation. Here we use
a vector defined by the package.

```{r}
leds.mspct[Norlux_leds]
```

And below we use a computed one. In this case we extract the member spectra
with names containing the string "QDDH".

```{r}
leds.mspct[grep("QDDH", names(leds.mspct))]
```

## Querying metadata

If package 'photobiology' is loaded then the specialised `print()` method will be
used and a summary of the metadata will be included in the header of the
printout.

```{r}
leds.mspct$LedEngin_LZ1_10R302_740nm
```

```{r}
cat(getWhatMeasured(leds.mspct$LedEngin_LZ1_10R302_740nm))
```

```{r}
getWhenMeasured(leds.mspct$LedEngin_LZ1_10R302_740nm)
```

```{r}
getInstrDesc(leds.mspct$LedEngin_LZ1_10R302_740nm)
```

```{r}
getInstrSettings(leds.mspct$LedEngin_LZ1_10R302_740nm)
```

```{r}
is_normalized(leds.mspct$LedEngin_LZ1_10R302_740nm)
```

```{r}
leds.mspct$Roithner_UVMAX305
```

```{r}
is_normalized(leds.mspct$Roithner_UVMAX305)
```

## Calculating summaries from the normalized data

The spectra in `leds.mspct` and `led_arrays.mspct` are normalized, and
consequently, several summaries that are normally expressed in absolute units
are undefined, and trigger errors. Summaries like waveband ratios and
photon:energy ratios which are not affected by normalization are allowed and
valid. The data have been normalized when the measuring conditions used are not
well known, and in many cases not well characterized (e.g. distance from LED to
cosine diffuser or exact alignment of the spectrometer input optics with respect
to light source was not recorded or attempted at the time of measurement).

_It is important to keep in mind that normalization based on peak energy emission and based on peak photon emission in most cases differ._ In some situations the normalization will be
automatically updated when data are converted between these to bases of 
expression. One example are `autoplot()` methods from package 'ggspectra'.

What we will do in this section is to rescale the spectral data so that after 
conversion a given target value for a summary quantity will be true. As an 
example, we will rescale one spectrum so that it yields an energy irradiance of
10 W m-2 for the range 315 to 400 nm.

```{r}
my.spct <- fscale(leds.mspct$Roithner_UV395,
                  range = c(315, 400),
                  e_irrad,
                  target = 10
                  )
e_irrad(my.spct, waveband(c(315,400)))
```

The default of `fscale()` is to treat rescaled spectral data as if they were 
true readings unless `target = 1` is passed. In this last case, the metadata
will be set to indicate that the data is in relative units and this will
generate a warning during computation of irradiance. Other methods such as 
`integrate_spct()` will still function silently.

```{r}
my.spct <- fscale(leds.mspct$Roithner_UV395,
                  range = c(315, 400),
                  e_irrad,
                  target = 1
                  )
integrate_spct(my.spct)
```

We can reset the attribute with method `setScaled()`. With 
method `getScaled()` we can test if a spectrum has been scaled.

```{r}
setScaled(my.spct)
getScaled(my.spct)
```
```{r}
e_irrad(my.spct, waveband(c(315,400)))
```

If for some obscure reason we want to simply "pretend" that the spectral data
have not been normalized, we can permanently override the attribute on a copy 
of the data. Most of the time this is a bad idea!

```{r}
my.UV395 <- leds.mspct$Roithner_UV395
setNormalized(my.UV395)
e_irrad(my.UV395)
```

As mentioned above, ratios can be calculated directly as they are not affected
by normalization.

```{r}
q_ratio(leds.mspct$Roithner_UV395, UVB(), UVA())
```

## Plotting

Spectra can be plotted in the same ways as other data stored in
data frames, using base R graphics, package 'lattice' or 'ggplot2'. However, another
package in this suite, 'ggspectra', built as an extension to 'ggplot2' makes 
plotting spectra even easier.

`autoplot()` methods use the metadata in the objects to set labels and decorations,
as well as automatically setting the mapping of the _x_ and _y_ aesthetics.

```{r, eval=eval_plots}
autoplot(leds.mspct$LedEngin_LZ1_10R302_740nm, annotations = c("+", "wls"))
```

Multiple LEDs can be plotted together.

```{r, eval=eval_plots}
autoplot(leds.mspct[Osram_leds]) + 
  theme(legend.position = "bottom")
```

They can alternatively be plotted in separate panels.

```{r, eval=eval_plots, fig.asp=1}
autoplot(leds.mspct[Osram_leds], facets = 1) # 1 column
```

Package 'ggspectra' also defines specializations of method `ggplot()` for 
spectra, that by default set the aesthetic mapping automatically.

```{r, eval=eval_plots}
ggplot(leds.mspct$LedEngin_LZ1_10R302_740nm) +
  geom_line()
```

## Using the data in other contexts

As `source_spct` is a class derived from `list`, and `source_spct` is derived from
`tibble::tible` which is a rather compatible reimplementation of `data.frame` the
data can be used very easily with any R function.

```{r}
head(as.data.frame(leds.mspct$LedEngin_LZ1_10R302_740nm))
```

Of course `attach` and `with` also work as expected.

```{r, eval=eval_bands}
attach(leds.mspct)
q_ratio(Roithner_UV395, UVB(), UVA())
detach(leds.mspct)
```

```{r}
attach(leds.mspct)
with(Roithner_UV395, max(w.length))
detach(leds.mspct)
```

```{r, eval=eval_bands}
with(leds.mspct, q_ratio(Roithner_UV395, UVB(), UVA()))
```
