#####Function to calculate the reducedDim matrices.
#' @rdname reduceFunctions
#' @param reducedDims a vector of character values indicating the methods of
#' dimensionality reduction to be performed. Currently only "PCA" is
#' implemented.
#' @param maxDims Numeric vector of integer giving the number of PC dimensions
#' to calculate. \code{maxDims} can also take values between (0,1) to indicate
#' keeping the number of dimensions necessary to account for that proportion
#' of the variance. \code{maxDims} should be of same length as
#' \code{reducedDims}, indicating the number of dimensions to keep for each
#' method (if \code{maxDims} is of length 1, the same number of dimensions
#' will be used for each).
#' @param ... Values passed on the the 'SingleCellExperiment' method.
#' @details The PCA method uses either \code{prcomp} from the \code{stats}
#' package or \code{svds} from the \code{RSpectra} package to perform PCA.
#' Both are called on \code{t(assay(x))} with \code{center=TRUE} and
#' \code{scale=TRUE} (i.e. the feature are centered and scaled), so that it is
#' performing PCA on the correlation matrix of the features.
#' @details Note that this function does not check if such a reduceDim value already exists, and will recalculate (and overwrite) if it does.
#' @return \code{makeReducedDims} returns a \code{\link{SingleCellExperiment}}
#' containing the calculated dimensionality reduction in the \code{reduceDims}
#' with names corresponding to the name given in \code{reducedDims}.
#' @examples
#' data(simData)
#' listBuiltInReducedDims()
#' scf<-makeReducedDims(simData, reducedDims="PCA", maxDims=3)
#' scf
#' @export
#' @aliases makeReducedDims,SingleCellExperiment-method makeReducedDims
#' @importFrom matrixStats rowVars
setMethod(
f = "makeReducedDims",
signature = "SingleCellExperiment",
definition = function(object,reducedDims="PCA",maxDims=500,transFun=NULL,isCount=FALSE,whichAssay=1)
{
###################
##Check user inputs
###################
#check valid options for reducedDims
validDim<-listBuiltInReducedDims()
reducedDims<-unique(reducedDims)
if(length(maxDims)==1) maxDims<-rep(maxDims,length=length(reducedDims))
if(length(maxDims)!=length(reducedDims)) stop("'maxDims' must be of same length as 'reducedDims'")
######Check dimensions and valid argument
for(dr in reducedDims){
dr<-match.arg(dr,validDim)
if(is.na(maxDims) || maxDims>NROW(object) || maxDims > NCOL(object)){
if(!is.na(maxDims) & (maxDims>NROW(object) || maxDims > NCOL(object)))
warning("User requested more dimensionality reduction dimensions than the minimimum of number of rows and columns. Will return all dimensions.")
maxDims<-min(c(NROW(object),NCOL(object)))
}
if(maxDims<=0) stop("the number of reducedDims dimensions must be a value strictly greater than 0")
}
###################
##Clean up data:
###################
#transform data
x<-transformData(object,transFun=transFun,isCount=isCount,whichAssay=whichAssay)
#---------
#Check zero variance genes before doing reducedDims:
#---------
varFun<-.matchToStats(x)[["var"]] #does matrixStats::rowVars if x is matrix, otherwise apply with var across rows.
rowvars <- varFun(x)
if(any(rowvars==0)) {
if(all(rowvars==0)) {
stop("All features have zero variance.")
}
warning("Found features with zero variance.\nMost likely these are features with 0 across all samples.\nThey will be removed from dimensionality reduction step.")
}
###################
##Do loop over reducedDims values:
###################
currErrors<-vector("character")
for(kk in seq_along(reducedDims)){
dr<-reducedDims[[kk]]
md<-maxDims[[kk]]
isPct <- md < 1
#check if already calculated
#note, currently no way to check if have already done if md<1
if(dr %in% reducedDimNames(object)){
if(!isPct & md<=ncol(reducedDim(object,type=dr))) next
}
#-------------
# if add other functions, add if statements here
if(dr=="PCA") out<-try(.pcaDimRed(x,md=md,isPct=isPct,rowvars=rowvars))
##-------
if(!inherits(out,"try-error")) reducedDim(object,reducedDims) <- out
else{
currErrors<-c(currErrors,paste("\t",dr,":",out,sep=""))
}
}
if(length(currErrors)>0){
if(length(currErrors)==length(reducedDims))
stop(paste("No dimensionality reduction techniques were successful:",currErrors,sep="\n"))
else{
warning(paste("The following dimensionality reduction techniques hit errors:",currErrors,sep="\n"))
}
}
return(object)
}
)
#' @rdname reduceFunctions
#' @export
setMethod(
f = "makeReducedDims",
signature = "matrixOrHDF5",
definition = function(object,...)
{
makeReducedDims(SummarizedExperiment(object),...)
}
)
#' @rdname reduceFunctions
#' @export
setMethod(
f = "makeReducedDims",
signature = "SummarizedExperiment",
definition = function(object,...)
{
makeReducedDims(as(object,"SingleCellExperiment"),...)
}
)
#' @rdname reduceFunctions
#' @export
setMethod(
f = "makeReducedDims",
signature = "ClusterExperiment",
definition = function(object,...)
{
if(any(c("transFun","isCount") %in% names(list(...))))
stop("The internally saved transformation function of a ClusterExperiment object must be used when given as input and setting 'transFun' or 'isCount' for a 'ClusterExperiment' is not allowed.")
out<-makeReducedDims(as(object,"SingleCellExperiment"),transFun=transformation(object),...)
return(.addBackSEInfo(newObj=object,oldObj=out))
}
)
#' @rdname reduceFunctions
#' @export
listBuiltInReducedDims<-function(){c("PCA")}
#' @importFrom BiocSingular runPCA
.pcaDimRed<-function(x,md,isPct,rowvars){
tempX <- t(x[which(rowvars>0),])
if(isPct) {
prcObj<-BiocSingular::runPCA(tempX,rank=min(dim(tempX)),center=TRUE,scale=TRUE)
prvar<-prcObj$sdev^2 #variance of each component
prvar<-prvar/sum(prvar)
prc<-prcObj$x
if(NROW(prc) != NCOL(x)) stop("Internal error in coding of principal components.")
md <- which(cumsum(prvar)>md)[1] #pick first pca coordinate with variance > value
prc <- prc[,seq_len(md)]
}
else {
prcObj <- BiocSingular::runPCA(tempX, rank=md, center=TRUE, scale=TRUE)
prc<-prcObj$x
if(any(md > NROW(prc)))
stop("Internal error in coding of principal components.")
}
return(prc)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.