rformassspectrometry / Spectra

Low level infrastructure to handle MS spectra
https://rformassspectrometry.github.io/Spectra/
34 stars 24 forks source link

fix: fix show,ProcessingStep (issue #162) #163

Closed jorainer closed 3 years ago

jorainer commented 3 years ago

This fixes issue #162 (as well as issue #70)

lgatto commented 3 years ago

Here's a real-life example that isn't very readable. I don't think printing de function body is a good solution; show print a much shorter and readable, I think.

> x <- Spectra(fl)
> ## function used as arguement to filterIntensity()
> low_int <- function(x, percentage = 0.05) {
+   x > max(x, na.rm = TRUE) * percentage
+ }
> x1 <- filterRt(x, rt = c(rtime(x)[1] - 24, rtime(x)[1] + 24))
> x1 <- filterEmptySpectra(x1)
> x1 <- filterMzRange(x1, c(1648, 1655))
> x1 <- combineSpectra(x1, intensityFun = sum)
Backend of the input object is read-only, will change that to an 'MsBackendDataFrame'
> x1 <- filterIntensity(x1, low_int)
> x1 <- pickPeaks(x1)
> x1@processingQueue
[[1]]
Object of class "ProcessingStep"
 Function: function(x, spectrumMsLevel, intensity,
                                             msLevel = spectrumMsLevel, ...) {

    if (!spectrumMsLevel %in% msLevel || !length(x))
        return(x)
    keep <- intensity(x[, "intensity"])
    if (!is.logical(keep) || length(keep) != nrow(x))
        stop("Error in filterIntensity: the provided function does not return ",
             "a logical vector of length equal to the number of peaks.",
             call. = FALSE)
    x[which(keep), , drop = FALSE]
}
<environment: namespace:Spectra>
 Arguments:
  o  intensity  = function(x, percentage = 0.05) {
  x > max(x, na.rm = TRUE) * percentage
}
  o  msLevel  = [1] 1

[[2]]
Object of class "ProcessingStep"
 Function: function(x, spectrumMsLevel, centroided = NA,
                        halfWindowSize = 2L, method = c("MAD", "SuperSmoother"),
                        snr = 0L, k = 0L, descending = FALSE, threshold = 0,
                        msLevel = spectrumMsLevel, ...) {
    if (!(spectrumMsLevel %in% msLevel))
        return(x)
    if (!nrow(x)) {
        warning("Spectrum is empty. Nothing to pick.")
        return(x)
    }

    n <- noise(x[, 1L], x[, 2L], method = method, ...)

    l <- localMaxima(x[, 2L], hws = halfWindowSize)

    p <- which(l & x[, 2L] > (snr * n))

    if (k > 0L) {
        cbind(mz = refineCentroids(x = x[, 1L], y = x[, 2L], p = p,
                                   k = k, threshold = threshold,
                                   descending = descending),
              intensity = x[p, 2L])
    } else {
        x[p, , drop = FALSE]
    }
}
<environment: namespace:Spectra>
 Arguments:
  o  halfWindowSize  = [1] 2
  o  method  = [1] "MAD"
  o  snr  = [1] 0
  o  k  = [1] 0
  o  descending  = [1] FALSE
  o  threshold  = [1] 0
  o  msLevel  = [1] 1
jorainer commented 3 years ago

Agree, that doesn't look good at all. I first tried to just get the function name with deparse(substitute( but that did not work for the arguments - there it was then simply printing args[1]. So maybe your solution is better. I will change.

lgatto commented 3 years ago

Maybe an exception, but for anonymous functions, there wouldn't be any name at all.

jorainer commented 3 years ago

show,ProcessingStep will now print "user-provided function" if an argument or @FUN is a function.

lgatto commented 3 years ago

I now get

> x1@processingQueue
[[1]]
Object of class "ProcessingStep"
 Function: user-provided function
 Arguments:
  o intensity = user-provided function  o msLevel = 1
[[2]]
Object of class "ProcessingStep"
 Function: user-provided function
 Arguments:
  o halfWindowSize = 2  o method = MAD  o snr = 0  o k = 0  o descending = FALSE  o threshold = 0  o msLevel = 1

I think you are missing a newline in the cat():

        for (i in seq_along(args)) {
            cat("  o ", names(args)[i], " = ", .cat_fun(args[[i]]), "\n", sep = "")
        }

to get

> x1@processingQueue
[[1]]
Object of class "ProcessingStep"
 Function: user-provided function
 Arguments:
  o intensity = user-provided function
  o msLevel = 1

[[2]]
Object of class "ProcessingStep"
 Function: user-provided function
 Arguments:
  o halfWindowSize = 2
  o method = MAD
  o snr = 0
  o k = 0
  o descending = FALSE
  o threshold = 0
  o msLevel = 1
jorainer commented 3 years ago

I fixed now the missing "\n" and added real unit tests for show,ProcessingStep.

jorainer commented 3 years ago

I will also fix this in the release version