heavy isotopes support
Showing 2 of 7 files from the diff.
R/chemFormula.R
changed.
Other files ignored by Codecov
DESCRIPTION
has changed.
tests/testthat/test_chemFormula.R
has changed.
NEWS.md
has changed.
tests/testthat/test_zzz.R
has changed.
man/calculateMass.Rd
has changed.
@@ -23,25 +23,30 @@
Loading
23 | 23 | ## regex pattern to isolate all elements |
|
24 | 24 | element_pattern <- paste0( |
|
25 | 25 | "(?<Element>", |
|
26 | - | "[A][cglmrstu]|", |
|
27 | - | "[B][aehikr]?|", |
|
28 | - | "[C][adeflmnorsu]?|", |
|
29 | - | "[D][bsy]|", |
|
30 | - | "[E][rsu]|", |
|
31 | - | "[F][elmr]?|", |
|
32 | - | "[G][ade]|", |
|
33 | - | "[H][efgos]?|", |
|
34 | - | "[I][nr]?|", |
|
35 | - | "[K][r]?|", |
|
36 | - | "[L][airuv]|", |
|
37 | - | "[M][cdgnot]|", |
|
38 | - | "[N][abdehiop]?|", |
|
39 | - | "[O][gs]?|", |
|
40 | - | "[P][abdmortu]?|", |
|
41 | - | "[R][abefghnu]|", |
|
42 | - | "[S][bcegimnr]?|", |
|
43 | - | "[T][abcehilms]|", |
|
44 | - | "[U]|[V]|[W]|[X][e]|[Y][b]?|[Z][nr]", |
|
26 | + | paste0("[0-9]*", |
|
27 | + | c( |
|
28 | + | "[A][cglmrstu]|", |
|
29 | + | "[B][aehikr]?|", |
|
30 | + | "[C][adeflmnorsu]?|", |
|
31 | + | "[D][bsy]|", |
|
32 | + | "[E][rsu]|", |
|
33 | + | "[F][elmr]?|", |
|
34 | + | "[G][ade]|", |
|
35 | + | "[H][efgos]?|", |
|
36 | + | "[I][nr]?|", |
|
37 | + | "[K][r]?|", |
|
38 | + | "[L][airuv]|", |
|
39 | + | "[M][cdgnot]|", |
|
40 | + | "[N][abdehiop]?|", |
|
41 | + | "[O][gs]?|", |
|
42 | + | "[P][abdmortu]?|", |
|
43 | + | "[R][abefghnu]|", |
|
44 | + | "[S][bcegimnr]?|", |
|
45 | + | "[T][abcehilms]|", |
|
46 | + | "[U]|[V]|[W]|[X][e]|[Y][b]?|[Z][nr]" |
|
47 | + | ), |
|
48 | + | collapse = "" |
|
49 | + | ), |
|
45 | 50 | ")", |
|
46 | 51 | "(?<Number>[0-9]*)" |
|
47 | 52 | ) |
@@ -56,10 +61,30 @@
Loading
56 | 61 | sbstr[!nchar(sbstr)] <- 1L |
|
57 | 62 | sl <- seq_len(n) |
|
58 | 63 | nm <- sbstr[sl] |
|
59 | - | setNames(as.integer(sbstr[n + sl]), nm) |
|
64 | + | r <- setNames(as.integer(sbstr[n + sl]), nm) |
|
65 | + | valid <- .isValidElementName(nm) |
|
66 | + | ||
67 | + | if (any(!valid)) { |
|
68 | + | warning( |
|
69 | + | "The following names are not valid and are dropped: ", |
|
70 | + | paste0(names(r)[!valid], collapse = ", ") |
|
71 | + | ) |
|
72 | + | r <- r[valid] |
|
73 | + | } |
|
74 | + | r |
|
60 | 75 | }, xx = x, rr = rx, SIMPLIFY = FALSE, USE.NAMES = TRUE) |
|
61 | 76 | } |
|
62 | 77 | ||
78 | + | #' Validate element names/heavy isotopes |
|
79 | + | #' |
|
80 | + | #' @param x `character`, element/heavy isotope names |
|
81 | + | #' @return `logical`, `TRUE` for valid name, `FALSE` otherwise |
|
82 | + | #' |
|
83 | + | #' @noRd |
|
84 | + | .isValidElementName <- function(x) { |
|
85 | + | x %in% names(.ISOTOPES) |
|
86 | + | } |
|
87 | + | ||
63 | 88 | #' @title Create chemical formula from a named vector |
|
64 | 89 | #' |
|
65 | 90 | #' @description |
@@ -92,7 +117,10 @@
Loading
92 | 117 | enms <- .sort_elements(names(x)) |
|
93 | 118 | y <- as.character(x[enms]) |
|
94 | 119 | y[y == "1"] <- "" |
|
95 | - | paste0(enms, y, collapse = "") |
|
120 | + | y <- paste0(enms, y) |
|
121 | + | ## brackets for heavy isotopes |
|
122 | + | y <- gsub("^([0-9]+[A-z]+[0-9]*)", "[\\1]", y) |
|
123 | + | paste0(y, collapse = "") |
|
96 | 124 | } |
|
97 | 125 | ||
98 | 126 | #' Sort elements starting with organic elements, according to the Hill notation |
@@ -105,9 +133,7 @@
Loading
105 | 133 | #' @examples |
|
106 | 134 | #' .sort_elements(c("H", "O", "S", "P", "C", "N", "Na", "Fe")) |
|
107 | 135 | .sort_elements <- function(x) { |
|
108 | - | org <- c("C", "H", "N", "O", "S", "P") |
|
109 | - | y <- c(org, sort(x[!x %in% org])) |
|
110 | - | x[match(y, x, nomatch = 0L)] |
|
136 | + | x[match(names(.ISOTOPES), x, nomatch = 0L)] |
|
111 | 137 | } |
|
112 | 138 | ||
113 | 139 | #' @title Standardize a chemical formula |
@@ -260,18 +286,19 @@
Loading
260 | 286 | #' calculateMass("C6H12O6") |
|
261 | 287 | #' calculateMass("NH3") |
|
262 | 288 | #' calculateMass(c("C6H12O6", "NH3")) |
|
289 | + | #' calculateMass(c("C6H12O6", "[13C3]C3H12O6")) |
|
263 | 290 | calculateMass <- function(x) { |
|
264 | 291 | if (is.character(x)) |
|
265 | 292 | x <- countElements(x) |
|
266 | 293 | if (!is.list(x)) |
|
267 | 294 | stop("x must be either a character or a list with element counts.") |
|
268 | 295 | vapply(x, function(z) { |
|
269 | - | elements <- names(z) |
|
270 | - | if (!all(elements %in% names(.MONOISOTOPES))) { |
|
271 | - | message("not for all elements a monoisotopic mass is found") |
|
296 | + | isotopes <- names(z) |
|
297 | + | if (!length(z) || !all(isotopes %in% names(.ISOTOPES))) { |
|
298 | + | message("not for all isotopes a mass is found") |
|
272 | 299 | return(NA_real_) |
|
273 | 300 | } |
|
274 | - | sum(z * .MONOISOTOPES[elements]) |
|
301 | + | sum(z * .ISOTOPES[isotopes]) |
|
275 | 302 | ## mass <- 0.0 |
|
276 | 303 | ## for (atom in elements) { |
|
277 | 304 | ## atom_mass <- .MONOISOTOPES[atom] |
@@ -17,7 +17,7 @@
Loading
17 | 17 | } |
|
18 | 18 | ||
19 | 19 | # get mono isotopes for exact mass calculation |
|
20 | - | assign(".MONOISOTOPES", .load_isotopes(), envir = asNamespace(pkgname)) |
|
20 | + | assign(".ISOTOPES", .load_isotopes(), envir = asNamespace(pkgname)) |
|
21 | 21 | } |
|
22 | 22 | ||
23 | 23 | .load_adducts <- function() { |
@@ -29,9 +29,24 @@
Loading
29 | 29 | } |
|
30 | 30 | ||
31 | 31 | .load_isotopes <- function() { |
|
32 | - | mono <- utils::read.table(system.file("isotopes", "isotope_definition.txt", |
|
33 | - | package = "MetaboCoreUtils"), |
|
34 | - | sep = "\t", header = TRUE) |
|
35 | - | vapply(split(mono, mono$element), function(z) |
|
36 | - | z$exact_mass[which.max(z$rel_abundance)], numeric(1)) |
|
32 | + | iso <- utils::read.table( |
|
33 | + | system.file( |
|
34 | + | "isotopes", "isotope_definition.txt", package = "MetaboCoreUtils" |
|
35 | + | ), |
|
36 | + | sep = "\t", header = TRUE |
|
37 | + | ) |
|
38 | + | ## sort by rel_abundance |
|
39 | + | iso <- iso[order(iso$element, -iso$rel_abundance),] |
|
40 | + | ## swap numbers and elements names |
|
41 | + | iso$isotope <- gsub("([A-z]+)([0-9]*)", "\\2\\1", iso$isotope) |
|
42 | + | ## drop isotope number from most common isotope |
|
43 | + | is_most_common <- !duplicated(iso$element) |
|
44 | + | iso$isotope[is_most_common] <- |
|
45 | + | gsub("^[0-9]+", "", iso$isotope[is_most_common]) |
|
46 | + | ## sort according to Hill notation |
|
47 | + | org <- c("C", "H", "N", "O", "S", "P") |
|
48 | + | iso$rank <- match(iso$element, org, nomatch = length(org) + 1L) |
|
49 | + | ## reorder according to Hill notation and non-common isotopes first |
|
50 | + | iso <- iso[order(iso$rank, iso$element, iso$isotope),] |
|
51 | + | setNames(iso$exact_mass, iso$isotope) |
|
37 | 52 | } |
Files | Coverage |
---|---|
R | 91.67% |
Project Totals (8 files) | 91.67% |
1968462840
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file.
The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files.
The size and color of each slice is representing the number of statements and the coverage, respectively.