Skip to content

Commit 065a8d3

Browse files
committed
More work on and testing off extension mechanism. Updated docs.
1 parent 167da31 commit 065a8d3

File tree

174 files changed

+882
-4531
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+882
-4531
lines changed

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ LinkingTo: Rcpp
4040
Depends:
4141
R (>= 3.1)
4242
Suggests:
43-
testthat,
43+
testthat (>= 2.1.0),
4444
vdiffr,
4545
roxygen2,
4646
knitr,

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export(plotlyYield)
130130
export(plotlyYieldGear)
131131
export(power_law_pred_kernel)
132132
export(project)
133+
export(removeComponent)
133134
export(retune_erepro)
134135
export(setColours)
135136
export(setComponent)

R/extension.R

+110-38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#' Set own rate function to replace mizer rate function
22
#'
3+
#' If the way mizer calculates a fundamental rate entering the model is
4+
#' not flexible enough for you (for example if you need to introduce time
5+
#' dependence) then you can write your own functions for calculating that
6+
#' rate and use `setRateFunction()` to register it with mizer.
7+
#'
38
#' At each time step during a simulation with the [project()] function, mizer
49
#' needs to calculate the instantaneous values of the various rates. By
510
#' default it calls the [mizerRates()] function which creates a list with the
@@ -17,24 +22,36 @@
1722
#' * `rdi` from [mizerRDI()]
1823
#' * `rdd` from [BevertonHoltRDD()]
1924
#'
20-
#' You can modify these in two ways.
25+
#' For each of these you can substitute your own function. So for example if
26+
#' you have written your own function for calculating the total mortality
27+
#' rate and have called it `myMort` and have a mizer model stored in a
28+
#' MizerParams object called `params` that you want to run with your new
29+
#' mortality rate, then you would call
30+
#' ```
31+
#' params <- setRateFunction(params, "Mort", "myMort")
32+
#' ```
33+
#' In some extreme cases you may need to swap out the entire `mizerRates()`
34+
#' function for your own function called `myRates()`. That you can do with
35+
#' ```
36+
#' params <- setRateFunction(params, "Rates", "myRates")
37+
#' ```
2138
#'
22-
#' @param params A `MizerParams` object
39+
#' @param params A MizerParams object
2340
#' @param rate Name of the rate for which a new function is to be set.
2441
#' @param fun Name of the function to use to calculate the rate.
42+
#' @return For `setRateFunction()`: An updated MizerParams object
2543
#' @export
26-
setRateFunction <- function(params, rate = "Rates", fun) {
44+
setRateFunction <- function(params, rate, fun) {
2745
assert_that(is(params, "MizerParams"),
2846
is.string(rate),
29-
is.string(fun),
30-
is.function(get(fun)))
47+
is.string(fun))
3148
if (!(rate %in% names(params@rates_funcs))) {
3249
stop("The `rate` argument must be one of ",
3350
toString(names(params@rates_funcs)), ".")
3451
}
35-
f <- get0(fun, mode = "function")
36-
if (is.null(f)) {
37-
stop(fun, " should be a function")
52+
if (!exists(fun, mode = "function")) {
53+
stop("`fun` should be a function, ",
54+
fun, " is of class ", class(fun), ".")
3855
}
3956
# TODO: put some code to test that the function has the right kind of
4057
# arguments
@@ -45,12 +62,15 @@ setRateFunction <- function(params, rate = "Rates", fun) {
4562
}
4663

4764
#' @rdname setRateFunction
65+
#' @return For `getRateFunction()`: The name of the registered rate function for
66+
#' the requested `rate`, or the list of all rate functions if called without
67+
#' `rate` argument.
4868
#' @export
49-
getRateFunction <- function(params, rate = "Rates") {
69+
getRateFunction <- function(params, rate) {
5070
assert_that(is(params, "MizerParams"),
5171
is.string(rate))
5272
validObject(params)
53-
if (rate == "All") {
73+
if (missing(rate)) {
5474
return(params@rates_funcs)
5575
}
5676
if (!(rate %in% names(params@rates_funcs))) {
@@ -62,58 +82,101 @@ getRateFunction <- function(params, rate = "Rates") {
6282

6383
#' Add a dynamical ecosystem component
6484
#'
85+
#' By default, mizer models any number of size-resolved consumer species
86+
#' and a single size-resolved plankton spectrum. Your model may require
87+
#' additional components, like for example detritus or carrion or multiple
88+
#' resources or .... This function allows you to set up such components.
89+
#'
90+
#' If you set a component with a new name, the new component will be added
91+
#' to the existing components. If you set a component with an existing name,
92+
#' that component will be overwritten. You can remove a component with
93+
#' `removeComponent()`.
94+
#'
6595
#' @param params A MizerParams object
6696
#' @param component Name of the component
6797
#' @param initial_value Initial value of the component
6898
#' @param dynamics_fun Name of function to calculate value at the next time step
6999
#' @param encounter_fun Name of function to calculate contribution to encounter
70-
#' rate
71-
#' @param pred_mort_fun Name of function to calculate contribution to the
72-
#' predation mortality rate.
100+
#' rate. Optional.
101+
#' @param mort_fun Name of function to calculate contribution to the
102+
#' mortality rate. Optional.
73103
#' @param component_params Named list of parameters needed by the component
74-
#' functions.
75-
#' @return For `setComponent`: The updated MizerParams object
104+
#' functions. Optional.
105+
#' @return The updated MizerParams object
76106
#' @export
77107
setComponent <- function(params, component, initial_value,
78-
encounter_fun, pred_mort_fun,
79-
dynamics_fun, component_params) {
108+
dynamics_fun,
109+
encounter_fun, mort_fun,
110+
component_params) {
80111
assert_that(is(params, "MizerParams"),
81112
is.string(component),
82113
is.string(dynamics_fun),
83-
is.string(encounter_fun),
84-
is.string(mortality_fun),
85-
is.function(get0(dynamics_fun)),
86-
is.function(get0(encounter_fun)),
87-
is.function(get0(mortality_fun)),
88-
is.list(component_params))
114+
is.function(get0(dynamics_fun)))
89115
params@other_dynamics[[component]] <- dynamics_fun
90-
params@other_pred_mort[[component]] <- pred_mort_fun
91-
params@other_encounter[[component]] <- encounter_fun
92-
params@other_params[[component]] <- component_params
93-
initialNOther(params)[[component]] <- initial_value
116+
params@initial_n_other[[component]] <- initial_value
117+
# TODO: Add checks that the functions have the right arguments and
118+
# return values
119+
if (!missing(mort_fun)) {
120+
if (!is.null(mort_fun) && !is.function(get0(mort_fun))) {
121+
stop("`mort_fun` needs to be NULL or a function.")
122+
}
123+
params@other_mort[[component]] <- mort_fun
124+
}
125+
if (!missing(encounter_fun)) {
126+
if (!is.null(encounter_fun) && !is.function(get0(encounter_fun))) {
127+
stop("`encounter_fun` needs to be NULL or a function.")
128+
}
129+
params@other_encounter[[component]] <- encounter_fun
130+
}
131+
if (!missing(component_params)) {
132+
if (!is.null(component_params) &&
133+
(!is.list(component_params) || is.null(names(component_params)))) {
134+
stop("`component_params` needs to be NULL or a named list.")
135+
}
136+
params@other_params[[component]] <- component_params
137+
}
138+
params
94139
}
95140

141+
#' @rdname setComponent
142+
#' @export
143+
removeComponent <- function(params, component) {
144+
if (!component %in% names(params@other_dynamics)) {
145+
stop("There is no component named ", component)
146+
}
147+
params@other_dynamics[[component]] <- NULL
148+
params@other_encounter[[component]] <- NULL
149+
params@other_mort[[component]] <- NULL
150+
params@other_params[[component]] <- NULL
151+
params@initial_n_other[[component]] <- NULL
152+
params
153+
}
154+
155+
96156
#' Get information about other ecosystem components
97157
#'
98158
#' @param params A MizerParams object
99159
#' @param component Name of the component of interest. If missing, a list of
100160
#' all components will be returned.
101-
#' @return For `getComponent`: A list with the entries `initial_value`, `dynamics_fun`,
102-
#' `encounter_fun`, `morality_fun`, `component_params`. If `component` is
161+
#' @return A list with the entries `initial_value`, `dynamics_fun`,
162+
#' `encounter_fun`, `mort_fun`, `component_params`. If `component` is
103163
#' missing, then a list of lists for all components is returned.
104-
#' @rdname setComponent
105164
#' @export
106165
getComponent <- function(params, component) {
107166
if (missing(component)) {
108-
lapply(names(params@other_dynamics),
109-
function(x) getComponent(params, x))
167+
l <- lapply(names(params@other_dynamics),
168+
function(x) getComponent(params, x))
169+
names(l) <- names(params@other_dynamics)
170+
return(l)
171+
}
172+
if (!component %in% names(params@other_dynamics)) {
173+
stop("There is no component named ", component)
110174
}
111-
comp_list <- list(
112-
initial_value = initialNOther(params)[[component]],
113-
component_params = params@other_params[[component]],
114-
dynamics_fun = params@other_dynamics[[component]],
115-
mortality_fun = params@other_mort[[component]],
116-
encounter_fun = params@other_encounter[[component]]
175+
list(initial_value = initialNOther(params)[[component]],
176+
dynamics_fun = params@other_dynamics[[component]],
177+
mort_fun = params@other_mort[[component]],
178+
encounter_fun = params@other_encounter[[component]],
179+
component_params = params@other_params[[component]]
117180
)
118181
}
119182

@@ -128,6 +191,15 @@ getComponent <- function(params, component) {
128191
`initialNOther<-` <- function(params, value) {
129192
assert_that(is(params, "MizerParams"),
130193
is.list(value))
194+
components <- names(params@other_dynamics)
195+
missing <- !(names(value) %in% components)
196+
if (any(missing)) {
197+
stop("The following components do not exist: ", names(value)[missing])
198+
}
199+
extra <- !(components %in% names(value))
200+
if (any(extra)) {
201+
stop("Missing values for components ", components[extra])
202+
}
131203
params@initial_n_other <- value
132204
params
133205
}

R/project_methods.R

+5-5
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ mizerEncounter <- function(params, n, n_pp, n_other, ...) {
236236
encounter <- encounter +
237237
do.call(fun_name,
238238
list(params = params,
239-
n = n, n_pp = n_pp, n_other = n_other))
239+
n = n, n_pp = n_pp, n_other = n_other, ...))
240240
}
241241

242242
return(encounter)
@@ -444,15 +444,15 @@ mizerFMort <- function(params, effort, ...) {
444444
#' @export
445445
#' @family mizer rate functions
446446
mizerMort <- function(params, n, n_pp, n_other, f_mort, pred_mort, ...){
447-
pred_mort <- pred_mort + params@mu_b + f_mort
447+
mort <- pred_mort + params@mu_b + f_mort
448448
# Add contributions from other components
449449
for (fun_name in params@other_mort) {
450-
pred_mort <- pred_mort +
450+
mort <- mort +
451451
do.call(fun_name,
452452
list(params = params,
453-
n = n, n_pp = n_pp, n_other = n_other))
453+
n = n, n_pp = n_pp, n_other = n_other, ...))
454454
}
455-
return(pred_mort)
455+
return(mort)
456456
}
457457

458458

R/rate_functions.R

+4-9
Original file line numberDiff line numberDiff line change
@@ -567,15 +567,10 @@ getMort <- function(params,
567567
nrow(params@species_params), ") x no. size bins (",
568568
length(params@w), ")")
569569
}
570-
571-
z <- pred_mort + params@mu_b + f_mort
572-
# Add contributions from other components
573-
for (fun_name in params@other_mort) {
574-
z <- z +
575-
do.call(fun_name,
576-
list(params = params,
577-
n = n, n_pp = n_pp, n_other = n_other))
578-
}
570+
571+
f <- get(params@rates_funcs$Mort)
572+
z <- f(params, n = n, n_pp = n_pp, n_other = n_other,
573+
f_mort = f_mort, pred_mort = pred_mort)
579574
dimnames(z) <- list(prey = dimnames(params@initial_n)$sp,
580575
w_prey = dimnames(params@initial_n)$w)
581576
return(z)

R/setFishing.R

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ getInitialEffort <- function(params) {
237237
#' @param gear_params Gear parameter data frame
238238
#' @param species_params Species parameter data frame
239239
#' @return A valid gear parameter data frame
240+
#' @concept helper
240241
validGearParams <- function(gear_params, species_params) {
241242
assert_that(is.data.frame(gear_params),
242243
is.data.frame(species_params))

R/species_params.R

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ get_ks_default <- function(params) {
223223
#'
224224
#' @param species_params The user-supplied species parameter data frame
225225
#' @return A valid species parameter data frame
226+
#' @concept("helper")
226227
validSpeciesParams <- function(species_params) {
227228
assert_that(is.data.frame(species_params))
228229

Loading
Loading

0 commit comments

Comments
 (0)