diff --git a/NAMESPACE b/NAMESPACE index 94439a7..4c638e0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,6 +10,7 @@ export(compress_low_energy) export(get_plot_sample_ids) export(ir_to_plotftir) export(move_plot_legend) +export(normalize_spectra) export(plot_ftir) export(plot_ftir_stacked) export(plotftir_to_chemospec) diff --git a/R/maths.R b/R/maths.R index 6bbc9c4..a36b622 100644 --- a/R/maths.R +++ b/R/maths.R @@ -1,6 +1,4 @@ ## Holds functions to do maths on spectra Currently: average like spectra -## -## Plans: rebaseline (scalar subtraction, subtract minimum, subtract wavenumber's value, average over wavenumber range) #' Average FTIR Spectra #' @@ -8,25 +6,31 @@ #' #' Calcule la moyenne de deux spectres ou plus. #' -#' @param ftir A data.frame of FTIR spectral data including spectra to be converted. +#' @param ftir A data.frame of FTIR spectral data including spectra to be +#' converted. #' -#' Un data.frame de données spectrales IRTF comprenant les spectres à convertir. +#' Un data.frame de données spectrales IRTF comprenant les spectres à +#' convertir. #' -#' @param sample_ids A vector of sample IDs to be averaged together. All sample IDs must be present in the `ftir` -#' data.frame. If averaging all spectra, provide `NA` or `NULL.` +#' @param sample_ids A vector of sample IDs to be averaged together. All sample +#' IDs must be present in the `ftir` data.frame. If averaging all spectra, +#' provide `NA` or `NULL.` #' -#' Un vecteur d'identifiants d'échantillons dont la moyenne doit être calculée.. Tous les identifiants des -#' échantillons doivent être présents dans le data.frame `ftir`. Si la moyenne est calculée pour tous les spectres, -#' indiquez `NA` ou `NULL.` +#' Un vecteur d'identifiants d'échantillons dont la moyenne doit être +#' calculée.. Tous les identifiants des échantillons doivent être présents +#' dans le data.frame `ftir`. Si la moyenne est calculée pour tous les +#' spectres, indiquez `NA` ou `NULL.` #' -#' @param average_id The name to be used as `sample_id` for the averaged spectra. +#' @param average_id The name to be used as `sample_id` for the averaged +#' spectra. #' #' Le nom à utiliser en tant que `sample_id` pour les spectres moyennés. #' -#' @return A data.frame containing the averaged FTIR spectra, with `sample_id` corresponding to the provided `average_id`. +#' @return A data.frame containing the averaged FTIR spectra, with `sample_id` +#' corresponding to the provided `average_id`. #' -#' Un data.frame contenant les spectres IRTF moyennés, avec `sample_id` correspondant à l'identifiant -#' `average_id` fourni. +#' Un data.frame contenant les spectres IRTF moyennés, avec `sample_id` +#' correspondant à l'identifiant `average_id` fourni. #' #' @export #' @@ -122,25 +126,30 @@ average_spectra <- function(ftir, sample_ids = NA, average_id = "averaged_spectr #' Add or Subtract Scalar Value #' -#' @description -#' Add or subtract a constant (scalar) value to each data point in a FTIR spectra. Shifts the plot up or down on the y axis by the specified amount without any other change. +#' @description Add or subtract a constant (scalar) value to each data point in +#' a FTIR spectra. Shifts the plot up or down on the y axis by the specified +#' amount without any other change. #' -#' Ajoute ou soustrait une valeur constante (scalaire) à chaque point de données d'un spectre IRTF. Décale le tracé vers le haut ou vers le bas sur l'axe des y de la valeur spécifiée sans aucune autre modification. +#' Ajoute ou soustrait une valeur constante (scalaire) à chaque point de données +#' d'un spectre IRTF. Décale le tracé vers le haut ou vers le bas sur l'axe des +#' y de la valeur spécifiée sans aucune autre modification. #' -#' @param ftir A data.frame of FTIR spectral data including spectra to be shifted. +#' @param ftir A data.frame of FTIR spectral data including spectra to be +#' shifted. #' #' Un data.frame de données spectrales IRTF comprenant les spectres à décalés. #' -#' @param sample_ids A vector of sample IDs to be shifted. All sample IDs must be present in the `ftir` -#' data.frame. If modifying all spectra, provide NA or NULL. +#' @param sample_ids A vector of sample IDs to be shifted. All sample IDs must +#' be present in the `ftir` data.frame. If modifying all spectra, provide NA +#' or NULL. #' -#' Un vecteur d'identifiants d'échantillons dont la moyenne doit être décalée. Tous les identifiants des -#' échantillons doivent être présents dans le data.frame `ftir`. Si modifiez tous les spectres, -#' indiquez NA ou NULL. +#' Un vecteur d'identifiants d'échantillons dont la moyenne doit être décalée. +#' Tous les identifiants des échantillons doivent être présents dans le +#' data.frame `ftir`. Si modifiez tous les spectres, indiquez NA ou NULL. #' #' @param value The numeric value to add or subtract. #' -#' Le valeur numerique d'ajute ou soustrait. +#' Le valeur numerique d'ajute ou soustrait. #' #' @return A data.frame containing the adjusted FTIR spectra. #' @@ -207,60 +216,100 @@ subtract_scalar_value <- function(ftir, value, sample_ids = NA) { #' Recalculate Baseline #' #' @md -#' @description -#' It may be desired to shift the baseline signal (0 for absorbance or 100 for transmittance) to aid in plotting the spectra. This can be done for all samples or a subset, using the same shift for all adjusted samples or calculated individually. +#' @description It may be desired to shift the baseline signal (0 for absorbance +#' or 100 for transmittance) to aid in plotting the spectra. This can be done +#' for all samples or a subset, using the same shift for all adjusted samples +#' or calculated individually. #' -#' Recalculate or shift to baseline/max transmittance can be done following one of a few methods: +#' Recalculate or shift to baseline/max transmittance can be done following +#' one of a few methods: #' * To shift baseline based on the value at a given wavenumber: -#' `recalculate_baseline(ftir, wavenumber_range = [numeric], method = 'point')` +#' `recalculate_baseline(ftir, wavenumber_range = [numeric], method = +#' 'point')` #' * To shift baseline based on the average value across a provided wavenumber range: -#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'average')` -#' * To shift baseline based on the value at the single lowest point of absorbance (or highest point of transmittance) across the whole spectra -#' `recalculate_baseline(ftir, method = 'minimum')` -#' * To shift baseline based on the value at the single lowest point of absorbance (or highest point of transmittance) in a given range -#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'minimum')` -#' -#' To perform the exact same baseline adjustment on all samples, specify `individually = FALSE`. To adjust with a unique determination for each sample, specify `individualy = TRUE`. -#' -#' -#' Il peut être souhaitable de décaler le signal de la ligne de base (0 pour l'absorbance ou 100 pour la transmittance) pour faciliter le tracé des spectres. Cela peut être fait pour tous les échantillons ou un sous-ensemble, en utilisant le même décalage pour tous les échantillons ajustés ou calculés individuellement. -#' -#' Le recalcul ou le décalage de la ligne de base/transmittance maximale peut être effectué en suivant l'une des méthodes suivantes : +#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), +#' method = 'average')` +#' * To shift baseline based on the value at the single lowest point of absorbance +#' (or highest point of transmittance) across the whole spectra +#' `recalculate_baseline(ftir, method = 'minimum')` +#' * To shift baseline based on the value at the single lowest point of absorbance +#' (or highest point of transmittance) in a given range +#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), +#' method = 'minimum')` +#' +#' To perform the exact same baseline adjustment on all samples, specify +#' `individually = FALSE`. To adjust with a unique determination for each +#' sample, specify `individualy = TRUE`. +#' +#' +#' Il peut être souhaitable de décaler le signal de la ligne de base (0 pour +#' l'absorbance ou 100 pour la transmittance) pour faciliter le tracé des +#' spectres. Cela peut être fait pour tous les échantillons ou un +#' sous-ensemble, en utilisant le même décalage pour tous les échantillons +#' ajustés ou calculés individuellement. +#' +#' Le recalcul ou le décalage de la ligne de base/transmittance maximale peut +#' être effectué en suivant l'une des méthodes suivantes : #' * Pour décaler la ligne de base en fonction de la valeur à un nombre d'ondes donné : -#' `recalculate_baseline(ftir, wavenumber_range = [numeric], method = 'point')` -#' * Pour décaler la ligne de base en fonction de la valeur moyenne sur un nombre d'ondes donné : #' `recalculate_baseline(ftir) = [numerique], method = 'point') -#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'average')` -#' * Pour décaler la ligne de base en fonction de la valeur du point d'absorbance le plus bas (ou du point de transmittance le plus élevé) sur l'ensemble des spectres. -#' `recalculate_baseline(ftir, method = 'minimum')` -#' * Décaler la ligne de base en fonction de la valeur du point d'absorbance le plus bas (ou du point de transmittance le plus élevé) dans une gamme donnée. -#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'minimum')` -#' -#' Pour effectuer exactement le même ajustement de la ligne de base sur tous les échantillons, spécifiez `individually = FALSE`. Pour ajuster avec une détermination unique pour chaque échantillon, spécifiez `individualy = TRUE`. -#' @param ftir A data.frame of FTIR spectral data including spectra to be baseline adjusted. -#' -#' Un data.frame de données spectrales IRTF comprenant les spectres à ajuster à la ligne de base. -#' -#' @param sample_ids A vector of sample IDs to be ajusted All sample IDs must be present in the `ftir` -#' data.frame. If ajusting all spectra, provide NA or NULL. Unlisted `sample_id` from `ftir` will be left alone. -#' -#' Un vecteur d'ID d'échantillons à ajuster Tous les ID d'échantillons doivent être présents dans la base de données `ftir` data.frame. Si l'ajustement concerne tous les spectres, fournir NA ou NULL. Les `sample_id` non listés de `ftir` seront laissés seuls. -#' -#' @param wavenumber_range If specifying a single point wavenumber; a single numeric value. If specifying a wavenumber range, then a vector of two numeric values. -#' -#' Si l'on spécifie un nombre d'ondes ponctuel, une seule valeur numérique. Si l'on spécifie un nombre d'ondes, alors un vecteur de deux valeurs numériques. +#' `recalculate_baseline(ftir, wavenumber_range = [numeric], method = +#' 'point')` +#' * Pour décaler la ligne de base en fonction de la valeur moyenne sur un nombre +#' d'ondes donné : #' `recalculate_baseline(ftir) = [numerique], method = 'point') +#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), +#' method = 'average')` +#' * Pour décaler la ligne de base en fonction de la valeur du point d'absorbance +#' le plus bas (ou du point de transmittance le plus élevé) sur l'ensemble des spectres. +#' `recalculate_baseline(ftir, method = 'minimum')` +#' * Décaler la ligne de base en fonction de la valeur du point d'absorbance le +#' plus bas (ou du point de transmittance le plus élevé) dans une gamme donnée. +#' `recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), +#' method = 'minimum')` +#' +#' Pour effectuer exactement le même ajustement de la ligne de base sur tous +#' les échantillons, spécifiez `individually = FALSE`. Pour ajuster avec une +#' détermination unique pour chaque échantillon, spécifiez `individualy = +#' TRUE`. +#' @param ftir A data.frame of FTIR spectral data including spectra to be +#' baseline adjusted. +#' +#' Un data.frame de données spectrales IRTF comprenant les spectres à ajuster +#' à la ligne de base. +#' +#' @param sample_ids A vector of sample IDs to be adjusted. All sample IDs must +#' be present in the `ftir` data.frame. If adjusting all spectra, provide NA +#' or NULL. Unlisted `sample_id` from `ftir` will be left alone. +#' +#' Un vecteur d'ID d'échantillons à ajuster Tous les ID d'échantillons doivent +#' être présents dans la base de données `ftir` data.frame. Si l'ajustement +#' concerne tous les spectres, fournir NA ou NULL. Les `sample_id` non listés +#' de `ftir` seront laissés seuls. +#' +#' @param wavenumber_range If specifying a single point wavenumber; a single +#' numeric value. If specifying a wavenumber range, then a vector of two +#' numeric values. +#' +#' Si l'on spécifie un nombre d'ondes ponctuel, une seule valeur numérique. Si +#' l'on spécifie un nombre d'ondes, alors un vecteur de deux valeurs +#' numériques. #' #' @param method One of three values: #' * If adjusting by the value from a specific wavenumber, provide `"point"`, #' * If adjusting by the average from a range, provide `"average"`. #' * If adjusting by the minimum (for absorbance) or maximum (for transmittance) from a range or spectra, provide `"minimum"` or `"maximum"`, the appropriate transformation will be performed based on spectra type. #' -#' Une des trois valeurs : +#' Une des trois valeurs : #' * Si l'ajustement se fait par la valeur d'un nombre d'ondes spécifique, fournir `"point"`, #' * Si l'ajustement se fait par la moyenne d'une gamme, fournir `"average"`. #' * Si l'ajustement se fait par le minimum (pour l'absorbance) ou le maximum (pour la transmittance) d'une gamme ou de spectres, indiquez `"minimum"` ou `"maximum"`, la transformation appropriée sera effectuée en fonction du type de spectre. -#' @param individually If adjusting all samples by the same amount, specify `TRUE`, else specify `FALSE` for unique adjustments. When `TRUE`, the smallest absolute individual sample adjustment to achieve baseline will be applied to all named samples. +#' @param individually If adjusting all samples by the same amount, specify +#' `TRUE`, else specify `FALSE` for unique adjustments. When `TRUE`, the +#' smallest absolute individual sample adjustment to achieve baseline will be +#' applied to all named samples. #' -#' Si vous ajustez tous les échantillons de la même manière, spécifiez `TRUE`, sinon spécifiez `FALSE` pour des ajustements uniques. Si `TRUE`, le plus petit ajustement absolu d'un échantillon individuel pour atteindre la ligne de base sera appliqué à tous les échantillons nommés. +#' Si vous ajustez tous les échantillons de la même manière, spécifiez `TRUE`, +#' sinon spécifiez `FALSE` pour des ajustements uniques. Si `TRUE`, le plus +#' petit ajustement absolu d'un échantillon individuel pour atteindre la ligne +#' de base sera appliqué à tous les échantillons nommés. #' #' @return A data.frame containing the adjusted FTIR spectra. #' @@ -434,3 +483,78 @@ recalculate_baseline <- function(ftir, sample_ids = NA, wavenumber_range = NA, m return(ftir) } + + +#' Normalize FTIR spectra +#' +#' @description Normalizing spectra restricts the range of absorbance values from +#' 0 to 1 inclusive. This function shifts and scales spectra to achieve this +#' absorbance range. It can be applied to a whole spectral set or just one +#' sample, and across the entire spectra or by normalizing within a wavenumber +#' region. This function does not operate on transmittance data, it will return +#' an error. +#' +#' La normalisation des spectres restreint la gamme des valeurs d'absorbance de 0 +#' à 1 inclus. Cette fonction décale et met à l'échelle les spectres pour +#' atteindre cette gamme d'absorbance. Elle peut être appliquée à un ensemble de +#' spectres ou à un seul échantillon, et sur l'ensemble des spectres ou en +#' normalisant dans une région de nombre d'ondes. Cette fonction ne fonctionne +#' pas sur les données de transmittance, elle renverra une erreur. +#' +#' @inherit recalculate_baseline params return +#' @export +#' @examples +#' # Normalize all samples in `biodiesel` +#' normalize_spectra(biodiesel) +#' +#' # Normalize just `paper` and `isopropanol` spectra from 4000 to 3100 cm^-1^ +#' normalize_spectra(sample_spectra, +#' sample_ids = c("paper", "isopropanol"), +#' wavenumber_range = c(4000, 3100)) +normalize_spectra <- function(ftir, sample_ids = NA, wavenumber_range = NA) { + # Check inputs + ftir <- check_ftir_data(ftir, "PlotFTIR::normalize_spectra") + if ("transmittance" %in% colnames(ftir)) { + # Can't normalize transmission spectra + cli::cli_abort(c("Error in {.fn PlotFTIR::normalize_spectra}: Normalization of Transmittance spectra not supported.", + i = "Convert spectra to absorbance using {.fn transmittance_to_absorbance} then try again." + )) + } + + if (length(sample_ids) <= 1) { + if (is.na(sample_ids) || is.null(sample_ids) || length(sample_ids) == 0) { + sample_ids <- unique(ftir$sample_id) + } + } + + if (any(!(sample_ids %in% unique(ftir$sample_id)))) { + mismatch <- sample_ids[!(sample_ids %in% unique(ftir$sample_id))] + cli::cli_abort(c("Error in {.fn PlotFTIR::normalize_spectra}. All provided {.arg sample_ids} must be in {.arg ftir} data.", + x = "The following {.arg sample_id{?s}} are not present: {.val {mismatch}}." + )) + } + + if (all(is.na(wavenumber_range))) { + wavenumber_range <- range(ftir$wavenumber, na.rm = TRUE) + } + + if (length(wavenumber_range) < 2 || length(wavenumber_range) > 2) { + cli::cli_abort(c("Error in {.fn PlotFTIR::normalize_spectra}. {.arg wavenumber_range} must be of length 2.")) + } + if (any(is.na(wavenumber_range)) | !all(is.numeric(wavenumber_range))) { + cli::cli_abort(c("Error in {.fn PlotFTIR::normalize_spectra}. {.arg wavenumber_range} must be {.code numeric} or {.code NA}.", + x = "You provided a {.obj_type_friendly wavenumber_range}." + )) + } + + for (i in seq_along(sample_ids)) { + sid <- sample_ids[i] + spectra <- ftir[ftir$sample_id == sid, ] + spectra_range <- range(spectra[spectra$wavenumber >= min(wavenumber_range) & spectra$wavenumber <= max(wavenumber_range), ]$absorbance) + spectra$absorbance <- spectra$absorbance - spectra_range[1] + spectra$absorbance <- spectra$absorbance * (1 / (spectra_range[2] - spectra_range[1])) + ftir[ftir$sample_id == sid, ]$absorbance <- spectra$absorbance + } + + return(ftir) +} diff --git a/README.Rmd b/README.Rmd index 81d5918..2372bbb 100644 --- a/README.Rmd +++ b/README.Rmd @@ -155,9 +155,10 @@ biodiesel_transm <- absorbance_to_transmittance(biodiesel) head(biodiesel_transm) ``` -Functions are provided for adjusting the baseline of spectra, adding or subtracting scalar values from entire spectra, and averaging spectra, see: +Functions are provided for adjusting the baseline of spectra, adding or subtracting scalar values from entire spectra, normalizing spectra, and averaging spectra, see: * `recalculate_baseline()` * `add_scalar_value()` and `subtract_scalar_value()` +* `normalize_spectra()` * `average_spectra()` ## Reading Files @@ -313,9 +314,10 @@ biodiesel_transm <- absorbance_to_transmittance(biodiesel) head(biodiesel_transm) ``` -Des fonctions sont fournies pour ajuster la ligne de base des spectres, ajouter ou soustraire des valeurs scalaires de spectres entiers, et calculer la moyenne des spectres, voir : +Des fonctions sont fournies pour ajuster la ligne de base des spectres, ajouter ou soustraire des valeurs scalaires de spectres entiers, normalisation des spectres, et calculer la moyenne des spectres, voir : * `recalculate_baseline()` * `add_scalar_value()` et `subtract_scalar_value()` +* `normalize_spectra()` * `average_spectra()` ## Lecture des fichiers diff --git a/README.md b/README.md index d9a86ec..62a0919 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ [![R-CMD-check](https://github.com/NRCan/PlotFTIR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/NRCan/PlotFTIR/actions/workflows/R-CMD-check.yaml) [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) -[![Coveralls test coverage](https://coveralls.io/repos/github/NRCan/PlotFTIR/badge.svg)](https://coveralls.io/r/NRCan/PlotFTIR?branch=main) +[![Coveralls test +coverage](https://coveralls.io/repos/github/NRCan/PlotFTIR/badge.svg)](https://coveralls.io/r/NRCan/PlotFTIR?branch=main) <!-- badges: end --> ## Introduction and Installation @@ -204,9 +205,10 @@ head(biodiesel_transm) ``` Functions are provided for adjusting the baseline of spectra, adding or -subtracting scalar values from entire spectra, and averaging spectra, -see: \* `recalculate_baseline()` \* `add_scalar_value()` and -`subtract_scalar_value()` \* `average_spectra()` +subtracting scalar values from entire spectra, normalizing spectra, and +averaging spectra, see: \* `recalculate_baseline()` \* +`add_scalar_value()` and `subtract_scalar_value()` \* +`normalize_spectra()` \* `average_spectra()` ## Reading Files @@ -454,9 +456,11 @@ head(biodiesel_transm) ``` Des fonctions sont fournies pour ajuster la ligne de base des spectres, -ajouter ou soustraire des valeurs scalaires de spectres entiers, et -calculer la moyenne des spectres, voir : \* `recalculate_baseline()` \* -`add_scalar_value()` et `subtract_scalar_value()` \* `average_spectra()` +ajouter ou soustraire des valeurs scalaires de spectres entiers, +normalisation des spectres, et calculer la moyenne des spectres, voir : +\* `recalculate_baseline()` \* `add_scalar_value()` et +`subtract_scalar_value()` \* `normalize_spectra()` \* +`average_spectra()` ## Lecture des fichiers diff --git a/cran-comments.md b/cran-comments.md index d74a3d2..3ed7ec9 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -17,3 +17,4 @@ * Changes to working directory were unavoidable by the interface to ChemoSpec (that package doesn't allow for specifying directory when importing files). As such, in-code changes to working directory are protected with a call to `on.exit()`. + * This resubmit also adds a function for normalization of spectra per user request (in maths.R), with associated docs. diff --git a/man/add_subtract_scalar.Rd b/man/add_subtract_scalar.Rd index e73a40f..06d63c5 100644 --- a/man/add_subtract_scalar.Rd +++ b/man/add_subtract_scalar.Rd @@ -11,20 +11,22 @@ add_scalar_value(ftir, value, sample_ids = NA) subtract_scalar_value(ftir, value, sample_ids = NA) } \arguments{ -\item{ftir}{A data.frame of FTIR spectral data including spectra to be shifted. +\item{ftir}{A data.frame of FTIR spectral data including spectra to be + shifted. Un data.frame de données spectrales IRTF comprenant les spectres à décalés.} \item{value}{The numeric value to add or subtract. -Le valeur numerique d'ajute ou soustrait.} + Le valeur numerique d'ajute ou soustrait.} -\item{sample_ids}{A vector of sample IDs to be shifted. All sample IDs must be present in the `ftir` - data.frame. If modifying all spectra, provide NA or NULL. +\item{sample_ids}{A vector of sample IDs to be shifted. All sample IDs must + be present in the `ftir` data.frame. If modifying all spectra, provide NA + or NULL. - Un vecteur d'identifiants d'échantillons dont la moyenne doit être décalée. Tous les identifiants des - échantillons doivent être présents dans le data.frame `ftir`. Si modifiez tous les spectres, - indiquez NA ou NULL.} + Un vecteur d'identifiants d'échantillons dont la moyenne doit être décalée. + Tous les identifiants des échantillons doivent être présents dans le + data.frame `ftir`. Si modifiez tous les spectres, indiquez NA ou NULL.} } \value{ A data.frame containing the adjusted FTIR spectra. @@ -32,9 +34,13 @@ A data.frame containing the adjusted FTIR spectra. Un data.frame contenant les spectres IRTF ajustee. } \description{ -Add or subtract a constant (scalar) value to each data point in a FTIR spectra. Shifts the plot up or down on the y axis by the specified amount without any other change. +Add or subtract a constant (scalar) value to each data point in +a FTIR spectra. Shifts the plot up or down on the y axis by the specified +amount without any other change. -Ajoute ou soustrait une valeur constante (scalaire) à chaque point de données d'un spectre IRTF. Décale le tracé vers le haut ou vers le bas sur l'axe des y de la valeur spécifiée sans aucune autre modification. +Ajoute ou soustrait une valeur constante (scalaire) à chaque point de données +d'un spectre IRTF. Décale le tracé vers le haut ou vers le bas sur l'axe des +y de la valeur spécifiée sans aucune autre modification. } \examples{ # Add 0.1 to each spectra in biodiesel diff --git a/man/average_spectra.Rd b/man/average_spectra.Rd index 458928c..b5c6053 100644 --- a/man/average_spectra.Rd +++ b/man/average_spectra.Rd @@ -7,26 +7,32 @@ average_spectra(ftir, sample_ids = NA, average_id = "averaged_spectra") } \arguments{ -\item{ftir}{A data.frame of FTIR spectral data including spectra to be converted. +\item{ftir}{A data.frame of FTIR spectral data including spectra to be +converted. -Un data.frame de données spectrales IRTF comprenant les spectres à convertir.} +Un data.frame de données spectrales IRTF comprenant les spectres à +convertir.} -\item{sample_ids}{A vector of sample IDs to be averaged together. All sample IDs must be present in the \code{ftir} -data.frame. If averaging all spectra, provide \code{NA} or \code{NULL.} +\item{sample_ids}{A vector of sample IDs to be averaged together. All sample +IDs must be present in the \code{ftir} data.frame. If averaging all spectra, +provide \code{NA} or \code{NULL.} -Un vecteur d'identifiants d'échantillons dont la moyenne doit être calculée.. Tous les identifiants des -échantillons doivent être présents dans le data.frame \code{ftir}. Si la moyenne est calculée pour tous les spectres, -indiquez \code{NA} ou \code{NULL.}} +Un vecteur d'identifiants d'échantillons dont la moyenne doit être +calculée.. Tous les identifiants des échantillons doivent être présents +dans le data.frame \code{ftir}. Si la moyenne est calculée pour tous les +spectres, indiquez \code{NA} ou \code{NULL.}} -\item{average_id}{The name to be used as \code{sample_id} for the averaged spectra. +\item{average_id}{The name to be used as \code{sample_id} for the averaged +spectra. Le nom à utiliser en tant que \code{sample_id} pour les spectres moyennés.} } \value{ -A data.frame containing the averaged FTIR spectra, with \code{sample_id} corresponding to the provided \code{average_id}. +A data.frame containing the averaged FTIR spectra, with \code{sample_id} +corresponding to the provided \code{average_id}. -Un data.frame contenant les spectres IRTF moyennés, avec \code{sample_id} correspondant à l'identifiant -\code{average_id} fourni. +Un data.frame contenant les spectres IRTF moyennés, avec \code{sample_id} +correspondant à l'identifiant \code{average_id} fourni. } \description{ Calculates an average of two or more spectra. diff --git a/man/normalize_spectra.Rd b/man/normalize_spectra.Rd new file mode 100644 index 0000000..e7c2998 --- /dev/null +++ b/man/normalize_spectra.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/maths.R +\name{normalize_spectra} +\alias{normalize_spectra} +\title{Normalize FTIR spectra} +\usage{ +normalize_spectra(ftir, sample_ids = NA, wavenumber_range = NA) +} +\arguments{ +\item{ftir}{A data.frame of FTIR spectral data including spectra to be +baseline adjusted. + +Un data.frame de données spectrales IRTF comprenant les spectres à ajuster +à la ligne de base.} + +\item{sample_ids}{A vector of sample IDs to be adjusted. All sample IDs must +be present in the \code{ftir} data.frame. If adjusting all spectra, provide NA +or NULL. Unlisted \code{sample_id} from \code{ftir} will be left alone. + +Un vecteur d'ID d'échantillons à ajuster Tous les ID d'échantillons doivent +être présents dans la base de données \code{ftir} data.frame. Si l'ajustement +concerne tous les spectres, fournir NA ou NULL. Les \code{sample_id} non listés +de \code{ftir} seront laissés seuls.} + +\item{wavenumber_range}{If specifying a single point wavenumber; a single +numeric value. If specifying a wavenumber range, then a vector of two +numeric values. + +Si l'on spécifie un nombre d'ondes ponctuel, une seule valeur numérique. Si +l'on spécifie un nombre d'ondes, alors un vecteur de deux valeurs +numériques.} +} +\value{ +A data.frame containing the adjusted FTIR spectra. + +Un data.frame contenant les spectres IRTF ajustee. +} +\description{ +Normalizing spectra restricts the range of absorbance values from +0 to 1 inclusive. This function shifts and scales spectra to achieve this +absorbance range. It can be applied to a whole spectral set or just one +sample, and across the entire spectra or by normalizing within a wavenumber +region. This function does not operate on transmittance data, it will return +an error. + +La normalisation des spectres restreint la gamme des valeurs d'absorbance de 0 +à 1 inclus. Cette fonction décale et met à l'échelle les spectres pour +atteindre cette gamme d'absorbance. Elle peut être appliquée à un ensemble de +spectres ou à un seul échantillon, et sur l'ensemble des spectres ou en +normalisant dans une région de nombre d'ondes. Cette fonction ne fonctionne +pas sur les données de transmittance, elle renverra une erreur. +} +\examples{ +# Normalize all samples in `biodiesel` +normalize_spectra(biodiesel) + +# Normalize just `paper` and `isopropanol` spectra from 4000 to 3100 cm^-1^ +normalize_spectra(sample_spectra, + sample_ids = c("paper", "isopropanol"), + wavenumber_range = c(4000, 3100)) +} diff --git a/man/plotftir_to_ir.Rd b/man/plotftir_to_ir.Rd index fa4ac30..cafe37a 100644 --- a/man/plotftir_to_ir.Rd +++ b/man/plotftir_to_ir.Rd @@ -38,7 +38,8 @@ Convertit les données `PlotFTIR` en données prêtes à être utilisées par le if (requireNamespace("ir", quietly = TRUE)) { # convert biodiesel to a `ir` object plotftir_to_ir(biodiesel, - metadata = data.frame("Biodiesel_Content" = c(0, 0.25, 0.5, 1, 2.5, 5, 7.5, 10, 0.5, 5, NA))) + metadata = data.frame("Biodiesel_Content" = c(0, 0.25, 0.5, 1, 2.5, 5, 7.5, 10, 0.5, 5, NA)) + ) } } \seealso{ diff --git a/man/read_ftir.Rd b/man/read_ftir.Rd index 4e73f11..bafabb2 100644 --- a/man/read_ftir.Rd +++ b/man/read_ftir.Rd @@ -36,8 +36,9 @@ Lit un fichier fourni et renvoie un data.frame dans le format approprié pour le \examples{ # Writing a temporary file to read later tf <- tempfile(fileext = ".csv") -write.csv(sample_spectra[sample_spectra$sample_id == "paper", c('wavenumber', 'absorbance')], - file = tf, row.names = FALSE) +write.csv(sample_spectra[sample_spectra$sample_id == "paper", c("wavenumber", "absorbance")], + file = tf, row.names = FALSE +) # Read the .csv file and call the sample `sample1` read_ftir(tf, sample_name = "sample1") diff --git a/man/read_ftir_directory.Rd b/man/read_ftir_directory.Rd index c1655d7..f31b6d0 100644 --- a/man/read_ftir_directory.Rd +++ b/man/read_ftir_directory.Rd @@ -36,10 +36,12 @@ Lit les fichiers fournis et renvoie un data.frame au format approprié pour les \examples{ # Putting some files in a temp dir to read back into PlotFTIR: td <- tempdir() -write.csv(sample_spectra[sample_spectra$sample_id == "paper", c('wavenumber', 'absorbance')], - file = file.path(td, "ftir_sample_1.csv"), row.names = FALSE) -write.csv(sample_spectra[sample_spectra$sample_id == "toluene", c('wavenumber', 'absorbance')], - file = file.path(td, "ftir_sample_2.csv"), row.names = FALSE) +write.csv(sample_spectra[sample_spectra$sample_id == "paper", c("wavenumber", "absorbance")], + file = file.path(td, "ftir_sample_1.csv"), row.names = FALSE +) +write.csv(sample_spectra[sample_spectra$sample_id == "toluene", c("wavenumber", "absorbance")], + file = file.path(td, "ftir_sample_2.csv"), row.names = FALSE +) # Read .csv files from the temp directory and call them `sample-1` and `sample-2` read_ftir_directory(td, c("ftir_sample_1.csv", "ftir_sample_2.csv"), c("sample-1", "sample-2")) diff --git a/man/recalculate_baseline.Rd b/man/recalculate_baseline.Rd index 537dfee..9019c70 100644 --- a/man/recalculate_baseline.Rd +++ b/man/recalculate_baseline.Rd @@ -13,36 +13,50 @@ recalculate_baseline( ) } \arguments{ -\item{ftir}{A data.frame of FTIR spectral data including spectra to be baseline adjusted. +\item{ftir}{A data.frame of FTIR spectral data including spectra to be +baseline adjusted. -Un data.frame de données spectrales IRTF comprenant les spectres à ajuster à la ligne de base.} +Un data.frame de données spectrales IRTF comprenant les spectres à ajuster +à la ligne de base.} -\item{sample_ids}{A vector of sample IDs to be ajusted All sample IDs must be present in the \code{ftir} -data.frame. If ajusting all spectra, provide NA or NULL. Unlisted \code{sample_id} from \code{ftir} will be left alone. +\item{sample_ids}{A vector of sample IDs to be adjusted. All sample IDs must +be present in the \code{ftir} data.frame. If adjusting all spectra, provide NA +or NULL. Unlisted \code{sample_id} from \code{ftir} will be left alone. -Un vecteur d'ID d'échantillons à ajuster Tous les ID d'échantillons doivent être présents dans la base de données \code{ftir} data.frame. Si l'ajustement concerne tous les spectres, fournir NA ou NULL. Les \code{sample_id} non listés de \code{ftir} seront laissés seuls.} +Un vecteur d'ID d'échantillons à ajuster Tous les ID d'échantillons doivent +être présents dans la base de données \code{ftir} data.frame. Si l'ajustement +concerne tous les spectres, fournir NA ou NULL. Les \code{sample_id} non listés +de \code{ftir} seront laissés seuls.} -\item{wavenumber_range}{If specifying a single point wavenumber; a single numeric value. If specifying a wavenumber range, then a vector of two numeric values. +\item{wavenumber_range}{If specifying a single point wavenumber; a single +numeric value. If specifying a wavenumber range, then a vector of two +numeric values. -Si l'on spécifie un nombre d'ondes ponctuel, une seule valeur numérique. Si l'on spécifie un nombre d'ondes, alors un vecteur de deux valeurs numériques.} +Si l'on spécifie un nombre d'ondes ponctuel, une seule valeur numérique. Si +l'on spécifie un nombre d'ondes, alors un vecteur de deux valeurs +numériques.} \item{method}{One of three values: \itemize{ \item If adjusting by the value from a specific wavenumber, provide \code{"point"}, \item If adjusting by the average from a range, provide \code{"average"}. \item If adjusting by the minimum (for absorbance) or maximum (for transmittance) from a range or spectra, provide \code{"minimum"} or \code{"maximum"}, the appropriate transformation will be performed based on spectra type. -} Une des trois valeurs : -\itemize{ \item Si l'ajustement se fait par la valeur d'un nombre d'ondes spécifique, fournir \code{"point"}, \item Si l'ajustement se fait par la moyenne d'une gamme, fournir \code{"average"}. \item Si l'ajustement se fait par le minimum (pour l'absorbance) ou le maximum (pour la transmittance) d'une gamme ou de spectres, indiquez \code{"minimum"} ou \code{"maximum"}, la transformation appropriée sera effectuée en fonction du type de spectre. }} -\item{individually}{If adjusting all samples by the same amount, specify \code{TRUE}, else specify \code{FALSE} for unique adjustments. When \code{TRUE}, the smallest absolute individual sample adjustment to achieve baseline will be applied to all named samples. +\item{individually}{If adjusting all samples by the same amount, specify +\code{TRUE}, else specify \code{FALSE} for unique adjustments. When \code{TRUE}, the +smallest absolute individual sample adjustment to achieve baseline will be +applied to all named samples. -Si vous ajustez tous les échantillons de la même manière, spécifiez \code{TRUE}, sinon spécifiez \code{FALSE} pour des ajustements uniques. Si \code{TRUE}, le plus petit ajustement absolu d'un échantillon individuel pour atteindre la ligne de base sera appliqué à tous les échantillons nommés.} +Si vous ajustez tous les échantillons de la même manière, spécifiez \code{TRUE}, +sinon spécifiez \code{FALSE} pour des ajustements uniques. Si \code{TRUE}, le plus +petit ajustement absolu d'un échantillon individuel pour atteindre la ligne +de base sera appliqué à tous les échantillons nommés.} } \value{ A data.frame containing the adjusted FTIR spectra. @@ -50,36 +64,55 @@ A data.frame containing the adjusted FTIR spectra. Un data.frame contenant les spectres IRTF ajustee. } \description{ -It may be desired to shift the baseline signal (0 for absorbance or 100 for transmittance) to aid in plotting the spectra. This can be done for all samples or a subset, using the same shift for all adjusted samples or calculated individually. +It may be desired to shift the baseline signal (0 for absorbance +or 100 for transmittance) to aid in plotting the spectra. This can be done +for all samples or a subset, using the same shift for all adjusted samples +or calculated individually. -Recalculate or shift to baseline/max transmittance can be done following one of a few methods: +Recalculate or shift to baseline/max transmittance can be done following +one of a few methods: \itemize{ \item To shift baseline based on the value at a given wavenumber: -\verb{recalculate_baseline(ftir, wavenumber_range = [numeric], method = 'point')} +\verb{recalculate_baseline(ftir, wavenumber_range = [numeric], method = 'point')} \item To shift baseline based on the average value across a provided wavenumber range: -\verb{recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'average')} -\item To shift baseline based on the value at the single lowest point of absorbance (or highest point of transmittance) across the whole spectra +\verb{recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'average')} +\item To shift baseline based on the value at the single lowest point of absorbance +(or highest point of transmittance) across the whole spectra \code{recalculate_baseline(ftir, method = 'minimum')} -\item To shift baseline based on the value at the single lowest point of absorbance (or highest point of transmittance) in a given range -\verb{recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'minimum')} +\item To shift baseline based on the value at the single lowest point of absorbance +(or highest point of transmittance) in a given range +\verb{recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'minimum')} } -To perform the exact same baseline adjustment on all samples, specify \code{individually = FALSE}. To adjust with a unique determination for each sample, specify \code{individualy = TRUE}. +To perform the exact same baseline adjustment on all samples, specify +\code{individually = FALSE}. To adjust with a unique determination for each +sample, specify \code{individualy = TRUE}. -Il peut être souhaitable de décaler le signal de la ligne de base (0 pour l'absorbance ou 100 pour la transmittance) pour faciliter le tracé des spectres. Cela peut être fait pour tous les échantillons ou un sous-ensemble, en utilisant le même décalage pour tous les échantillons ajustés ou calculés individuellement. +Il peut être souhaitable de décaler le signal de la ligne de base (0 pour +l'absorbance ou 100 pour la transmittance) pour faciliter le tracé des +spectres. Cela peut être fait pour tous les échantillons ou un +sous-ensemble, en utilisant le même décalage pour tous les échantillons +ajustés ou calculés individuellement. -Le recalcul ou le décalage de la ligne de base/transmittance maximale peut être effectué en suivant l'une des méthodes suivantes : +Le recalcul ou le décalage de la ligne de base/transmittance maximale peut +être effectué en suivant l'une des méthodes suivantes : \itemize{ \item Pour décaler la ligne de base en fonction de la valeur à un nombre d'ondes donné : \verb{recalculate_baseline(ftir, wavenumber_range = [numeric], method = 'point')} -\item Pour décaler la ligne de base en fonction de la valeur moyenne sur un nombre d'ondes donné : #' \verb{recalculate_baseline(ftir) = [numerique], method = 'point') }recalculate_baseline(ftir, wavenumber_range = c(\link{numeric}, \link{numeric}), method = 'average')` -\item Pour décaler la ligne de base en fonction de la valeur du point d'absorbance le plus bas (ou du point de transmittance le plus élevé) sur l'ensemble des spectres. +\item Pour décaler la ligne de base en fonction de la valeur moyenne sur un nombre +d'ondes donné : #' \verb{recalculate_baseline(ftir) = [numerique], method = 'point') }recalculate_baseline(ftir, wavenumber_range = c(\link{numeric}, \link{numeric}), +method = 'average')` +\item Pour décaler la ligne de base en fonction de la valeur du point d'absorbance +le plus bas (ou du point de transmittance le plus élevé) sur l'ensemble des spectres. \code{recalculate_baseline(ftir, method = 'minimum')} -\item Décaler la ligne de base en fonction de la valeur du point d'absorbance le plus bas (ou du point de transmittance le plus élevé) dans une gamme donnée. +\item Décaler la ligne de base en fonction de la valeur du point d'absorbance le +plus bas (ou du point de transmittance le plus élevé) dans une gamme donnée. \verb{recalculate_baseline(ftir, wavenumber_range = c([numeric], [numeric]), method = 'minimum')} -} -Pour effectuer exactement le même ajustement de la ligne de base sur tous les échantillons, spécifiez \code{individually = FALSE}. Pour ajuster avec une détermination unique pour chaque échantillon, spécifiez \code{individualy = TRUE}. +Pour effectuer exactement le même ajustement de la ligne de base sur tous +les échantillons, spécifiez \code{individually = FALSE}. Pour ajuster avec une +détermination unique pour chaque échantillon, spécifiez \code{individualy = TRUE}. +} } \examples{ # Adjust the biodiesel spectra to minimum for each sample diff --git a/man/save_plot.Rd b/man/save_plot.Rd index 12b2412..a8a6c2d 100644 --- a/man/save_plot.Rd +++ b/man/save_plot.Rd @@ -29,7 +29,7 @@ Save FTIR plot object to file. Uses [ggplot2::ggsave()] to save to disk. Enregistrer l'objet de tracé IRTF dans un fichier. Utilise [ggplot2::ggsave()] pour enregistrer sur le disque. } \examples{ -if(requireNamespace("ggplot2", quietly = TRUE)){ +if (requireNamespace("ggplot2", quietly = TRUE)) { td <- tempdir() save_plot(plot_ftir(biodiesel), filename = file.path(td, "biodiesel_plot.png")) } diff --git a/tests/testthat/test-maths.R b/tests/testthat/test-maths.R index 1c34899..e3d7925 100644 --- a/tests/testthat/test-maths.R +++ b/tests/testthat/test-maths.R @@ -515,3 +515,32 @@ test_that("Baseline - minimum/maximum works", { recalculate_baseline(ftir_data, sample_ids = c("A", "B"), method = "maximum", wavenumber_range = c(1030, 1050), individually = FALSE) ) }) + + +test_that("Normalization works", { + expect_error(normalize_spectra("not_a_dataframe"), regexp = "must be a data frame. You provided a string", fixed = TRUE) + expect_error(normalize_spectra(biodiesel, sample_ids = "A"), regexp = "All provided `sample_ids` must be in `ftir` data.", fixed = TRUE) + expect_error(normalize_spectra(biodiesel, wavenumber_range = c(1, 2, 3)), regexp = "must be of length 2", fixed = TRUE) + expect_error(normalize_spectra(biodiesel, wavenumber_range = c("one", "two")), regexp = "`wavenumber_range` must be `numeric` or `NA`.", fixed = TRUE) + expect_error(normalize_spectra(biodiesel, wavenumber_range = c(1, NA)), regexp = "`wavenumber_range` must be `numeric` or `NA`", fixed = TRUE) + expect_error(normalize_spectra(biodiesel, wavenumber_range = 1500), regexp = "must be of length 2", fixed = TRUE) + expect_error(normalize_spectra(absorbance_to_transmittance(biodiesel)), regexp = "Normalization of Transmittance spectra not supported", fixed = TRUE) + + spectra <- data.frame( + wavenumber = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + absorbance = c(0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9), + sample_id = "test" + ) + expect_equal(range(spectra$absorbance), c(0.1, 1.9)) + expect_equal(range(normalize_spectra(spectra)$absorbance), c(0.0, 1.0)) + expect_equal(range(normalize_spectra(spectra, wavenumber_range = c(1, 5))$absorbance), c(0.0, 2.25)) + expect_equal(range(normalize_spectra(spectra, wavenumber_range = c(6, 10))$absorbance), c(-1.25, 1)) + + biodiesel_normal <- normalize_spectra(biodiesel, sample_ids = c("diesel_unknown")) + + expect_equal( + range(biodiesel[biodiesel$sample_id == "biodiesel_0", "absorbance"]), + range(biodiesel_normal[biodiesel_normal$sample_id == "biodiesel_0", "absorbance"]) + ) + expect_equal(range(biodiesel_normal[biodiesel_normal$sample_id == "diesel_unknown", "absorbance"]), c(0, 1)) +})