#' @title Performs channel compensation on multi-channel images
#'
#' @description Corrects the intensity spillover between neighbouring channels
#' of multi-channel images using a non-negative least squares approach.
#'
#' @param object a \code{CytoImageList} object containing pixel
#' intensities for all channels. The \code{channelNames} must be in the form
#' of \code{(mt)(mass)Di} (e.g. \code{Sm152Di} for Samarium isotope with the
#' atomic mass 152) and match with the column names in \code{sm}.
#' @param sm numeric matrix containing the spillover estimated between channels.
#' The column names must be of the form \code{(mt)(mass)Di} (e.g.
#' \code{Sm152Di} for Samarium isotope with the atomic mass 152) and match to
#' the \code{channelNames} of \code{object}.
#' @param overwrite (for images stored on disk) should the original image array
#' be overwritten by the compensated image array? By default (\code{overwrite
#' = FALSE}), a new entry called "XYZ_comp" will be written to the .h5 file
#' (see below).
#' @param BPPARAM parameters for parallelised processing.
#'
#' @return returns the compensated pixel intensities in form of a
#' \code{CytoImageList} object.
#'
#' @section The input object:
#' The \code{channelNames} of \code{object} need to match the column names
#' of \code{sm}. To adapt the spillover matrix accordingly, please use the
#' \code{\link[CATALYST]{adaptSpillmat}} function.
#'
#' @section Images stored on disk:
#' Image compensation also works for images stored on disk. By default,
#' the compensated images are stored as a second entry called "XYZ_comp"
#' in the .h5 file. Here "XYZ" specifies the name of the original entry.
#' By storing the compensated next to the original images on disk, space
#' usage increases. To avoid storing duplicated data, one can specify
#' \code{overwrite = TRUE}, therefore deleting the original images
#' and only storing the compensated images. However, the original images
#' cannot be accessed anymore after compensation.
#'
#' @examples
#' data("pancreasImages")
#'
#' # Generate example spillover matrix
#' metals <- c("Dy161Di", "Dy162Di", "Dy163Di", "Dy164Di", "Ho165Di")
#' sm <- matrix(c(1, 0.033, 0.01, 0.007, 0,
#' 0.016, 1, 0.051, 0.01, 0,
#' 0.004, 0.013, 1, 0.023, 0,
#' 0.005, 0.008, 0.029, 1, 0.006,
#' 0, 0, 0, 0.001, 1), byrow = TRUE,
#' ncol = 5, nrow = 5,
#' dimnames = list(metals, metals))
#'
#' # Rename channels - just used as example
#' channelNames(pancreasImages) <- metals
#'
#' # Perform channel spillover
#' comp_images <- compImage(pancreasImages, sm)
#'
#' @author Nils Eling (\email{nils.eling@@dqbm.uzh.ch})
#'
#' @seealso
#' \code{\link[nnls]{nnls}}, for the underlying algorithm
#'
#' \code{\link[CATALYST]{compCytof}}, for how to compensate single-cell data
#'
#' @references
#' \href{https://www.sciencedirect.com/science/article/pii/S2405471217305434}{
#' Chevrier, S. et al., Compensation of Signal Spillover in Suspension
#' and Imaging Mass Cytometry., Cell Systems 2018 6(5):612-620.e5}
#'
#' @export
#' @importFrom nnls nnls
compImage <- function(object, sm, overwrite = FALSE, BPPARAM = SerialParam()){
.valid.compImage.input(object, sm)
cur_channels <- channelNames(object)
cur_meta <- mcols(object)
if (is(object[[1]], "Image")) {
# in memory
object <- CytoImageList(bplapply(object, function(x){
cur_out <- apply(as.array(x), c(1,2),
function(u){nnls(t(sm), u)$x})
cur_out <- aperm(cur_out, c(2,3,1))
return(Image(cur_out))
}, BPPARAM = BPPARAM))
} else {
# on disk
object <- CytoImageList(bplapply(object, function(x){
cur_out <- apply(as.array(x), c(1,2),
function(u){nnls(t(sm), u)$x})
cur_out <- aperm(cur_out, c(2,3,1))
cur_out <- .add_h5(x, cur_out, overwrite, suffix = "_comp")
return(cur_out)
}, BPPARAM = BPPARAM), on_disk = TRUE)
}
channelNames(object) <- cur_channels
mcols(object) <- cur_meta
return(object)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.