test_that("jointModel input checks work", { #' @srrstats {G5.2,G5.2b,BS2.15} Tests the assure function input checks are #' behaving as expected. #1. input tags are valid, q = FALSE, cov = FALSE expect_error(jointModel(data = list(qPCR.k = rbind(c(1,1,1),c(1,1,NA)), qPCR.n = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("Data should include 'qPCR.N', 'qPCR.K', and 'count'.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #2. input tags are valid, q = FALSE, cov = TRUE site.cov <- cbind(c(1,0),c(0.4,-0.4)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.k = rbind(c(1,1,1),c(1,1,NA)), qPCR.n = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), multicore = FALSE), paste(paste0("Data should include 'qPCR.N', 'qPCR.K', ", "'count', and 'site.cov'."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html#prepare-the-data'), sep='\n')) #3. input tags are valid, q = TRUE, cov = FALSE expect_error(jointModel(data = list(qPCR.k = rbind(c(1,1,1),c(1,1,NA)), qPCR.n = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,2,NA))), q = TRUE, multicore = FALSE), paste(paste0("Data should include 'qPCR.N', 'qPCR.K', ", "'count', and 'count.type'."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #4. input tags are valid, q = TRUE, cov = TRUE site.cov <- cbind(c(1,0),c(0.4,-0.4)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.k = rbind(c(1,1,1),c(1,1,NA)), qPCR.n = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,2,NA)), site.cov = site.cov), cov = c('var_a','var_b'),q = TRUE, multicore = FALSE), paste(paste0("Data should include 'qPCR.N', 'qPCR.K', 'count', ", "'count.type', and 'site.cov'."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #5. make sure dimensions of qPCR.N and qPCR.K are equal #' @srrstats {BS2.1a} Test to ensure pre-processing routines to ensure all #' input data is dimensionally commensurate expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1,1),c(1,1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("Dimensions of qPCR.N and qPCR.K do not match.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #6. make sure dimensions of count and count.type are equal, if count.type is # present #' @srrstats {BS2.1a} Test to ensure pre-processing routines to ensure all #' input data is dimensionally commensurate expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2),c(1,2))), q = TRUE, multicore = FALSE), paste("Dimensions of count and count.type do not match.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #7. make sure number of rows in count = number of rows in qPCR.N and qPCR.K #' @srrstats {BS2.1a} Test to ensure pre-processing routines to ensure all #' input data is dimensionally commensurate expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA), c(4,1,1))), multicore = FALSE), paste(paste0("Number of sites \\(rows\\) in qPCR data and ", "traditional survey count data do not match."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #8. make sure all data is numeric -- if q == TRUE expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c('NA',2,2),c(1,2,2))), q = TRUE, multicore = FALSE), paste("Data should be numeric.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #9. make sure all data is numeric -- if q == FALSE expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,'NA')), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("Data should be numeric.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #10. make sure locations of NAs in count data match locations of NAs in # count.type data expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(NA,2,2),c(1,2,2))), q = TRUE, multicore = FALSE), paste(paste0("Empty data cells \\(NA\\) in count data should ", "match ", "empty data cells \\(NA\\) in count.type data."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #11. make sure locations of NAs in qPCR.N data match locations of NAs in # qPCR.K data expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,NA,1)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste(paste0("Empty data cells \\(NA\\) in qPCR.N data should ", "match ", "empty data cells \\(NA\\) in qPCR.K data."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #12. make sure family is either 'poisson', 'negbin', or 'gamma' expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), family = 'normal', multicore = FALSE), paste0("Invalid family. Options include 'poisson', ", "'negbin', and 'gamma'.")) #13. p10 priors is a vector of two numeric values expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), p10priors = c(1,1,2), multicore = FALSE), paste0("p10priors should be a vector of two positive numeric ", "values. ex. c\\(1,20\\)")) #14. p10 priors is a vector of two numeric values expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE, p10priors = '1,20'), paste0("p10priors should be a vector of two positive numeric ", "values. ex. c\\(1,20\\)")) #15. p10 priors is a vector of two numeric values expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), p10priors = c(0,20), multicore = FALSE), paste0("p10priors should be a vector of two positive numeric ", "values. ex. c\\(1,20\\)")) #16. phi priors is a vector of two numeric values expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), phipriors = c(0,1),family = 'negbin', multicore = FALSE), paste0("phipriors should be a vector of two positive numeric ", "values. ex. c\\(0.25,0.25\\)")) #17. the smallest count.type is 1 expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(0,1,2),c(1,2,NA))), q = TRUE, multicore = FALSE), paste(paste0("The first gear type should be referenced as 1 in ", "count.type. Subsequent gear types should be ", "referenced 2, 3, 4, etc."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #18. count are integers expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4.1,1,1),c(1,1,NA)), count.type = rbind(c(1,1,2),c(1,2,NA))), q = TRUE, family = 'negbin', multicore = FALSE), paste0("All values in count should be non-negative integers. ", "Use family = 'gamma' if count is continuous.")) #19. qPCR.N are integers expect_error(jointModel(data = list(qPCR.K = rbind(c(0.99,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,1,2),c(1,2,NA))), q = TRUE, multicore = FALSE), paste("All values in qPCR.K should be non-negative integers.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #20. qPCR.K are integers expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3.1,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,1,2),c(1,2,NA))), q = TRUE, multicore = FALSE), paste("All values in qPCR.N should be non-negative integers.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #21. count.type are integers expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1.1,1,2),c(1,2,NA))), q = TRUE, multicore = FALSE), paste("All values in count.type should be integers.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #22. site.cov is numeric, if present site.cov <- cbind(c('high','low'),c(0.4,-0.4)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,2,NA)), site.cov = site.cov), cov = c('var_a','var_b'),q = TRUE, multicore = FALSE), paste("site.cov should be numeric.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #23. cov values match column names in site.cov site.cov <- cbind(c(0,1),c(0.4,-0.4)) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,2,NA)), site.cov = site.cov), cov = c('var_a','var_b'),q = TRUE, multicore = FALSE), paste(paste0("cov values should be listed in the column names of ", "site.cov in the data."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #24. site.cov has same number of rows as qPCR.N and count, if present site.cov <- cbind(c(0,1,1),c(0.4,-0.4,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,2,NA)), site.cov = site.cov), cov = c('var_a','var_b'),q = TRUE, multicore = FALSE), paste(paste0("The number of rows in site.cov matrix should match ", "the number of rows in all other matrices."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #25. make sure count.type is not zero-length expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = matrix(NA,ncol = 3, nrow = 0)), q = TRUE, multicore = FALSE), paste("count.type contains zero-length data.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #26. make sure no column is entirely NA in count.type expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(4,1,NA),c(1,1,NA))), q = TRUE, multicore = FALSE), paste("count.type contains a column with all NA.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase3.html#prepare-the-data'), sep='\n')) #27. make sure no column is entirely NA in qPCR.K expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,NA),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("qPCR.K contains a column with all NA.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #28. make sure no column is entirely NA in qPCR.N expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,NA),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("qPCR.N contains a column with all NA.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #29. make sure no column is entirely NA in count expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,NA),c(1,1,NA))), multicore = FALSE), paste("count contains a column with all NA.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #30. make sure no data are undefined expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,Inf),c(1,1,NA))), multicore = FALSE), paste("count contains undefined values \\(i.e., Inf or -Inf\\)", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #31. make sure no data are undefined expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,Inf),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("qPCR.N contains undefined values \\(i.e., Inf or -Inf\\)", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #32. make sure no data are undefined expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,Inf),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), multicore = FALSE), paste("qPCR.K contains undefined values \\(i.e., Inf or -Inf\\)", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n')) #33. make sure site.cov is not zero-length site.cov <- matrix(NA,ncol = 2,nrow = 0) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), multicore = FALSE), paste("site.cov contains zero-length data.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #34. make sure no column is entirely NA in site.cov site.cov <- rbind(c(4,1,NA),c(1,1,NA)) colnames(site.cov) <- c('var_a','var_b','var_c') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), multicore = FALSE), paste("site.cov contains a column with all NA.", 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #35. make sure no data are undefined site.cov <- rbind(c(4,1,Inf),c(1,1,NA)) colnames(site.cov) <- c('var_a','var_b','var_c') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), multicore = FALSE), paste(paste0("site.cov contains undefined values \\(i.e., ", "Inf or -Inf\\)"), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html'), sep='\n')) #36. length of initial values is equal to the number of chains n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(3, 0.01, 5), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), alpha <- rep(0.1,3) ) } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, n.chain = 5, multicore = FALSE), paste(paste0("The length of the list of initial values ", "should equal the number of chains \\(n.chain, ", "default is 4\\)."), paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #37. initial values check: if mu is numeric n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(3, -1, 0), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), alpha <- rep(0.1,3) ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste("Initial values for 'mu' should be numeric values > 0.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #38. initial values check: mu length n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(4, 0.1, 1), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), alpha <- rep(0.1,3) ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste(paste0("The length of initial values for 'mu' should ", "equal the number of sites."), paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #39. initial values check: p10 numeric n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- "-1", alpha <- rep(0.1,3) ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste("Initial values for 'p10' should be numeric.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #40. initial values check: p10 length n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- exp(stats::runif(2,log(0.0001),log(0.08))), alpha <- rep(0.1,3) ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste("The length of initial values for 'p10' should equal 1.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #41. initial values check: beta numeric n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), beta <- "1" ) names(inits[[i]]) <- c('mu','p10','beta') } expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), initial_values = inits, multicore = FALSE), paste("Initial values for 'beta' should be numeric.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #42. initial values check: beta length n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), beta <- c(1,0) ) names(inits[[i]]) <- c('mu','p10','beta') } expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA))), initial_values = inits, multicore = FALSE), paste("The length of initial values for 'beta' should equal 1.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #43. initial values check: alpha numeric n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), alpha <- c("1","2") ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste("Initial values for 'alpha' should be numeric.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html#initialvalues'), sep='\n')) #44. initial values check: alpha length n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( mu <- stats::runif(2,0,1), p10 <- exp(stats::runif(1,log(0.0001),log(0.08))), alpha <- rep(0.1,2) ) names(inits[[i]]) <- c('mu','p10','alpha') } site.cov <- rbind(c(4,1),c(1,1)) colnames(site.cov) <- c('var_a','var_b') expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), site.cov = site.cov), cov = c('var_a','var_b'), initial_values = inits, multicore = FALSE), paste(paste0("The length of initial values for 'alpha' should ", "equal\\: \\# covariates \\+ 1 \\(i.e., ", "including intercept\\)."), paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase2.html#initialvalues'), sep='\n')) #45. initial values check: q numeric n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( q <- "0.1" ) names(inits[[i]]) <- c('q') } expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), initial_values = inits, multicore = FALSE), paste("Initial values for 'q' should be numeric.", paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #46. initial values check: q length n.chain <- 4 inits <- list() for(i in 1:n.chain){ inits[[i]] <- list( q <- c(0.1,0.1) ) names(inits[[i]]) <- c('q') } expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), initial_values = inits, multicore = FALSE), paste(paste0("The length of initial values for 'q' should ", "equal: \\# unique gear types \\- 1 \\(i.e., q ", "for reference type = 1\\)."), paste0('See the eDNAjoint guide for help formatting ', 'initial values: '), paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#initialvalues'), sep='\n')) #47. check length and range of n.chain expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.chain = c(1,1),multicore = FALSE), paste0("n.chain should be an integer > 0 and of length 1.")) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.chain = 0,multicore = FALSE), paste0("n.chain should be an integer > 0 and of length 1.")) #48. check length and range of n.iter.sample expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.iter.sample = c(1,1),multicore = FALSE), paste0("n.iter.sample should be an integer > 0 and of length 1.") ) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.iter.sample = 0,multicore = FALSE), paste0("n.iter.sample should be an integer > 0 and of length 1.") ) #49. check length and range of n.iter.burn expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.iter.burn = c(1,1),multicore = FALSE), paste0("n.iter.burn should be an integer > 0 and of length 1.") ) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), n.iter.burn = 0,multicore = FALSE), paste0("n.iter.burn should be an integer > 0 and of length 1.") ) #50. check length and range of thin expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), thin = c(1,1),multicore = FALSE), paste0("thin should be an integer > 0 and of length 1.") ) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), thin = 0,multicore = FALSE), paste0("thin should be an integer > 0 and of length 1.") ) #51. check length and range of adapt_delta expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), adapt_delta = c(0.9,0.9),multicore = FALSE), paste0("adapt_delta should be a numeric value > 0 and < 1 and ", "of length 1.") ) expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), adapt_delta = 1.2,multicore = FALSE), paste0("adapt_delta should be a numeric value > 0 and < 1 and ", "of length 1.") ) #52. check length of seed expect_error(jointModel(data = list(qPCR.K = rbind(c(1,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), count.type = rbind(c(1,2,1),c(1,1,NA))), seed = c(1,2),multicore = FALSE), paste0("seed should be an integer of length 1.") ) #53. check K <= N expect_error(jointModel(data = list(qPCR.K = rbind(c(4,1,1),c(1,1,NA)), qPCR.N = rbind(c(3,3,3),c(3,3,NA)), count = rbind(c(4,1,1),c(1,1,NA)), multicore = FALSE)), paste(paste0("N should be >= K in qPCR data. N is the number ", "of qPCR replicates per sample, and K is the ", "number of positive detections among replicates."), 'See the eDNAjoint guide for data formatting help: ', paste0('https://bookdown.org/abigailkeller/eDNAjoint_', 'vignette/usecase1.html#prepare-the-data'), sep='\n') ) }) # correctness and parameter recovery tests #' @srrstats {G5.4, G5.6} Correctness/parameter recovery tests to test that #' the implementation produces expected results given data with known #' properties #' @srrstats {PD4.0} These tests do not test for numeric equality of outputs, #' but rather test for the recovery of parameter values. In these tests, I #' simulate data with known parameter values, run the main statistical #' function (jointModel()) with the data, and then test if the known parameter #' values are within the 95% credibility interval of the parameters' #' posteriors in the function output. test_that("jointModel parameter recovery tests work",{ ################################ # model run 1: smaller dataset # ################################ # simulate data: seed 123 #' @srrstats {G5.5, G5.6} Running correctness test with a fixed random seed set.seed(123) # constants nsite <- 20 nobs_count <- 200 nobs_pcr <- 8 # params mu <- rlnorm(nsite,meanlog = log(1),sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 # count count <- matrix(NA,nrow = nsite,ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rpois(nobs_count,mu[i]) } # site-level covariates mat_site <- matrix(NA,nrow = nsite,ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability of # eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # run model fit1 <- suppressWarnings({jointModel(data = data, cov = c('var_a','var_b'), multicore = FALSE, seed = 10)}) # summary summary1 <- as.data.frame(rstan::summary(fit1$model, pars = c('mu','alpha','log_p10'), probs = c(0.025, 0.975))$summary) # set up empty vector to check if true values are in 95% interval of # posterior estimates check <- rep(NA,length(mu)+length(alpha)+length(log_p10)) # check mu for(i in 1:nsite){ par <- paste0('mu[',i,']') if(mu[i] > summary1[par,'2.5%'] && mu[i] < summary1[par,'97.5%']){ check[i] <- TRUE } else { check[i] <- FALSE } } # check alpha for(i in seq_along(alpha)){ par <- paste0('alpha[',i,']') if(alpha[i] > summary1[par,'2.5%'] && alpha[i] < summary1[par,'97.5%']){ check[nsite+i] <- TRUE } else { check[nsite+i] <- FALSE } } # check p10 if(log_p10 > summary1['log_p10','2.5%'] && log_p10 < summary1['log_p10','97.5%']){ check[nsite+length(alpha)+1] <- TRUE } else { check[nsite+length(alpha)+1] <- FALSE } #' @srrstats {G3.0, G5.6a} Instead of comparing floating point values for #' equality, here the model is tested to determine if the true parameter #' values are within the 95% quantiles of the posterior # all should be equal to true expect_equal(check,rep(TRUE,nsite+length(alpha)+length(log_p10))) # test that output values are on the same scale as the data mu_estimates <- rep(NA,nsite) for(i in 1:nsite){ mu_estimates[i] <- summary1[paste0('mu[',i,']'),'mean'] } # get mean of input count data at each site data_mean <- rep(NA,nsite) for(i in 1:nsite){ data_mean[i] <- mean(data$count[i,]) } #' @srrstats {BS7.4, BS7.4a} Check to ensure that mean posterior estimates #' are on the same scale as the mean of the input data (here checking #' estimates of mu, i.e., expected catch rate at each site) # check that estimates are on same scale as data expect_equal(round(mu_estimates,0),round(data_mean,0)) ########################################## # model run 2: smaller dataset, new seed # ########################################## #' @srrstats {G5.6b,G5.9b} Run test for multiple seeds with same data # simulate data: seed 222 set.seed(222) # constants nsite <- 20 nobs_count <- 200 nobs_pcr <- 8 # params mu <- rlnorm(nsite,meanlog = log(1),sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 # count count <- matrix(NA,nrow = nsite,ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rpois(nobs_count,mu[i]) } # site-level covariates mat_site <- matrix(NA,nrow = nsite,ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability of # eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # run model fit2 <- suppressWarnings({jointModel(data = data, cov = c('var_a','var_b'), multicore = FALSE, seed = 2)}) # summary summary2 <- as.data.frame(rstan::summary(fit2$model, pars = c('mu','alpha','log_p10'), probs = c(0.025, 0.975))$summary) # set up empty vector to check if true values are in 95% interval of # posterior estimates check <- rep(NA,length(mu)+length(alpha)+length(log_p10)) # check mu for(i in 1:nsite){ par <- paste0('mu[',i,']') if(mu[i] > summary2[par,'2.5%'] && mu[i] < summary2[par,'97.5%']){ check[i] <- TRUE } else { check[i] <- FALSE } } # check alpha for(i in seq_along(alpha)){ par <- paste0('alpha[',i,']') if(alpha[i] > summary2[par,'2.5%'] && alpha[i] < summary2[par,'97.5%']){ check[nsite+i] <- TRUE } else { check[nsite+i] <- FALSE } } # check p10 if(log_p10 > summary2['log_p10','2.5%'] && log_p10 < summary2['log_p10','97.5%']){ check[nsite+length(alpha)+1] <- TRUE } else { check[nsite+length(alpha)+1] <- FALSE } #' @srrstats {G3.0, G5.6a} Instead of comparing floating point values for #' equality, here the model is tested to determine if the true parameter #' values are within the 95% quantiles of the posterior # all should be equal to true expect_equal(check,rep(TRUE,nsite+length(alpha)+length(log_p10))) ################################ # model run 3: larger dataset # ################################ # simulate data: seed 123 set.seed(123) # constants nsite <- 20 nobs_count <- 200 # increased dataset size (doubled) nobs_pcr <- 16 # increased dataset size (doubled) # params mu <- rlnorm(nsite,meanlog = log(1),sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 # count count <- matrix(NA,nrow = nsite,ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rpois(nobs_count,mu[i]) } # site-level covariates mat_site <- matrix(NA,nrow = nsite,ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # run model fit_large <- suppressWarnings({jointModel(data = data, cov = c('var_a','var_b'), multicore = FALSE, seed = 10)}) # summary summary_large <- as.data.frame(rstan::summary(fit_large$model, pars = 'alpha', probs = c(0.025, 0.975))$summary) # compare standard errors of estimates of alpha coefficients with # implementation with a smaller dataset se_large <- c(summary_large['alpha[2]','se_mean'], summary_large['alpha[3]','se_mean'] ) # get values for smaller dataset se_small <- c(summary1['alpha[2]','se_mean'], summary1['alpha[3]','se_mean'] ) # set up empty vector to check if standard errors are smaller with # larger dataset check <- rep(NA,length(alpha)-1) for(i in seq_along(check)){ check[i] <- se_large[i] < se_small[i] } #' @srrstats {G5.7} Check to see that implementation performs as expected #' properties of data change (i.e., standard error of posteriors is smaller #' if there are more data observations) # all should be equal to true expect_equal(check,rep(TRUE,length(alpha)-1)) }) test_that("jointModel probability distribution tests work",{ #' @srrstats {PD4.2} This package fits models with fixed distributions to #' data. Users can choose the distribution used to represent the #' data generating process for traditional survey data through an input #' argument to the function (family). This test assesses whether estimates #' of mu, or the site-level expected catch rate, is different when a #' negative binomial or poisson distribution is used to represent the data #' generating process. ####################################################### # generate data with a negative binomial distribution # set.seed(222) # constants nsite <- 20 nobs_count <- 200 nobs_pcr <- 8 # params mu <- rlnorm(nsite,meanlog = log(1),sdlog = 1) beta <- 0.5 log_p10 <- -4.5 phi <- 0.1 # count count <- matrix(NA,nrow = nsite,ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rnbinom(nobs_count,mu = mu[i],size = phi) } # p11 (probability of true positive eDNA detection) and p (probability of # eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA,nrow = nsite,ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count ) ############################################################## # fit data with a negative binomial and poisson distribution # # run model -- negative binomial distribution negbin.fit <- suppressWarnings({jointModel(data = data, multicore = FALSE, family = 'negbin',seed = 2)}) # run model -- poisson distribution pois.fit <- suppressWarnings({jointModel(data = data, multicore = FALSE, family = 'poisson',seed = 2)}) # summarize outputs negbin_summary <- as.data.frame(rstan::summary(negbin.fit$model, pars = 'mu', probs = c(0.025, 0.975))$summary) pois_summary <- as.data.frame(rstan::summary(pois.fit$model, pars = 'mu', probs = c(0.025, 0.975))$summary) # summarize differences in mean estimates of mu summary_table <- table(negbin_summary$mean > pois_summary$mean) # calculate percentage of mean estimates of mu that are greater when # a negative binomial distribution are used rather than a poisson distribution percent <- summary_table[[2]]/(summary_table[[2]]+summary_table[[1]]) # test that estimates of mu when a negative binomial distribution is used is # greater than estimates of mu when a poisson distribution is used for # >80% of sites expect_gt(percent,0.8) }) test_that("semi-paired model works", { ## 1. # model includes 'p10','q','phi','beta' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 q <- 2 phi <- 1.2 # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rnbinom(n = 1, mu = mu[i], size = phi) } else { count[i,j] <- rnbinom(n = 1, mu = mu[i]*q, size = phi) } } } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), beta = beta, phi = phi, q = q ) names(inits[[1]]) <- c('mu','p10','beta','phi','q') # run model fit <- suppressWarnings({jointModel(data = data, q = TRUE, family = 'negbin', initial_values = inits, n.iter.burn = 25, n.iter.sample = 75, n.chain = 1, multicore = FALSE, seed = 10 )}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','phi','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 2. # model includes 'p10','beta','q' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 q <- 2 # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rpois(1, mu[i]) } else { count[i,j] <- rpois(1, mu[i]*q) } } } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i], nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), beta = beta, q = q ) names(inits[[1]]) <- c('mu','p10','beta','q') # run model fit <- suppressWarnings({jointModel(data = data, q = TRUE, n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 3. # model includes 'p10','beta','q', 'alpha_gamma','beta_gamma' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 q <- 2 beta_gamma <- 1 alpha_gamma <- mu * beta_gamma # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rgamma(1,shape = alpha_gamma[i],rate = beta_gamma) } else { count[i,j] <- rgamma(1,shape = alpha_gamma[i]*q,rate = beta_gamma) } } } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type ) # initial values inits <- list() inits[[1]] <- list( alpha_gamma = mu, beta_gamma = rep(1,length(mu)), p10 = exp(log_p10), beta = beta, q = q ) names(inits[[1]]) <- c('alpha_gamma','beta_gamma','p10','beta','q') # run model fit <- suppressWarnings({jointModel(data = data, q = TRUE, family = 'gamma', n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 4. # model includes 'p10','phi','beta' # constants nsite <- 50 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 phi <- 1.2 # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rnbinom(n = nobs_count, mu = mu[i], size = phi) } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count ) # add NA to sites 2 and 4 count[c(2,4),] <- NA # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), beta = beta, phi = phi ) names(inits[[1]]) <- c('mu','p10','beta','phi') # run model fit <- suppressWarnings({jointModel(data = data, family = 'negbin', initial_values = inits, n.chain = 1, multicore = FALSE, seed = 10, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','phi','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) ## 5. # model includes 'p10','beta' # constants nsite <- 50 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rpois(nobs_count, mu[i]) } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), beta = beta ) names(inits[[1]]) <- c('mu','p10','beta') # run model fit <- suppressWarnings({jointModel(data = data, initial_values = inits, n.chain = 1, multicore = FALSE, seed = 10, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) ## 6. # model includes 'p10','beta','alpha_gamma','alpha_beta' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) beta <- 0.5 log_p10 <- -4.5 beta_gamma <- 1 alpha_gamma <- mu * beta_gamma # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rgamma(nobs_count,shape = alpha_gamma[i],rate = beta_gamma) } # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(beta)) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count ) # initial values inits <- list() inits[[1]] <- list( alpha_gamma = mu, beta_gamma = rep(1,length(mu)), p10 = exp(log_p10), beta = beta ) names(inits[[1]]) <- c('alpha_gamma','beta_gamma','p10','beta') # run model fit <- suppressWarnings({jointModel(data = data, initial_values = inits, family = 'gamma', n.chain = 1, multicore = FALSE, seed = 10, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','beta') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) ## 7. # model includes 'p10','q','phi','alpha' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 q <- 2 phi <- 10 # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rnbinom(n = 1, mu = mu[i], size = phi) } else { count[i,j] <- rnbinom(n = 1, mu = mu[i]*q, size = phi) } } } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), alpha = alpha, q = q, phi = phi ) names(inits[[1]]) <- c('mu','p10','alpha','q','phi' ) # run model fit <- suppressWarnings({jointModel(data = data, family = 'negbin', q = TRUE, cov = c('var_a','var_b'), n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, adapt_delta = 0.99, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','phi','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 8. # model includes 'p10','alpha','q' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 q <- 2 # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rpois(n = 1, mu[i]) } else { count[i,j] <- rpois(n = 1, mu[i]*q) } } } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), alpha = alpha ) names(inits[[1]]) <- c('mu','p10','alpha' ) # run model fit <- suppressWarnings({jointModel(data = data, q = TRUE, cov = c('var_a','var_b'), n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 9. # model includes 'p10','alpha','q', 'alpha_gamma', 'alpha_beta' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 q <- 2 beta_gamma <- 1 alpha_gamma <- mu * beta_gamma # traditional type count_type <- cbind(matrix(1, nrow = nsite, ncol = nobs_count/2), matrix(2, nrow = nsite, ncol = nobs_count/2)) # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ for(j in 1:nobs_count){ if(count_type[i,j]==1){ count[i,j] <- rgamma(1,shape = alpha_gamma[i],rate = beta_gamma) } else { count[i,j] <- rgamma(1,shape = alpha_gamma[i]*q,rate = beta_gamma) } } } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA count_type[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, count.type = count_type, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( alpha_gamma = mu, beta_gamma = rep(1,length(mu)), p10 = exp(log_p10), alpha = alpha, q = q ) names(inits[[1]]) <- c('alpha_gamma','beta_gamma','p10','alpha','q' ) # run model fit <- suppressWarnings({jointModel(data = data, q = TRUE, family = 'gamma', cov = c('var_a','var_b'), n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75 )}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','q[1]','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite*2) expect_true(is.numeric(mu_estimates)) ## 10. # model includes 'p10','phi','alpha' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 phi <- 10 # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rnbinom(n = nobs_count, mu = mu[i], size = phi) } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), alpha = alpha, phi = phi ) names(inits[[1]]) <- c('mu','p10','alpha', 'phi') # run model fit <- suppressWarnings({jointModel(data = data, family = 'negbin', cov = c('var_a','var_b'),n.iter.burn = 25, n.iter.sample = 75, n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','phi','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) ## 11. # model includes 'p10','alpha' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rpois(nobs_count, mu[i]) } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( mu = mu, p10 = exp(log_p10), alpha = alpha ) names(inits[[1]]) <- c('mu','p10','alpha' ) # run model fit <- suppressWarnings({jointModel(data = data, cov = c('var_a','var_b'), n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) ## 12. # model includes 'p10','alpha','alpha_gamma','beta_gamma' # constants nsite <- 20 nobs_count <- 100 nobs_pcr <- 8 # params mu <- rlnorm(nsite, meanlog = log(1), sdlog = 1) alpha <- c(0.5, 0.1, -0.4) log_p10 <- -4.5 beta_gamma <- 1 alpha_gamma <- mu * beta_gamma # count count <- matrix(NA, nrow = nsite, ncol = nobs_count) for(i in 1:nsite){ count[i,] <- rgamma(nobs_count,shape = alpha_gamma[i],rate = beta_gamma) } # site-level covariates mat_site <- matrix(NA, nrow = nsite, ncol = length(alpha)) mat_site[,1] <- 1 # intercept for(i in 2:length(alpha)){ mat_site[,i] <- rnorm(nsite,0,1) } colnames(mat_site) <- c('int','var_a','var_b') # p11 (probability of true positive eDNA detection) and p (probability # of eDNA detection) p11 <- rep(NA,nsite) p <- rep(NA,nsite) for (i in 1:nsite){ p11[i] <- mu[i] / (mu[i] + exp(sum(mat_site[i,]*alpha))) p[i] <- min(p11[i] + exp(log_p10),1) } # qPCR.N (# qPCR observations) qPCR.N <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for(i in 1:nsite){ qPCR.N[i,] <- rep(3,nobs_pcr) } # qPCR.K (# positive qPCR detections) qPCR.K <- matrix(NA, nrow = nsite, ncol = nobs_pcr) for (i in 1:nsite){ qPCR.K[i,] <- rbinom(nobs_pcr, qPCR.N[i,], rep(p[i],nobs_pcr)) } # add NA to sites 2 and 4 count[c(2,4),] <- NA # collect data data <- list( qPCR.N = qPCR.N, qPCR.K = qPCR.K, count = count, site.cov = mat_site ) # initial values inits <- list() inits[[1]] <- list( alpha_gamma = mu, beta_gamma = rep(1,length(mu)), p10 = exp(log_p10), alpha = alpha ) names(inits[[1]]) <- c('alpha_gamma','beta_gamma','p10','alpha' ) # run model fit <- suppressWarnings({jointModel(data = data,family = 'gamma', cov = c('var_a','var_b'), n.chain = 1, multicore = FALSE, seed = 10, initial_values = inits, n.iter.burn = 25, n.iter.sample = 75)}) # get output params output_params <- rownames(as.data.frame(jointSummarize(fit$model))) # test expectation expect_true(all(c('p10','alpha[1]') %in% output_params)) # check length of of mu mu_estimates <- as.vector(rstan::summary(fit$model,par='mu')$summary[,1]) expect_equal(length(mu_estimates),nsite) expect_true(is.numeric(mu_estimates)) })