diff --git a/DESCRIPTION b/DESCRIPTION index 681be9a6..a7119cac 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -210,6 +210,7 @@ Collate: 'trellis.factor.key.R' 'vandermonde.R' 'wl.R' + 'wl_fix_unit_name.R' 'wl_convert_units.R' 'wl_sort.R' 'write_txt_long.R' diff --git a/R/wl_convert_units.R b/R/wl_convert_units.R index 799c6fd9..266c7112 100644 --- a/R/wl_convert_units.R +++ b/R/wl_convert_units.R @@ -22,6 +22,8 @@ #' @return Object of the same class as input `x`. #' #' @concept wavelengths +#' @include wl_fix_unit_name.R +#' @include hyperspec-class.R #' #' @export #' @@ -78,69 +80,28 @@ wl_convert_units.hyperSpec <- function(x, from, to, ref_wl = NULL) { # Helper functions ----------------------------------------------------------- -wl_ev2freq <- function(x, ...) wl_nm2freq(wl_ev2nm(x)) -wl_ev2invcm <- function(x, ...) q * x / (100 * h * c) -wl_ev2nm <- function(x, ...) 1e9 * h * c / (q * x) -wl_ev2raman <- function(x, ref_wl) 1e7 / ref_wl - x * q / (100 * h * c) -wl_freq2ev <- function(x, ...) wl_nm2ev(wl_freq2nm(x)) -wl_freq2invcm <- function(x, ...) wl_nm2invcm(wl_freq2nm(x)) -wl_freq2nm <- function(x, ...) 1e-3 * c / x -wl_freq2raman <- function(x, ref_wl) wl_nm2raman(wl_freq2nm(x), ref_wl) -wl_invcm2ev <- function(x, ...) 100 * x * c * h / q -wl_invcm2freq <- function(x, ...) wl_nm2freq(wl_invcm2nm(x)) -wl_invcm2nm <- function(x, ...) 1e7 / x +wl_ev2freq <- function(x, ...) wl_nm2freq(wl_ev2nm(x)) +wl_ev2invcm <- function(x, ...) q * x / (100 * h * c) +wl_ev2nm <- function(x, ...) 1e9 * h * c / (q * x) +wl_ev2raman <- function(x, ref_wl) 1e7 / ref_wl - x * q / (100 * h * c) +wl_freq2ev <- function(x, ...) wl_nm2ev(wl_freq2nm(x)) +wl_freq2invcm <- function(x, ...) wl_nm2invcm(wl_freq2nm(x)) +wl_freq2nm <- function(x, ...) 1e-3 * c / x +wl_freq2raman <- function(x, ref_wl) wl_nm2raman(wl_freq2nm(x), ref_wl) +wl_invcm2ev <- function(x, ...) 100 * x * c * h / q +wl_invcm2freq <- function(x, ...) wl_nm2freq(wl_invcm2nm(x)) +wl_invcm2nm <- function(x, ...) 1e7 / x wl_invcm2raman <- function(x, ref_wl) 1e7 / ref_wl - x -wl_nm2ev <- function(x, ...) 1e9 * h * c / (q * x) -wl_nm2freq <- function(x, ...) 1e-3 * c / x -wl_nm2invcm <- function(x, ...) 1e7 / x -wl_nm2raman <- function(x, ref_wl) 1e7 * (1 / ref_wl - 1 / x) -wl_raman2ev <- function(x, ref_wl) 100 * h * c * (1e7 / ref_wl - x) / q -wl_raman2freq <- function(x, ref_wl) wl_nm2freq(wl_raman2nm(x, ref_wl)) +wl_nm2ev <- function(x, ...) 1e9 * h * c / (q * x) +wl_nm2freq <- function(x, ...) 1e-3 * c / x +wl_nm2invcm <- function(x, ...) 1e7 / x +wl_nm2raman <- function(x, ref_wl) 1e7 * (1 / ref_wl - 1 / x) +wl_raman2ev <- function(x, ref_wl) 100 * h * c * (1e7 / ref_wl - x) / q +wl_raman2freq <- function(x, ref_wl) wl_nm2freq(wl_raman2nm(x, ref_wl)) wl_raman2invcm <- function(x, ref_wl) 1e7 / ref_wl - x -wl_raman2nm <- function(x, ref_wl) 1e7 / (1e7 / ref_wl - x) +wl_raman2nm <- function(x, ref_wl) 1e7 / (1e7 / ref_wl - x) -# Bring the argument to a conventional name - -# FIXME: This function should be documented. -# Even if it used for internal purposes. -# -#' @export -.wl_fix_unit_name <- function(unit, null_ok = FALSE) { - - # Allow NULL as the default value - if (isTRUE(null_ok)) { - if (is.null(unit)) { - return(unit) - } - } - - - unit <- gsub(" .*$", "", tolower(unit)) - if (unit %in% c("raman", "stokes", "rel", "rel.", "relative", "rel.cm-1", "rel.cm", "rel.1/cm", "raman shift")) { - return("raman") - } - if (unit %in% c("invcm", "energy", "wavenumber", "cm-1", "cm^-1", "cm^{-1}", "inverted", "cm", "1/cm")) { - return("invcm") - } - if (unit %in% c("nm", "nanometer", "wavelength")) { - return("nm") - } - if (unit %in% c("ev", "electronvolt")) { - return("ev") - } - if (unit %in% c("freq", "frequency", "thz", "terahertz")) { - return("freq") - } - if (unit %in% c("pixel", "px", "sensor")) { - return("px") - } - if (unit == "file") { - return(unit) - } - stop(paste0("'", unit, "': Unknown unit type")) -} - # Some physical constants ---------------------------------------------------- # @concept constants @@ -187,23 +148,6 @@ hySpc.testthat::test(wl) <- function() { }) } -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -hySpc.testthat::test(.wl_fix_unit_name) <- function() { - context(".wl_fix_unit_name") - - test_that(".wl_fix_unit_name() works", { - expect_equal(.wl_fix_unit_name("raman"), "raman") - expect_equal(.wl_fix_unit_name("invcm"), "invcm") - expect_equal(.wl_fix_unit_name("nm"), "nm") - expect_equal(.wl_fix_unit_name("ev"), "ev") - expect_equal(.wl_fix_unit_name("freq"), "freq") - expect_equal(.wl_fix_unit_name("px"), "px") - expect_equal(.wl_fix_unit_name("file"), "file") - expect_error(.wl_fix_unit_name("ddd"), "Unknown unit type") - }) - - # TODO (tests): add more specific tests. -} # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hySpc.testthat::test(wl_convert_units) <- function() { diff --git a/R/wl_fix_unit_name.R b/R/wl_fix_unit_name.R new file mode 100644 index 00000000..ef95ab48 --- /dev/null +++ b/R/wl_fix_unit_name.R @@ -0,0 +1,126 @@ +#' Bring argument to a conventional name +#' +#' @description +#' Fix a string with unit name (for wavelength axis) into a sting that +#' can be used as a standardized argument value for other \pkg{hyperSpec} +#' functions, e.g., [wl_convert_units()]. +#' +#' **Note:** This function is usually used internally in other \pkg{hyperSpec} +#' functions. +#' +#' @param unit (sting): +#' A name, abbreviation or shot description of unit for wavelength axis. +#' +#' @param null_ok (logical): +#' If `unit = NULL` and `null_ok = TRUE`, the function will not fail and +#' will return `NULL`. +#' +#' @param on_failure (string): +#' The type of behavior in case unrecognized value of `unit` is passed +#' (i.e., in case of failure to convert to a standardized value): +#' - `"fail"` -- the code is stopped with an error message. +#' - `"warn"` -- a warning is issued and the value of `unit` is returned as +#' an output. +#' - `"pass"` -- the value of `unit` is returned as an output and no error nor +#' warning is issued. +#' +#' +#' @return +#' The function returns one of these "standard" values: +#' - `"raman"` for Raman shift in relative 1/cm; +#' - `"invcm"` for inverted centimeters (1/cm); +#' - `"nm"` for nanometers (nm); +#' - `"ev"` for electron volts (eV); +#' - `"freq"` for frequency (THz); +#' - `"px"` for pixels. +#' +#' +#' @seealso [wl_convert_units()] +#' @author R. Kiselev, V. Gegzna +#' +#' @export +#' +#' @examples +#' .wl_fix_unit_name("wavelength") +.wl_fix_unit_name <- function(unit, null_ok = FALSE, on_failure = "fail") { + + on_failure <- match.arg(tolower(on_failure), c("fail", "warn", "pass")) + unit0 <- unit + # Allow NULL as the default value + if (isTRUE(null_ok)) { + if (is.null(unit)) { + return(unit) + } + } + + + unit <- gsub(" .*$", "", tolower(unit)) # remove everything after space + unit <- gsub("[ ._]*", "", unit) # remove spaces, dots and underscores + + if (unit %in% c("rel", "relative", "relcm-1", "rel1/cm", "relcm", + "raman", "ramanshift", "stokes", "stokesshift")) { + return("raman") + } + if (unit %in% c("1/cm", "cm-1", "cm^-1", "cm^{-1}", + "invcm", "invertedcm", "inverted", + "wavenumber", "wn")) { + return("invcm") + } + if (unit %in% c("nm", "nanometer", "wavelength")) { + return("nm") + } + if (unit %in% c("ev", "electronvolt")) { + return("ev") + } + if (unit %in% c("thz", "terahertz", "freq", "frequency")) { + return("freq") # FIXME: why `freq` and not `THz`? + } + if (unit %in% c("pixel", "px", "sensor")) { + return("px") + } + if (unit == "file") { + return(unit) + } + + msg <- paste0("'", unit0, "': Unknown unit type") + + switch(on_failure, + pass = return(unit0), + warn = { + warning(msg) + return(unit0) + }, + fail = stop(msg) + ) +} + + +#' # Unit tests ----------------------------------------------------------------- + +hySpc.testthat::test(.wl_fix_unit_name) <- function() { + context(".wl_fix_unit_name") + + test_that(".wl_fix_unit_name() works", { + expect_equal(.wl_fix_unit_name("raman"), "raman") + expect_equal(.wl_fix_unit_name("raman shift"), "raman") + expect_equal(.wl_fix_unit_name("raman_shift"), "raman") + expect_equal(.wl_fix_unit_name("raman.shift"), "raman") + expect_equal(.wl_fix_unit_name("invcm"), "invcm") + expect_equal(.wl_fix_unit_name("nm"), "nm") + expect_equal(.wl_fix_unit_name("ev"), "ev") + expect_equal(.wl_fix_unit_name("freq"), "freq") + expect_equal(.wl_fix_unit_name("px"), "px") + expect_equal(.wl_fix_unit_name("file"), "file") + + expect_error(.wl_fix_unit_name("dDd"), "Unknown unit type") + expect_equal(.wl_fix_unit_name("dDd", on_failure = "pass"), "dDd") + expect_warning(.wl_fix_unit_name("dDd", on_failure = "warn"), "dDd") + + expect_error(.wl_fix_unit_name(NULL), "argument is of length zero") + expect_silent(.wl_fix_unit_name(NULL, null_ok = TRUE)) + }) + + # TODO (tests): add more specific tests. +} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +