Diff of /R/create_config.R [000000] .. [dfe06d]

Switch to unified view

a b/R/create_config.R
1
#' Set and check parameter settings of outbreaker
2
#'
3
#' This function defines settings for outbreaker.  It takes a list of named
4
#' items as input, performs various checks, set defaults where arguments are
5
#' missing, and return a correct list of settings. If no input is given, it
6
#' returns the default settings.
7
#'
8
#' Acceptables arguments for ... are:
9
#'
10
#' \describe{
11
#'
12
#' \item{init_tree}{the tree used to initialize the MCMC. Can be either a
13
#' character string indicating how this tree should be computed, or a vector of
14
#' integers corresponding to the tree itself, where the i-th value corresponds
15
#' to the index of the ancestor of 'i' (i.e., \code{init.tree[i]} is the
16
#' ancestor of case \code{i}). Accepted character strings are "seqTrack" (uses
17
#' seqTrack algorithm to generate the initial tree - see function
18
#' \code{seqTrack} in the package \code{adegenet}), "random" (ancestor randomly
19
#' selected from preceding cases), and "star" (all cases coalesce to the first
20
#' case).  Note that for SeqTrack, all cases should have been sequenced.}
21
#'
22
#' \item{init_alpha}{a vector of integers indicating the initial values of
23
#' alpha, where the i-th value indicates the ancestor of case 'i'; defaults to
24
#' \code{NULL}, in which ancestries are defined from \code{init_tree}.}
25
#'
26
#' \item{init_kappa}{a (recycled) vector of integers indicating the initial
27
#' values of kappa; defaults to 1.}
28
#'
29
#' \item{init_t_inf}{a vector of integers indicating the initial values of
30
#' \code{t_inf}, i.e. dates of infection; defaults to \code{NULL}, in which case
31
#' the most likely \code{t_inf} will be determined from the delay to
32
#' reporting/symptoms distribution, and the dates of reporting/symptoms,
33
#' provided in \code{data}.}
34
#'
35
#' \item{init_mu}{initial value for the mutation rates.}
36
#'
37
#' \item{init_pi}{initial value for the reporting probability.}
38
#'
39
#' \item{init_eps}{initial value for the contact reporting coverage.}
40
#'
41
#' \item{init_lambda}{initial value for the non-infectious contact rate.}
42
#'
43
#' \item{n_iter}{an integer indicating the number of iterations in the MCMC,
44
#' including the burnin period.}
45
#'
46
#'
47
#' \item{move_alpha}{a vector of logicals indicating, for each case, if the
48
#' ancestry should be estimated ('moved' in the MCMC), or not, defaulting to
49
#' TRUE; the vector is recycled if needed.}
50
#'
51
#' \item{move_t_inf}{a vector of logicals indicating, for each case, if the
52
#' dates of infection should be estimated ('moved' in the MCMC), or not,
53
#' defaulting to TRUE; the vector is recycled if needed.}
54
#'
55
#' \item{move_mu}{a logical indicating whether the mutation rates
56
#' should be estimated ('moved' in the MCMC), or not, all defaulting to TRUE.}
57
#'
58
#' \item{move_pi}{a logical indicating whether the reporting probability
59
#' should be estimated ('moved' in the MCMC), or not, all defaulting to TRUE.}
60
#'
61
#' \item{move_eps}{a logical indicating whether the contact reporting coverage
62
#' should be estimated ('moved' in the MCMC), or not at all, defaulting to
63
#' TRUE.}
64
#'
65
#' \item{move_lambda}{a logical indicating whether the non-infectious contact
66
#' rate should be estimated ('moved' in the MCMC), or not at all, defaulting to
67
#' TRUE.}
68
#'
69
#' \item{move_kappa}{a logical indicating whether the number of generations
70
#' between two successive cases should be estimated ('moved' in the MCMC), or
71
#' not, all defaulting to TRUE.}
72
#'
73
#' \item{move_pi}{a logical indicating whether the reporting probability
74
#' should be estimated ('moved' in the MCMC), or not, all defaulting to TRUE.}
75
#'
76
#' \item{n_iter}{the number of iterations of the MCMC.}
77
#'
78
#' \item{sample_every}{the frequency at which MCMC samples are retained for the
79
#' output.}
80
#'
81
#' \item{sd_mu}{the standard deviation for the Normal proposal for the mutation
82
#' rates.}
83
#'
84
#' \item{sd_pi}{the standard deviation for the Normal proposal for the reporting
85
#' probability.}
86
#'
87
#' \item{sd_eps}{the standard deviation for the Normal proposal for the
88
#' contact reporting coverage.}
89
#'
90
#' \item{sd_lambda}{the standard deviation for the Normal proposal for the
91
#' non-infectious contact rate.}
92
#'
93
#' \item{prop_alpha_move}{the proportion of ancestries to move at each iteration
94
#' of the MCMC.}
95
#'
96
#' \item{prop_t_inf_move}{the proportion of infection dates to move at each
97
#' iteration of the MCMC.}
98
99
#' \item{batch_size}{the size of the batch of random number pre-generated.}
100
#'
101
#' \item{paranoid}{a logical indicating if the paranoid mode should be used;
102
#' this mode is used for performing additional tests during outbreaker; it makes
103
#' computations substantially slower and is mostly used for debugging purposes.}
104
#'
105
#' \item{min_date}{earliest infection date possible, expressed as days since the
106
#' first sampling.}
107
#'
108
#' \item{max_kappa}{an integer indicating the largest number of generations
109
#' between any two linked cases; defaults to 5.}
110
#'
111
#' \item{prior_mu}{a numeric value indicating the rate of the exponential prior
112
#' for the mutation rate 'mu'.}
113
#'
114
#' \item{prior_pi}{a numeric vector of length 2 indicating the first and second
115
#' parameter of the beta prior for the reporting probability 'pi'.}
116
#'
117
#' \item{prior_eps}{a numeric vector of length 2 indicating the first and second
118
#' parameter of the beta prior for the contact reporting coverage 'eps'.}
119
#'
120
#' \item{prior_lambda}{a numeric vector of length 2 indicating the first and
121
#' second parameter of the beta prior for the non-infectious contact rate
122
#' 'lambda'.}
123
#'
124
#' \item{ctd_directed}{a logical indicating if the contact tracing data is
125
#' directed or not. If yes, the first column represents the infector and the
126
#' second column the infectee. If ctd is provided as an epicontacts objects,
127
#' directionality will be taken from there.}
128
#'
129
#' \item{pb}{a logical indicating if a progress bar should be displayed.}
130
#'
131
#' }
132
#'
133
#' @param data an optional list of data items as returned by
134
#'     \code{outbreaker_data}; if provided, this allows for further checks of
135
#'     the outbreaker settings.
136
#'
137
#' @seealso \code{\link{outbreaker_data}} to check and process data for outbreaker.
138
#'
139
#' @author Thibaut Jombart (\email{thibautjombart@@gmail.com}).
140
#'
141
#' @export
142
#'
143
#' @examples
144
#' ## see default settings
145
#' create_config()
146
#'
147
#' ## change defaults
148
#' create_config(move_alpha = FALSE, n_iter = 2e5, sample_every = 1000)
149
#'
150
#'
151
#'
152
create_config <- function(..., data = NULL) {
153
154
  ## This function returns a list of configuration settings of the class
155
  ## 'outbreaker_config'. Arguments are passed through '...' as a list. If the
156
  ## list contains a single item which is already an outbreaker_config object,
157
  ## this one is still processed. This means all the checks are repeated, and
158
  ## the config is matched against data if data are provided. This should in
159
  ## principle allow using the same config object for several datasets. It
160
  ## also implicitely serves as a checking procedure for existing configs.
161
162
163
  config <- list(...)
164
  if (length(config) == 1L && is.list(config[[1]])) {
165
    config <- config[[1]]
166
  }
167
168
  ## SET DEFAULTS
169
  defaults <- list(init_tree = c("seqTrack","star","random"),
170
                   init_mu = 1e-4,
171
                   init_alpha = NULL,
172
                   init_kappa = 1,
173
                   init_t_inf = NULL,
174
                   init_pi = 0.9,
175
                   init_eps = 0.5,
176
                   init_lambda = 0.05,
177
                   move_alpha = TRUE, move_swap_cases = TRUE,
178
                   move_t_inf = TRUE,
179
                   move_mu = TRUE, move_kappa = TRUE, move_pi = TRUE,
180
                   move_eps = TRUE, move_lambda = TRUE,
181
                   n_iter = 1e4, sample_every = 50,
182
                   sd_mu = 0.0001, sd_pi = 0.1,
183
                   sd_eps = 0.1, sd_lambda = 0.05,
184
                   prop_alpha_move = 1/4,
185
                   prop_t_inf_move = 0.2,
186
                   paranoid = FALSE,
187
                   min_date = -10,
188
                   max_kappa = 5,
189
                   find_import = TRUE,
190
                   outlier_threshold = 5,
191
                   n_iter_import = 5000,
192
                   sample_every_import = 50,
193
                   prior_mu = 1,
194
                   prior_pi = c(10,1),
195
                   prior_eps = c(1,1),
196
                   prior_lambda = c(1,1),
197
                   ctd_directed = FALSE,
198
                   pb = FALSE)
199
200
  ## MODIFY CONFIG WITH ARGUMENTS ##
201
  config <- modify_defaults(defaults, config)
202
203
  ## CHECK CONFIG ##
204
  ## check init_tree
205
  if (is.character(config$init_tree)) {
206
    config$init_tree <- match.arg(config$init_tree, c("seqTrack","star","random"))
207
  }
208
  if (is.numeric(config$init_tree)) {
209
    config$init_alpha <- as.integer(config$init_tree)
210
  }
211
212
  ## check / process init_t_inf
213
  if (!is.null(config$init_t_inf)) {
214
    if (inherits(config$init_t_inf, "Date")) {
215
      config$init_t_inf <- config$init_t_inf - min(config$init_t_inf)
216
    }
217
    if (inherits(config$init_t_inf, "POSIXct")) {
218
      config$init_t_inf <- difftime(config$init_t_inf,
219
                                    min(config$init_t_inf),
220
                                    units = "days")
221
    }
222
    config$init_t_inf <- as.integer(round(config$init_t_inf))
223
  }
224
225
  ## check init_mu
226
  if (!is.numeric(config$init_mu)) {
227
    stop("init_mu is not a numeric value")
228
  }
229
  if (config$init_mu < 0) {
230
    stop("init_mu is negative")
231
  }
232
  if (config$init_mu > 1) {
233
    stop("init_mu is greater than 1")
234
  }
235
  if (!is.finite(config$init_mu)) {
236
    stop("init_mu is infinite or NA")
237
  }
238
239
  ## check init_kappa
240
  if (!is.null(config$init_alpha)) {
241
    are_not_imports <- !is.na(config$init_alpha)
242
  } else {
243
    are_not_imports <- TRUE
244
  }
245
  if (!is.numeric(config$init_kappa)) {
246
    stop("init_kappa is not a numeric value")
247
  }
248
  config$init_kappa <- as.integer(round(config$init_kappa))
249
  if (any(config$init_kappa < 1, na.rm = TRUE)) {
250
    stop("init_kappa has values smaller than 1")
251
  }
252
  if (any(config$init_kappa > config$max_kappa, na.rm = TRUE)) {
253
    config$init_kappa[config$init_kappa > config$max_kappa] <- config$max_kappa
254
    warning("values of init_kappa greater than max_kappa have been set to max_kappa")
255
  }
256
257
258
  ## check init_pi
259
  if (!is.numeric(config$init_pi)) {
260
    stop("init_pi is not a numeric value")
261
  }
262
  if (config$init_pi < 0) {
263
    stop("init_pi is negative")
264
  }
265
  if (config$init_pi > 1) {
266
    stop("init_pi is greater than 1")
267
  }
268
  if (!is.finite(config$init_pi)) {
269
    stop("init_pi is infinite or NA")
270
  }
271
272
273
  ## check init_eps
274
  if (!is.numeric(config$init_eps)) {
275
    stop("init_eps is not a numeric value")
276
  }
277
  if (config$init_eps < 0) {
278
    stop("init_eps is negative")
279
  }
280
  if (config$init_eps > 1) {
281
    stop("init_eps is greater than 1")
282
  }
283
  if (!is.finite(config$init_eps)) {
284
    stop("init_eps is infinite or NA")
285
  }
286
287
288
  ## check init_lambda
289
  if (!is.numeric(config$init_lambda)) {
290
    stop("init_lambda is not a numeric value")
291
  }
292
  if (config$init_lambda < 0) {
293
    stop("init_lambda is negative")
294
  }
295
  if (config$init_lambda > 1) {
296
    stop("init_lambda is greater than 1")
297
  }
298
  if (!is.finite(config$init_lambda)) {
299
    stop("init_lambda is infinite or NA")
300
  }
301
302
303
  ## check move_alpha
304
  if (!all(is.logical(config$move_alpha))) {
305
    stop("move_alpha is not a logical")
306
  }
307
  if (any(is.na(config$move_alpha))) {
308
    stop("move_alpha is NA")
309
  }
310
311
  ## check move_swap_cases
312
  if (!is.logical(config$move_swap_cases)) {
313
    stop("move_swap_cases is not a logical")
314
  }
315
  if (is.na(config$move_swap_cases)) {
316
    stop("move_swap_cases is NA")
317
  }
318
319
  ## check move_t_inf
320
  if (!is.logical(config$move_t_inf)) {
321
    stop("move_t_inf is not a logical")
322
  }
323
  if (any(is.na(config$move_t_inf))) {
324
    stop("move_t_inf has NAs")
325
  }
326
327
  ## check move_mu
328
  if (!is.logical(config$move_mu)) {
329
    stop("move_mu is not a logical")
330
  }
331
  if (is.na(config$move_mu)) {
332
    stop("move_mu is NA")
333
  }
334
335
  ## check move_kappa
336
  if (!is.logical(config$move_kappa)) {
337
    stop("move_kappa is not a logical")
338
  }
339
  if (any(is.na(config$move_kappa))) {
340
    stop("move_kappa has NA")
341
  }
342
343
  ## check move_pi
344
  if (!is.logical(config$move_pi)) {
345
    stop("move_pi is not a logical")
346
  }
347
  if (is.na(config$move_pi)) {
348
    stop("move_pi is NA")
349
  }
350
351
  ## check move_eps
352
  if (!is.logical(config$move_eps)) {
353
    stop("move_eps is not a logical")
354
  }
355
  if (is.na(config$move_eps)) {
356
    stop("move_eps is NA")
357
  }
358
359
  ## check move_lambda
360
  if (!is.logical(config$move_lambda)) {
361
    stop("move_lambda is not a logical")
362
  }
363
  if (is.na(config$move_lambda)) {
364
    stop("move_lambda is NA")
365
  }
366
367
  ## check n_iter
368
  if (!is.numeric(config$n_iter)) {
369
    stop("n_iter is not a numeric value")
370
  }
371
  if (config$n_iter < 2 ) {
372
    stop("n_iter is smaller than 2")
373
  }
374
  if (!is.finite(config$n_iter)) {
375
    stop("n_iter is infinite or NA")
376
  }
377
378
379
  ## check sample_every
380
  if (!is.numeric(config$sample_every)) {
381
    stop("sample_every is not a numeric value")
382
  }
383
  if (config$sample_every < 1 ) {
384
    stop("sample_every is smaller than 1")
385
  }
386
  if (!is.finite(config$sample_every)) {
387
    stop("sample_every is infinite or NA")
388
  }
389
  config$sample_every <- as.integer(config$sample_every)
390
391
  ## check sd_mu
392
  if (!is.numeric(config$sd_mu)) {
393
    stop("sd_mu is not a numeric value")
394
  }
395
  if (config$sd_mu < 1e-10) {
396
    stop("sd_mu is close to zero or negative")
397
  }
398
  if (!is.finite(config$sd_mu)) {
399
    stop("sd_mu is infinite or NA")
400
  }
401
402
  ## check sd_pi
403
  if (!is.numeric(config$sd_pi)) {
404
    stop("sd_pi is not a numeric value")
405
  }
406
  if (config$sd_pi < 1e-10) {
407
    stop("sd_pi is close to zero or negative")
408
  }
409
  if (!is.finite(config$sd_pi)) {
410
    stop("sd_pi is infinite or NA")
411
  }
412
413
  ## check sd_eps
414
  if (!is.numeric(config$sd_eps)) {
415
    stop("sd_eps is not a numeric value")
416
  }
417
  if (config$sd_eps < 1e-10) {
418
    stop("sd_eps is close to zero or negative")
419
  }
420
  if (!is.finite(config$sd_eps)) {
421
    stop("sd_eps is infinite or NA")
422
  }
423
424
  ## check sd_lambda
425
  if (!is.numeric(config$sd_lambda)) {
426
    stop("sd_lambda is not a numeric value")
427
  }
428
  if (config$sd_lambda < 1e-10) {
429
    stop("sd_lambda is close to zero or negative")
430
  }
431
  if (!is.finite(config$sd_lambda)) {
432
    stop("sd_lambda is infinite or NA")
433
  }
434
435
  ## check prop_alpha_move
436
  if (!is.numeric(config$prop_alpha_move)) {
437
    stop("prop_alpha_move is not a numeric value")
438
  }
439
  if (config$prop_alpha_move < 0 ) {
440
    stop("prop_alpha_move is negative")
441
  }
442
  if (config$prop_alpha_move > 1 ) {
443
    stop("prop_alpha_move is greater than one")
444
  }
445
  if (!is.finite(config$prop_alpha_move)) {
446
    stop("prop_alpha_move is infinite or NA")
447
  }
448
449
  ## check prop_t_inf_move
450
  if (!is.numeric(config$prop_t_inf_move)) {
451
    stop("prop_t_inf_move is not a numeric value")
452
  }
453
  if (config$prop_t_inf_move < 0 ) {
454
    stop("prop_t_inf_move is negative")
455
  }
456
  if (config$prop_t_inf_move > 1 ) {
457
    stop("prop_t_inf_move is greater than one")
458
  }
459
  if (!is.finite(config$prop_t_inf_move)) {
460
    stop("prop_t_inf_move is infinite or NA")
461
  }
462
463
464
  ## check paranoid
465
  if (!is.logical(config$paranoid)) {
466
    stop("paranoid is not logical")
467
  }
468
  if (length(config$paranoid) != 1L) {
469
    stop("paranoid should be a single logical value")
470
  }
471
  if (is.na(config$paranoid)) {
472
    stop("paranoid is NA")
473
  }
474
475
  ## check min_date
476
  if (!is.numeric(config$min_date)) {
477
    stop("min_date is not numeric")
478
  }
479
  if (config$min_date >= 0) {
480
    stop("min_date is greater or equal to 0")
481
  }
482
  if (!is.finite(config$min_date)) {
483
    stop("min_date is infinite or NA")
484
  }
485
486
  ## check find_import
487
  if (!is.logical(config$find_import)) {
488
    stop("find_import is not logical")
489
  }
490
  if (length(config$find_import) != 1L) {
491
    stop("find_import should be a single logical value")
492
  }
493
  if (is.na(config$find_import)) {
494
    stop("find_import is NA")
495
  }
496
497
  ## check outlier_threshold
498
  if (!is.numeric(config$outlier_threshold)) {
499
    stop("outlier_threshold is not a numeric value")
500
  }
501
  if (any(config$outlier_threshold < 1)) {
502
    stop("outlier_threshold has values smaller than 1")
503
  }
504
  if (!is.finite(config$outlier_threshold)) {
505
    stop("outlier_threshold is infinite or NA")
506
  }
507
508
  ## check n_iter_import
509
  if (!is.numeric(config$n_iter_import)) {
510
    stop("n_iter_import is not a numeric value")
511
  }
512
  if (config$n_iter_import < 1000) {
513
    stop("n_iter is smaller than 1000")
514
  }
515
  if (!is.finite(config$n_iter_import)) {
516
    stop("n_iter_import is infinite or NA")
517
  }
518
  config$n_iter_import <- as.integer(config$n_iter_import)
519
520
  ## check sample_every_import
521
  if (!is.numeric(config$sample_every_import)) {
522
    stop("sample_every_import is not a numeric value")
523
  }
524
  if (config$sample_every_import < 1) {
525
    stop("sample_every_import is smaller than 1")
526
  }
527
  if (!is.finite(config$sample_every_import)) {
528
    stop("sample_every_import is infinite or NA")
529
  }
530
  config$sample_every_import <- as.integer(config$sample_every_import)
531
532
  ## check prior value for mu
533
  if (!is.numeric(config$prior_mu)) {
534
    stop("prior_mu is not a numeric value")
535
  }
536
  if (config$prior_mu < 0) {
537
    stop("prior_mu is negative (it should be a rate)")
538
  }
539
  if (!is.finite(config$prior_mu)) {
540
    stop("prior_mu is infinite or NA")
541
  }
542
543
  ## check prior value for pi
544
  if (!all(is.numeric(config$prior_pi))) {
545
    stop("prior_pi has non-numeric values")
546
  }
547
  if (any(config$prior_pi < 0)) {
548
    stop("prior_pi has negative values")
549
  }
550
  if (length(config$prior_pi)!=2L) {
551
    stop("prior_pi should be a vector of length 2")
552
  }
553
  if (!all(is.finite(config$prior_pi))) {
554
    stop("prior_pi is has values which are infinite or NA")
555
  }
556
557
  ## check prior value for eps
558
  if (!all(is.numeric(config$prior_eps))) {
559
    stop("prior_eps has non-numeric values")
560
  }
561
  if (any(config$prior_eps < 0)) {
562
    stop("prior_eps has negative values")
563
  }
564
  if (length(config$prior_eps)!=2L) {
565
    stop("prior_eps should be a vector of length 2")
566
  }
567
  if (!all(is.finite(config$prior_eps))) {
568
    stop("prior_eps is has values which are infinite or NA")
569
  }
570
571
572
  ## check prior value for lambda
573
  if (!all(is.numeric(config$prior_lambda))) {
574
    stop("prior_lambda has non-numeric values")
575
  }
576
  if (any(config$prior_lambda < 0)) {
577
    stop("prior_lambda has negative values")
578
  }
579
  if (length(config$prior_lambda)!=2L) {
580
    stop("prior_lambda should be a vector of length 2")
581
  }
582
  if (!all(is.finite(config$prior_lambda))) {
583
    stop("prior_lambda is has values which are infinite or NA")
584
  }
585
586
587
  if (!is.logical(config$pb)) {
588
    stop("pb must be a logical")
589
  }
590
591
  ## CHECKS POSSIBLE IF DATA IS PROVIDED ##
592
  if (!is.null(data)) {
593
    ## check initial tree
594
    if (is.character(config$init_tree)) {
595
      if (config$init_tree=="seqTrack" &&
596
          is.null(data$dna)) {
597
        msg <- paste0("Can't use seqTrack initialization with missing ",
598
                      "DNA sequences; using a star-like tree")
599
        message(msg)
600
        config$init_tree <- "star"
601
      }
602
603
      ## check initial tree
604
      if (config$init_tree=="seqTrack" &&
605
          nrow(data$dna) != data$N) {
606
        msg <- sprintf(paste("Can't use seqTrack initialization when",
607
                             "numbers of sequences and cases differ",
608
                             "(%d vs %d)"), nrow(data$dna), data$N)
609
        message(msg)
610
        config$init_tree <- "star"
611
      }
612
613
      ## seqTrack init
614
      if (config$init_tree=="seqTrack") {
615
        D_temp <- data$D
616
        ## use strictly positive serial interval for starting tree
617
        can_be_ances_tmp <- outer(data$dates, data$dates, FUN = "<")
618
        diag(can_be_ances_tmp) <- FALSE
619
        D_temp[!can_be_ances_tmp] <- 1e30
620
        config$init_alpha <- apply(D_temp,2,which.min)
621
        config$init_alpha[data$dates==min(data$dates)] <- NA
622
        config$init_alpha <- as.integer(config$init_alpha)
623
      } else if (config$init_tree=="star") {
624
        config$init_alpha <- rep(which.min(data$dates), length(data$dates))
625
        config$init_alpha[data$dates==min(data$dates)] <- NA
626
      } else if (config$init_tree=="random") {
627
        config$init_alpha <- ralpha(data$dates)
628
      }
629
    } else { ## if ancestries are provided
630
      if (length(config$init_alpha) != data$N) {
631
        stop("inconvenient length for init_alpha")
632
      }
633
      unknownAnces <- config$init_alpha<1 | config$init_alpha>data$N
634
      if (any(stats::na.omit(unknownAnces))) {
635
        warning("some initial ancestries refer to unknown cases (idx<1 or >N)")
636
        config$init_alpha[unknownAnces] <- NA
637
      }
638
    }
639
640
    ## check initial t_inf
641
    if (!is.null(config$init_t_inf)) {
642
      if (any(config$init_t_inf >= data$dates, na.rm = TRUE)) {
643
        msg <- paste0("Initial dates of infection come after ",
644
                      "sampling dates / dates of onset.")
645
        stop(msg)
646
      }
647
    } else {
648
      ## set to most likely delay if t_inf not set
649
      max_like_delay <- which.max(data$f_dens)
650
      if (!is.finite(max_like_delay)) {
651
        max_like_delay <- 1L
652
      }
653
      config$init_t_inf <- as.integer(data$dates - max_like_delay)
654
    }
655
656
    ## recycle move_alpha
657
    config$move_alpha <- rep(config$move_alpha, length.out = data$N)
658
659
    ## recycle move_t_inf
660
    config$move_t_inf <- rep(config$move_t_inf, length.out = data$N)
661
662
    ## recycle move_kappa
663
    config$move_kappa <- rep(config$move_kappa, length.out = data$N)
664
665
    ## recycle init_kappa
666
    config$init_kappa <- rep(config$init_kappa, length.out = data$N)
667
    config$init_kappa[is.na(config$init_alpha)] <- NA
668
669
    ## disable moves for imported cases
670
    config$move_alpha[is.na(config$init_alpha)] <- FALSE
671
    config$move_kappa[is.na(config$init_alpha)] <- FALSE
672
673
    ## disable moves for mu if no DNA sequences
674
    if(is.null(data$D) || nrow(data$D)<1) {
675
      config$move_mu <- FALSE
676
    }
677
678
    ## disable moves for eps and lambda if no CTD is provided
679
    if(is.null(data$contacts) || nrow(data$contacts) < 1) {
680
      config$move_eps <- config$move_lambda <- FALSE
681
    } else {
682
      if(inherits(data$ctd, "epicontacts")) {
683
        config$ctd_directed <- data$ctd$directed
684
      }
685
    }
686
687
  }
688
689
  ## output is a list of checked settings with a dedicated class (for
690
  ## printing)
691
692
  class(config) <- c("outbreaker_config", "list")
693
  return(config)
694
}
695
696
697
698
699
700
701
#' @rdname create_config
702
#'
703
#' @export
704
#'
705
#' @aliases print.outbreaker_config
706
#'
707
#' @param x an \code{outbreaker_config} object as returned by \code{create_config}.
708
#'
709
#' @param ... further arguments to be passed to other methods.
710
711
print.outbreaker_config <- function(x, ...) {
712
  cat("\n\n ///// outbreaker settings ///\n")
713
  cat("\nclass:", class(x))
714
  cat("\nnumber of items:", length(x))
715
716
  cat("\n\n/// initialisation //\n")
717
  to_print <- grep("init", names(x))
718
  print(noquote(unlist(x[to_print])))
719
  x <- x[-to_print]
720
721
  cat("\n/// movements //\n")
722
  to_print <- unlist(sapply(c("move", "^sd"), grep, names(x)))
723
  print(noquote(sapply(x[to_print], as.character)))
724
  x <- x[-to_print]
725
726
  cat("\n/// chains //\n")
727
  to_print <- c("n_iter", "sample_every")
728
  print(noquote(sapply(x[to_print], as.character)))
729
  x <- x[-match(to_print, names(x))]
730
731
  cat("\n/// priors //\n")
732
  to_print <- grep("prior", names(x))
733
  print(noquote(unlist(x[to_print])))
734
  x <- x[-to_print]
735
736
  cat("\n/// imported cases //\n")
737
  to_print <- unlist(sapply(c("import", "threshold"), grep, names(x)))
738
  print(noquote(sapply(x[to_print], as.character)))
739
  x <- x[-to_print]
740
741
  if(length(x)>0){
742
    cat("\n/// other settings //\n")
743
    print(noquote(sapply(x, as.character)))
744
  }
745
746
  return(invisible(NULL))
747
}