Population sensitivity with imperfect test sensitivity and specificity
This utility estimates the probability of detecting disease herd or cluster-sensitivity in a large (infinite) population, if it is present at the specified design prevalence, assuming a test of known sensitivity and specificity and for a variable cut-point number fo positives to determine the test result. These analyses use the method from Martin et el. (1992) (Prev Vet Med, 14:33-43) and the binomial distribution function, assuming known test sensitivity and test specificity and a variable cut-point number of positives to declare a population infected (i.e. a variable (non-zero) number of positive positives can be allowed and still be recognised as free). The population is classified as infected if the number of positive results is equal to or greater than the cut-point.
Inputs are the sample size tested, test sensitivity, test specificity, the design (target) prevalence and the cut-point number of positives.
Outputs are:
- the cluster-level sensitivity and specificity for the given sample size, test sensitivity, test specificity, design prevalence and cut-point number of positives; and
- tables and graphs of cluster-level sensitivity and specificity values for a range of cut-point, sample size and design prevalence values.
No results
###################################### # Program to calculate herd/flock level sensitivity and specificity ###################################### # uses RSurveillance rm(list = ls()) test<- ifelse(length(commandArgs()) < 3, TRUE, FALSE) fpath<- ifelse(test, "webRootUrl", "rtoolsPath") # load header scripts source(paste(fpath, "R/epi_head.R", sep = "")) source(paste(fpath, "R/HTMLStream.R", sep = "")) source(paste(fpath, "R/epitools_functions.r", sep = "")) # extract command arguments a1<- type.convert(a0[8:12]) # cat(a1) digits<- 4 Prevalence<- a1[1] Sens<- a1[2] Spec<- a1[3] # names(a1)<- c("Prevalence", "Sensitivity", "Specificity", "Sample Size") s.size<- a1[4] # number of sample sizes excluding user input CP<- a1[5] filename<- digest(Sys.time) graphfile<- paste(fpath, "tmp/", filename, "a.png", sep="") graph2<- paste(fpath, "tmp/", filename, "b.png", sep="") graph3<- paste(fpath, "tmp/", filename, "c.png", sep="") sinkfile<- paste(fpath, "tmp/", filename, ".txt", sep="") # check for valid cut-point if (CP > s.size) { cat("Cut-point number of reactors exceeds sample size. Please try again.") quit() } sink(sinkfile) # table of inputs inputs<- array("", dim = c(length(a1), 1)) inputs[1:length(a1), 1]<- a1[1:length(a1)] rownames(inputs)<- c("Design prevalence", "Test sensitivity", "Test specificity", "Sample size", "Cut-point number of positives") sample.size<- c(5, 10, 15, 20, 30, 50, 75, 100, 200, 300, 500) Prev.list<- c(0.01, 0.02, 0.05, 0.1, 0.2, 0.3) CP.list<- c(1, 2, 3, 4, 5, 10, 15) s.sizes<- length(sample.size) n.Prev<- length(Prev.list) n.CP<- length(CP.list) # P.Pos<- Prev.list * Sens + (1 - Prev.list)*(1 - Spec) # SeH/SpH by cut-point results<- array(0, dim = c(n.Prev + 1, n.CP)) rownames(results)<- c(paste("SeH - Prevalence = ", Prev.list, sep = ""), "SpH") colnames(results)<- paste("CP = ", CP.list, sep = "") for (c in 1:n.CP) { results[-nrow(results), c]<- sep.binom.imperfect(s.size, c=CP.list[c]-1, se=Sens, sp=Spec, pstar=Prev.list) results[n.Prev+1, c]<- sph.binom(s.size, c=CP.list[c]-1, Spec) } results<- round(results, digits) # SeH/SpH by sample size results1<- array(0, dim = c(n.Prev + 1, s.sizes)) rownames(results1)<- rownames(results) colnames(results1)<- paste("Sample size = ", sample.size, sep = "") for (c in 1:s.sizes) { results1[-nrow(results), c]<- sep.binom.imperfect(sample.size[c], c=CP, se=Sens, sp=Spec, pstar=Prev.list) results1[n.Prev+1, c]<- sph.binom(sample.size[c], c=CP, Spec) } results1<- round(results1, digits) # actual SeH/SpH SeH<- round(sep.binom.imperfect(s.size, c=CP, se=Sens, sp=Spec, pstar=Prevalence), digits) SpH<- round(sph.binom(s.size, c=CP, Spec), digits) # graph results by cut-point Title<-c("Cluster-level sensitivity and specificity") line.colours<- c("darkblue", "red", "darkgreen", "magenta", "brown", "purple", "orange") OpenGraphOutput(graphfile, pointsize = 12, ht = 6, wd = 8) plot(x = CP.list, y = results[1,], type="l", xlab = "Cut-point reactors", ylim = c(0, 1), xlim = c(0, max(CP.list)), ylab="SeH/SpH", main=Title, col = line.colours[1]) legend.txt<- rownames(results) for (i in 2:(n.Prev + 1)) { lines(CP.list, results[i,], type="l", col = line.colours[i]) # legend.txt[i]<- rownames(results)[i] } legend(max(CP.list), 0.5, legend.txt, xjust = 1, yjust = 0.5, col = line.colours, lty = c(1, 1), plot = TRUE, cex = 0.7) CloseGraphOutput("B") # graph SeH by prevalence Title<-c("Cluster-level sensitivity") OpenGraphOutput(graph2, pointsize = 12, ht = 6, wd = 8) plot(x = Prev.list, y = results[1:n.Prev,1], type="l", xlab = "Prevalence", ylim = c(0, 1), xlim = c(0, max(Prev.list)), ylab="SeH", main=Title, col = line.colours[1]) legend.txt<- colnames(results) for (i in 2:n.CP) { lines(Prev.list, results[1:n.Prev,i], type="l", col = line.colours[i]) # legend.txt[i]<- rownames(results)[i] } legend(max(Prev.list), 0.5, legend.txt, xjust = 1, yjust = 0.5, col = line.colours, lty = c(1, 1), plot = TRUE, cex = 0.7) CloseGraphOutput("B") # graph results by sample size Title<-c("Cluster-level sensitivity and specificity") line.colours<- c("darkblue", "red", "darkgreen", "magenta", "brown", "purple", "orange") OpenGraphOutput(graph3, pointsize = 12, ht = 6, wd = 8) plot(x = sample.size, y = results1[1,], type="l", xlab = "Sample size", ylim = c(0, 1), xlim = c(0, max(sample.size)), ylab="SeH/SpH", main=Title, col = line.colours[1]) legend.txt<- rownames(results1) for (i in 2:(n.Prev + 1)) { lines(sample.size, results1[i,], type="l", col = line.colours[i]) # legend.txt[i]<- rownames(results)[i] } legend(max(sample.size), 0.5, legend.txt, xjust = 1, yjust = 0.5, col = line.colours, lty = c(1, 1), plot = TRUE, cex = 0.7) CloseGraphOutput("B") sink() # write to html and file heading<- "Cluster-level sensitivity for testing with imperfect specificity and variable cut-points" subheadings<- c("SeH and SpH for varying prevalence and cut-point", "SeH and SpH for varying prevalence and sample size at specified cut-point") graph.txt<- c("Plots of SeH and SpH", "", "") tmp.file<- paste(fpath, "tmp/", filename, sep = "") result.txt<- c(paste("The table and graphs below summarise the cluster-sensitivity and cluster-specificity for various cut-points and prevalence levels, for specified sample size = ", s.size, ", test sensitivity = ", Sens, " and specificity = ", Spec, ".
", "For an assumed prevalence in the source population of ", Prevalence, ", and a sample size of ", s.size, ", the cluster-level sensitivity is ", SeH, ".
", sep = ""), paste("
For an uninfected population, a test specificity of ", Spec, " and a sample size of ", s.size, ", the cluster-level specificity is ", SpH, ".The table and graphs below summarise the cluster-sensitivity and cluster-specificity for various sample sizes and prevalence levels, for cut-point number of positives = ", CP, ", test sensitivity = ", Sens, " and specificity = ", Spec, ".
", sep = "")) output<- html.output(heading, subheadings, inputs, results = list(results, results1), graphs = c(graphfile, graph2, graph3), graph.headings = graph.txt, show.inputs = T, show.graphs = T, tmp.file, result.txt = result.txt) write.html(output, tmp.file) cat(output)