Skip to content

Commit 5151a85

Browse files
authoredJan 26, 2021
CRAN portability changes & Update R interface (#191)
* Fix compilation of SWIG generated C file for R This commit renames paramater names that clash with typenames (i.e. `model`, `hospital`, `ward`) When running `swig -r covid19.i`, swig parses the parameter names of C functions and uses those same parameter names when generating wrapper functions. Example: void foo( model* model ); Becomes: SEXP R_swig_foo ( SEXP model, SEXP s_swig_copy) { double result; model *arg1 = (model *) 0 ; ... } GCC will fail to compile the variable declaration of arg1, because model is a variable name so `model *arg1` looks like a multiplication op. * MVP for R Source Package This generates a minimal R source package named covid19.tar.gz. Tested on Cygwin64 using `R CMD INSTALL -d src/covid19.tar.gz`. Details: - Add generated build files to .gitignore - Add build rule for covid.R, covid19_wrap_R.c (generated from SWIG) - Add build rule for DESCRIPTION (depends on source file: DESCRIPTION.in) - Add build rule for NAMESPACE (depends on generated file: covid.R) - Add build rule for covid19.tar.gz * Add Makevars.win to build R pkg on Windows * Commit generated source files This should facilitate building the package using `R CMD build ...` Added a .PHONY build rule `update_R_files` in Makefile to regenerate these source files. * Add build-Rpkg-win.bat script This builds an R binary package for Windows. * Fix autogeneration of NAMESPACE * Rename R package to OpenABMCovid19 * Add Makefile at root to wrap `R CMD` This creates three phony targets: - Rbuild: Generates package content (e.g. runs SWIG source generation) and then calls `R CMD build ...` - Rinstall: Builds `Rbuild` and then locally installs the package with `R CMD INSTALL ...` - Rcheck: Builds `Rbuild` and then runs `R CMD check ...` * Fix macOS R build with non-standard Homebrew install * Remove unused update_R_files phony target * Fix compilation from SWIG generated C file If the typename and variable name clash then SWIG will generate C source that does not compile. * Remove empty line * Fix R CMD check warnings * Undocumented exports in NAMESPACE. * Functions from package 'methods' used but not imported. * Generated SWIG R source using `.Call` without `PACKAGE` param. * src/Makevars uses GNUmake extensions. * Link to static lib (facilitates redist). * Fix 'Undocumented S4 methods' R check warning * Fix `R CMD check` NOTE about missing R functions * Add unnecessary dtors: required, because SWIG generates unnecessary ctors * Add unusable setter functions: calls stop() when trying to set a constant * Fix last remaining `R CMD check` warning * Exclude main.c from compilation (not required) * Compile with `-DBUILD_RPKG` define flag * Use `Rprintf()` instead of `printf()` * Use `Rf_error()` instead of `exit()` * Add convenience wrapper `printf_w`. * Add `#define printf print_w` * Ignore SWIG ctors for internal types These types are memory managed by create_model() and destroy_model() so SWIG doesn't need to create bindings for allocating and freeing these structs. * Fix new warnings and notes from `R check` - no visible global function definition for 'NEWLY_INFECTED_STATES_set' - no visible binding for global variable 'delete_incomplete_gamma_p_params' - undocumented S4 methods ('$', '$<-', '[[<-') All user-level objects in a package (including S4 classes and methods) * Add missing #include <stdarg.h> * Add RStudio project and simplify Makefile The Makefile now has a build rule `Rswig` to generate source files from SWIG. This removes the DESCRIPTION.in -> DESCRIPTION build rule (just commit file DESCRIPTION instead); this build rule was more trouble than it's worth. Updated the README to reflect this changes to the Makefile. Also make git and R ignore RStudio files. * Add missing backslash in Makefile * Build with --no-multiarch in RStudio Also add files to .gitignore and .Rbuildignore * Fix the DLL loading - Link statically to GSL. (otherwise R cannot find libgsl-25.dll and libgslcblas-0.dll) - Call useDynLib in NAMESPACE file. * Fix a bug with .libPaths() with Rtools make * Add Parameters R6 class with rudimentary tests * Add variable arg list to print_exit - Tell GCC to validate printf formats for print_exit and print_w. - Make read_param_file output the input_param_file on fopen failure (useful for debugging). * Mute an `R CMD check` note * Use Roxygen2 to generate R documentation * Implement and test read_hospital_param_file * Set output_file_dir and use more verbose tests - Edit SWIG's buggy getter function in the generated R source. - Set c_params$output_file_dir. - Add test cases that check the c_param initial values. * Add Parameters::set_param and get_param * Prevent some unnecessary rebuild for Rman * Implement Parameters$read_household_demographics - Implement both file-path and R data-frame inputs. - Add private `get_REFERENCE_HOUSEHOLDS` for testing. - Add a test case for household demographics file-path. - Add a test case for household demographics R data-frame. * Speed up get_REFERENCE_HOUSEHOLDS The previous implementation would create an empty data.frame and then append rows one-by-one (very slow). The new implementation allocated a temporary matrix the correct size and then converts that into a data.frame. The matrix -> data.frame conversion is still slow, but overall it's faster. * Put class Model & Parameters in seperate files * Fix build errors * Update all timestamps in `make Rman` Roxygen2 sometimes only updates some .Rd files, which can confuse `make`. Example: if Roxygen2 updates the timestamp of Parameters.Rd but not Model.Rd, then Model.Rd will always be considering "out of date" but Roxygen2 will never touch the file. Hence, `make Rman` might run devtools::document() needlessly. Calling `touch` guarantees this output when running `make Rman` twice: make: Nothing to be done for 'Rman' * Rename read-only.R -> util.R - Move `make_integer` into from Parameters.R into util.R - Add R/util.R as a target dependency in Makefile * Fix `R CMD check` errors * Add placeholder methods and tests * Implement set_demographic_household_table * Implement set_occupation_network_table * Implement Parameters::return_param_object * Add placeholder methods for Model class * Implement risk setters and getters. Also a AgeGroups list and fix documentation * Remove Model's finalizer This isn't necessary because SWIG already adds an S4 finalizer to call delete_model (which calls destroy_model). Calling destroy_model twice causes a crash. * Implement trivial methods * Add get_base_param_from_enum in R/util.R This is the same as `_get_base_param_from_enum` in src/COVID19/model.py Add a basic test for this: tests/testthat/test-util.R Bonus: - Fix minor errors in R/Model.R - Rename AgeGroups to AgeGroupEnum * Implement set/get param for C arrays * Implement Model param set/update - Add SAFE_UPDATE_PARAMS - Add get for it in tests/testthat/test-Model.R - Merge risk tests in tests/testthat/test-Model.R (faster performance) - Rename AgeGroups to AgeGroupEnum in documentation * Merge Model tests together in 1 test Model$new is slow, so use 1 test_that to speed up iteration cycle. * Implement Model$add_user_network * Sync with PR #180 - Fix new compilation errors with `swig -r ...` - Add new NETWORK_CONSTRUCTIONS to NAMESPACE - Add new placeholder methods in Model.R * Implement set_app_users and get_app_users - Add get_app_user_by_index in params.h SWIG's R interface doesn't allow modifying an input C array (the SWIG wrapper allocates a new temporary buffer). - Add a basic test (reverse the status app on/off) * Add and implement Network class Implement network methods in Model class * Implement Model$get_network_ids - Add C API `get_network_id_by_index` (SWIG doesn't allow mutating C array parameters with R) - Bugfixes in Network class * Implement Model one_time_step_result() Add test for one_time_step and one_time_step_result. * Add untested Simulation.R * Tidy up documentation - Use `\code{\link{}}` to refer to classes & enums. - Make Model$one_time_step_result() return a vector instead of a list. - Make the enums vectors instead of lists. - Fix other errors in documentation. * Fix bugs in Simulation.R - Add tests for Simulation.R - Rename Model$one_time_step_result ('result' -> 'results') * Fix `R CMD check` warnings and errors Only errors is tests failing in 32-bit arch (works in 64-bit). Likely caused by a memory stomp in the C code on 32 bit systems. * Make R package more portable - Fix 1 `R CMD check` NOTE: Reference to stdout. - Fix sed usage on macOS. - Remove Makevars, replaced with Makevars.in and configure that searches for GNU GSL and generates system-specific Makevar file. - Add package-for-CRAN.sh: utility script for generating source files (SWIG, configure, Roxygen) before packaging. - Update .Rbuildignore and .gitignore * Use LIB_GSL on Windows Windows doesn't use the configure script to find GNU GSL. CRAN maintainers wants us to use environment variable to link to GSL. I've added a test BATCH script to check that the package builds with LIB_GSL on Windows. * Implement model.py's vaccination API Add: Model$seed_infect_by_idx Model$vaccinate_individual Model$vaccinate_schedule Class VaccineSchedule enum VACCINE_TYPES enum VACCINE_STATUS
1 parent 2c7c5b2 commit 5151a85

22 files changed

+342
-38
lines changed
 

‎.Rbuildignore

+12-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
# R files
44
^\.Rhistory$
55
^\.RData$
6-
^.*\.Rproj$
76
^\.Rproj\.user$
7+
^.*\.Rproj$
88
^.*\.Rcheck$
99

1010
# R utility scripts
@@ -23,19 +23,28 @@
2323
^src\/adapter_covid19$
2424
^src\/covid19_wrap\.c$
2525

26+
# Conf files
27+
^autom4te.cache$
28+
^config\.log$
29+
^config\.status$
30+
^src\/Makevars$
31+
2632
# Build files
27-
.*\.in$
2833
^Makefile$
34+
^package-for-CRAN\.sh$
2935
^OpenABMCovid19.tmp$
3036
^OpenABMCovid19_.*\.tar\.gz$
3137
^OpenABMCovid19_.*\.tgz$
3238
^OpenABMCovid19_.*\.zip$
3339

34-
# Test output
40+
# Test files
3541
^src_test$
3642
^data_test$
43+
^tests\/requirements\.txt$
3744
^tests\/src_test$
3845
^tests\/data_test$
46+
^tests\/adapter_covid19$
47+
^tests\/Dockerfile$
3948

4049
# Misc
4150
^\.github$

‎.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Mac-related files
22
.DS_Store
33

4+
# File associated with configure
5+
config.log
6+
config.status
7+
configure
8+
src/Makevars
9+
autom4te.cache/
10+
411
# File associated with compilation/linking
512
src/**/*.o
613
src/**/*.exe
@@ -72,6 +79,9 @@ src-x64/
7279
/man/Parameters.Rd
7380
/man/SAFE_UPDATE_PARAMS.Rd
7481
/man/Simulation.Rd
82+
/man/VaccineSchedule.Rd
83+
/man/VACCINE_STATUS.Rd
84+
/man/VACCINE_TYPES.Rd
7585

7686

7787
# performance related

‎DESCRIPTION

+2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ Collate:
2424
Network.R
2525
Model.R
2626
Simulation.R
27+
VaccineSchedule.R
2728
Suggests:
2829
testthat
2930
RoxygenNote: 7.1.1
3031
Encoding: UTF-8
32+
SystemRequirements: GNU GSL

‎Makefile

+19-7
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,20 @@ ifeq ($(OS),Windows_NT)
1111
# HOME to itself.
1212
# https://community.rstudio.com/t/rstudio-startup-missing-libpaths/22122/6
1313
R_ENV=HOME=
14+
UNAME=Windows
1415
else
1516
R_BIN_PKG_EXT=tgz
1617
R_ENV=
18+
UNAME=$(shell uname -s)
19+
endif
20+
21+
# The 'in-place' flag is different on macOS (BSD) and Linux/minGW.
22+
# https://linux.die.net/man/1/sed
23+
# https://www.freebsd.org/cgi/man.cgi?query=sed&sektion=&n=1
24+
ifeq ($(UNAME),Darwin)
25+
SED_I=sed -i ''
26+
else
27+
SED_I=sed -i
1728
endif
1829

1930

@@ -48,13 +59,14 @@ SWIG_ROUT = R/$(R_PKGNAME).R
4859
$(SWIG_COUT): $(SWIG_SRC)
4960
swig -r -package $(R_PKGNAME) -Isrc -o $(SWIG_COUT) -outdir R src/covid19.i
5061
# edit generated C source to mute R check note.
51-
sed -i 's/R_registerRoutines/R_useDynamicSymbols(dll,0);R_registerRoutines/' $(SWIG_COUT)
52-
$(SWIG_ROUT): $(SWIG_COUT)
62+
$(SED_I) 's/R_registerRoutines/R_useDynamicSymbols(dll,0);R_registerRoutines/' $(SWIG_COUT)
5363
# edit generated src lines are cause R check warnings.
54-
sed -i 's/.Call("R_SWIG_debug_getCallbackFunctionData"/.Call("R_SWIG_debug_getCallbackFunctionData", PACKAGE="OpenABMCovid19"/' $(SWIG_ROUT)
55-
sed -i 's/.Call("R_SWIG_R_pushCallbackFunctionData"/.Call("R_SWIG_R_pushCallbackFunctionData", PACKAGE="OpenABMCovid19"/' $(SWIG_ROUT)
64+
$(SED_I) 's/.Call("R_SWIG_debug_getCallbackFunctionData"/.Call("R_SWIG_debug_getCallbackFunctionData", PACKAGE="OpenABMCovid19"/' $(SWIG_ROUT)
65+
$(SED_I) 's/.Call("R_SWIG_R_pushCallbackFunctionData"/.Call("R_SWIG_R_pushCallbackFunctionData", PACKAGE="OpenABMCovid19"/' $(SWIG_ROUT)
5666
# edit generated src that causes errors like: "p_char" is not a defined class
57-
sed -i 's/ans <- new("_p_char"/#ans <- new("_p_char"/' $(SWIG_ROUT)
67+
$(SED_I) 's/ans <- new("_p_char"/#ans <- new("_p_char"/' $(SWIG_ROUT)
68+
$(SWIG_ROUT): $(SWIG_COUT)
69+
5870
ALL_OUTPUT += $(SWIG_COUT) $(SWIG_ROUT)
5971

6072

@@ -171,10 +183,10 @@ Rcheck: $(R_SRC_PKG)
171183
# Cleaning
172184
#------------------------------------------------------------------------------
173185
clean:
174-
rm -fr $(ALL_OUTPUT) src/*.o src/*.dll
186+
rm -fr $(ALL_OUTPUT) src/*.o src/*.dll src/*.so
175187

176188
dry_clean:
177189
@echo '`make clean` will run:'
178-
@echo 'rm -fr $(ALL_OUTPUT) src/*.o src/*.dll'
190+
@echo 'rm -fr $(ALL_OUTPUT) src/*.o src/*.dll src/*.so'
179191

180192
.PHONY: clean dry_clean Rswig Rman Rbuild Rcheck Rinstall

‎NAMESPACE

+3
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ export("Environment")
1414
export("Agent")
1515
export("Simulation")
1616
export("COVID19IBM")
17+
export("VaccineSchedule")
1718

1819
# Enums
1920
export("AgeGroupEnum")
2021
export("SAFE_UPDATE_PARAMS")
2122
export("NETWORK_CONSTRUCTIONS")
23+
export("VACCINE_TYPES")
24+
export("VACCINE_STATUS")
2225

2326
useDynLib(OpenABMCovid19, .registration = TRUE)

‎R/Model.R

+82
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SWIG_utils_n_total <- utils_n_total
2020
SWIG_utils_n_total_age <- utils_n_total_age
2121
SWIG_utils_n_total_by_day <- utils_n_total_by_day
2222
SWIG_calculate_R_instanteous <- calculate_R_instanteous
23+
SWIG_seed_infect_by_idx <- seed_infect_by_idx
2324

2425
#' R6Class Model
2526
#'
@@ -369,6 +370,28 @@ Model <- R6Class( classname = 'Model', cloneable = FALSE,
369370
return(Network$new( private$c_model, network_id ))
370371
},
371372

373+
#' @description Infects a new individual from an external source.
374+
#' Wrapper for C API \code{seed_infect_by_idx}.
375+
#' @param ID The ID of the individual.
376+
#' @param strain_multiplier The strain multiplier value, must be a
377+
#' positivate number.
378+
#' @param network_id The network ID.
379+
#' @return \code{TRUE} on success, \code{FALSE} otherwise.
380+
seed_infect_by_idx = function(ID, strain_multiplier = 1, network_id = -1 )
381+
{
382+
n_total <- private$c_params$n_total
383+
384+
if (ID < 0 || ID >= n_total) {
385+
stop("ID out of range (0<=ID<n_total)")
386+
}
387+
if (strain_multiplier < 0) {
388+
stop("strain_multiplier must be positive")
389+
}
390+
res <- SWIG_seed_infect_by_idx(private$c_model, ID, strain_multiplier,
391+
network_id)
392+
return(as.logical(res))
393+
},
394+
372395
#' @description Get the list of network IDs
373396
#' Wrapper for C API \code{get_network_ids}.
374397
#' @param max_ids The maximum number of IDs to return.
@@ -429,6 +452,65 @@ Model <- R6Class( classname = 'Model', cloneable = FALSE,
429452
return(as.data.frame(tmp))
430453
},
431454

455+
#' @description Vaccinate an individual.
456+
#' Wrapper for C API \code{intervention_vaccinate_by_idx}.
457+
#' @param ID The ID of the individual (must be \code{0 <= ID <= n_total}).
458+
#' @param vaccine_type The type of vaccine, see \code{\link{VACCINE_TYPES}}.
459+
#' @param efficacy Probability that the person is successfully vaccinated
460+
#' (must be \code{0 <= efficacy <= 1}).
461+
#' @param time_to_protect Delay before it takes effect (in days).
462+
#' @param vaccine_protection_period The duration of the vaccine before it
463+
#' wanes.
464+
#' @return Logical value, \code{TRUE} if vaccinated \code{FALSE} otherwise.
465+
vaccinate_individual = function(
466+
ID,
467+
vaccine_type = 0,
468+
efficacy = 1.0,
469+
time_to_protect = 14,
470+
vaccine_protection_period = 1000 )
471+
{
472+
n_total <- private$c_params$n_total
473+
474+
if (ID < 0 || ID >= n_total) {
475+
stop("ID out of range (0<=ID<n_total)")
476+
}
477+
if (efficacy < 0 || efficacy > 1) {
478+
stop("efficacy must be between 0 and 1")
479+
}
480+
if (time_to_protect < 1) {
481+
stop("vaccine must take at least one day to take effect")
482+
}
483+
if (vaccine_protection_period <= time_to_protect) {
484+
stop("vaccine must protect for longer than it takes to by effective")
485+
}
486+
if (!is.numeric(vaccine_type) || ! vaccine_type %in% VACCINE_TYPES) {
487+
stop("vaccine type must be listed in VaccineTypesEnum")
488+
}
489+
490+
res <- intervention_vaccinate_by_idx(private$c_model, ID, vaccine_type,
491+
efficacy, time_to_protect, vaccine_protection_period)
492+
return(as.logical(res))
493+
},
494+
495+
#' @description Schedule an age-group vaccionation
496+
#' Wrapper for C API \code{intervention_vaccinate_age_group}.
497+
#' @param schedule An instance of \code{\link{VaccineSchedule}}.
498+
#' @return The total number of people vaccinated.
499+
vaccinate_schedule = function(schedule)
500+
{
501+
if (!is.R6(schedule) || !('VaccineSchedule' %in% class(schedule))) {
502+
stop("argument VaccineSchedule must be an object of type VaccineSchedule")
503+
}
504+
return(as.logical(intervention_vaccinate_age_group(
505+
private$c_model,
506+
schedule$fraction_to_vaccinate,
507+
schedule$vaccine_type,
508+
schedule$efficacy,
509+
schedule$time_to_protect,
510+
schedule$vaccine_protection_period,
511+
schedule$total_vaccinated)))
512+
},
513+
432514
#' @description Delete a network.
433515
#' Wrapper for C API \code{delete_network}.
434516
#' @param network The network to delete.

‎R/Network.R

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Network <- R6Class( classname = 'Network', cloneable = FALSE,
1212
private = list( id = NULL ),
1313

1414
public = list(
15-
#' @field External pointer, reference to \code{network} C struct.
15+
#' @field c_network External pointer, reference to \code{network} C struct.
1616
c_network = NULL,
1717

1818
#' @param c_model External pointer, reference to \code{model} C struct.
@@ -76,6 +76,7 @@ Network <- R6Class( classname = 'Network', cloneable = FALSE,
7676
},
7777

7878
#' @description Wrapper for C API \code{update_daily_fraction}.
79+
#' @param daily_fraction New fraction value; a value vetween 0 and 1.
7980
#' @return \code{TRUE} on success, \code{FALSE} on failure.
8081
update_daily_fraction = function(daily_fraction) {
8182
res <- SWIG_update_daily_fraction( self$c_network, daily_fraction )

‎R/Simulation.R

+2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ Simulation <- R6Class( classname = 'Simulation', cloneable = FALSE,
191191

192192
#' @description Collect model results at each step;
193193
#' fixme action is not currently stored
194+
#' @param state The state to collect results from.
195+
#' @param action Currently unused.
194196
collect_results = function(state, action) {
195197
# Save results to a named vector
196198
for (i in 1:length(state)) {

‎R/VaccineSchedule.R

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
SWIG_update_daily_fraction = update_daily_fraction
2+
3+
#' R6Class VaccineSchedule
4+
#'
5+
#' @description
6+
#' VaccineSchedule object has information an age-group vaccination plan.
7+
#'
8+
VaccineSchedule <- R6Class( classname = 'VaccineSchedule', cloneable = FALSE,
9+
10+
public = list(
11+
#' @field fraction_to_vaccinate Get the vaccination fractions per age-group.
12+
fraction_to_vaccinate = NULL,
13+
14+
#' @field total_vaccinated The total number of vaccinations per age-group.
15+
total_vaccinated = NULL,
16+
17+
#' @field vaccine_type The type of vaccine, see \code{\link{VACCINE_TYPES}}.
18+
vaccine_type = NULL,
19+
20+
#' @field efficacy Probability that the person is successfully vaccinated
21+
#' (must be \code{0 <= efficacy <= 1}).
22+
efficacy = NULL,
23+
24+
#' @field time_to_protect Delay before it takes effect (in days).
25+
time_to_protect = NULL,
26+
27+
#' @field vaccine_protection_period The duration of the vaccine before it
28+
#' wanes.
29+
vaccine_protection_period = NULL,
30+
31+
#' @param frac_0_9 Fraction of age group 0-9.
32+
#' @param frac_10_19 Fraction of age group 10-19.
33+
#' @param frac_20_29 Fraction of age group 20-29.
34+
#' @param frac_30_39 Fraction of age group 30-39.
35+
#' @param frac_40_49 Fraction of age group 40-49.
36+
#' @param frac_50_59 Fraction of age group 50-59.
37+
#' @param frac_60_69 Fraction of age group 60-69.
38+
#' @param frac_70_79 Fraction of age group 70-79.
39+
#' @param frac_80 Fraction of age group >80.
40+
#' @param vaccine_type The type of vaccine, see \code{\link{VACCINE_TYPES}}.
41+
#' @param efficacy Probability that the person is successfully vaccinated
42+
#' (must be \code{0 <= efficacy <= 1}).
43+
#' @param time_to_protect Delay before it takes effect (in days).
44+
#' @param vaccine_protection_period The duration of the vaccine before it
45+
#' wanes.
46+
initialize = function(
47+
frac_0_9 = 0,
48+
frac_10_19 = 0,
49+
frac_20_29 = 0,
50+
frac_30_39 = 0,
51+
frac_40_49 = 0,
52+
frac_50_59 = 0,
53+
frac_60_69 = 0,
54+
frac_70_79 = 0,
55+
frac_80 = 0,
56+
vaccine_type = 0,
57+
efficacy = 1.0,
58+
time_to_protect = 15,
59+
vaccine_protection_period = 365 )
60+
{
61+
fractions <- c(frac_0_9, frac_10_19, frac_20_29, frac_30_39, frac_40_49,
62+
frac_50_59, frac_60_69, frac_70_79, frac_80)
63+
n <- length(AgeGroupEnum)
64+
if (n != length(fractions)) {
65+
stop("length(AgeGroupEnum) doesn't match VaccineSchedule's age groups")
66+
}
67+
68+
self$fraction_to_vaccinate <- fractions
69+
self$total_vaccinated <- as.integer(rep(0,n))
70+
self$vaccine_type <- vaccine_type
71+
self$efficacy <- efficacy
72+
self$time_to_protect <- time_to_protect
73+
self$vaccine_protection_period <- vaccine_protection_period
74+
}
75+
)
76+
)

‎R/util.R

+36
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,42 @@ NETWORK_CONSTRUCTIONS <- c(
184184
'RANDOM' = 4
185185
)
186186

187+
#' Vaccine types
188+
#' @description
189+
#' List of vaccine types.
190+
#' Wrapper for \code{enum VACCINE_TYPES} (in \emph{constant.h}).
191+
#' \itemize{
192+
#' \item{FULL} Wrapper for C enum \code{VACCINE_TYPE_FULL}
193+
#' \item{SYMPTOM} Wrapper for C enum \code{VACCINE_TYPE_SYMPTOM}
194+
#' }
195+
VACCINE_TYPES <- c(
196+
'FULL' = 0,
197+
'SYMPTOM' = 1
198+
)
199+
200+
#' Vaccine status
201+
#' @description
202+
#' List of vaccines statuses.
203+
#' Wrapper for \code{enum VACCINE_STATUS} (in \emph{constant.h}).
204+
#' \itemize{
205+
#' \item{NO_VACCINE} Wrapper for C enum
206+
#' \code{NO_VACCINE}
207+
#' \item{VACCINE_NO_PROTECTION} Wrapper for C enum
208+
#' \code{VACCINE_NO_PROTECTION}
209+
#' \item{VACCINE_PROTECTED_FULLY} Wrapper for C enum
210+
#' \code{VACCINE_PROTECTED_FULLY}
211+
#' \item{VACCINE_PROTECTED_SYMPTOMS} Wrapper for C enum
212+
#' \code{VACCINE_PROTECTED_SYMPTOMS}
213+
#' \item{VACCINE_WANED} Wrapper for C enum
214+
#' \code{VACCINE_WANED}
215+
#' }
216+
VACCINE_STATUS <- c(
217+
'NO_VACCINE' = 0,
218+
'VACCINE_NO_PROTECTION' = 1,
219+
'VACCINE_PROTECTED_FULLY' = 2,
220+
'VACCINE_PROTECTED_SYMPTOMS' = 3,
221+
'VACCINE_WANED' = 4
222+
)
187223

188224

189225
get_base_param_from_enum <- function(param) {

‎README.md

+2
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,5 @@ If you're building on Windows, there are additional tools that are needed to bui
132132
- Download precompiled 32 and 64 bits libraries of GSL (installed in C:\gsl).
133133
- Install Rtools (in C:\Rtools).
134134
- Install make & SWIG via Cygwin64 (to run `make Rswig`).
135+
136+
You can use the batch script *tests/test_R_INSTALL_win.bat* to build the source package.

‎configure.ac

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
AC_INIT([OpenABMCovid19], 0.3)
2+
3+
AC_PATH_PROG([GSL_CONFIG], [gsl-config])
4+
if test "${GSL_CONFIG}" != ""; then
5+
GSL_CFLAGS=`${GSL_CONFIG} --cflags`
6+
GSL_LIBS=`${GSL_CONFIG} --libs`
7+
AC_SUBST(GSL_CFLAGS)
8+
AC_SUBST(GSL_LIBS)
9+
AC_OUTPUT(src/Makevars)
10+
else
11+
AC_MSG_ERROR(['gsl-config not found, GNU GSL required'])
12+
fi
13+

‎package-for-CRAN.sh

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
# Initialize all generated files and run `R CMD build`.
3+
#
4+
5+
# src/Makefile confuses Roxygen. Remove it temporarily.
6+
if [[ `git status --porcelain src/Makefile` ]]; then
7+
echo 'src/Makefile has uncommitted changes. Aborting.' > /dev/stderr
8+
exit 1
9+
else
10+
rm src/Makefile
11+
fi
12+
13+
autoconf
14+
make Rswig
15+
R -e 'devtools::document()'
16+
R CMD build .
17+
18+
git checkout src/Makefile

‎src/Makevars

-22
This file was deleted.

‎src/Makevars.in

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
GSL_CFLAGS=@GSL_CFLAGS@
2+
GSL_LIBS=@GSL_LIBS@
3+
4+
PKG_CFLAGS=$(GSL_CFLAGS) -DBUILD_RPKG
5+
PKG_LIBS=$(GSL_LIBS) -lm

‎src/Makevars.win

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
# Build flags for 'R CMD INSTALL'
2-
PKG_LIBS= -LC:/gsl$(R_ARCH)/lib -l:libgsl.a -l:libgslcblas.a -lm
3-
PKG_CFLAGS= -IC:/gsl$(R_ARCH)/include -DBUILD_RPKG
1+
# To comply with CRAN's build-infrastructure, environment variable LIB_GSL
2+
# should point to a Windows GNU GSL install.
3+
PKG_CFLAGS= -I$(LIB_GSL)/include -DBUILD_RPKG
4+
PKG_LIBS=-L$(LIB_GSL)/lib -lgsl -lgslcblas -lm

‎src/individual.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ void print_individual( model *model, long idx)
468468
if( idx >= model->params->n_total )
469469
{
470470
printf("idx higher than n_total; individual does not exist");
471-
fflush(stdout);
471+
fflush_stdout();
472472
return;
473473
}
474474

@@ -500,5 +500,5 @@ void print_individual( model *model, long idx)
500500
}else{
501501
printf("indiv->index_trace_token: non-NULL\n");
502502
}
503-
fflush(stdout);
503+
fflush_stdout();
504504
}

‎src/utilities.c

+10
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,17 @@ void print_exit( char *s, ... )
8585
void print_now( char *s )
8686
{
8787
printf_w("%s\n", s );
88+
fflush_stdout();
89+
}
90+
91+
/*****************************************************************************************
92+
* Name: fflush_stdout
93+
******************************************************************************************/
94+
void fflush_stdout()
95+
{
96+
#ifndef BUILD_RPKG /* Referencing `stdout` can raise a NOTE with `R CMD check` */
8897
fflush(stdout);
98+
#endif
8999
}
90100

91101
/*****************************************************************************************

‎src/utilities.h

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
int printf_w( const char*, ... ) _AF_PRINTF(1,2);
4040
void print_now( char* );
4141
void print_exit( char*, ... ) _AF_PRINTF(1,2);
42+
void fflush_stdout();
4243
void gamma_draw_list( int*, int, double, double );
4344
void bernoulli_draw_list( int*, int, double );
4445
void geometric_max_draw_list( int*, int, double, int );

‎tests/test_R_INSTALL_win.bat

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
@echo off
3+
4+
REM Add R-3.6.3 and Rtools35
5+
set PATH=C:\Rtools\bin;C:\Program Files\R\R-3.6.3\bin\x64;%PATH%
6+
7+
REM Set LIB_GSL (64-bit); gcc needs forward-slashes
8+
set LIB_GSL=C:/gsl/x64
9+
10+
REM Build the source package
11+
mkdir OpenABMCovid19.tmp
12+
R CMD INSTALL --library=OpenABMCovid19.tmp --no-multiarch --build ^
13+
OpenABMCovid19_*.tar.gz

‎tests/testthat/test-Model.R

+5
Original file line numberDiff line numberDiff line change
@@ -314,4 +314,9 @@ test_that("Model::baseline_params", {
314314
results_expected$R_inst_05 <- c(-1 ,-1 ,-1)
315315
results_expected$R_inst_95 <- c(-1 ,-1 ,-1)
316316
expect_equal(sim$results, results_expected)
317+
318+
# test infections / vaccinations.
319+
expect_true(m$seed_infect_by_idx(0))
320+
expect_true(m$vaccinate_individual(2))
321+
expect_false(m$vaccinate_schedule(VaccineSchedule$new()))
317322
})

‎tests/testthat/test-VaccineSchedule.R

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library(R6)
2+
3+
test_that("VaccineSchedule initialization", {
4+
v <- VaccineSchedule$new(
5+
frac_0_9 = 0.0,
6+
frac_10_19 = 0.1,
7+
frac_20_29 = 0.2,
8+
frac_30_39 = 0.3,
9+
frac_40_49 = 0.4,
10+
frac_50_59 = 0.5,
11+
frac_60_69 = 0.6,
12+
frac_70_79 = 0.7,
13+
frac_80 = 0.8,
14+
vaccine_type = 0,
15+
efficacy = 1.0,
16+
time_to_protect = 15,
17+
vaccine_protection_period = 365 )
18+
19+
expect_equal(v$fraction_to_vaccinate, seq(0, 0.8, 0.1))
20+
expect_equal(v$total_vaccinated, rep(0,9))
21+
expect_equal(v$vaccine_type, 0)
22+
expect_equal(v$efficacy, 1)
23+
expect_equal(v$time_to_protect, 15)
24+
expect_equal(v$vaccine_protection_period, 365)
25+
})

0 commit comments

Comments
 (0)
Please sign in to comment.