File: logNormCounts.R

package info (click to toggle)
r-bioc-scuttle 1.0.4%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 728 kB
  • sloc: cpp: 356; sh: 17; makefile: 2
file content (151 lines) | stat: -rw-r--r-- 7,439 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#' Compute log-normalized expression values
#'
#' Compute log-transformed normalized expression values from a count matrix in a \linkS4class{SingleCellExperiment} object.
#'
#' @param x A \linkS4class{SingleCellExperiment} or \linkS4class{SummarizedExperiment} object containing a count matrix.
#' @inheritParams normalizeCounts
#' @param use.altexps Logical scalar indicating whether normalization should be performed for alternative experiments in \code{x}.
#' 
#' Alternatively, a character vector specifying the names of the alternative experiments to be normalized.
#' 
#' Alternatively \code{NULL}, in which case no calculations are performed on the alternative experiments. 
#' @param ... For the generic, additional arguments passed to specific methods. 
#'
#' For the methods, additional arguments passed to \code{\link{normalizeCounts}}.
#' @param name String containing an assay name for storing the output normalized values.
#' Defaults to \code{"logcounts"} when \code{log=TRUE} and \code{"normcounts"} otherwise.
#' @param BPPARAM A \linkS4class{BiocParallelParam} object specifying how library size factor calculations should be parallelized.
#' Only used if \code{size.factors} is not specified.
#' @param use_altexps Soft-deprecated equivalent to the argument above.
#'
#' @details
#' This function is a convenience wrapper around \code{\link{normalizeCounts}}.
#' It returns a \linkS4class{SingleCellExperiment} or \linkS4class{SummarizedExperiment} containing the normalized values in a separate assay.
#' This makes it easier to perform normalization by avoiding book-keeping errors during a long analysis workflow.
#' 
#' If \code{x} is a \linkS4class{SingleCellExperiment} that contains alternative Experiments, normalized values can be computed and stored within each alternative experiment by setting \code{use.altexps} appropriately.
#' By default, \code{use.altexps=FALSE} to avoid problems from attempting to library size-normalize alternative experiments that have zero total counts for some cells.
#'
#' If \code{size.factors=NULL}, size factors are obtained following the rules in \code{\link{normalizeCounts}}.
#' This is done independently for the main and alternative Experiments when \code{use.altexps} is specified,
#' i.e. no information is shared between Experiments by default.
#' However, if \code{size.factors} is supplied, it will override any size factors available in any Experiment.
#'
#' @return 
#' \code{x} is returned containing the (log-)normalized expression values in an additional assay named as \code{name}.
#' 
#' If \code{x} is a \linkS4class{SingleCellExperiment}, the size factors used for normalization are stored in \code{\link{sizeFactors}}.
#' These are centered if \code{center.size.factors=TRUE}.
#'
#' If \code{x} contains alternative experiments and \code{use.altexps=TRUE},  each of the alternative experiments in \code{x} will also contain an additional assay.
#' This can be limited to particular \code{\link{altExps}} entries by specifying them in \code{use.altexps}.
#'
#' @author Aaron Lun, based on code by Davis McCarthy 
#' @seealso
#' \code{\link{normalizeCounts}}, which is used to compute the normalized expression values.
#'
#' @examples
#' example_sce <- mockSCE()
#'
#' # Standard library size normalization:
#' example_sce2 <- logNormCounts(example_sce)
#' assayNames(example_sce2)
#' logcounts(example_sce2)[1:5,1:5]
#'
#' # Without logging, the assay is 'normcounts':
#' example_sce2 <- logNormCounts(example_sce, log=FALSE)
#' assayNames(example_sce2)
#' normcounts(example_sce2)[1:5,1:5]
#'
#' # Pre-loading with size factors:
#' example_sce2 <- computeMedianFactors(example_sce)
#' example_sce2 <- logNormCounts(example_sce2)
#' logcounts(example_sce2)[1:5,1:5]
#'
#' # Also normalizing the alternative experiments:
#' example_sce2 <- logNormCounts(example_sce, use.altexps="Spikes")
#' logcounts(altExp(example_sce2))[1:5,1:5]
#'
#' @name logNormCounts
NULL

#' @export
#' @rdname logNormCounts
setGeneric("logNormCounts", function(x, ...) standardGeneric("logNormCounts"))

#' @export
#' @rdname logNormCounts
#' @importClassesFrom SummarizedExperiment SummarizedExperiment
setMethod("logNormCounts", "SummarizedExperiment", function(x, size.factors=NULL, log=TRUE, 
    pseudo.count=1, center.size.factors=TRUE, ..., assay.type="counts", name=NULL, BPPARAM=SerialParam(), 
    size_factors=NULL, pseudo_count=NULL, center_size_factors=NULL, exprs_values=NULL)
{
    size.factors <- .replace(size.factors, size_factors)
    pseudo.count <- .replace(pseudo.count, pseudo_count)
    center.size.factors <- .replace(center.size.factors, center_size_factors)
    assay.type <- .replace(assay.type, exprs_values)
    
    FUN <- .se_lnc(assay.type=assay.type, log=log, pseudo.count=pseudo.count, ..., name=name, BPPARAM=BPPARAM) 
    FUN(x, size.factors=size.factors, center.size.factors=center.size.factors)
})

#' @importFrom SummarizedExperiment assay<-
.se_lnc <- function(assay.type, log, pseudo.count, ..., name) {
    args <- list(..., assay.type=assay.type, log=log, pseudo.count=pseudo.count)
    if (is.null(name)) {
        name <- if (log) "logcounts" else "normcounts"
    }
    function(x, ...) {
        out <- do.call(normalizeCounts, c(list(x, ...), args))
        assay(x, name) <- out
        x
    }
}

#' @export
#' @rdname logNormCounts
#' @importFrom BiocGenerics sizeFactors sizeFactors<-
#' @importFrom SingleCellExperiment altExp altExp<- int_metadata int_metadata<-
#' @importClassesFrom SingleCellExperiment SingleCellExperiment
setMethod("logNormCounts", "SingleCellExperiment", function(x, size.factors=NULL, log=TRUE, pseudo.count=1, 
    center.size.factors=TRUE, ..., assay.type="counts", use.altexps=FALSE, name=NULL, BPPARAM=SerialParam(), 
    size_factors=NULL, pseudo_count=NULL, center_size_factors=NULL, exprs_values=NULL, use_altexps=NULL) 
{
    size.factors <- .replace(size.factors, size_factors)
    pseudo.count <- .replace(pseudo.count, pseudo_count)
    center.size.factors <- .replace(center.size.factors, center_size_factors)
    use.altexps <- .replace(use.altexps, use_altexps)
    assay.type <- .replace(assay.type, exprs_values)

    # Guarantee that we get (centered) size factors back out.
    original <- size.factors
    if (is.null(size.factors)) {
        size.factors <- sizeFactors(x)
        if (is.null(size.factors)) {
            size.factors <- librarySizeFactors(x, assay.type=assay.type, BPPARAM=BPPARAM)
        }
    }
    size.factors <- .center.size.factors(size.factors, center.size.factors)
    sizeFactors(x) <- size.factors

    # Set center.size.factors=FALSE, as we've already centered above.
    FUN <- .se_lnc(assay.type=assay.type, log=log, pseudo.count=pseudo.count, ..., name=name) 
    x <- FUN(x, size.factors=size.factors, center.size.factors=FALSE)
    if (log) {
        if (is.null(int_metadata(x)$scater)) {
            int_metadata(x)$scater <- list()
        }
        int_metadata(x)$scater$pseudo.count <- pseudo.count
    }

    use.altexps <- .use_names_to_integer_indices(use.altexps, x=x, nameFUN=altExpNames, msg="use.altexps")
    for (i in use.altexps) {
        tryCatch({
            altExp(x, i) <- FUN(altExp(x, i), size.factors=original, center.size.factors=center.size.factors)
        }, error=function(err) {
            stop(paste0(sprintf("failed to normalize 'altExp(x, %s)'\n", deparse(i)), conditionMessage(err)))
        })
    }

    x
})