R/tally.R

Defines functions tally

Documented in tally

#' Tally Positive Fluorescent Values
#'
#' Tally positive and negative values from from the data.frame generated
#' by \code{\link{parseImages}} by a grouping variable such as \code{"well"}
#' or \code{"file"} that corresponds to a single multiplicity.
#'
#' @param df Annotated \code{data.frame} with fluorescent values to evaluate.
#' @param pd Optional phenotype \code{data.frame} to add to results.
#' @param moi Character string identifying the independent value. If \code{NULL},
#'   variables named \code{"moi"} and \code{"x"} will be sought. Note
#'   that in the returned value, this variable will be named \code{"x"}.
#' @param by Character string identifying the grouping variable. If \code{NULL},
#'   either \code{"well"} or \code{"file"} must be present and will be used as
#'   the grouping variable. 
#' @param param Character string identifying the variable in \code{df} to evaluate, 
#'   typically \code{"mfi"}.
#'
#' @details
#'
#' The variable named \code{positive} will be tallied for each value of
#' \code{moi} (if present) represented by each level of the grouping
#' variable \code{by}. 
#'
#' @return
#'
#' A \code{data.frame} of tallied values for each level of the grouping
#' variable (typically \code{well} or \code{file}) with additional information
#' provided by the optional phenotype data. Variables generated by \code{\link{tally}} are
#' expected by downstream functions. Notably, the dependent variable will
#' be renamed \code{x} in the output. These variables include:
#' \itemize{
#' 	\item The independent variable representing the multiplicity of infection
#'     in \code{x}
#'   \item The dependent variable as the fraction of positive cells in \code{y}
#'   \item The number of positive cells in \code{pos}
#'   \item The number of negative in \code{neg}
#'   \item Details about the grouping variable, typically \code{well} or \code{file}
#' }
#'
#' @examples
#' # Sample data by folder
#'   f <- system.file("extdata", "by_folder", package = "virustiter")
#'   pd <- read.csv(system.file("extdata", "by_folder/phenoData.csv", package = "virustiter"))
#'   i <- getImages(f)
#'   v <- parseImages(i)
#'   v <- mergePdata(pd, v)
#'   v <- score(v)
#'   tally(v)
#'
#' @import
#' EBImage
#'
#' @export
#'  
tally <- function(df, pd = NULL, moi = NULL, by = NULL, param = "mfi")
{
# parameter check
	if(!"positive" %in% names(df))
		stop("\ntally() requires the logical variable 'positive'.",
			"\nPerhaps score() needs to be called on '", deparse(substitute(df)))

# if the moi is NULL, first seek "moi" and then "x" in df
	if (is.null(moi)) {
		moi <- FALSE
		if ("moi" %in% names(df))
			moi <- "moi"
		else if ("x" %in% names(df))
			moi <- "x"
		else
			message("No variable has been assigned to 'moi'")
	}
	else if (!moi %in% names(df))
		stop("'", moi, "' is missing from ", deparse(substitute(df)))

# assign grouping value
	if (!is.null(by) && !by %in% names(df))
		stop("'", by, "' is missing from ", deparse(substitute(df)))
	else if ("well" %in% names(df))
		by <- "well"
	else if ("file" %in% names(df))
		by <- "file"
	else
		stop("Unable to use '", deparse(substitute(by)), "' as grouping variable")
	group <- df[[by]]

# check for param
	if (!param %in% names(df))
		stop("'", param, "' is missing from ", deparse(substitute(df)))

# record unit of measure
	unit <- df$unit[1]
	if (is.null(unit))
		unit <- "[no unit]"

# tally positive and create results data.frame
	res <- aggregate(cbind(positive == TRUE, positive == FALSE) ~ group, df, sum)
	names(res)[2:3] <- c("pos", "neg")
	y <- with(res, pos/(pos + neg))
	if (moi == FALSE)
		x <- 1
	else
		x <- sapply(levels(res$group), function(v) df[[moi]][group == v][1])
	if (by == "well") {
		well <- levels(as.factor(res$group))
		row <- well.info(well)$row
		column <- well.info(well)$column
		res <- cbind(well, row, column, unit, res[c("pos", "neg")], x, y)
	}
	else if (by == "file") {
		file <- levels(as.factor(res$group))
		res <- cbind(file, unit, res[c("pos", "neg")], x, y)
	}
	else {
		group <- levels(as.factor(res$group))
		res <- cbind(group, unit, res[c("pos", "neg")], x, y)
	}
	if (!is.null(pd)) {
		n1 <- max(nchar(levels(as.factor(pd$well))))
		n2 <- max(nchar(levels(as.factor(df$well))))
		nmax <- max(n1, n2)
		if (nmax <= 2)
			formatString <- NULL
		else 
			formatString <- sprintf("%%0%dd", nmax - 1)
		res <- mergePdata(pd, res, formatString = formatString)
	}
	rownames(res) <- NULL
	return(res)
}
ornelles/virustiter documentation built on March 15, 2024, 9:28 a.m.