diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9da68d6296e4942d9b3f868112baf9a48f606c1a..6215d205134654c365528c5446fb55d191beaaf1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,13 +6,13 @@ - merge_requests - tags script: - - R -e 'devtools::install_deps(quiet = TRUE)' + - R -e 'devtools::install_deps()' - R -e 'devtools::check(error_on = "warning")' -# latest version of the previous major R release -check-previous: - image: rocker/tidyverse:3.5.3 - <<: *check_job_template +# # latest version of the previous major R release +# check-previous: +# image: rocker/tidyverse:3.5.3 +# <<: *check_job_template # latest R release check-latest: diff --git a/DESCRIPTION b/DESCRIPTION index b396809dd5850402898b79c47bdaf32ca5c4391a..f327c51916595e89589a25b0321f3c6b5ad19264 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: stressaddition Type: Package Title: Modeling Tri-Phasic Concentration-Response Relationships -Version: 2.4.0 -Date: 2020-03-13 +Version: 2.5.0 +Date: 2020-03-16 Authors@R: c(person("Sebastian", "Henz", role = c("aut", "cre"), diff --git a/NEWS.md b/NEWS.md index f43297f4ed42b587536adf2677196cefe1837555..1270c2a73ba20c57598ddc4946250979cef79daf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,9 @@ +# stressaddition 2.5.0 + +* Fixed unintended behaviour in `plot_effect()` and `plot_stress()` where supplying an empty vector caused the four standard curves to show. Now setting `which` to an empty vector or `NULL` shows just the axes. The default value is NA. +* Renamed the `mixture_effect` column in the `predict_mixture` output data frame to `effect`. +* Remove the restriction that the concentration vectors in `predict_mixture()` must be the same length. The longer length must be a multiple of the shorter length because the shorter vector gets recycled to the longer length. + # stressaddition 2.4.0 * Improved `plot_effect()` and `plot_stress()`. You can now control whether the observed values (the points) should be plotted using the `which` argument. diff --git a/R/plot_ecxsys.R b/R/plot_ecxsys.R index f1cd7ca72bf0006851b40ea7b726c556ed44e4ee..e3d1f3e4385b1674d2b78e3a915c847d16ecbb36 100644 --- a/R/plot_ecxsys.R +++ b/R/plot_ecxsys.R @@ -31,8 +31,9 @@ #' \code{model$curves} data frame. There is also \code{"effect_tox_observed"} #' and \code{"effect_tox_env_observed"} for the observed effects and #' \code{"sys_tox_observed"} and \code{"sys_tox_env_observed"} for the -#' observed Sys. The default \code{NULL} only plots the most important curves. -#' Use \code{which = "all"} to display all curves. +#' observed Sys. The default \code{NA} only plots the most important curves. +#' Use \code{which = "all"} to display all curves. An empty vector or +#' \code{NULL} creates just the axes. #' #' @param show_legend Should the plot include a legend? Defaults to \code{FALSE} #' because it may cover some parts of the plot depending on the plot size and diff --git a/R/plot_effect.R b/R/plot_effect.R index 0645f032b95d573703537f86a828064c80e33c2e..942b3cc15faa002eeeb07deff1f0b5b49c8dad06 100644 --- a/R/plot_effect.R +++ b/R/plot_effect.R @@ -20,7 +20,7 @@ #' @rdname plot_ecxsys #' @export plot_effect <- function(model, - which = NULL, + which = NA, show_legend = FALSE, xlab = "concentration", ylab = "effect", @@ -32,7 +32,7 @@ plot_effect <- function(model, curve_names[startsWith(curve_names, "effect")], "effect_tox_observed", "effect_tox_env_observed" # the observed points ) - if (is.null(which)) { + if (length(which) == 1 && is.na(which)) { which <- c("effect_tox", "effect_tox_sys", "effect_tox_observed") if (model$with_env) { which <- c(which, "effect_tox_env", "effect_tox_env_sys", @@ -43,12 +43,12 @@ plot_effect <- function(model, stop("'all' must not be combined with other curve names.") } which <- valid_names + } else if (!model$with_env && any(grepl("env", which, fixed = TRUE))) { + warning("'which' contains names with 'env' but the model was built ", + "without environmental effects.") + which <- which[which %in% valid_names] } else if (any(!which %in% valid_names)) { warning("Argument 'which' contains invalid names.") - if (!model$with_env && any(grepl("env", which, fixed = TRUE))) { - warning("'which' contains names with 'env' but the model was", - " built without environmental effects.") - } which <- which[which %in% valid_names] } diff --git a/R/plot_stress.R b/R/plot_stress.R index 296f90a6b181cefe217f02aa56aebacacf4f4751..152b0a3859913d91b7a2455e54d28342b81745ce 100644 --- a/R/plot_stress.R +++ b/R/plot_stress.R @@ -20,7 +20,7 @@ #' @rdname plot_ecxsys #' @export plot_stress <- function(model, - which = NULL, + which = NA, show_legend = FALSE, xlab = "concentration", ylab = "stress", @@ -32,7 +32,7 @@ plot_stress <- function(model, curve_names[startsWith(curve_names, "stress") | startsWith(curve_names, "sys")], "sys_tox_observed", "sys_tox_env_observed" # the observed points ) - if (is.null(which)) { + if (length(which) == 1 && is.na(which)) { which <- c("sys_tox", "sys_tox_observed") if (model$with_env) { which <- c(which, "sys_tox_env", "sys_tox_env_observed") @@ -42,12 +42,12 @@ plot_stress <- function(model, stop("'all' must not be combined with other curve names.") } which <- valid_names + } else if (!model$with_env && any(grepl("env", which, fixed = TRUE))) { + warning("'which' contains names with 'env' but the model was built ", + "without environmental effects.") + which <- which[which %in% valid_names] } else if (any(!which %in% valid_names)) { warning("Argument 'which' contains invalid names.") - if (!model$with_env && any(grepl("env", which, fixed = TRUE))) { - warning("'which' contains names with 'env' but the model was", - " built without environmental effects.") - } which <- which[which %in% valid_names] } diff --git a/R/predict_mixture.R b/R/predict_mixture.R index c79582c6ef3dea42682f09cc94e9dc105fe8fd0f..f4045cb600fa4a5c5754ee30e536e87c958d11c1 100644 --- a/R/predict_mixture.R +++ b/R/predict_mixture.R @@ -31,7 +31,9 @@ #' #' @param model_a,model_b The ecxsys models of the toxicants. #' @param concentration_a,concentration_b The concentrations of the toxicants in -#' the mixture. Both vectors must be the same length. +#' the mixture. Both vectors must either be the same length or the longer +#' length must be a multiple of the shorter length. That's because the shorter +#' concentration vector gets recycled to the length of the longer one. #' @param proportion_ca The proportion of concentration addition in the #' calculation of the toxicant stress of the mixture. Must be between 0 and 1. #' @param effect_max Controls the scaling of the result. This represents the @@ -61,11 +63,11 @@ #' #' # Example of symmetric prediction: #' conc_a <- c(0, 0.03, 0.3, 3) -#' conc_b <- rep(5.5, 4) +#' conc_b <- 5.5 #' prop_ca <- 0.75 -#' effect_a <- predict_mixture(toxicant_a , toxicant_b , conc_a, conc_b, prop_ca) -#' effect_b <- predict_mixture(toxicant_b , toxicant_a , conc_b, conc_a, prop_ca) -#' identical(effect_a$mixture_effect, effect_b$mixture_effect) +#' mix_a <- predict_mixture(toxicant_a , toxicant_b , conc_a, conc_b, prop_ca) +#' mix_b <- predict_mixture(toxicant_b , toxicant_a , conc_b, conc_a, prop_ca) +#' identical(mix_a$effect, mix_b$effect) #' #' @export predict_mixture <- function(model_a, @@ -81,7 +83,6 @@ predict_mixture <- function(model_a, is.numeric(concentration_b), length(concentration_a) > 0, length(concentration_b) > 0, - length(concentration_a) == length(concentration_b), all(!is.na(concentration_a)), all(!is.na(concentration_b)), proportion_ca >= 0, @@ -129,11 +130,11 @@ predict_mixture <- function(model_a, proportion_sam <- 1 - proportion_ca stress_tox_total <- stress_tox_ca * proportion_ca + stress_tox_sam * proportion_sam stress_total <- stress_tox_total + sys_total - mixture_effect <- stress_to_effect(stress_total) * effect_max + effect <- stress_to_effect(stress_total) * effect_max - # unname() to remove the name when concentration_a is a single number. - mixture_effect <- unname(mixture_effect) - data.frame(concentration_a, concentration_b, mixture_effect) + # Setting row.names to NULL to prevent row names when one of the + # concentrations is a single number. + data.frame(concentration_a, concentration_b, effect, row.names = NULL) } diff --git a/man/plot_ecxsys.Rd b/man/plot_ecxsys.Rd index 1c9c32f9517e753c541357bc979485436dd6648a..1b5e970a49e0db13a9298f9c6c4e2c19d0ae5984 100644 --- a/man/plot_ecxsys.Rd +++ b/man/plot_ecxsys.Rd @@ -8,7 +8,7 @@ \usage{ plot_effect( model, - which = NULL, + which = NA, show_legend = FALSE, xlab = "concentration", ylab = "effect", @@ -17,7 +17,7 @@ plot_effect( plot_stress( model, - which = NULL, + which = NA, show_legend = FALSE, xlab = "concentration", ylab = "stress", @@ -31,8 +31,9 @@ plot_stress( \code{model$curves} data frame. There is also \code{"effect_tox_observed"} and \code{"effect_tox_env_observed"} for the observed effects and \code{"sys_tox_observed"} and \code{"sys_tox_env_observed"} for the -observed Sys. The default \code{NULL} only plots the most important curves. -Use \code{which = "all"} to display all curves.} +observed Sys. The default \code{NA} only plots the most important curves. +Use \code{which = "all"} to display all curves. An empty vector or +\code{NULL} creates just the axes.} \item{show_legend}{Should the plot include a legend? Defaults to \code{FALSE} because it may cover some parts of the plot depending on the plot size and diff --git a/man/predict_mixture.Rd b/man/predict_mixture.Rd index 297c291ba1662e2ff5c3320bb3396fed24e650e6..a769976c97c4e4d8a136dcae1042773fd206b513 100644 --- a/man/predict_mixture.Rd +++ b/man/predict_mixture.Rd @@ -17,7 +17,9 @@ predict_mixture( \item{model_a, model_b}{The ecxsys models of the toxicants.} \item{concentration_a, concentration_b}{The concentrations of the toxicants in -the mixture. Both vectors must be the same length.} +the mixture. Both vectors must either be the same length or the longer +length must be a multiple of the shorter length. That's because the shorter +concentration vector gets recycled to the length of the longer one.} \item{proportion_ca}{The proportion of concentration addition in the calculation of the toxicant stress of the mixture. Must be between 0 and 1.} @@ -63,10 +65,10 @@ predict_mixture( # Example of symmetric prediction: conc_a <- c(0, 0.03, 0.3, 3) -conc_b <- rep(5.5, 4) +conc_b <- 5.5 prop_ca <- 0.75 -effect_a <- predict_mixture(toxicant_a , toxicant_b , conc_a, conc_b, prop_ca) -effect_b <- predict_mixture(toxicant_b , toxicant_a , conc_b, conc_a, prop_ca) -identical(effect_a$mixture_effect, effect_b$mixture_effect) +mix_a <- predict_mixture(toxicant_a , toxicant_b , conc_a, conc_b, prop_ca) +mix_b <- predict_mixture(toxicant_b , toxicant_a , conc_b, conc_a, prop_ca) +identical(mix_a$effect, mix_b$effect) } diff --git a/tests/testthat/test-predict_mixture.R b/tests/testthat/test-predict_mixture.R index 2ad99b6f8d49429b6b8943e14ba3e1fbdb410c5e..a1974bbc89b5db3d8ba344366b0968ef83c0df97 100644 --- a/tests/testthat/test-predict_mixture.R +++ b/tests/testthat/test-predict_mixture.R @@ -38,9 +38,9 @@ test_that("results have not changed", { model_a, model_b, c(0, 0.01, 0.1, 1, 7, 15), - rep(5, 6), + 5, 0.3 - )$mixture_effect + )$effect reference <- c(88.574578, 84.361552, 80.633762, 56.730550, 2.882718, 0) expect_equal(new, reference, tolerance = 1e-5) @@ -51,7 +51,7 @@ test_that("results have not changed", { c(0, 0.01, 0.1, 1, 7, 15), c(0, 0.02, 0.2, 2, 14, 30), 0.3 - )$mixture_effect + )$effect reference <- c(88.2698383, 79.9617127, 78.1574808, 65.7999834, 0.3861678, 0) expect_equal(new, reference, tolerance = 1e-5) @@ -63,7 +63,7 @@ test_that("results have not changed", { c(0, 0.02, 0.2, 2, 14, 30), 0.3, 42 - )$mixture_effect + )$effect reference <- c(88.2698383, 79.9617127, 78.1574808, 65.7999834, 0.3861678, 0) * 0.42 expect_equal(new, reference, tolerance = 1e-5) }) @@ -71,10 +71,10 @@ test_that("results have not changed", { test_that("predictions are symmetric", { conc_a <- c(0, 10^seq(log10(0.001), log10(40), length.out = 50)) - conc_b <- rep(3.5, length(conc_a)) + conc_b <- 3.5 prop_ca <- 0.8 - effect_12 <- predict_mixture(model_a, model_b, conc_a, conc_b, prop_ca)$mixture_effect - effect_21 <- predict_mixture(model_b, model_a, conc_b, conc_a, prop_ca)$mixture_effect + effect_12 <- predict_mixture(model_a, model_b, conc_a, conc_b, prop_ca)$effect + effect_21 <- predict_mixture(model_b, model_a, conc_b, conc_a, prop_ca)$effect expect_equal(effect_12, effect_21) })