## ----echo = FALSE, message = FALSE--------------------------------------------
knitr::opts_chunk$set(echo = TRUE, message = FALSE)
library(BiocStyle)

## -----------------------------------------------------------------------------
#' Class definition
setClass("MySpectrum",
         slots = c(mz = "numeric",
                   intensity = "numeric",
                   rtime = "numeric",
                   msl = "integer"),
         prototype = prototype(
             mz = numeric(),
             intensity = numeric(),
             rtime = numeric(),
             msl = integer()))

#' Default constructor function
MySpectrum <- function(mz = numeric(), intensity = numeric(),
                       rtime = numeric(), msl = integer()) {
    stopifnot(length(mz) == length(intensity))
    if (length(mz) && !length(rtime)) rtime <- NA_real_
    if (length(mz) && !length(msl)) msl <- NA_integer_
    new("MySpectrum", mz = mz, intensity = intensity, rtime = rtime,
        msl = as.integer(msl))
}

## -----------------------------------------------------------------------------
s <- MySpectrum(c(1.4, 1.6, 1.9, 2.56), c(123.1, 1235.3, 12.45, 51.5))
s

## -----------------------------------------------------------------------------
library(MsStash)

## -----------------------------------------------------------------------------
#' Write example class to a plain text file
setMethod("saveMsObject", signature(object = "MySpectrum",
                                    param = "PlainTextParam"),
          function(object, param) {
              dir.create(path = param@path, recursive = TRUE,
                         showWarnings = FALSE)
              fl <- file.path(param@path, "my_spectrum.txt")
              if (file.exists(fl))
                  stop("Overwriting an existing result object is not ",
                       "supported.")
              ## Write the type of object as a comment followed by the
              ## metadata.
              writeLines(c(paste0("# ", class(object)[1L]),
                           paste0("rtime:", object@rtime),
                           paste0("msl:", object@msl)), con = fl)
              ## Write the peak data, i.e. m/z and intensity values
              write.table(cbind(object@mz, object@intensity), file = fl,
                          sep = "\t", append = TRUE, col.names = FALSE,
                          row.names = FALSE)
          })

## -----------------------------------------------------------------------------
p <- PlainTextParam(path = file.path(tempdir(), "text_format"))
saveMsObject(s, p)

## -----------------------------------------------------------------------------
readLines(file.path(p@path, "my_spectrum.txt"))

## -----------------------------------------------------------------------------
#' Read example object from plain text file storage format
setMethod("readMsObject", signature(object = "MySpectrum",
                                    param = "PlainTextParam"),
          function(object, param) {
              fl <- file.path(param@path, "my_spectrum.txt")
              if (!file.exists(fl))
                  stop("my_spectrum.txt not found in the provided path")
              l <- readLines(fl, n = 3) # read the comment and the metadata
              p <- read.table(fl, sep = "\t", skip = 3)
              MySpectrum(
                  mz = p[, 1L], intensity = p[, 2L],
                  rtime = suppressWarnings(
                      as.numeric(sub("rtime:", "", l[2], fixed = TRUE))),
                  msl = suppressWarnings(
                      as.integer(sub("msl:", "", l[3], fixed = TRUE))))
          })

## -----------------------------------------------------------------------------
p <- PlainTextParam(path = file.path(tempdir(), "text_format"))
b <- readMsObject(MySpectrum(), p)
b

## -----------------------------------------------------------------------------
library(alabaster.base)

setMethod("saveObject", "MySpectrum", function(x, path, ...) {
    ## Create the directory where to save the data
    dir.create(path = path, recursive = TRUE, showWarnings = FALSE)
    ## Create an "object" file; this defines the type of object stored in path
    saveObjectFile(path, "my_spectrum")
    ## save each slot into it's own directory
    altSaveObject(x@mz, path = file.path(path, "mz"))
    altSaveObject(x@intensity, path = file.path(path, "intensity"))
    altSaveObject(x@rtime, path = file.path(path, "retention_time"))
    altSaveObject(x@msl, path = file.path(path, "ms_level"))
})

## -----------------------------------------------------------------------------
#' Define a helper function to check that the folder contains all
#' expected sub-directories.
validateMySpectrum <- function(path, metadata) {
    if (!dir.exists(path))
        stop("Directory ", path, " does not exist")
    req_dir <- c("mz", "intensity", "retention_time", "ms_level")
    if (any(miss <- !dir.exists(file.path(path, req_dir))))
        stop("Required directories ",
             paste0("\"", req_dir[miss], "\"", collapse = ", "),
             " not found in ", path)
}

#' Register the validation function
registerValidateObjectFunction("my_spectrum", validateMySpectrum)

## -----------------------------------------------------------------------------
#' Define a function that can read from an alabaster-based serialization
#' of `MySpectrum` objects
readMySpectrum <- function(path, metadata, ...) {
    validateMySpectrum(path)
    ## Read the data from individual sub-directories
    mz <- altReadObject(file.path(path, "mz"))
    int <- altReadObject(file.path(path, "intensity"))
    rtime <- altReadObject(file.path(path, "retention_time"))
    msl <- altReadObject(file.path(path, "ms_level"))
    MySpectrum(mz = mz, intensity = int, rtime = rtime, msl = msl)
}

#' Register the read function
registerReadObjectFunction("my_spectrum", readMySpectrum)

## -----------------------------------------------------------------------------
#' Define the path where we want to export out data
p <- file.path(tempdir(), "alabaster_export")

#' Save the object
saveObject(s, path = p)

## -----------------------------------------------------------------------------
library(fs)
dir_tree(p)

## -----------------------------------------------------------------------------
b <- readObject(p)
b

## -----------------------------------------------------------------------------
#' Write example class to a plain text file
setMethod("saveMsObject", signature(object = "MySpectrum",
                                    param = "AlabasterParam"),
          function(object, param) {
              if (file.exists(file.path(param@path, "OBJECT")))
                  stop("'path' contains already an MS data stash. Overwriting",
                       " is not supported. Please remove 'path' first.")
              saveObject(object, param@path)
          })

#' Read example object from plain text file storage format
setMethod("readMsObject", signature(object = "MySpectrum",
                                    param = "AlabasterParam"),
          function(object, param) {
              readMySpectrum(param@path)
          })

## -----------------------------------------------------------------------------
p <- file.path(tempdir(), "alabaster_format_2")
ap <- AlabasterParam(p)

saveMsObject(s, ap)

## -----------------------------------------------------------------------------
b <- readMsObject(MySpectrum(), ap)
b

## -----------------------------------------------------------------------------
sessionInfo()

