From 65058422de43212e493288a4775bcac831cd5e8e Mon Sep 17 00:00:00 2001
From: cazodi <cazodi@svi.edu.au>
Date: Tue, 24 Mar 2020 12:29:23 +1100
Subject: [PATCH] update description and namespace

---
 DESCRIPTION                     |   98 +-
 NAMESPACE                       |  175 ----
 R/data.R                        |   76 --
 R/epi-functions.R               | 1524 +++++++++++++++++++++++++++++++
 R/results-parse.R               |   40 +
 R/sirPlus-functions.R           |  956 +++++++++++++++++++
 R/sirPlus-package.R             |    9 +
 R/utils.R                       |   84 +-
 man/arrivals.FUN.Rd             |   23 +
 man/control.icm.Rd              |   39 +
 man/cum_discr_si.Rd             |   21 +
 man/departures.FUN.Rd           |   20 +
 man/get_prev.FUN.Rd             |   20 +
 man/get_times.Rd                |   17 +
 man/icm.seiqhrf.Rd              |   21 +
 man/infection.FUN.Rd            |   19 +
 man/infection.seiqhrf.icm.Rd    |   19 +
 man/init_status.icm.Rd          |   17 +
 man/initialize.FUN.Rd           |   21 +
 man/merge.seiqhrf.icm.Rd        |   19 +
 man/progress.seiqhrf.icm.Rd     |   19 +
 man/saveout.seiqhrf.icm.Rd      |   21 +
 man/set.control.Rd              |   54 ++
 man/set.init.Rd                 |   47 +
 man/set.param.Rd                |  175 ++++
 man/sirPlus.Rd                  |   10 +
 vignettes/epimodels-SEIQHRF.Rmd |  133 +++
 27 files changed, 3300 insertions(+), 377 deletions(-)
 create mode 100644 R/epi-functions.R
 create mode 100644 R/results-parse.R
 create mode 100644 R/sirPlus-functions.R
 create mode 100644 R/sirPlus-package.R
 create mode 100644 man/arrivals.FUN.Rd
 create mode 100644 man/control.icm.Rd
 create mode 100644 man/cum_discr_si.Rd
 create mode 100644 man/departures.FUN.Rd
 create mode 100644 man/get_prev.FUN.Rd
 create mode 100644 man/get_times.Rd
 create mode 100644 man/icm.seiqhrf.Rd
 create mode 100644 man/infection.FUN.Rd
 create mode 100644 man/infection.seiqhrf.icm.Rd
 create mode 100644 man/init_status.icm.Rd
 create mode 100644 man/initialize.FUN.Rd
 create mode 100644 man/merge.seiqhrf.icm.Rd
 create mode 100644 man/progress.seiqhrf.icm.Rd
 create mode 100644 man/saveout.seiqhrf.icm.Rd
 create mode 100644 man/set.control.Rd
 create mode 100644 man/set.init.Rd
 create mode 100644 man/set.param.Rd
 create mode 100644 man/sirPlus.Rd
 create mode 100644 vignettes/epimodels-SEIQHRF.Rmd

diff --git a/DESCRIPTION b/DESCRIPTION
index d252d16..f8c1412 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,76 +1,52 @@
-Package: splatter
+Package: sirPLUS
 Type: Package
-Title: Simple Simulation of Single-cell RNA Sequencing Data
-Version: 1.11.1
-Date: 2020-01-30
+Title: Using stochastic individual compartment models (ICMs) to simulate COVID-19 spread
+Version: 1.0
+Date: 2020-03-23
 Authors@R:
-    c(person("Luke", "Zappia", role = c("aut", "cre"),
-      email = "luke@lazappi.id.au",
-      comment = c(ORCID = "0000-0001-7744-8565")),
-      person("Belinda", "Phipson", role = c("aut"),
-      email = "belinda.phipson@mcri.edu.au",
-      comment = c(ORCID = "0000-0002-1711-7454")),
-      person("Alicia", "Oshlack", role = c("aut"),
-      email = "alicia.oshlack@mcri.edu.au",
-      comment = c(ORCID = "0000-0001-9788-5690")))
-Description: Splatter is a package for the simulation of single-cell RNA
-    sequencing count data. It provides a simple interface for creating complex
-    simulations that are reproducible and well-documented. Parameters can be
-    estimated from real data and functions are provided for comparing real and
-    simulated datasets.
+    c(person("Christina", "Azodi", role = c("aut"),
+      email = "cazodi@svi.edu.au",
+      comment = c(ORCID = "0000-0002-6097-606X")),
+      person("Puxue", "Qiao", role = c("aut"),
+      email = "pqiao@svi.edu.au"),
+      person("Ruqian", "Lyu", role = c("aut"),
+      email = "rlyu@svi.edu.au"),
+      person("Davis", "McCarthy", role = c("aut", "cre"),
+      email = "dmccarthy@svi.edu.au",
+      comment = c(ORCID = "0000-0002-2218-6833")))
+Description: sirPlus is a package for the modeling of COVID-19 spread using 
+    stochastic individual compartment models (ICMs). It provides a simple interface
+    for creating experiments to demonstrate how factors like social-distancing and
+    epidemeological parameters will change the curve. 
 License: GPL-3 + file LICENSE
 LazyData: TRUE
 Depends:
-    R (>= 3.6),
-    SingleCellExperiment
+    R (>= 3.6)
 Imports:
-    akima,
-    BiocGenerics,
-    BiocParallel,
-    checkmate,
-    edgeR,
-    dplyr,
-    data.table,
-    fitdistrplus,
+    tidyverse,
+    magrittr,
+    lubridate,
+    stringr,
+    tibble,
+    broom,
     ggplot2,
-    locfit,
-    matrixStats,
-    methods,
-    scales,
-    scater, 
-    stats,
-    SummarizedExperiment,
-    utils,
-    crayon,
-    S4Vectors,
-    rlang
-Suggests:
-    BiocStyle,
-    covr,
-    cowplot,
+    gt,
     knitr,
+    devtools,
+    DiagrammeR,
+    parallel,
+    foreach,
+    tictoc,
+    EpiModel,
+    incidence,
+    earlyR
+Suggests:
     magick,
-    limSolve,
-    lme4,
-    progress,
-    pscl,
     testthat,
     rmarkdown,
-    scDD,
-    scran,
-    mfa,
-    phenopath,
-    BASiCS (>= 1.7.10),
-    zinbwave,
-    SparseDC,
     BiocManager,
-    spelling,
-    igraph,
-    DropletUtils
-biocViews: SingleCell, RNASeq, Transcriptomics, GeneExpression, Sequencing,
-    Software, ImmunoOncology
-URL: https://github.com/Oshlack/splatter
-BugReports: https://github.com/Oshlack/splatter/issues
+    spelling
+biocViews: Epidemiology, Software
 RoxygenNote: 7.0.2
 VignetteBuilder: knitr
 Encoding: UTF-8
diff --git a/NAMESPACE b/NAMESPACE
index 758ebc8..1feab89 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,178 +1,3 @@
 # Generated by roxygen2: do not edit by hand
 
-S3method(BASiCSEstimate,SingleCellExperiment)
-S3method(BASiCSEstimate,matrix)
-S3method(kersplatEstimate,SingleCellExperiment)
-S3method(kersplatEstimate,matrix)
-S3method(lun2Estimate,SingleCellExperiment)
-S3method(lun2Estimate,matrix)
-S3method(lunEstimate,SingleCellExperiment)
-S3method(lunEstimate,matrix)
-S3method(mfaEstimate,SingleCellExperiment)
-S3method(mfaEstimate,matrix)
-S3method(phenoEstimate,SingleCellExperiment)
-S3method(phenoEstimate,matrix)
-S3method(scDDEstimate,SingleCellExperiment)
-S3method(scDDEstimate,default)
-S3method(scDDEstimate,matrix)
-S3method(simpleEstimate,SingleCellExperiment)
-S3method(simpleEstimate,matrix)
-S3method(sparseDCEstimate,SingleCellExperiment)
-S3method(sparseDCEstimate,matrix)
-S3method(splatEstimate,SingleCellExperiment)
-S3method(splatEstimate,matrix)
-S3method(zinbEstimate,SingleCellExperiment)
-S3method(zinbEstimate,matrix)
-export(BASiCSEstimate)
-export(BASiCSSimulate)
-export(addGeneLengths)
-export(compareSCEs)
-export(diffSCEs)
-export(eQTLEstimate)
-export(eQTLSimulate)
-export(getParam)
-export(getParams)
-export(kersplatEstimate)
-export(kersplatSample)
-export(kersplatSetup)
-export(kersplatSimulate)
-export(listSims)
-export(lun2Estimate)
-export(lun2Simulate)
-export(lunEstimate)
-export(lunSimulate)
-export(makeCompPanel)
-export(makeDiffPanel)
-export(makeOverallPanel)
-export(mfaEstimate)
-export(mfaSimulate)
-export(newBASiCSParams)
-export(newKersplatParams)
-export(newLun2Params)
-export(newLunParams)
-export(newMFAParams)
-export(newPhenoParams)
-export(newSCDDParams)
-export(newSimpleParams)
-export(newSparseDCParams)
-export(newSplatParams)
-export(newZINBParams)
-export(neweQTLParams)
-export(phenoEstimate)
-export(phenoSimulate)
-export(scDDEstimate)
-export(scDDSimulate)
-export(setParam)
-export(setParams)
-export(simpleEstimate)
-export(simpleSimulate)
-export(sparseDCEstimate)
-export(sparseDCSimulate)
-export(splatEstimate)
-export(splatSimulate)
-export(splatSimulateGroups)
-export(splatSimulatePaths)
-export(splatSimulateSingle)
-export(splatSimulateeQTL)
-export(summariseDiff)
-export(zinbEstimate)
-export(zinbSimulate)
-exportClasses(BASiCSParams)
-exportClasses(KersplatParams)
-exportClasses(Lun2Params)
-exportClasses(LunParams)
-exportClasses(MFAParams)
-exportClasses(PhenoParams)
-exportClasses(SCDDParams)
-exportClasses(SimpleParams)
-exportClasses(SparseDCParams)
-exportClasses(SplatParams)
-exportClasses(ZINBParams)
-exportClasses(eQTLParams)
-importFrom(BiocParallel,SerialParam)
-importFrom(BiocParallel,bplapply)
-importFrom(S4Vectors,"metadata<-")
-importFrom(S4Vectors,metadata)
-importFrom(SingleCellExperiment,"cpm<-")
-importFrom(SingleCellExperiment,SingleCellExperiment)
-importFrom(SingleCellExperiment,cbind)
-importFrom(SingleCellExperiment,cpm)
-importFrom(SummarizedExperiment,"assays<-")
-importFrom(SummarizedExperiment,"colData<-")
-importFrom(SummarizedExperiment,"rowData<-")
-importFrom(SummarizedExperiment,assays)
-importFrom(SummarizedExperiment,colData)
-importFrom(SummarizedExperiment,rowData)
-importFrom(checkmate,checkCharacter)
-importFrom(checkmate,checkClass)
-importFrom(checkmate,checkDataFrame)
-importFrom(checkmate,checkFactor)
-importFrom(checkmate,checkFlag)
-importFrom(checkmate,checkInt)
-importFrom(checkmate,checkIntegerish)
-importFrom(checkmate,checkNumber)
-importFrom(checkmate,checkNumeric)
-importFrom(data.table,.I)
-importFrom(data.table,between)
-importFrom(data.table,data.table)
-importFrom(ggplot2,aes_string)
-importFrom(ggplot2,coord_fixed)
-importFrom(ggplot2,element_blank)
-importFrom(ggplot2,facet_wrap)
-importFrom(ggplot2,geom_abline)
-importFrom(ggplot2,geom_boxplot)
-importFrom(ggplot2,geom_hline)
-importFrom(ggplot2,geom_point)
-importFrom(ggplot2,geom_smooth)
-importFrom(ggplot2,geom_tile)
-importFrom(ggplot2,geom_violin)
-importFrom(ggplot2,ggplot)
-importFrom(ggplot2,ggtitle)
-importFrom(ggplot2,scale_colour_manual)
-importFrom(ggplot2,scale_fill_distiller)
-importFrom(ggplot2,scale_fill_manual)
-importFrom(ggplot2,scale_x_log10)
-importFrom(ggplot2,scale_y_continuous)
-importFrom(ggplot2,scale_y_log10)
-importFrom(ggplot2,theme)
-importFrom(ggplot2,theme_minimal)
-importFrom(ggplot2,xlab)
-importFrom(ggplot2,ylab)
-importFrom(locfit,locfit)
-importFrom(methods,"slot<-")
-importFrom(methods,as)
-importFrom(methods,callNextMethod)
-importFrom(methods,is)
-importFrom(methods,new)
-importFrom(methods,show)
-importFrom(methods,slot)
-importFrom(methods,slotNames)
-importFrom(methods,validObject)
-importFrom(stats,aggregate)
-importFrom(stats,approxfun)
-importFrom(stats,cor)
-importFrom(stats,dbeta)
-importFrom(stats,density)
-importFrom(stats,dnbinom)
-importFrom(stats,ks.test)
-importFrom(stats,median)
-importFrom(stats,model.matrix)
-importFrom(stats,nls)
-importFrom(stats,pnorm)
-importFrom(stats,qgamma)
-importFrom(stats,qnorm)
-importFrom(stats,quantile)
-importFrom(stats,rbinom)
-importFrom(stats,rchisq)
-importFrom(stats,rgamma)
-importFrom(stats,rlnorm)
-importFrom(stats,rnbinom)
-importFrom(stats,rnorm)
-importFrom(stats,rpois)
-importFrom(stats,runif)
 importFrom(stats,sd)
-importFrom(stats,shapiro.test)
-importFrom(utils,globalVariables)
-importFrom(utils,head)
-importFrom(utils,read.delim)
-importFrom(utils,write.table)
diff --git a/R/data.R b/R/data.R
index 6f6a7a1..e69de29 100644
--- a/R/data.R
+++ b/R/data.R
@@ -1,76 +0,0 @@
-#' Example GFF file
-#'
-#' An example GFF file containing human genes from chromosome 22 of the GRCh38
-#'
-#' @docType data
-#' 
-#' @usage data(ex_gff)
-#'
-#' @format A data frame with 504 rows and 9 variables:
-#' \describe{
-#'   \item{V1}{id}
-#'   \item{V2}{source}
-#'   \item{V3}{feature}
-#'   \item{V4}{start}
-#'   \item{V5}{end}
-#'   \item{V6}{score}
-#'   \item{V7}{direction}
-#'   \item{V8}{frame}
-#'   \item{V9}{attribute}
-#'   ...
-#' }
-#' @source \url{ftp://ftp.ensembl.org/pub/release-98/gff3/homo_sapiens/Homo_sapiens.GRCh38.98.chromosome.22.gff3.gz
-#'}
-"ex_gff"
-
-
-#' Example simulated genotype file (vcf)
-#'
-#' An example genotype file in the .vcf format, where each column is a sample
-#' and each row is a SNP.
-#' 
-#' @docType data
-#' 
-#' @usage data(ex_snps)
-#' 
-#' @format A data frame with 141882 rows and 109 variables:
-#' 
-#' @source \url{ftp://ftp.ensembl.org/pub/release-98/gff3/homo_sapiens/Homo_sapiens.GRCh38.98.chromosome.22.gff3.gz
-#'}
-"ex_snps"
-
-
-#' Example gene mean data for a whole population (from GTEx)
-#'
-#' An example population wide gene mean data.frame, where each column is a 
-#' sample and each row is a gene. Data is from the Thyroid tissue from the GTEx
-#' dataset. Example data has already been filtered to remove genes with >50% 
-#' of samples have < 0.1 TPM
-#' 
-#' @docType data
-#' 
-#' @usage data(ex_means)
-#' 
-#' @format A data frame with 2438 rows and 850 variables:
-#' 
-#' @source \url{https://storage.googleapis.com/gtex_analysis_v8/rna_seq_data/GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_tpm.gct.gz
-#'}
-"ex_means"
-
-
-#' Example eQTL results from GTEx Thyroid tissue
-#'
-#' An example dataframe with eQTL pairs and effect sizes from the Thyroid 
-#' tissue from the GTEx dataset. This example data has already been filtered to 
-#' include only the top eSNP for each gene. Columns that must be included are: 
-#' 'gene_id', 'pval_nominal', and 'slope'.
-#' 
-#' @docType data
-#' 
-#' @usage data(ex_pairs)
-#' 
-#' @format A data frame with 25,244 rows and 9 variables:
-#' 
-#' @source \url{https://storage.googleapis.com/gtex_analysis_v7/single_tissue_eqtl_data/all_snp_gene_associations/Thyroid.allpairs.txt.gz
-#'}
-"ex_pairs"
diff --git a/R/epi-functions.R b/R/epi-functions.R
new file mode 100644
index 0000000..2d37367
--- /dev/null
+++ b/R/epi-functions.R
@@ -0,0 +1,1524 @@
+#' Set control params
+#'
+#' Sets the controls for stochastic individual contact models simulated with 
+#' icm.
+#'
+#' @param type Type of model: SI, SIR, SIS, SEIR, SEIQHR and 
+#'     SEIQHRF available, but only SEIQHRF is likely to work in the 
+#'     current version of the code.
+#' @param s.num Initial number of *S compartment individuals in 
+#'     the simulated population. An overall population of 10,000 is a good 
+#'     compromise. A set of models will still take several minutes or more
+#'     to run, in parallel.
+#' @param e.num Initial number of E compartment individuals in 
+#'     the simulated population.
+#' @param i.num Initial number of I compartment individuals in 
+#'     the simulated population.
+#' @param q.num Initial number of Q compartment individuals in 
+#'     the simulated population.
+#' @param h.num Initial number of H compartment individuals in
+#'      the simulated population.
+#' @param r.num Initial number of R compartment individuals in 
+#'     the simulated population.
+#' @param f.num Initial number of F compartment individuals in 
+#'     the simulated population.
+#'
+#' @return control.icm object
+#' 
+set.control <- function(type = 'SEIQHRF', 
+                        nsteps = 366, 
+                        nsims = 8,
+                        ncores = 4,
+                        prog.rand = FALSE,
+                        rec.rand = FALSE,
+                        fat.rand = TRUE,
+                        quar.rand = FALSE,
+                        hosp.rand = FALSE,
+                        disch.rand = TRUE) {
+    
+    control <- control.icm(type = type, 
+                           nsteps = nsteps, 
+                           nsims = nsims,
+                           ncores = ncores,
+                           prog.rand = prog.rand,
+                           rec.rand = rec.rand,
+                           fat.rand = fat.rand,
+                           quar.rand = quar.rand,
+                           hosp.rand = hosp.rand,
+                           disch.rand = disch.rand)
+    return(control)
+}
+
+
+#' Set init params
+#'
+#' Sets the initial conditions for stochastic individual contact models 
+#' simulated with icm.
+#'
+#' @param s.num Initial number of *S compartment individuals in 
+#'     the simulated population. An overall population of 10,000 is a good 
+#'     compromise. A set of models will still take several minutes or more
+#'     to run, in parallel.
+#' @param e.num Initial number of E compartment individuals in 
+#'     the simulated population.
+#' @param i.num Initial number of I compartment individuals in 
+#'     the simulated population.
+#' @param q.num Initial number of Q compartment individuals in 
+#'     the simulated population.
+#' @param h.num Initial number of H compartment individuals in
+#'      the simulated population.
+#' @param r.num Initial number of R compartment individuals in 
+#'     the simulated population.
+#' @param f.num Initial number of F compartment individuals in 
+#'     the simulated population.
+#'
+#' @return init.icm object
+#' 
+set.init <- function(s.num = 9997,
+                        e.num=0,
+                        i.num = 3,
+                        q.num=0,
+                        h.num=0,
+                        r.num = 0,
+                        f.num = 0){
+    
+    init <- init.icm(s.num = s.num,
+                     e.num = e.num,
+                     i.num = i.num,
+                     q.num = q.num,
+                     h.num = h.num,
+                     r.num = r.num,
+                     f.num = f.num)
+    return(init)
+}
+ 
+#' Set epidemic params
+#'
+#' Sets the epidemic parameters for stochastic individual contact models 
+#' simulated with icm.
+#'
+#' @param act.rate.i The number of exposure events (acts) between 
+#'     infectious individuals in the I compartment and susceptible individuals 
+#'     in the S compartment, per day. It's stochastic, so the rate is an
+#'     average, some individuals may have more or less. Note that not every 
+#'     exposure event results in infection - that is governed by the inf.prob.i
+#'     parameters (see below). Reducing act.rate.i is equivalent to increasing 
+#'     social distancing by people in the I compartment.
+#' @param inf.prob.i Probability of passing on infection at each 
+#'     exposure event for interactions between infectious people in the I
+#'     compartment and susceptibles in S. Reducing inf.prob.i is equivalent to 
+#'     increasing hygiene measures, such as not putting hands in eyes, nose or 
+#'     moth, use of hand sanitisers, wearing masks by the infected, and so on.
+#' @param act.rate.e The number of exposure events (acts) between 
+#'     infectious individuals in the E compartment and susceptible individuals 
+#'     in the S compartment, per day. Otherwise as for act.rate.i.
+#' @param inf.prob.e Probability of passing on infection at each 
+#'     exposure event for interactions between infectious people in the E 
+#'     compartment and susceptibles in S. Note the default is lower than for 
+#'     inf.prob.i reflecting the reduced infectivity of infected but 
+#'     asymptomatic people (the E compartment). Otherwise as for inf.exp.i.
+#' @param act.rate.q The number of exposure events (acts) between 
+#'     infectious individuals in the Q compartment (isolated, self or otherwise)
+#'     and susceptible individuals in the S compartment, per day. Note the much
+#'     lower rate than for the I and E compartments, reflecting the much 
+#'     greater degree of social isolation for someone in (self-)isolation. The
+#'     exposure event rate is not zero for this group, just much less. 
+#'     Otherwise as for act.rate.i.
+#' @param inf.prob.q Probability of passing on infection at each 
+#'     exposure event for interactions between infectious people in the Q 
+#'     compartment and susceptibles in S. Note the default is lower than for 
+#'     inf.prob.i reflecting the greater care that self-isolated individuals 
+#'     will, on average, take regarding hygiene measures, such as wearing masks,
+#'     to limit spread to others. Otherwise as for inf.exp.i.
+#' @param quar.rate Rate per day at which symptomatic (or tested 
+#'     positive), infected I compartment people enter self-isolation (Q 
+#'     compartment). Asymptomatic E compartment people can't enter 
+#'     self-isolation because they don't yet know they are infected. Default is
+#'     a low rate reflecting low community awareness or compliance with 
+#'     self-isolation requirements or practices, but this can be tweaked when
+#'     exploring scenarios.
+#' @param hosp.rate Rate per day at which symptomatic (or tested 
+#'     positive), infected I compartment people or self-isolated Q compartment
+#'     people enter the state of requiring hospital care -- that is, become 
+#'     serious cases. A default rate of 1% per day with an average illness 
+#'     duration of about 10 days means a bit less than 10% of cases will 
+#'     require hospitalisation, which seems about right (but can be tweaked, 
+#'     of course).
+#' @param disch.rate Rate per day at which people needing 
+#'     hospitalisation recover.
+#' @param prog.rate Rate per day at which people who are infected 
+#'     but asymptomatic (E compartment) progress to becoming symptomatic (or 
+#'     test-positive), the I compartment. See prog.rand above for more details.
+#' @param prog.dist.scale Scale parameter for Weibull distribution 
+#'     for progression, see prog.rand for details.
+#' @param prog.dist.shape Shape parameter for Weibull distribution 
+#'     for progression, see prog.rand for details. Read up on the Weibull 
+#'     distribution before changing the default.
+#' @param rec.rate Rate per day at which people who are infected and
+#'     symptomatic (I compartment) recover, thus entering the R compartment. 
+#'     See rec.rand above for more details.
+#' @param rec.dist.scale Scale parameter for Weibull distribution for
+#'     recovery, see rec.rand for details.
+#' @param rec.dist.shape Shape parameter for Weibull distribution for
+#'     recovery, see rec.rand for details. Read up on the Weibull distribution
+#'     before changing the default.
+#' @param fat.rate.base Baseline mortality rate per day for people 
+#'     needing hospitalisation (deaths due to the virus). See fat.rand for more
+#'     details.
+#' @param hosp.cap Number of available hospital beds for the modelled
+#'     population. See fat.rand for more details.
+#' @param fat.rate.overcap Mortality rate per day for people needing
+#'     hospitalisation but who can't get into hospital due to the hospitals 
+#'     being full (see hosp.cap and fat.rand). The default rate is twice that 
+#'     for those who do get into hospital.
+#' @param fat.tcoeff Time co-efficient for increasing mortality rate 
+#'     as time in the H compartment increases for each individual in it. See 
+#'     fat.rand for details.
+#' @param vital Enables demographics, that is, arrivals and 
+#'     departures, to and from the simulated population.
+#' @param a.rate Background demographic arrival rate. Currently all 
+#'     arrivals go into the S compartment, the default is approximately the 
+#'     daily birth rate for Australia. Will be extended to cover immigration in
+#'     future versions.
+#' @param ds.rate Background demographic departure (death not due to
+#'     virus) rates. Defaults based on Australian crude death rates. Can be 
+#'     used to model emigration as well as deaths.
+#' @param de.rate Background demographic departure (death not due to
+#'     virus) rates. Defaults based on Australian crude death rates. Can be 
+#'     used to model emigration as well as deaths.
+#' @param de.rate Background demographic departure (death not due to 
+#'     virus) rates. Defaults based on Australian crude death rates. Can be used
+#'     to model emigration as well as deaths.
+#' @param dq.rate Background demographic departure (death not due to 
+#'     virus) rates. Defaults based on Australian crude death rates. Can be used
+#'     to model emigration as well as deaths.
+#' @param dh.rate Background demographic departure (death not due to 
+#'     virus) rates. Defaults based on Australian crude death rates. Can be used
+#'     to model emigration as well as deaths.
+#' @param dr.rate Background demographic departure (death not due to 
+#'     virus) rates. Defaults based on Australian crude death rates. Can be used 
+#'     to model emigration as well as deaths.
+#' @param out Summary function for the simulation runs. median is 
+#'     also available, or percentiles, see the EpiModel documentation.
+#'
+#' @return param.icm object
+#' 
+set.param <- function(inf.prob.e = 0.02, 
+                        act.rate.e = 10,
+                        inf.prob.i = 0.05, 
+                        act.rate.i = 10,
+                        inf.prob.q = 0.02, 
+                        act.rate.q = 2.5,                    
+                        quar.rate = 1/30, 
+                        hosp.rate = 1/100,
+                        disch.rate = 1/15,
+                        prog.rate = 1/10,
+                        prog.dist.scale = 5,
+                        prog.dist.shape = 1.5,
+                        rec.rate = 1/20,
+                        rec.dist.scale = 35,
+                        rec.dist.shape = 1.5,
+                        fat.rate.base = 1/50,
+                        hosp.cap = 40,
+                        fat.rate.overcap = 1/25,
+                        fat.tcoeff = 0.5,
+                        vital = TRUE,
+                        a.rate = (10.5/365)/1000, 
+                        a.prop.e = 0.01,
+                        a.prop.i = 0.001,
+                        a.prop.q = 0.01,
+                        ds.rate = (7/365)/1000, 
+                        de.rate = (7/365)/1000, 
+                        di.rate = (7/365)/1000,
+                        dq.rate = (7/365)/1000,
+                        dh.rate = (20/365)/1000,
+                        dr.rate = (7/365)/1000,
+                        out="mean"){
+    
+    param <- param.icm(inf.prob.e = inf.prob.e, 
+                       act.rate.e = act.rate.e,
+                       inf.prob.i = inf.prob.i, 
+                       act.rate.i = act.rate.i,
+                       inf.prob.q = inf.prob.q, 
+                       act.rate.q = act.rate.q,                    
+                       quar.rate = quar.rate,
+                       hosp.rate = hosp.rate,
+                       disch.rate = disch.rate,
+                       prog.rate = prog.rate,
+                       prog.dist.scale = prog.dist.scale,
+                       prog.dist.shape = prog.dist.shape,
+                       rec.rate = rec.rate,
+                       rec.dist.scale = rec.dist.scale,
+                       rec.dist.shape = rec.dist.shape,
+                       fat.rate.base = fat.rate.base,
+                       hosp.cap = hosp.cap,
+                       fat.rate.overcap = fat.rate.overcap,
+                       fat.tcoeff = fat.tcoeff,
+                       vital = vital,
+                       a.rate = a.rate, 
+                       a.prop.e = a.prop.e,
+                       a.prop.i = a.prop.i,
+                       a.prop.q = a.prop.q,
+                       ds.rate = ds.rate, 
+                       de.rate = de.rate, 
+                       di.rate = di.rate,
+                       dq.rate = dq.rate,
+                       dh.rate = dh.rate,
+                       dr.rate = dr.rate)
+    return(param)
+}
+
+
+#' Initialize ICM 
+#'
+#' Function to initialize the icm
+#'
+#' @param param ICM parameters.
+#' @param init Initial value parameters.
+#' @param control Control parameters.
+#'
+#' @return Updated dat
+initialize.FUN <- function(param, init, control) {
+    
+    ## Master List for Data ##
+    dat <- list()
+    dat$param <- getParams(param, c(slotNames(param)))
+    dat$init <- getParams(init, c(slotNames(init)))
+    dat$control <- getParams(control, c(slotNames(control)))
+    
+    # Set attributes
+    dat$attr <- list()
+    numeric.init <- init[which(sapply(init, class) == "numeric")]
+    n <- do.call("sum", numeric.init)
+    dat$attr$active <- rep(1, n)
+    if (dat$param$groups == 1) {
+        dat$attr$group <- rep(1, n)
+    } else {
+        g2inits <- grep(".g2", names(numeric.init))
+        g1inits <- setdiff(1:length(numeric.init), g2inits)
+        nG1 <- sum(sapply(g1inits, function(x) init[[x]]))
+        nG2 <- sum(sapply(g2inits, function(x) init[[x]]))
+        dat$attr$group <- c(rep(1, nG1), rep(2, max(0, nG2)))
+    }
+    
+    # Initialize status and infection time
+    dat <- init_status.icm(dat)
+    
+    
+    # Summary out list
+    dat <- get_prev.icm(dat, at = 1)
+    
+    return(dat)
+}
+
+
+#' Infection function
+#'
+#' Function to implement infection processes for SEIQHRF model
+#'
+#' @param dat Input data needed.
+#' @param at Not sure???
+#'
+#' @return Updated dat
+
+infection.FUN <- function(dat, at) {
+    type <- dat$control$type
+    
+    # the following checks need to be moved to control.icm in due course
+    nsteps <- dat$control$nsteps
+    
+    act.rate.i <- dat$param$act.rate.i
+    if (!(length(act.rate.i) == 1 || length(act.rate.i == nsteps))) {
+        stop("Length of act.rate.i must be 1 or the value of nsteps")
+    }
+    act.rate.i.g2 <- dat$param$act.rate.i.g2
+    if (!is.null(act.rate.i.g2) && 
+        !(length(act.rate.i.g2) == 1 || length(act.rate.i.g2 == nsteps))) {
+        stop("Length of act.rate.i.g2 must be 1 or the value of nsteps")
+    }
+    inf.prob.i <- dat$param$inf.prob.i
+    if (!(length(inf.prob.i) == 1 || length(inf.prob.i == nsteps))) {
+        stop("Length of inf.prob.i must be 1 or the value of nsteps")
+    }
+    inf.prob.i.g2 <- dat$param$inf.prob.i.g2
+    if (!is.null(inf.prob.i.g2) &&
+        !(length(inf.prob.i.g2) == 1 || length(inf.prob.i.g2 == nsteps))) {
+        stop("Length of inf.prob.i.g2 must be 1 or the value of nsteps")
+    }
+    if (type %in% c("SEIQHR", "SEIQHRF")) {  
+        quar.rate <- dat$param$quar.rate
+        if (!(length(quar.rate) == 1 || length(quar.rate == nsteps))) {
+            stop("Length of quar.rate must be 1 or the value of nsteps")
+        }
+        quar.rate.g2 <- dat$param$quar.rate.g2
+        if (!is.null(quar.rate.g2) &&
+            !(length(quar.rate.g2) == 1 || length(quar.rate.g2 == nsteps))) {
+            stop("Length of quar.rate.g2 must be 1 or the value of nsteps")
+        }
+        disch.rate <- dat$param$disch.rate
+        if (!(length(disch.rate) == 1 || length(disch.rate == nsteps))) {
+            stop("Length of disch.rate must be 1 or the value of nsteps")
+        }
+        disch.rate.g2 <- dat$param$disch.rate.g2
+        if (!is.null(disch.rate.g2) &&
+            !(length(disch.rate.g2) == 1 || length(disch.rate.g2 == nsteps))) {
+            stop("Length of disch.rate.g2 must be 1 or the value of nsteps")
+        }
+    }
+    
+    if (type %in% c("SEIQHR", "SEIQHRF")) {  
+        act.rate.e <- dat$param$act.rate.e
+        if (!(length(act.rate.e) == 1 || length(act.rate.e == nsteps))) {
+            stop("Length of act.rate.e must be 1 or the value of nsteps")
+        }
+        act.rate.e.g2 <- dat$param$act.rate.e.g2
+        if (!is.null(act.rate.e.g2) &&
+            !(length(act.rate.e.g2) == 1 || length(act.rate.e.g2 == nsteps))) {
+            stop("Length of act.rate.e.g2 must be 1 or the value of nsteps")
+        }
+        inf.prob.e <- dat$param$inf.prob.e
+        if (!(length(inf.prob.e) == 1 || length(inf.prob.e == nsteps))) {
+            stop("Length of inf.prob.e must be 1 or the value of nsteps")
+        }
+        inf.prob.e.g2 <- dat$param$inf.prob.e.g2
+        if (!is.null(inf.prob.e.g2) &&
+            !(length(inf.prob.e.g2) == 1 || length(inf.prob.e.g2 == nsteps))) {
+            stop("Length of inf.prob.e.g2 must be 1 or the value of nsteps")
+        }
+        
+        act.rate.q <- dat$param$act.rate.q
+        if (!(length(act.rate.q) == 1 || length(act.rate.q == nsteps))) {
+            stop("Length of act.rate.q must be 1 or the value of nsteps")
+        }
+        act.rate.q.g2 <- dat$param$act.rate.q.g2
+        if (!is.null(act.rate.q.g2) &&
+            !(length(act.rate.q.g2) == 1 || length(act.rate.q.g2 == nsteps))) {
+            stop("Length of act.rate.q.g2 must be 1 or the value of nsteps")
+        }
+        inf.prob.q <- dat$param$inf.prob.q
+        if (!(length(inf.prob.q) == 1 || length(inf.prob.q == nsteps))) {
+            stop("Length of inf.prob.q must be 1 or the value of nsteps")
+        }
+        inf.prob.q.g2 <- dat$param$inf.prob.q.g2
+        if (!is.null(inf.prob.q.g2) &&
+            !(length(inf.prob.q.g2) == 1 || length(inf.prob.q.g2 == nsteps))) {
+            stop("Length of inf.prob.q.g2 must be 1 or the value of nsteps")
+        }
+    }
+    
+    # Transmission from infected  
+    ## Expected acts
+    if (dat$param$groups == 1) {
+        if (length(act.rate.i) > 1) {
+            acts <- round(act.rate.i[at - 1] * dat$epi$num[at - 1] / 2)
+        } else {
+            acts <- round(act.rate.i * dat$epi$num[at - 1] / 2)
+        }
+    }
+    if (dat$param$groups == 2) {
+        if (dat$param$balance == "g1") {
+            if (length(act.rate.i) > 1) {
+                acts <- round(act.rate.i[at - 1] *
+                                  (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+            } else {
+                acts <- round(act.rate.i *
+                                  (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+            }
+        }
+        if (dat$param$balance == "g2") {
+            if (length(act.rate.i.g2) > 1) {
+                acts <- round(act.rate.i.g2[at - 1] *
+                                  (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+            } else {
+                acts <- round(act.rate.i.g2 *
+                                  (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+            }
+        }
+    }
+    
+    ## Edgelist
+    if (dat$param$groups == 1) {
+        p1 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+        p2 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+    } else {
+        p1 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 1 & dat$attr$status != "f"),
+                      acts, replace = TRUE)
+        p2 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 2 & dat$attr$status != "f"),
+                      acts, replace = TRUE)
+    }
+    
+    del <- NULL
+    if (length(p1) > 0 & length(p2) > 0) {
+        del <- data.frame(p1, p2)
+        if (dat$param$groups == 1) {
+            while (any(del$p1 == del$p2)) {
+                del$p2 <- ifelse(del$p1 == del$p2,
+                                 ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), 1), del$p2)
+            }
+        }
+    } 
+    
+    ## Discordant edgelist (del)
+    del$p1.stat <- dat$attr$status[del$p1]
+    del$p2.stat <- dat$attr$status[del$p2]
+    serodis <- (del$p1.stat == "s" & del$p2.stat == "i") |
+        (del$p1.stat == "i" & del$p2.stat == "s")
+    del <- del[serodis == TRUE, ]
+    
+    ## Transmission on edgelist
+    if (nrow(del) > 0) {
+        if (dat$param$groups == 1) {
+            if (length(inf.prob.i) > 1) {
+                del$tprob <- inf.prob.i[at]
+            } else {
+                del$tprob <- inf.prob.i
+            }
+        } else {
+            if (length(inf.prob.i) > 1) {
+                del$tprob <- ifelse(del$p1.stat == "s", inf.prob.i[at],
+                                    inf.prob.i.g2[at])
+            } else {
+                del$tprob <- ifelse(del$p1.stat == "s", inf.prob.i,
+                                    inf.prob.i.g2)
+            }
+        }
+        if (!is.null(dat$param$inter.eff.i) && at >= dat$param$inter.start.i &&
+            at <= dat$param$inter.stop.i) {
+            del$tprob <- del$tprob * (1 - dat$param$inter.eff.i)
+        }
+        del$trans <- rbinom(nrow(del), 1, del$tprob)
+        del <- del[del$trans == TRUE, ]
+        if (nrow(del) > 0) {
+            if (dat$param$groups == 1) {
+                newIds <- unique(ifelse(del$p1.stat == "s", del$p1, del$p2))
+                nExp.i <- length(newIds)
+            }
+            if (dat$param$groups == 2) {
+                newIdsg1 <- unique(del$p1[del$p1.stat == "s"])
+                newIdsg2 <- unique(del$p2[del$p2.stat == "s"])
+                nExp.i <- length(newIdsg1)
+                nExpg2.i <- length(newIdsg2)
+                newIds <- c(newIdsg1, newIdsg2)
+            }
+            dat$attr$status[newIds] <- "e"
+            dat$attr$expTime[newIds] <- at
+        } else {
+            nExp.i <- nExpg2.i <- 0
+        }
+    } else {
+        nExp.i <- nExpg2.i <- 0
+    }
+    
+    if (type %in% c("SEIQHRF")) {  
+        
+        # Transmission from exposed  
+        ## Expected acts
+        if (dat$param$groups == 1) {
+            if (length(act.rate.e) > 1) {
+                acts <- round(act.rate.e[at - 1] * dat$epi$num[at - 1] / 2)
+            } else {
+                acts <- round(act.rate.e * dat$epi$num[at - 1] / 2)
+            }
+        }
+        if (dat$param$groups == 2) {
+            if (dat$param$balance == "g1") {
+                if (length(act.rate.e.g2) > 1) {
+                    acts <- round(act.rate.e.g2[at - 1] *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                } else {
+                    acts <- round(act.rate.e.g2 *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                }
+            }
+            if (dat$param$balance == "g2") {
+                if (length(act.rate.e.g2) > 1) {
+                    acts <- round(act.rate.e.g2[at - 1] *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                } else {
+                    acts <- round(act.rate.e.g2 *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                }
+            }
+        }
+        
+        ## Edgelist
+        if (dat$param$groups == 1) {
+            p1 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+            p2 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+        } else {
+            p1 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 1 & dat$attr$status != "f"),
+                          acts, replace = TRUE)
+            p2 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 2 & dat$attr$status != "f"),
+                          acts, replace = TRUE)
+        }
+        
+        del <- NULL
+        if (length(p1) > 0 & length(p2) > 0) {
+            del <- data.frame(p1, p2)
+            if (dat$param$groups == 1) {
+                while (any(del$p1 == del$p2)) {
+                    del$p2 <- ifelse(del$p1 == del$p2,
+                                     ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), 1), del$p2)
+                }
+            }
+            
+            ## Discordant edgelist (del)
+            del$p1.stat <- dat$attr$status[del$p1]
+            del$p2.stat <- dat$attr$status[del$p2]
+            # serodiscordance
+            serodis <- (del$p1.stat == "s" & del$p2.stat == "e") |
+                (del$p1.stat == "e" & del$p2.stat == "s")
+            del <- del[serodis == TRUE, ]
+            
+            ## Transmission on edgelist
+            if (nrow(del) > 0) {
+                if (dat$param$groups == 1) {
+                    if (length(inf.prob.e) > 1) {
+                        del$tprob <- inf.prob.e[at]
+                    } else {
+                        del$tprob <- inf.prob.e
+                    }
+                } else {
+                    if (length(inf.prob.e) > 1) {
+                        del$tprob <- ifelse(del$p1.stat == "s", inf.prob.e[at],
+                                            inf.prob.e.g2[at])
+                    } else {
+                        del$tprob <- ifelse(del$p1.stat == "s", inf.prob.e,
+                                            inf.prob.e.g2)
+                    }
+                }
+                if (!is.null(dat$param$inter.eff.e) && at >= dat$param$inter.start.e &&
+                    at <= dat$param$inter.stop.e) {
+                    del$tprob <- del$tprob * (1 - dat$param$inter.eff.e)
+                }
+                del$trans <- rbinom(nrow(del), 1, del$tprob)
+                del <- del[del$trans == TRUE, ]
+                if (nrow(del) > 0) {
+                    if (dat$param$groups == 1) {
+                        newIds <- unique(ifelse(del$p1.stat == "s", del$p1, del$p2))
+                        nExp.e <- length(newIds)
+                    }
+                    if (dat$param$groups == 2) {
+                        newIdsg1 <- unique(del$p1[del$p1.stat == "s"])
+                        newIdsg2 <- unique(del$p2[del$p2.stat == "s"])
+                        nExp.e <- length(newIdsg1)
+                        nExpg2.e <- length(newIdsg2)
+                        newIds <- c(newIdsg1, newIdsg2)
+                    }
+                    dat$attr$status[newIds] <- "e"
+                    dat$attr$expTime[newIds] <- at
+                } else {
+                    nExp.e <- nExpg2.e <- 0
+                }
+            } else {
+                nExp.e <- nExpg2.e <- 0
+            }
+        } else {
+            nExp.e <- nExpg2.e <- 0
+        }
+        
+        
+        # Transmission from quarantined  
+        ## Expected acts
+        if (dat$param$groups == 1) {
+            if (length(act.rate.q) > 1) {
+                acts <- round(act.rate.q[at - 1] * dat$epi$num[at - 1] / 2)
+            } else {
+                acts <- round(act.rate.q * dat$epi$num[at - 1] / 2)
+            }
+        }
+        if (dat$param$groups == 2) {
+            if (dat$param$balance == "g1") {
+                if (length(act.rate.q.g2) > 1) {
+                    acts <- round(act.rate.q.g2[at - 1] *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                } else {
+                    acts <- round(act.rate.q.g2 *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                }
+            }
+            if (dat$param$balance == "g2") {
+                if (length(act.rate.q.g2) > 1) {
+                    acts <- round(act.rate.q.g2[at - 1] *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                } else {
+                    acts <- round(act.rate.q.g2 *
+                                      (dat$epi$num[at - 1] + dat$epi$num.g2[at - 1]) / 2)
+                }
+            }
+        }
+        
+        ## Edgelist
+        if (dat$param$groups == 1) {
+            p1 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+            p2 <- ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), acts, replace = TRUE)
+        } else {
+            p1 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 1 & dat$attr$status != "f"),
+                          acts, replace = TRUE)
+            p2 <- ssample(which(dat$attr$active == 1 & dat$attr$group == 2 & dat$attr$status != "f"),
+                          acts, replace = TRUE)
+        }
+        
+        del <- NULL
+        if (length(p1) > 0 & length(p2) > 0) {
+            del <- data.frame(p1, p2)
+            if (dat$param$groups == 1) {
+                while (any(del$p1 == del$p2)) {
+                    del$p2 <- ifelse(del$p1 == del$p2,
+                                     ssample(which(dat$attr$active == 1 & dat$attr$status != "f"), 1), del$p2)
+                }
+            }
+            
+            ## Discordant edgelist (del)
+            del$p1.stat <- dat$attr$status[del$p1]
+            del$p2.stat <- dat$attr$status[del$p2]
+            # serodiscordance
+            serodis <- (del$p1.stat == "s" & del$p2.stat == "q") |
+                (del$p1.stat == "q" & del$p2.stat == "s")
+            del <- del[serodis == TRUE, ]
+            
+            ## Transmission on edgelist
+            if (nrow(del) > 0) {
+                if (dat$param$groups == 1) {
+                    if (length(inf.prob.q) > 1) {
+                        del$tprob <- inf.prob.q[at]
+                    } else {
+                        del$tprob <- inf.prob.q
+                    }
+                } else {
+                    if (length(inf.prob.q) > 1) {
+                        del$tprob <- ifelse(del$p1.stat == "s", inf.prob.q[at],
+                                            inf.prob.q.g2[at])
+                    } else {
+                        del$tprob <- ifelse(del$p1.stat == "s", inf.prob.q,
+                                            inf.prob.q.g2)
+                    }
+                }
+                if (!is.null(dat$param$inter.eff.q) && at >= dat$param$inter.start.q &&
+                    at <= dat$param$inter.stop.q) {
+                    del$tprob <- del$tprob * (1 - dat$param$inter.eff.q)
+                }
+                del$trans <- rbinom(nrow(del), 1, del$tprob)
+                del <- del[del$trans == TRUE, ]
+                if (nrow(del) > 0) {
+                    if (dat$param$groups == 1) {
+                        newIds <- unique(ifelse(del$p1.stat == "s", del$p1, del$p2))
+                        nExp.q <- length(newIds)
+                    }
+                    if (dat$param$groups == 2) {
+                        newIdsg1 <- unique(del$p1[del$p1.stat == "s"])
+                        newIdsg2 <- unique(del$p2[del$p2.stat == "s"])
+                        nExp.q <- length(newIdsg1)
+                        nExpg2.q <- length(newIdsg2)
+                        newIds <- c(newIdsg1, newIdsg2)
+                    }
+                    dat$attr$status[newIds] <- "e"
+                    dat$attr$expTime[newIds] <- at
+                } else {
+                    nExp.q <- nExpg2.q <- 0
+                }
+            } else {
+                nExp.q <- nExpg2.q <- 0
+            }
+        } else {
+            nExp.q <- nExpg2.q <- 0
+        }
+    }
+    
+    ## Output
+    if (type %in% c("SEIQHR", "SEIQHRF")) {  
+        if (at == 2) {
+            dat$epi$se.flow <- c(0, nExp.i + nExp.q)
+        } else {
+            dat$epi$se.flow[at] <- nExp.i + nExp.q
+        }
+        if (dat$param$groups == 2) {
+            if (at == 2) {
+                dat$epi$se.flow.g2 <- c(0, nExpg2.i + nExpg2.q )
+            } else {
+                dat$epi$se.flow.g2[at] <- nExpg2.i + nExpg2.q
+            }
+        }
+    } else {
+        if (at == 2) {
+            dat$epi$se.flow <- c(0, nExp.i)
+        } else {
+            dat$epi$se.flow[at] <- nExp.i
+        }
+        if (dat$param$groups == 2) {
+            if (at == 2) {
+                dat$epi$se.flow.g2 <- c(0, nExpg2.i)
+            } else {
+                dat$epi$se.flow.g2[at] <- nExpg2.i
+            }
+        }
+    }
+    return(dat)
+    
+}
+
+
+#' Departures function
+#'
+#' Function to handel background demographics for the SEIQHRF model. 
+#' Specifically departures (deaths not due to the virus, and emigration).
+#'
+#' @param dat Input data needed.
+#' @param at Not sure???
+#'
+#' @return Updated dat
+#' 
+departures.FUN <- function(dat, at) {
+
+    # Conditions --------------------------------------------------------------
+    if (dat$param$vital == FALSE) {
+        return(dat)
+    }
+    
+    
+    # Variables ---------------------------------------------------------------
+    groups <- dat$param$groups
+    group <- dat$attr$group
+    
+    
+    # Susceptible departures ------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "s")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$ds.rate, dat$param$ds.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$ds.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$ds.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$ds.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$ds.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    # Exposed Departures ---------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "e")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$de.rate, dat$param$de.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$de.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$de.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$de.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$de.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    
+    # Infected Departures ---------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "i")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$di.rate, dat$param$di.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$di.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$di.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$di.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$di.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    # Quarantined Departures ---------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "q")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$dq.rate, dat$param$dq.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$dq.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$dq.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$dq.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$dq.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    # Hospitalised Departures ---------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "h")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$dh.rate, dat$param$dh.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$dh.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$dh.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$dh.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$dh.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    
+    # Recovered Departures --------------------------------------------------------
+    nDepartures <- nDeparturesG2 <- 0
+    idsElig <- which(dat$attr$active == 1 & dat$attr$status == "r")
+    nElig <- length(idsElig)
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(dat$param$dr.rate, dat$param$dr.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (dat$control$d.rand == TRUE) {
+            vecDepartures <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecDepartures) > 0) {
+                idsDpt <- idsElig[vecDepartures]
+                nDepartures <- sum(group[idsDpt] == 1)
+                nDeparturesG2 <- sum(group[idsDpt] == 2)
+                dat$attr$active[idsDpt] <- 0
+            }
+        } else {
+            nDepartures <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+            dat$attr$active[ssample(idsElig[gElig == 1], nDepartures)] <- 0
+            if (groups == 2) {
+                nDeparturesG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                dat$attr$active[ssample(idsElig[gElig == 2], nDeparturesG2)] <- 0
+            }
+        }
+    }
+    
+    if (at == 2) {
+        dat$epi$dr.flow <- c(0, nDepartures)
+        if (groups == 2) {
+            dat$epi$dr.flow.g2 <- c(0, nDeparturesG2)
+        }
+    } else {
+        dat$epi$dr.flow[at] <- nDepartures
+        if (groups == 2) {
+            dat$epi$dr.flow.g2[at] <- nDeparturesG2
+        }
+    }
+    
+    return(dat)
+}
+
+
+#' Arrivals function
+#'
+#' Function to handel background demographics for the SEIQHRF model. 
+#' Specifically arrivals (births and immigration). Uses the original EpiModel
+#' code currently. A replacement that implements modelling the arrival of 
+#' infected individuals is under development -- but for now, all arrivals 
+#' go into the S compartment..
+#'
+#' @param dat Input data needed.
+#' @param at Not sure???
+#'
+#' @return Updated dat
+#' 
+arrivals.FUN <- function(dat, at) {
+    
+    # Conditions --------------------------------------------------------------
+    if (dat$param$vital == FALSE) {
+        return(dat)
+    }
+    
+    # Variables ---------------------------------------------------------------
+    a.rate <- dat$param$a.rate
+    a.rate.g2 <- dat$param$a.rate.g2
+    a.rand <- dat$control$a.rand
+    groups <- dat$param$groups
+    nOld <- dat$epi$num[at - 1]
+    
+    # checking params, should be in control.icm or params.icm eventually
+    type <- dat$control$type
+    nsteps <- dat$control$nsteps
+    
+    if (!(length(a.rate) == 1 || length(a.rate == nsteps))) {
+        stop("Length of a.rate must be 1 or the value of nsteps")
+    }
+    if (!is.null(a.rate.g2) && 
+        !(length(a.rate.g2) == 1 || length(a.rate.g2 == nsteps))) {
+        stop("Length of a.rate.g2 must be 1 or the value of nsteps")
+    }
+    
+    a.prop.e <- dat$param$a.prop.e
+    if (!(length(a.prop.e) == 1 || length(a.prop.e == nsteps))) {
+        stop("Length of a.prop.e must be 1 or the value of nsteps")
+    }
+    a.prop.i <- dat$param$a.prop.i
+    if (!(length(a.prop.i) == 1 || length(a.prop.i == nsteps))) {
+        stop("Length of a.prop.i must be 1 or the value of nsteps")
+    }
+    a.prop.q <- dat$param$a.prop.q
+    if (!(length(a.prop.q) == 1 || length(a.prop.q == nsteps))) {
+        stop("Length of a.prop.q must be 1 or the value of nsteps")
+    }
+    
+    a.prop.e.g2 <- dat$param$a.prop.e.g2
+    if (!is.null(a.prop.e.g2) &&
+        !(length(a.prop.e.g2) == 1 || length(a.prop.e.g2 == nsteps))) {
+        stop("Length of a.prop.e.g2 must be 1 or the value of nsteps")
+    }
+    a.prop.i.g2 <- dat$param$a.prop.i.g2
+    if (!is.null(a.prop.i.g2) &&
+        !(length(a.prop.i.g2) == 1 || length(a.prop.i.g2 == nsteps))) {
+        stop("Length of a.prop.i.g2 must be 1 or the value of nsteps")
+    }
+    a.prop.q.g2 <- dat$param$a.prop.q.g2
+    if (!is.null(a.prop.q.g2) &&
+        !(length(a.prop.q.g2) == 1 || length(a.prop.q.g2 == nsteps))) {
+        stop("Length of a.prop.q.g2 must be 1 or the value of nsteps")
+    }
+    
+    # Process -----------------------------------------------------------------
+    nArrivals <- nArrivals.g2 <- 0
+    
+    if (groups == 1) {
+        if (a.rand == TRUE) {
+            nArrivals <- sum(rbinom(nOld, 1, a.rate))
+        }
+        if (a.rand == FALSE) {
+            nArrivals <- round(nOld * a.rate)
+        }
+    }
+    if (groups == 2) {
+        nOldG2 <- dat$epi$num.g2[at - 1]
+        if (a.rand == TRUE) {
+            if (is.na(a.rate.g2)) {
+                nArrivals <- sum(rbinom(nOld, 1, a.rate))
+                nArrivals.g2 <- sum(rbinom(nOld, 1, a.rate))
+            } else {
+                nArrivals <- sum(rbinom(nOld, 1, a.rate))
+                nArrivals.g2 <- sum(rbinom(nOldG2, 1, a.rate.g2))
+            }
+        }
+        if (a.rand == FALSE) {
+            if (is.na(a.rate.g2)) {
+                nArrivals <- round(nOld * a.rate)
+                nArrivals.g2 <- round(nOld * a.rate)
+            } else {
+                nArrivals <- round(nOld * a.rate)
+                nArrivals.g2 <- round(nOldG2 * a.rate.g2)
+            }
+        }
+    }
+    
+    
+    ## Set attributes
+    totArrivals <- 0
+    totArrivals.g2 <- 0
+    
+    # partition arrivals into compartments
+    if (length(a.prop.e) > 1) {
+        nArrivals.e <- round(nArrivals*(a.prop.e[at]))
+        totArrivals <- totArrivals + nArrivals.e
+        if (!is.null(a.prop.e.g2)) {
+            nArrivals.e.g2 <- round(nArrivals.g2*(a.prop.e.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.e.g2
+        } else {
+            nArrivals.e.g2 <- round(nArrivals.g2*(a.prop.e.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.e.g2
+        }
+    } else {
+        nArrivals.e <- round(nArrivals*a.prop.e)
+        totArrivals <- totArrivals + nArrivals.e
+        if (!is.null(a.prop.e.g2)) {
+            nArrivals.e.g2 <- round(nArrivals.g2*(a.prop.e.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.e.g2
+        } else {
+            nArrivals.e.g2 <- round(nArrivals.g2*(a.prop.e.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.e.g2
+        }
+    }
+    
+    if (length(a.prop.i) > 1) {
+        nArrivals.i <- round(nArrivals*(a.prop.i[at]))
+        totArrivals <- totArrivals + nArrivals.i
+        if (!is.null(a.prop.i.g2)) {
+            nArrivals.i.g2 <- round(nArrivals.g2*(a.prop.i.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.i.g2
+        } else {
+            nArrivals.i.g2 <- round(nArrivals.g2*(a.prop.i.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.i.g2
+        }
+    } else {
+        nArrivals.i <- round(nArrivals*a.prop.i)
+        totArrivals <- totArrivals + nArrivals.i
+        if (!is.null(a.prop.i.g2)) {
+            nArrivals.i.g2 <- round(nArrivals.g2*(a.prop.i.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.i.g2
+        } else {
+            nArrivals.i.g2 <- round(nArrivals.g2*(a.prop.i.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.i.g2
+        }
+    }
+    
+    if (length(a.prop.q) > 1) {
+        nArrivals.q <- round(nArrivals*(a.prop.q[at]))
+        totArrivals <- totArrivals + nArrivals.q
+        if (!is.null(a.prop.q.g2)) {
+            nArrivals.q.g2 <- round(nArrivals.g2*(a.prop.q.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.q.g2
+        } else {
+            nArrivals.q.g2 <- round(nArrivals.g2*(a.prop.q.g2[at]))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.q.g2
+        }
+    } else {
+        nArrivals.q <- round(nArrivals*a.prop.q)
+        totArrivals <- totArrivals + nArrivals.q
+        if (!is.null(a.prop.q.g2)) {
+            nArrivals.q.g2 <- round(nArrivals.g2*(a.prop.q.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.q.g2
+        } else {
+            nArrivals.q.g2 <- round(nArrivals.g2*(a.prop.q.g2))
+            totArrivals.g2 <- totArrivals.g2 + nArrivals.q.g2
+        }
+    }
+    
+    # debug
+    print("totArrivals:")
+    print(totArrivals)
+    print("totArrivals.g2:")
+    print(totArrivals.g2)
+    print("----")
+    
+    # group 1
+    dat$attr$active <- c(dat$attr$active, rep(1, totArrivals))
+    dat$attr$group <- c(dat$attr$group, rep(1, totArrivals))
+    dat$attr$status <- c(dat$attr$status,
+                         rep("e", nArrivals.e),
+                         rep("i", nArrivals.i),
+                         rep("q", nArrivals.q),
+                         rep("s", totArrivals - nArrivals.e - nArrivals.i - nArrivals.q))
+    dat$attr$expTime <- c(dat$attr$expTime, rep(NA, totArrivals))
+    dat$attr$infTime <- c(dat$attr$infTime, rep(NA, totArrivals))
+    dat$attr$quarTime <- c(dat$attr$quarTime, rep(NA, totArrivals))
+    dat$attr$hospTime <- c(dat$attr$ihospTime, rep(NA, totArrivals))
+    dat$attr$recovTime <- c(dat$attr$recovTime, rep(NA, totArrivals))
+    dat$attr$fatTime <- c(dat$attr$fatTime, rep(NA, totArrivals))
+    
+    # group 2
+    if (length(totArrivals.g2) > 0) {
+        dat$attr$active <- c(dat$attr$active, rep(1, totArrivals.g2))
+        dat$attr$group <- c(dat$attr$group, rep(2, totArrivals.g2))
+        dat$attr$status <- c(dat$attr$status,
+                             rep("e", nArrivals.e.g2),
+                             rep("i", nArrivals.i.g2),
+                             rep("q", nArrivals.q.g2),
+                             rep("s", totArrivals.g2 - nArrivals.e.g2 - 
+                                     nArrivals.i.g2 - nArrivals.q.g2))
+        dat$attr$expTime <- c(dat$attr$expTime, rep(NA, totArrivals.g2))
+        dat$attr$infTime <- c(dat$attr$infTime, rep(NA, totArrivals.g2))
+        dat$attr$quarTime <- c(dat$attr$quarTime, rep(NA, totArrivals.g2))
+        dat$attr$hospTime <- c(dat$attr$ihospTime, rep(NA, totArrivals.g2))
+        dat$attr$recovTime <- c(dat$attr$recovTime, rep(NA, totArrivals.g2))
+        dat$attr$fatTime <- c(dat$attr$fatTime, rep(NA, totArrivals.g2))
+    }
+    
+    # Output ------------------------------------------------------------------
+    if (at == 2) {
+        dat$epi$a.flow <- c(0, totArrivals)
+        dat$epi$a.e.flow <- c(0, nArrivals.e)
+        dat$epi$a.i.flow <- c(0, nArrivals.i)
+        dat$epi$a.q.flow <- c(0, nArrivals.q)
+    } else {
+        dat$epi$a.flow[at] <- totArrivals
+        dat$epi$a.e.flow[at] <- c(0, nArrivals.e)
+        dat$epi$a.i.flow[at] <- c(0, nArrivals.i)
+        dat$epi$a.q.flow[at] <- c(0, nArrivals.q)
+    }
+    if (length(totArrivals.g2) > 0 && dat$param$groups == 2) {
+        if (at == 2) {
+            dat$epi$a.flow.g2 <- c(0, totArrivals.g2)
+            dat$epi$a.e.flow.g2 <- c(0, nArrivals.e.g2)
+            dat$epi$a.i.flow.g2 <- c(0, nArrivals.i.g2)
+            dat$epi$a.q.flow.g2 <- c(0, nArrivals.q.g2)
+        } else {
+            dat$epi$a.flow.g2[at] <- totArrivals.g2
+            dat$epi$a.e.flow.g2[at] <- c(0, nArrivals.e.g2)
+            dat$epi$a.i.flow.g2[at] <- c(0, nArrivals.i.g2)
+            dat$epi$a.q.flow.g2[at] <- c(0, nArrivals.q.g2)
+        }
+    }
+    
+    return(dat)
+}
+
+
+#' Get previous function
+#'
+#' Utility function that collects prevalence and transition time data from each
+#' run and stores it away in the simulation result object. 
+#'
+#' @param dat Input data needed.
+#' @param at Not sure???
+#'
+#' @return Updated dat
+#' 
+get_prev.FUN <- function(dat, at) {
+    
+    if (at == 1) {
+        dat$epi <- list()
+        dat$epi$s.num <- sum(dat$attr$active == 1 &
+                                 dat$attr$status == "s" &
+                                 dat$attr$group == 1)
+        dat$epi$i.num <- sum(dat$attr$active == 1 &
+                                 dat$attr$status == "i" &
+                                 dat$attr$group == 1)
+        if (dat$control$type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+            dat$epi$e.num <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "e" &
+                                     dat$attr$group == 1)
+        }        
+        if (dat$control$type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF")) {
+            dat$epi$r.num <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "r" &
+                                     dat$attr$group == 1)
+        }
+        if (dat$control$type %in% c("SEIQHR", "SEIQHRF")) {
+            dat$epi$q.num <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "q" &
+                                     dat$attr$group == 1)
+            dat$epi$h.num <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "h" &
+                                     dat$attr$group == 1)
+        }
+        if (dat$control$type =="SEIQHRF") {
+            dat$epi$f.num <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "f" &
+                                     dat$attr$group == 1)
+        }
+        if (dat$control$type == "SIR") {
+            dat$epi$num <- dat$epi$s.num +
+                dat$epi$i.num +
+                dat$epi$r.num
+        } else if (dat$control$type == "SEIR") {
+            dat$epi$num <- dat$epi$s.num +
+                dat$epi$e.num +
+                dat$epi$i.num +
+                dat$epi$r.num
+        } else if (dat$control$type == "SEIQHR") {
+            dat$epi$num <- dat$epi$s.num +
+                dat$epi$e.num +
+                dat$epi$i.num +
+                dat$epi$q.num +
+                dat$epi$h.num +
+                dat$epi$r.num
+        } else if (dat$control$type == "SEIQHRF") {
+            dat$epi$num <- dat$epi$s.num +
+                dat$epi$e.num +
+                dat$epi$i.num +
+                dat$epi$q.num +
+                dat$epi$h.num +
+                dat$epi$r.num +
+                dat$epi$f.num
+        } else {
+            dat$epi$num <- dat$epi$s.num + dat$epi$i.num
+        }         
+        if (dat$param$groups == 2) {
+            dat$epi$s.num.g2 <- sum(dat$attr$active == 1 &
+                                        dat$attr$status == "s" &
+                                        dat$attr$group == 2)
+            if (dat$control$type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi$e.num.g2 <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "e" &
+                                            dat$attr$group == 2)
+            }
+            if (dat$control$type %in% c("SEIQHR", "SEIQHRF")) {
+                dat$epi$q.num.g2 <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "q" &
+                                            dat$attr$group == 2)
+                dat$epi$h.num.g2 <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "h" &
+                                            dat$attr$group == 2)
+            }
+            if (dat$control$type %in% c("SEIQHRF")) {
+                dat$epi$f.num.g2 <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "f" &
+                                            dat$attr$group == 2)
+            }
+            dat$epi$i.num.g2 <- sum(dat$attr$active == 1 &
+                                        dat$attr$status == "i" &
+                                        dat$attr$group == 2)
+            dat$epi$num.g2 <- dat$epi$s.num.g2 + dat$epi$i.num.g2
+            if (dat$control$type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi$r.num.g2 <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "r" &
+                                            dat$attr$group == 2)
+            }
+            if (dat$control$type == "SIR") {
+                dat$epi$num.g2 <- dat$epi$s.num.g2 +
+                    dat$epi$i.num.g2 +
+                    dat$epi$r.num.g2
+            } else if (dat$control$type == "SEIR") {
+                dat$epi$num.g2 <- dat$epi$s.num.g2 +
+                    dat$epi$e.num.g2 +
+                    dat$epi$i.num.g2 +
+                    dat$epi$r.num.g2
+            } else if (dat$control$type == "SEIQHR") {
+                dat$epi$num.g2 <- dat$epi$s.num.g2 +
+                    dat$epi$e.num.g2 +
+                    dat$epi$i.num.g2 +
+                    dat$epi$q.num.g2 +
+                    dat$epi$h.num.g2 +
+                    dat$epi$r.num.g2
+            } else if (dat$control$type == "SEIQHRF") {
+                dat$epi$num.g2 <- dat$epi$s.num.g2 +
+                    dat$epi$e.num.g2 +
+                    dat$epi$i.num.g2 +
+                    dat$epi$q.num.g2 +
+                    dat$epi$h.num.g2 +
+                    dat$epi$r.num.g2 +
+                    dat$epi$f.num.g2
+            } else {
+                dat$epi$num.g2 <- dat$epi$s.num.g2 + dat$epi$i.num.g2
+            }         
+        }
+    } else {
+        dat$epi$s.num[at] <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "s" &
+                                     dat$attr$group == 1)
+        if (dat$control$type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+            dat$epi$e.num[at] <- sum(dat$attr$active == 1 &
+                                         dat$attr$status == "e" &
+                                         dat$attr$group == 1)
+        }
+        dat$epi$i.num[at] <- sum(dat$attr$active == 1 &
+                                     dat$attr$status == "i" &
+                                     dat$attr$group == 1)
+        if (dat$control$type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF")) {
+            dat$epi$r.num[at] <- sum(dat$attr$active == 1 &
+                                         dat$attr$status == "r" &
+                                         dat$attr$group == 1)
+        }
+        if (dat$control$type %in% c("SEIQHR", "SEIQHRF")) {
+            dat$epi$q.num[at] <- sum(dat$attr$active == 1 &
+                                         dat$attr$status == "q" &
+                                         dat$attr$group == 1)
+            dat$epi$h.num[at] <- sum(dat$attr$active == 1 &
+                                         dat$attr$status == "h" &
+                                         dat$attr$group == 1)
+        }
+        if (dat$control$type %in% c("SEIQHRF")) {
+            dat$epi$f.num[at] <- sum(dat$attr$active == 1 &
+                                         dat$attr$status == "f" &
+                                         dat$attr$group == 1)
+        }
+        if (dat$control$type == "SIR") {
+            dat$epi$num[at] <- dat$epi$s.num[at] +
+                dat$epi$i.num[at] +
+                dat$epi$r.num[at]
+        } else if (dat$control$type == "SEIR") {
+            dat$epi$num[at] <- dat$epi$s.num[at] +
+                dat$epi$e.num[at] +
+                dat$epi$i.num[at] +
+                dat$epi$r.num[at]
+        } else if (dat$control$type == "SEIQHR") {
+            dat$epi$num[at] <- dat$epi$s.num[at] +
+                dat$epi$e.num[at] +
+                dat$epi$i.num[at] +
+                dat$epi$q.num[at] +
+                dat$epi$h.num[at] +
+                dat$epi$r.num[at]
+        } else if (dat$control$type == "SEIQHRF") {
+            dat$epi$num[at] <- dat$epi$s.num[at] +
+                dat$epi$e.num[at] +
+                dat$epi$i.num[at] +
+                dat$epi$q.num[at] +
+                dat$epi$h.num[at] +
+                dat$epi$r.num[at] +
+                dat$epi$f.num[at]
+        } else {
+            dat$epi$num[at] <- dat$epi$s.num[at] + dat$epi$i.num[at]
+        }
+        
+        if (dat$param$groups == 2) {
+            dat$epi$s.num.g2[at] <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "s" &
+                                            dat$attr$group == 2)
+            if (dat$control$type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi$i.num.g2[at] <- sum(dat$attr$active == 1 &
+                                                dat$attr$status == "e" &
+                                                dat$attr$group == 2)
+            }
+            dat$epi$i.num.g2[at] <- sum(dat$attr$active == 1 &
+                                            dat$attr$status == "i" &
+                                            dat$attr$group == 2)
+            if (dat$control$type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi$r.num.g2[at] <- sum(dat$attr$active == 1 &
+                                                dat$attr$status == "r" &
+                                                dat$attr$group == 2)
+            }
+            if (dat$control$type %in% c("SEIQHR", "SEIQHRF")) {
+                dat$epi$q.num.g2[at] <- sum(dat$attr$active == 1 &
+                                                dat$attr$status == "q" &
+                                                dat$attr$group == 2)
+                dat$epi$h.num.g2[at] <- sum(dat$attr$active == 1 &
+                                                dat$attr$status == "h" &
+                                                dat$attr$group == 2)
+            }
+            if (dat$control$type %in% c("SEIQHRF")) {
+                dat$epi$f.num.g2[at] <- sum(dat$attr$active == 1 &
+                                                dat$attr$status == "f" &
+                                                dat$attr$group == 2)
+            }
+            if (dat$control$type == "SIR") {
+                dat$epi$num.g2[at] <- dat$epi$s.num.g2[at] +
+                    dat$epi$i.num.g2[at] +
+                    dat$epi$r.num.g2[at]
+            } else if (dat$control$type == "SEIR") {
+                dat$epi$num.g2[at] <- dat$epi$s.num.g2[at] +
+                    dat$epi$e.num.g2[at] +
+                    dat$epi$i.num.g2[at] +
+                    dat$epi$r.num.g2[at]
+            } else if (dat$control$type == "SEIQHR") {
+                dat$epi$num.g2[at] <- dat$epi$s.num.g2[at] +
+                    dat$epi$e.num.g2[at] +
+                    dat$epi$i.num.g2[at] +
+                    dat$epi$q.num.g2[at] +
+                    dat$epi$h.num.g2[at] +
+                    dat$epi$r.num.g2[at]
+            } else if (dat$control$type == "SEIQHRF") {
+                dat$epi$num.g2[at] <- dat$epi$s.num.g2[at] +
+                    dat$epi$e.num.g2[at] +
+                    dat$epi$i.num.g2[at] +
+                    dat$epi$q.num.g2[at] +
+                    dat$epi$h.num.g2[at] +
+                    dat$epi$r.num.g2[at] +
+                    dat$epi$f.num.g2[at]
+            } else {
+                dat$epi$num.g2[at] <- dat$epi$s.num.g2[at] +
+                    dat$epi$i.num.g2[at]
+            }
+        }
+    }
+    
+    return(dat)
+}
+
+
diff --git a/R/results-parse.R b/R/results-parse.R
new file mode 100644
index 0000000..7c63959
--- /dev/null
+++ b/R/results-parse.R
@@ -0,0 +1,40 @@
+#' Get times
+#'
+#' Function to extract timings and assemble results in a dataframe
+#'
+#' @param simulate_results  results from `simulte()` function.
+#'
+#' @return Dataframe of 
+
+get_times <- function(simulate_results) {
+    
+    sim <- simulate_results$sim
+    
+    for (s in 1:sim$control$nsims) {
+        if (s == 1) {
+            times <- sim$times[[paste("sim", s, sep = "")]]
+            times <- times %>% mutate(s = s)
+        } else {
+            times <- times %>% bind_rows(sim$times[[paste("sim", s, sep = "")]] 
+                                         %>% mutate(s = s))
+        }
+    }
+    
+    times <- times %>% mutate(infTime = ifelse(infTime < 0, -5, 
+                                               infTime), expTime = ifelse(expTime < 0, -5, expTime)) %>% 
+        mutate(incubation_period = infTime - expTime, illness_duration = recovTime - 
+                   expTime, illness_duration_hosp = dischTime - expTime, 
+               hosp_los = dischTime - hospTime, quarantine_delay = quarTime - 
+                   infTime, survival_time = fatTime - infTime) %>% 
+        select(s, incubation_period, quarantine_delay, illness_duration, 
+               illness_duration_hosp, hosp_los, survival_time) %>% 
+        pivot_longer(-s, names_to = "period_type", values_to = "duration") %>% 
+        mutate(period_type = factor(period_type, levels = c("incubation_period", 
+                                                            "quarantine_delay", "illness_duration", "illness_duration_hosp", 
+                                                            "hosp_los", "survival_time"), labels = c("Incubation period", 
+                                                                                                     "Delay entering isolation", "Illness duration", "Illness duration (hosp)", 
+                                                                                                     "Hospital care required duration", "Survival time of case fatalities"), ordered = TRUE))
+    return(times)
+}
+
+
diff --git a/R/sirPlus-functions.R b/R/sirPlus-functions.R
new file mode 100644
index 0000000..ec2dad1
--- /dev/null
+++ b/R/sirPlus-functions.R
@@ -0,0 +1,956 @@
+#' Infection function
+#'
+#' Function to implement infection processes for SEIQHRF model
+#'
+#' @param param ICM parameters.
+#' @param init Initial value parameters.
+#' @param control Control parameters.
+#'
+#' @return Updated dat
+#' 
+icm.seiqhrf <- function(param, init, control) {
+    
+    crosscheck.icm(param, init, control)
+    verbose.icm(control, type = "startup")
+    nsims <- control$nsims
+    ncores <- ifelse(control$nsims == 1, 1, min(future::availableCores(), control$ncores))
+    control$ncores <- ncores
+    
+    if (ncores == 1) {
+        
+        # Simulation loop start
+        for (s in 1:control$nsims) {
+            
+            ## Initialization module
+            if (!is.null(control[["initialize.FUN"]])) {
+                dat <- do.call(control[["initialize.FUN"]], list(param, init, control))
+            }
+            
+            
+            # Timestep loop
+            for (at in 2:control$nsteps) {
+                
+                ## User Modules
+                um <- control$user.mods
+                if (length(um) > 0) {
+                    for (i in 1:length(um)) {
+                        dat <- do.call(control[[um[i]]], list(dat, at))
+                    }
+                }
+                
+                ## Infection
+                if (!is.null(control[["infection.FUN"]])) {
+                    dat <- do.call(control[["infection.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Recovery
+                if (!is.null(control[["recovery.FUN"]])) {
+                    dat <- do.call(control[["recovery.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Departure Module
+                if (!is.null(control[["departures.FUN"]])) {
+                    dat <- do.call(control[["departures.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Arrival Module
+                if (!is.null(control[["arrivals.FUN"]])) {
+                    dat <- do.call(control[["arrivals.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Outputs
+                if (!is.null(control[["get_prev.FUN"]])) {
+                    dat <- do.call(control[["get_prev.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Track progress
+                verbose.icm(dat, type = "progress", s, at)
+            }
+            
+            # Set output
+            if (s == 1) {
+                out <- saveout.seiqhrf.icm(dat, s)
+            } else {
+                out <- saveout.seiqhrf.icm(dat, s, out)
+            }
+            
+        } # Simulation loop end
+        
+        class(out) <- "icm"
+        
+    } # end of single core execution
+    
+    if (ncores > 1) {  
+        doParallel::registerDoParallel(ncores)
+        
+        sout <- foreach(s = 1:nsims) %dopar% {
+            
+            control$nsims <- 1
+            control$currsim <- s
+            
+            ## Initialization module
+            if (!is.null(control[["initialize.FUN"]])) {
+                dat <- do.call(control[["initialize.FUN"]], list(param, init, control))
+            }
+            
+            # Timestep loop
+            for (at in 2:control$nsteps) {
+                
+                ## User Modules
+                um <- control$user.mods
+                if (length(um) > 0) {
+                    for (i in 1:length(um)) {
+                        dat <- do.call(control[[um[i]]], list(dat, at))
+                    }
+                }
+                
+                ## Infection
+                if (!is.null(control[["infection.FUN"]])) {
+                    dat <- do.call(control[["infection.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Recovery
+                if (!is.null(control[["recovery.FUN"]])) {
+                    dat <- do.call(control[["recovery.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Departure Module
+                if (!is.null(control[["departures.FUN"]])) {
+                    dat <- do.call(control[["departures.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Arrival Module
+                if (!is.null(control[["arrivals.FUN"]])) {
+                    dat <- do.call(control[["arrivals.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Outputs
+                if (!is.null(control[["get_prev.FUN"]])) {
+                    dat <- do.call(control[["get_prev.FUN"]], list(dat, at))
+                }
+                
+                
+                ## Track progress
+                verbose.icm(dat, type = "progress", s, at)
+            }
+            
+            # Set output
+            out <- saveout.seiqhrf.icm(dat, s=1)
+            class(out) <- "icm"
+            return(out)
+            
+        }
+        
+        # aggregate results collected from each thread
+        collected_times <- list()
+        
+        # collect the times from sout then delete them
+        for (i in 1:length(sout)) {
+            collected_times[[paste0("sim", i)]] <- sout[[i]]$times$sim1 
+            sout[[i]]$times <- NULL
+        }
+        
+        # merge $epi structures
+        merged.out <- sout[[1]]
+        for (i in 2:length(sout)) {
+            merged.out <- merge.seiqhrf.icm(merged.out, sout[[i]], param.error = FALSE)
+        }
+        out <- merged.out
+        
+        # add the collected timing data
+        out$times <- collected_times
+        
+        class(out) <- "icm"
+    } # end of parallel execution
+    
+    return(out)
+}
+
+
+#' Initialize status of ICM 
+#'
+#' Function to get the status of the initialized icm
+#'
+#' @param dat Object containing all data
+#'
+#' @return Updated dat
+init_status.icm <- function(dat) {
+    
+    # Variables ---------------------------------------------------------------
+    type <- dat$control$type
+    group <- dat$attr$group
+    nGroups <- dat$param$groups
+    
+    nG1 <- sum(group == 1)
+    nG2 <- sum(group == 2)
+    
+    e.num <- dat$init$e.num
+    i.num <- dat$init$i.num
+    q.num <- dat$init$q.num
+    h.num <- dat$init$h.num
+    r.num <- dat$init$r.num
+    f.num <- dat$init$f.num
+    e.num.g2 <- dat$init$e.num.g2
+    i.num.g2 <- dat$init$i.num.g2
+    q.num.g2 <- dat$init$q.num.g2
+    h.num.g2 <- dat$init$h.num.g2
+    r.num.g2 <- dat$init$r.num.g2
+    f.num.g2 <- dat$init$f.num.g2
+    
+    # Status ------------------------------------------------------------------
+    status <- rep("s", nG1 + nG2)
+    status[sample(which(group == 1), size = i.num)] <- "i"
+    if (nGroups == 2) {
+        status[sample(which(group == 2), size = i.num.g2)] <- "i"
+    }
+    if (type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF")) {
+        status[sample(which(group == 1 & status == "s"), size = r.num)] <- "r"
+        if (nGroups == 2) {
+            status[sample(which(group == 2 & status == "s"), size = r.num.g2)] <- "r"
+        }
+    }
+    if (type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+        status[sample(which(group == 1 & status == "s"), size = e.num)] <- "e"
+        if (nGroups == 2) {
+            status[sample(which(group == 2 & status == "s"), size = e.num.g2)] <- "e"
+        }
+    }
+    if (type %in% c("SEIQHR", "SEIQHRF")) {
+        status[sample(which(group == 1 & status == "s"), size = q.num)] <- "q"
+        if (nGroups == 2) {
+            status[sample(which(group == 2 & status == "s"), size = q.num.g2)] <- "q"
+        }
+        status[sample(which(group == 1 & status == "s"), size = h.num)] <- "h"
+        if (nGroups == 2) {
+            status[sample(which(group == 2 & status == "s"), size = h.num.g2)] <- "h"
+        }
+    }
+    if (type %in% c("SEIQHRF")) {
+        status[sample(which(group == 1 & status == "s"), size = f.num)] <- "f"
+        if (nGroups == 2) {
+            status[sample(which(group == 2 & status == "s"), size = f.num.g2)] <- "f"
+        }
+    }
+    
+    dat$attr$status <- status
+    
+    
+    # Exposure Time ----------------------------------------------------------
+    idsExp <- which(status == "e")
+    expTime <- rep(NA, length(status))
+    # leave exposure time uninitialised for now, and 
+    # just set to NA at start.
+    dat$attr$expTime <- expTime
+    
+    # Infection Time ----------------------------------------------------------
+    idsInf <- which(status == "i")
+    infTime <- rep(NA, length(status))
+    dat$attr$infTime <- infTime # overwritten below
+    
+    # Recovery Time ----------------------------------------------------------
+    idsRecov <- which(status == "r")
+    recovTime <- rep(NA, length(status))
+    dat$attr$recovTime <- recovTime
+    
+    # Need for Hospitalisation Time ----------------------------------------------------------
+    idsHosp <- which(status == "h")
+    hospTime <- rep(NA, length(status))
+    dat$attr$hospTime <- hospTime
+    
+    # Quarantine Time ----------------------------------------------------------
+    idsQuar <- which(status == "q")
+    quarTime <- rep(NA, length(status))
+    dat$attr$quarTime <- quarTime
+    
+    # Hospital-need cessation  Time ----------------------------------------------------------
+    dischTime <- rep(NA, length(status))
+    dat$attr$dischTime <- dischTime
+    
+    # Case-fatality  Time ----------------------------------------------------------
+    fatTime <- rep(NA, length(status))
+    dat$attr$fatTime <- fatTime
+    
+    # If vital=TRUE, infTime is a uniform draw over the duration of infection
+    # note the initial infections may have negative infTime!
+    if (FALSE) {
+        # not sure what the following section is trying to do, but it
+        # mucks up the gamma-distributed incumabtion periods, so set 
+        # infTime for initial infected people to t=1 instead
+        if (dat$param$vital == TRUE && dat$param$di.rate > 0) {
+            infTime[idsInf] <- -rgeom(n = length(idsInf), prob = dat$param$di.rate) + 2
+        } else {
+            if (dat$control$type == "SI" || dat$param$rec.rate == 0) {
+                # infTime a uniform draw over the number of sim time steps
+                infTime[idsInf] <- ssample(1:(-dat$control$nsteps + 2),
+                                           length(idsInf), replace = TRUE)
+            } else {
+                if (nGroups == 1) {
+                    infTime[idsInf] <- ssample(1:(-round(1 / dat$param$rec.rate) + 2),
+                                               length(idsInf), replace = TRUE)
+                }
+                if (nGroups == 2) {
+                    infG1 <- which(status == "i" & group == 1)
+                    infTime[infG1] <- ssample(1:(-round(1 / dat$param$rec.rate) + 2),
+                                              length(infG1), replace = TRUE)
+                    infG2 <- which(status == "i" & group == 2)
+                    infTime[infG2] <- ssample(1:(-round(1 / dat$param$rec.rate.g2) + 2),
+                                              length(infG2), replace = TRUE)
+                }
+            }
+        }
+    }
+    infTime[idsInf] <- 1
+    dat$attr$infTime <- infTime
+    
+    return(dat)
+}
+
+
+#' Check control ICM
+#'
+#' Function to check the control icm
+#'
+#' @param type Model type
+#'
+#' @return Control icm
+control.icm <- function(type, nsteps, nsims = 1, 
+                        rec.rand = TRUE, quar.rand = TRUE, hosp.rand = TRUE, disch.rand = TRUE,
+                        fat.rand = TRUE, a.rand = TRUE, d.rand = TRUE, initialize.FUN = initialize.FUN,
+                        infection.FUN = infection.FUN, recovery.FUN = recovery.FUN,
+                        departures.FUN = departures.FUN, arrivals.FUN = arrivals.FUN,
+                        get_prev.FUN = get_prev.FUN, verbose = FALSE,
+                        verbose.int = 0, skip.check = FALSE, ncores=1, ...) {
+    
+    # Get arguments
+    p <- list()
+    formal.args <- formals(sys.function())
+    formal.args[["..."]] <- NULL
+    for (arg in names(formal.args)) {
+        if (as.logical(mget(arg) != "")) {
+            p[arg] <- list(get(arg))
+        }
+    }
+    dot.args <- list(...)
+    names.dot.args <- names(dot.args)
+    if (length(dot.args) > 0) {
+        for (i in 1:length(dot.args)) {
+            p[[names.dot.args[i]]] <- dot.args[[i]]
+        }
+    }
+    
+    if ("births.FUN" %in% names(dot.args)) {
+        p$arrivals.FUN <- dot.args$births.FUN
+        p$births.FUN <- dot.args$births.FUN <- NULL
+        message("EpiModel 1.7.0 onward renamed the birth function births.FUN to arrivals.FUN. See documentation for details.")
+    }
+    if ("deaths.FUN" %in% names(dot.args)) {
+        p$departures.FUN <- dot.args$deaths.FUN
+        p$deaths.FUN <- dot.args$deaths.FUN <- NULL
+        message("EpiModel 1.7.0 onward renamed the death function deaths.FUN to departures.FUN. See documentation for details.")
+    }
+    
+    
+    ## Module classification
+    p$bi.mods <- grep(".FUN", names(formal.args), value = TRUE)
+    p$user.mods <- grep(".FUN", names(dot.args), value = TRUE)
+    
+    
+    ## Defaults and checks
+    if (is.null(p$type) | !(p$type %in% c("SI", "SIS", "SIR", "SEIR", "SEIQHR", "SEIQHRF"))) {
+        stop("Specify type as \"SI\", \"SIS\", \"SIR\", \"SEIR\", \"SEIQHR\", or \"SEIQHRF\" ", call. = FALSE)
+    }
+    if (is.null(p$nsteps)) {
+        stop("Specify nsteps", call. = FALSE)
+    }
+    
+    
+    ## Output
+    class(p) <- c("control.icm", "list")
+    return(p)
+}
+
+
+#' Merge icm
+#'
+#' Function to merge icms
+#'
+#' @param x First to merge
+#' @param y Second to merge
+#'
+#' @return Combined
+merge.seiqhrf.icm <- function(x, y, ...) {
+    
+    ## Check structure
+    if (length(x) != length(y) || !identical(names(x), names(y))) {
+        stop("x and y have different structure")
+    }
+    if (x$control$nsims > 1 & y$control$nsims > 1 &
+        !identical(sapply(x, class), sapply(y, class))) {
+        stop("x and y have different structure")
+    }
+    
+    ## Check params
+    check1 <- identical(x$param, y$param)
+    check2 <- identical(x$control[-which(names(x$control) %in% c("nsims", "currsim"))],
+                        y$control[-which(names(y$control) %in% c("nsims", "currsim"))])
+    
+    if (check1 == FALSE) {
+        stop("x and y have different parameters")
+    }
+    if (check2 == FALSE) {
+        stop("x and y have different controls")
+    }
+    
+    
+    z <- x
+    new.range <- (x$control$nsims + 1):(x$control$nsims + y$control$nsims)
+    
+    # Merge data
+    for (i in 1:length(x$epi)) {
+        if (x$control$nsims == 1) {
+            x$epi[[i]] <- data.frame(x$epi[[i]])
+        }
+        if (y$control$nsims == 1) {
+            y$epi[[i]] <- data.frame(y$epi[[i]])
+        }
+        z$epi[[i]] <- cbind(x$epi[[i]], y$epi[[i]])
+        names(z$epi[[i]])[new.range] <- paste0("sim", new.range)
+    }
+    
+    z$control$nsims <- max(new.range)
+    
+    return(z)
+}
+
+
+
+#' Progress icm
+#'
+#' Function to get progress of icms
+#'
+#' @param dat Object containing all data
+#' @param at ?
+#'
+#' @return progress
+progress.seiqhrf.icm <- function(dat, at) {
+    
+    #print(at)
+    #print(dat$control$type)
+    #print("-------")
+    
+    # Conditions --------------------------------------------------------------
+    if (!(dat$control$type %in% c("SIR", "SIS", "SEIR", "SEIQHR", "SEIQHRF"))) {
+        return(dat)
+    }
+    
+    
+    # Variables ---------------------------------------------------------------
+    active <- dat$attr$active
+    status <- dat$attr$status
+    
+    groups <- dat$param$groups
+    group <- dat$attr$group
+    
+    type <- dat$control$type
+    recovState <- ifelse(type %in% c("SIR", "SEIR", "SEIQHR", "SEIQHRF"), "r", "s")
+    progState <- "i"
+    quarState <- "q"
+    hospState <- "h"
+    fatState <- "f"
+    
+    # --- progress from exposed to infectious ----
+    prog.rand <- dat$control$prog.rand
+    prog.rate <- dat$param$prog.rate
+    prog.rate.g2 <- dat$param$prog.rate.g2
+    prog.dist.scale <- dat$param$prog.dist.scale
+    prog.dist.shape <- dat$param$prog.dist.shape
+    prog.dist.scale.g2 <- dat$param$prog.dist.scale.g2
+    prog.dist.shape.g2 <- dat$param$prog.dist.shape.g2
+    
+    nProg <- nProgG2 <- 0
+    idsElig <- which(active == 1 & status == "e")
+    nElig <- length(idsElig)
+    
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(prog.rate, prog.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (prog.rand == TRUE) {
+            vecProg <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecProg) > 0) {
+                idsProg <- idsElig[vecProg]
+                nProg <- sum(group[idsProg] == 1)
+                nProgG2 <- sum(group[idsProg] == 2)
+                status[idsProg] <- progState
+                dat$attr$infTime[idsProg] <- at
+            }
+        } else {
+            vecTimeSinceExp <- at - dat$attr$expTime[idsElig]
+            gammaRatesElig <- pweibull(vecTimeSinceExp, prog.dist.shape, scale=prog.dist.scale) 
+            nProg <- round(sum(gammaRatesElig[gElig == 1], na.rm=TRUE))
+            if (nProg > 0) {
+                ids2bProg <- ssample(idsElig[gElig == 1], 
+                                     nProg, prob = gammaRatesElig[gElig == 1])
+                status[ids2bProg] <- progState
+                dat$attr$infTime[ids2bProg] <- at
+                # debug
+                if (FALSE & at <= 30) {
+                    print(paste("at:", at))
+                    print("idsElig:")
+                    print(idsElig[gElig == 1])
+                    print("vecTimeSinceExp:")
+                    print(vecTimeSinceExp[gElig == 1])
+                    print("gammaRatesElig:")
+                    print(gammaRatesElig)
+                    print(paste("nProg:",nProg))
+                    print(paste("sum of elig rates:", round(sum(gammaRatesElig[gElig == 1]))))
+                    print(paste("sum(gElig == 1):", sum(gElig == 1)))
+                    print("ids progressed:")
+                    print(ids2bProg)
+                    print("probs of ids to be progressed:")
+                    print(gammaRatesElig[which(idsElig %in% ids2bProg)]) 
+                    print("days since exposed of ids to be progressed:")
+                    print(vecTimeSinceExp[which(idsElig %in% ids2bProg)]) 
+                    print("------")
+                }  
+            }
+            if (groups == 2) {
+                nProgG2 <- round(sum(gammaRatesElig[gElig == 2], na.rm=TRUE))
+                if (nProgG2 > 0) {
+                    ids2bProgG2 <- ssample(idsElig[gElig == 2], 
+                                           nProgG2, prob = gammaRatesElig[gElig == 2])
+                    status[ids2bProgG2] <- progState
+                    dat$attr$infTime[ids2bProgG2] <- at
+                }
+            }
+        }
+    }
+    dat$attr$status <- status
+    
+    if (type %in% c("SEIQHR", "SEIQHRF")) {  
+        # ----- quarantine ------- 
+        quar.rand <- dat$control$quar.rand
+        quar.rate <- dat$param$quar.rate
+        quar.rate.g2 <- dat$param$quar.rate.g2
+        
+        nQuar <- nQuarG2 <- 0
+        idsElig <- which(active == 1 & status == "i")
+        nElig <- length(idsElig)
+        
+        if (nElig > 0) {
+            
+            gElig <- group[idsElig]
+            rates <- c(quar.rate, quar.rate.g2)
+            
+            if (length(quar.rate) > 1) {
+                qrate <- quar.rate[at]
+            } else {
+                qrate <- quar.rate
+            }
+            if (length(quar.rate.g2) > 1) {
+                qrate.g2 <- quar.rate.g2[at]
+            } else {
+                qrate.g2 <- quar.rate.g2
+            }
+            rates <- c(qrate, qrate.g2)
+            ratesElig <- rates[gElig]
+            if (quar.rand == TRUE) {
+                vecQuar <- which(rbinom(nElig, 1, ratesElig) == 1)
+                if (length(vecQuar) > 0) {
+                    idsQuar <- idsElig[vecQuar]
+                    nQuar <- sum(group[idsQuar] == 1)
+                    nQuarG2 <- sum(group[idsQuar] == 2)
+                    status[idsQuar] <- quarState
+                    dat$attr$quarTime[idsQuar] <- at
+                }
+            } else {
+                nQuar <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+                idsQuar <- ssample(idsElig[gElig == 1], nQuar)
+                status[idsQuar] <- quarState
+                dat$attr$quarTime[idsQuar] <- at
+                if (groups == 2) {
+                    nQuarG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                    idsQuarG2 <- ssample(idsElig[gElig == 2], nQuarG2)
+                    status[idsQuarG2] <- quarState
+                    dat$attr$quarTime[idsQuarG2] <- at
+                }
+            }
+        }
+        dat$attr$status <- status
+        
+        # ----- need to be hospitalised ------- 
+        hosp.rand <- dat$control$hosp.rand
+        hosp.rate <- dat$param$hosp.rate
+        hosp.rate.g2 <- dat$param$hosp.rate.g2
+        
+        nHosp <- nHospG2 <- 0
+        idsElig <- which(active == 1 & (status == "i" | status == "q"))
+        nElig <- length(idsElig)
+        idsHosp <- numeric(0)
+        
+        if (nElig > 0) {
+            
+            gElig <- group[idsElig]
+            rates <- c(hosp.rate, hosp.rate.g2)
+            ratesElig <- rates[gElig]
+            
+            if (hosp.rand == TRUE) {
+                vecHosp <- which(rbinom(nElig, 1, ratesElig) == 1)
+                if (length(vecHosp) > 0) {
+                    idsHosp <- idsElig[vecHosp]
+                    nHosp <- sum(group[idsHosp] == 1)
+                    nHospG2 <- sum(group[idsHosp] == 2)
+                    status[idsHosp] <- hospState
+                }
+            } else {
+                nHosp <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+                idsHosp <- ssample(idsElig[gElig == 1], nHosp)
+                status[idsHosp] <- hospState
+                if (groups == 2) {
+                    nHospG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                    idsHospG2 <- ssample(idsElig[gElig == 2], nHospG2)
+                    status[idsHospG2] <- hospState
+                    idsHosp <- c(idsHosp, idsHospG2)
+                }
+            }
+        }
+        dat$attr$status <- status
+        dat$attr$hospTime[idsHosp] <- at
+        
+        # ----- discharge from need to be hospitalised ------- 
+        disch.rand <- dat$control$disch.rand
+        disch.rate <- dat$param$disch.rate
+        disch.rate.g2 <- dat$param$disch.rate.g2
+        
+        nDisch <- nDischG2 <- 0
+        idsElig <- which(active == 1 & status == "h")
+        nElig <- length(idsElig)
+        idsDisch <- numeric(0)
+        
+        if (nElig > 0) {
+            
+            gElig <- group[idsElig]
+            rates <- c(disch.rate, disch.rate.g2)
+            
+            if (length(disch.rate) > 1) {
+                dcrate <- disch.rate[at]
+            } else {
+                dcrate <- disch.rate
+            }
+            if (length(disch.rate.g2) > 1) {
+                dcrate.g2 <- disch.rate.g2[at]
+            } else {
+                dcrate.g2 <- disch.rate.g2
+            }
+            
+            rates <- c(dcrate, dcrate.g2)
+            ratesElig <- rates[gElig]
+            
+            if (disch.rand == TRUE) {
+                vecDisch <- which(rbinom(nElig, 1, ratesElig) == 1)
+                if (length(vecDisch) > 0) {
+                    idsDisch <- idsElig[vecDisch]
+                    nDisch <- sum(group[idsDisch] == 1)
+                    nDischG2 <- sum(group[idsDisch] == 2)
+                    status[idsDisch] <- recovState
+                }
+            } else {
+                nDisch <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+                idsDisch <- ssample(idsElig[gElig == 1], nDisch)
+                status[idsDisch] <- recovState
+                if (groups == 2) {
+                    nDischG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                    idsDischG2 <- ssample(idsElig[gElig == 2], nDischG2)
+                    status[idsDischG2] <- recovState
+                    idsDisch <- c(idsDisch, idsDischG2)
+                }
+            }
+        }
+        dat$attr$status <- status
+        dat$attr$dischTime[idsDisch] <- at
+    }
+    
+    # ----- recover ------- 
+    rec.rand <- dat$control$rec.rand
+    rec.rate <- dat$param$rec.rate
+    rec.rate.g2 <- dat$param$rec.rate.g2
+    rec.dist.scale <- dat$param$rec.dist.scale
+    rec.dist.shape <- dat$param$rec.dist.shape
+    rec.dist.scale.g2 <- dat$param$rec.dist.scale.g2
+    rec.dist.shape.g2 <- dat$param$rec.dist.shape.g2
+    
+    nRecov <- nRecovG2 <- 0
+    idsElig <- which(active == 1 & (status == "i" | status == "q" | status == "h"))
+    nElig <- length(idsElig)
+    idsRecov <- numeric(0)
+    
+    if (nElig > 0) {
+        
+        gElig <- group[idsElig]
+        rates <- c(rec.rate, rec.rate.g2)
+        ratesElig <- rates[gElig]
+        
+        if (rec.rand == TRUE) {
+            vecRecov <- which(rbinom(nElig, 1, ratesElig) == 1)
+            if (length(vecRecov) > 0) {
+                idsRecov <- idsElig[vecRecov]
+                nRecov <- sum(group[idsRecov] == 1)
+                nRecovG2 <- sum(group[idsRecov] == 2)
+                status[idsRecov] <- recovState
+            }
+        } else {
+            vecTimeSinceExp <- at - dat$attr$expTime[idsElig]
+            vecTimeSinceExp[is.na(vecTimeSinceExp)] <- 0
+            gammaRatesElig <- pweibull(vecTimeSinceExp, rec.dist.shape, scale=rec.dist.scale) 
+            nRecov <- round(sum(gammaRatesElig[gElig == 1], na.rm=TRUE))
+            if (nRecov > 0) {
+                idsRecov <- ssample(idsElig[gElig == 1], 
+                                    nRecov, prob = gammaRatesElig[gElig == 1])
+                status[idsRecov] <- recovState
+                # debug
+                if (FALSE & at <= 30) {
+                    print(paste("at:", at))
+                    print("idsElig:")
+                    print(idsElig[gElig == 1])
+                    print("vecTimeSinceExp:")
+                    print(vecTimeSinceExp[gElig == 1])
+                    print("gammaRatesElig:")
+                    print(gammaRatesElig)
+                    print(paste("nRecov:",nRecov))
+                    print(paste("sum of elig rates:", round(sum(gammaRatesElig[gElig == 1]))))
+                    print(paste("sum(gElig == 1):", sum(gElig == 1)))
+                    print("ids recovered:")
+                    print(idsRecov)
+                    print("probs of ids to be progressed:")
+                    print(gammaRatesElig[which(idsElig %in% idsRecov)]) 
+                    print("days since exposed of ids to be Recovered:")
+                    print(vecTimeSinceExp[which(idsElig %in% idsRecov)]) 
+                    print("------")
+                }  
+                
+            }
+            if (groups == 2) {
+                nRecovG2 <- round(sum(gammaRatesElig[gElig == 2], na.rm=TRUE))
+                if (nRecovG2 > 0) {
+                    idsRecovG2 <- ssample(idsElig[gElig == 2], 
+                                          nRecovG2, prob = gammaRatesElig[gElig == 2])
+                    status[idsRecovG2] <- recovState
+                    idsRecov <- c(idsRecov, idsRecovG2)
+                }
+            }
+        }
+    }
+    dat$attr$status <- status
+    dat$attr$recovTime[idsRecov] <- at
+    
+    fatEnable <- TRUE
+    if (fatEnable & type %in% c("SEIQHRF")) {  
+        # ----- case fatality ------- 
+        fat.rand <- dat$control$fat.rand
+        fat.rate.base <- dat$param$fat.rate.base
+        fat.rate.base.g2 <- dat$param$fat.rate.base.g2
+        fat.rate.base.g2 <- ifelse(is.null(fat.rate.base.g2), 
+                                   0, fat.rate.base.g2)
+        fat.rate.overcap <- dat$param$fat.rate.overcap
+        fat.rate.overcap.g2 <- dat$param$fat.rate.overcap.g2
+        fat.rate.overcap.g2 <- ifelse(is.null(fat.rate.overcap.g2), 
+                                      0, fat.rate.overcap.g2)
+        hosp.cap <- dat$param$hosp.cap
+        fat.tcoeff <- dat$param$fat.tcoeff
+        
+        nFat <- nFatG2 <- 0
+        idsElig <- which(active == 1 & status =="h")
+        nElig <- length(idsElig)
+        
+        if (nElig > 0) {
+            gElig <- group[idsElig]
+            timeInHospElig <- at - dat$attr$hospTime[idsElig]
+            rates <- c(fat.rate.base, fat.rate.base.g2)
+            h.num.yesterday <- 0
+            if (!is.null(dat$epi$h.num[at - 1])) {
+                h.num.yesterday <- dat$epi$h.num[at - 1]
+                if (h.num.yesterday > hosp.cap) {
+                    blended.rate <- ((hosp.cap * fat.rate.base) + 
+                                         ((h.num.yesterday - hosp.cap) * fat.rate.overcap)) / 
+                        h.num.yesterday
+                    blended.rate.g2 <- ((hosp.cap * fat.rate.base.g2) + 
+                                            ((h.num.yesterday - hosp.cap) * fat.rate.overcap.g2)) / 
+                        h.num.yesterday
+                    rates <- c(blended.rate, blended.rate.g2)
+                }  
+            } 
+            ratesElig <- rates[gElig]
+            ratesElig <- ratesElig + timeInHospElig*fat.tcoeff*ratesElig
+            
+            if (fat.rand == TRUE) {
+                vecFat <- which(rbinom(nElig, 1, ratesElig) == 1)
+                if (length(vecFat) > 0) {
+                    idsFat <- idsElig[vecFat]
+                    nFat <- sum(group[idsFat] == 1)
+                    nFatG2 <- sum(group[idsFat] == 2)
+                    status[idsFat] <- fatState
+                    dat$attr$fatTime[idsFat] <- at
+                }
+            } else {
+                nFat <- min(round(sum(ratesElig[gElig == 1])), sum(gElig == 1))
+                idsFat <- ssample(idsElig[gElig == 1], nFat)
+                status[idsFat] <- fatState
+                dat$attr$fatTime[idsFat] <- at
+                if (groups == 2) {
+                    nFatG2 <- min(round(sum(ratesElig[gElig == 2])), sum(gElig == 2))
+                    idsFatG2 <- ssample(idsElig[gElig == 2], nFatG2)
+                    status[idsFatG2] <- fatState
+                    dat$attr$fatTime[idsFatG2] <- at
+                }
+            }
+        }
+        dat$attr$status <- status
+    }
+    
+    # Output ------------------------------------------------------------------
+    outName_a <- ifelse(type %in% c("SIR", "SEIR"), "ir.flow", "is.flow")
+    outName_a[2] <- paste0(outName_a, ".g2")
+    if (type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+        outName_b <- "ei.flow"
+        outName_b[2] <- paste0(outName_b, ".g2")
+    }
+    if (type %in% c("SEIQHR", "SEIQHRF")) {
+        outName_c <- "iq.flow"
+        outName_c[2] <- paste0(outName_c, ".g2")
+        outName_d <- "iq2h.flow"
+        outName_d[2] <- paste0(outName_d, ".g2")
+    }
+    if (type %in% c("SEIQHRF")) {
+        outName_e <- "hf.flow"
+        outName_e[2] <- paste0(outName_e, ".g2")
+    }
+    ## Summary statistics
+    if (at == 2) {
+        dat$epi[[outName_a[1]]] <- c(0, nRecov)
+        if (type %in% c("SEIR", "SEIQHR")) {
+            dat$epi[[outName_b[1]]] <- c(0, nProg) 
+        }
+        if (type %in% c("SEIQHR", "SEIQHRF")) {
+            dat$epi[[outName_c[1]]] <- c(0, nQuar) 
+            dat$epi[[outName_d[1]]] <- c(0, nHosp) 
+        }
+        if (fatEnable & type %in% c("SEIQHRF")) {
+            dat$epi[[outName_e[1]]] <- c(0, nFat) 
+        }
+    } else {
+        dat$epi[[outName_a[1]]][at] <- nRecov
+        if (type %in% c("SEIR", "SEIQHR")) {
+            dat$epi[[outName_b[1]]][at] <- nProg 
+        }
+        if (type %in% c("SEIQHR", "SEIQHRF")) {
+            dat$epi[[outName_c[1]]][at] <- nQuar 
+            dat$epi[[outName_d[1]]][at] <- nHosp 
+        }
+        if (fatEnable & type %in% c("SEIQHRF")) {
+            dat$epi[[outName_e[1]]][at] <- nFat 
+        }
+    }
+    if (groups == 2) {
+        if (at == 2) {
+            dat$epi[[outName_a[2]]] <- c(0, nRecovG2)
+            if (type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi[[outName_b[2]]] <- c(0, nProgG2) 
+            }
+            if (type %in% c("SEIQHR", "SEIQHRF")) {
+                dat$epi[[outName_c[2]]] <- c(0, nQuarG2) 
+                dat$epi[[outName_d[2]]] <- c(0, nHospG2) 
+            }
+            if (type %in% c("SEIQHRF")) {
+                dat$epi[[outName_e[2]]] <- c(0, nFatG2) 
+            }
+        } else {
+            dat$epi[[outName_a[2]]][at] <- nRecovG2
+            if (type %in% c("SEIR", "SEIQHR", "SEIQHRF")) {
+                dat$epi[[outName_b[2]]][at] <- nProgG2 
+            }
+            if (type %in% c("SEIQHR", "SEIQHRF")) {
+                dat$epi[[outName_c[2]]][at] <- nQuarG2 
+                dat$epi[[outName_d[2]]][at] <- nHospG2 
+            }
+            if (type %in% c("SEIQHRF")) {
+                dat$epi[[outName_e[2]]][at] <- nFatG2 
+            }
+        }
+    }
+    
+    return(dat)
+}
+
+#' Save icm
+#' 
+#' Function to save icm
+#' 
+#' @param dat Object containing all data
+#' @param at ?
+#' @param out ?
+#' 
+#' @return out to save
+#' 
+saveout.seiqhrf.icm <- function(dat, s, out = NULL) {
+    
+    alist2df <- function(dat,s) {
+        alist <- list()
+        alist$expTime <- dat$attr$expTime
+        alist$infTime <- dat$attr$infTime
+        alist$quarTime <- dat$attr$quarTime
+        alist$recovTime <- dat$attr$recovTime
+        alist$hospTime <- dat$attr$hospTime
+        alist$dischTime <- dat$attr$dischTime
+        alist$fatTime <- dat$attr$fatTime
+        alist <- lapply(alist, `length<-`, max(lengths(alist)))
+        return(data.frame(alist))
+    }
+    
+    if (s == 1) {
+        out <- list()
+        out$param <- dat$param
+        out$control <- dat$control
+        out$epi <- list()
+        for (j in 1:length(dat$epi)) {
+            out$epi[[names(dat$epi)[j]]] <- data.frame(dat$epi[j])
+        }
+    } else {
+        for (j in 1:length(dat$epi)) {
+            out$epi[[names(dat$epi)[j]]][, s] <- data.frame(dat$epi[j])
+        }
+    }
+    
+    # capture transition times from attribs  
+    if (dat$control$type %in% c("SEIQHR", "SEIQHRF")) {
+        out$times[[paste("sim",s,sep="")]] <- alist2df(dat,s)  
+    }
+    
+    ## Processing for final run
+    if (s == dat$getParam(control, 'nsims')) {
+        
+        # Remove functions from control list
+        ftodel <- grep(".FUN", names(out$control), value = TRUE)
+        out$control[ftodel] <- NULL
+        
+        # Set column names for varying list elements
+        for (i in as.vector(which(lapply(out$epi, class) == "data.frame"))) {
+            colnames(out$epi[[i]]) <- paste0("sim", 1:dat$getParam(control, 'nsims'))
+        }
+        
+    }
+    
+    return(out)
+}
+
+    
\ No newline at end of file
diff --git a/R/sirPlus-package.R b/R/sirPlus-package.R
new file mode 100644
index 0000000..49512df
--- /dev/null
+++ b/R/sirPlus-package.R
@@ -0,0 +1,9 @@
+#' sirPlus
+#'
+#' \pkg{sirPlus} is a package for modeling COVID-19 spread, focusing on rates
+#' of hospitalization, which should be useful for hospitals.
+#'
+#'
+#' @name sirPlus
+#' @docType package
+NULL
diff --git a/R/utils.R b/R/utils.R
index 155ea80..30886a1 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -1,38 +1,3 @@
-#' @importFrom utils globalVariables
-utils::globalVariables(c("pval_nominal", 'perc', 'ex_pairs', 'ex_means'))
-
-#' Logistic function
-#'
-#' Implementation of the logistic function
-#'
-#' @param x value to apply the function to.
-#' @param x0 midpoint parameter. Gives the centre of the function.
-#' @param k shape parameter. Gives the slope of the function.
-#'
-#' @return Value of logistic function with given parameters
-logistic <- function(x, x0, k) {
-    1 / (1 + exp(-k * (x - x0)))
-}
-
-#' Bind rows (matched)
-#'
-#' Bind the rows of two data frames, keeping only the columns that are common
-#' to both.
-#'
-#' @param df1 first data.frame to bind.
-#' @param df2 second data.frame to bind.
-#'
-#' @return data.frame containing rows from \code{df1} and \code{df2} but only
-#'         common columns.
-rbindMatched <- function(df1, df2) {
-    common.names <- intersect(names(df1), names(df2))
-    if (length(common.names) < 2) {
-        stop("There must be at least two columns in common")
-    }
-    combined <- rbind(df1[, common.names], df2[, common.names])
-
-    return(combined)
-}
 
 #' Bring items forward
 #'
@@ -61,39 +26,28 @@ bringItemsForward <- function(ll, items) {
     return(ll)
 }
 
-#' Winsorize vector
-#'
-#' Set outliers in a numeric vector to a specified percentile.
-#'
-#' @param x Numeric vector to winsorize
-#' @param q Percentile to set from each end
-#'
-#' @return Winsorized numeric vector
-winsorize <- function(x, q) {
-
-    checkmate::check_numeric(x, any.missing = FALSE)
-    checkmate::check_number(q, lower = 0, upper = 1)
-
-    lohi <- stats::quantile(x, c(q, 1 - q), na.rm = TRUE)
-
-    if (diff(lohi) < 0) { lohi <- rev(lohi) }
-
-    x[!is.na(x) & x < lohi[1]] <- lohi[1]
-    x[!is.na(x) & x > lohi[2]] <- lohi[2]
-
-    return(x)
-}
-
-#' Calculate coefficient of variation
-#'
-#' Implementation of the coefficient of variation
+#' cum_discr_si
 #'
-#' @param x vector of values.
+#' cum_discr_si
 #'
+#' @param vecTimeSinceExp ?
+#' @param scale ?
+#' @param shape ?
+#' 
 #' @return Value of coefficient of variation for vector
 #' @importFrom stats sd
-co.var <- function(x) {
-    sd(x)/mean(x) 
-} 
+cum_discr_si <- function(vecTimeSinceExp, scale, shape) {
+    vlen <- length(vecTimeSinceExp)
+    if (vlen > 0) {
+        probVec <- numeric(vlen)
+        for (p in 1:vlen) {
+            probVec[p] <- pweibull(vecTimeSinceExp[p], shape=shape, scale=scale)
+        }
+    } else {
+        probVec <- 0    
+    }
+    return(probVec)
+}
+
 
 
diff --git a/man/arrivals.FUN.Rd b/man/arrivals.FUN.Rd
new file mode 100644
index 0000000..285952a
--- /dev/null
+++ b/man/arrivals.FUN.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{arrivals.FUN}
+\alias{arrivals.FUN}
+\title{Arrivals function}
+\usage{
+arrivals.FUN(dat, at)
+}
+\arguments{
+\item{dat}{Input data needed.}
+
+\item{at}{Not sure???}
+}
+\value{
+Updated dat
+}
+\description{
+Function to handel background demographics for the SEIQHRF model. 
+Specifically arrivals (births and immigration). Uses the original EpiModel
+code currently. A replacement that implements modelling the arrival of 
+infected individuals is under development -- but for now, all arrivals 
+go into the S compartment..
+}
diff --git a/man/control.icm.Rd b/man/control.icm.Rd
new file mode 100644
index 0000000..92fe5aa
--- /dev/null
+++ b/man/control.icm.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{control.icm}
+\alias{control.icm}
+\title{Check control ICM}
+\usage{
+control.icm(
+  type,
+  nsteps,
+  nsims = 1,
+  rec.rand = TRUE,
+  quar.rand = TRUE,
+  hosp.rand = TRUE,
+  disch.rand = TRUE,
+  fat.rand = TRUE,
+  a.rand = TRUE,
+  d.rand = TRUE,
+  initialize.FUN = initialize.icm,
+  infection.FUN = infection.icm,
+  recovery.FUN = recovery.icm,
+  departures.FUN = departures.icm,
+  arrivals.FUN = arrivals.icm,
+  get_prev.FUN = get_prev.icm,
+  verbose = FALSE,
+  verbose.int = 0,
+  skip.check = FALSE,
+  ncores = 1,
+  ...
+)
+}
+\arguments{
+\item{type}{Model type}
+}
+\value{
+Control icm
+}
+\description{
+Function to check the control icm
+}
diff --git a/man/cum_discr_si.Rd b/man/cum_discr_si.Rd
new file mode 100644
index 0000000..18214e7
--- /dev/null
+++ b/man/cum_discr_si.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{cum_discr_si}
+\alias{cum_discr_si}
+\title{cum_discr_si}
+\usage{
+cum_discr_si(vecTimeSinceExp, scale, shape)
+}
+\arguments{
+\item{vecTimeSinceExp}{?}
+
+\item{scale}{?}
+
+\item{shape}{?}
+}
+\value{
+Value of coefficient of variation for vector
+}
+\description{
+cum_discr_si
+}
diff --git a/man/departures.FUN.Rd b/man/departures.FUN.Rd
new file mode 100644
index 0000000..b8aba6e
--- /dev/null
+++ b/man/departures.FUN.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{departures.FUN}
+\alias{departures.FUN}
+\title{Departures function}
+\usage{
+departures.FUN(dat, at)
+}
+\arguments{
+\item{dat}{Input data needed.}
+
+\item{at}{Not sure???}
+}
+\value{
+Updated dat
+}
+\description{
+Function to handel background demographics for the SEIQHRF model. 
+Specifically departures (deaths not due to the virus, and emigration).
+}
diff --git a/man/get_prev.FUN.Rd b/man/get_prev.FUN.Rd
new file mode 100644
index 0000000..eb0ad9f
--- /dev/null
+++ b/man/get_prev.FUN.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{get_prev.FUN}
+\alias{get_prev.FUN}
+\title{Get previous function}
+\usage{
+get_prev.FUN(dat, at)
+}
+\arguments{
+\item{dat}{Input data needed.}
+
+\item{at}{Not sure???}
+}
+\value{
+Updated dat
+}
+\description{
+Utility function that collects prevalence and transition time data from each
+run and stores it away in the simulation result object.
+}
diff --git a/man/get_times.Rd b/man/get_times.Rd
new file mode 100644
index 0000000..2a43e33
--- /dev/null
+++ b/man/get_times.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/results-parse.R
+\name{get_times}
+\alias{get_times}
+\title{Get times}
+\usage{
+get_times(simulate_results)
+}
+\arguments{
+\item{simulate_results}{results from `simulte()` function.}
+}
+\value{
+Dataframe of
+}
+\description{
+Function to extract timings and assemble results in a dataframe
+}
diff --git a/man/icm.seiqhrf.Rd b/man/icm.seiqhrf.Rd
new file mode 100644
index 0000000..4e1c29b
--- /dev/null
+++ b/man/icm.seiqhrf.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{icm.seiqhrf}
+\alias{icm.seiqhrf}
+\title{Infection function}
+\usage{
+icm.seiqhrf(param, init, control)
+}
+\arguments{
+\item{param}{ICM parameters.}
+
+\item{init}{Initial value parameters.}
+
+\item{control}{Control parameters.}
+}
+\value{
+Updated dat
+}
+\description{
+Function to implement infection processes for SEIQHRF model
+}
diff --git a/man/infection.FUN.Rd b/man/infection.FUN.Rd
new file mode 100644
index 0000000..2890047
--- /dev/null
+++ b/man/infection.FUN.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{infection.FUN}
+\alias{infection.FUN}
+\title{Infection function}
+\usage{
+infection.FUN(dat, at)
+}
+\arguments{
+\item{dat}{Input data needed.}
+
+\item{at}{Not sure???}
+}
+\value{
+Updated dat
+}
+\description{
+Function to implement infection processes for SEIQHRF model
+}
diff --git a/man/infection.seiqhrf.icm.Rd b/man/infection.seiqhrf.icm.Rd
new file mode 100644
index 0000000..658db31
--- /dev/null
+++ b/man/infection.seiqhrf.icm.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{infection.seiqhrf.icm}
+\alias{infection.seiqhrf.icm}
+\title{Model infections in ICM}
+\usage{
+infection.seiqhrf.icm(dat, at)
+}
+\arguments{
+\item{dat}{Object containing all data}
+
+\item{at}{?}
+}
+\value{
+Updated dat
+}
+\description{
+Function to model infections in icm
+}
diff --git a/man/init_status.icm.Rd b/man/init_status.icm.Rd
new file mode 100644
index 0000000..1328bb6
--- /dev/null
+++ b/man/init_status.icm.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{init_status.icm}
+\alias{init_status.icm}
+\title{Initialize status of ICM}
+\usage{
+init_status.icm(dat)
+}
+\arguments{
+\item{dat}{Object containing all data}
+}
+\value{
+Updated dat
+}
+\description{
+Function to get the status of the initialized icm
+}
diff --git a/man/initialize.FUN.Rd b/man/initialize.FUN.Rd
new file mode 100644
index 0000000..e65216e
--- /dev/null
+++ b/man/initialize.FUN.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{initialize.FUN}
+\alias{initialize.FUN}
+\title{Initialize ICM}
+\usage{
+initialize.FUN(param, init, control)
+}
+\arguments{
+\item{param}{ICM parameters.}
+
+\item{init}{Initial value parameters.}
+
+\item{control}{Control parameters.}
+}
+\value{
+Updated dat
+}
+\description{
+Function to initialize the icm
+}
diff --git a/man/merge.seiqhrf.icm.Rd b/man/merge.seiqhrf.icm.Rd
new file mode 100644
index 0000000..7bcc4b0
--- /dev/null
+++ b/man/merge.seiqhrf.icm.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{merge.seiqhrf.icm}
+\alias{merge.seiqhrf.icm}
+\title{Merge icm}
+\usage{
+\method{merge}{seiqhrf.icm}(x, y, ...)
+}
+\arguments{
+\item{x}{First to merge}
+
+\item{y}{Second to merge}
+}
+\value{
+Combined
+}
+\description{
+Function to merge icms
+}
diff --git a/man/progress.seiqhrf.icm.Rd b/man/progress.seiqhrf.icm.Rd
new file mode 100644
index 0000000..2ffb896
--- /dev/null
+++ b/man/progress.seiqhrf.icm.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{progress.seiqhrf.icm}
+\alias{progress.seiqhrf.icm}
+\title{Progress icm}
+\usage{
+progress.seiqhrf.icm(dat, at)
+}
+\arguments{
+\item{dat}{Object containing all data}
+
+\item{at}{?}
+}
+\value{
+progress
+}
+\description{
+Function to get progress of icms
+}
diff --git a/man/saveout.seiqhrf.icm.Rd b/man/saveout.seiqhrf.icm.Rd
new file mode 100644
index 0000000..31c337b
--- /dev/null
+++ b/man/saveout.seiqhrf.icm.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-functions.R
+\name{saveout.seiqhrf.icm}
+\alias{saveout.seiqhrf.icm}
+\title{Save icm}
+\usage{
+saveout.seiqhrf.icm(dat, s, out = NULL)
+}
+\arguments{
+\item{dat}{Object containing all data}
+
+\item{out}{?}
+
+\item{at}{?}
+}
+\value{
+out to save
+}
+\description{
+Function to save icm
+}
diff --git a/man/set.control.Rd b/man/set.control.Rd
new file mode 100644
index 0000000..45c87fc
--- /dev/null
+++ b/man/set.control.Rd
@@ -0,0 +1,54 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{set.control}
+\alias{set.control}
+\title{Set control params}
+\usage{
+set.control(
+  type = "SEIQHRF",
+  nsteps = 366,
+  nsims = 8,
+  ncores = 4,
+  prog.rand = FALSE,
+  rec.rand = FALSE,
+  fat.rand = TRUE,
+  quar.rand = FALSE,
+  hosp.rand = FALSE,
+  disch.rand = TRUE
+)
+}
+\arguments{
+\item{type}{Type of model: SI, SIR, SIS, SEIR, SEIQHR and 
+SEIQHRF available, but only SEIQHRF is likely to work in the 
+current version of the code.}
+
+\item{s.num}{Initial number of *S compartment individuals in 
+the simulated population. An overall population of 10,000 is a good 
+compromise. A set of models will still take several minutes or more
+to run, in parallel.}
+
+\item{e.num}{Initial number of E compartment individuals in 
+the simulated population.}
+
+\item{i.num}{Initial number of I compartment individuals in 
+the simulated population.}
+
+\item{q.num}{Initial number of Q compartment individuals in 
+the simulated population.}
+
+\item{h.num}{Initial number of H compartment individuals in
+the simulated population.}
+
+\item{r.num}{Initial number of R compartment individuals in 
+the simulated population.}
+
+\item{f.num}{Initial number of F compartment individuals in 
+the simulated population.}
+}
+\value{
+control.icm object
+}
+\description{
+Sets the controls for stochastic individual contact models simulated with 
+icm.
+}
diff --git a/man/set.init.Rd b/man/set.init.Rd
new file mode 100644
index 0000000..b649bbc
--- /dev/null
+++ b/man/set.init.Rd
@@ -0,0 +1,47 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{set.init}
+\alias{set.init}
+\title{Set init params}
+\usage{
+set.init(
+  s.num = 9997,
+  e.num = 0,
+  i.num = 3,
+  q.num = 0,
+  h.num = 0,
+  r.num = 0,
+  f.num = 0
+)
+}
+\arguments{
+\item{s.num}{Initial number of *S compartment individuals in 
+the simulated population. An overall population of 10,000 is a good 
+compromise. A set of models will still take several minutes or more
+to run, in parallel.}
+
+\item{e.num}{Initial number of E compartment individuals in 
+the simulated population.}
+
+\item{i.num}{Initial number of I compartment individuals in 
+the simulated population.}
+
+\item{q.num}{Initial number of Q compartment individuals in 
+the simulated population.}
+
+\item{h.num}{Initial number of H compartment individuals in
+the simulated population.}
+
+\item{r.num}{Initial number of R compartment individuals in 
+the simulated population.}
+
+\item{f.num}{Initial number of F compartment individuals in 
+the simulated population.}
+}
+\value{
+init.icm object
+}
+\description{
+Sets the initial conditions for stochastic individual contact models 
+simulated with icm.
+}
diff --git a/man/set.param.Rd b/man/set.param.Rd
new file mode 100644
index 0000000..33846aa
--- /dev/null
+++ b/man/set.param.Rd
@@ -0,0 +1,175 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/epi-functions.R
+\name{set.param}
+\alias{set.param}
+\title{Set epidemic params}
+\usage{
+set.param(
+  inf.prob.e = 0.02,
+  act.rate.e = 10,
+  inf.prob.i = 0.05,
+  act.rate.i = 10,
+  inf.prob.q = 0.02,
+  act.rate.q = 2.5,
+  quar.rate = 1/30,
+  hosp.rate = 1/100,
+  disch.rate = 1/15,
+  prog.rate = 1/10,
+  prog.dist.scale = 5,
+  prog.dist.shape = 1.5,
+  rec.rate = 1/20,
+  rec.dist.scale = 35,
+  rec.dist.shape = 1.5,
+  fat.rate.base = 1/50,
+  hosp.cap = 40,
+  fat.rate.overcap = 1/25,
+  fat.tcoeff = 0.5,
+  vital = TRUE,
+  a.rate = (10.5/365)/1000,
+  a.prop.e = 0.01,
+  a.prop.i = 0.001,
+  a.prop.q = 0.01,
+  ds.rate = (7/365)/1000,
+  de.rate = (7/365)/1000,
+  di.rate = (7/365)/1000,
+  dq.rate = (7/365)/1000,
+  dh.rate = (20/365)/1000,
+  dr.rate = (7/365)/1000,
+  out = "mean"
+)
+}
+\arguments{
+\item{inf.prob.e}{Probability of passing on infection at each 
+exposure event for interactions between infectious people in the E 
+compartment and susceptibles in S. Note the default is lower than for 
+inf.prob.i reflecting the reduced infectivity of infected but 
+asymptomatic people (the E compartment). Otherwise as for inf.exp.i.}
+
+\item{act.rate.e}{The number of exposure events (acts) between 
+infectious individuals in the E compartment and susceptible individuals 
+in the S compartment, per day. Otherwise as for act.rate.i.}
+
+\item{inf.prob.i}{Probability of passing on infection at each 
+exposure event for interactions between infectious people in the I
+compartment and susceptibles in S. Reducing inf.prob.i is equivalent to 
+increasing hygiene measures, such as not putting hands in eyes, nose or 
+moth, use of hand sanitisers, wearing masks by the infected, and so on.}
+
+\item{act.rate.i}{The number of exposure events (acts) between 
+infectious individuals in the I compartment and susceptible individuals 
+in the S compartment, per day. It's stochastic, so the rate is an
+average, some individuals may have more or less. Note that not every 
+exposure event results in infection - that is governed by the inf.prob.i
+parameters (see below). Reducing act.rate.i is equivalent to increasing 
+social distancing by people in the I compartment.}
+
+\item{inf.prob.q}{Probability of passing on infection at each 
+exposure event for interactions between infectious people in the Q 
+compartment and susceptibles in S. Note the default is lower than for 
+inf.prob.i reflecting the greater care that self-isolated individuals 
+will, on average, take regarding hygiene measures, such as wearing masks,
+to limit spread to others. Otherwise as for inf.exp.i.}
+
+\item{act.rate.q}{The number of exposure events (acts) between 
+infectious individuals in the Q compartment (isolated, self or otherwise)
+and susceptible individuals in the S compartment, per day. Note the much
+lower rate than for the I and E compartments, reflecting the much 
+greater degree of social isolation for someone in (self-)isolation. The
+exposure event rate is not zero for this group, just much less. 
+Otherwise as for act.rate.i.}
+
+\item{quar.rate}{Rate per day at which symptomatic (or tested 
+positive), infected I compartment people enter self-isolation (Q 
+compartment). Asymptomatic E compartment people can't enter 
+self-isolation because they don't yet know they are infected. Default is
+a low rate reflecting low community awareness or compliance with 
+self-isolation requirements or practices, but this can be tweaked when
+exploring scenarios.}
+
+\item{hosp.rate}{Rate per day at which symptomatic (or tested 
+positive), infected I compartment people or self-isolated Q compartment
+people enter the state of requiring hospital care -- that is, become 
+serious cases. A default rate of 1% per day with an average illness 
+duration of about 10 days means a bit less than 10% of cases will 
+require hospitalisation, which seems about right (but can be tweaked, 
+of course).}
+
+\item{disch.rate}{Rate per day at which people needing 
+hospitalisation recover.}
+
+\item{prog.rate}{Rate per day at which people who are infected 
+but asymptomatic (E compartment) progress to becoming symptomatic (or 
+test-positive), the I compartment. See prog.rand above for more details.}
+
+\item{prog.dist.scale}{Scale parameter for Weibull distribution 
+for progression, see prog.rand for details.}
+
+\item{prog.dist.shape}{Shape parameter for Weibull distribution 
+for progression, see prog.rand for details. Read up on the Weibull 
+distribution before changing the default.}
+
+\item{rec.rate}{Rate per day at which people who are infected and
+symptomatic (I compartment) recover, thus entering the R compartment. 
+See rec.rand above for more details.}
+
+\item{rec.dist.scale}{Scale parameter for Weibull distribution for
+recovery, see rec.rand for details.}
+
+\item{rec.dist.shape}{Shape parameter for Weibull distribution for
+recovery, see rec.rand for details. Read up on the Weibull distribution
+before changing the default.}
+
+\item{fat.rate.base}{Baseline mortality rate per day for people 
+needing hospitalisation (deaths due to the virus). See fat.rand for more
+details.}
+
+\item{hosp.cap}{Number of available hospital beds for the modelled
+population. See fat.rand for more details.}
+
+\item{fat.rate.overcap}{Mortality rate per day for people needing
+hospitalisation but who can't get into hospital due to the hospitals 
+being full (see hosp.cap and fat.rand). The default rate is twice that 
+for those who do get into hospital.}
+
+\item{fat.tcoeff}{Time co-efficient for increasing mortality rate 
+as time in the H compartment increases for each individual in it. See 
+fat.rand for details.}
+
+\item{vital}{Enables demographics, that is, arrivals and 
+departures, to and from the simulated population.}
+
+\item{a.rate}{Background demographic arrival rate. Currently all 
+arrivals go into the S compartment, the default is approximately the 
+daily birth rate for Australia. Will be extended to cover immigration in
+future versions.}
+
+\item{ds.rate}{Background demographic departure (death not due to
+virus) rates. Defaults based on Australian crude death rates. Can be 
+used to model emigration as well as deaths.}
+
+\item{de.rate}{Background demographic departure (death not due to 
+virus) rates. Defaults based on Australian crude death rates. Can be used
+to model emigration as well as deaths.}
+
+\item{dq.rate}{Background demographic departure (death not due to 
+virus) rates. Defaults based on Australian crude death rates. Can be used
+to model emigration as well as deaths.}
+
+\item{dh.rate}{Background demographic departure (death not due to 
+virus) rates. Defaults based on Australian crude death rates. Can be used
+to model emigration as well as deaths.}
+
+\item{dr.rate}{Background demographic departure (death not due to 
+virus) rates. Defaults based on Australian crude death rates. Can be used 
+to model emigration as well as deaths.}
+
+\item{out}{Summary function for the simulation runs. median is 
+also available, or percentiles, see the EpiModel documentation.}
+}
+\value{
+param.icm object
+}
+\description{
+Sets the epidemic parameters for stochastic individual contact models 
+simulated with icm.
+}
diff --git a/man/sirPlus.Rd b/man/sirPlus.Rd
new file mode 100644
index 0000000..0c18f8b
--- /dev/null
+++ b/man/sirPlus.Rd
@@ -0,0 +1,10 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sirPlus-package.R
+\docType{package}
+\name{sirPlus}
+\alias{sirPlus}
+\title{sirPlus}
+\description{
+\pkg{sirPlus} is a package for modeling COVID-19 spread, focusing on rates
+of hospitalization, which should be useful for hospitals.
+}
diff --git a/vignettes/epimodels-SEIQHRF.Rmd b/vignettes/epimodels-SEIQHRF.Rmd
new file mode 100644
index 0000000..6c7ffad
--- /dev/null
+++ b/vignettes/epimodels-SEIQHRF.Rmd
@@ -0,0 +1,133 @@
+---
+title: "sirPLUS models"
+date: "Last updated: 23 March 2020"
+output:
+    BiocStyle::html_document:
+        toc: true
+        toc_float: true
+vignette: >
+  %\VignetteIndexEntry{sirPLUS models}
+  %\VignetteEngine{knitr::rmarkdown}
+  %\VignetteEncoding{UTF-8}
+---
+
+```{r, include = FALSE}
+knitr::opts_chunk$set(
+  collapse = TRUE,
+  comment = "#>"
+)
+```
+
+## Backgrouund on the SEIQHRF (SIR + extra compartments) model
+
+Based on [Tim Churches"'" blog post](https://timchurches.github.io/blog/posts/2020-03-18-modelling-the-effects-of-public-health-interventions-on-covid-19-transmission-part-2/). 
+
+![COVID-19 transition diagram]('figure/TChurches-transition-diagram.png')
+*Note the lower case letters between compartment nodes represent model input 
+parameters defined in the blog post*
+
+
+## Sett up environment and pull parameters
+
+```{r setup environment, include=FALSE}
+library(tidyverse)
+library(dplyr)
+library(magrittr)
+library(lubridate)
+library(stringr)
+library(tibble)
+library(broom)
+library(ggplot2)
+#remotes::install_github("rstudio/gt")
+library(gt)
+library(knitr)
+library(devtools)
+library(DiagrammeR)
+library(parallel)
+library(foreach)
+library(tictoc)
+suppressMessages(library(EpiModel))
+library(incidence)
+.libPaths('/mnt/mcfiles/rlyu/Software/R/3.6/Rlib')
+#devtools::install_github("reconhub/earlyR")
+library(earlyR)
+
+tic("Time to complete")
+```
+
+```{r data from Tim Churches}
+source_files <- c("_icm.mod.init.seiqhrf.R", "_icm.mod.status.seiqhrf.R", 
+    "_icm.mod.vital.seiqhrf.R", "_icm.control.seiqhrf.R", "_icm.utils.seiqhrf.R", 
+    "_icm.saveout.seiqhrf.R", "_icm.icm.seiqhrf.R")
+
+src_path <- paste0("./_posts/2020-03-18-modelling-the-effects-of-public-health-", 
+    "interventions-on-covid-19-transmission-part-2/")
+
+gist_url <- "https://gist.github.com/timchurches/92073d0ea75cfbd387f91f7c6e624bd7"
+
+local_source <- FALSE
+
+for (source_file in source_files) {
+    if (local_source) {
+        source(paste(src_path, source_file, sep = ""))
+    } else {
+        Sys.sleep(1)
+        source_gist(gist_url, filename = source_file)
+    }
+}
+```
+
+## Define Functions
+
+```{r simulate baselines}  
+# function to set-up and run the baseline simulations
+devtools::load_all(".")
+control <- set.control()
+param <- set.param()
+init <- set.init(s.num = 10000, e.num = 150, q.num = 10, h.num = 0)
+init
+
+sim <- icm.seiqhrf(param, init, control)
+sim_df <- as.data.frame(sim, out=out)
+simulate <- list(sim=sim, df=sim_df)
+
+```
+
+
+## Generate and inspect baseline simulations
+started at 3:12 pm
+```{r baseline sims}
+baseline_sim <- simulate(ncores = 4)
+times <- get_times(baseline_sim)
+
+times %>% filter(duration <= 30) %>% ggplot(aes(x = duration)) + 
+    geom_bar() + facet_grid(period_type ~ ., scales = "free_y") + 
+    labs(title = "Duration frequency distributions", subtitle = "Baseline simulation")
+```
+
+
+
+```{r viz prevalence}
+baseline_plot_df <- baseline_sim$df %>% # use only the prevalence columns
+select(time, s.num, e.num, i.num, q.num, h.num, r.num, f.num) %>% 
+    # examine only the first 100 days since it is all over by
+# then using the default parameters
+filter(time <= 100) %>% pivot_longer(-c(time), names_to = "compartment", 
+    values_to = "count")
+
+# define a standard set of colours to represent compartments
+compcols <- c(s.num = "yellow", e.num = "orange", i.num = "red", 
+    q.num = "cyan", h.num = "magenta", r.num = "lightgreen", 
+    f.num = "black")
+complabels <- c(s.num = "Susceptible", e.num = "Infected/asymptomatic", 
+    i.num = "Infected/infectious", q.num = "Self-isolated", h.num = "Requires hospitalisation", 
+    r.num = "Recovered", f.num = "Case fatality")
+
+baseline_plot_df %>% ggplot(aes(x = time, y = count, colour = compartment)) + 
+    geom_line(size = 2, alpha = 0.7) + scale_colour_manual(values = compcols, 
+    labels = complabels) + theme_dark() + labs(title = "Baseline simulation", 
+    x = "Days since beginning of epidemic", y = "Prevalence (persons)")
+```
+## Experiment 1
+
+
-- 
GitLab