#' Parse files with OpenChrom
#'
#' Writes `xml` batch-files and calls OpenChrom file parsers using a
#' system call to the command-line interface. To use this function
#' [OpenChrom](https://lablicate.com/platform/openchrom) (version 0.4.0) must be
#' manually installed. The command line interface is no longer supported in the
#' latest versions of OpenChrom (starting with version 0.5.0), so the function
#' will no longer work with these newer versions. OpenChrom 1.4 has been scrubbed
#' from the internet, but OpenChrom 1.3 is still available from
#' [SourceForge](https://sourceforge.net/projects/openchrom/files/REL-1.3.0/).
#'
#' The \code{call_openchrom} works by creating an \code{xml} batchfile and
#' feeding it to the OpenChrom command-line interface. OpenChrom batchfiles
#' consist of \code{InputEntries} (the files you want to convert) and
#' \code{ProcessEntries} (what you want to do to the files). The parsers are
#' organized into broad categories by detector-type and output format. The
#' detector-types are \code{msd} (mass selective detectors), \code{csd}
#' (current selective detectors, e.g. FID, ECD, NPD), and \code{wsd}
#' (wavelength selective detectors, e.g. DAD, and UV/VIS). Thus, when calling
#' the OpenChrom parsers, you must select one of these three options for the
#' input format (\code{format_in}).
#'
#' @note Activating the OpenChrom command-line will deactivate the graphical
#' user interface (GUI). Thus, if you wish to continue using the OpenChrom GUI,
#' it is recommended to create a separate command-line version of OpenChrom to
#' call from R.
#'
#' @import xml2
#' @param files files to parse
#' @param path_out directory to export converted files.
#' @param format_in Either `msd` for mass spectrometry data, `csd` for flame
#' ionization data, or `wsd` for DAD/UV data.
#' @param format_out R format. Either \code{matrix}, \code{data.frame} or
#' \code{data.table}.
#' @param data_format Whether to return data in \code{wide} or \code{long} format.
#' @param export_format Either \code{mzml}, \code{csv}, \code{cdf}, \code{animl}.
#' Defaults to \code{mzml}.
#' @param return_paths Logical. If TRUE, the function will return a character
#' vector of paths to the newly created files.
#' @param verbose Logical. Whether to print output from OpenChrom to the console.
#' @return If \code{return_paths} is \code{FALSE}, the function will return a
#' list of chromatograms (if an appropriate parser is available to import the
#' files into R). The chromatograms will be returned in \code{matrix} or
#' \code{data.frame} format according to the value of \code{format_out}. If
#' \code{return_paths} is \code{TRUE}, the function will return a character
#' vector of paths to the newly created files.
#' @section Side effects: Chromatograms will be exported in the format specified
#' by \code{export_format} in the folder specified by \code{path_out}.
#' @author Ethan Bass
#' @references
#' Wenig, Philip and Odermatt, Juergen. OpenChrom: A Cross-Platform Open Source
#' Software for the Mass Spectrometric Analysis of Chromatographic Data. \emph{
#' BMC Bioinformatics} \bold{11}, no. 1 (July 30, 2010): 405.
#' \doi{10.1186/1471-2105-11-405}.
#' @export
call_openchrom <- function(files, path_out = NULL, format_in,
format_out = c("matrix", "data.frame", "data.table"),
data_format = c("wide", "long"),
export_format = c("mzml", "csv", "cdf", "animl"),
return_paths = FALSE,
verbose = getOption("verbose")){
format_out <- check_format_out(format_out)
if (length(files) == 0){
stop("Files not found.")
}
if (missing(format_in)){
stop("Format must be specified. The options are `msd` for mass spectrometry,
`csd` for flame ionization (FID), or `wsd` for DAD/UV data.")}
export_format <- match.arg(export_format, c("mzml", "csv", "cdf", "animl"))
if (is.null(path_out)){
path_out <- tempdir()
} else{
path_out <- fs::path_expand(path_out)
}
if(!dir.exists(path_out)){
stop("Export directory not found. Please check `path_out` argument and try again.")
}
openchrom_path <- configure_openchrom()
path_xml <- write_openchrom_batchfile(files = files, path_out = path_out,
format_in = format_in,
export_format = export_format)
system(paste0(openchrom_path, " -nosplash -cli -batchfile ", path_xml),
ignore.stdout = !verbose, ignore.stderr = !verbose)
new_files <- fs::path(path_out,
fs::path_ext_remove(fs::path_file(files)),
ext = switch(export_format, "animl" = "animl",
"csv" = "csv", "cdf" = "CDF",
"mzml" = "mzML"))
if (return_paths){
new_files
} else{
file_reader <- switch(export_format,
"csv" = read.csv,
"cdf" = purrr::partial(read_cdf, format_out = format_out,
data_format = data_format),
"animl" = warning("An animl parser is not currently available in chromConverter"),
"mzml" = read_mzml)
lapply(new_files, function(x){
xx <- file_reader(x)
if (export_format == "csv" && format_out == "matrix"){
xx <- as.matrix(xx)
}
xx
})
}
}
#' Writes OpenChrom XML batch file
#' This function is called internally by \code{call_openchrom}.
#' @import xml2
#' @param files Paths to files for conversion
#' @param path_out directory to export converted files.
#' @param format_in Either \code{msd} for mass spectrometry data, \code{csd} for
#' flame ionization data, or \code{wsd} for DAD/UV data.
#' @param export_format Either \code{csv}, \code{cdf}, \code{mzml}, or \code{animl}.
#' @return Returns path to newly created xml batch file.
#' @author Ethan Bass
#' @noRd
write_openchrom_batchfile <- function(files, path_out,
format_in = c("msd", "csd", "wsd"),
export_format = c("csv", "cdf", "mzml",
"animl")){
path_template <- system.file("openchrom_template.xml",
package = "chromConverter")
x <- xml2::read_xml(x = path_template)
input_entries <- xml_find_first(x,"//InputEntries")
for (file in files){
xml_add_child(input_entries, .value = "InputEntry") |>
xml_add_child(xml_cdata(file))
}
### add appropriate parser to ProcessEntries ###
msd_mzml_converter <- 'ProcessEntry id="msd.export.org.eclipse.chemclipse.msd.converter.supplier.mzml" name="mzML Chromatogram (*.mzML)" description="Reads mzML Chromatograms" jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
msd_netcdf_converter <- 'ProcessEntry id="msd.export.net.openchrom.msd.converter.supplier.cdf" name="ANDI/AIA CDF Chromatogram (*.CDF)" description="Reads an writes ANDI/AIA CDF Chromatograms." jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
msd_animl_converter <- 'ProcessEntry id="msd.export.net.openchrom.msd.converter.supplier.animl.chromatogram" name="AnIML MSD Chromatogram (*.animl)" description="Reads and writes Analytical Information Markup Language Chromatograms" jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
msd_csv_converter <- 'ProcessEntry id="msd.export.org.eclipse.chemclipse.msd.converter.supplier.csv" name="CSV Chromatogram (*.csv)" description="Reads and Writes Chromatograms to CSV." jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
csd_csv_converter <- 'ProcessEntry id="csd.export.org.eclipse.chemclipse.csd.converter.supplier.csv" name="CSV Chromatogram (*.csv)" description="Reads and Writes Chromatograms to CSV." jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
csd_animl_converter <- 'ProcessEntry id="csd.export.net.openchrom.csd.converter.supplier.animl" name="AnIML FID Chromatogram (*.animl)" description="Writes AnIML Chromatograms." jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
wsd_animl_converter <- 'ProcessEntry id="wsd.export.net.openchrom.wsd.converter.supplier.animl.chromatogram" name="AnIML UV-Vis Chromatogram (*.animl)" description="Reads Analytical Information Markup Language Chromatograms" jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
wsd_csv_converter <- 'ProcessEntry id="wsd.export.org.eclipse.chemclipse.csd.converter.supplier.csv" name="CSV Chromatogram (*.csv)" description="Reads and Writes Chromatograms to CSV." jsonSettings="{"Filename":"{chromatogram_name}{extension}","Export Folder":"path_out"}" symbolicName="" className="" dataTypes=""'
if (format_in == "msd"){
parser <- switch(export_format,
"mzml" = msd_mzml_converter,
"cdf" = msd_netcdf_converter,
"animl" = msd_animl_converter,
"csv" = msd_csv_converter)
} else if (format_in == "csd"){
parser <- switch(export_format,
"csv" = csd_csv_converter,
"animl" = csd_animl_converter)
} else if (format_in == "wsd"){
parser <- switch(export_format,
"csv" = wsd_csv_converter,
"animl" = wsd_animl_converter)
}
process_entries <- xml_find_first(x,"//ProcessEntries")
for (file in files){
xml_add_child(input_entries, .value = gsub("path_out", path_out, parser))
}
path_xml <- fs::path(path_out, paste0("batchfile_",
strftime(Sys.time(),
format = "%Y-%m-%d_%H-%M-%S")),
ext = "xml")
write_xml(x, file = path_xml)
path_xml
}
#' Configure OpenChrom parser
#'
#' @name configure_openchrom
#' @param cli Defaults to NULL. If "true", R will rewrite openchrom ini file to enable CLI.
#' If "false", R will disable CLI. If NULL, R will not modify the ini file.
#' @param path Path to 'OpenChrom' executable (Optional). The supplied path will
#' overwrite the current path.
#' @importFrom utils read.table write.table
#' @return If \code{cli} is set to \code{"status"}, returns a Boolean value
#' indicating whether 'OpenChrom' is configured correctly. Otherwise, returns
#' the path to OpenChrom command-line application.
#' @author Ethan Bass
#' @export
configure_openchrom <- function(cli = c("null", "true", "false", "status"), path = NULL){
cli <- match.arg(cli, c("null", "true", "false", "status"))
if (is.null(path)){
path_parser <- readLines(system.file("shell/path_to_openchrom_commandline.txt", package = 'chromConverter'))
if (path_parser == "NULL"){
path_parser <- switch(.Platform$OS.type,
unix = "/Applications/Eclipse.app/Contents/MacOS/openchrom",
windows = fs::path(fs::path_home(),
"AppData/Local/Programs/OpenChrom/openchrom.exe"),
linux = "/snap/bin/openchrom"
)
}
} else{
path_parser <- path
}
if (grepl("app/?$", path_parser)){
path_parser <- fs::path(path_parser, "Contents/MacOS/openchrom")
}
writeLines(path_parser,
con = system.file('shell/path_to_openchrom_commandline.txt',
package='chromConverter'))
if (!file.exists(path_parser)){
warning("OpenChrom not found!", immediate. = TRUE)
path_parser <- readline(prompt = "Please provide path to `OpenChrom` command line (v0.4)):")
if (.Platform$OS.type == "windows"){
path_parser <- gsub("/","\\\\", path_parser)
}
writeLines(path_parser,
con = system.file('shell/path_to_openchrom_commandline.txt',
package='chromConverter'))
}
path_ini <- switch(.Platform$OS.type,
"unix" = paste0(gsub("MacOS/openchrom", "", path_parser),
"Eclipse/openchrom.ini"),
"linux" = paste0(path_parser, ".uni"),
"windows" = paste0(gsub(".exe", "", path_parser), ".ini"))
ini <- readLines(path_ini)
cli_index <- grep("-Denable.cli.support", ini)
ini_split <- strsplit(ini[cli_index], "=")[[1]]
cli_bool <- ini_split[2]
if (cli == "null"){
if (cli_bool == "false"){
message(" The OpenChrom command-line interface is turned off!
Update `openchrom.ini` to activate the command-line interface (y/n)?
(Warning: This will deactivate the GUI on your OpenChrom installation!)")
ans <- readline()
if (ans %in% c("y","Y", "yes", "Yes", "YES")){
cli <- "true"
} else{
stop("-Denable.cli.support must be enabled to use the OpenChrom parsers from R.")
}
}
} else if (cli == "status"){
return(cli_bool)
}
if (cli %in% c("true", "false")){
ini_split[2] <- cli
ini[cli_index] <- paste(ini_split, collapse = "=")
writeLines(ini, path_ini)
}
path_parser[1]
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.