Skip to content

Commit

Permalink
feat: add filterPrecursorMzValues (issue #230)
Browse files Browse the repository at this point in the history
- Add the `filterPrecursorMzValues` method to enable filtering based on multiple
  target precursor m/z values.
  • Loading branch information
jorainer committed Dec 10, 2021
1 parent 94aa191 commit 4687a57
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 9 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: Spectra
Title: Spectra Infrastructure for Mass Spectrometry Data
Version: 1.5.2
Version: 1.5.3
Description: The Spectra package defines an efficient infrastructure
for storing and handling mass spectrometry spectra and functionality to
subset, process, visualize and compare spectra data. It provides different
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ exportMethods(filterMzValues)
exportMethods(filterPolarity)
exportMethods(filterPrecursorCharge)
exportMethods(filterPrecursorMz)
exportMethods(filterPrecursorMzValues)
exportMethods(filterPrecursorScan)
exportMethods(filterRt)
exportMethods(intensity)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Spectra 1.5

## Changes in 1.5.3

- Add `filterPrecursorMzValues` method to filter `Spectra` keeping all spectra
with matching precursor m/z (supports multiple target precursor m/z values).

## Changes in 1.5.2

- Small documentation update (related to `MsCoreUtils` issue
Expand Down
3 changes: 3 additions & 0 deletions R/AllGenerics.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ setGeneric("filterMzRange", function(object, ...)
setGeneric("filterMzValues", function(object, ...)
standardGeneric("filterMzValues"))
#' @rdname hidden_aliases
setGeneric("filterPrecursorMzValues", function(object, ...)
standardGeneric("filterPrecursorMzValues"))
#' @rdname hidden_aliases
setGeneric("isReadOnly", function(object, ...)
standardGeneric("isReadOnly"))
#' @rdname hidden_aliases
Expand Down
29 changes: 26 additions & 3 deletions R/MsBackend.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,12 @@
#'
#' @param mz For `filterIsolationWindow`: `numeric(1)` with the m/z value to
#' filter the object. For `filterPrecursorMz`: `numeric(2)` with the lower
#' and upper m/z boundary.
#' and upper m/z boundary. For `filterPrecursorMzValues`: `numeric` with the
#' m/z value(s) to filter the object.
#'
#' @param ppm For `filterPrecursorMzValues`: `numeric(1)` with the m/z-relative
#' maximal acceptable difference for a m/z to be considered matching. See
#' [closest()] for details.
#'
#' @param z For `filterPrecursorCharge`: `integer()` with the precursor charges
#' to be used as filter.
Expand All @@ -112,6 +117,10 @@
#' @param spectraVariables For `selectSpectraVariables`: `character` with the
#' names of the spectra variables to which the backend should be subsetted.
#'
#' @param tolerance For `filterPrecursorMzValues`: `numeric(1)` with the
#' maximal absolute acceptable difference for an m/z value to be considered
#' matching. See [closest()] for details.
#'
#' @param use.names For `lengths`: whether spectrum names should be used.
#'
#' @param value replacement value for `<-` methods. See individual
Expand Down Expand Up @@ -253,6 +262,11 @@
#' Implementation of this method is optional since a default implementation
#' for `MsBackend` is available.
#'
#' - `filterPrecursorMzValues`: retains spectra with a precursor m/z matching
#' any of the provided m/z values (given `ppm` and `tolerance`).
#' Implementation of this method is optional since a default implementation
#' for `MsBackend` is available.
#'
#' - `filterPrecursorCharge`: retains spectra with the defined precursor
#' charge(s).
#' Implementation of this method is optional since a default implementation
Expand Down Expand Up @@ -844,6 +858,17 @@ setMethod("filterPrecursorMz", "MsBackend",
} else object
})

#' @exportMethod filterPrecursorMzValues
#'
#' @rdname MsBackend
setMethod("filterPrecursorMzValues", "MsBackend",
function(object, mz = numeric(), ppm = 20, tolerance = 0) {
if (length(mz)) {
object[.values_match_mz(precursorMz(object), mz = mz,
ppm = ppm, tolerance = tolerance)]
} else object
})

#' @exportMethod filterPrecursorCharge
#'
#' @importMethodsFrom ProtGenerics filterPrecursorCharge
Expand All @@ -857,8 +882,6 @@ setMethod("filterPrecursorCharge", "MsBackend",
} else object
})



#' @exportMethod filterPrecursorScan
#'
#' @importMethodsFrom ProtGenerics filterPrecursorScan
Expand Down
20 changes: 18 additions & 2 deletions R/Spectra.R
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ NULL
#' provided m/z range. See examples for details on selecting spectra with
#' a precursor m/z for a target m/z accepting a small difference in *ppm*.
#'
#' - `filterPrecursorMzValues`: retains spectra with precursor m/z matching any
#' of the provided m/z values (given `ppm` and `tolerance`). Spectra with
#' missing precursor m/z value (e.g. MS1 spectra) are dropped.
#'
#' - `filterPrecursorCharge`: retains spectra with the defined precursor
#' charge(s).
#'
Expand Down Expand Up @@ -702,8 +706,8 @@ NULL
#' @param mz For `filterIsolationWindow`: `numeric(1)` with the m/z value to
#' filter the object. For `filterPrecursorMz` and `filterMzRange`:
#' `numeric(2)` defining the lower and upper m/z boundary.
#' For `filterMzValues`: `numeric` with the m/z values to match peaks
#' against.
#' For `filterMzValues` and `filterPrecursorMzValues`: `numeric` with the
#' m/z values to match peaks or precursor m/z against.
#'
#' @param z For `filterPrecursorCharge`: `integer()` with the precursor charges
#' to be used as filter.
Expand Down Expand Up @@ -1943,6 +1947,18 @@ setMethod("filterPrecursorMz", "Spectra",
object
})

#' @rdname Spectra
setMethod("filterPrecursorMzValues", "Spectra",
function(object, mz = numeric(), ppm = 20, tolerance = 0) {
object@backend <- filterPrecursorMzValues(
object@backend, mz, ppm = ppm, tolerance = tolerance)
object@processing <- .logging(
object@processing,
"Filter: select spectra with precursor m/z matching ",
paste0(mz, collapse = ", "), "")
object
})

#' @rdname Spectra
setMethod("filterPrecursorCharge", "Spectra",
function(object, z = integer()) {
Expand Down
19 changes: 19 additions & 0 deletions R/functions-util.R
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,22 @@ setAs("logical", "factor", function(from, to) factor(from))
sanitize_file_name <- function(x) {
file.path(normalizePath(dirname(x)), path_sanitize(basename(x)))
}

#' Helper function that matches `x` against `mz` (using the `closest` function)
#' and returns the indices of `x` that match any of the values in `mz`. The
#' function takes care of sorting `x` and `mz` and deals also with missing
#' values.
#'
#' @return `integer` with the indices of values in `x` that are not `NA` and
#' are matching any of the values in `mz` given `ppm` and `tolerance`.
#'
#' @noRd
#'
#' @author Johannes Rainer
.values_match_mz <- function(x, mz, ppm = 20, tolerance = 0) {
keep <- which(!is.na(x))
idx <- order(x[keep])
mtch <- closest(x[keep][idx], sort(mz), tolerance = tolerance, ppm = ppm,
duplicates = "keep", .check = FALSE)
keep[!is.na(mtch[order(idx)])]
}
18 changes: 17 additions & 1 deletion man/MsBackend.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions man/Spectra.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions man/hidden_aliases.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions tests/testthat/test_functions-util.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,23 @@ test_that("sanitize_file_name works", {
expect_equal(basename(res)[1], "memory")
expect_equal(basename(res)[2], "path")
})

test_that(".values_match_mz works", {
pmz <- c(12.4, 15, 3, 12.4, 3, 1234, 23, 5, 12.4, NA, 3)
mz <- c(200, 12.4, 3)

res <- .values_match_mz(pmz, mz)
expect_true(all(pmz[res] %in% mz))
expect_false(any(pmz[-res] %in% mz))

pmz <- rev(pmz)
res <- .values_match_mz(pmz, mz)
expect_true(all(pmz[res] %in% mz))
expect_false(any(pmz[-res] %in% mz))

res <- .values_match_mz(c(NA, NA), mz)
expect_identical(res, integer())

res <- .values_match_mz(pmz, c(NA, 3))
expect_true(all(pmz[res] == 3))
})

0 comments on commit 4687a57

Please sign in to comment.