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)
 })