Skip to contents

R-CMD-check pkgdown CRAN status Codecov test coverage CRAN downloads CRAN downloads total License: MIT Lifecycle: experimental

What is libscanR?

libscanR provides a vendor-agnostic pipeline for Laser-Induced Breakdown Spectroscopy (LIBS) data, including import, preprocessing, peak detection, calibration, quantification, chemometrics, spatial mapping, and visualization. It ships with a curated NIST emission line database and example datasets so every feature is runnable without real instrument data.

Core data structures

libscanR defines three S3 classes:

  • libs_spectrum — a single spectrum (possibly multi-shot).
  • libs_dataset — a collection of spectra sharing a wavelength axis.
  • libs_calibration — a fitted calibration model.

A 5-minute tour

Simulate a spectrum

spec <- ls_simulate_spectrum(
  elements = c(Ca = 5000, Na = 1000, Fe = 200),
  n_channels = 1024,
  seed = 1
)
spec
#> <libs_spectrum>
#>  Range: 200-900 nm (1024 channels)
#>  Shots: 10
#>  Sample: "simulated" (synthetic)
#>  Baseline corrected: FALSE

Plot it

ls_plot_spectrum(spec, show_elements = c("Ca", "Na"))

Preprocess: baseline, smooth, normalize

spec_proc <- spec |>
  ls_baseline(method = "snip", iterations = 40) |>
  ls_smooth(method = "moving_avg", window = 5) |>
  ls_normalize(method = "total")
ls_plot_spectrum(spec_proc)

Detect and identify peaks

peaks <- ls_find_peaks(spec_proc, snr_threshold = 3)
id <- ls_identify_peaks(peaks, elements = c("Ca", "Na", "Fe"))
head(id[, c("wavelength_nm", "element", "ionization", "nist_aki", "confidence")])
#> # A tibble: 6 × 5
#>   wavelength_nm element ionization nist_aki confidence
#>           <dbl> <chr>        <int>    <dbl>      <dbl>
#> 1          201. NA              NA    NA        NA    
#> 2          240. Ca               1     1.87      0.134
#> 3          212. NA              NA    NA        NA    
#> 4          218. NA              NA    NA        NA    
#> 5          223. NA              NA    NA        NA    
#> 6          231. NA              NA    NA        NA

Read from a file

tmp <- tempfile(fileext = ".csv")
utils::write.csv(
  data.frame(wavelength = spec$wavelength,
             intensity = colMeans(spec$intensity)),
  tmp, row.names = FALSE
)
spec_in <- ls_read_spectrum(tmp, verbose = FALSE)
unlink(tmp)
spec_in
#> <libs_spectrum>
#>  Range: 200-900 nm (1024 channels)
#>  Shots: 1
#>  Sample: "file1f1975b1acb6"
#>  Baseline corrected: FALSE

Use example datasets

ds <- ls_example_data("tissue")
summary(ds)
#> <libs_dataset> summary
#>  Spectra: 50
#>  Channels: 1024
#>  Range: 200-900 nm
#>  Group counts (column "material"):
#>  material  n
#>      bone 10
#>       fat 10
#>    kidney 10
#>     liver 10
#>    muscle 10
#>  Per-spectrum max intensity: median = 103.79, range =
#> 94.1-643.47

Use of LLM tools

Portions of this package were prepared with assistance from large language model tooling for narrowly defined, non-authorial tasks: copyediting, prose smoothing, Markdown/LaTeX formatting, scaffolding of boilerplate files (CI configs, build scripts), code refactoring. The tools used were Chat AI, the LLM service of KISSKI (GWDG), and a self-hosted Mistral Small (24B, Apache-2.0) run locally via Ollama and the ollamar R package — local inference only, with no data sent to third parties for the self-hosted model.

All scientific claims, methodological choices, analyses, interpretations, and conclusions are the author’s own. No LLM-generated text was incorporated without review and revision, and every reference was verified against its DOI, arXiv ID, or ISBN.