|
a |
|
b/R/custom_moves.R |
|
|
1 |
|
|
|
2 |
|
|
|
3 |
#' Customise samplers for outbreaker |
|
|
4 |
#' |
|
|
5 |
#' This function is used to specify customised movement functions |
|
|
6 |
#' (a.k.a. samplers) for outbreaker. Custom functions are specified as a named |
|
|
7 |
#' list or series of comma-separated, named arguments, indicating which type of |
|
|
8 |
#' movement they implement. Values currently available are: |
|
|
9 |
#' |
|
|
10 |
#' \itemize{ |
|
|
11 |
#' |
|
|
12 |
#' \item \code{mu}: movement of the mutation rate; by default, the function |
|
|
13 |
#' \code{cpp_move_mu} is used. |
|
|
14 |
#' |
|
|
15 |
#' \item \code{pi}: movement of the reporting probability; by default, the function |
|
|
16 |
#' \code{cpp_move_pi} is used. |
|
|
17 |
#' |
|
|
18 |
#' \item \code{eps}: movement of the contact reporting coverage; by default, the |
|
|
19 |
#' function \code{cpp_move_eps} is used. |
|
|
20 |
#' |
|
|
21 |
#' \item \code{lambda}: the movement of the non-infectious contact rate; the |
|
|
22 |
#' function \code{cpp_move_lambda} is used. |
|
|
23 |
#' |
|
|
24 |
#' \item \code{alpha}: movement of the transmission tree, by randomly proposing |
|
|
25 |
#' infectors in the pool of cases infected before; by default, the function |
|
|
26 |
#' \code{cpp_move_alpha} is used. |
|
|
27 |
#' |
|
|
28 |
#' \item \code{swap_cases}: movement of the transmission tree, by swapping |
|
|
29 |
#' infectors and infected cases; by default, the function |
|
|
30 |
#' \code{cpp_move_swap_cases} is used. |
|
|
31 |
#' |
|
|
32 |
#' \item \code{t_inf}: movement of the date of infection; by default, the |
|
|
33 |
#' function \code{cpp_move_t_inf} is used. |
|
|
34 |
#' |
|
|
35 |
#' \item \code{kappa}: movement of the number generations between cases; by |
|
|
36 |
#' default, the function \code{cpp_move_kappa} is used. |
|
|
37 |
#' |
|
|
38 |
#' } |
|
|
39 |
#' |
|
|
40 |
#' |
|
|
41 |
#' Movement functions must have an argument \code{param}, which is a list of |
|
|
42 |
#' parameters and augmented data of the class \code{\link{create_param}}. |
|
|
43 |
#' Each movement function will be enclosed with its other arguments, so that the |
|
|
44 |
#' resulting function will have a single argument 'param'. For non-standard |
|
|
45 |
#' movements (i.e. none of the names specified above), the closure will contain: |
|
|
46 |
#' |
|
|
47 |
#' \itemize{ |
|
|
48 |
#' |
|
|
49 |
#' \item \code{data}: a list of named items containing input data as returned by |
|
|
50 |
#' \code{\link{outbreaker_data}}. |
|
|
51 |
#' |
|
|
52 |
#' \item \code{config}: a list of named items containing input data as returned by |
|
|
53 |
#' \code{\link{create_config}}. |
|
|
54 |
#' |
|
|
55 |
#' \item \code{likelihoods}: a list of named custom likelihood functions as returned by |
|
|
56 |
#' \code{\link{custom_likelihoods}}. |
|
|
57 |
#' |
|
|
58 |
#' \item \code{priors}: a list of named custom prior functions as returned by |
|
|
59 |
#' \code{\link{custom_priors}}. |
|
|
60 |
#' |
|
|
61 |
#' } |
|
|
62 |
#' |
|
|
63 |
#' @author Thibaut Jombart (\email{thibautjombart@@gmail.com}). |
|
|
64 |
#' |
|
|
65 |
#' @seealso See \href{http://www.repidemicsconsortium.org/outbreaker2/articles/customisation.html#customising-movements}{customization vignette} for detailed examples on how to customise movement functions. |
|
|
66 |
#' |
|
|
67 |
#' @export |
|
|
68 |
#' |
|
|
69 |
#' @param ... A list or a series of named, comma-separated functions |
|
|
70 |
#' implementing movements of parameters or augmented data. |
|
|
71 |
#' |
|
|
72 |
#' @return A list of movement functions with a single argument 'param', with |
|
|
73 |
#' class \code{outbreaker_moves}. |
|
|
74 |
|
|
|
75 |
custom_moves <- function(...) { |
|
|
76 |
|
|
|
77 |
move_functions <- list(...) |
|
|
78 |
|
|
|
79 |
if (length(move_functions) == 1L && is.list(move_functions[[1]])) { |
|
|
80 |
move_functions <- move_functions[[1]] |
|
|
81 |
} |
|
|
82 |
|
|
|
83 |
|
|
|
84 |
defaults <- list(mu = cpp_move_mu, |
|
|
85 |
pi = cpp_move_pi, |
|
|
86 |
eps = cpp_move_eps, |
|
|
87 |
lambda = cpp_move_lambda, |
|
|
88 |
alpha = cpp_move_alpha, |
|
|
89 |
swap_cases = cpp_move_swap_cases, |
|
|
90 |
t_inf = cpp_move_t_inf, |
|
|
91 |
kappa = cpp_move_kappa |
|
|
92 |
) |
|
|
93 |
|
|
|
94 |
|
|
|
95 |
moves <- modify_defaults(defaults, move_functions, FALSE) |
|
|
96 |
moves_names <- names(moves) |
|
|
97 |
|
|
|
98 |
|
|
|
99 |
|
|
|
100 |
## check all moves are functions |
|
|
101 |
|
|
|
102 |
function_or_null <- function(x) { |
|
|
103 |
is.null(x) || is.function(x) |
|
|
104 |
} |
|
|
105 |
|
|
|
106 |
is_ok <- vapply(moves, function_or_null, logical(1)) |
|
|
107 |
|
|
|
108 |
if (!all(is_ok)) { |
|
|
109 |
culprits <- moves_names[!is_ok] |
|
|
110 |
msg <- paste0("The following moves are not functions: ", |
|
|
111 |
paste(culprits, collapse = ", ")) |
|
|
112 |
stop(msg) |
|
|
113 |
} |
|
|
114 |
|
|
|
115 |
|
|
|
116 |
## check they all have a 'param' argument |
|
|
117 |
|
|
|
118 |
param_is_arg <- function(x) { |
|
|
119 |
if(is.function(x)) { |
|
|
120 |
return ("param" %in% methods::formalArgs(x)) |
|
|
121 |
} |
|
|
122 |
|
|
|
123 |
return(TRUE) |
|
|
124 |
} |
|
|
125 |
|
|
|
126 |
param_ok <- vapply(moves, param_is_arg, logical(1)) |
|
|
127 |
|
|
|
128 |
if (!all(param_ok)) { |
|
|
129 |
culprits <- moves_names[!param_ok] |
|
|
130 |
msg <- paste0("The following moves dont' have a 'param' argument: ", |
|
|
131 |
paste(culprits, collapse = ", ")) |
|
|
132 |
stop(msg) |
|
|
133 |
} |
|
|
134 |
|
|
|
135 |
|
|
|
136 |
class(moves) <- c("outbreaker_moves", "list") |
|
|
137 |
return(moves) |
|
|
138 |
} |
|
|
139 |
|
|
|
140 |
|
|
|
141 |
|
|
|
142 |
|
|
|
143 |
|
|
|
144 |
#' @rdname custom_moves |
|
|
145 |
#' |
|
|
146 |
#' @export |
|
|
147 |
#' |
|
|
148 |
#' @aliases print.outbreaker_moves |
|
|
149 |
#' |
|
|
150 |
#' @param x an \code{outbreaker_moves} object as returned by \code{create_moves}. |
|
|
151 |
#' |
|
|
152 |
|
|
|
153 |
print.outbreaker_moves <- function(x, ...) { |
|
|
154 |
cat("\n\n ///// outbreaker movement functions ///\n") |
|
|
155 |
cat("\nclass:", class(x)) |
|
|
156 |
cat("\nnumber of items:", length(x)) |
|
|
157 |
|
|
|
158 |
cat("\n\n/// movement functions //\n") |
|
|
159 |
print(x[]) |
|
|
160 |
|
|
|
161 |
|
|
|
162 |
## is_custom <- !vapply(x, is.null, FALSE) |
|
|
163 |
|
|
|
164 |
## names_default <- names(x)[!is_custom] |
|
|
165 |
## if (length(names_default) > 0) { |
|
|
166 |
## cat("/// custom priors set to NULL (default used) //\n") |
|
|
167 |
## print(x[!is_custom]) |
|
|
168 |
## } |
|
|
169 |
|
|
|
170 |
|
|
|
171 |
## names_custom <- names(x)[is_custom] |
|
|
172 |
## if (length(names_custom) > 0) { |
|
|
173 |
## cat("/// custom priors //\n") |
|
|
174 |
## print(x[is_custom]) |
|
|
175 |
## } |
|
|
176 |
|
|
|
177 |
return(invisible(NULL)) |
|
|
178 |
} |
|
|
179 |
|