From aae77a9cea765e50a19651a8b3ae4f9dcbb74529 Mon Sep 17 00:00:00 2001 From: Luke Zappia <lazappi@users.noreply.github.com> Date: Wed, 4 Oct 2017 12:36:34 +1100 Subject: [PATCH] Add PhenoParams --- DESCRIPTION | 3 +- R/AllClasses.R | 40 ++++++++++++++++ R/PhenoParams-methods.R | 79 +++++++++++++++++++++++++++++++ tests/testthat/test-PhenoParams.R | 15 ++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 R/PhenoParams-methods.R create mode 100644 tests/testthat/test-PhenoParams.R diff --git a/DESCRIPTION b/DESCRIPTION index 3717687..4be8b4b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -52,7 +52,8 @@ Suggests: S4Vectors, scDD, scran, - mfa + mfa, + phenopath biocViews: SingleCell, RNASeq, Transcriptomics, GeneExpression, Sequencing, Software URL: https://github.com/Oshlack/splatter diff --git a/R/AllClasses.R b/R/AllClasses.R index 536efce..e9a131c 100644 --- a/R/AllClasses.R +++ b/R/AllClasses.R @@ -500,3 +500,43 @@ setClass("MFAParams", dropout.lambda = "numeric"), prototype = prototype(trans.prop = 0, zero.neg = TRUE, dropout.present = FALSE, dropout.lambda = 1)) + + +#' The PhenoParams class +#' +#' S4 class that holds parameters for the PhenoPath simulation. +#' +#' @section Parameters: +#' +#' The PhenoPath simulation uses the following parameters: +#' +#' \describe{ +#' \item{\code{nGenes}}{The number of genes to simulate.} +#' \item{\code{nCells}}{The number of cells to simulate.} +#' \item{\code{[seed]}}{Seed to use for generating random numbers.} +#' \item{\code{[n.de]}}{Number of genes to simulate from the differential +#' expression regime} +#' \item{\code{[n.pst]}}{Number of genes to simulate from the pseudotime +#' regime} +#' \item{\code{[n.pst.beta]}}{Number of genes to simulate from the +#' pseudotime + beta interactions regime} +#' \item{\code{[n.de.pst.beta]}}{Number of genes to simulate from the +#' differential expression + pseudotime + interactions regime} +#' } +#' +#' The parameters not shown in brackets can be estimated from real data using +#' \code{\link{phenoEstimate}}. For details of the PhenoPath simulation +#' see \code{\link{phenoSimulate}}. +#' +#' @name PhenoParams +#' @rdname PhenoParams +#' @aliases PhenoParams-class +#' @exportClass PhenoParams +setClass("PhenoParams", + contains = "Params", + slots = c(n.de = "numeric", + n.pst = "numeric", + n.pst.beta = "numeric", + n.de.pst.beta = "numeric"), + prototype = prototype(n.de = 2500, n.pst = 2500, n.pst.beta = 2500, + n.de.pst.beta = 2500)) diff --git a/R/PhenoParams-methods.R b/R/PhenoParams-methods.R new file mode 100644 index 0000000..2151c52 --- /dev/null +++ b/R/PhenoParams-methods.R @@ -0,0 +1,79 @@ +#' @rdname newParams +#' @importFrom methods new +#' @export +newPhenoParams <- function(...) { + + if (!requireNamespace("phenopath", quietly = TRUE)) { + stop("The PhenoPath simulation requires the 'phenopath' package.") + } + + params <- new("PhenoParams") + params <- setParams(params, ...) + + return(params) +} + +setValidity("PhenoParams", function(object) { + + v <- getParams(object, slotNames(object)) + + checks <- c(nGenes = checkmate::checkInt(v$nGenes, lower = 1), + nCells = checkmate::checkInt(v$nCells, lower = 1), + n.de = checkmate::checkInt(v$n.de, lower = 0), + n.pst = checkmate::checkInt(v$n.pst, lower = 0), + n.pst.beta = checkmate::checkInt(v$n.pst.beta, lower = 0), + n.de.pst.beta = checkmate::checkInt(v$n.de.pst.beta, lower = 0), + seed = checkmate::checkInt(v$seed, lower = 0)) + + if (v$nGenes != (v$n.de + v$n.pst + v$n.pst.beta + v$n.de.pst.beta)) { + checks <- c(checks, + nGenes = paste("nGenes is not consistent with", + "n.de, n.pst, n.pst.beta, n.de.pst.beta")) + } + + if (all(checks == TRUE)) { + valid <- TRUE + } else { + valid <- checks[checks != TRUE] + valid <- paste(names(valid), valid, sep = ": ") + } + + return(valid) +}) + +#' @rdname setParam +setMethod("setParam", "PhenoParams", function(object, name, value) { + checkmate::assertString(name) + + if (name == "nGenes") { + stop(name, " cannot be set directly, set n.de, n.pst, n.pst.beta or ", + "n.de.pst.beta instead") + } + + nNames <- c("n.de", "n.pst", "n.pst.beta", "n.de.pst.beta") + if (name %in% nNames) { + checkmate::assertInt(value, lower = 0) + total <- value + for (nName in nNames) { + if (nName != name) { + total <- total + getParam(object, nName) + } + } + object <- setParamUnchecked(object, "nGenes", total) + } + + object <- callNextMethod() + + return(object) +}) + +setMethod("show", "PhenoParams", function(object) { + + pp <- list("Genes:" = c("[DE]" = "n.de", + "[PST]" = "n.pst", + "[PST + Beta]" = "n.pst.beta", + "[DE + PST + Beta]" = "n.de.pst.beta")) + + callNextMethod() + showPP(object, pp) +}) diff --git a/tests/testthat/test-PhenoParams.R b/tests/testthat/test-PhenoParams.R new file mode 100644 index 0000000..535724a --- /dev/null +++ b/tests/testthat/test-PhenoParams.R @@ -0,0 +1,15 @@ +context("PhenoParams") + +test_that("constructor is valid", { + expect_true(validObject(newSCDDParams())) +}) + +test_that("nGenes checks work", { + params <- newPhenoParams() + expect_error(setParam(params, "nGenes", 1), + "nGenes cannot be set directly") + params <- setParam(params, "n.de", 0) + total <- getParam(params, "n.de") + getParam(params, "n.pst") + + getParam(params, "n.pst.beta") + getParam(params, "n.de.pst.beta") + expect_equal(getParam(params, "nGenes"), total) +}) -- GitLab