Skip to content

Commit

Permalink
Merge pull request #108 from jr-leary7/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
jr-leary7 authored Jul 15, 2023
2 parents b80377b + ccaac09 commit 248b944
Show file tree
Hide file tree
Showing 16 changed files with 116 additions and 85 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: scLANE
Type: Package
Title: Model gene expression dynamics with spline-based NB GLMs, GEEs, & GLMMs
Version: 0.7.0
Version: 0.7.1
Authors@R: c(person(given = "Jack", family = "Leary", email = "[email protected]", role = c("aut", "cre")),
person(given = "Rhonda", family = "Bacher", email = "[email protected]", role = c("ctb", "fnd")))
Description: This package uses truncated power basis spline models to build flexible, interpretable models of single cell gene expression over pseudotime or latent time.
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# scLANE 0.7.1

* Changed input format of all functions to allow counts matrices formatted as `SingleCellExperiment` or `Seurat` objects, sparse matrices, or dense matrices.
* Updated visualization functions to reflect changes made in `ggplot2` v3.4 (mostly changing the `size` parameter in line-based geoms to be `linewidth` instead).

# scLANE 0.6.3

* Added a `NEWS.md` file to track changes to the package.
9 changes: 6 additions & 3 deletions R/createCellOffset.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @name createCellOffset
#' @author Jack Leary
#' @description Creates a vector of per-cell size factors to be used as input to \code{\link{testDynamic}} as a model offset given a variety of inputs.
#' @param expr.mat Either a gene-by-cell (cells as columns) matrix of raw integer counts prior to any cell filtering, a \code{Seurat} object, or a \code{SingleCellExperiment} object. Defaults to NULL.
#' @param expr.mat Either a matrix of raw integer counts (cells as columns), a \code{Seurat} object, or a \code{SingleCellExperiment} object. Defaults to NULL.
#' @param scale.factor The scaling factor use to multiply the sequencing depth factor for each cell. The default value is 1e4, which returns counts-per-10k.
#' @return A named numeric vector containing the computed size factor for each cell.
#' @seealso \code{\link{testDynamic}}
Expand All @@ -13,8 +13,8 @@
#' @export
#' @examples
#' \dontrun{
#' createCellOffset(expr.mat = raw_counts)
#' createCellOffset(expr.mat = raw_counts, scale.factor = 1e5)
#' createCellOffset(expr.mat = counts(sce_obj))
#' createCellOffset(expr.mat = seu_obj, scale.factor = 1e5)
#' }

createCellOffset <- function(expr.mat = NULL, scale.factor = 1e4) {
Expand All @@ -26,7 +26,10 @@ createCellOffset <- function(expr.mat = NULL, scale.factor = 1e4) {
expr.mat <- as.matrix(Seurat::GetAssayData(expr.mat,
slot = "counts",
assay = Seurat::DefaultAssay(expr.mat)))
} else if (inherits(expr.mat, "dgCMatrix")) {
expr.mat <- as.matrix(expr.mat)
}
if (!(inherits(expr.mat, "matrix") || inherits(expr.mat, "array"))) { stop("Input expr.mat must be coerceable to a matrix of integer counts.") }
# compute per-cell size factors
cell_names <- colnames(expr.mat)
seq_depths <- colSums(expr.mat)
Expand Down
25 changes: 22 additions & 3 deletions R/getFittedValues.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#' @param test.dyn.res The output from \code{\link{testDynamic}}. Defaults to NULL.
#' @param genes A character vector of genes to generate fitted values for. Defaults to NULL.
#' @param pt A data.frame of pseudotime values for each cell. Defaults to NULL.
#' @param expr.mat A matrix of integer expression values for each cell & gene. Must have genes as columns & cells as rows, with column names being gene names. Defaults to NULL.
#' @param expr.mat Either a \code{SingleCellExperiment} or \code{Seurat} object from which counts can be extracted, or a matrix of integer-valued counts with genes as rows & cells as columns. Defaults to NULL.
#' @param size.factor.offset (Optional) An offset to be used to rescale the fitted values. Can be generated easily with \code{\link{createCellOffset}}. No need to provide if the GEE backend was used. Defaults to NULL.
#' @param cell.meta.data (Optional) A data.frame of metadata values for each cell (celltype label, subject characteristics, tissue type, etc.) that will be included in the result table. Defaults to NULL.
#' @param id.vec (Optional) A vector of subject IDs used in fitting GEE or GLMM models. Defaults to NULL.
Expand All @@ -23,8 +23,8 @@
#' getFittedValues(gene_stats,
#' genes = c("Neurog3", "Epcam", "Krt19"),
#' pt = pt_df,
#' expr.mat = gene_counts,
#' cell.meta.data = seurat_object@meta.data,
#' expr.mat = seu_obj,
#' cell.meta.data = seu_obj@meta.data,
#' ci.alpha = 0.05)
#' }

Expand All @@ -39,6 +39,25 @@ getFittedValues <- function(test.dyn.res = NULL,
filter.lineage = NULL) {
# check inputs
if (is.null(expr.mat) || is.null(pt) || is.null(genes) || is.null(test.dyn.res)) { stop("You forgot one or more of the arguments to getFittedValues().") }
# get raw counts from SingleCellExperiment or Seurat object & transpose to cell x gene dense matrix
if (inherits(expr.mat, "SingleCellExperiment")) {
expr.mat <- BiocGenerics::counts(expr.mat)[genes, ]
expr.mat <- as.matrix(expr.mat)
} else if (inherits(expr.mat, "Seurat")) {
expr.mat <- Seurat::GetAssayData(expr.mat,
slot = "counts",
assay = Seurat::DefaultAssay(expr.mat))
expr.mat <- as.matrix(expr.mat[genes, ])
} else if (inherits(expr.mat, "dgCMatrix")) {
expr.mat <- as.matrix(expr.mat)
}
if (!(inherits(expr.mat, "matrix") || inherits(expr.mat, "array"))) { stop("Input expr.mat must be coerceable to a matrix of integer counts.") }
expr.mat <- t(expr.mat) # transpose to cell x gene matrix
if (is.null(genes)) {
genes <- colnames(expr.mat)
} else {
expr.mat <- expr.mat[, genes]
}
# generate parameters for CIs
Z <- stats::qnorm(ci.alpha / 2, lower.tail = FALSE)
# select sublist for gene of interest
Expand Down
25 changes: 15 additions & 10 deletions R/plotModels.R
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,23 @@ plotModels <- function(test.dyn.res = NULL,
plot.gam = TRUE,
plot.scLANE = TRUE,
filter.lineage = NULL,
gg.theme = ggplot2::theme_classic(base_size = 14)) {
gg.theme = ggplot2::theme_classic(base_size = 14,
base_line_size = 0.75,
base_rect_size = 0.75)) {
# check inputs
if (is.null(expr.mat) || is.null(pt) || is.null(gene) || is.null(test.dyn.res)) { stop("You forgot one or more of the arguments to plotModels().") }
# get raw counts from SingleCellExperiment or Seurat object & transpose to cell x gene dense matrix
if (inherits(expr.mat, "SingleCellExperiment")) {
expr.mat <- as.matrix(t(BiocGenerics::counts(expr.mat)))
expr.mat <- as.matrix(BiocGenerics::counts(expr.mat))
} else if (inherits(expr.mat, "Seurat")) {
expr.mat <- as.matrix(t(Seurat::GetAssayData(expr.mat,
slot = "counts",
assay = Seurat::DefaultAssay(expr.mat))))
expr.mat <- as.matrix(Seurat::GetAssayData(expr.mat,
slot = "counts",
assay = Seurat::DefaultAssay(expr.mat)))
} else if (inherits(expr.mat, "dgCMatrix")) {
expr.mat <- as.matrix(expr.mat)
}
if (!(inherits(expr.mat, "matrix") || inherits(expr.mat, "array"))) { stop("Input expr.mat must be coerceable to a matrix of integer counts.") }
expr.mat <- t(expr.mat)
# generate parameters for CIs
Z <- stats::qnorm(ci.alpha / 2, lower.tail = FALSE)
# select sublist for gene of interest
Expand Down Expand Up @@ -277,13 +282,13 @@ plotModels <- function(test.dyn.res = NULL,
}
p <- p +
ggplot2::geom_line(mapping = ggplot2::aes(y = PRED),
size = 0.75,
linewidth = 0.75,
color = "black",
show.legend = FALSE) +
ggplot2::geom_ribbon(mapping = ggplot2::aes(ymin = CI_LL, ymax = CI_UL),
fill = "grey50",
alpha = 0.4,
size = 0,
linewidth = 0,
show.legend = FALSE) +
ggplot2::scale_y_continuous(labels = scales::label_comma()) +
ggplot2::scale_x_continuous(labels = scales::label_number(accuracy = 0.1)) +
Expand All @@ -301,17 +306,17 @@ plotModels <- function(test.dyn.res = NULL,
size = 0.5,
show.legend = ifelse(ncol(pt) > 1, TRUE, FALSE))
if (requireNamespace("ggh4x", quietly = TRUE)) {
p <- p + ggh4x::facet_nested_wrap(~paste0("Lineage ", LINEAGE) + MODEL)
p <- p + ggh4x::facet_nested_wrap(~paste0("Lineage ", LINEAGE) + MODEL, )
} else {
p <- p + ggplot2::facet_wrap(~paste0("Lineage ", LINEAGE) + MODEL)
}
p <- p +
ggplot2::geom_line(mapping = ggplot2::aes(y = PRED),
size = 0.75,
linewidth = 0.75,
color = "black") +
ggplot2::geom_ribbon(mapping = ggplot2::aes(ymin = CI_LL, ymax = CI_UL),
alpha = 0.4,
size = 0,
linewidth = 0,
color = "grey") +
ggplot2::scale_y_continuous(labels = scales::label_comma()) +
ggplot2::scale_x_continuous(labels = scales::label_number(accuracy = 0.1)) +
Expand Down
17 changes: 10 additions & 7 deletions R/testDynamic.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#' @importFrom stats predict logLik deviance offset
#' @importFrom geeM geem
#' @importFrom glmmTMB glmmTMB nbinom2
#' @param expr.mat Either a \code{SingleCellExperiment} or \code{Seurat} object from which counts can be extracted, or a dense matrix of integer-valued counts. Defaults to NULL.
#' @param expr.mat Either a \code{SingleCellExperiment} or \code{Seurat} object from which counts can be extracted, or a matrix of integer-valued counts with genes as rows & cells as columns. Defaults to NULL.
#' @param pt Either the output from \code{\link[slingshot]{SlingshotDataSet}} object from which pseudotime can be generated, or a data.frame containing the pseudotime or latent time estimates for each cell (can be multiple columns / lineages). Defaults to NULL.
#' @param genes A character vector of genes to model. If not provided, defaults to all genes in \code{expr.mat}. Defaults to NULL.
#' @param n.potential.basis.fns (Optional) The maximum number of possible basis functions. See the parameter \code{M} in \code{\link{marge2}}. Defaults to 5.
Expand Down Expand Up @@ -59,20 +59,20 @@
#' parallel.exec = TRUE,
#' n.cores = 8,
#' n.potential.basis.fns = 7)
#' testDynamic(expr.mat = raw_counts,
#' testDynamic(expr.mat = counts(sce_obj),
#' pt = pseudotime_df,
#' is.gee = TRUE,
#' id.vec = my_subject_ids,
#' id.vec = colData(sce_obj)$subject_id,
#' cor.structure = "ar1",
#' parallel.exec = TRUE,
#' n.cores = 8,
#' n.potential.basis.fns = 7)
#' testDynamic(expr.mat = raw_counts,
#' testDynamic(expr.mat = seu_obj,
#' pt = pseudotime_df,
#' parallel.exec = TRUE,
#' n.cores = 8,
#' is.glmm = TRUE,
#' id.vec = my_subject_ids,
#' id.vec = seu_obj$subject_id,
#' log.file = "scLANE_log.txt",
#' log.iter = 10)
#' }
Expand All @@ -98,14 +98,17 @@ testDynamic <- function(expr.mat = NULL,
# get raw counts from SingleCellExperiment or Seurat object & transpose to cell x gene dense matrix
if (inherits(expr.mat, "SingleCellExperiment")) {
expr.mat <- BiocGenerics::counts(expr.mat)[genes, ]
expr.mat <- t(as.matrix(expr.mat))
expr.mat <- as.matrix(expr.mat)
} else if (inherits(expr.mat, "Seurat")) {
expr.mat <- Seurat::GetAssayData(expr.mat,
slot = "counts",
assay = Seurat::DefaultAssay(expr.mat))
expr.mat <- t(as.matrix(expr.mat[genes, ]))
expr.mat <- as.matrix(expr.mat[genes, ])
} else if (inherits(expr.mat, "dgCMatrix")) {
expr.mat <- as.matrix(expr.mat)
}
if (!(inherits(expr.mat, "matrix") || inherits(expr.mat, "array"))) { stop("Input expr.mat must be coerceable to a matrix of integer counts.") }
expr.mat <- t(expr.mat) # transpose to cell x gene matrix
if (is.null(genes)) {
genes <- colnames(expr.mat)
} else {
Expand Down
Loading

0 comments on commit 248b944

Please sign in to comment.