time-dependent-9-tunnel-states.R 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # We will use cycles from 0 to 100
  2. cycles <- 0:100
  3. # We use 10 states for Diseased (9 tunnel and 1 with self-loop)
  4. n_tunnel <- 9
  5. states <- c("Healthy", paste0("Diseased", sprintf("%02i", 1:(n_tunnel+1))), "Dead")
  6. # Create an array for the state membership
  7. state_membership <- array(NA_real_, c(length(cycles), length(states)), list(cycle = cycles, state = states))
  8. state_membership[1, ] <- c(1, rep(0, length(states) - 1))
  9. # Define the survival model parameters
  10. # - Healthy to Diseased
  11. lambda_inc <- 2e-5
  12. gamma_inc <- 2.5
  13. # - Healthy to Dead
  14. a_general <- 0.2
  15. b_general <- 1e-7
  16. # - Diseased to Dead
  17. lambda_surv <- 0.2
  18. gamma_surv <- 0.5
  19. # Calculate exponential distribution with same mean survival as conditional
  20. # Weibull distribution for Diseased to Dead given survived to 10th state
  21. upper_incomplete_gamma <- function(a, x) pgamma(x, a, lower = FALSE) * gamma(a)
  22. mean_surv <- exp(lambda_surv * n_tunnel ^ gamma_surv) * lambda_surv ^ (-1 / gamma_surv) * upper_incomplete_gamma(1 + 1 / gamma_surv, lambda_surv * n_tunnel ^ gamma_surv)
  23. rate_surv <- 1 / mean_surv
  24. # Calculate the hazard rates for the transitions out of the Healthy state
  25. healthy_haz <- array(NA_real_, c(length(cycles), 2), list(cycle = cycles, to = c("Diseased", "Dead")))
  26. healthy_haz[, 1] <- lambda_inc * ((cycles + 1) ^ gamma_inc - cycles ^ gamma_inc)
  27. healthy_haz[, 2] <- b_general / a_general * (exp(a_general * (cycles + 1)) - exp(a_general * cycles))
  28. # Create an array for transition probabilities in each cycle
  29. transition_probs <- array(
  30. NA_real_,
  31. c(length(cycles), 2 + n_tunnel + 1),
  32. list(
  33. cycle = cycles,
  34. transition = c(
  35. "Healthy->Diseased01",
  36. "Healthy->Dead",
  37. paste0("Diseased", sprintf("%02i", 1:(n_tunnel)), "->Diseased", sprintf("%02i", 2:(n_tunnel + 1))),
  38. paste0("Diseased", sprintf("%02i", n_tunnel + 1), "->Diseased", sprintf("%02i", n_tunnel + 1)))))
  39. transition_probs[, 1:2] <- healthy_haz / rowSums(healthy_haz) * (1 - exp(-rowSums(healthy_haz)))
  40. for (t in 1:n_tunnel) {
  41. transition_probs[, t + 2] <- exp(-lambda_surv * (t ^ gamma_surv - (t - 1) ^ gamma_surv))
  42. }
  43. transition_probs[, n_tunnel + 3] <- exp(-rate_surv)
  44. # Run cohort simulation
  45. for (i in 2:length(cycles)) {
  46. # Update state membership
  47. state_membership[i, "Healthy"] <- state_membership[i - 1, "Healthy"] * (1 - transition_probs[i - 1, "Healthy->Diseased01"] - transition_probs[i - 1, "Healthy->Dead"])
  48. state_membership[i, "Diseased01"] <- state_membership[i - 1, "Healthy"] * transition_probs[i - 1, "Healthy->Diseased01"]
  49. for (t in 1:n_tunnel) {
  50. from <- paste0("Diseased", sprintf("%02i", t))
  51. to <- paste0("Diseased", sprintf("%02i", t + 1))
  52. state_membership[i, to] <- state_membership[i - 1, from] * transition_probs[i - 1, paste0(from, "->", to)]
  53. }
  54. last <- paste0("Diseased", sprintf("%02i", n_tunnel + 1))
  55. state_membership[i, last] <- state_membership[i - 1, last] * transition_probs[i - 1, paste0(last, "->", last)] + state_membership[i, last]
  56. state_membership[i, "Dead"] <- 1 - sum(state_membership[i, 1:(n_tunnel+2)])
  57. }
  58. summarised_state_membership <- cbind(state_membership[, "Healthy"], rowSums(state_membership[, 2:(n_tunnel + 2)]), state_membership[, "Dead"])
  59. dimnames(summarised_state_membership) <- list(cycle = cycles, state = c("Healthy", "Diseased", "Dead"))