---
title: "Preprocessing Workflow"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Preprocessing Workflow}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
resource_files:
- figures/logo.svg
- figures/logo-dark.svg
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.width = 7,
fig.height = 4.5,
message = FALSE,
warning = FALSE
)
```
```{r load}
library(libscanR)
```
LIBS spectra typically contain a continuum background, electronic noise,
and shot-to-shot intensity variation. `libscanR` provides chainable
preprocessing primitives: baseline correction, normalization, smoothing,
cropping, and shot averaging.
## Baseline correction
Four methods are supported: `snip`, `als`, `rolling_ball`, `linear`,
`polynomial`. SNIP and ALS are the workhorses for LIBS continuum removal.
```{r baseline, fig.alt="Three curves compare the raw fictional spectrum with SNIP and ALS baseline-corrected intensities on the same wavelength axis."}
spec <- ls_simulate_spectrum(line_data = ls_demo_peaks(),
elements = c(Ca = 5000, Na = 1000, K = 800, Fe = 200),
n_channels = 1024, seed = 1
)
snip <- ls_baseline(spec, method = "snip", iterations = 60)
als <- ls_baseline(spec, method = "als", iterations = 10, lambda = 1e5)
df <- rbind(
data.frame(w = spec$wavelength,
y = libscanR:::.mean_intensity(spec),
method = "raw"),
data.frame(w = spec$wavelength,
y = libscanR:::.mean_intensity(snip),
method = "SNIP"),
data.frame(w = spec$wavelength,
y = libscanR:::.mean_intensity(als),
method = "ALS")
)
ggplot2::ggplot(df, ggplot2::aes(w, y, colour = method)) +
ggplot2::geom_line() + theme_libs() +
ggplot2::labs(x = "Wavelength (nm)", y = "Intensity (a.u.)")
```
## Normalization
Five options:
```{r normalize}
norm_total <- ls_normalize(snip, method = "total")
cat("sum after total normalization:",
round(sum(norm_total$intensity[1, ]), 2), "\n")
norm_is <- ls_normalize(snip, method = "internal_std", ref_wavelength = 589)
```
## Smoothing
```{r smooth, fig.alt="The 380 to 410 nm region of the fictional spectrum after SNIP baseline correction and seven-channel moving-average smoothing."}
sm <- ls_smooth(snip, method = "moving_avg", window = 7)
ls_plot_region(sm, 380, 410)
```
## Averaging replicate shots with outlier removal
```{r avg}
multi <- ls_simulate_spectrum(line_data = ls_demo_peaks(), seed = 1, n_channels = 512, n_shots = 20,
noise_level = 0.05)
avg <- ls_average_shots(multi, remove_outliers = TRUE)
avg$n_shots
```
## Cropping
```{r crop, fig.alt="SNIP-corrected fictional spectrum cropped to 380 through 450 nm, showing the simulated peak near the Ca-labelled teaching window."}
ca_region <- ls_crop(snip, 380, 450)
ls_plot_spectrum(ca_region)
```
## Recommended pipeline
```{r pipeline, fig.alt="Fictional spectrum after the recommended SNIP, five-channel moving-average and total-normalization pipeline, plotted against wavelength."}
processed <- spec |>
ls_baseline(method = "snip", iterations = 60) |>
ls_smooth(method = "moving_avg", window = 5) |>
ls_normalize(method = "total")
ls_plot_spectrum(processed)
```