Nothing
#' @title Dead-time (linearity) Correction for Photomultiplier tubes (PMT)
#'
#' @description
#' Correct dead-time (also linearity) of PMT counts to avoid saturation effects, depending
#' on pulse-pair-resolution of individual PMTs.
#'
#' @details
#' We correct for count linearity using a well-known formula that can be
#' found for example in the Hamamatsu Photomultiplier handbook
#' (Hamamatsu Photonics K.K., 2017):
#'
#' \deqn{N = \frac{M}{1 - Mt}}
#'
#' where \eqn{N} (in s\eqn{^{-1}}) is the true count rate, \eqn{M} (in s\eqn{^{-1}}) the measured count rate,
#' and \eqn{t} (in s) the pulse pair resolution.
#'
#' @param object [Luminescence::RLum.Analysis-class] [Luminescence::RLum.Data.Curve-class] (**required**):
#' object with records to correct; can be a [list] of such objects
#'
#' @param PMT_pulse_pair_resolution [numeric] (*with default*): pulse-pair resolution
#' in ns. Values can be found on the PMT datasheets. If `NULL` nothing is done.
#'
#' @section Function version: 0.1.1
#'
#' @returns
#' Returns the same type of object type as `object`.
#'
#' @note
#' This function is an adaptation of core from the R package
#' 'OSLdecomposition'.
#'
#' @author
#' Sebastian Kreutzer, F2.1 Geophysical Parametrisation/Regionalisation, LIAG - Institute for Applied Geophysics (Germany)\cr
#' Dirk Mittelstrass, F2.1 Geophysical Parametrisation/Regionalisation, LIAG - Institute for Applied Geophysics (Germany)
#'
#' @references
#'
#' Hamamatsu Photonics K.K., 2017. Photomultiplier Tubes: Basics and Applications, 4th edition. ed. Hamamatsu.
#'
#' Mittelstraß, D., Kreutzer, S., Schmidt, C., 2022. OSLdecomposition: Signal
#' component analysis for optically stimulated luminescence. \doi{10.32614/CRAN.package.OSLdecomposition}
#'
#' @examples
#' o <- set_RLum("RLum.Data.Curve")
#' correct_PMTLinearity(o, PMT_pulse_pair_resolution = 10)
#'
#' @keywords manip
#'
#' @md
#' @export
correct_PMTLinearity <- function(
object,
PMT_pulse_pair_resolution = NULL
) {
## set function name
.set_function_name("correct_PMTLinearity")
on.exit(.unset_function_name(), add = TRUE)
# Self-call ---------------------------------------------------------------
if(inherits(object, "list")) {
## remove non-RLum objects and run
return(lapply(
X = .rm_nonRLum(object),
FUN = correct_PMTLinearity,
PMT_pulse_pair_resolution = PMT_pulse_pair_resolution))
}
## input validation
.validate_class(object, c("RLum.Analysis", "RLum.Data.Curve"))
.validate_positive_scalar(PMT_pulse_pair_resolution, null.ok = TRUE)
## run only of parameter was set
if (is.null(PMT_pulse_pair_resolution))
return(object)
## extract records
if (inherits(object, "RLum.Analysis"))
records <- object@records
else
records <- list(object)
## convert to seconds
res <- PMT_pulse_pair_resolution[1] * 1e-9
## set threshold for correction (taken from OSLdecomposition)
## function OSLdecomposition::RLum.OSL_correction() (v1.0.0)
thresh <- -0.5 * 0.5 + 0.5 * sqrt(0.5^2 + 2 / res)
## loop over records
records <- lapply(records, \(x) {
## skip non-supported records
## no further test to keep the speed up
if (!inherits(x, "RLum.Data.Curve"))
return(x)
## access the slot
rec <- x@data
## get channel width (we assume constant channel width)
## if only one channel set width to 1
if (nrow(rec) >= 2)
w <- rec[2, 1] - rec[1, 1]
else
w <- 1
## fall back for channel resolution that is "0"
if(w == 0)
return(x)
## get cps
cps <- rec[, 2, drop = FALSE] / w
## define threshold and tag
idx <- cps > thresh
## correct if required
if (any(idx)) {
new_vals <- round(cps[idx] / (1 - cps[idx] * res) * w)
rec[idx, 2] <- new_vals
x@data <- rec
}
return(x)
})
## extract records
if (inherits(object, "RLum.Analysis"))
object@records <- records
else
object <- records[[1]]
return(object)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.