Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch transformations. #429 #618

Merged
merged 34 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
10ebc25
#601 and OMA #482
ake123 Jul 10, 2024
38b1a00
Merge branch 'microbiome:devel' into devel
ake123 Jul 10, 2024
bfeeafb
correction to indentation
ake123 Jul 10, 2024
7f7cb44
Merge remote-tracking branch 'origin' into devel
ake123 Jul 10, 2024
2316ecb
remove all the changes to the diversities
ake123 Jul 10, 2024
10be9b9
Merge branch 'microbiome:devel' into devel
ake123 Jul 12, 2024
338d7d8
index validation
ake123 Jul 12, 2024
dd5c307
Merge branch 'microbiome:devel' into devel
ake123 Jul 15, 2024
e3a417e
correction as suggested
ake123 Jul 15, 2024
2053998
Merge branch 'microbiome:devel' into devel
ake123 Jul 19, 2024
5e59cc8
Update addAlpha.R
TuomasBorman Jul 22, 2024
cbdb378
Merge branch 'devel' into devel
ake123 Jul 22, 2024
6db8dd7
Update addAlpha.R
ake123 Jul 23, 2024
3f5bcb5
Merge branch 'devel' into devel
ake123 Jul 24, 2024
c3c4973
Merge branch 'devel' into devel
antagomir Jul 30, 2024
705c55a
Merge branch 'microbiome:devel' into devel
ake123 Jul 30, 2024
cd0fe47
Batch transformations. #429
ake123 Jul 30, 2024
260d42b
correcting the unit tests for transformassay
ake123 Jul 31, 2024
32f5602
adding documentation on altexp
ake123 Jul 31, 2024
6182358
adding documentation on altexp
ake123 Jul 31, 2024
8fc7e58
Merge branch 'devel' into devel
ake123 Aug 12, 2024
6ff7265
Merge branch 'microbiome:devel' into devel
ake123 Aug 18, 2024
bfbca49
Batch transformations corrections
ake123 Aug 28, 2024
df8f7bc
Merge branch 'microbiome:devel' into devel
ake123 Sep 2, 2024
5e11004
correction to transformasssay
ake123 Sep 6, 2024
df15567
Merge remote-tracking branch 'origin' into devel
ake123 Sep 6, 2024
8a0a695
up
TuomasBorman Sep 9, 2024
5263ab4
Merge branch 'devel' into devel
TuomasBorman Sep 9, 2024
1692395
Merge branch 'devel' into devel
TuomasBorman Sep 10, 2024
3c19d3f
Merge branch 'devel' into devel
Daenarys8 Sep 19, 2024
a657d16
up
TuomasBorman Sep 21, 2024
3ac46d3
up
TuomasBorman Sep 21, 2024
181e5b9
up
TuomasBorman Sep 21, 2024
09e1a9b
fix indentation
TuomasBorman Sep 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 131 additions & 91 deletions R/transformCounts.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
#'
#' @param name \code{Character scalar}. A name for the column of the
#' \code{colData} where results will be stored. (Default: \code{"method"})
#'
#' @param altexp \code{Character vector} or \code{NULL}. Specifies the names
#' of alternative experiments to which the transformation should also be
#' applied. If \code{NULL}, the transformation is only applied to the main
#' experiment. (Default: \code{NULL}).
#'
#' @param ... additional arguments passed on to \code{vegan:decostand}:
#' \itemize{
Expand Down Expand Up @@ -109,97 +114,132 @@
#' assay(tse, "rank_average", withDimnames = FALSE) <- colRanks(
#' assay(tse, "counts"), ties.method = "average", preserveShape = TRUE)
#'
#' #using altexp parameter
#' data("GlobalPatterns", package="mia")
#' tse <- GlobalPatterns
#' altExp(tse,"species") <- transformAssay(tse, method = "relabundance",rank = "species", na.rm = FALSE)
TuomasBorman marked this conversation as resolved.
Show resolved Hide resolved
#' altExp(tse,"species")
TuomasBorman marked this conversation as resolved.
Show resolved Hide resolved
#'
NULL

#' @rdname transformAssay
#' @export
setGeneric("transformAssay", signature = c("x"),
function(x,
assay.type = "counts", assay_name = NULL,
method = c("alr", "chi.square", "clr", "frequency",
"hellinger", "log", "log10", "log2", "max",
"normalize", "pa", "range", "rank", "rclr",
"relabundance", "rrank", "standardize", "total",
"z"),
MARGIN = "samples",
name = method,
pseudocount = FALSE,
...)
standardGeneric("transformAssay"))
function(x, ...)
standardGeneric("transformAssay"))

#' @rdname transformAssay
#' @export
setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
function(x,
assay.type = "counts", assay_name = NULL,
method = c("alr", "chi.square", "clr", "frequency", "hellinger",
"log", "log10", "log2", "max", "normalize", "pa",
"range", "rank", "rclr", "relabundance", "rrank",
"standardize", "total", "z"),
MARGIN = "samples",
name = method,
pseudocount = FALSE,
...){
# Input check

if (!is.null(assay_name)) {
.Deprecated(old="assay_name", new="assay.type", "Now assay_name is deprecated. Use assay.type instead.")
assay.type <- assay_name
}
assay.type = "counts", assay_name = NULL,
method = c("alr", "chi.square", "clr", "css", "css.fast", "frequency",
"hellinger", "log", "log10", "log2", "max", "normalize",
"pa", "range", "rank", "rclr", "relabundance", "rrank",
"standardize", "total", "z"),
MARGIN = "samples",
name = method,
pseudocount = FALSE,
...){
#
x <- .transform_assay(
x = x, method = method, name = name, assay.type = assay.type,
MARGIN = MARGIN, pseudocount = pseudocount, ...)
return(x)
}
)

# Check assay.type
.check_assay_present(assay.type, x)
.transform_assay <- function(
x, assay.type = "counts", assay_name = NULL,
method = c(
"alr", "chi.square", "clr", "css", "css.fast", "frequency",
"hellinger", "log", "log10", "log2", "max", "normalize",
"pa", "range", "rank", "rclr", "relabundance", "rrank",
"standardize", "total", "z"),
MARGIN = "samples",
name = method,
pseudocount = FALSE,
...){
# Input check
if (!is.null(assay_name)) {
.Deprecated(old="assay_name", new="assay.type", "Now assay_name is
deprecated. Use assay.type instead.")
assay.type <- assay_name
}

# Check assay.type
.check_assay_present(assay.type, x)

# Check name
if(!.is_non_empty_string(name) ||
name == assay.type){
stop("'name' must be a non-empty single character value and be ",
"different from `assay.type`.",
call. = FALSE)
}
# Check method
# If method is not single string, user has not specified transform method,
# or has given e.g. a vector
if(!.is_non_empty_string(method)){
stop("'method' must be a non-empty single character value.",
call. = FALSE)
}
method <- match.arg(method, several.ok = FALSE)
# Check that MARGIN is 1 or 2
MARGIN <- .check_MARGIN(MARGIN)
# Check pseudocount
if( !.is_a_bool(pseudocount) && !(is.numeric(pseudocount) &&
length(pseudocount) == 1 && pseudocount >= 0) ){
stop("'pseudocount' must be TRUE, FALSE or a number equal to or
greater than 0.",
call. = FALSE)
}
# Input check end
#
# Get the method and abundance table
method <- match.arg(method)
assay <- assay(x, assay.type)

# Apply pseudocount, if it is not 0
assay <- .apply_pseudocount(assay, pseudocount, ...)
# Store pseudocount value and set attr equal to NULL
pseudocount <- attr(assay, "pseudocount")
attr(assay, "pseudocount") <- NULL

# Calls help function that does the transformation
# Help function is different for mia and vegan transformations
if( method %in% c("log10", "log2", "css", "css.fast") ){
transformed_table <- .apply_transformation(
assay, method, MARGIN, ...)
} else {
transformed_table <- .apply_transformation_from_vegan(
assay, method, MARGIN, ...)
}

# Add pseudocount info to transformed table
attr(transformed_table, "parameters")$pseudocount <- pseudocount

# Assign transformed table to assays
assay(x, name, withDimnames=FALSE) <- transformed_table
x
}

# Check name
if(!.is_non_empty_string(name) ||
name == assay.type){
stop("'name' must be a non-empty single character value and be ",
"different from `assay.type`.",
call. = FALSE)
}
# Check method
# If method is not single string, user has not specified transform method,
# or has given e.g. a vector
if(!.is_non_empty_string(method)){
stop("'method' must be a non-empty single character value.",
call. = FALSE)
}
method <- match.arg(method, several.ok = FALSE)
# Check that MARGIN is 1 or 2
MARGIN <- .check_MARGIN(MARGIN)
# Check pseudocount
if( !.is_a_bool(pseudocount) && !(is.numeric(pseudocount) && length(pseudocount) == 1 && pseudocount >= 0) ){
stop("'pseudocount' must be TRUE, FALSE or a number equal to or greater than 0.",
call. = FALSE)
#' @rdname transformAssay
#' @export
setMethod("transformAssay", signature = c(x = "SingleCellExperiment"),
function(x, altexp = altExpNames(x), ...){
# Check altexp
if( !(is.null(altexp) || (!is.null(altexp) && all(altexp %in% altExpNames(x)))) ){
stop("Some provided altexp names are not valid.", call. = FALSE)
}
# Input check end

# Get the method and abundance table
method <- match.arg(method)
assay <- assay(x, assay.type)

# Apply pseudocount, if it is not 0
assay <- .apply_pseudocount(assay, pseudocount, ...)
# Store pseudocount value and set attr equal to NULL
pseudocount <- attr(assay, "pseudocount")
attr(assay, "pseudocount") <- NULL

# Calls help function that does the transformation
# Help function is different for mia and vegan transformations
if( method %in% c("log10", "log2") ){
transformed_table <- .apply_transformation(
assay, method, MARGIN, ...)
} else{
transformed_table <- .apply_transformation_from_vegan(
assay, method, MARGIN, ...)
# Transform the main object
x <- .transform_assay(x, ...)
if (!is.null(altexp)) {
altExps(x)[altexp] <- lapply(altExps(x)[altexp], function(y){
.transform_assay(y, ...)
})
}

# Add pseudocount info to transformed table
attr(transformed_table, "parameters")$pseudocount <- pseudocount

# Assign transformed table to assays
assay(x, name, withDimnames=FALSE) <- transformed_table
x
return(x)
}
)

Expand All @@ -218,7 +258,7 @@ setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
# Function is selected based on the "method" variable
FUN <- switch(method,
log10 = .calc_log,
log2 = .calc_log,
log2 = .calc_log,
)

# Get transformed table
Expand All @@ -241,16 +281,15 @@ setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
# table as input and returns transformed table. This function utilizes vegan's
# transformation functions.
.apply_transformation_from_vegan <- function(mat, method, MARGIN, reference = ref_vals,
ref_vals = NA, ...){
# Input check
# Check reference
if( length(reference) != 1 ){
stop("'reference' must be a single value specifying the ",
"values of the reference sample.",
call. = FALSE)
ref_vals = NA, ...) {
# Ensure that the matrix has proper dimnames
if (is.null(rownames(mat))) {
rownames(mat) <- paste0("feature", seq_len(nrow(mat)))
}
# Input check end

TuomasBorman marked this conversation as resolved.
Show resolved Hide resolved
if (is.null(colnames(mat))) {
colnames(mat) <- paste0("sample", seq_len(ncol(mat)))
}

# Adjust method if mia-specific alias was used
method <- ifelse(method == "relabundance", "total", method)

Expand All @@ -268,16 +307,16 @@ setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
transformed_table <- vegan::decostand(mat, method = method, MARGIN = MARGIN, ...)

# Add reference sample back if ALR
if( method %in% c("alr") ){
if (method %in% c("alr")) {
transformed_table <- .adjust_alr_table(
mat = transformed_table, orig_dimnames = orig_dimnames,
reference = reference)
}
# If table is transposed (like in chi.square), transpose back
if(identical(rownames(transformed_table), colnames(mat)) &&
if (identical(rownames(transformed_table), colnames(mat)) &&
identical(colnames(transformed_table), rownames(mat)) &&
ncol(transformed_table) != ncol(mat) &&
nrow(transformed_table != nrow(mat))){
nrow(transformed_table != nrow(mat))) {
transformed_table <- t(transformed_table)
}
return(transformed_table)
Expand Down Expand Up @@ -358,6 +397,7 @@ setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
return(mat)
}


###############################.apply_pseudocount###############################
# This function applies pseudocount to abundance table.
.apply_pseudocount <- function(mat, pseudocount, na.rm = TRUE, ...){
Expand All @@ -372,7 +412,7 @@ setMethod("transformAssay", signature = c(x = "SummarizedExperiment"),
stop("The assay contains negative values. ",
"'pseudocount' must be specified manually.", call. = FALSE)
}
# If pseudocount TRUE, set it to half of non-zero minimum value
# If pseudocount TRUE, set it to half of non-zero minimum value
# else set it to zero.
# Get min value
value <- min(mat[mat > 0], na.rm = na.rm)
Expand Down
47 changes: 25 additions & 22 deletions man/transformAssay.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading