Infectious disease surveillance

#load various variable definitions that are the same for each app
source('startup_script.R')
#currentrmdfile = knitr::current_input() 
currentrmdfile = "idsurveillance_documentation.Rmd"
appsettings = get_settings(currentrmdfile,appdocdir,packagename)

Overview {#shinytab1}

This app teaches the topic of Infectious disease surveillance and demonstrates the effect of the type and extent of surveillance on the dynamics of an infectious disease in a population, including the course and outcome of an epidemic. Read about the model in the "Model" tab. Then do the tasks described in the "What to do" tab.

Learning Objectives

The Model {#shinytab2}

Model Overview

For this compartmental model, we track the following compartments/stages:

The model can be extended to include a reported compartment. This compartment would represent for example the US Centers for Disease Control and Prevention (CDC) to which health systems report the observed cases of disease at some rate(s).

In addition to specifying the compartments of a model, we need to specify the dynamics determining the changes for each compartment. In general, more compartments leads to more processes and more parameters governing these processes.

For this model, we include the following processes:

Model Implementation

The flow diagram and the set of ordinary differential equations (ODE) which are used to implement this model are as follows:

knitr::include_graphics(here::here('inst/media',appsettings$modelfigname))

$$\dot S = m - S(b_P P + b_A A + b_I I) + wR - nS$$ $$\dot P = S (b_P P + b_A A + b_I I) - P(g_P + r_P + n) $$ $$\dot A = f g_P P - A(r_A + n) $$ $$\dot I = (1-f) g_P P - I (r_I + n + d) $$ $$\dot R = r_PP + r_A A + r_I I - wR $$ $$\dot D = dD$$

What to do {#shinytab3}

The tasks below are described in a way that assumes everything is in units of months (rate parameters, therefore, have units of inverse months). If any quantity is not given in those units, you need to convert it first (e.g. if it says a year, you need to convert it to 12 months).

#this is the running counter for the records which starts at 1 
rc=1

#empty object, will hold all outcomes
alloutcomes = NULL

# Task 1
tid = 1
tasktext = "This will be our 'base case'--we'll have no surveillance going on, so that you have a comparison point for when we later include some surveillance. Set the model parameters such that they correspond to the following setting: A population size, _S_, of 1000, 1 initially infected presymptomatic host, _P_, simulation duration _tmax_ = 50 years. Be sure to convert the units to months. Assume that only symptomatic individuals transmit, at rate _bI_ = 0.002. Assume that _gP_ = 5 (the inverse of this parameter is the average duration of the presymptomatic period). Assume that 20% of the infections are asymptomatic--accordingly set _f_ = 0.2. Assume that immunity wanes at a rate _w_ = 1/100. Set the natural death rate, n, to a value that corresponds to an average lifespan of 41 years. Recall that the unit of n needs to be in 1/months. You need to convert lifespan to months, then take the inverse to get the death rate. Round to the first significant digit (i.e. 0.00X). Set the birth rate to _m_ = 5 per month and the death rate _d_ = 0.5. Also assume that no surveillance is done. Accordingly set the surveillance parameters _rP_, _rA_ and _rI_ to zero. With parameters set to correspond to the scenario just described, run the simulation and ensure that you observe oscillations/cycles (i.e. repeated outbreaks). In the diagram for the model, make note of which arrows are present and which are not when you plug in these parameters (for example, the arrows pointing to the 'R' compartment would disappear). Because there is no mechanism for recovery or removal, you should see the number of deaths steadily increase. Additionally, you should see the number of susceptibles oscillate due to the nonzero birth rate parameter."

# Record for task 1
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                    "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 2
tid = 2
tasktext = "Surveillance ensures that diseased individuals are removed from the transmission cycle before they contribute to the next generation of cases. Previously, we assumed that there was no surveillance. Now, assume that there exists a surveillance system that detects only symptomatic infections. Set the rate of surveillance of symptomatic hosts, _rI_ to 0.5. Leave the rest of the settings as in task 1, and run the simulation. Compare this result with the result observed in task 1 so as to understand the effect of surveillance on the course of the epidemic. Pay attention to the y-axis! You should see changes in the number of deaths over time, in the number of susceptibles over time, and of course in the number of removed over time. Why might the number of deaths change as it did?"

# Record for task 2
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                    "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 3 
tid = 3
tasktext = "Now, let's see what happens when we change values of _rI_. First, plot a graph of _S~f~_ as a function of _rI_ to determine the effect of the extent of surveillance on the number of susceptibles left at the end of the simulation. Then, plot a graph of _D~f~_ as a function of _rI_ to determine the effect of the extent of surveillance on the total number of deaths that occurred. You can make this plot either by hand or in R. If you plot by hand, you'll want to plot a rough trend line. If you want to plot in R, see the DSAIDE Package Tutorial, under the 'Level 2' heading, for an example of how to write the code."

# Record for task 3
nrec = 2 # number of items to record
out_records = c("Do you see an increasing trend between _rI_ and the number of susceptibles left at the end _S~f~_? (Yes/No)",
                "The number of deaths at the end drops to 0 once _rI_ passes 1 (Yes/No)")
out_types = rep("Logical",nrec)
out_notes = rep("Report Yes or No",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 4
tid = 4
tasktext = "Previously, although we had 20% of our infections as asymptomatic, they weren't actually transmitting (recall, _bA_ was set to be 0). Now, let's consider the scenario where they do transmit the infection--and let's see what happens with and without surveillance. Start with the settings in task 2. Consider the case where asymptomatic individuals transmit, and they do so at a rate similar to that of symptomatic hosts (_bA_ = 0.002) but no surveillance for them is done (_rA_ = 0). Run the simulation. Compare _S~f~_ with that in task 2. Note--the only thing we've changed is the number of susceptibles becoming infected (because now they can get infected by both infected symptomatic and infected asymptomatic individuals). What happens to the susceptible population? "

# Record for task 4
nrec = 1 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 5
tid = 5
tasktext = "Then consider the case where a new surveillance system detects asymptomatic cases at the same rate as that of symptomatic cases, i.e., _rA_ = 0.5 in addition to surveillance of symptomatic cases. Also in this case, assume that asymptomatic cases still transmit at a rate similar to that of symptomatic hosts, i.e., _bA_ = 0.002. Run the simulation and compare this result with that in task 4 part 1. Notice now what happens to the susceptible population. A couple other compartments should also change!"

# Record for task 5
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 6
tid = 6
tasktext = "Finally, consider the case where asymptomatic individuals don't transmit but they're still detected by the surveillance system, i.e., set  _bA_ = 0 but keep _rA_ = 0.5. Run the simulation and compare your result with that in task 4 part 1 and part 2."

# Record for task 6
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 


# Task 7
tid = 7
tasktext = "For some infectious diseases, such as tuberculosis (TB), it is possible to control the epidemic by identifying latently infected individuals i.e., while individuals are at the presymptomatic stage. These can be given Preventive Therapy so as to reduce the number of individuals transitioning to infectiousness. Consider the case where surveillance is done for asymptomatic, symptomatic and presymptomatic individuals at the same rate (i.e., 0.5). Also assume that asymptomatic individuals don't transmit, as the case is with TB. Leave the other settings as in task 1. Run the simulation and compare the value of Sf in this simulation with those in the other tasks." 

# Record for task 7
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 

# Task 8
tid = 8
tasktext = "Play with the rates of disease detection ( _rP_ , _rI_, and _rA_) and explore their effect on the disease dynamics. Specifically, consider the case where the rate of detection of asymptomatic and presymptomatic hosts is lower than the rate of detection of symptomatic hosts, which is usually the case. Set _rI_ = 1, _rA_ = 0.5 and _rP_ = 0.5 and leave other settings as in task 7."

# Record for task 8
nrec = 2 # number of items to record
out_records = c("The number of susceptibles left, _S~f~_",
                "The final value of the disease induced deaths, _D~f~_")
out_types = rep("Rounded_Integer",nrec)
out_notes = rep("Report the rounded integer",nrec)
outcomes = data.frame( TaskID = rep(tid,nrec),
                       TaskText = rep(tasktext,nrec),
                      RecordID = paste0('T',tid,'R',(1:nrec)),
                      Record = out_records, 
                      Type = out_types, 
                      Note = out_notes)
alloutcomes = rbind(alloutcomes,outcomes)
rc = rc + nrec #increment record counter by number of outcomes to record for this task 
#save the fully filled task table to a tsv file
alloutcomes$QuizID = paste0(packagename,"_",appsettings$appid)
alloutcomes$AppTitle = appsettings$apptitle
alloutcomes$AppID = appsettings$appid
#remove a few variables from the data frame
savedoutcomes <- dplyr::select(alloutcomes,QuizID,AppID,AppTitle,TaskID,TaskText,RecordID,Record,Type,Note)     
write.table(savedoutcomes, paste0(appsettings$appid,"_tasktable.tsv"), append = FALSE, sep = "\t", row.names = F, col.names = TRUE)
# Take all the text stored in the table and print the tasks and items to record
write_tasktext(alloutcomes)

Further Information {#shinytab4}

References



Try the DSAIDE package in your browser

Any scripts or data that you put into this service are public.

DSAIDE documentation built on Aug. 24, 2023, 1:07 a.m.