Convolve reflectance onto a sensor using only NOMINAL band characteristics (center wavelength + FWHM, or center + band edges) – for sensors with no real measured per-nm SRF curve available at all, approximated as a Gaussian response (optionally truncated to a published band edge range).
get.spectral.convolution.gaussian.Rdget.spectral.convolution.rfl() needs SMAC atmospheric-correction
coefficients bundled; get.spectral.convolution.srf() needs a real,
measured, per-nm SRF table. Neither exists for most sensors – often all
that is published (or all a student has, e.g. from an instrument's own
ENVI header, or their own camera calibration sheet) is a list of band
center wavelengths and full widths at half maximum (FWHM). This function
covers that case, from three possible inputs:
Usage
get.spectral.convolution.gaussian(
df = NULL,
sensor.i = NULL,
centers = NULL,
fwhm = NULL,
get.plots = FALSE,
rfl = NULL,
wave = NULL
)Arguments
- df
A data frame with a
wavecolumn (wavelength, nm) and anrflcolumn (reflectance) – same convention asget.spectral.convolution.rfl()/get.spectral.convolution.srf(). Used for a SINGLE spectrum; for many spectra at once (e.g. an entire LUT), userfl/waveinstead (see below) – much faster, vectorized as one matrix multiplication instead of one call per row.- sensor.i
Optional: a bundled sensor name (see above). If given,
centers/fwhmare looked up automatically and any values you also pass for them are ignored.- centers
Optional (required if
sensor.iis not given): your own sensor's band center wavelengths, nm.- fwhm
Optional: your own sensor's per-band FWHM, nm, same length and order as
centers. Derived from band spacing if omitted.- get.plots
logical, plot the convolved spectrum? Default
FALSE. Ignored whenrfl/wave(bulk mode) is used instead ofdf.- rfl
Optional: a matrix or data.frame of MANY reflectance spectra at once, one row per spectrum, columns matching
wave(e.g. a LUT's simulated reflectance matrix). When supplied (together withwave),dfis ignored and the whole matrix is convolved in one vectorized pass – this is the fast path for large tables.- wave
Required together with
rfl: the wavelength grid (nm)rfl's columns are on.
Value
Single-spectrum mode (df): a data frame with one row per band:
band (index), wl (center wavelength, nm), fwhm (nm), RFL
(convolved reflectance) – sorted by wl. Bulk mode (rfl/wave): a
numeric matrix, one row per input spectrum (same row order as rfl),
one column per band (named by center wavelength, sorted by wl); the
per-band wl/fwhm vectors are attached as attr(out, "wl") /
attr(out, "fwhm").
Details
sensor.i = "EnMAP"–ToolsRTM::EnMap.characteristics's 242 channels (center + FWHM already given).sensor.i= one ofunique(ToolsRTM::sensor.characteristics$Sensor)("ALI", "Hyperion", "Landsat4", "Landsat5", "Landsat7", "Landsat8", "MODIS", "Quickbird", "RapidEye", "Sentinel2a", "Sentinel2b", "WorldView2-4", "WorldView2-8") – these ship published band edges (lb/ub), not FWHM directly; FWHM is derived asub - lband the Gaussian response is additionally hard-truncated to[lb, ub](same conventionget.srf.from_fwhm()already uses for these sensors). (Sentinel-2A/B and PRISMA have a REAL measured SRF table bundled instead – useget.spectral.convolution.srf()for those, it's more accurate than this Gaussian approximation.)Your OWN sensor/camera: supply
centersyourself, in nm (e.g. copied straight out of an ENVI header'swavelength = {...}block).fwhmis optional – if omitted, each band's width is approximated from its distance to its neighboring bands (the standard assumption for a CONTIGUOUS pushbroom imaging spectrometer, e.g. a Headwall camera, where the true per-band SRF calibration isn't available). If you do know each band's real FWHM (e.g. from a camera datasheet, or an ENVI header that includes anfwhm = {...}block), pass it explicitly for a more accurate result.
Examples
df <- data.frame(wave = ToolsRTM::dataSpec_PDB[, 1],
rfl = 0.05 + 0.3 * ToolsRTM::dataSpec_PDB[, 1] / 2500)
# A bundled sensor with only nominal characteristics (no measured SRF):
enmap_bands <- get.spectral.convolution.gaussian(df, sensor.i = "EnMAP")
modis_bands <- get.spectral.convolution.gaussian(df, sensor.i = "MODIS")
# Your OWN sensor -- e.g. a 3-camera 15-band synchronized rig, with
# known band center + FWHM for every band:
own_centers <- c(444, 475, 502, 531, 550, 560, 570, 650, 668, 678, 705, 717, 740, 754, 842)
own_fwhm <- c(28, 32, 18, 14, 12, 27, 14, 16, 14, 14, 10, 12, 18, 10, 57)
own_bands <- get.spectral.convolution.gaussian(df, centers = own_centers, fwhm = own_fwhm)
# A pushbroom imaging spectrometer's own band list from its ENVI header
# (e.g. a Headwall camera) -- only wavelength centers known, no FWHM:
headwall_centers <- c(398.02, 400.25, 402.48, 404.71, 406.94) # (truncated example)
headwall_bands <- get.spectral.convolution.gaussian(df, centers = headwall_centers)
# Bulk mode: an entire LUT's reflectance matrix at once (fast, vectorized)
wave <- 400:2500
rfl_matrix <- matrix(0.05 + 0.3 * wave / 2500, nrow = 50, ncol = length(wave), byrow = TRUE)
bulk_bands <- get.spectral.convolution.gaussian(centers = own_centers, fwhm = own_fwhm,
rfl = rfl_matrix, wave = wave)