Skip to content
Snippets Groups Projects
Commit 64d07b41 authored by R. Helmus's avatar R. Helmus
Browse files

Use OpenBabel for formula/neutral mass calculation

parent 3124c79e
No related branches found
Tags 1.0.1
No related merge requests found
Package: patRoon
Type: Package
Title: Workflows for Mass-Spectrometry Based Non-Target Analysis
Version: 1.0.0
Version: 1.0.1
Authors@R: c(
person("Rick", "Helmus",
email = "r.helmus@uva.nl",
......
# patRoon 1.0.1
* Perform neutral mass calculation for suspect screening with OpenBabel to avoid some possible Java/RCDK bugs on Linux.
# patRoon 1.0
## June 2020
......
......@@ -17,7 +17,7 @@ getMoleculesFromSMILES <- function(SMILES, doTyping = FALSE, doIsotopes = FALSE,
if (emptyIfFails)
ret <- emptyMol()
}
else
else if (!isEmptyMol(ret))
{
if (doTyping)
{
......@@ -35,25 +35,16 @@ getMoleculesFromSMILES <- function(SMILES, doTyping = FALSE, doIsotopes = FALSE,
getNeutralMassFromSMILES <- function(SMILES, mustWork = TRUE)
{
# NOTE: molecules are converted to formula to get the mass instead of using
# rcdk::get.exact.mass() so that the neutral mass can be obtained
getMass <- function(m) rcdk::get.mol2formula(m)@mass
sapply(getMoleculesFromSMILES(SMILES, doTyping = TRUE, doIsotopes = TRUE), function(m)
{
if (!mustWork)
{
if(!isValidMol(m))
return(NA)
# this could fail for some edge cases
return(tryCatch(getMass(m), error = function(e) NA))
}
return(getMass(m))
})
}
# Use OpenBabel to convert to (neutral) formulas and get mass from there,
# which seems less buggy compared to parsing the SMILES with RCDK and then
# using rcdk::get.mol2formula() to get the mass. The latter could give
# troubles in tryCatch() calls on Linux with certain JVMs.
forms <- convertToFormulaBabel(SMILES, "smi", mustWork = mustWork)
return(sapply(forms, function(f) if (length(f) > 0) rcdk::get.formula(f)@mass else NA_character_,
USE.NAMES = FALSE))
}
babelConvert <- function(input, inFormat, outFormat, mustWork = TRUE)
babelConvert <- function(input, inFormat, outFormat, mustWork = TRUE, extraOpts = NULL)
{
# Use batch conversion with a single input/output file. Note that obabel
# will stop after an error. This can be overidden, however, then it is
......@@ -66,10 +57,13 @@ babelConvert <- function(input, inFormat, outFormat, mustWork = TRUE)
doConversion <- function(inp)
{
cat(inp, file = inputFile, sep = "\n")
executeCommand(getCommandWithOptPath("obabel", "obabel"),
c(paste0("-i", inFormat), inputFile,
paste0("-o", outFormat), "-O", outputFile, "-xw"),
stderr = FALSE)
args <- c(paste0("-i", inFormat), inputFile,
paste0("-o", outFormat), "-O", outputFile, "-xw")
if (!is.null(extraOpts))
args <- c(args, extraOpts)
executeCommand(getCommandWithOptPath("obabel", "obabel"), args, stderr = FALSE)
# each conversion is followed by a tab (why??) and newline. Read line
# by line and remove tab afterwards.
ret <- readLines(outputFile)
......@@ -104,3 +98,10 @@ babelConvert <- function(input, inFormat, outFormat, mustWork = TRUE)
return(ret)
}
convertToFormulaBabel <- function(input, inFormat, mustWork)
{
ret <- babelConvert(input = input, inFormat = inFormat, outFormat = "txt", mustWork = mustWork,
extraOpts = c("--append", "formula"))
ret <- sub("[\\+\\-]+$", "", ret) # remove trailing positive/negative charge is present
}
......@@ -4,7 +4,7 @@ susps <- as.data.table(patRoonData::targets)
susps[, InChI := babelConvert(SMILES, "smi", "inchi")]
susps[, neutralMass := getNeutralMassFromSMILES(SMILES)]
susps[, formula := sapply(getMoleculesFromSMILES(SMILES), function(m) rcdk::get.mol2formula(m)@string)]
susps[, formula := convertToFormulaBabel(SMILES, "smi")]
susps[, adduct := "[M+H]+"]
susps[name %in% c("TBA", "TPA"), adduct := "[M]+"]
......@@ -46,12 +46,14 @@ test_that("suspect screening is OK", {
expect_equal(scrSMI, screenSuspects(fGroups, suspsMissing[, c("name", "rt", "adduct", "formula", "SMILES")]))
expect_equal(scrSMI, screenSuspects(fGroups, suspsMissing[, c("name", "rt", "adduct", "SMILES", "InChI")]))
expect_warning(screenSuspects(fGroups, suspsMissingRow, skipInvalid = TRUE))
expect_error(screenSuspects(fGroups, suspsMissingRow, skipInvalid = FALSE))
# adduct argument
expect_equal(screenSuspects(fGroups, susps[name %in% c("TBA", "TPA")]),
screenSuspects(fGroups, susps[name %in% c("TBA", "TPA"), -"adduct"], adduct = "[M]+"))
# certain Linux/JVM combinations (e.g. current CI Docker image) give Java StackOverflows...
testthat::skip_on_os("linux")
expect_warning(screenSuspects(fGroups, suspsMissingRow, skipInvalid = TRUE))
expect_error(screenSuspects(fGroups, suspsMissingRow, skipInvalid = FALSE))
})
TQFile <- file.path(getTestDataPath(), "GlobalResults-TASQ.csv")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment