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

PositiveTFHeatmap #2033

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 12 additions & 8 deletions .github/workflows/auto-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ jobs:
GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
issuesOpened: |
Hi @{{ author }}! Thanks for using ArchR! Please make sure that your post belongs in the Issues section. Only bugs and error reports belong in the Issues section. Usage questions and feature requests should be posted in the [Discussions](https://github.com/GreenleafLab/ArchR/discussions) section, not in Issues.<br />
__Before we help you, you must respond to the following questions__ unless your original post already contained this information:
It is worth noting that there are very few actual bugs in ArchR. If you are getting an error, it is probably something specific to your dataset, usage, or computational environment, all of which are extremely challenging to troubleshoot. As such, we require [reproducible examples](https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html) (preferably using the tutorial dataset) from users who want assistance. If you cannot reproduce your error, we will not be able to help.
Before going through the work of making a reproducible example, search the previous [Issues](https://github.com/GreenleafLab/ArchR/issues), [Discussions](https://github.com/GreenleafLab/ArchR/discussions), [function definitions](https://www.archrproject.com/reference/index.html), or the [ArchR manual](https://www.archrproject.com/bookdown/index.html) and you will likely find the answers you are looking for.
If your post does not contain a reproducible example, it is unlikely to receive a response.<br />
__In addition to a reproducible example, you must do the following things before we help you, unless your original post already contained this information:
__1.__ If you've encountered an error, have you already searched previous Issues to make sure that this hasn't already been solved?
__2.__ Can you recapitulate your error using the tutorial code and dataset? If so, provide a reproducible example.
__3.__ Did you post your log file? If not, add it now.
__4.__ Remove any screenshots that contain text and instead copy and paste the text using markdown's codeblock syntax (three consecutive backticks). You can do this by editing your original post.
__2.__ Did you post your log file? If not, add it now.
__3.__ Remove any screenshots that contain text and instead copy and paste the text using markdown's codeblock syntax (three consecutive backticks). You can do this by editing your original post.

# issuesOpened: |
# Hi @{{ author }}! Thanks for using ArchR! I am currently on paternity leave and will not be responding to any issues or discussion threads. I plan to be back in late January and will do my best to address your issue then.<br />
# In the meantime, it is worth noting that there are very few actual bugs in ArchR. If you are getting an error, it is probably something specific to your dataset, usage, or computational environment. Search the previous [Issues](https://github.com/GreenleafLab/ArchR/issues), [Discussions](https://github.com/GreenleafLab/ArchR/discussions), [function definitions](https://www.archrproject.com/reference/index.html), or the [ArchR manual](https://www.archrproject.com/bookdown/index.html) and you will likely find the answers you are looking for.<br />
# If you are able to solve your issue, please post the solution and close this issue post. <br />
# Otherwise __if you would like my help when I return, you must respond to the following questions__ unless your original post already contained this information:
# Hi @{{ author }}! Thanks for using ArchR! I am currently on vacation and will not be responding to any issues or discussion threads until 5/5.<br />
# Please make sure that your post belongs in the Issues section. Only bugs and error reports belong in the Issues section. Usage questions and feature requests should be posted in the [Discussions](https://github.com/GreenleafLab/ArchR/discussions) section, not in Issues.<br />
# It is worth noting that there are very few actual bugs in ArchR. If you are getting an error, it is probably something specific to your dataset, usage, or computational environment, all of which are extremely challenging to troubleshoot. As such, we require [reproducible examples](https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html) (preferably using the tutorial dataset) from users who want assistance. If you cannot reproduce your error, how will we be able to help?
# Before going through the work of making a reproducible example, search the previous [Issues](https://github.com/GreenleafLab/ArchR/issues), [Discussions](https://github.com/GreenleafLab/ArchR/discussions), [function definitions](https://www.archrproject.com/reference/index.html), or the [ArchR manual](https://www.archrproject.com/bookdown/index.html) and you will likely find the answers you are looking for.
# If your post does not contain a reproducible example, it is unlikely to receive a response.<br />
# __1.__ If you've encountered an error, have you already searched previous Issues to make sure that this hasn't already been solved?
# __2.__ Can you recapitulate your error using the tutorial code and dataset? If so, provide a reproducible example.
# __3.__ Did you post your log file? If not, add it now.
# __4.__ Remove any screenshots that contain text and instead copy and paste the text using markdown's codeblock syntax (three consecutive backticks). You can do this by editing your original post.
212 changes: 212 additions & 0 deletions R/PositiveTFHeatmap.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#' Plot a Heatmap of Features across a Trajectory
#'
#' This function will plot a heatmap of the results from getTrajectory
#'
#' @param sePositiveTF A `SummarizedExperiment` object that results from calling `getTrajectory()`.
#' @param varCutOff The "Variance Quantile Cutoff" to be used for identifying the top variable features across the given trajectory.
#' Only features with a variance above the provided quantile will be retained.
#' @param maxFeatures The maximum number of features, ordered by variance, to consider from `useMatrix` when generating a trajectory.
#' This prevents smoothing a large number number of features which can be very time consuming.
#' @param scaleRows A boolean value that indicates whether row-wise z-scores should be computed on the matrix provided by `sePositiveTF`.
#' @param limits A numeric vector of two numbers that represent the lower and upper limits of the heatmap color scheme.
#' @param grepExclude A character vector or string that indicates the `rownames` or a specific pattern that identifies
#' rownames from `sePositiveTF` to be excluded from the heatmap.
#' @param pal A custom continuous palette (see `paletteContinuous()`) used to override the default continuous palette for the heatmap.
#' @param labelMarkers A character vector listing the `rownames` of `sePositiveTF` that should be labeled on the side of the heatmap.
#' @param labelTop A number indicating how many of the top N features, based on variance, in `sePositiveTF` should be labeled on the side of the heatmap.
#' @param labelRows A boolean value that indicates whether all rows should be labeled on the side of the heatmap.
#' @param labelCols A boolean value that indicates whether all columns should be labeled at the bottom of the heatmap.
#' @param rowOrder If wanting to set the order of rows to be plotted, the indices (integer or character correpsonding
#' to rownmaes) can be provided here.
#' @param useSeqnames A character vector that indicates which `seqnames` should be plotted in the heatmap. Features from
#' `seqnames` that are not listed will be ignored. In the context of a `Sparse.Assays.Matrix`, such as a matrix containing chromVAR
#' deviations, the `seqnames` do not correspond to chromosomes, rather they correspond to the sub-portions of the matrix, for example
#' raw deviations ("deviations") or deviation z-scores ("z") for a chromVAR deviations matrix.
#' @param returnMatrix A boolean value that indicates whether the final heatmap matrix should be returned in lieu of plotting the actual heatmap.
#' @param force If useSeqnames is longer than 1 if matrixClass is "Sparse.Assays.Matrix" to continue. This is not recommended because these matrices
#' can be in different units.
#' @param logFile The path to a file to be used for logging ArchR output.
#' @export
plotPositiveTFHeatmap <- function(
sePositiveTF = NULL,
varCutOff = 0.9,
maxFeatures = 25000,
scaleRows = TRUE,
limits = c(-1.5, 1.5),
grepExclude = NULL,
pal = NULL,
labelMarkers = NULL,
labelTop = 50,
labelRows = FALSE,
labelCols = FALSE,
rowOrder = NULL,
useSeqnames = NULL,
returnMatrix = FALSE,
force = FALSE,
logFile = createLogFile("plotPositiveTFHeatmap")
){

ArchR:::.validInput(input = sePositiveTF, name = "sePositiveTF", valid = c("SummarizedExperiment"))
ArchR:::.validInput(input = varCutOff, name = "varCutOff", valid = c("numeric", "null"))
ArchR:::.validInput(input = maxFeatures, name = "maxFeatures", valid = c("integer", "null"))
ArchR:::.validInput(input = scaleRows, name = "scaleRows", valid = c("boolean"))
ArchR:::.validInput(input = limits, name = "limits", valid = c("numeric"))
ArchR:::.validInput(input = grepExclude, name = "grepExclude", valid = c("character", "null"))
ArchR:::.validInput(input = pal, name = "pal", valid = c("palette", "null"))
ArchR:::.validInput(input = labelMarkers, name = "labelMarkers", valid = c("character", "null"))
ArchR:::.validInput(input = labelTop, name = "labelTop", valid = c("integer"))
ArchR:::.validInput(input = labelRows, name = "labelRows", valid = c("boolean"))
ArchR:::.validInput(input = labelCols, name = "labelCols", valid = c("boolean"))
ArchR:::.validInput(input = rowOrder, name = "rowOrder", valid = c("vector", "null"))
ArchR:::.validInput(input = useSeqnames, name = "useSeqnames", valid = c("character", "null"))
ArchR:::.validInput(input = returnMatrix, name = "returnMatrix", valid = c("boolean"))
ArchR:::.validInput(input = force, name = "force", valid = c("boolean"))
ArchR:::.validInput(input = logFile, name = "logFile", valid = c("character"))

ArchR:::.startLogging(logFile = logFile)
ArchR:::.logThis(mget(names(formals()),sys.frame(sys.nframe())), "plotTrajectoryHeatmap Input-Parameters", logFile = logFile)


if(!is.null(useSeqnames)){
sePositiveTF <- sePositiveTF[paste0(rowData(sePositiveTF)$seqnames) %in% paste0(useSeqnames), ]
}

if(nrow(sePositiveTF) == 0){
ArchR:::.logStop("No features left in sePositiveTF, please check input!", logFile = logFile)
}

mat <- assay(sePositiveTF)

if(!is.null(grepExclude)){
idxExclude <- grep(grepExclude, rownames(mat))
if(length(idxExclude) > 0){
mat <- mat[-grep(grepExclude, rownames(mat)), , drop = FALSE]
}
}

#Rows with NA
rSNA <- rowSums(is.na(mat))
if(sum(rSNA > 0) > 0){
ArchR:::.logMessage("Removing rows with NA values...", verbose = TRUE, logFile = logFile)
mat <- mat[rSNA == 0, ]#Remove NA Rows
}
ArchR:::.logThis(mat, "mat-pre", logFile = logFile)
varQ <- ArchR:::.getQuantiles(matrixStats::rowVars(mat))
ArchR:::.logThis(varQ, "varQ", logFile = logFile)
orderedVar <- FALSE
if(is.null(rowOrder)){
mat <- mat[order(varQ, decreasing = TRUE), ]
orderedVar <- TRUE
if(is.null(varCutOff) & is.null(maxFeatures)){
n <- nrow(mat)
}else if(is.null(varCutOff)){
n <- maxFeatures
}else if(is.null(maxFeatures)){
n <- (1-varCutOff) * nrow(mat)
}else{
n <- min((1-varCutOff) * nrow(mat), maxFeatures)
}
n <- min(n, nrow(mat))
mat <- mat[head(seq_len(nrow(mat)), n ),]
}
ArchR:::.logThis(mat, "mat-post", logFile = logFile)

#rownames(mat) <- rowData(sePositiveTF)$name

if(!is.null(labelTop)){
if(orderedVar){
idxLabel <- rownames(mat)[seq_len(labelTop)]
}else{
idxLabel <- rownames(mat)[order(varQ,decreasing=TRUE)][seq_len(labelTop)]
}
}else{
idxLabel <- NULL
}
ArchR:::.logThis(idxLabel, "idxLabel", logFile = logFile)

if(!is.null(labelMarkers)){
idxLabel2 <- match(tolower(labelMarkers), tolower(rownames(mat)), nomatch = 0)
idxLabel2 <- idxLabel2[idxLabel2 > 0]
}else{
idxLabel2 <- NULL
}
ArchR:::.logThis(idxLabel2, "idxLabel2", logFile = logFile)

idxLabel <- c(idxLabel, rownames(mat)[idxLabel2])
ArchR:::.logThis(idxLabel, "idxLabel", logFile = logFile)

if(scaleRows){
mat <- sweep(mat - rowMeans(mat), 1, matrixStats::rowSds(mat), `/`)
mat[mat > max(limits)] <- max(limits)
mat[mat < min(limits)] <- min(limits)
ArchR:::.logThis(mat, "mat-zscores", logFile = logFile)
}

if(nrow(mat) == 0){
stop("No Features Remaining!")
}

if(is.null(pal)){
if(is.null(metadata(sePositiveTF)$Params$useMatrix)){
pal <- paletteContinuous(set = "solarExtra", n = 100)
}else if(tolower(metadata(sePositiveTF)$Params$useMatrix)=="genescorematrix"){
pal <- paletteContinuous(set = "blueYellow", n = 100)
}else{
pal <- paletteContinuous(set = "solarExtra", n = 100)
}
}

if(!is.null(rowOrder)){
idx <- rowOrder
}else{
idx <- order(apply(mat, 1, which.max))
}
ArchR:::.logThis(idx, "idx", logFile = logFile)

ht <- tryCatch({

ArchR:::.ArchRHeatmap(
mat = mat[idx, ],
scale = FALSE,
limits = c(min(mat), max(mat)),
color = pal,
clusterCols = FALSE,
clusterRows = FALSE,
labelRows = labelRows,
labelCols = labelCols,
customRowLabel = match(idxLabel, rownames(mat[idx,])),
showColDendrogram = TRUE,
name = names(sePositiveTF@assays),
draw = FALSE
)

}, error = function(e){

errorList = list(
mat = mat[idx, ],
scale = FALSE,
limits = c(min(mat), max(mat)),
color = pal,
clusterCols = FALSE,
clusterRows = FALSE,
labelRows = labelRows,
labelCols = labelCols,
customRowLabel = match(idxLabel, rownames(mat[idx,])),
showColDendrogram = TRUE,
name = metadata(sePositiveTF)$Params$useMatrix,
draw = FALSE
)

ArchR:::.logError(e, fn = ".ArchRHeatmap", info = "", errorList = errorList, logFile = logFile)

})

ArchR:::.endLogging(logFile = logFile)

if(returnMatrix){
return(mat[idx, ])
}else{
return(ht)
}

}