#' Read FCS-files or flowFrames
#'
#' Take some input and return FlowSOM object containing a matrix with
#' the preprocessed data (compensated, transformed, scaled)
#'
#' @param input a flowFrame, a flowSet, a matrix with column names or
#' an array of paths to files or directories
#' @param pattern if input is an array of file- or directorynames,
#' select only files containing pattern
#' @param compensate logical, does the data need to be compensated
#' @param spillover spillover matrix to compensate with
#' If \code{NULL} and compensate = \code{TRUE}, we will
#' look for \code{$SPILL} description in FCS file.
#' @param transform logical, does the data need to be transformed
#' @param toTransform column names or indices that need to be transformed.
#' Will be ignored if \code{transformList} is given.
#' If \code{NULL} and transform = \code{TRUE}, column names
#' of \code{$SPILL} description in FCS file will be used.
#' @param transformFunction Defaults to logicleTransform()
#' @param transformList transformList to apply on the samples.
#' @param scale logical, does the data needs to be rescaled
#' @param scaled.center see \code{\link{scale}}
#' @param scaled.scale see \code{\link{scale}}
#' @param silent if \code{TRUE}, no progress updates will be printed.
#' Default = \code{FALSE}
#'
#' @return FlowSOM object containing the data, which can be used as input
#' for the BuildSOM function
#'
#' @seealso \code{\link{scale}}, \code{\link{BuildSOM}}
#'
#' @examples
#' # Read from file
#' fileName <- system.file("extdata", "68983.fcs", package = "FlowSOM")
#' flowSOM.res <- ReadInput(fileName, compensate = TRUE, transform = TRUE,
#' scale = TRUE)
#'
#' # Or read from flowFrame object
#' ff <- flowCore::read.FCS(fileName)
#' ff <- flowCore::compensate(ff, flowCore::keyword(ff)[["SPILL"]])
#' ff <- flowCore::transform(ff,
#' flowCore::transformList(colnames(flowCore::keyword(ff)[["SPILL"]]),
#' flowCore::logicleTransform()))
#' flowSOM.res <- ReadInput(ff, scale = TRUE)
#'
#' # Build the self-organizing map and the minimal spanning tree
#' flowSOM.res <- BuildSOM(flowSOM.res, colsToUse = c(9, 12, 14:18))
#' flowSOM.res <- BuildMST(flowSOM.res)
#'
#' # Apply metaclustering
#' metacl <- MetaClustering(flowSOM.res$map$codes,
#' "metaClustering_consensus", max = 10)
#'
#' # Get metaclustering per cell
#' flowSOM.clustering <- metacl[flowSOM.res$map$mapping[, 1]]
#'
#' @export
ReadInput <- function(input, pattern = ".fcs",
compensate = FALSE,
spillover = NULL,
transform = FALSE,
toTransform = NULL,
transformFunction = flowCore::logicleTransform(),
transformList = NULL,
scale = FALSE,
scaled.center = TRUE,
scaled.scale = TRUE,
silent = FALSE){
fsom <- list(pattern = pattern,
compensate = compensate,
spillover = spillover,
transform = transform,
toTransform = toTransform,
transformFunction = transformFunction,
transformList = transformList,
scale = scale)
class(fsom) <- "FlowSOM"
if(is(input, "flowFrame")){
fsom <- AddFlowFrame(fsom, input)
} else if(is(input, "flowSet")){
for(i in seq_along(input)){
fsom <- AddFlowFrame(fsom, input[[i]])
}
} else if(is(input, "matrix")){
flowFrame <- flowCore::flowFrame(input)
fsom <- AddFlowFrame(fsom, flowFrame)
} else if(is(input, "character")){
# Replace all directories by the files they contain
toAdd <- NULL
toRemove <- NULL
for(i in seq_along(input)){
if(file.info(input[i])$isdir){
toAdd <- c(toAdd, list.files(input[i], pattern = pattern,
full.names = TRUE))
toRemove <- c(toRemove, i)
}
}
if(!is.null(toRemove)){
input <- c(input[-toRemove], toAdd)
}
# Select all files corresponding to the pattern
input <- grep(pattern, input, value = TRUE)
# Read all files
if(length(input) > 0){
for(i in seq_along(input)){
if(file.exists(input[i])){
if(!silent) message("Reading file ", input[i], "\n")
if (tools::file_ext(input[i]) == "csv") {
flowFrame <- flowFrame(utils::read.table(input[i]))
} else { #else if(tools::file_ext(input[i]) == "fcs"){
flowFrame <- suppressWarnings(
flowCore::read.FCS(input[i]))
}
fsom <- AddFlowFrame(fsom, flowFrame)
}
}
} else {
stop("No files containing the pattern are found.")
}
} else {
stop(paste("Inputs of type", class(input), "are not supported.
Please supply either a FlowFrame, a FlowSet or an array
of valid paths to files or directories."))
}
if(scale){
if(!silent) message("Scaling the data\n")
if(!all(is.null(names(scaled.center)))){
cols_to_scale <- intersect(colnames(fsom$data), names(scaled.center))
sc <- scale(x = fsom$data[, cols_to_scale],
center = scaled.center[cols_to_scale],
scale = scaled.scale[cols_to_scale])
fsom$data[, cols_to_scale] <- sc
fsom$scaled.center <- attr(sc, "scaled:center")
fsom$scaled.scale <- attr(sc, "scaled:scale")
} else {
fsom$data <- scale(x = fsom$data, center = TRUE, scale = TRUE)
fsom$scaled.center <- attr(fsom$data, "scaled:center")
attr(fsom$data, "scaled:center") <- NULL
fsom$scaled.scale <- attr(fsom$data, "scaled:scale")
attr(fsom$data, "scaled:scale") <- NULL
}
}
return(fsom)
}
#' Add a flowFrame to the data variable of the FlowSOM object
#'
#' @param fsom FlowSOM object, as constructed by the ReadInput function
#' @param flowFrame flowFrame to add to the FlowSOM object
#'
#' @return FlowSOM object with data added
#'
#' @seealso \code{\link{ReadInput}}
AddFlowFrame <- function(fsom, flowFrame){
# Compensation
if(fsom$compensate){
if(is.null(fsom$spillover)){
if(!is.null(flowFrame@description$SPILL)){
spillover <- flowFrame@description$SPILL
} else if (!is.null(flowFrame@description$`$SPILLOVER`)){
if(is(flowFrame@description$`$SPILLOVER`, "matrix")){
spillover <- flowFrame@description$`$SPILLOVER`
flowFrame@description$SPILL <- spillover
} else {
spilloverStr <- strsplit(
flowFrame@description$`$SPILLOVER`,
", ")[[1]]
n <- as.numeric(spilloverStr[1])
spillover <- t(
matrix(as.numeric(spilloverStr[(n+2):length(spilloverStr)]),
ncol = n))
colnames(spillover) <- spilloverStr[2:(n+1)]
flowFrame@description$SPILL <- spillover
}
} else {
stop("No compensation matrix found")
}
} else {
spillover <- fsom$spillover
}
flowFrame <- flowCore::compensate(flowFrame, spillover)
}
# Transform
if(fsom$transform){
if(!is.null(fsom$transformList)){
flowFrame <- flowCore::transform(flowFrame,
fsom$transformList)
} else {
if(is.null(fsom$toTransform)){
fsom$toTransform <- colnames(flowFrame@description$SPILL)
} else{
fsom$toTransform <-
colnames(flowCore::exprs(flowFrame)[, fsom$toTransform])
}
flowFrame <-
flowCore::transform(flowFrame,
flowCore::transformList(fsom$toTransform,
fsom$transformFunction))
}
}
# Save pretty names for nicer visualisation later on
if(is.null(fsom$prettyColnames)){
n <- flowCore::parameters(flowFrame)@data[, "name"]
d <- flowCore::parameters(flowFrame)@data[, "desc"]
d[is.na(d)] <- n[is.na(d)]
if(any(grepl("#", d))){
# Support for hashtag notation:
# antibody#fluorochrome -> antibody (fluorochrome)
fsom$prettyColnames <- gsub("#(.*)$", " <\\1>", d)
} else {
fsom$prettyColnames <- paste(d, " <", n, ">", sep = "")
}
names(fsom$prettyColnames) <- colnames(flowCore::exprs(flowFrame))
}
# Add the data to the matrix
f <- flowCore::exprs(flowFrame)
attr(f, "ranges") <- NULL
name <- flowCore::keyword(flowFrame,"FIL")[[1]]
if(is.null(name)) name <- flowFrame@description$`$FIL`
if(is.null(name)) name <- length(fsom$metaData)+1
if(is.null(fsom$data)){
fsom$data <- f
fsom$metaData <- list()
fsom$metaData[[name]] <- c(1, nrow(fsom$data))
} else {
fsom$data <- rbind(fsom$data, f)
fsom$metaData[[name]] <- c(nrow(fsom$data) - nrow(f) + 1,
nrow(fsom$data))
}
return(fsom)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.