Underwater Light Analysis and Visual Ecology
luxR provides tools for quantifying and modelling underwater light environments. It propagates spectral irradiance through the water column via Beer-Lambert attenuation, converts between energy and photon-flux units, and estimates photoreceptor excitation and visual contrast.
# Release build from r-universe:
install.packages(
"luxR",
repos = c(
luxR = "https://johnkirwan.r-universe.dev",
CRAN = "https://cloud.r-project.org"
)
)
# Alternatively, install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("JohnKirwan/luxR")
library(luxR)
# Load a coastal irradiance profile as a lux_spectrum object
x <- from_naples("0m")
print(x)
#> <lux_spectrum> irradiance [umol/m2/s/nm] | 352.5-862.5 nm, 5 nm bins (103 pts)
# Convert units
x_W <- convert_unit(x, "W/m2/nm")
# Compute PAR and lux
par_irradiance(x_W) # µmol m⁻² s⁻¹
irradiance2lux(x_W) # lux
# Propagate to depth using a Jerlov Type II water model
x_prop <- x_W[350, 700] # bundled Jerlov Kd is supported here
lam <- x_prop$lambda
Kd_II <- jerlov_Kd("II", lam)
specs <- propagate_spectrum(x_prop, Kd_II, from = 0,
to = c(0, 5, 10, 20, 50))
plot(specs)
# Colour discrimination at depth
grey_R <- lux_spectrum(rep(0.3, length(lam)), lam,
quantity = "reflectance", unit = "dimensionless")
red_R <- lux_spectrum(0.2 + 0.25 * exp(-((lam - 625)/35)^2), lam,
quantity = "reflectance", unit = "dimensionless")
colour_jnd(
stim1 = reflectance_to_radiance(grey_R, specs[["0"]])$E,
stim2 = reflectance_to_radiance(red_R, specs[["0"]])$E,
lambda = lam,
species = "Danio rerio",
receptor = c("S-cone", "M-cone", "L-cone")
)
Default colour models use only cited chromatic receptor combinations from
species_channels. Rods, melanopsin channels, and incomplete receptor sets are
not silently treated as additional colour channels.
luxR's principal modeling tier is wavelength-resolved Beer–Lambert attenuation with a diffuse attenuation coefficient, Kd(λ). It assumes Kd is constant over the modeled path and propagates wavelength bins independently. It does not solve an angular radiance field, multiple scattering, or processes that move energy between wavelengths; use HydroLight, EcoLight, or WASI when those are required.
The bundled Jerlov table covers eight optical water types from 350–700 nm.
jerlov_Kd() fails outside that range by default; constant endpoint extension
must be explicitly requested and is recorded in result metadata. There is no
universal supported maximum depth—the chosen Kd must remain representative of
the full path. Inverse propagation is a homogeneous-column reconstruction and
can strongly amplify measurement noise.
| Area | Functions |
|---|---|
| Spectral class |
lux_spectrum(), convert_unit(), as_lux_spectrum()
|
| Depth propagation |
propagate_spectrum(), band_irradiance(), fit_Kd(), jerlov_Kd()
|
| Photometrics |
par_irradiance(), irradiance2lux(), scotopic_lux()
|
| File I/O |
from_naples(), from_solar(), read_trios(), from_trios(), read_ocean_optics(), from_ocean_optics()
|
| Visual ecology |
govardovskii_template(), quantum_catch(), colour_jnd()
|
| Visibility scenarios |
secchi_depth(), visual_range(), detection_range(), detectability()
|
| Interactive app | run_app() |
run_app() # requires the 'shiny' package
run_app() launches a bundled Shiny application with guided tabs including:
Full function reference and four vignettes are on the pkgdown site:
GPL (>= 3)