From afe646c2dec32144472a202145a53798b8bc30f4 Mon Sep 17 00:00:00 2001 From: Jack Leary Date: Sun, 12 Nov 2023 17:48:25 -0500 Subject: [PATCH] Added docs for bioconductor submission -- related to #96 --- .github/workflows/bioc-check.yaml | 3 +- .github/workflows/render-README.yaml | 6 ++-- DESCRIPTION | 1 + R/GetResultsDE.R | 8 ++--- R/clusterGenes.R | 19 ++++------- R/createCellOffset.R | 7 ++-- R/createSlopeTestData.R | 7 ---- R/embedGenes.R | 27 +++++++++------ R/enrichDynamicGenes.R | 9 ++--- R/extractBreakpoints.R | 10 ++++-- R/fitGLMM.R | 13 ++++---- R/geneProgramScoring.R | 18 ++++++---- R/getFittedValues.R | 15 ++++----- R/getKnotDist.R | 5 ++- R/marge2.R | 24 ++++---------- R/nbGAM.R | 20 +++++------- R/npConvolve.R | 4 +-- R/plotClusteredGenes.R | 2 +- R/plotModelCoefs.R | 15 +++++---- R/plotModels.R | 37 +++++++-------------- R/smoothedCountsMatrix.R | 17 ++++------ R/sortGenesHeatmap.R | 12 ++++--- R/stripGLM.R | 10 ++++-- R/summarizeModel.R | 10 ++++-- R/testDynamic.R | 40 +++++++---------------- R/testSlope.R | 8 ++--- R/theme_scLANE.R | 17 ++++++---- R/tp1.R | 12 ++++--- R/tp2.R | 12 ++++--- man/clusterGenes.Rd | 19 ++++------- man/createCellOffset.Rd | 7 ++-- man/createSlopeTestData.Rd | 8 ----- man/embedGenes.Rd | 16 +++++---- man/enrichDynamicGenes.Rd | 9 ++--- man/extractBreakpoints.Rd | 10 ++++-- man/figures/README-unnamed-chunk-2-1.png | Bin 30995 -> 30842 bytes man/fitGLMM.Rd | 13 ++++---- man/geneProgramScoring.Rd | 18 ++++++---- man/getFittedValues.Rd | 15 ++++----- man/getKnotDist.Rd | 5 ++- man/getResultsDE.Rd | 8 ++--- man/marge2.Rd | 24 ++++---------- man/nbGAM.Rd | 20 +++++------- man/npConvolve.Rd | 4 +-- man/plotClusteredGenes.Rd | 2 +- man/plotModelCoefs.Rd | 15 +++++---- man/plotModels.Rd | 33 +++++-------------- man/smoothedCountsMatrix.Rd | 15 ++++----- man/sortGenesHeatmap.Rd | 12 ++++--- man/stripGLM.Rd | 10 ++++-- man/summarizeModel.Rd | 10 ++++-- man/testDynamic.Rd | 23 ++----------- man/testSlope.Rd | 8 ++--- man/theme_scLANE.Rd | 17 ++++++---- man/tp1.Rd | 10 +++--- man/tp2.Rd | 10 +++--- 56 files changed, 317 insertions(+), 412 deletions(-) diff --git a/.github/workflows/bioc-check.yaml b/.github/workflows/bioc-check.yaml index d12e442..13a952e 100644 --- a/.github/workflows/bioc-check.yaml +++ b/.github/workflows/bioc-check.yaml @@ -4,7 +4,8 @@ on: push: branches: main - pull_request: main + pull_request: + branches: main name: bioc-check diff --git a/.github/workflows/render-README.yaml b/.github/workflows/render-README.yaml index b7a250d..9d46354 100644 --- a/.github/workflows/render-README.yaml +++ b/.github/workflows/render-README.yaml @@ -10,7 +10,7 @@ name: render-README jobs: render: - runs-on: ubuntu-latest + runs-on: macos-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: @@ -22,9 +22,9 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 - name: install CRAN packages - run: Rscript -e 'install.packages(c("rmarkdown","ggplot2", "dplyr", "purrr", "remotes", "devtools", "BiocManager", "Seurat"), dependencies = TRUE)' + run: Rscript -e 'install.packages(c("rmarkdown","ggplot2", "dplyr", "purrr", "remotes", "devtools", "BiocManager", "Seurat"), force = TRUE)' - name: install BioConductor packages - run: Rscript -e 'BiocManager::install(c("SingleCellExperiment", "scater", "scran", "scuttle", "bluster"))' + run: Rscript -e 'BiocManager::install(c("SingleCellExperiment", "scater", "scran", "scuttle", "bluster"), force = TRUE)' - name: install GitHub packages run: Rscript -e 'remotes::install_github("jr-leary7/scLANE")' - name: render README diff --git a/DESCRIPTION b/DESCRIPTION index 5529133..ef4685d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -63,6 +63,7 @@ Suggests: BiocStyle, slingshot, gprofiler2, + BiocParallel, BiocGenerics, BiocNeighbors, testthat (>= 3.0.0), diff --git a/R/GetResultsDE.R b/R/GetResultsDE.R index 5b0ac01..22c0c41 100644 --- a/R/GetResultsDE.R +++ b/R/GetResultsDE.R @@ -16,12 +16,8 @@ #' @seealso \code{\link{testDynamic}} #' @seealso \code{\link[stats]{p.adjust}} #' @examples -#' \dontrun{ -#' getResultsDE(gene_stats) -#' getResultsDE(gene_stats, -#' p.adj.method = "BH", -#' fdr.cutoff = 5e-3) -#' } +#' data(scLANE_models) +#' scLANE_de_res <- getResultsDE(scLANE_models) getResultsDE <- function(test.dyn.res = NULL, p.adj.method = "holm", diff --git a/R/clusterGenes.R b/R/clusterGenes.R index 5833918..42a61fb 100644 --- a/R/clusterGenes.R +++ b/R/clusterGenes.R @@ -23,19 +23,12 @@ #' @seealso \code{\link{plotClusteredGenes}} #' @export #' @examples -#' \dontrun{ -#' clusterGenes(gene_stats, pt = pt_df) -#' clusterGenes(gene_stats, -#' pt = pt_df, -#' size.factor.offset = createCellOffset(sce_obj), -#' clust.algo = "kmeans", -#' use.pca = TRUE, -#' n.PC = 10, -#' lineages = "B") -#' clusterGenes(gene_stats, -#' pt = pt_df, -#' lineages = c("A", "C")) -#' } +#' data(sim_pseudotime) +#' data(scLANE_models) +#' cell_offset <- createCellOffset(sim_counts) +#' gene_clusters <- clusterGenes(scLANE_models, +#' pt = sim_pseudotime, +#' size.factor.offset = cell_offset) clusterGenes <- function(test.dyn.res = NULL, pt = NULL, diff --git a/R/createCellOffset.R b/R/createCellOffset.R index ecaa277..4576e3c 100644 --- a/R/createCellOffset.R +++ b/R/createCellOffset.R @@ -13,11 +13,8 @@ #' @seealso \code{\link[scuttle]{computeLibraryFactors}} #' @export #' @examples -#' \dontrun{ -#' createCellOffset(expr.mat = sce_obj) -#' createCellOffset(expr.mat = counts(sce_obj)) -#' createCellOffset(expr.mat = seu_obj, scale.factor = 1e5) -#' } +#' data(sim_counts) +#' cell_offset <- createCellOffset(sim_counts) createCellOffset <- function(expr.mat = NULL, scale.factor = 1e4) { # check inputs diff --git a/R/createSlopeTestData.R b/R/createSlopeTestData.R index 339213d..524c827 100644 --- a/R/createSlopeTestData.R +++ b/R/createSlopeTestData.R @@ -11,13 +11,6 @@ #' @return A data.frame containing model data. #' @seealso \code{\link{marge2}} #' @seealso \code{\link{testSlope}} -#' @examples -#' \dontrun{ -#' createSlopeTestData(marge_mod, pt_df) -#' createSlopeTestData(marge_mod, -#' pt = pt_df, -#' is.glmm = TRUE) -#' } createSlopeTestData <- function(marge.model = NULL, pt = NULL, diff --git a/R/embedGenes.R b/R/embedGenes.R index 7bb7eed..8af54f5 100644 --- a/R/embedGenes.R +++ b/R/embedGenes.R @@ -17,14 +17,16 @@ #' @param k.param (Optional) The value of nearest-neighbors used in creating the SNN graph prior to clustering & in running UMAP. Defaults to 20. #' @param resolution.param (Optional) The value of the resolution parameter for the Leiden algorithm. If unspecified, silhouette scoring is used to select an optimal value. Defaults to NULL. #' @param random.seed (Optional) The random seed used to control stochasticity in the clustering algorithm. Defaults to 312. +#' @param n.cores (Optional) Integer specifying the number of threads used by \code{\link[uwot]{umap}} and in \code{\link[bluster]{makeSNNGraph}}. Defaults to 2. #' @return A data.frame containing embedding coordinates, cluster IDs, and metadata for each gene. #' @export #' @examples -#' \dontrun{ -#' embedGenes(smoothed_counts$Lineage_A, -#' pcs.return = 3, -#' cluster.genes = TRUE) -#' } +#' data(sim_pseudotime) +#' data(scLANE_models) +#' smoothed_dynamics <- smoothedCountsMatrix(scLANE_models, +#' pt = sim_pseudotime, +#' n.cores = 1L) +#' gene_embed <- embedGenes(smoothed_dynamics$Lineage_A, n.cores = 1L) embedGenes <- function(smoothed.counts = NULL, genes = NULL, @@ -35,7 +37,8 @@ embedGenes <- function(smoothed.counts = NULL, gene.meta.data = NULL, k.param = 20, resolution.param = NULL, - random.seed = 312) { + random.seed = 312, + n.cores = 2L) { # check inputs if (is.null(smoothed.counts)) { stop("You forgot to provide a smoothed counts matrix to embedGenes().") } genes <- colnames(smoothed.counts) @@ -52,7 +55,8 @@ embedGenes <- function(smoothed.counts = NULL, n_neighbors = k.param, init = "spectral", nn_method = "annoy", - seed = random.seed) + seed = random.seed, + n_threads = n.cores) } else { smoothed_counts_umap <- uwot::umap(smoothed.counts, n_components = 2, @@ -60,7 +64,8 @@ embedGenes <- function(smoothed.counts = NULL, n_neighbors = k.param, init = "spectral", nn_method = "annoy", - seed = random.seed) + seed = random.seed, + n_threads = n.cores) } # clustering w/ silhouette score parameter tuning if (cluster.genes) { @@ -68,12 +73,14 @@ embedGenes <- function(smoothed.counts = NULL, smoothed_counts_snn <- bluster::makeSNNGraph(smoothed_counts_pca$x, k = k.param, type = "jaccard", - BNPARAM = BiocNeighbors::AnnoyParam(distance = "Cosine")) + BNPARAM = BiocNeighbors::AnnoyParam(distance = "Cosine"), + BPPARAM = BiocParallel::SnowParam(workers = n.cores)) } else { smoothed_counts_snn <- bluster::makeSNNGraph(smoothed.counts, k = k.param, type = "jaccard", - BNPARAM = BiocNeighbors::AnnoyParam(distance = "Cosine")) + BNPARAM = BiocNeighbors::AnnoyParam(distance = "Cosine"), + BPPARAM = BiocParallel::SnowParam(workers = n.cores)) } if (is.null(resolution.param)) { if (pca.init) { diff --git a/R/enrichDynamicGenes.R b/R/enrichDynamicGenes.R index 4acb05b..654e60d 100644 --- a/R/enrichDynamicGenes.R +++ b/R/enrichDynamicGenes.R @@ -12,12 +12,9 @@ #' @seealso \code{\link[gprofiler2]{gost}} #' @export #' @examples -#' \dontrun{ -#' enrichDynamicGenes(scLANE.de.res = de_stats) -#' enrichDynamicGenes(scLANE.de.res = de_stats, -#' lineage = "B", -#' species = "mmusculus") -#' } +#' data(scLANE_models) +#' scLANE_de_res <- getResultsDE(scLANE_models) +#' enr_res <- enrichDynamicGenes(scLANE_de_res) enrichDynamicGenes <- function(scLANE.de.res = NULL, lineage = NULL, diff --git a/R/extractBreakpoints.R b/R/extractBreakpoints.R index 3bb1871..4e19b00 100644 --- a/R/extractBreakpoints.R +++ b/R/extractBreakpoints.R @@ -8,9 +8,13 @@ #' @return A data.frame of breakpoints & their directions. #' @export #' @examples -#' \dontrun{ -#' extractBreakpoints(model = marge_mod) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' marge_model <- marge2(sim_pseudotime, +#' Y = BiocGenerics::counts(sim_counts)[4, ], +#' Y.offset = cell_offset) +#' breakpoint_df <- extractBreakpoints(model = marge_model) extractBreakpoints <- function(model = NULL, directions = TRUE) { # check inputs diff --git a/R/fitGLMM.R b/R/fitGLMM.R index 3549575..8473967 100644 --- a/R/fitGLMM.R +++ b/R/fitGLMM.R @@ -22,12 +22,13 @@ #' @seealso \code{\link{modelLRT}} #' @export #' @examples -#' \dontrun{ -#' fitGLMM(X_pred = pt_df, -#' Y = raw_counts, -#' Y.offset = size_factor_vec, -#' id.vec = subject_vec) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' glmm_mod <- fitGLMM(X_pred = sim_pseudotime, +#' Y = BiocGenerics::counts(sim_counts)[4, ], +#' Y.offset = cell_offset, +#' id.vec = sim_counts$subject) fitGLMM <- function(X_pred = NULL, Y = NULL, diff --git a/R/geneProgramScoring.R b/R/geneProgramScoring.R index 49a6102..1404ce1 100644 --- a/R/geneProgramScoring.R +++ b/R/geneProgramScoring.R @@ -15,18 +15,22 @@ #' @return Either a \code{Seurat} or \code{SingleCellExperiment} object if \code{expr.mat} is in either form, or a data.frame containing per-cell program scores if \code{expr.mat} is a matrix. #' @export #' @examples -#' \dontrun{ -#' geneProgramScoring(seu_obj, -#' genes = gene_embed$gene, -#' gene.clusters = gene_embed$leiden, -#' program.labels = c("cell cycle", "organogenesis")) -#' } +#' data(sim_pseudotime) +#' data(scLANE_models) +#' smoothed_dynamics <- smoothedCountsMatrix(scLANE_models, +#' pt = sim_pseudotime, +#' n.cores = 1L) +#' gene_embed <- embedGenes(smoothed_dynamics$Lineage_A, n.cores = 1L) +#' sim_counts <- geneProgramScoring(sim_counts, +#' genes = gene_embed$gene, +#' gene.clusters = gene_embed$leiden, +#' n.cores = 1L) geneProgramScoring <- function(expr.mat = NULL, genes = NULL, gene.clusters = NULL, program.labels = NULL, - n.cores = 2) { + n.cores = 2L) { # check inputs if (is.null(expr.mat) || is.null(genes) || is.null(gene.clusters)) { stop("Arguments to geneProgramScoring() are missing.") } if (!is.factor(gene.clusters)) { diff --git a/R/getFittedValues.R b/R/getFittedValues.R index 738f325..1364a39 100644 --- a/R/getFittedValues.R +++ b/R/getFittedValues.R @@ -20,14 +20,13 @@ #' @return A data.frame containing depth- and log1p-normalized expression, model predictions, and cell-level metadata. #' @export #' @examples -#' \dontrun{ -#' getFittedValues(gene_stats, -#' genes = c("Neurog3", "Epcam", "Krt19"), -#' pt = pt_df, -#' expr.mat = seu_obj, -#' cell.meta.data = seu_obj@meta.data, -#' ci.alpha = 0.05) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' data(scLANE_models) +#' fitted_vals <- getFittedValues(scLANE_models, +#' genes = sample(names(scLANE_models), 5), +#' pt = sim_pseudotime, +#' expr.mat = sim_counts) getFittedValues <- function(test.dyn.res = NULL, genes = NULL, diff --git a/R/getKnotDist.R b/R/getKnotDist.R index c88fc4b..502f226 100644 --- a/R/getKnotDist.R +++ b/R/getKnotDist.R @@ -11,9 +11,8 @@ #' @return A data.frame containing gene name, lineage ID, and knot location in pseudotime. #' @export #' @examples -#' \dontrun{ -#' getKnotDist(gene_stats) -#' } +#' data(scLANE_models) +#' knot_dist <- getKnotDist(scLANE_models) getKnotDist <- function(test.dyn.res = NULL, dyn.genes = NULL) { # check inputs diff --git a/R/marge2.R b/R/marge2.R index 73dfedc..7f87a2b 100644 --- a/R/marge2.R +++ b/R/marge2.R @@ -42,24 +42,12 @@ #' @seealso \code{\link[geeM]{geem}} #' @export #' @examples -#' \dontrun{ -#' marge2(pseudotime_df, -#' Y = expr_vec, -#' M = 3) -#' marge2(pseudotime_df, -#' Y = expr_vec, -#' Y.offset = size_factor_vec, -#' is.gee = TRUE, -#' id.vec = subject_vec, -#' cor.structure = "exchangeable") -#' marge2(pseudotime_df, -#' Y = expr_vec, -#' is.gee = TRUE, -#' id.vec = subject_vec, -#' cor.structure = "ar1", -#' n.knot.max = 10, -#' return.basis = TRUE) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' marge_model <- marge2(sim_pseudotime, +#' Y = BiocGenerics::counts(sim_counts)[4, ], +#' Y.offset = cell_offset) marge2 <- function(X_pred = NULL, Y = NULL, diff --git a/R/nbGAM.R b/R/nbGAM.R index 0811985..1462559 100644 --- a/R/nbGAM.R +++ b/R/nbGAM.R @@ -21,18 +21,14 @@ #' @seealso \code{\link[gamlss.dist]{NBI}} #' @export #' @examples -#' \dontrun{ -#' nbGAM(expr_vec, pt_df) -#' nbGAM(expr_vec, -#' pt = pt_df, -#' id.vec = subject_ids, -#' random.slopes = TRUE) -#' nbGAM(expr_vec, -#' pt = pt_df, -#' Y.offset = size_factor_vec, -#' penalize.spline = TRUE, -#' spline.df = 10) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' gam_mod <- nbGAM(BiocGenerics::counts(sim_counts)[4, ], +#' pt = sim_pseudotime, +#' Y.offset = cell_offset, +#' penalize.spline = TRUE, +#' spline.df = 10) nbGAM <- function(expr = NULL, pt = NULL, diff --git a/R/npConvolve.R b/R/npConvolve.R index 3b76f81..f3e6159 100644 --- a/R/npConvolve.R +++ b/R/npConvolve.R @@ -9,12 +9,12 @@ #' @return A convolution with same length as the input vector. #' @details #' \itemize{ -#' \item The convolution here uses \code{\link[stats]{convolve}}, but creates the kernel and padding in such a way that it matches the output from `np.convolve` in Python's \code{numpy} matrix algebra package. +#' \item The convolution here uses \code{\link[stats]{convolve}}, but creates the kernel and padding in such a way that it matches the output from \code{np.convolve} in Python's \code{numpy} matrix algebra package. #' } #' @seealso \code{\link[stats]{convolve}} #' @export #' @examples -#' npConvolve(x = rnorm(20), conv.kernel = rep(1/5, 5)) +#' convolved_vec <- npConvolve(x = rnorm(20), conv.kernel = rep(1/5, 5)) #' npConvolve <- function(x = NULL, conv.kernel = NULL) { diff --git a/R/plotClusteredGenes.R b/R/plotClusteredGenes.R index a7e6cd6..1d7e6d6 100644 --- a/R/plotClusteredGenes.R +++ b/R/plotClusteredGenes.R @@ -37,7 +37,7 @@ plotClusteredGenes <- function(test.dyn.res = NULL, pt = NULL, size.factor.offset = NULL, parallel.exec = TRUE, - n.cores = 2) { + n.cores = 2L) { # check inputs if (is.null(test.dyn.res) || is.null(gene.clusters) || is.null(pt)) { stop("Arguments to plotClusteredGenes() are missing.") } colnames(pt) <- paste0("Lineage_", LETTERS[seq_len(ncol(pt))]) diff --git a/R/plotModelCoefs.R b/R/plotModelCoefs.R index 052f347..2915b42 100644 --- a/R/plotModelCoefs.R +++ b/R/plotModelCoefs.R @@ -18,13 +18,16 @@ #' @return A \code{ggplot2} object displaying a gene dynamics plot & a table of coefficients across pseudotime intervals. #' @export #' @examples -#' \dontrun{ -#' plotModelCoefs(gene_stats, -#' gene = "BRCA2", -#' pt = pt_df, -#' expr.mat = seu_obj, +#' data(sim_counts) +#' data(sim_pseudotime) +#' data(scLANE_models) +#' cell_offset <- createCellOffset(sim_counts) +#' scLANE_de_res <- getResultsDE(scLANE_models) +#' plotModelCoefs(scLANE_models, +#' gene = scLANE_de_res$Gene[1], +#' pt = sim_pseudotime, +#' expr.mat = sim_counts, #' size.factor.offset = cell_offset) -#' } plotModelCoefs <- function(test.dyn.res = NULL, gene = NULL, diff --git a/R/plotModels.R b/R/plotModels.R index 4e01a1f..4ad13f7 100644 --- a/R/plotModels.R +++ b/R/plotModels.R @@ -34,30 +34,15 @@ #' @return A \code{ggplot} object. #' @export #' @examples -#' \dontrun{ -#' plotModels(gene_stats, -#' gene = "AURKA", -#' pt = pt_df, -#' expr.mat = count_mat, -#' size.factor.offset = cell_offset) -#' plotModels(gene_stats, -#' gene = "CD3E", -#' pt = pt_df, -#' expr.mat = seu_obj, -#' size.factor.offset = cell_offset, -#' ci.alpha = 0.1, -#' filter.lineage = c("A", "C")) -#' plotModels(gene_stats, -#' gene = "CD14", -#' pt = pt_df, -#' expr.mat = sce_obj, -#' size.factor.offset = cell_offset, -#' is.glmm = TRUE, -#' id.vec = subject_ids, -#' plot.glm = TRUE, # plots an NB GLMM with random intercepts & slopes per-subject -#' plot.gam = TRUE, # plots an NB GAMM with random intercepts per-subject -#' gg.theme = ggplot2::theme_minimal()) -#' } +#' data(sim_counts) +#' data(scLANE_models) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' model_plot <- plotModels(scLANE_models, +#' gene = names(scLANE_models)[2], +#' pt = sim_pseudotime, +#' expr.mat = sim_counts, +#' size.factor.offset = cell_offset) plotModels <- function(test.dyn.res = NULL, gene = NULL, @@ -315,7 +300,7 @@ plotModels <- function(test.dyn.res = NULL, ggplot2::scale_y_continuous(labels = scales::label_comma()) + ggplot2::scale_x_continuous(labels = scales::label_number(accuracy = 0.1)) + ggplot2::labs(x = "Pseudotime", - y = "Expression", + y = ifelse(log1p.norm, "Normalized Expression", "Expression"), color = "Subject", fill = "Subject", title = gene) + @@ -347,7 +332,7 @@ plotModels <- function(test.dyn.res = NULL, ggplot2::scale_y_continuous(labels = scales::label_comma()) + ggplot2::scale_x_continuous(labels = scales::label_number(accuracy = 0.1)) + ggplot2::labs(x = "Pseudotime", - y = "Expression", + y = ifelse(log1p.norm, "Normalized Expression", "Expression"), color = "Lineage", fill = "Lineage", title = gene) + diff --git a/R/smoothedCountsMatrix.R b/R/smoothedCountsMatrix.R index 620006c..daa124f 100644 --- a/R/smoothedCountsMatrix.R +++ b/R/smoothedCountsMatrix.R @@ -19,14 +19,11 @@ #' @seealso \code{\link{testDynamic}} #' @export #' @examples -#' \dontrun{ -#' smoothedCountsMatrix(gene_stats, pt = pt_df) -#' smoothedCountsMatrix(gene_stats, -#' pt = pt_df, -#' genes = c("AURKA", "KRT19", "EPCAM", "GATA6"), -#' parallel.exec = TRUE, -#' n.cores = 2) -#' } +#' data(sim_pseudotime) +#' data(scLANE_models) +#' smoothed_dynamics <- smoothedCountsMatrix(scLANE_models, +#' pt = sim_pseudotime, +#' n.cores = 1L) smoothedCountsMatrix <- function(test.dyn.res = NULL, size.factor.offset = NULL, @@ -34,7 +31,7 @@ smoothedCountsMatrix <- function(test.dyn.res = NULL, genes = NULL, log1p.norm = FALSE, parallel.exec = TRUE, - n.cores = 2) { + n.cores = 2L) { # check inputs if (is.null(test.dyn.res) || is.null(pt)) { stop("Please provide the scLANE output from testDynamic().") } # set up parallel execution @@ -58,7 +55,7 @@ smoothedCountsMatrix <- function(test.dyn.res = NULL, purrr::discard(rlang::is_na) %>% purrr::discard(rlang::is_null) %>% purrr::discard(\(p) rlang::inherits_only(p, "try-error")) - fitted_vals_mat <- purrr::map(fitted_vals_list, \(z) { + fitted_vals_mat <- furrr::future_map(fitted_vals_list, \(z) { if (is.null(size.factor.offset)) { exp(z$marge_link_fit) } else { diff --git a/R/sortGenesHeatmap.R b/R/sortGenesHeatmap.R index 1565280..7135177 100644 --- a/R/sortGenesHeatmap.R +++ b/R/sortGenesHeatmap.R @@ -12,11 +12,13 @@ #' @seealso \code{\link{smoothedCountsMatrix}} #' @export #' @examples -#' \dontrun{ -#' smoothed_counts <- smoothedCountsMatrix(gene_stats, pt = pt_df) -#' sortGenesheatmap(heatmap.mat = smoothed_counts$Lineage_A, -#' pt.vec = pt_df[!is.na(pt_df$Lineage_A), ]$Lineage_A) -#' } +#' data(sim_pseudotime) +#' data(scLANE_models) +#' smoothed_counts <- smoothedCountsMatrix(scLANE_models, +#' pt = sim_pseudotime, +#' n.cores = 1L) +#' sorted_genes <- sortGenesHeatmap(smoothed_counts$Lineage_A, +#' pt.vec = sim_pseudotime$PT) sortGenesHeatmap <- function(heatmap.mat = NULL, pt.vec = NULL) { # check inputs diff --git a/R/stripGLM.R b/R/stripGLM.R index a18b0ea..72a0923 100644 --- a/R/stripGLM.R +++ b/R/stripGLM.R @@ -8,9 +8,13 @@ #' @export #' @seealso \code{\link{glm}} #' @examples -#' \dontrun{ -#' stripGLM(marge_model) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' marge_model <- marge2(sim_pseudotime, +#' Y = BiocGenerics::counts(sim_counts)[4, ], +#' Y.offset = cell_offset) +#' smaller_model <- stripGLM(marge_model$final_mod) stripGLM <- function(glm.obj = NULL) { # check inputs diff --git a/R/summarizeModel.R b/R/summarizeModel.R index 744e9e9..fa5809f 100644 --- a/R/summarizeModel.R +++ b/R/summarizeModel.R @@ -12,9 +12,13 @@ #' @seealso \code{\link{marge2}} #' @export #' @examples -#' \dontrun{ -#' summarizeModel(marge.model = marge_mod, pt = pt_df) -#' } +#' data(sim_counts) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' marge_model <- marge2(sim_pseudotime, +#' Y = BiocGenerics::counts(sim_counts)[4, ], +#' Y.offset = cell_offset) +#' model_summary <- summarizeModel(marge.model = marge_model, pt = sim_pseudotime) summarizeModel <- function(marge.model = NULL, pt = NULL) { # check inputs diff --git a/R/testDynamic.R b/R/testDynamic.R index 1a1b8cc..1b96e71 100644 --- a/R/testDynamic.R +++ b/R/testDynamic.R @@ -46,29 +46,12 @@ #' @seealso \code{\link[glmmTMB]{glmmTMB}} #' @export #' @examples -#' \donttest{ #' data(sim_counts) #' data(sim_pseudotime) #' cell_offset <- createCellOffset(sim_counts) -#' testDynamic(sim_counts, -#' pt = sim_pseudotime, -#' size.factor.offset = cell_offset, -#' genes = sample(rownames(sim_counts), 20)) -#' testDynamic(sim_counts, -#' pt = sim_pseudotime, -#' size.factor.offset = cell_offset, -#' is.gee = TRUE, -#' id.vec = sim_counts$subject, -#' cor.structure = "ar1", -#' genes = sample(rownames(sim_counts), 20)) -#' testDynamic(sim_counts, -#' pt = sim_pseudotime, -#' size.factor.offset = cell_offset, -#' is.glmm = TRUE, -#' glmm.adaptive = TRUE, -#' id.vec = sim_counts$subject, -#' genes = sample(rownames(sim_counts), 20)) -#'} +#' scLANE_models <- testDynamic(sim_counts, +#' pt = sim_pseudotime, +#' size.factor.offset = cell_offset) testDynamic <- function(expr.mat = NULL, pt = NULL, @@ -172,6 +155,7 @@ testDynamic <- function(expr.mat = NULL, .packages = package_list, .noexport = no_export, .errorhandling = "pass", + .inorder = TRUE, .verbose = FALSE) %dopar% { lineage_list <- vector("list", n_lineages) for (j in seq(n_lineages)) { @@ -256,7 +240,7 @@ testDynamic <- function(expr.mat = NULL, # slim down GLM object if not a GEE / GLMM model (which are much smaller for some reason) if (!(is.gee || is.glmm)) { - null_mod <- scLANE::stripGLM(glm.obj = null_mod) + null_mod <- stripGLM(glm.obj = null_mod) } # record model fit status @@ -275,21 +259,21 @@ testDynamic <- function(expr.mat = NULL, } # summarize hinge function coefficients - null_sumy <- scLANE:::pull.null.sumy(null_mod, is.gee, is.glmm) - marge_sumy <- scLANE:::pull.marge.sumy(marge_mod, is.gee, is.glmm) + null_sumy <- pull.null.sumy(null_mod, is.gee, is.glmm) + marge_sumy <- pull.marge.sumy(marge_mod, is.gee, is.glmm) # perform slope test - marge_slope_df <- scLANE:::createSlopeTestData(marge.model = marge_mod, - pt = pt[lineage_cells, j, drop = FALSE], - is.gee = is.gee, - is.glmm = is.glmm) + marge_slope_df <- createSlopeTestData(marge.model = marge_mod, + pt = pt[lineage_cells, j, drop = FALSE], + is.gee = is.gee, + is.glmm = is.glmm) marge_slope_df <- dplyr::mutate(marge_slope_df, Gene = genes[i], Lineage = LETTERS[j], .before = 1) # solve values of slopes across pseudotime intervals -- TODO: add support for GLMM backend if (!is.glmm) { - marge_dynamic_df <- scLANE:::summarizeModel(marge.model = marge_mod, + marge_dynamic_df <- summarizeModel(marge.model = marge_mod, pt = pt[lineage_cells, j, drop = FALSE]) marge_dynamic_df <- data.frame(t(unlist(marge_dynamic_df))) %>% dplyr::mutate(Gene = genes[i], diff --git a/R/testSlope.R b/R/testSlope.R index 0544216..c155157 100644 --- a/R/testSlope.R +++ b/R/testSlope.R @@ -15,12 +15,8 @@ #' @seealso \code{\link[stats]{p.adjust}} #' @export #' @examples -#' \dontrun{ -#' testSlope(gene_stats) -#' testSlope(gene_stats, -#' method = "BH", -#' fdr.cutoff = 0.05) -#' } +#' data(scLANE_models) +#' slope_test_res <- testSlope(scLANE_models) testSlope <- function(test.dyn.res = NULL, p.adj.method = "holm", diff --git a/R/theme_scLANE.R b/R/theme_scLANE.R index 9908a11..84a7142 100644 --- a/R/theme_scLANE.R +++ b/R/theme_scLANE.R @@ -11,13 +11,16 @@ #' @return A \code{ggplot2} theme. #' @export #' @examples -#' \dontrun{ -#' plotModels(gene_stats, -#' gene = "CD14", -#' pt = pt_df, -#' expr.mat = count_mat -#' ) + theme_scLANE() -#' } +#' data(sim_counts) +#' data(scLANE_models) +#' data(sim_pseudotime) +#' cell_offset <- createCellOffset(sim_counts) +#' plotModels(scLANE_models, +#' gene = names(scLANE_models)[1], +#' pt = sim_pseudotime, +#' expr.mat = sim_counts, +#' size.factor.offset = cell_offset) + +#' theme_scLANE() theme_scLANE <- function(base.size = 12, base.lwd = 0.75, diff --git a/R/tp1.R b/R/tp1.R index de9b18a..cf1e90b 100644 --- a/R/tp1.R +++ b/R/tp1.R @@ -1,16 +1,18 @@ #' Truncated p-th power function (positive part). #' #' @name tp1 -#' @param x : a vector of predictor variable values. -#' @param t : a specified knot value. -#' @param p : the pth degree of the polynomial considered. -#' @return \code{tp1} returns a vector of values that have been transformed using a truncated p-th power function (positive part) for a specified knot value. +#' @param x A predictor variable value. Defaults to NULL. #' @author Jakub Stoklosa and David I. Warton +#' @param t A specified knot value. Defaults to NULL. +#' @param p The \eqn{p^{th}} degree of the polynomial considered. Defaults to 1. +#' @return A vector of values that have been transformed using a truncated \eqn{p^{th}} power function (positive part) for a specified knot value. #' @references Friedman, J. (1991). Multivariate adaptive regression splines. \emph{The Annals of Statistics}, \strong{19}, 1--67. #' @references Stoklosa, J. and Warton, D.I. (2018). A generalized estimating equation approach to multivariate adaptive regression splines. \emph{Journal of Computational and Graphical Statistics}, \strong{27}, 245--253. #' @seealso \code{\link{tp2}} -tp1 <- function(x, t, p = 1) { +tp1 <- function(x = NULL, + t = NULL, + p = 1) { res <- ((x - t)^p) * (x > t) return(res) } diff --git a/R/tp2.R b/R/tp2.R index 40946ad..cc62dd3 100644 --- a/R/tp2.R +++ b/R/tp2.R @@ -1,16 +1,18 @@ #' Truncated p-th power function (negative part). #' #' @name tp2 -#' @param x : a predictor variable value. -#' @param t : a specified knot value. -#' @param p : the pth degree of the polynomial considered. -#' @return \code{tp2} returns a vector of values that have been transformed using a truncated p-th power function (negative part) for a specified knot value. #' @author Jakub Stoklosa and David I. Warton +#' @param x A predictor variable value. Defaults to NULL. +#' @param t A specified knot value. Defaults to NULL. +#' @param p The \eqn{p^{th}} degree of the polynomial considered. Defaults to 1. +#' @return A vector of values that have been transformed using a truncated \eqn{p^{th}} power function (negative part) for a specified knot value. #' @references Friedman, J. (1991). Multivariate adaptive regression splines. \emph{The Annals of Statistics}, \strong{19}, 1--67. #' @references Stoklosa, J. and Warton, D.I. (2018). A generalized estimating equation approach to multivariate adaptive regression splines. \emph{Journal of Computational and Graphical Statistics}, \strong{27}, 245--253. #' @seealso \code{\link{tp1}} -tp2 <- function(x, t, p = 1) { +tp2 <- function(x = NULL, + t = NULL, + p = 1) { res <- ((t - x)^p) * (x < t) return(res) } diff --git a/man/clusterGenes.Rd b/man/clusterGenes.Rd index a0d770d..67ca7cf 100644 --- a/man/clusterGenes.Rd +++ b/man/clusterGenes.Rd @@ -41,19 +41,12 @@ This function takes as input the output from \code{\link{testDynamic}} and clust } } \examples{ -\dontrun{ -clusterGenes(gene_stats, pt = pt_df) -clusterGenes(gene_stats, - pt = pt_df, - size.factor.offset = createCellOffset(sce_obj), - clust.algo = "kmeans", - use.pca = TRUE, - n.PC = 10, - lineages = "B") -clusterGenes(gene_stats, - pt = pt_df, - lineages = c("A", "C")) -} +data(sim_pseudotime) +data(scLANE_models) +cell_offset <- createCellOffset(sim_counts) +gene_clusters <- clusterGenes(scLANE_models, + pt = sim_pseudotime, + size.factor.offset = cell_offset) } \seealso{ \code{\link{testDynamic}} diff --git a/man/createCellOffset.Rd b/man/createCellOffset.Rd index 0085236..6e72ada 100644 --- a/man/createCellOffset.Rd +++ b/man/createCellOffset.Rd @@ -18,11 +18,8 @@ A named numeric vector containing the computed size factor for each cell. 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. } \examples{ -\dontrun{ -createCellOffset(expr.mat = sce_obj) -createCellOffset(expr.mat = counts(sce_obj)) -createCellOffset(expr.mat = seu_obj, scale.factor = 1e5) -} +data(sim_counts) +cell_offset <- createCellOffset(sim_counts) } \seealso{ \code{\link{testDynamic}} diff --git a/man/createSlopeTestData.Rd b/man/createSlopeTestData.Rd index 530aa85..ce53462 100644 --- a/man/createSlopeTestData.Rd +++ b/man/createSlopeTestData.Rd @@ -26,14 +26,6 @@ A data.frame containing model data. \description{ Creates a data.frame of \code{marge} model breakpoints, \emph{p}-values, and other info. } -\examples{ -\dontrun{ -createSlopeTestData(marge_mod, pt_df) -createSlopeTestData(marge_mod, - pt = pt_df, - is.glmm = TRUE) -} -} \seealso{ \code{\link{marge2}} diff --git a/man/embedGenes.Rd b/man/embedGenes.Rd index cfeb947..2380b47 100644 --- a/man/embedGenes.Rd +++ b/man/embedGenes.Rd @@ -14,7 +14,8 @@ embedGenes( gene.meta.data = NULL, k.param = 20, resolution.param = NULL, - random.seed = 312 + random.seed = 312, + n.cores = 2L ) } \arguments{ @@ -37,6 +38,8 @@ embedGenes( \item{resolution.param}{(Optional) The value of the resolution parameter for the Leiden algorithm. If unspecified, silhouette scoring is used to select an optimal value. Defaults to NULL.} \item{random.seed}{(Optional) The random seed used to control stochasticity in the clustering algorithm. Defaults to 312.} + +\item{n.cores}{(Optional) Integer specifying the number of threads used by \code{\link[uwot]{umap}} and in \code{\link[bluster]{makeSNNGraph}}. Defaults to 2.} } \value{ A data.frame containing embedding coordinates, cluster IDs, and metadata for each gene. @@ -45,11 +48,12 @@ A data.frame containing embedding coordinates, cluster IDs, and metadata for eac Embed genes in dimension-reduced space given a smoothed counts matrix. } \examples{ -\dontrun{ -embedGenes(smoothed_counts$Lineage_A, - pcs.return = 3, - cluster.genes = TRUE) -} +data(sim_pseudotime) +data(scLANE_models) +smoothed_dynamics <- smoothedCountsMatrix(scLANE_models, + pt = sim_pseudotime, + n.cores = 1L) +gene_embed <- embedGenes(smoothed_dynamics$Lineage_A, n.cores = 1L) } \author{ Jack Leary diff --git a/man/enrichDynamicGenes.Rd b/man/enrichDynamicGenes.Rd index 58cefcf..8d3e01e 100644 --- a/man/enrichDynamicGenes.Rd +++ b/man/enrichDynamicGenes.Rd @@ -20,12 +20,9 @@ The output from \code{\link[gprofiler2]{gost}}. This function uses the \code{gprofiler2} package to perform pathway analysis on a set of genes from one or more lineages that were determined to be dynamic with \code{\link{testDynamic}}. } \examples{ -\dontrun{ -enrichDynamicGenes(scLANE.de.res = de_stats) -enrichDynamicGenes(scLANE.de.res = de_stats, - lineage = "B", - species = "mmusculus") -} +data(scLANE_models) +scLANE_de_res <- getResultsDE(scLANE_models) +enr_res <- enrichDynamicGenes(scLANE_de_res) } \seealso{ \code{\link[gprofiler2]{gost}} diff --git a/man/extractBreakpoints.Rd b/man/extractBreakpoints.Rd index 0e1322b..a7ca637 100644 --- a/man/extractBreakpoints.Rd +++ b/man/extractBreakpoints.Rd @@ -18,9 +18,13 @@ A data.frame of breakpoints & their directions. Extracts the breakpoints from a fitted \code{marge} model. Note - this function relies on the name of the pseudotime variable not having any numeric characters in it e.g., "pseudotime" or "PT" would be fine but "pseudotime1" would not. If multiple lineages exist, use letters to denote lineages instead of numbers e.g., "Lineage_A" and "Lineage_B". This is currently handled automatically in \code{\link{testDynamic}}, so don't change anything. } \examples{ -\dontrun{ -extractBreakpoints(model = marge_mod) -} +data(sim_counts) +data(sim_pseudotime) +cell_offset <- createCellOffset(sim_counts) +marge_model <- marge2(sim_pseudotime, + Y = BiocGenerics::counts(sim_counts)[4, ], + Y.offset = cell_offset) +breakpoint_df <- extractBreakpoints(model = marge_model) } \author{ Jack Leary diff --git a/man/figures/README-unnamed-chunk-2-1.png b/man/figures/README-unnamed-chunk-2-1.png index f70fdb387c6fa8ef80cc1065309a5240dfc9686c..32713b6d6f5f4fdd72999880a17c6078a79eedf9 100644 GIT binary patch literal 30842 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 literal 30995 zcmeFZbyQVb^fn9!5EKy<0Vyc~X(gqRkOt{I9Hb>Br9%*;n?rYqARW>u-QC^Y%^}`> zyjQQ>_xs}=-}t^U-Z6gn4;g1{_ugymwPrl?nR71R*D|6QcL?qvARu6fiwVmkARuWY zAb1;!As`^%dn+XL+C)fH$imdZO5xobU42n~bA79~y7Hoe2na6%1C_u= zL`o0&;wp;io^*Q-W@d)nyJCwdF_rK08ehHAFE*Q`4>v7&8Pc{nmGG8|W#J)F^tAU}G^HQ!_C^IuaaH&?lbVjnv*q|5*Oh7O z?P>IoZ}b{b)07~3f;@($f%)Q=<;F%Xo9`~Y7%sgGbU~4{kyMC;3qR_{w{}RIr$>&< zPp%C&@?MJ~ewz9?n){-id|n^n3a6+#AR_cnzXV)0PJBXLp*U7YMz!9Z2;yP;{FR2hL!^y8Csu}HpvDvCRwgoK(m3HM z8(jR%<>3s{w__-+Rn(jhR+7@IhUZVsF|1boy->*8t?Q&0zSJYowPm!@%z){kH$Y{(a>vzDAYoM5y2;grWRlGbOLL zR{UL?)@QaCN9T4b2{CB%VVrpA1Ob#x%B6dPt!^r%)ah7|G8?zx`N>x4iSTyBq`D-6 zrPtvk;ai$~jX2SPZ35rD95!*DX=4kAkYc`d*3eGNx`BM2!a>c34fe^V16NEWd@yO(qGdk23H))%(c% zqv401r0gn=x7Y1AOpbOOIoN@C;Hq0K1r~ZaF1hY_+18upxy8eC{EDxlZc#gDF6^)% z$(S#AQHb;7lYca;a`f6d%CvKpoVXtv%n>uK&J%yezgBK@Z_sM3 zsN>#zz}tk9(%5yshPK58ojdu=w77Sd>XV;tRIXML^<~~Gg&Hj(6gV-z_+cS_b%{6O zkfCp#bnC?hHTQ{n87Jm!E>bVdsDs_zaG_=gA(t=H{#f3gx>08a^kT@f;k$|~K~E0J z#*v1-Ips9MsB?|hHSE&StXVH_Tm|mK|9#8PoBz-6n>|NR z*3h6E8XD^F?ZqN}AmjPx%+Ov?05`DPt}FTm21c$VI(6eC8jIW*9P|XZ1D6!_-w!eh zAXvvoW8eJJ7Wg-b|G%B<|JUFCKka>3_{j(M>#P_U81fLvj(yUPh6YM<@*jH#??A{O zUM3e7%B`=j6ImFmszwXH+E+5Qx_$v1CO7FOnv|CVyBSP*i7!lM(^$Myn;r3_^Zp=#owRraf zLK;|Dsym4{^{o32R(MS+4l$gJ*LlNAb4 zOc2J7Cs5!4)}tyljN9S}ji>z+TP^&_6vQ_&!z(6F!v z6Q96UcH+v)QBSC-*xA-$GuN&I))=~u_~fWJz7J~?gov&k7#Mim-!P)(Bwcc9P=Gb@tpC$K4Pm8u4JWxBvN{a`r9`&>b@h zL8m`oRu7l`o_h?$LVqqxIUswJ?Bpe=e+oYjAbbD4^uIOzLwx=dssA+UKZEjzLJ0h4 zPycf#|C7CGsK=(7u5KE=Mw!&rUa*^(jZKME0+&)0y&8F2TbqaJtrfvPfd+D=FljQ2 zHl1>A2*-@GLSFU0M8#e+q5jr*>HcPMkDYi6C(TXBW#r-B{S%flRxCbHE711XTB&w8 zSS%gU3eU-}J@<0uKOWT$gF+16)@Ul1`-^4l%WY1MV8J#C3Q43#uo9z+t9|j_WiIhkc?VoAp8N6rxtz?*qj*hXApyk%mV~`2ff<;IDZcNt{ecZQwu^H zH;k+h09r9IsK7TOzW3+=XyxTAxpxD!{`b=V*7QG-`a^sE)2RP32Bmi!L0Lh8LIvVd znyXnMPe4GxBP^iuhb#buTs>L|xBFXbEteyu7+$Bc!>tJw*Ykm-_Vc3+qydTUo8HJ? zAbARro{LNU&Ye4pTjeuR=#1Y49y=`F$LDn{2_WWH-mco=<9s*kj{0I1bi;4Y#tT#- zMYEIf@Ms!zMw6Y)xYcb=l*>*#tPscWxm03kkByC4^@-rMX;{=OX_{o?|7par&~!ZR zp%jF}vQIv+v9pguO-xMm7n%c^Ev9*5*v(>zxNKGzgAZ74jEL0_BEF-2baZ6ry}^IA zz@ILg#K&yCEad<=xFvwnsofkc6k<0Ue=<>KhJ87ibaj{&;+=7D!*kcSfkLV4c9r-y zXg|fo#Ml|o@$!NhYfp754*Mnb`_sj#o%LtyJ(vx;Dpa361wN4R{fx`|f#nX#DEdMc za2LPh;i}x(tS9DTl!p1+E9RaXZ~zfG_I3$=y-k^$3Z~H z8L_z&^Es=U*Paj=8~5~<~kG_9xj9cqb1V%lOgs9!2|BbAYc`vrK5`r2_ohm z{x^Gw03yaVI^omq${9l8JnUUsNrGd%wG3!_Sy|bcsQpcDmh@eifDdT2YNytO>A7aD zb4ATVIS$CxGDjVaKQ2Sq+CY}1v~-vF&;i8_k#u*L1@uSi1aY8%&1z9BhTpBW`efRv z>|%+@tuXG{&S+r+qufqT^uI}SY!vkx)Z8=CgZ=&Vf`VSg#uS)4?`}Pk9e)8`-ZwZy zsy|)rus>#)#CCn>|6yO9Zo$V)&Oo=OeV+Q;PEGVL-Q&U zs4}bv^q*R{B`9*jyh<97oHtC|)xfh~rz&kX{?dG=>SqxQ{}$RWa4jF+FHX9YVuXWT zB`jI)Emk;8uRdFjOZB&mw;fiqIvP?bcVwOxz7YusswE2{Zf-!XD?1Z;HSBh#&F~gJ z1q4J)PHK)7yzvZp^qf3`_}}AY0^1Nh92FaD?4NH?!y1b8FS#>=+YMf)BeSwR!0DEXqxhMqGQ15XWW`MfBob{q#Wwx>dY$dRA7_#RLAE5Ejju z46v=4gbW*6+FTt+o+K9t0yp2}aqmuv6G?%W7qZ5Y2p)LwyTY#J%{vfrjNT&*bfDX2 zpXql*k@?)%1Jd5x9(Irqst^bhK&~fFp-Vv%NI1;n8=IOE-nCnIbG9%_y8ZCKxRHi{ z=PLnYV{Brw1nhFer%z~b0XF3vE3lZUMJ@=JJH2UDPX*!DoSj`6&PNH^q?Per~s|gZst_K-qZ^~l&iO1!tD1TT<2`fC6H0ikU zbsw;99gA(@@OX|4Mbz-74hP+_F}k%$&41?0bJ#1y?&WfIwsNeQCK`+jPIdkM0mUw< z;PmuVd1CkCpvONdHI*Fy#k=H-6}PLb#l^*vbK-vqP&H}qHvTiP*Fvz{MHAf_OF1|F$J81 z)#m7P&aIMx+QGB!sj8023Typ?@Ex}qSlV%3;kFu(=4kUkLfxeOL=cqd zdj1w}kVWuTPn$Vv`)EIOJD%MGR||PY4ddfG=&;zl3?9l+f$_D|`b$5!kvsFy#(nYp ztfVg-9-GRms8E+rTKTiGvX08~?=@ogXUUQ{?6*(sij@o6x~J`Qycx=W zeb!TCyP?eKd|D7dz$QT@9jk{F%_uaJD5Ubbv#To-04w#3t8=iRX}ru6=)dNrg=?gO z00Rs$P5G2v+~DA#Sh@MsCZ$iMShLH?l%eN9zT2hA*&L?ZXlD5IL?jeSZBcu+d^-tT zW*T#skbTo@X0% z2T_VcYgjFBBfsuSaxSN0>}&b7@eZa&ooh`=$(J_=J^O#b1&=c1;jbFhmFjr|K3C+0 zD*0M6NzH}l9A@KsI~{hL$PmTc9HI@smcObbvKV`f5$K*iEr2;;Jm&c}#Bz2eKV77c zj+m=N^Op`91=nM`?jkvyOue5t=u)3<>%}Bb||N?uyE+a0sF?rq1ggpB-%U#E}G>XVjQY~ z*1xaf>+rb=oL@f#FvZ$DK|a7)J+16DykXtzcR+Kl`Js1i7(7H|^@pVHrL8~wZ-7kq zYaso7#gXyq#v77FfK0hRef3SGbP56T&u$9FH(lp{uLY3Ae~a*c^&*h=Un|L{@go}> z8>gqFyxc!HxRjfMt{a(}M*R38C@wA@`t92{rkb4|yz|2~in+P(aYrXx6V&TVhoPaN zWTBzoVf<~EuoFoaml|Cu)O$qla?NRfr}9CRSk>3#=n=2+5)3cTkE~92-?VjiZ>Qp( z?v$WnK8{G_bvn=gfiMyg7e^Nv85xvh3q(=O_Pg3GJqv@k;ochs1w}?lw&s^&x>Exs zC5(?>U7~Jba7@mMq0`aQE&`M-)FiLs)pBRdLMx|oz7_*u?~*8NQ7ilD@~h<;zs-U~ zWncgbZ(}H*oEMw&$g=@>)#IK>>=hT-R=NIKe};^rbi%JO1nPk?5Yx6#eH~A>w?_HT zB_$+GJ(~jwS4KI%eEGsP{TAw~+xY2z5NA_MOI67Tu|-t(EGLd)M|(ThG->T`zwu3q z)ZU`g68}lp4LTHg94KHZrEG-#8t*5-bWZ{Xb^VY|aMRc@0LDf`usZk#2t5UgRhFs6 zzWn#v|Kmj+z%H+Qo=cH%msT*&YWaOpD z5D*Zi7Z&yzfAsN@6jt>TekCj}r5C_pDQ6jml|btI+&Apugmlia%Yn&Yk|&aK4k<)W`L!SWFKUZ~5`B4L)c%Hs&#o~-hbE7QTyExp8kuaH z-?eM|&euKx+$k&y{F!x{y7N^=e05f-{wjSj1FOtK@wSM~LDM#|bq0df7r#9n2b@#q z;VQvE^g)r3vL9Ed7Cjy>QaO%Xl&qyWAEhgVURbxR%aoFGk&ky9uXQTv*?S2aJ!b*W zy_tJ}i)*kxNZxOBmByk2FL;}IZ6T2`$UZneRuo%F0IPMCF&sSPf3DWI-{*m8);AJI z;wXcmgXDNG>}BTSVSD8Fw?a=i%nBMsTR5(t{zlUtj6gx7Ej};xt9l2-n!z3Sn3{20 zd*~)#QHR#!Zyh|_oJA8+`|JDprowH74`7MjR0$pu&!EWTqSyxWT|JiPMvQm?rIgB7 z=PPyXt#cIm)0++uuiX6H$|(yYw45(2cuonk z6cvlM7=BgHX{uJC(^;;#z^y$r?F;QIGm1MFJqj65<-!l+QYI#mbsB$8sE%S61vZ-|>-_+8F58v!I) zXw=q4>U%&0Mb5>l=idg988N`MB24PsU}weZCoNfG5|evjrX=CgyAsb?)GWWcusxj~ zz#3yI%wp&w%w=)cH}Kv}t}v9|0V@dAK)0eR(k*2RV^CO^KHAc4s@T}&$EAxkMn6+4 zUeU!*;Ph_dkJbGfj3OdmkOP??bc#sQck3X>?5VO;vt!rXi!k2h2QL+*1V%5LmOfOb zYMc1vJvKs8cK+fZ#ReUHJKDcOV~3kvy5o4nn@};J^sp3=nYZf(A1jls-U}lj~AJX z^tD;k8zyEJCe%*;L-da0IJb*9d392h44B?QVprJFf{of?;}3R|fIvU9J4&?$k;b5? zZlg6PqAl!RNjht%w{4}6-laV@uNqiemHcZh(monFJN(P?^1O!(j_H&c9cr8`i@B5d zR3QoaLJ2OO*T1u(T%-aB8wj{0A_6F^QfvF0m8YK5?-kYcB?f9ln~rPKC`5yaAYU$5 zUt(9^i|v?|&}i}(`&6*A@c~bqifHvx)e$nhH%6Gy249_|TxGiXE}7fH-lF46n*&e4 z`{i5V*Qfj=(aD-dh7`8A@<_$ERnQSHM3;8p?@0z(saOM zkg-i(ZJ0(@5N&HWkzupn^YzBSAa%?S#I328JIMEgt>0gT~SkzM-#6AY8J_Z*wGf?LlOoNCN5S*`JY&iyJvAeOKIAu~S@2 z*;D#hqxQ2x&m4EsHqxX~6o0Pk!rO`L8yuBvyM_~Vd`-w zzeAE^Y7z$r2YHCH1=N0|zIBcdk=U@tr}I6@7}-Gw>g9|#?$l>>!?vr#eE#t;TbBdl^q19GC>hziyR}84$8w)>SLv@*cDh!dpY8}v zq_yl}INEyWe(zR~xi0G=+{}#``=-LNb5!%be_?NjohV<#urju*;O*3L=W%*%40{62 z06s^82ura!q%(6ZS3^%Yo#&*}n%Q9R5k7}OH5iBK74%i`r^24wQnUn)J{C<);+ItZ zj6ta{OS*0~!H_sD zg3pqsbyZ8m;#DO+lT|DC&X)S)G)&8HVO^TJ9`L3fUOlPtVkD#bZu%omTTsc~e`W}e zL(wdx=QuA?u0~YS+4(}nwR_8A5RXHwd{?h+HEQlSv%eO|YeNL?_B?tc33f?Hz?d+1 z%}!xy745P*VY0CA!v#Olf3;0d*nBws{Bj2CSE;C1BCr7qx_KuYE>YLM)x}%HY6;~M z!`raI>4WsCAVMsPp}--#SD&2(F~udNOvWX%ot!ZVOQPrYPD!vTS5y!ao)eE+hcEyh zG|Yl=V#@Vhjwyf1)HL4Nd8Uepzg8KS^{y1B;i7}x{a}0R7~0?CdIRHnF67c3UN+Dt zT%Pn?8$f&c98mZ!rJZ-ur;FCox|nSbS!4L-?pkMqBTy+ zY*vpA45#b??un~6DrN^Ra!iz+5^YhgQ!sHmW60VYgQ_n%IZMSWBjWp~dOx6;exk@k z4|-!3b0g?A3>LdtVRbmsP7LL(?AXmgF&z&f6Q_O*j+|*)iJw_?Sx|d)EI53cJ&peg zu2&@h?5eV!G+$x+-S6am4Rw$6enfTI8jh21c)kSK*5Y-K$Fcn9+(FY~MQ)+3;<@`C zc@KM^Eo;ncHAHs@ynQsGrT0U1t1#24*#%gYDk4W9FtcPQ#d?S83pJir9~TTNX2*mH&iP~5adY8tM%(TxldZcSWf7%?2`*VN1$^da#TF8gu=S}Ws(!*9f_rK?z#Hmm4 z)>Z|qv#5LP-(BGgrNT)hoy9=B6!Dub&ekteix%P#n#qLH#Aa;SV%tC-4a5|V2`#t& zxW5uhxotRld0I^-!1R}?+06q6Xwub)w-R2S;h(s|og9$@&pT=kzkq32&6x0zySu+f zv0-bv;ys^W?l7e*9Pxe*9_Q=n4me{}INV|>(>@(b&7rmP-&zJgboBnYECN^n{?uf* zuYBL@zX1t3l}y#MXqO2k4@E0>Z+^!zz{cnFVd~MCzH}xhKn0N^)+~N=3q~yKWOq~9 zWIG8kV}S*%>H9^NM%o2GpE8ufn~GtdWsTu*_NaJonm8t0{oY-@_3hu5GWo9<2+{dE zP&&WE#bQd=u=56WCJspgX;ZBJ<4CtTB(=^7`qaJQoz2xld!n4Mjj^M=OE9rnlL z8-gAHOVrVqCc0EMVQyVwyU-F01$g?Ei0%{?-7Y4D$*efOIE*AV_=Ixyr%RVIp?T0y zmsf2>#nm;_-0Z0*Vxre4_7VwqW}%Xjl3QaxYoXS^bVO^*B4nc*PY`-54-HJ zE0??&%^-@d^`@t$KcXw7_ICS(ic+*|7_Kjm^D|U*V!?|-96o%yy*A>0(#C}eDf{z4 z0}DMimDIcRDiW8&P#%C}J|-y%im#`LT%VaMEiHu;+v3K?UnpwSfm|D}4@IP#T=wzH z>+NVDgGQ01R^wR8b24eYpGI;i#>~P(%-Le$dO+9*k-3=1t9zI3`t=YXR104A7h=DD z4tfa(SU+Bls}#v@J1;=(W=PDur|t96O{BK@MO?3E>Y%%(7P&?*Ea!!NgM;4-JI>U) z$SW%^i%lsK#DdP_X5J2Dat@!#@?Q=XR=VJ1QD*o@4ctm(%!te=YCtX|_IdxQJB&E@ zX;>DYnz_GL{|hpw)G0&L^JJE-8Gf!}T#1$+AJLckC7Eo~J1}_egQ#gi z?bMUPEK45w1H88cB~3|5gAz0EyoRS>9aA2xqOTD$VNwv!w|ZCHS90wGuB8Mr*6tSp zE6t*Sj>i^~(%`^N#%YGCdpoT9P@=EdA(-#ov^(;rt2M&9X80X5?>q$nuyV*o$Zyh@R+%@BTm*8OiJs=Rt4A*K zTldQx!f`R{mf509V`&+!8#%<2XmAP+d3>AK+2Y_AdrJ*icNx&$N^s?yby<}Q;pvGp zCXKIGX?kU9cVas*F0-Y;Xr!}V0zmwK_nA}B+dd(~R#vYqjucb3F;^PaC8I96s^=wF z;4BvXS|Js6qF6pf@93~N_R*-9yw;t(25q&$yMK)(&`?xN5M zzZ8f61N|o_?7;>?6E9IS_$rkXH4nUM(hI9@TVz{ihdoFlpVA5c2r)>YZ~d#=&zA*QFZ#}Cru~4O6`g8j-h|Rrw14g1e4@H$kR*G6~m~SJ5ZZ;#2b8U%gk#G zRnq%R8W5?6BxLjAY6v*E!x8GrylV{77 z=oHnT2kT1BkW;pID!vjC_Rq7&ziiSq)r+rLQQhGV3igA(ScuTBeh`qtbxvQ^WXm#F z7B_aU2^m~W`BG5o!%hj{ngMTnDhCitqEZkgM{L;8K&{!eZ1)L4FhCv(JVjsSUoO>) z>A;ZXV~vhbiHsBBYwyw#!Lb^Q2p(~zpL;&nPw};CHDj{HI9S})thAW|W(&p=_Ae>K zgw2+a6_pxwv}Kj>zlVg7Gd)%%W2!AlZ92K!(=ok%bjIoy$p6K-;$F>{sfP)chbQ;- z1#|MOV)nKY_igs9#;y)m?1rRjTJoW4yeu^ul?h)vSBEvibiyxO9M|DFYaVz#9N5EeRD>GoihgH-zLY&R{XF>2i&VX^ZJ^nWT%33}aBs9_t^; z4a=^J(9`dX8nnkiL>5$XN5K6;AzKGvWe-y9-gl|czB66)V4%tEY^$R#van)7|8TW0 zNX(1)9yAzzq_wx?%>!cMtya#|_0){QR~MC)d0LKYN-FwH7(-(%J|s@6uY&N&)?(J| zLL<|b`S`)6B8H^4lu{U_=ie@8*)`PHKi^^nyJtX7u9yo}1Qc$uMMm-Um;hqr4n?Va z;;y8k((%6bfcWgJ$BmJblT+(B!{RT38adK^n%Z#ZK1+&taHWuK*!>}m%)8P18Lq2R z@!lm?HO_;Yuhh-A*XZ&YSx$~)xKBG>T=kVQ?8@Yk#+xq*O*t#V%;nm`%F=!4FGno& zbo!p)$MXq$r(-NVE(uS8mp<@N0CmaAKt3C2nhk;%#My06(f|cwi5}?`f6W2#Tip`t zKd9Aha5|#yf%P&5>8s^U{VeWB&FhM$kJ7iMLItCSq9i8kA2}E-D3qP9ubPz6Jeqd; zHi}Wp@~X9!FRjzX5WlwE0iK}ypiG*K2vnKrvb&227vL%PUiqfX{WXw{!0f4h8a{(J zbxnZfR#fT!HtJ4mbhd7Kb!MlzO7eG8**$X&t(imhfiauCU;rj|M0Y-C=CaNWXd~#j z)R*Q0680Y2_tA_HHio~(!AmWM4S>7}>X!@3Oes0gecgb5-ecUI!lkAoCRL&YOF}5y^kx&M8dXecN&wQU_E<0i0_!{Y zSpaaa8}3erGzv$pP)#de+w(SASMo|D)ZgK4o&bOb)Ipj45sfsba^G55-=t@oCsB=h9ay>V>op1#7)I(Iqt7CgV1n zU9)OVUSm$#dE)yV*7UQiz~jL?eFSvH6;8~*>%Z(p1q`d0E04x&-2NWVr6;c_8d5!yTkuVEU-CHCrTvSZ?KG{%w*3OMpYFLd z5LQPNTN$?6V7DJ?vEGCGW}ue=w_f?H`cjYUYrJ2DYQ356x0o3!y`2e+9AAafH7`EQ^;_nM4I-OBPHpo-JJ)I@ zHvU^w06!4s(105)iEC)PE9DH}6hSq>2)3um&itK?pQS@_q&j}cfZat-tYpB}1U68n z-+7%_p=k+?P>O6r-$*Q{~ORd2XLMc9*N!BkDCJ2<;o-YLd*9j!*l!|CaH0 z9s-W?l}0gqt5Rbsl|9~tW(EdQDhisl%a$6<;VfoYu<>Yg{SdW#N$`gO1vyy$)=&5A z;S~4oclsH6W6TuqGr|3?)^i5MBdUoQ1}AmJiX{PE1k`vzRbsd?PR(Hp@|vUAv0ezE z1mMg7Tjih~vR`#|S)|E1H1{?+Tcg%1jr;HmyFSL5V!`OI75c0ua_R~s$3+!m+=?u1 z=V^=%l#nMW03Gd7?S1g~6wu@l!Jl;XlH|%Fl%vK;GvDNvd{JcIo*~unFBe8i;6!zl3+0(z@yff~(AFoRhUGkF z9qF#&OL5qYq1LbBsV(~~AFuO*U)IAwbJIKIyua&1J}8h5OfuOSbgMCQzWG8lAx~2? z?>H9ZTmln1tLwQ`rJ7<<&U2gNQmeB7zq1Qbroj3D>U94&n>?WZ>mwLFJ{6#4^S-7o zhV?{7n?FA;YLs4nAOh|O8oWqK^@Vprt@auz?c55}RawBzK%z45q4urL$Ogf*zcm-Z zBML=+L18K2<-pR!KrO{ejM4+t!$(HLD`>?jn*a||UaZ3p-ork#*`a1osm}rGfir+f z*wXM*|E}WYqQ-jsn9;M7)=!=GONTVV#8bjM!;%#aSA*0YX82LhHKU{|rEDw;8>1V$ z6Fymxxw}K)J@9nYk-zuS15YeKJdEZts~rw+8DCz+-qz<#1tLZXKQ218k{64`%eF6Cl1GHexXI!-+bSBY>{qp zGSvSGJ1zSsC&_{PfUgCqz6&D!dK@AkCl|Wa1uuwltHYFBiTIUl}nE^>21*@P3YAMznqZ+iI%6-W1o0O4-HK zjw>}#wrDNeB9u;vT!4jdRJo?*QCZ0~@vYVcCSjV(Qs+BZ*LYN(3ZSx}m(CY^EkQ%l zO=!qz?pGF7z_}#1?h!q`fB$}v&0M%FsJK-y_%ZJj3W|nMzRjsB6xf^Eo5Qx2xT58 zQB7c)hnK>JB>;D>7I~7_Y9HGAoxIL%<-Hvz?D6gH3paW0*f!CC`gHMdJ)mGCNcABu z?l{7-*plLSraQ|Bcd3Iq-!JO`2&xk3{@i`$CoZ3zbuT!Uio{h~SNYOJ2!wxhMy{XK zIzXkW-ltxyu<(b-9_Ounp|aBY8L-?qMj_eEBhi;ve>jBmK{>@sf@4;RlhbW^1qek? zzKaYllg5)3z5;>7t3~nbFKp1KR;2FrGyp3q6BBahw|>pyp_$wbZx$j~kvfagd~v)H zmL@qCcfCsMcU?Mv-Kxk!XE!oq4!sDwnBAf06-Y)$`G%T{zQ_5?+LO+{^4J`#P0gtO zGD$yPI2>^#FRw-qut=U4J?p4?-60iLOM^L!cZ==e_{&BLAex>t@df@$ig^VH$eV`6 z8{lq5>)>vUs+Tm;kMG4ijKXQ3;lGY!0LY`wfU)^PJn>Yu<3zwzkK@ihXeo%UGm8OKo z&>kO%46yU)F)5j8f4e$&po9-N`HQj~fQ$e#8G|*lM+*{^cDC|?c0M+K!&0kbc?pH=s3_5$w6KYsks6A1R$FMaO6)J~(~OLQlE zxA`6CYptgzHMaRuup!~IzJZZ;YNrw8&m!@+Jn{fPWqbLk7xcH25U4)@W$$G_sO1;D zrL@wX`@J{=$YN!G&5y(z{ul#9McQ9&;&_0o3t@O_Qvi-(CF+53vZSQ>~=7 zIeC?}CenImH^(c4*pcgZd&oCQQgR+a?@UaVI1UK8B$XBwg;Q`?>#kVw_XDkp4U6&) zMQexo;H0yZ+_8hgDgqf3tW|fw(-7Cs|CS~MkjH&El?LRZ+7IJd^arj2i_B-#Y4Yf! za7>a)_3fL{Ds1+b?7~;PqP^-_{fbFvQ4tO5FWkj&eyt_~s2iS@hdXuQ(3ai-xVsf`Q^k0ez+`1)8Gt*o^K*Cp=L99v0)Y7QWwxzn zjhS=;P`L5 zR-XU@%7~ahs{}CsB1F;ys{E4X3e#s2GwDLk>@BUMUTF6XF|gxtFPqlA16Zw z-u!;p3DjoUW(Cmho1LRULJq*=7JHAYbW-zT?K^V#q3F%@QU28Qp>s8&_L%OEQ33(a zW904U{gVs(iC{}8lO@MiGBL_B8co-$0Wk!N6y|=Bx;p7xOsCL3`et66i5&e=jgngR=wUgzM{ z-kKNw-;}|91+XU#KkW$@cIJui+O*En(9(Wqmh2dFa*M!O^Qr&R4@(HNB;BSbuJ?N$ zwl+yYUhzujALHY$;!a3sV!V*fOFTBK^0hY4|DNja0DuJ{c+|ywH0^73l%~>dLI{Z* zKOaXZ4;uLR0g%I#XYGeS3$cMv2QZb$9t8!@)@IV`7=R?&zQddWH;disDw$fvlC%aK z(p~gH!t;Y+-T|8|>s~ttNdG&6Mza?r?KU0f0jiG}P}?y_Nz0b%SLB^@zrE#zrK~k{ zF8Sh(MLu+*Jl+?sTN55Z!>X@rPAL9o7rwnFotnJPSn7-~7KRp&I5pXkj4>pUjKWh^ zIg>}_6J1U$i$4k>P(WK^YMOMwqv)}V1^}lYC+bu78~dTz_zLLRr^EBK9ewL}#!Nw@ znU`^kt%VJMZkL;i`-vCjJY{5mBc&oY*g?RFWh4o>xG1ch-@z=JSBb!fF*;M78S%1J zO20UC4qvU*&%iT~gKrFKG-}8Djp)sqPXSjaIPTwF4xGGaGUfCB@8Ax;mPQYZDupe3 z)qq@x40bbn$GzefRaf!a$?I-;4V&*l=&zWfMACW;#bH#OiKjr6$#?tlpHFAGZ!@qL ztdMGa+4!Qb0WaK$zEy~UvSC(n8K}_}c9InrQ<&fOVb0K>(E}(JL=51EN9Dg9bo>W+ zW&xb3Wmwyu(+=$_vP}| zkpeB1fr#+NVQF5U1$r72tzOOBaJtOm7uA{80jFwZ&-cZq?O%+qn2HBUK8I2>MjX6i zD1y?x@)Gs>th{Oyhk(naD=quaYE%jcK(ltjCtITMD_HaatuFSP$8F;-0mG4I8=LHC zKShcUJ&|kBV7jt++8L$~2cVwQL@JKIa_vB>MbKln;N99tO&!A#hIOZeUzJ|YZQaVS z`METorM}=RT4wP@&q}v;X{IUdV|;EEI5enSMfKqTc4qpKsN?T)Oj0a8kYmLhX>nL; zROPw)n1g+mDS*<10U#4D<%76Y_9v=klyN1Tc4=%nf%DOeiaUQNoP5DjVtf{1n179a>9 z%8B!vV0x{tPRmqtC=aXa^_7i+LjA9JN2}iN$T(NIK(ePHbTL9Ov3B=|WBP()-~BwP zKJl9RYh}IwXb4WHMNa0@>$eZ^=epgx>(1A6ifq>Uk8MvM^05Iu78OUs8nP+g^=?B6 z6u9=N-SEVcyff+yX1bx!lD3llM=s;z4h#pWoePpgH4I;0VIxeC5T7XxGoxhpo!b= z@$?%e1?P(eQ4vWA%`crSIW+5!bq(*vG6IxO&|w8jrDE3;p) zq5!9+5nr-6O_-H`q{@|a0=ffDe;$4K)oC$QRJh?|xEm_amYg7MHbS|MnuSp&0+fk- zGUNZ&HOW#YBth%Hlr0-I5%w_r37{>7Z=~?fKl$6W@aZyD?|#rFdpq~zqqNNTLoWne zsWcIde}q<0S)f5R@3yY``uc|6`#tk9t@Jnavh6t?@B&Fw-$1{}Vk?8uXPGJVoQ#}$ zU6Z4hplCwTkL>@LFw$N>_i5OYMtxdsiWWfewX-MSb4ODHIhQevB-?=%0A$2)X~%YQ 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