| 1 | 
                      #' Row Numbers of Data with Missing Variables  | 
                  |
| 2 | 
                      #'  | 
                  |
| 3 | 
                      #' @param df (`data.frame`)\cr input data.  | 
                  |
| 4 | 
                      #' @param formula (`formula` or `NULL`)\cr which variables to inspect for missingness, if `NULL`  | 
                  |
| 5 | 
                      #' all variables are considered.  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' @returns Numeric vector specifying which rows contain at least 1 missing observation  | 
                  |
| 8 | 
                      #' in any of the inspected variables.  | 
                  |
| 9 | 
                      #'  | 
                  |
| 10 | 
                      #' @keywords internal  | 
                  |
| 11 | 
                      get_missing_rownumbers <- function(df, formula = NULL) {
                     | 
                  |
| 12 | 455x | 
                          if (is.null(formula)) {
                     | 
                  
| 13 | ! | 
                      formula <- ~ .  | 
                  
| 14 | 
                      }  | 
                  |
| 15 | 455x | 
                      mdf <- stats::model.frame(formula, data = df, na.action = stats::na.pass)  | 
                  
| 16 | 455x | 
                      which(!stats::complete.cases(mdf))  | 
                  
| 17 | 
                      }  | 
                  |
| 18 | ||
| 19 | 
                      #' Remove Rows with Missing Variables  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' Removes any rows from a data set that contain missing values in the inspected  | 
                  |
| 22 | 
                      #' variables. Allows users to specify which variables to inspect for missing values  | 
                  |
| 23 | 
                      #' based on either a formula or a character vector of variable names.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @param data (`data.frame`)\cr input data.  | 
                  |
| 26 | 
                      #' @param formula (`formula` or `NULL`)\cr which variables to inspect for missingness.  | 
                  |
| 27 | 
                      #' @param extra_vars (`character`)\cr additional variables to inspect for missingness.  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @returns The `data` after removing observations that contain missing values in the required variables.  | 
                  |
| 30 | 
                      #' Note that additional variables not listed in `formula` or `extra_vars` are not dropped and may  | 
                  |
| 31 | 
                      #' still contain missing values.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #' @keywords internal  | 
                  |
| 34 | 
                      remove_missing_rows <- function(data, formula, extra_vars = NULL) {
                     | 
                  |
| 35 | 454x | 
                          if (!is.null(extra_vars)) {
                     | 
                  
| 36 | 1x | 
                      extra_vars <- paste(extra_vars, collapse = " + ")  | 
                  
| 37 | 1x | 
                              formula_update_string <- paste0(". ~ . + ", extra_vars)
                     | 
                  
| 38 | 1x | 
                      formula <- stats::update(formula, formula_update_string)  | 
                  
| 39 | 
                      }  | 
                  |
| 40 | ||
| 41 | 454x | 
                      missing_rows <- get_missing_rownumbers(data, formula)  | 
                  
| 42 | ||
| 43 | 454x | 
                          if (length(missing_rows) == 0) {
                     | 
                  
| 44 | 452x | 
                      return(data)  | 
                  
| 45 | 
                      }  | 
                  |
| 46 | 2x | 
                      message(sprintf(  | 
                  
| 47 | 2x | 
                      "Note that %d observations were removed as one of more required variables contained missing values",  | 
                  
| 48 | 2x | 
                      length(missing_rows)  | 
                  
| 49 | 
                      ))  | 
                  |
| 50 | 2x | 
                      data_reduced <- data[-missing_rows, ]  | 
                  
| 51 | 2x | 
                      rownames(data_reduced) <- NULL  | 
                  
| 52 | 2x | 
                      data_reduced  | 
                  
| 53 | 
                      }  | 
                  |
| 54 | ||
| 55 | 
                      #' Replicate Single Values in a List  | 
                  |
| 56 | 
                      #'  | 
                  |
| 57 | 
                      #' @param initial_values (`list`)\cr initial values with names.  | 
                  |
| 58 | 
                      #' @param sizes (`list`)\cr each size corresponds to an element in `initial_values`,  | 
                  |
| 59 | 
                      #' matched by the names. An attribute `array` must be attached to each element,  | 
                  |
| 60 | 
                      #' see [replace_with_lookup()].  | 
                  |
| 61 | 
                      #'  | 
                  |
| 62 | 
                      #' @returns A named list of values, with any single values in the `initial_values` list  | 
                  |
| 63 | 
                      #' replicated according to the corresponding values in the `sizes` list.  | 
                  |
| 64 | 
                      #' Even when the size is 1, the value is passed as an `array` if the corresponding  | 
                  |
| 65 | 
                      #' attribute is `TRUE` in `sizes`.  | 
                  |
| 66 | 
                      #'  | 
                  |
| 67 | 
                      #' @note The resulting list has the same names as the original lists.  | 
                  |
| 68 | 
                      #'  | 
                  |
| 69 | 
                      #' @keywords internal  | 
                  |
| 70 | 
                      expand_initial_values <- function(initial_values, sizes) {
                     | 
                  |
| 71 | 28x | 
                      assert_that(  | 
                  
| 72 | 28x | 
                      is.list(initial_values),  | 
                  
| 73 | 28x | 
                      msg = "`initial_values` must be a list"  | 
                  
| 74 | 
                      )  | 
                  |
| 75 | 28x | 
                      assert_that(  | 
                  
| 76 | 28x | 
                      is.list(sizes),  | 
                  
| 77 | 28x | 
                      msg = "`sizes` must be a list"  | 
                  
| 78 | 
                      )  | 
                  |
| 79 | 28x | 
                      assert_that(  | 
                  
| 80 | 28x | 
                      all(names(sizes) %in% names(initial_values)),  | 
                  
| 81 | 28x | 
                      all(names(initial_values) %in% names(sizes)),  | 
                  
| 82 | 28x | 
                      msg = "`initial_values` and `sizes` must have identical names"  | 
                  
| 83 | 
                      )  | 
                  |
| 84 | ||
| 85 | 28x | 
                          for (name in names(initial_values)) {
                     | 
                  
| 86 | 
                      # Check for single values and replicate them according to sizes.  | 
                  |
| 87 | 181x | 
                              if (length(initial_values[[name]]) == 1) {
                     | 
                  
| 88 | 178x | 
                      initial_values[[name]] <- rep(initial_values[[name]], sizes[[name]])  | 
                  
| 89 | 
                      }  | 
                  |
| 90 | 
                      # Check for array handling.  | 
                  |
| 91 | 181x | 
                      needs_array <- attr(sizes[[name]], "array")  | 
                  
| 92 | 181x | 
                      assert_that(  | 
                  
| 93 | 181x | 
                      is.flag(needs_array),  | 
                  
| 94 | 181x | 
                      msg = "each sizes element must have array flag attribute"  | 
                  
| 95 | 
                      )  | 
                  |
| 96 | 181x | 
                              if (needs_array) {
                     | 
                  
| 97 | 101x | 
                      initial_values[[name]] <- as.array(initial_values[[name]])  | 
                  
| 98 | 
                      }  | 
                  |
| 99 | 
                      }  | 
                  |
| 100 | ||
| 101 | 
                      # Check that each element of initial_values has the same length as specified in sizes.  | 
                  |
| 102 | 28x | 
                          for (name in names(initial_values)) {
                     | 
                  
| 103 | 181x | 
                      assert_that(  | 
                  
| 104 | 181x | 
                      length(initial_values[[name]]) == sizes[[name]],  | 
                  
| 105 | 181x | 
                      msg = "length of element in `initial_values` does not match specified size"  | 
                  
| 106 | 
                      )  | 
                  |
| 107 | 
                      }  | 
                  |
| 108 | ||
| 109 | 28x | 
                      initial_values  | 
                  
| 110 | 
                      }  | 
                  |
| 111 | ||
| 112 | 
                      #' Replace Character Size by Looked Up Numbers  | 
                  |
| 113 | 
                      #'  | 
                  |
| 114 | 
                      #' @param sizes (`list`)\cr may include character elements that correspond to  | 
                  |
| 115 | 
                      #' names in the data list.  | 
                  |
| 116 | 
                      #' @param data (`list`)\cr data containing numeric values.  | 
                  |
| 117 | 
                      #'  | 
                  |
| 118 | 
                      #' @returns A list of sizes with character elements in `sizes`  | 
                  |
| 119 | 
                      #' replaced by their corresponding numeric values in `data`.  | 
                  |
| 120 | 
                      #'  | 
                  |
| 121 | 
                      #' @details An attribute `array` for each returned list element indicates  | 
                  |
| 122 | 
                      #' whether the parameter needs to be handled  | 
                  |
| 123 | 
                      #' as an array. This is the case when the size is larger than 1, or when  | 
                  |
| 124 | 
                      #' the size was looked up in the `data`, because in that case it is flexible  | 
                  |
| 125 | 
                      #' and hence is handled as an array in the Stan code.  | 
                  |
| 126 | 
                      #'  | 
                  |
| 127 | 
                      #' @note Each element in the final list of sizes must be a single number.  | 
                  |
| 128 | 
                      #'  | 
                  |
| 129 | 
                      #' @keywords internal  | 
                  |
| 130 | 
                      replace_with_lookup <- function(sizes, data) {
                     | 
                  |
| 131 | ||
| 132 | 21x | 
                      assert_that(is.list(sizes), msg = "`sizes` must be a list")  | 
                  
| 133 | 21x | 
                      assert_that(is.list(data), msg = "`data` must be a list")  | 
                  
| 134 | ||
| 135 | 21x | 
                          for (idx in seq_along(sizes)) {
                     | 
                  
| 136 | 130x | 
                      val <- sizes[[idx]]  | 
                  
| 137 | 130x | 
                              if (is.character(val)) {
                     | 
                  
| 138 | 70x | 
                      assert_that(  | 
                  
| 139 | 70x | 
                      length(val) == 1,  | 
                  
| 140 | 70x | 
                      msg = "character elements of `sizes` must be strings"  | 
                  
| 141 | 
                      )  | 
                  |
| 142 | 70x | 
                      assert_that(  | 
                  
| 143 | 70x | 
                      val %in% names(data),  | 
                  
| 144 | 70x | 
                                      msg = sprintf("`%s` is not available in `data`", val)
                     | 
                  
| 145 | 
                      )  | 
                  |
| 146 | 70x | 
                      new_val <- data[[val]]  | 
                  
| 147 | 70x | 
                      assert_that(  | 
                  
| 148 | 70x | 
                      is.number(new_val),  | 
                  
| 149 | 70x | 
                      msg = "Selected values from data must be single numbers"  | 
                  
| 150 | 
                      )  | 
                  |
| 151 | 69x | 
                      sizes[[idx]] <- structure(new_val, array = TRUE)  | 
                  
| 152 | 
                              } else {
                     | 
                  |
| 153 | 60x | 
                      assert_that(  | 
                  
| 154 | 60x | 
                      is.number(val),  | 
                  
| 155 | 60x | 
                      msg = "Existing values in sizes must be single numbers"  | 
                  
| 156 | 
                      )  | 
                  |
| 157 | 59x | 
                      sizes[[idx]] <- structure(val, array = val > 1)  | 
                  
| 158 | 
                      }  | 
                  |
| 159 | 
                      }  | 
                  |
| 160 | 19x | 
                      sizes  | 
                  
| 161 | 
                      }  | 
                  |
| 162 | ||
| 163 | 
                      #' Obtain Median and Credible Intervals from MCMC samples  | 
                  |
| 164 | 
                      #'  | 
                  |
| 165 | 
                      #' @param samples (`matrix`)\cr with samples in rows and parameters in columns.  | 
                  |
| 166 | 
                      #' @param level (`number`)\cr credibility level to use for the credible intervals.  | 
                  |
| 167 | 
                      #'  | 
                  |
| 168 | 
                      #' @returns A `data.frame` with columns `median`, `lower` and `upper`.  | 
                  |
| 169 | 
                      #' @keywords internal  | 
                  |
| 170 | 
                      #' samples_median_ci(samples)  | 
                  |
| 171 | 
                      samples_median_ci <- function(samples, level = 0.95) {
                     | 
                  |
| 172 | 38x | 
                      assert_that(is.matrix(samples))  | 
                  
| 173 | 38x | 
                      assert_that(is.number(level), level < 1, level > 0)  | 
                  
| 174 | ||
| 175 | 38x | 
                      samples_median <- apply(samples, MARGIN = 2L, FUN = stats::median)  | 
                  
| 176 | 38x | 
                      probs <- c((1 - level) / 2, (1 + level) / 2)  | 
                  
| 177 | 38x | 
                      samples_ci <- t(apply(samples, MARGIN = 2L, FUN = stats::quantile, probs = probs))  | 
                  
| 178 | 38x | 
                          colnames(samples_ci) <- c("lower", "upper")
                     | 
                  
| 179 | 38x | 
                      as.data.frame(cbind(  | 
                  
| 180 | 38x | 
                      median = samples_median,  | 
                  
| 181 | 38x | 
                      samples_ci  | 
                  
| 182 | 
                      ))  | 
                  |
| 183 | 
                      }  | 
                  |
| 184 | ||
| 185 | ||
| 186 | ||
| 187 | 
                      #' `decorated_render`  | 
                  |
| 188 | 
                      #'  | 
                  |
| 189 | 
                      #' Simple wrapper around [jinjar::render()] that provides some additional default  | 
                  |
| 190 | 
                      #' variables about the system (avoids each call to jinjar having to specify them)  | 
                  |
| 191 | 
                      #' @param ... Arguments passed onto [jinjar::render()]  | 
                  |
| 192 | 
                      #' @returns See [jinjar::render()]  | 
                  |
| 193 | 
                      #' @keywords internal  | 
                  |
| 194 | 
                      decorated_render <- function(...) {
                     | 
                  |
| 195 | 343x | 
                      jinjar::render(  | 
                  
| 196 | 
                      ...,  | 
                  |
| 197 | 343x | 
                      machine_double_eps = sqrt(.Machine$double.eps),  | 
                  
| 198 | 343x | 
                      machine_double_neg_eps = sqrt(.Machine$double.neg.eps)  | 
                  
| 199 | 
                      )  | 
                  |
| 200 | 
                      }  | 
                  |
| 201 | ||
| 202 | ||
| 203 | 
                      is_windows <- function() {
                     | 
                  |
| 204 | 52x | 
                      sysname <- Sys.info()["sysname"]  | 
                  
| 205 | 52x | 
                      return(sysname == "Windows")  | 
                  
| 206 | 
                      }  | 
                  |
| 207 | ||
| 208 | 
                      #' `validate_time_grid`  | 
                  |
| 209 | 
                      #'  | 
                  |
| 210 | 
                      #' Validate that the provided time grid is:  | 
                  |
| 211 | 
                      #' - finite  | 
                  |
| 212 | 
                      #' - numeric  | 
                  |
| 213 | 
                      #' - non-missing  | 
                  |
| 214 | 
                      #' - sorted  | 
                  |
| 215 | 
                      #' - unique  | 
                  |
| 216 | 
                      #'  | 
                  |
| 217 | 
                      #' @param time_grid (`numeric`)\cr A vector of times which quantities will be  | 
                  |
| 218 | 
                      #' evaluated at.  | 
                  |
| 219 | 
                      #'  | 
                  |
| 220 | 
                      #' @keywords internal  | 
                  |
| 221 | 
                      validate_time_grid <- function(time_grid) {
                     | 
                  |
| 222 | 80x | 
                      assert_that(  | 
                  
| 223 | 80x | 
                      !any(is.na(time_grid)),  | 
                  
| 224 | 80x | 
                      is.numeric(time_grid),  | 
                  
| 225 | 80x | 
                      !is.null(time_grid),  | 
                  
| 226 | 80x | 
                      !is.unsorted(time_grid),  | 
                  
| 227 | 80x | 
                      !any(duplicated(time_grid)),  | 
                  
| 228 | 80x | 
                      all(is.finite(time_grid)),  | 
                  
| 229 | 80x | 
                      msg = "`time_grid` needs to be finite, sorted, unique valued numeric vector"  | 
                  
| 230 | 
                      )  | 
                  |
| 231 | 76x | 
                      invisible(time_grid)  | 
                  
| 232 | 
                      }  | 
                  |
| 233 | ||
| 234 | ||
| 235 | ||
| 236 | 
                      #' `expand_subjects`  | 
                  |
| 237 | 
                      #'  | 
                  |
| 238 | 
                      #' This function checks and expands a given subjects vector.  | 
                  |
| 239 | 
                      #' The input vector must be unique and contain only values  | 
                  |
| 240 | 
                      #' as specified by `all_subjects`  | 
                  |
| 241 | 
                      #'  | 
                  |
| 242 | 
                      #' @param subjects (`character` or `NULL`)\cr Character vector representing the subjects.  | 
                  |
| 243 | 
                      #' If NULL, it will be set to the value of `all_subjects`.  | 
                  |
| 244 | 
                      #' @param all_subjects (`character`)\cr Character vector representing all possible subjects.  | 
                  |
| 245 | 
                      #' @return Returns the expanded `subjects` vector.  | 
                  |
| 246 | 
                      #' @keywords internal  | 
                  |
| 247 | 
                      expand_subjects <- function(subjects, all_subjects) {
                     | 
                  |
| 248 | 38x | 
                      assert_that(  | 
                  
| 249 | 38x | 
                      is.character(all_subjects),  | 
                  
| 250 | 38x | 
                      msg = "`all_subjects` must be a character vector"  | 
                  
| 251 | 
                      )  | 
                  |
| 252 | 38x | 
                          if (is.null(subjects)) {
                     | 
                  
| 253 | 3x | 
                      subjects <- unique(all_subjects)  | 
                  
| 254 | 
                      }  | 
                  |
| 255 | 38x | 
                      assert_that(  | 
                  
| 256 | 38x | 
                      is.character(subjects),  | 
                  
| 257 | 38x | 
                      all(subjects %in% all_subjects),  | 
                  
| 258 | 38x | 
                      !any(duplicated(subjects)),  | 
                  
| 259 | 38x | 
                      msg = "`subjects` should be a unique character vector containing only values from the original df"  | 
                  
| 260 | 
                      )  | 
                  |
| 261 | 30x | 
                      return(subjects)  | 
                  
| 262 | 
                      }  | 
                  |
| 263 | ||
| 264 | ||
| 265 | ||
| 266 | 
                      #' Decompose subjects into Relevant Components  | 
                  |
| 267 | 
                      #'  | 
                  |
| 268 | 
                      #' This function takes in a character vector or list of subjects and decomposes it into a  | 
                  |
| 269 | 
                      #' structured format.  | 
                  |
| 270 | 
                      #'  | 
                  |
| 271 | 
                      #' The primary use of this function is to correctly setup indexing variables for  | 
                  |
| 272 | 
                      #' predicting survival quantities (see [SurvivalQuantities()])  | 
                  |
| 273 | 
                      #'  | 
                  |
| 274 | 
                      #' @param subjects (`character` or `list`)\cr subject identifiers. If `NULL` will be set to `all_subjects`.  | 
                  |
| 275 | 
                      #'  | 
                  |
| 276 | 
                      #' @param all_subjects (`character`)\cr the set of allowable subject identifiers.  | 
                  |
| 277 | 
                      #' Will cause an error if any value of `subjects` is not in this vector.  | 
                  |
| 278 | 
                      #'  | 
                  |
| 279 | 
                      #' @return A list containing three components:  | 
                  |
| 280 | 
                      #' - `groups`: (`list`)\cr each element of the list is a character vector  | 
                  |
| 281 | 
                      #' specifying which subjects belong to a given "group" where the "group" is the element name  | 
                  |
| 282 | 
                      #' - `unique_values`: (`character`)\cr vector of the unique subjects within `subjects`  | 
                  |
| 283 | 
                      #' - `indexes`: (`list`)\cr each element is a named and is a numeric index vector  | 
                  |
| 284 | 
                      #' that maps the values of `grouped` to `unique_values`  | 
                  |
| 285 | 
                      #' @examples  | 
                  |
| 286 | 
                      #' \dontrun{
                     | 
                  |
| 287 | 
                      #' result <- decompose_subjects(c("A", "B"), c("A", "B", "C", "D"))
                     | 
                  |
| 288 | 
                      #' result <- decompose_subjects(  | 
                  |
| 289 | 
                      #'     list("g1" = c("A", "B"), "g2" = c("B", "C")),
                     | 
                  |
| 290 | 
                      #'     c("A", "B", "C", "D")
                     | 
                  |
| 291 | 
                      #' )  | 
                  |
| 292 | 
                      #' }  | 
                  |
| 293 | 
                      #' @seealso [expand_subjects()], [SurvivalQuantities()]  | 
                  |
| 294 | 
                      #' @keywords internal  | 
                  |
| 295 | 
                      decompose_subjects <- function(subjects, all_subjects) {
                     | 
                  |
| 296 | 13x | 
                          if (is.character(subjects) || is.null(subjects)) {
                     | 
                  
| 297 | 7x | 
                      subjects <- expand_subjects(subjects, all_subjects)  | 
                  
| 298 | 4x | 
                      names(subjects) <- subjects  | 
                  
| 299 | 4x | 
                      subjects <- as.list(subjects)  | 
                  
| 300 | 
                      }  | 
                  |
| 301 | 10x | 
                      subjects <- lapply(  | 
                  
| 302 | 10x | 
                      subjects,  | 
                  
| 303 | 10x | 
                      expand_subjects,  | 
                  
| 304 | 10x | 
                      all_subjects = all_subjects  | 
                  
| 305 | 
                      )  | 
                  |
| 306 | 8x | 
                      assert_that(  | 
                  
| 307 | 8x | 
                      is.list(subjects),  | 
                  
| 308 | 8x | 
                      length(unique(names(subjects))) == length(subjects),  | 
                  
| 309 | 8x | 
                      all(vapply(subjects, is.character, logical(1)))  | 
                  
| 310 | 
                      )  | 
                  |
| 311 | 8x | 
                      subjects_vec_unordered <- unique(unlist(subjects))  | 
                  
| 312 | 8x | 
                      subjects_vec <- subjects_vec_unordered[order(subjects_vec_unordered)]  | 
                  
| 313 | 8x | 
                      subjects_lookup <- stats::setNames(seq_along(subjects_vec), subjects_vec)  | 
                  
| 314 | 8x | 
                      subjects_index <- lapply(  | 
                  
| 315 | 8x | 
                      subjects,  | 
                  
| 316 | 8x | 
                              \(x) {
                     | 
                  
| 317 | 22x | 
                      z <- subjects_lookup[x]  | 
                  
| 318 | 22x | 
                      names(z) <- NULL  | 
                  
| 319 | 22x | 
                      z  | 
                  
| 320 | 
                      }  | 
                  |
| 321 | 
                      )  | 
                  |
| 322 | 8x | 
                      list(  | 
                  
| 323 | 8x | 
                      groups = subjects,  | 
                  
| 324 | 8x | 
                      unique_values = subjects_vec,  | 
                  
| 325 | 8x | 
                      indexes = subjects_index  | 
                  
| 326 | 
                      )  | 
                  |
| 327 | 
                      }  | 
                  |
| 328 | ||
| 329 | 
                      is_cmdstanr_available <- function() {
                     | 
                  |
| 330 | 4x | 
                          requireNamespace("cmdstanr", quietly = TRUE)
                     | 
                  
| 331 | 
                      }  | 
                  |
| 332 | ||
| 333 | ||
| 334 | 
                      is_connection <- function(obj) {
                     | 
                  |
| 335 | ! | 
                      inherits(obj, "connection")  | 
                  
| 336 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include StanModule.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' `Prior` Function Arguments  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' The documentation lists all the conventional arguments for [`Prior`]  | 
                  |
| 8 | 
                      #' constructors.  | 
                  |
| 9 | 
                      #'  | 
                  |
| 10 | 
                      #' @param centre (`number`)\cr the central point of distribution to shrink sampled values towards  | 
                  |
| 11 | 
                      #' (for most distributions this is the mean or median if the mean is undefined)  | 
                  |
| 12 | 
                      #' @param x ([`Prior`])\cr a prior Distribution  | 
                  |
| 13 | 
                      #' @param object ([`Prior`])\cr a prior Distribution  | 
                  |
| 14 | 
                      #' @param name (`character`)\cr the name of the parameter the prior distribution is for  | 
                  |
| 15 | 
                      #' @param ... Not Used.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @name Prior-Shared  | 
                  |
| 18 | 
                      #' @keywords internal  | 
                  |
| 19 | 
                      NULL  | 
                  |
| 20 | ||
| 21 | 
                      # Prior-class ----  | 
                  |
| 22 | ||
| 23 | 
                      #' Prior Object and Constructor Function  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' Specifies the prior distribution in a Stan Model  | 
                  |
| 26 | 
                      #'  | 
                  |
| 27 | 
                      #' @slot parameters (`list`)\cr See arguments.  | 
                  |
| 28 | 
                      #' @slot repr_model (`string`)\cr See arguments.  | 
                  |
| 29 | 
                      #' @slot repr_data (`string`)\cr See arguments.  | 
                  |
| 30 | 
                      #' @slot centre (`numeric`)\cr See arguments.  | 
                  |
| 31 | 
                      #' @slot validation (`list`)\cr See arguments.  | 
                  |
| 32 | 
                      #' @slot display (`string`)\cr See arguments.  | 
                  |
| 33 | 
                      #' @slot sample (`function`)\cr See arguments.  | 
                  |
| 34 | 
                      #' @slot limits (`numeric`)\cr See arguments.  | 
                  |
| 35 | 
                      #'  | 
                  |
| 36 | 
                      #' @family Prior-internal  | 
                  |
| 37 | 
                      #' @export Prior  | 
                  |
| 38 | 
                      #' @exportClass Prior  | 
                  |
| 39 | 
                      .Prior <- setClass(  | 
                  |
| 40 | 
                      Class = "Prior",  | 
                  |
| 41 | 
                      slots = c(  | 
                  |
| 42 | 
                      "parameters" = "list",  | 
                  |
| 43 | 
                      "display" = "character",  | 
                  |
| 44 | 
                      "repr_model" = "character",  | 
                  |
| 45 | 
                      "repr_data" = "character",  | 
                  |
| 46 | 
                      "centre" = "numeric",  | 
                  |
| 47 | 
                      "validation" = "list",  | 
                  |
| 48 | 
                      "sample" = "function",  | 
                  |
| 49 | 
                      "limits" = "numeric"  | 
                  |
| 50 | 
                      )  | 
                  |
| 51 | 
                      )  | 
                  |
| 52 | ||
| 53 | ||
| 54 | 
                      #' @param parameters (`list`)\cr the prior distribution parameters.  | 
                  |
| 55 | 
                      #' @param repr_model (`string`)\cr the Stan code representation for the model block.  | 
                  |
| 56 | 
                      #' @param repr_data (`string`)\cr the Stan code representation for the data block.  | 
                  |
| 57 | 
                      #' @param display (`string`)\cr the string to display when object is printed.  | 
                  |
| 58 | 
                      #' @param centre (`numeric`)\cr the central point of distribution to shrink sampled values towards  | 
                  |
| 59 | 
                      #' @param validation (`list`)\cr the prior distribution parameter validation functions. Must have  | 
                  |
| 60 | 
                      #' the same names as the `paramaters` slot.  | 
                  |
| 61 | 
                      #' @param sample (`function`)\cr a function to sample from the prior distribution.  | 
                  |
| 62 | 
                      #' @param limits (`numeric`)\cr the lower and upper limits for a truncated distribution  | 
                  |
| 63 | 
                      #' @rdname Prior-class  | 
                  |
| 64 | 
                      Prior <- function(  | 
                  |
| 65 | 
                      parameters,  | 
                  |
| 66 | 
                      display,  | 
                  |
| 67 | 
                      repr_model,  | 
                  |
| 68 | 
                      repr_data,  | 
                  |
| 69 | 
                      centre,  | 
                  |
| 70 | 
                      validation,  | 
                  |
| 71 | 
                      sample,  | 
                  |
| 72 | 
                      limits = c(-Inf, Inf)  | 
                  |
| 73 | 
                      ) {
                     | 
                  |
| 74 | 932x | 
                      .Prior(  | 
                  
| 75 | 932x | 
                      parameters = parameters,  | 
                  
| 76 | 932x | 
                      repr_model = repr_model,  | 
                  
| 77 | 932x | 
                      repr_data = repr_data,  | 
                  
| 78 | 932x | 
                      centre = centre,  | 
                  
| 79 | 932x | 
                      display = display,  | 
                  
| 80 | 932x | 
                      validation = validation,  | 
                  
| 81 | 932x | 
                      sample = sample,  | 
                  
| 82 | 932x | 
                      limits = limits  | 
                  
| 83 | 
                      )  | 
                  |
| 84 | 
                      }  | 
                  |
| 85 | ||
| 86 | ||
| 87 | 
                      setValidity(  | 
                  |
| 88 | 
                      Class = "Prior",  | 
                  |
| 89 | 
                          method = function(object) {
                     | 
                  |
| 90 | 
                              for (param in names(object@parameters)) {
                     | 
                  |
| 91 | 
                                  if (!param %in% names(object@validation)) {
                     | 
                  |
| 92 | 
                                      return(sprintf("Parameter `%s` does not have a validation method", param))
                     | 
                  |
| 93 | 
                      }  | 
                  |
| 94 | 
                                  if (!object@validation[[param]](object@parameters[[param]])) {
                     | 
                  |
| 95 | 
                      return_message <- sprintf(  | 
                  |
| 96 | 
                      "Invalid value of `%d` for parameter `%s`",  | 
                  |
| 97 | 
                      object@parameters[[param]],  | 
                  |
| 98 | 
                      param  | 
                  |
| 99 | 
                      )  | 
                  |
| 100 | 
                      return(return_message)  | 
                  |
| 101 | 
                      }  | 
                  |
| 102 | 
                      }  | 
                  |
| 103 | 
                      return(TRUE)  | 
                  |
| 104 | 
                      }  | 
                  |
| 105 | 
                      )  | 
                  |
| 106 | ||
| 107 | ||
| 108 | ||
| 109 | 
                      #' @rdname set_limits  | 
                  |
| 110 | 
                      #' @export  | 
                  |
| 111 | 
                      set_limits.Prior <- function(object, lower = -Inf, upper = Inf) {
                     | 
                  |
| 112 | 285x | 
                      object@limits <- c(lower, upper)  | 
                  
| 113 | 285x | 
                      return(object)  | 
                  
| 114 | 
                      }  | 
                  |
| 115 | ||
| 116 | ||
| 117 | 
                      #' `Prior` -> `Character`  | 
                  |
| 118 | 
                      #'  | 
                  |
| 119 | 
                      #' Converts a [`Prior`] object to a character vector  | 
                  |
| 120 | 
                      #' @inheritParams Prior-Shared  | 
                  |
| 121 | 
                      #' @family Prior-internal  | 
                  |
| 122 | 
                      #' @export  | 
                  |
| 123 | 
                      as.character.Prior <- function(x, ...) {
                     | 
                  |
| 124 | ||
| 125 | 67x | 
                      parameters_rounded <- lapply(x@parameters, round, 5)  | 
                  
| 126 | ||
| 127 | 67x | 
                      do.call(  | 
                  
| 128 | 67x | 
                      glue::glue,  | 
                  
| 129 | 67x | 
                      append(x@display, parameters_rounded)  | 
                  
| 130 | 
                      )  | 
                  |
| 131 | 
                      }  | 
                  |
| 132 | ||
| 133 | ||
| 134 | 
                      #' @rdname show-object  | 
                  |
| 135 | 
                      #' @export  | 
                  |
| 136 | 
                      setMethod(  | 
                  |
| 137 | 
                      f = "show",  | 
                  |
| 138 | 
                      signature = "Prior",  | 
                  |
| 139 | 
                          definition = function(object) {
                     | 
                  |
| 140 | 1x | 
                              x <- sprintf("\nPrior Object:\n   %s\n\n", as.character(object))
                     | 
                  
| 141 | 1x | 
                      cat(x)  | 
                  
| 142 | 1x | 
                      return(object)  | 
                  
| 143 | 
                      }  | 
                  |
| 144 | 
                      )  | 
                  |
| 145 | ||
| 146 | ||
| 147 | 
                      #' `Prior` -> `StanModule`  | 
                  |
| 148 | 
                      #'  | 
                  |
| 149 | 
                      #' Converts a [`Prior`] object to a [`StanModule`] object  | 
                  |
| 150 | 
                      #'  | 
                  |
| 151 | 
                      #' @inheritParams Prior-Shared  | 
                  |
| 152 | 
                      #'  | 
                  |
| 153 | 
                      #' @family Prior-internal  | 
                  |
| 154 | 
                      #' @family as.StanModule  | 
                  |
| 155 | 
                      #' @export  | 
                  |
| 156 | 
                      as.StanModule.Prior <- function(object, name, ...) {
                     | 
                  |
| 157 | 652x | 
                      string <- paste(  | 
                  
| 158 | 652x | 
                              "data {{",
                     | 
                  
| 159 | 652x | 
                              paste0("    ", object@repr_data, collapse = "\n"),
                     | 
                  
| 160 | 
                      "}}",  | 
                  |
| 161 | 652x | 
                              "model {{",
                     | 
                  
| 162 | 652x | 
                              paste0("    ", object@repr_model, collapse = "\n"),
                     | 
                  
| 163 | 
                      "}}",  | 
                  |
| 164 | 652x | 
                      sep = "\n"  | 
                  
| 165 | 
                      )  | 
                  |
| 166 | 652x | 
                      StanModule(glue::glue(string, name = name))  | 
                  
| 167 | 
                      }  | 
                  |
| 168 | ||
| 169 | ||
| 170 | 
                      #' `Prior` -> `list`  | 
                  |
| 171 | 
                      #'  | 
                  |
| 172 | 
                      #' Converts a Prior object to a list of parameter data values  | 
                  |
| 173 | 
                      #' for a Stan model.  | 
                  |
| 174 | 
                      #'  | 
                  |
| 175 | 
                      #' @inheritParams Prior-Shared  | 
                  |
| 176 | 
                      #'  | 
                  |
| 177 | 
                      #' @family as_stan_list  | 
                  |
| 178 | 
                      #' @family Prior-internal  | 
                  |
| 179 | 
                      #' @export  | 
                  |
| 180 | 
                      as_stan_list.Prior <- function(object, name, ...) {
                     | 
                  |
| 181 | 384x | 
                      vals <- object@parameters  | 
                  
| 182 | 384x | 
                      vals_names <- names(vals)  | 
                  
| 183 | 384x | 
                          if (length(vals_names) >= 1) {
                     | 
                  
| 184 | 317x | 
                              names(vals) <- paste0("prior_", vals_names, "_", name)
                     | 
                  
| 185 | 
                      }  | 
                  |
| 186 | 384x | 
                      return(vals)  | 
                  
| 187 | 
                      }  | 
                  |
| 188 | ||
| 189 | ||
| 190 | ||
| 191 | 
                      #' Prior Getter Functions  | 
                  |
| 192 | 
                      #' @description  | 
                  |
| 193 | 
                      #' Getter functions for the slots of a [`Prior`] object  | 
                  |
| 194 | 
                      #' @inheritParams Prior-Shared  | 
                  |
| 195 | 
                      #' @family Prior-internal  | 
                  |
| 196 | 
                      #' @name Prior-Getter-Methods  | 
                  |
| 197 | 
                      NULL  | 
                  |
| 198 | ||
| 199 | ||
| 200 | ||
| 201 | 
                      # initialValues-Prior ----  | 
                  |
| 202 | ||
| 203 | 
                      #' @describeIn Prior-Getter-Methods The prior's initial value  | 
                  |
| 204 | 
                      #' @export  | 
                  |
| 205 | 
                      initialValues.Prior <- function(object, ...) {
                     | 
                  |
| 206 | 68560x | 
                          samples <- getOption("jmpost.prior_shrinkage") * object@centre +
                     | 
                  
| 207 | 68560x | 
                              (1 - getOption("jmpost.prior_shrinkage")) * object@sample(100)
                     | 
                  
| 208 | ||
| 209 | 68560x | 
                      valid_samples <- samples[samples >= min(object@limits) & samples <= max(object@limits)]  | 
                  
| 210 | 68560x | 
                      assert_that(  | 
                  
| 211 | 68560x | 
                      length(valid_samples) >= 1,  | 
                  
| 212 | 68560x | 
                      msg = "Unable to generate an initial value that meets the required constraints"  | 
                  
| 213 | 
                      )  | 
                  |
| 214 | 68543x | 
                          if (length(valid_samples) == 1) {
                     | 
                  
| 215 | 26x | 
                      return(valid_samples)  | 
                  
| 216 | 
                      }  | 
                  |
| 217 | 68517x | 
                      return(sample(valid_samples, 1))  | 
                  
| 218 | 
                      }  | 
                  |
| 219 | ||
| 220 | ||
| 221 | 
                      # Prior-constructors ----  | 
                  |
| 222 | ||
| 223 | 
                      #' Normal Prior Distribution  | 
                  |
| 224 | 
                      #'  | 
                  |
| 225 | 
                      #' @param mu (`number`)\cr mean.  | 
                  |
| 226 | 
                      #' @param sigma (`number`)\cr standard deviation.  | 
                  |
| 227 | 
                      #' @family Prior  | 
                  |
| 228 | 
                      #' @export  | 
                  |
| 229 | 
                      prior_normal <- function(mu, sigma) {
                     | 
                  |
| 230 | 359x | 
                      Prior(  | 
                  
| 231 | 359x | 
                      parameters = list(mu = mu, sigma = sigma),  | 
                  
| 232 | 359x | 
                              display = "normal(mu = {mu}, sigma = {sigma})",
                     | 
                  
| 233 | 359x | 
                              repr_model = "{name} ~ normal(prior_mu_{name}, prior_sigma_{name});",
                     | 
                  
| 234 | 359x | 
                      repr_data = c(  | 
                  
| 235 | 359x | 
                                  "real prior_mu_{name};",
                     | 
                  
| 236 | 359x | 
                                  "real<lower=0> prior_sigma_{name};"
                     | 
                  
| 237 | 
                      ),  | 
                  |
| 238 | 359x | 
                      centre = mu,  | 
                  
| 239 | 359x | 
                      sample = \(n) local_rnorm(n, mu, sigma),  | 
                  
| 240 | 359x | 
                      validation = list(  | 
                  
| 241 | 359x | 
                      mu = is.numeric,  | 
                  
| 242 | 359x | 
                      sigma = \(x) x > 0  | 
                  
| 243 | 
                      )  | 
                  |
| 244 | 
                      )  | 
                  |
| 245 | 
                      }  | 
                  |
| 246 | ||
| 247 | ||
| 248 | 
                      #' Standard Normal Prior Distribution  | 
                  |
| 249 | 
                      #'  | 
                  |
| 250 | 
                      #'  | 
                  |
| 251 | 
                      #' @family Prior  | 
                  |
| 252 | 
                      #' @export  | 
                  |
| 253 | 
                      prior_std_normal <- function() {
                     | 
                  |
| 254 | 151x | 
                      Prior(  | 
                  
| 255 | 151x | 
                      parameters = list(),  | 
                  
| 256 | 151x | 
                      display = "std_normal()",  | 
                  
| 257 | 151x | 
                              repr_model = "{name} ~ std_normal();",
                     | 
                  
| 258 | 151x | 
                      repr_data = "",  | 
                  
| 259 | 151x | 
                      centre = 0,  | 
                  
| 260 | 151x | 
                      sample = \(n) local_rnorm(n),  | 
                  
| 261 | 151x | 
                      validation = list()  | 
                  
| 262 | 
                      )  | 
                  |
| 263 | 
                      }  | 
                  |
| 264 | ||
| 265 | 
                      #' Cauchy Prior Distribution  | 
                  |
| 266 | 
                      #'  | 
                  |
| 267 | 
                      #' @param mu (`number`)\cr mean.  | 
                  |
| 268 | 
                      #' @param sigma (`number`)\cr scale.  | 
                  |
| 269 | 
                      #' @family Prior  | 
                  |
| 270 | 
                      #'  | 
                  |
| 271 | 
                      #' @export  | 
                  |
| 272 | 
                      prior_cauchy <- function(mu, sigma) {
                     | 
                  |
| 273 | 5x | 
                      Prior(  | 
                  
| 274 | 5x | 
                      parameters = list(mu = mu, sigma = sigma),  | 
                  
| 275 | 5x | 
                              display = "cauchy(mu = {mu}, sigma = {sigma})",
                     | 
                  
| 276 | 5x | 
                              repr_model = "{name} ~ cauchy(prior_mu_{name}, prior_sigma_{name});",
                     | 
                  
| 277 | 5x | 
                      repr_data = c(  | 
                  
| 278 | 5x | 
                                  "real prior_mu_{name};",
                     | 
                  
| 279 | 5x | 
                                  "real<lower=0> prior_sigma_{name};"
                     | 
                  
| 280 | 
                      ),  | 
                  |
| 281 | 5x | 
                      centre = mu,  | 
                  
| 282 | 5x | 
                      sample = \(n) local_rcauchy(n, mu, sigma),  | 
                  
| 283 | 5x | 
                      validation = list(  | 
                  
| 284 | 5x | 
                      mu = is.numeric,  | 
                  
| 285 | 5x | 
                      sigma = \(x) x > 0  | 
                  
| 286 | 
                      )  | 
                  |
| 287 | 
                      )  | 
                  |
| 288 | 
                      }  | 
                  |
| 289 | ||
| 290 | ||
| 291 | 
                      #' Gamma Prior Distribution  | 
                  |
| 292 | 
                      #'  | 
                  |
| 293 | 
                      #' @param alpha (`number`)\cr shape.  | 
                  |
| 294 | 
                      #' @param beta (`number`)\cr inverse scale.  | 
                  |
| 295 | 
                      #' @family Prior  | 
                  |
| 296 | 
                      #'  | 
                  |
| 297 | 
                      #' @export  | 
                  |
| 298 | 
                      prior_gamma <- function(alpha, beta) {
                     | 
                  |
| 299 | 33x | 
                      Prior(  | 
                  
| 300 | 33x | 
                      parameters = list(alpha = alpha, beta = beta),  | 
                  
| 301 | 33x | 
                              repr_model = "{name} ~ gamma(prior_alpha_{name}, prior_beta_{name});",
                     | 
                  
| 302 | 33x | 
                              display = "gamma(alpha = {alpha}, beta = {beta})",
                     | 
                  
| 303 | 33x | 
                      repr_data = c(  | 
                  
| 304 | 33x | 
                                  "real<lower=0> prior_alpha_{name};",
                     | 
                  
| 305 | 33x | 
                                  "real<lower=0> prior_beta_{name};"
                     | 
                  
| 306 | 
                      ),  | 
                  |
| 307 | 33x | 
                      centre = alpha / beta,  | 
                  
| 308 | 33x | 
                      sample = \(n) local_rgamma(n, shape = alpha, rate = beta),  | 
                  
| 309 | 33x | 
                      validation = list(  | 
                  
| 310 | 33x | 
                      alpha = \(x) x > 0,  | 
                  
| 311 | 33x | 
                      beta = \(x) x > 0  | 
                  
| 312 | 
                      )  | 
                  |
| 313 | 
                      )  | 
                  |
| 314 | 
                      }  | 
                  |
| 315 | ||
| 316 | 
                      #' Log-Normal Prior Distribution  | 
                  |
| 317 | 
                      #'  | 
                  |
| 318 | 
                      #' @param mu (`number`)\cr mean of the logarithm.  | 
                  |
| 319 | 
                      #' @param sigma (`number`)\cr standard deviation of the logarithm.  | 
                  |
| 320 | 
                      #' @family Prior  | 
                  |
| 321 | 
                      #'  | 
                  |
| 322 | 
                      #' @export  | 
                  |
| 323 | 
                      prior_lognormal <- function(mu, sigma) {
                     | 
                  |
| 324 | 303x | 
                      Prior(  | 
                  
| 325 | 303x | 
                      parameters = list(mu = mu, sigma = sigma),  | 
                  
| 326 | 303x | 
                              display = "lognormal(mu = {mu}, sigma = {sigma})",
                     | 
                  
| 327 | 303x | 
                              repr_model = "{name} ~ lognormal(prior_mu_{name}, prior_sigma_{name});",
                     | 
                  
| 328 | 303x | 
                      repr_data = c(  | 
                  
| 329 | 303x | 
                                  "real prior_mu_{name};",
                     | 
                  
| 330 | 303x | 
                                  "real<lower=0> prior_sigma_{name};"
                     | 
                  
| 331 | 
                      ),  | 
                  |
| 332 | 303x | 
                      centre = exp(mu + (sigma^2) / 2),  | 
                  
| 333 | 303x | 
                      sample = \(n) local_rlnorm(n, mu, sigma),  | 
                  
| 334 | 303x | 
                      validation = list(  | 
                  
| 335 | 303x | 
                      mu = is.numeric,  | 
                  
| 336 | 303x | 
                      sigma = \(x) x > 0  | 
                  
| 337 | 
                      )  | 
                  |
| 338 | 
                      )  | 
                  |
| 339 | 
                      }  | 
                  |
| 340 | ||
| 341 | 
                      #' Beta Prior Distribution  | 
                  |
| 342 | 
                      #'  | 
                  |
| 343 | 
                      #' @param a (`number`)\cr first parameter.  | 
                  |
| 344 | 
                      #' @param b (`number`)\cr second parameter  | 
                  |
| 345 | 
                      #' @family Prior  | 
                  |
| 346 | 
                      #'  | 
                  |
| 347 | 
                      #' @export  | 
                  |
| 348 | 
                      prior_beta <- function(a, b) {
                     | 
                  |
| 349 | 5x | 
                      Prior(  | 
                  
| 350 | 5x | 
                      parameters = list(a = a, b = b),  | 
                  
| 351 | 5x | 
                              display = "beta(a = {a}, b = {b})",
                     | 
                  
| 352 | 5x | 
                              repr_model = "{name} ~ beta(prior_a_{name}, prior_b_{name});",
                     | 
                  
| 353 | 5x | 
                      repr_data = c(  | 
                  
| 354 | 5x | 
                                  "real<lower=0> prior_a_{name};",
                     | 
                  
| 355 | 5x | 
                                  "real<lower=0> prior_b_{name};"
                     | 
                  
| 356 | 
                      ),  | 
                  |
| 357 | 5x | 
                      centre = a / (a + b),  | 
                  
| 358 | 5x | 
                      sample = \(n) local_rbeta(n, a, b),  | 
                  
| 359 | 5x | 
                      validation = list(  | 
                  
| 360 | 5x | 
                      a = \(x) x > 0,  | 
                  
| 361 | 5x | 
                      b = \(x) x > 0  | 
                  
| 362 | 
                      )  | 
                  |
| 363 | 
                      )  | 
                  |
| 364 | 
                      }  | 
                  |
| 365 | ||
| 366 | 
                      #' Initial Values Specification  | 
                  |
| 367 | 
                      #'  | 
                  |
| 368 | 
                      #' @param dist (`Prior`)\cr a prior Distribution  | 
                  |
| 369 | 
                      #' @family Prior  | 
                  |
| 370 | 
                      #' @description  | 
                  |
| 371 | 
                      #' This function is used to specify only the initial values for a parameter.  | 
                  |
| 372 | 
                      #' This is primarily used for hierarchical parameters whose distributions  | 
                  |
| 373 | 
                      #' are fixed within the model and cannot be altered by the user.  | 
                  |
| 374 | 
                      #'  | 
                  |
| 375 | 
                      #' @export  | 
                  |
| 376 | 
                      prior_init_only <- function(dist) {
                     | 
                  |
| 377 | 61x | 
                      Prior(  | 
                  
| 378 | 61x | 
                      parameters = list(),  | 
                  
| 379 | 61x | 
                      display = "<None>",  | 
                  
| 380 | 61x | 
                      repr_model = "",  | 
                  
| 381 | 61x | 
                      repr_data = "",  | 
                  
| 382 | 61x | 
                              sample = \(n) {
                     | 
                  
| 383 | 632x | 
                      dist@sample(n)  | 
                  
| 384 | 
                      },  | 
                  |
| 385 | 61x | 
                      centre = dist@centre,  | 
                  
| 386 | 61x | 
                      validation = list()  | 
                  
| 387 | 
                      )  | 
                  |
| 388 | 
                      }  | 
                  |
| 389 | ||
| 390 | ||
| 391 | ||
| 392 | ||
| 393 | 
                      #' Uniform Prior Distribution  | 
                  |
| 394 | 
                      #'  | 
                  |
| 395 | 
                      #' @param alpha (`number`)\cr minimum value parameter.  | 
                  |
| 396 | 
                      #' @param beta (`number`)\cr maximum value parameter.  | 
                  |
| 397 | 
                      #' @family Prior  | 
                  |
| 398 | 
                      #'  | 
                  |
| 399 | 
                      #' @export  | 
                  |
| 400 | 
                      prior_uniform <- function(alpha, beta) {
                     | 
                  |
| 401 | 5x | 
                      assert_that(  | 
                  
| 402 | 5x | 
                      alpha < beta,  | 
                  
| 403 | 5x | 
                      msg = "`alpha`` must be less than `beta`"  | 
                  
| 404 | 
                      )  | 
                  |
| 405 | 4x | 
                      Prior(  | 
                  
| 406 | 4x | 
                      parameters = list(alpha = alpha, beta = beta),  | 
                  
| 407 | 4x | 
                              display = "uniform(alpha = {alpha}, beta = {beta})",
                     | 
                  
| 408 | 4x | 
                              repr_model = "{name} ~ uniform(prior_alpha_{name}, prior_beta_{name});",
                     | 
                  
| 409 | 4x | 
                      repr_data = c(  | 
                  
| 410 | 4x | 
                                  "real prior_alpha_{name};",
                     | 
                  
| 411 | 4x | 
                                  "real prior_beta_{name};"
                     | 
                  
| 412 | 
                      ),  | 
                  |
| 413 | 4x | 
                      centre = 0.5 * (alpha + beta),  | 
                  
| 414 | 4x | 
                      sample = \(n) local_runif(n, alpha, beta),  | 
                  
| 415 | 4x | 
                      validation = list(  | 
                  
| 416 | 4x | 
                      alpha = is.numeric,  | 
                  
| 417 | 4x | 
                      beta = is.numeric  | 
                  
| 418 | 
                      )  | 
                  |
| 419 | 
                      )  | 
                  |
| 420 | 
                      }  | 
                  |
| 421 | ||
| 422 | ||
| 423 | 
                      #' Student-t Prior Distribution  | 
                  |
| 424 | 
                      #'  | 
                  |
| 425 | 
                      #' @param nu (`number`)\cr Degrees of freedom parameter.  | 
                  |
| 426 | 
                      #' @param mu (`number`)\cr Location parameter.  | 
                  |
| 427 | 
                      #' @param sigma (`number`)\cr Scale parameter.  | 
                  |
| 428 | 
                      #' @family Prior  | 
                  |
| 429 | 
                      #'  | 
                  |
| 430 | 
                      #' @export  | 
                  |
| 431 | 
                      prior_student_t <- function(nu, mu, sigma) {
                     | 
                  |
| 432 | 3x | 
                      Prior(  | 
                  
| 433 | 3x | 
                      parameters = list(  | 
                  
| 434 | 3x | 
                      nu = nu,  | 
                  
| 435 | 3x | 
                      mu = mu,  | 
                  
| 436 | 3x | 
                      sigma = sigma  | 
                  
| 437 | 
                      ),  | 
                  |
| 438 | 3x | 
                              display = "student_t(nu = {nu}, mu = {mu}, sigma = {sigma})",
                     | 
                  
| 439 | 3x | 
                              repr_model = "{name} ~ student_t(prior_nu_{name}, prior_mu_{name}, prior_sigma_{name});",
                     | 
                  
| 440 | 3x | 
                      repr_data = c(  | 
                  
| 441 | 3x | 
                                  "real<lower=0> prior_nu_{name};",
                     | 
                  
| 442 | 3x | 
                                  "real prior_mu_{name};",
                     | 
                  
| 443 | 3x | 
                                  "real<lower=0> prior_sigma_{name};"
                     | 
                  
| 444 | 
                      ),  | 
                  |
| 445 | 3x | 
                      centre = mu,  | 
                  
| 446 | 3x | 
                      sample = \(n) local_rt(n, nu, mu, sigma),  | 
                  
| 447 | 3x | 
                      validation = list(  | 
                  
| 448 | 3x | 
                      nu = \(x) x > 0,  | 
                  
| 449 | 3x | 
                      mu = is.numeric,  | 
                  
| 450 | 3x | 
                      sigma = \(x) x > 0  | 
                  
| 451 | 
                      )  | 
                  |
| 452 | 
                      )  | 
                  |
| 453 | 
                      }  | 
                  |
| 454 | ||
| 455 | ||
| 456 | ||
| 457 | 
                      #' Logistic Prior Distribution  | 
                  |
| 458 | 
                      #'  | 
                  |
| 459 | 
                      #' @param mu (`number`)\cr Location parameter.  | 
                  |
| 460 | 
                      #' @param sigma (`number`)\cr Scale parameter.  | 
                  |
| 461 | 
                      #' @family Prior  | 
                  |
| 462 | 
                      #'  | 
                  |
| 463 | 
                      #' @export  | 
                  |
| 464 | 
                      prior_logistic <- function(mu, sigma) {
                     | 
                  |
| 465 | 2x | 
                      Prior(  | 
                  
| 466 | 2x | 
                      parameters = list(  | 
                  
| 467 | 2x | 
                      mu = mu,  | 
                  
| 468 | 2x | 
                      sigma = sigma  | 
                  
| 469 | 
                      ),  | 
                  |
| 470 | 2x | 
                              display = "logistic(mu = {mu}, sigma = {sigma})",
                     | 
                  
| 471 | 2x | 
                              repr_model = "{name} ~ logistic(prior_mu_{name}, prior_sigma_{name});",
                     | 
                  
| 472 | 2x | 
                      repr_data = c(  | 
                  
| 473 | 2x | 
                                  "real prior_mu_{name};",
                     | 
                  
| 474 | 2x | 
                                  "real<lower=0> prior_sigma_{name};"
                     | 
                  
| 475 | 
                      ),  | 
                  |
| 476 | 2x | 
                      centre = mu,  | 
                  
| 477 | 2x | 
                      sample = \(n) local_rlogis(n, mu, sigma),  | 
                  
| 478 | 2x | 
                      validation = list(  | 
                  
| 479 | 2x | 
                      mu = is.numeric,  | 
                  
| 480 | 2x | 
                      sigma = \(x) x > 0  | 
                  
| 481 | 
                      )  | 
                  |
| 482 | 
                      )  | 
                  |
| 483 | 
                      }  | 
                  |
| 484 | ||
| 485 | ||
| 486 | 
                      #' Log-Logistic Prior Distribution  | 
                  |
| 487 | 
                      #'  | 
                  |
| 488 | 
                      #' @param alpha (`number`)\cr Scale parameter.  | 
                  |
| 489 | 
                      #' @param beta (`number`)\cr Shape parameter.  | 
                  |
| 490 | 
                      #' @family Prior  | 
                  |
| 491 | 
                      #'  | 
                  |
| 492 | 
                      #' @export  | 
                  |
| 493 | 
                      prior_loglogistic <- function(alpha, beta) {
                     | 
                  |
| 494 | 3x | 
                      Prior(  | 
                  
| 495 | 3x | 
                      parameters = list(  | 
                  
| 496 | 3x | 
                      alpha = alpha,  | 
                  
| 497 | 3x | 
                      beta = beta  | 
                  
| 498 | 
                      ),  | 
                  |
| 499 | 3x | 
                              display = "loglogistic(alpha = {alpha}, beta = {beta})",
                     | 
                  
| 500 | 3x | 
                              repr_model = "{name} ~ loglogistic(prior_alpha_{name}, prior_beta_{name});",
                     | 
                  
| 501 | 3x | 
                      repr_data = c(  | 
                  
| 502 | 3x | 
                                  "real<lower=0> prior_alpha_{name};",
                     | 
                  
| 503 | 3x | 
                                  "real<lower=0> prior_beta_{name};"
                     | 
                  
| 504 | 
                      ),  | 
                  |
| 505 | 3x | 
                      centre = alpha * pi / (beta * sin(pi / beta)),  | 
                  
| 506 | 3x | 
                              sample = \(n) {
                     | 
                  
| 507 | ! | 
                      local_rloglogis(n, alpha, beta)  | 
                  
| 508 | 
                      },  | 
                  |
| 509 | 3x | 
                      validation = list(  | 
                  
| 510 | 3x | 
                      alpha = \(x) x > 0,  | 
                  
| 511 | 3x | 
                      beta = \(x) x > 0  | 
                  
| 512 | 
                      )  | 
                  |
| 513 | 
                      )  | 
                  |
| 514 | 
                      }  | 
                  |
| 515 | ||
| 516 | ||
| 517 | 
                      #' Inverse-Gamma Prior Distribution  | 
                  |
| 518 | 
                      #'  | 
                  |
| 519 | 
                      #' @param alpha (`number`)\cr Shape parameter.  | 
                  |
| 520 | 
                      #' @param beta (`number`)\cr Scale parameter.  | 
                  |
| 521 | 
                      #' @family Prior  | 
                  |
| 522 | 
                      #'  | 
                  |
| 523 | 
                      #' @export  | 
                  |
| 524 | 
                      prior_invgamma <- function(alpha, beta) {
                     | 
                  |
| 525 | 3x | 
                      Prior(  | 
                  
| 526 | 3x | 
                      parameters = list(  | 
                  
| 527 | 3x | 
                      alpha = alpha,  | 
                  
| 528 | 3x | 
                      beta = beta  | 
                  
| 529 | 
                      ),  | 
                  |
| 530 | 3x | 
                              display = "inv_gamma(alpha = {alpha}, beta = {beta})",
                     | 
                  
| 531 | 3x | 
                              repr_model = "{name} ~ inv_gamma(prior_alpha_{name}, prior_beta_{name});",
                     | 
                  
| 532 | 3x | 
                      repr_data = c(  | 
                  
| 533 | 3x | 
                                  "real<lower=0> prior_alpha_{name};",
                     | 
                  
| 534 | 3x | 
                                  "real<lower=0> prior_beta_{name};"
                     | 
                  
| 535 | 
                      ),  | 
                  |
| 536 | 3x | 
                      centre = beta / (alpha - 1),  | 
                  
| 537 | 3x | 
                      sample = \(n) local_rinvgamma(n, alpha, beta),  | 
                  
| 538 | 3x | 
                      validation = list(  | 
                  
| 539 | 3x | 
                      alpha = \(x) x > 0,  | 
                  
| 540 | 3x | 
                      beta = \(x) x > 0  | 
                  
| 541 | 
                      )  | 
                  |
| 542 | 
                      )  | 
                  |
| 543 | 
                      }  | 
                  |
| 544 | ||
| 545 | ||
| 546 | 
                      # nolint start  | 
                  |
| 547 | 
                      #  | 
                  |
| 548 | 
                      # Developer Notes  | 
                  |
| 549 | 
                      #  | 
                  |
| 550 | 
                      # The `median.Prior` function is a rough workaround to help generate initial values for  | 
                  |
| 551 | 
                      # hierarchical distributions. The original implementation involved sampling initial values  | 
                  |
| 552 | 
                      # for the random effects using the medians of the parent distribution e.g.  | 
                  |
| 553 | 
                      # ```  | 
                  |
| 554 | 
                      # random_effect ~ beta(a_prior@centre, b_prior@centre)  | 
                  |
| 555 | 
                      # ```  | 
                  |
| 556 | 
                      # A problem came up though when we implemented support for constrained distributions  | 
                  |
| 557 | 
                      # as there was no longer any guarantee that the median/centre of the distribution is  | 
                  |
| 558 | 
                      # a valid value e.g. `a_prior ~ prior_normal(-200, 400)`.  | 
                  |
| 559 | 
                      #  | 
                  |
| 560 | 
                      # To resolve this issue the `median.Prior` method was created which simply samples  | 
                  |
| 561 | 
                      # multiple observations from the constrained distribution and then takes the median  | 
                  |
| 562 | 
                      # of those constrained observations; this then ensures that the value being used  | 
                  |
| 563 | 
                      # for the parameters is a valid value  | 
                  |
| 564 | 
                      #  | 
                  |
| 565 | 
                      # nolint end  | 
                  |
| 566 | 
                      #' @importFrom stats median  | 
                  |
| 567 | 
                      #' @export  | 
                  |
| 568 | 
                      median.Prior <- function(x, na.rm, ...) {
                     | 
                  |
| 569 | 118x | 
                      vals <- replicate(  | 
                  
| 570 | 118x | 
                      n = 500,  | 
                  
| 571 | 118x | 
                      initialValues(x),  | 
                  
| 572 | 118x | 
                      simplify = FALSE  | 
                  
| 573 | 
                      ) |>  | 
                  |
| 574 | 118x | 
                      unlist()  | 
                  
| 575 | 117x | 
                      median(vals)  | 
                  
| 576 | 
                      }  | 
                  |
| 577 | ||
| 578 | ||
| 579 | ||
| 580 | ||
| 581 | 
                      #' Stub functions for sampling from distributions  | 
                  |
| 582 | 
                      #'  | 
                  |
| 583 | 
                      #' @description  | 
                  |
| 584 | 
                      #' These functions only exist so that they can be mocked during unit  | 
                  |
| 585 | 
                      #' tests in order to provide deterministic values. In most cases  | 
                  |
| 586 | 
                      #' these are just straight forward pass throughs for the underlying  | 
                  |
| 587 | 
                      #' distributions.  | 
                  |
| 588 | 
                      #'  | 
                  |
| 589 | 
                      #' @param alpha (`number`)\cr Parameter for underlying distribution.  | 
                  |
| 590 | 
                      #' @param beta (`number`)\cr Parameter for underlying distribution.  | 
                  |
| 591 | 
                      #' @param mu (`number`)\cr Parameter for underlying distribution.  | 
                  |
| 592 | 
                      #' @param sigma (`number`)\cr Parameter for underlying distribution.  | 
                  |
| 593 | 
                      #' @param nu (`number`)\cr Parameter for underlying distribution.  | 
                  |
| 594 | 
                      #' @param ... Pass any additional arguments to the underlying distribution.  | 
                  |
| 595 | 
                      #'  | 
                  |
| 596 | 
                      #' @importFrom stats rbeta rcauchy rgamma rlnorm rlogis rnorm rt runif  | 
                  |
| 597 | 
                      #'  | 
                  |
| 598 | 
                      #' @details  | 
                  |
| 599 | 
                      #'  | 
                  |
| 600 | 
                      #' ## Log-Logistic  | 
                  |
| 601 | 
                      #'  | 
                  |
| 602 | 
                      #' There is no log-logistic sampling function within base R so it was implemented  | 
                  |
| 603 | 
                      #' in terms of sampling from the CDF distribution. Using the Stan parameterisation  | 
                  |
| 604 | 
                      #' the CDF is defined as:  | 
                  |
| 605 | 
                      #' \deqn{
                     | 
                  |
| 606 | 
                      #' u = F(x) = \frac{1}{1 + (x/ \alpha)^{-\beta}}
                     | 
                  |
| 607 | 
                      #' }  | 
                  |
| 608 | 
                      #' The inverse of this function is:  | 
                  |
| 609 | 
                      #' \deqn{
                     | 
                  |
| 610 | 
                      #' x = ((u / (1 - u))^(1 / beta)) * alpha  | 
                  |
| 611 | 
                      #' }  | 
                  |
| 612 | 
                      #'  | 
                  |
| 613 | 
                      #' Thus we can sample u from a \eqn{Uni(0, 1)} distribution and then derive x from this.
                     | 
                  |
| 614 | 
                      #'  | 
                  |
| 615 | 
                      #' ## Inverse-Gamma  | 
                  |
| 616 | 
                      #'  | 
                  |
| 617 | 
                      #' The inverse Gamma distribution is defined as 1/Gamma thus we calculate this simply  | 
                  |
| 618 | 
                      #' by sampling sampling from the Gamma distribution and then taking the reciprocal.  | 
                  |
| 619 | 
                      #'  | 
                  |
| 620 | 
                      #' ## Student-t  | 
                  |
| 621 | 
                      #'  | 
                  |
| 622 | 
                      #' R's sampling functions only produce the standard Student-t distribution so in order  | 
                  |
| 623 | 
                      #' to match Stan's implementation we multiply by the scale parameter and add the location  | 
                  |
| 624 | 
                      #' parameter. See this \href{https://stats.stackexchange.com/a/623611}{Stack Overflow} post
                     | 
                  |
| 625 | 
                      #' for details  | 
                  |
| 626 | 
                      #'  | 
                  |
| 627 | 
                      #' @name Local_Sample  | 
                  |
| 628 | 
                      #' @keywords internal  | 
                  |
| 629 | 
                      NULL  | 
                  |
| 630 | ||
| 631 | 
                      #' @rdname Local_Sample  | 
                  |
| 632 | 37300x | 
                      local_rnorm <- \(...) rnorm(...)  | 
                  
| 633 | ||
| 634 | 
                      #' @rdname Local_Sample  | 
                  |
| 635 | 700x | 
                      local_rcauchy <- \(...) rcauchy(...)  | 
                  
| 636 | ||
| 637 | 
                      #' @rdname Local_Sample  | 
                  |
| 638 | 605x | 
                      local_rgamma <- \(...) rgamma(...)  | 
                  
| 639 | ||
| 640 | 
                      #' @rdname Local_Sample  | 
                  |
| 641 | 29327x | 
                      local_rlnorm <- \(...) rlnorm(...)  | 
                  
| 642 | ||
| 643 | 
                      #' @rdname Local_Sample  | 
                  |
| 644 | 2x | 
                      local_rbeta <- \(...) rbeta(...)  | 
                  
| 645 | ||
| 646 | 
                      #' @rdname Local_Sample  | 
                  |
| 647 | 600x | 
                      local_runif <- \(...) runif(...)  | 
                  
| 648 | ||
| 649 | 
                      #' @rdname Local_Sample  | 
                  |
| 650 | 
                      local_rt <- \(n, nu, mu, sigma) {
                     | 
                  |
| 651 | ! | 
                      rt(n, nu) * sigma + mu  | 
                  
| 652 | 
                      }  | 
                  |
| 653 | ||
| 654 | 
                      #' @rdname Local_Sample  | 
                  |
| 655 | ! | 
                      local_rlogis <- \(...) rlogis(...)  | 
                  
| 656 | ||
| 657 | 
                      #' @rdname Local_Sample  | 
                  |
| 658 | 
                      local_rloglogis <- \(n, alpha, beta) {
                     | 
                  |
| 659 | ! | 
                      r <- runif(n)  | 
                  
| 660 | ! | 
                      ((r / (1 - r))^(1 / beta)) * alpha  | 
                  
| 661 | 
                      }  | 
                  |
| 662 | ||
| 663 | 
                      #' @rdname Local_Sample  | 
                  |
| 664 | 
                      local_rinvgamma <- \(n, alpha, beta) {
                     | 
                  |
| 665 | ! | 
                      1 / rgamma(n, alpha, rate = beta)  | 
                  
| 666 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # STAN_BLOCKS ----  | 
                  |
| 5 | ||
| 6 | 
                      #' List of Stan Blocks  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @description  | 
                  |
| 9 | 
                      #' A list with 1 element per standard Stan program blocks.  | 
                  |
| 10 | 
                      #' This object is mostly used internally as a reference for  | 
                  |
| 11 | 
                      #' what blocks are expected to exist within a given Stan program.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @export  | 
                  |
| 14 | 
                      STAN_BLOCKS <- list(  | 
                  |
| 15 | 
                      functions = "functions",  | 
                  |
| 16 | 
                      data = "data",  | 
                  |
| 17 | 
                      transformed_data = "transformed data",  | 
                  |
| 18 | 
                      parameters = "parameters",  | 
                  |
| 19 | 
                      transformed_parameters = "transformed parameters",  | 
                  |
| 20 | 
                      model = "model",  | 
                  |
| 21 | 
                      generated_quantities = "generated quantities"  | 
                  |
| 22 | 
                      )  | 
                  |
| 23 | ||
| 24 | 
                      # add_missing_stan_blocks ----  | 
                  |
| 25 | ||
| 26 | 
                      #' Add Missing Stan Blocks  | 
                  |
| 27 | 
                      #'  | 
                  |
| 28 | 
                      #' @param x (`list`)\cr list of Stan code blocks  | 
                  |
| 29 | 
                      #' @param stan_blocks (`list`)\cr reference list of stan blocks.  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @return Amended list `x` such that all blocks in the global variable  | 
                  |
| 32 | 
                      #' `STAN_BLOCKS` are contained.  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' @keywords internal  | 
                  |
| 35 | 
                      add_missing_stan_blocks <- function(x, stan_blocks = STAN_BLOCKS) {
                     | 
                  |
| 36 | 384x | 
                          for (block in names(stan_blocks)) {
                     | 
                  
| 37 | 2683x | 
                              if (is.null(x[[block]])) {
                     | 
                  
| 38 | 146x | 
                      x[[block]] <- ""  | 
                  
| 39 | 
                      }  | 
                  |
| 40 | 
                      }  | 
                  |
| 41 | 384x | 
                      return(x)  | 
                  
| 42 | 
                      }  | 
                  |
| 43 | ||
| 44 | 
                      # StanModule-class ----  | 
                  |
| 45 | ||
| 46 | 
                      #' `StanModule` Object and Constructor Function  | 
                  |
| 47 | 
                      #'  | 
                  |
| 48 | 
                      #' @param x (`string`)\cr file path to a Stan program or a character vector  | 
                  |
| 49 | 
                      #' of Stan code to be parsed.  | 
                  |
| 50 | 
                      #' @param ... additional arguments passed to the constructor.  | 
                  |
| 51 | 
                      #'  | 
                  |
| 52 | 
                      #' @slot functions (`character`)\cr the `functions` block.  | 
                  |
| 53 | 
                      #' @slot data (`character`)\cr the `data` block.  | 
                  |
| 54 | 
                      #' @slot transformed_data (`character`)\cr the `transformed_data` block.  | 
                  |
| 55 | 
                      #' @slot parameters (`character`)\cr the `parameters` block.  | 
                  |
| 56 | 
                      #' @slot transformed_parameters (`character`)\cr the `transformed_parameters` block.  | 
                  |
| 57 | 
                      #' @slot model (`character`)\cr the `model` block.  | 
                  |
| 58 | 
                      #' @slot generated_quantities (`character`)\cr the `generated_quantities` block.  | 
                  |
| 59 | 
                      #'  | 
                  |
| 60 | 
                      #' @exportClass StanModule  | 
                  |
| 61 | 
                      #' @export StanModule  | 
                  |
| 62 | 
                      #' @family StanModule  | 
                  |
| 63 | 
                      .StanModule <- setClass(  | 
                  |
| 64 | 
                      Class = "StanModule",  | 
                  |
| 65 | 
                      slots = list(  | 
                  |
| 66 | 
                      functions = "character",  | 
                  |
| 67 | 
                      data = "character",  | 
                  |
| 68 | 
                      transformed_data = "character",  | 
                  |
| 69 | 
                      parameters = "character",  | 
                  |
| 70 | 
                      transformed_parameters = "character",  | 
                  |
| 71 | 
                      model = "character",  | 
                  |
| 72 | 
                      generated_quantities = "character"  | 
                  |
| 73 | 
                      )  | 
                  |
| 74 | 
                      )  | 
                  |
| 75 | ||
| 76 | 
                      # StanModule-constructors ----  | 
                  |
| 77 | ||
| 78 | 
                      #' @rdname StanModule-class  | 
                  |
| 79 | 
                      StanModule <- function(  | 
                  |
| 80 | 
                      x = "",  | 
                  |
| 81 | 
                      ...  | 
                  |
| 82 | 
                      ) {
                     | 
                  |
| 83 | 2223x | 
                      assert_that(  | 
                  
| 84 | 2223x | 
                      is.character(x),  | 
                  
| 85 | 2223x | 
                      length(x) == 1,  | 
                  
| 86 | 2223x | 
                      msg = "`x` must be a length 1 character vector"  | 
                  
| 87 | 
                      )  | 
                  |
| 88 | 2223x | 
                      code <- read_stan(x)  | 
                  
| 89 | 2223x | 
                      code_fragments <- as_stan_fragments(code)  | 
                  
| 90 | ||
| 91 | 2220x | 
                          if (paste0(unlist(code_fragments), collapse = "") == "" && paste0(x, collaspe = "") != "") {
                     | 
                  
| 92 | 1x | 
                              warning("Non-empty input resulted in an empty StanModule object. Is the input correct?")
                     | 
                  
| 93 | 
                      }  | 
                  |
| 94 | ||
| 95 | 2220x | 
                      .StanModule(  | 
                  
| 96 | 2220x | 
                      functions = code_fragments$functions,  | 
                  
| 97 | 2220x | 
                      data = code_fragments$data,  | 
                  
| 98 | 2220x | 
                      transformed_data = code_fragments$transformed_data,  | 
                  
| 99 | 2220x | 
                      parameters = code_fragments$parameters,  | 
                  
| 100 | 2220x | 
                      transformed_parameters = code_fragments$transformed_parameters,  | 
                  
| 101 | 2220x | 
                      model = code_fragments$model,  | 
                  
| 102 | 2220x | 
                      generated_quantities = code_fragments$generated_quantities,  | 
                  
| 103 | 
                      ...  | 
                  |
| 104 | 
                      )  | 
                  |
| 105 | 
                      }  | 
                  |
| 106 | ||
| 107 | 
                      # as.character-StanModule ----  | 
                  |
| 108 | ||
| 109 | 
                      #' `StanModule` -> `character`  | 
                  |
| 110 | 
                      #' @param x ([`StanModule`])\cr A stan program  | 
                  |
| 111 | 
                      #' @param ... Not Used.  | 
                  |
| 112 | 
                      #' @description  | 
                  |
| 113 | 
                      #' Converts a [`StanModule`] object into a valid Stan program file where each  | 
                  |
| 114 | 
                      #' line of the returned `character` vector represents a line of the program  | 
                  |
| 115 | 
                      #' @family StanModule  | 
                  |
| 116 | 
                      #' @export  | 
                  |
| 117 | 
                      as.character.StanModule <- function(x, ...) {
                     | 
                  |
| 118 | 443x | 
                      as_stan_file(  | 
                  
| 119 | 443x | 
                      functions = x@functions,  | 
                  
| 120 | 443x | 
                      data = x@data,  | 
                  
| 121 | 443x | 
                      transformed_data = x@transformed_data,  | 
                  
| 122 | 443x | 
                      parameters = x@parameters,  | 
                  
| 123 | 443x | 
                      transformed_parameters = x@transformed_parameters,  | 
                  
| 124 | 443x | 
                      model = x@model,  | 
                  
| 125 | 443x | 
                      generated_quantities = x@generated_quantities  | 
                  
| 126 | 
                      )  | 
                  |
| 127 | 
                      }  | 
                  |
| 128 | ||
| 129 | ||
| 130 | ||
| 131 | 
                      # merge-StanModule,StanModule ----  | 
                  |
| 132 | ||
| 133 | 
                      #' @param stan_blocks (`list`)\cr reference list of stan blocks.  | 
                  |
| 134 | 
                      #' @rdname merge  | 
                  |
| 135 | 
                      setMethod(  | 
                  |
| 136 | 
                      f = "merge",  | 
                  |
| 137 | 
                          signature = c("StanModule", "StanModule"),
                     | 
                  |
| 138 | 
                          definition = function(x, y, stan_blocks = STAN_BLOCKS, ...) {
                     | 
                  |
| 139 | 867x | 
                      stan_fragments <- lapply(  | 
                  
| 140 | 867x | 
                      names(stan_blocks),  | 
                  
| 141 | 867x | 
                                  \(par) {
                     | 
                  
| 142 | 6069x | 
                                      if (all(slot(y, par) == "")) {
                     | 
                  
| 143 | 4081x | 
                      return(slot(x, par))  | 
                  
| 144 | 
                      }  | 
                  |
| 145 | 1988x | 
                                      if (all(slot(x, par) == "")) {
                     | 
                  
| 146 | 561x | 
                      return(slot(y, par))  | 
                  
| 147 | 
                      }  | 
                  |
| 148 | 1427x | 
                      return(c(slot(x, par), slot(y, par)))  | 
                  
| 149 | 
                      }  | 
                  |
| 150 | 
                      )  | 
                  |
| 151 | 867x | 
                      names(stan_fragments) <- names(stan_blocks)  | 
                  
| 152 | 867x | 
                      stan_code <- do.call(as_stan_file, stan_fragments)  | 
                  
| 153 | 867x | 
                      StanModule(  | 
                  
| 154 | 867x | 
                      x = stan_code  | 
                  
| 155 | 
                      )  | 
                  |
| 156 | 
                      }  | 
                  |
| 157 | 
                      )  | 
                  |
| 158 | ||
| 159 | 
                      # compileStanModel-StanModule,character ----  | 
                  |
| 160 | ||
| 161 | 
                      #' @rdname compileStanModel  | 
                  |
| 162 | 
                      compileStanModel.StanModule <- function(object) {
                     | 
                  |
| 163 | 48x | 
                          exe_dir <- getOption("jmpost.cache_dir")
                     | 
                  
| 164 | 48x | 
                          if (!dir.exists(exe_dir)) {
                     | 
                  
| 165 | 3x | 
                      dir.create(exe_dir, recursive = TRUE)  | 
                  
| 166 | 
                      }  | 
                  |
| 167 | 48x | 
                      stan_code <- as.character(object)  | 
                  
| 168 | 48x | 
                      hash_name <- digest::digest(stan_code, "md5")  | 
                  
| 169 | 48x | 
                      exe_name <- paste0(  | 
                  
| 170 | 48x | 
                      "model_",  | 
                  
| 171 | 48x | 
                      hash_name,  | 
                  
| 172 | 48x | 
                      if (is_windows()) ".exe" else ""  | 
                  
| 173 | 
                      )  | 
                  |
| 174 | 48x | 
                      exe_file <- file.path(exe_dir, exe_name)  | 
                  
| 175 | 48x | 
                      source_file <- cmdstanr::write_stan_file(  | 
                  
| 176 | 48x | 
                      code = stan_code,  | 
                  
| 177 | 48x | 
                      dir = exe_dir,  | 
                  
| 178 | 48x | 
                              basename = sprintf("model_%s.stan", hash_name)
                     | 
                  
| 179 | 
                      )  | 
                  |
| 180 | ||
| 181 | 
                      # Suppress "model executable is up to date" message as  | 
                  |
| 182 | 
                      # users are not in control of the cache so this message is meaningless  | 
                  |
| 183 | 48x | 
                      withCallingHandlers(  | 
                  
| 184 | 
                              {
                     | 
                  |
| 185 | 48x | 
                      x <- cmdstanr::cmdstan_model(  | 
                  
| 186 | 48x | 
                      stan_file = source_file,  | 
                  
| 187 | 48x | 
                      exe_file = exe_file,  | 
                  
| 188 | 48x | 
                      quiet = TRUE  | 
                  
| 189 | 
                      )  | 
                  |
| 190 | 
                      },  | 
                  |
| 191 | 48x | 
                              message = function(m) {
                     | 
                  
| 192 | ! | 
                                  if (m$message == "Model executable is up to date!\n") {
                     | 
                  
| 193 | ! | 
                                      invokeRestart("muffleMessage")
                     | 
                  
| 194 | 
                      }  | 
                  |
| 195 | 
                      }  | 
                  |
| 196 | 
                      )  | 
                  |
| 197 | 48x | 
                      invisible(x)  | 
                  
| 198 | 
                      }  | 
                  |
| 199 | ||
| 200 | ||
| 201 | ||
| 202 | 
                      # as.list-StanModule ----  | 
                  |
| 203 | ||
| 204 | 
                      #' `StanModule` -> `list`  | 
                  |
| 205 | 
                      #' @description  | 
                  |
| 206 | 
                      #' Returns a named list where each element of the list corresponds  | 
                  |
| 207 | 
                      #' to a Stan modelling block e.g. `data`, `model`, etc.  | 
                  |
| 208 | 
                      #' @param x ([`StanModule`])\cr A Stan Module  | 
                  |
| 209 | 
                      #' @param stan_blocks (`list`)\cr reference list of stan blocks.  | 
                  |
| 210 | 
                      #' @param ... Not Used.  | 
                  |
| 211 | 
                      #' @family StanModule  | 
                  |
| 212 | 
                      #' @export  | 
                  |
| 213 | 
                      as.list.StanModule <- function(x, stan_blocks = STAN_BLOCKS, ...) {
                     | 
                  |
| 214 | 362x | 
                      string <- as.character(x)  | 
                  
| 215 | 362x | 
                      li <- as_stan_fragments(string)  | 
                  
| 216 | 362x | 
                          for (block in names(stan_blocks)) {
                     | 
                  
| 217 | 2534x | 
                      li[[block]] <- paste(li[[block]], collapse = "\n")  | 
                  
| 218 | 
                      }  | 
                  |
| 219 | 362x | 
                      return(li)  | 
                  
| 220 | 
                      }  | 
                  |
| 221 | ||
| 222 | 
                      # is_file ----  | 
                  |
| 223 | ||
| 224 | 
                      #' Is String a Valid File?  | 
                  |
| 225 | 
                      #'  | 
                  |
| 226 | 
                      #' A utility function to check if a string is a valid file or not.  | 
                  |
| 227 | 
                      #' Used to help address short comings of [file.exists()] that will return `TRUE`  | 
                  |
| 228 | 
                      #' for a directory as well as a file.  | 
                  |
| 229 | 
                      #'  | 
                  |
| 230 | 
                      #' @param filename (`string`)\cr file name.  | 
                  |
| 231 | 
                      #'  | 
                  |
| 232 | 
                      #' @keywords internal  | 
                  |
| 233 | 
                      is_file <- function(filename = NULL) {
                     | 
                  |
| 234 | 7455x | 
                          if (is.null(filename)) {
                     | 
                  
| 235 | ! | 
                      return(FALSE)  | 
                  
| 236 | 
                      }  | 
                  |
| 237 | 7455x | 
                      assert_that(  | 
                  
| 238 | 7455x | 
                      is.character(filename),  | 
                  
| 239 | 7455x | 
                      length(filename) == 1,  | 
                  
| 240 | 7455x | 
                      msg = "`filename` must be a length 1 character"  | 
                  
| 241 | 
                      )  | 
                  |
| 242 | 7455x | 
                          if (nchar(filename) > 1000) {
                     | 
                  
| 243 | 1446x | 
                      return(FALSE)  | 
                  
| 244 | 
                      }  | 
                  |
| 245 | 6009x | 
                          if (is.na(filename)) {
                     | 
                  
| 246 | ! | 
                      return(FALSE)  | 
                  
| 247 | 
                      }  | 
                  |
| 248 | 6009x | 
                      return(file.exists(filename) & !dir.exists(filename))  | 
                  
| 249 | 
                      }  | 
                  |
| 250 | ||
| 251 | 
                      # read_stan ----  | 
                  |
| 252 | ||
| 253 | 
                      #' Stan Code as Character  | 
                  |
| 254 | 
                      #'  | 
                  |
| 255 | 
                      #' @param string Character, either the absolute path of a stan file, or the name of the stan  | 
                  |
| 256 | 
                      #' file in the package directory or the stan code as a string.  | 
                  |
| 257 | 
                      read_stan <- function(string) {
                     | 
                  |
| 258 | 2493x | 
                          local_inst_file <- file.path("inst", "stan", string)
                     | 
                  
| 259 | 2493x | 
                          system_file <- system.file(file.path("stan", string), package = "jmpost")
                     | 
                  
| 260 | 2493x | 
                      local_file <- string  | 
                  
| 261 | 2493x | 
                      files <- c(local_file, local_inst_file, system_file)  | 
                  
| 262 | 2493x | 
                          for (fi in files) {
                     | 
                  
| 263 | 7455x | 
                              if (is_file(fi)) {
                     | 
                  
| 264 | 620x | 
                      string <- readLines(fi)  | 
                  
| 265 | 620x | 
                      break  | 
                  
| 266 | 
                      }  | 
                  |
| 267 | 
                      }  | 
                  |
| 268 | 2493x | 
                      string <- paste0(string, collapse = "\n")  | 
                  
| 269 | 2493x | 
                      return(string)  | 
                  
| 270 | 
                      }  | 
                  |
| 271 | ||
| 272 | 
                      # as_stan_file ----  | 
                  |
| 273 | ||
| 274 | 
                      #' Merging Code Blocks into Stan Code Character Vector  | 
                  |
| 275 | 
                      #'  | 
                  |
| 276 | 
                      #' @param functions (`character`)\cr code block.  | 
                  |
| 277 | 
                      #' @param data (`character`)\cr code block.  | 
                  |
| 278 | 
                      #' @param transformed_data (`character`)\cr code block.  | 
                  |
| 279 | 
                      #' @param parameters (`character`)\cr code block.  | 
                  |
| 280 | 
                      #' @param transformed_parameters (`character`)\cr code block.  | 
                  |
| 281 | 
                      #' @param model (`character`)\cr code block.  | 
                  |
| 282 | 
                      #' @param generated_quantities (`character`)\cr code block.  | 
                  |
| 283 | 
                      #' @param stan_blocks (`list`)\cr reference list of stan blocks.  | 
                  |
| 284 | 
                      #'  | 
                  |
| 285 | 
                      #' @return Character vector of the complete Stan code.  | 
                  |
| 286 | 
                      #'  | 
                  |
| 287 | 
                      #' @keywords internal  | 
                  |
| 288 | 
                      as_stan_file <- function(  | 
                  |
| 289 | 
                      functions = "",  | 
                  |
| 290 | 
                      data = "",  | 
                  |
| 291 | 
                      transformed_data = "",  | 
                  |
| 292 | 
                      parameters = "",  | 
                  |
| 293 | 
                      transformed_parameters = "",  | 
                  |
| 294 | 
                      model = "",  | 
                  |
| 295 | 
                      generated_quantities = "",  | 
                  |
| 296 | 
                      stan_blocks = STAN_BLOCKS  | 
                  |
| 297 | 
                      ) {
                     | 
                  |
| 298 | 1310x | 
                      block_strings <- lapply(  | 
                  
| 299 | 1310x | 
                      names(stan_blocks),  | 
                  
| 300 | 1310x | 
                              function(id) {
                     | 
                  
| 301 | 9170x | 
                      char <- get(id)  | 
                  
| 302 | 9170x | 
                                  if (any(nchar(char) >= 1)) {
                     | 
                  
| 303 | 4649x | 
                                      return(sprintf("%s {\n%s\n}\n\n", stan_blocks[[id]], paste(char, collapse = "\n")))
                     | 
                  
| 304 | 
                                  } else {
                     | 
                  |
| 305 | 4521x | 
                                      return("")
                     | 
                  
| 306 | 
                      }  | 
                  |
| 307 | 
                      }  | 
                  |
| 308 | 
                      )  | 
                  |
| 309 | 1310x | 
                      return(paste0(block_strings, collapse = ""))  | 
                  
| 310 | 
                      }  | 
                  |
| 311 | ||
| 312 | 
                      # as_stan_fragments ----  | 
                  |
| 313 | ||
| 314 | 
                      #' Conversion of Character Vector into Stan Code Block List  | 
                  |
| 315 | 
                      #'  | 
                  |
| 316 | 
                      #' @param x (`character`)\cr the single Stan code vector.  | 
                  |
| 317 | 
                      #' @param stan_blocks (`list`)\cr reference list of stan blocks.  | 
                  |
| 318 | 
                      #'  | 
                  |
| 319 | 
                      #' @return A list with the Stan code blocks.  | 
                  |
| 320 | 
                      #'  | 
                  |
| 321 | 
                      #' @details  | 
                  |
| 322 | 
                      #' Function only works if code is in format  | 
                  |
| 323 | 
                      #' ```  | 
                  |
| 324 | 
                      #' data {
                     | 
                  |
| 325 | 
                      #' <code>  | 
                  |
| 326 | 
                      #' }  | 
                  |
| 327 | 
                      #' model {
                     | 
                  |
| 328 | 
                      #' <code>  | 
                  |
| 329 | 
                      #' }  | 
                  |
| 330 | 
                      #' ```  | 
                  |
| 331 | 
                      #' That is to say we do not support code in inline format i.e.  | 
                  |
| 332 | 
                      #' ```  | 
                  |
| 333 | 
                      #' data { <code> }
                     | 
                  |
| 334 | 
                      #' model { <code> }
                     | 
                  |
| 335 | 
                      #' ```  | 
                  |
| 336 | 
                      #'  | 
                  |
| 337 | 
                      #' @keywords internal  | 
                  |
| 338 | 
                      as_stan_fragments <- function(x, stan_blocks = STAN_BLOCKS) {
                     | 
                  |
| 339 | 2585x | 
                      code <- unlist(stringr::str_split(x, "\n"))  | 
                  
| 340 | ||
| 341 | 2585x | 
                      errmsg <- paste(  | 
                  
| 342 | 2585x | 
                      "There were problems parsing the `%s` block.",  | 
                  
| 343 | 2585x | 
                      "Please consult the `Formatting Stan Files` section of the",  | 
                  
| 344 | 2585x | 
                      "`Extending jmpost` vignette"  | 
                  
| 345 | 
                      )  | 
                  |
| 346 | ||
| 347 | 
                      # Check to see if any block openings exist that have code on the same line  | 
                  |
| 348 | 
                          # e.g.  `data { int i;}`. This is unsupported so we throw an error
                     | 
                  |
| 349 | 2585x | 
                          for (block in stan_blocks) {
                     | 
                  
| 350 | 18090x | 
                              regex <- sprintf("^\\s*%s\\s*\\{\\s*[^\\s-]+", block)
                     | 
                  
| 351 | 18090x | 
                              if (any(grepl(regex, code, perl = TRUE))) {
                     | 
                  
| 352 | 2x | 
                      stop(sprintf(errmsg, block))  | 
                  
| 353 | 
                      }  | 
                  |
| 354 | 
                      }  | 
                  |
| 355 | ||
| 356 | 
                          # We first look to identify the opening of a block e.g.  `data {`
                     | 
                  |
| 357 | 
                      # We then regard all lines that follow as belonging to that block  | 
                  |
| 358 | 
                          # until we see another block being opened e.g. `model{`
                     | 
                  |
| 359 | 2583x | 
                      results <- list()  | 
                  
| 360 | 2583x | 
                      target <- NULL  | 
                  
| 361 | 2583x | 
                          for (line in code) {
                     | 
                  
| 362 | 200954x | 
                              for (block in names(stan_blocks)) {
                     | 
                  
| 363 | 1383314x | 
                                  regex <- sprintf("^\\s*%s\\s*\\{\\s*$", stan_blocks[[block]])
                     | 
                  
| 364 | 1383314x | 
                                  if (stringr::str_detect(line, regex)) {
                     | 
                  
| 365 | 7489x | 
                      target <- block  | 
                  
| 366 | 7489x | 
                      line <- NULL  | 
                  
| 367 | 7489x | 
                      break  | 
                  
| 368 | 
                      }  | 
                  |
| 369 | 
                      }  | 
                  |
| 370 | 200954x | 
                              if (!is.null(target)) {
                     | 
                  
| 371 | 
                      # This is memory inefficient but given the relatively small size of  | 
                  |
| 372 | 
                      # stan files its regarded as a acceptable simplification to ease the  | 
                  |
| 373 | 
                      # code burden  | 
                  |
| 374 | 199992x | 
                      results[[target]] <- c(results[[target]], line)  | 
                  
| 375 | 
                      }  | 
                  |
| 376 | 
                      }  | 
                  |
| 377 | ||
| 378 | 
                      # Loop over each block to remove trailing "}".  | 
                  |
| 379 | 2583x | 
                          for (block in names(results)) {
                     | 
                  
| 380 | 7488x | 
                      block_length <- length(results[[block]])  | 
                  
| 381 | 
                      # The following processing is only required if the block actually has content  | 
                  |
| 382 | 7488x | 
                              if (block_length == 1 && results[[block]] == "") {
                     | 
                  
| 383 | ! | 
                      next  | 
                  
| 384 | 
                      }  | 
                  |
| 385 | 7488x | 
                      has_removed_char <- FALSE  | 
                  
| 386 | 
                              # Walk backwards to find the closing `}` that corresponds to the `<block> {`
                     | 
                  |
| 387 | 7488x | 
                              for (index in rev(seq_len(block_length))) {
                     | 
                  
| 388 | 16194x | 
                      line <- results[[block]][[index]]  | 
                  
| 389 | 
                      # This code will exit the for loop as soon as it hits the closing `}`  | 
                  |
| 390 | 
                      # thus if we ever see a line that ends in text/numbers it means  | 
                  |
| 391 | 
                      # somethings gone wrong  | 
                  |
| 392 | 16194x | 
                                  if (stringr::str_detect(line, "[\\w\\d]+\\s*$")) {
                     | 
                  
| 393 | 1x | 
                      stop(sprintf(errmsg, block))  | 
                  
| 394 | 
                      }  | 
                  |
| 395 | 16193x | 
                                  if (stringr::str_detect(line, "\\}\\s*$")) {
                     | 
                  
| 396 | 7487x | 
                      new_line <- stringr::str_replace(line, "\\s*\\}\\s*$", "")  | 
                  
| 397 | 
                      # If the line is now blank after removing the closing `}` then drop the line  | 
                  |
| 398 | 7487x | 
                      keep_offset <- if (nchar(new_line) == 0) -1 else 0  | 
                  
| 399 | 
                      # Only keep lines from the start of the block to the closing `}`  | 
                  |
| 400 | 
                      # this is to ensure we drop blank lines that were between the end  | 
                  |
| 401 | 
                      # of the block and the start of the next  | 
                  |
| 402 | 7487x | 
                      keep_range <- seq_len(index + keep_offset)  | 
                  
| 403 | 7487x | 
                      results[[block]][[index]] <- new_line  | 
                  
| 404 | 7487x | 
                      results[[block]] <- results[[block]][keep_range]  | 
                  
| 405 | 7487x | 
                      has_removed_char <- TRUE  | 
                  
| 406 | 7487x | 
                      break  | 
                  
| 407 | 
                      }  | 
                  |
| 408 | 
                      }  | 
                  |
| 409 | 
                      # If we haven't actually removed a closing `}` then something has gone wrong...  | 
                  |
| 410 | 7487x | 
                              if (!has_removed_char) {
                     | 
                  
| 411 | ! | 
                      stop(sprintf(errmsg, block))  | 
                  
| 412 | 
                      }  | 
                  |
| 413 | 
                      }  | 
                  |
| 414 | ||
| 415 | 
                      # Add any missing blocks back in  | 
                  |
| 416 | 2582x | 
                          for (block in names(stan_blocks)) {
                     | 
                  
| 417 | 18074x | 
                              if (is.null(results[[block]])) {
                     | 
                  
| 418 | 10587x | 
                      results[[block]] <- ""  | 
                  
| 419 | 
                      }  | 
                  |
| 420 | 
                      }  | 
                  |
| 421 | 2582x | 
                      results  | 
                  
| 422 | 
                      }  | 
                  |
| 423 | ||
| 424 | 
                      #' `StanModule` -> Printable `Character`  | 
                  |
| 425 | 
                      #'  | 
                  |
| 426 | 
                      #' Converts [`StanModule`] object into a printable string.  | 
                  |
| 427 | 
                      #' @param object ([`StanModule`])\cr A stan program  | 
                  |
| 428 | 
                      #' @family StanModule  | 
                  |
| 429 | 
                      #' @param indent (`numeric`)\cr how much white space to prefix the print string with.  | 
                  |
| 430 | 
                      #' @keywords internal  | 
                  |
| 431 | 
                      #' @export  | 
                  |
| 432 | 
                      as_print_string.StanModule <- function(object, indent = 1, ...) {
                     | 
                  |
| 433 | 1x | 
                          slots <- names(getSlots("StanModule"))
                     | 
                  
| 434 | 1x | 
                      components <- Filter(\(block) paste(slot(object, block), collapse = "") != "", slots)  | 
                  
| 435 | 1x | 
                      template <- c(  | 
                  
| 436 | 1x | 
                      "StanModule Object with components:",  | 
                  
| 437 | 1x | 
                              paste("    ", components)
                     | 
                  
| 438 | 
                      )  | 
                  |
| 439 | 1x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 440 | 1x | 
                      template_padded <- paste(pad, template)  | 
                  
| 441 | 1x | 
                      sprintf(  | 
                  
| 442 | 1x | 
                      paste(template_padded, collapse = "\n")  | 
                  
| 443 | 
                      )  | 
                  |
| 444 | 
                      }  | 
                  |
| 445 | ||
| 446 | 
                      #' @rdname show-object  | 
                  |
| 447 | 
                      #' @export  | 
                  |
| 448 | 
                      setMethod(  | 
                  |
| 449 | 
                      f = "show",  | 
                  |
| 450 | 
                      signature = "StanModule",  | 
                  |
| 451 | 
                          definition = function(object) {
                     | 
                  |
| 452 | 1x | 
                      string <- as_print_string(object)  | 
                  
| 453 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 454 | 
                      }  | 
                  |
| 455 | 
                      )  | 
                  
| 1 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 2 | 
                      #' @include StanModule.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      #' @include ParameterList.R  | 
                  |
| 5 | 
                      #' @include Parameter.R  | 
                  |
| 6 | 
                      #' @include Link.R  | 
                  |
| 7 | 
                      NULL  | 
                  |
| 8 | ||
| 9 | 
                      # LongitudinalGSF-class ----  | 
                  |
| 10 | ||
| 11 | 
                      #' `LongitudinalGSF`  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' This class extends the general [`LongitudinalModel`] class for using the  | 
                  |
| 14 | 
                      #' Generalized Stein-Fojo (GSF) model for the longitudinal outcome.  | 
                  |
| 15 | 
                      #'  | 
                  |
| 16 | 
                      #' @section Available Links:  | 
                  |
| 17 | 
                      #' - [`linkDSLD()`]  | 
                  |
| 18 | 
                      #' - [`linkTTG()`]  | 
                  |
| 19 | 
                      #' - [`linkIdentity()`]  | 
                  |
| 20 | 
                      #' - [`linkGrowth()`]  | 
                  |
| 21 | 
                      #' @exportClass LongitudinalGSF  | 
                  |
| 22 | 
                      .LongitudinalGSF <- setClass(  | 
                  |
| 23 | 
                      Class = "LongitudinalGSF",  | 
                  |
| 24 | 
                      contains = "LongitudinalModel"  | 
                  |
| 25 | 
                      )  | 
                  |
| 26 | ||
| 27 | 
                      # LongitudinalGSF-constructors ----  | 
                  |
| 28 | ||
| 29 | 
                      #' @rdname LongitudinalGSF-class  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @param mu_bsld (`Prior`)\cr for the mean baseline value `mu_bsld`.  | 
                  |
| 32 | 
                      #' @param mu_ks (`Prior`)\cr for the mean shrinkage rate `mu_ks`.  | 
                  |
| 33 | 
                      #' @param mu_kg (`Prior`)\cr for the mean growth rate `mu_kg`.  | 
                  |
| 34 | 
                      #' @param mu_phi (`Prior`)\cr for the mean proportion of cells affected by the treatment `mu_phi`.  | 
                  |
| 35 | 
                      #'  | 
                  |
| 36 | 
                      #' @param omega_bsld (`Prior`)\cr for the baseline value standard deviation `omega_bsld`.  | 
                  |
| 37 | 
                      #' @param omega_ks (`Prior`)\cr for the shrinkage rate standard deviation `omega_ks`.  | 
                  |
| 38 | 
                      #' @param omega_kg (`Prior`)\cr for the growth rate standard deviation `omega_kg`.  | 
                  |
| 39 | 
                      #' @param omega_phi (`Prior`)\cr for the standard deviation of the proportion of cells  | 
                  |
| 40 | 
                      #' affected by the treatment `omega_phi`.  | 
                  |
| 41 | 
                      #'  | 
                  |
| 42 | 
                      #' @param sigma (`Prior`)\cr for the variance of the longitudinal values `sigma`.  | 
                  |
| 43 | 
                      #'  | 
                  |
| 44 | 
                      #' @param centred (`logical`)\cr whether to use the centred parameterization.  | 
                  |
| 45 | 
                      #'  | 
                  |
| 46 | 
                      #' @importFrom stats qlogis  | 
                  |
| 47 | 
                      #' @export  | 
                  |
| 48 | 
                      LongitudinalGSF <- function(  | 
                  |
| 49 | ||
| 50 | 
                      mu_bsld = prior_normal(log(60), 1),  | 
                  |
| 51 | 
                      mu_ks = prior_normal(log(0.5), 1),  | 
                  |
| 52 | 
                      mu_kg = prior_normal(log(0.3), 1),  | 
                  |
| 53 | 
                      mu_phi = prior_normal(qlogis(0.5), 1),  | 
                  |
| 54 | ||
| 55 | 
                      omega_bsld = prior_lognormal(log(0.2), 1),  | 
                  |
| 56 | 
                      omega_ks = prior_lognormal(log(0.2), 1),  | 
                  |
| 57 | 
                      omega_kg = prior_lognormal(log(0.2), 1),  | 
                  |
| 58 | 
                      omega_phi = prior_lognormal(log(0.2), 1),  | 
                  |
| 59 | ||
| 60 | 
                      sigma = prior_lognormal(log(0.1), 1),  | 
                  |
| 61 | ||
| 62 | 
                      centred = FALSE  | 
                  |
| 63 | 
                      ) {
                     | 
                  |
| 64 | ||
| 65 | 21x | 
                      gsf_model <- StanModule(decorated_render(  | 
                  
| 66 | 21x | 
                              .x = read_stan("lm-gsf/model.stan"),
                     | 
                  
| 67 | 21x | 
                      centred = centred  | 
                  
| 68 | 
                      ))  | 
                  |
| 69 | ||
| 70 | 
                      # Apply constraints  | 
                  |
| 71 | 21x | 
                      omega_bsld <- set_limits(omega_bsld, lower = 0)  | 
                  
| 72 | 21x | 
                      omega_ks <- set_limits(omega_ks, lower = 0)  | 
                  
| 73 | 21x | 
                      omega_kg <- set_limits(omega_kg, lower = 0)  | 
                  
| 74 | 21x | 
                      omega_phi <- set_limits(omega_phi, lower = 0)  | 
                  
| 75 | 21x | 
                      sigma <- set_limits(sigma, lower = 0)  | 
                  
| 76 | ||
| 77 | ||
| 78 | 21x | 
                      parameters <- list(  | 
                  
| 79 | 21x | 
                      Parameter(name = "lm_gsf_mu_bsld", prior = mu_bsld, size = "n_studies"),  | 
                  
| 80 | 21x | 
                      Parameter(name = "lm_gsf_mu_ks", prior = mu_ks, size = "n_arms"),  | 
                  
| 81 | 21x | 
                      Parameter(name = "lm_gsf_mu_kg", prior = mu_kg, size = "n_arms"),  | 
                  
| 82 | 21x | 
                      Parameter(name = "lm_gsf_mu_phi", prior = mu_phi, size = "n_arms"),  | 
                  
| 83 | ||
| 84 | 21x | 
                      Parameter(name = "lm_gsf_omega_bsld", prior = omega_bsld, size = 1),  | 
                  
| 85 | 21x | 
                      Parameter(name = "lm_gsf_omega_ks", prior = omega_ks, size = 1),  | 
                  
| 86 | 21x | 
                      Parameter(name = "lm_gsf_omega_kg", prior = omega_kg, size = 1),  | 
                  
| 87 | 21x | 
                      Parameter(name = "lm_gsf_omega_phi", prior = omega_phi, size = 1),  | 
                  
| 88 | ||
| 89 | 21x | 
                      Parameter(name = "lm_gsf_sigma", prior = sigma, size = 1)  | 
                  
| 90 | 
                      )  | 
                  |
| 91 | ||
| 92 | 21x | 
                      assert_flag(centred)  | 
                  
| 93 | 21x | 
                          parameters_extra <- if (centred) {
                     | 
                  
| 94 | 4x | 
                      list(  | 
                  
| 95 | 4x | 
                      Parameter(  | 
                  
| 96 | 4x | 
                      name = "lm_gsf_psi_bsld",  | 
                  
| 97 | 4x | 
                      prior = prior_init_only(prior_lognormal(median(mu_bsld), median(omega_bsld))),  | 
                  
| 98 | 4x | 
                      size = "n_subjects"  | 
                  
| 99 | 
                      ),  | 
                  |
| 100 | 4x | 
                      Parameter(  | 
                  
| 101 | 4x | 
                      name = "lm_gsf_psi_ks",  | 
                  
| 102 | 4x | 
                      prior = prior_init_only(prior_lognormal(median(mu_ks), median(omega_ks))),  | 
                  
| 103 | 4x | 
                      size = "n_subjects"  | 
                  
| 104 | 
                      ),  | 
                  |
| 105 | 4x | 
                      Parameter(  | 
                  
| 106 | 4x | 
                      name = "lm_gsf_psi_kg",  | 
                  
| 107 | 4x | 
                      prior = prior_init_only(prior_lognormal(median(mu_kg), median(omega_kg))),  | 
                  
| 108 | 4x | 
                      size = "n_subjects"  | 
                  
| 109 | 
                      ),  | 
                  |
| 110 | 4x | 
                      Parameter(  | 
                  
| 111 | 4x | 
                      name = "lm_gsf_psi_phi_logit",  | 
                  
| 112 | 4x | 
                      prior = prior_init_only(prior_normal(median(mu_phi), median(omega_phi))),  | 
                  
| 113 | 4x | 
                      size = "n_subjects"  | 
                  
| 114 | 
                      )  | 
                  |
| 115 | 
                      )  | 
                  |
| 116 | 
                          } else {
                     | 
                  |
| 117 | 17x | 
                      list(  | 
                  
| 118 | 17x | 
                      Parameter(name = "lm_gsf_eta_tilde_bsld", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 119 | 17x | 
                      Parameter(name = "lm_gsf_eta_tilde_ks", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 120 | 17x | 
                      Parameter(name = "lm_gsf_eta_tilde_kg", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 121 | 17x | 
                      Parameter(name = "lm_gsf_eta_tilde_phi", prior = prior_std_normal(), size = "n_subjects")  | 
                  
| 122 | 
                      )  | 
                  |
| 123 | 
                      }  | 
                  |
| 124 | 21x | 
                      parameters <- append(parameters, parameters_extra)  | 
                  
| 125 | ||
| 126 | 21x | 
                      x <- LongitudinalModel(  | 
                  
| 127 | 21x | 
                      name = "Generalized Stein-Fojo",  | 
                  
| 128 | 21x | 
                      stan = merge(  | 
                  
| 129 | 21x | 
                      gsf_model,  | 
                  
| 130 | 21x | 
                                  StanModule("lm-gsf/functions.stan")
                     | 
                  
| 131 | 
                      ),  | 
                  |
| 132 | 21x | 
                      parameters = do.call(ParameterList, parameters)  | 
                  
| 133 | 
                      )  | 
                  |
| 134 | 21x | 
                      .LongitudinalGSF(x)  | 
                  
| 135 | 
                      }  | 
                  |
| 136 | ||
| 137 | ||
| 138 | ||
| 139 | 
                      #' @export  | 
                  |
| 140 | 
                      enableGQ.LongitudinalGSF <- function(object, ...) {
                     | 
                  |
| 141 | 7x | 
                          StanModule("lm-gsf/quantities.stan")
                     | 
                  
| 142 | 
                      }  | 
                  |
| 143 | ||
| 144 | ||
| 145 | 
                      #' @export  | 
                  |
| 146 | 
                      enableLink.LongitudinalGSF <- function(object, ...) {
                     | 
                  |
| 147 | 4x | 
                      object@stan <- merge(  | 
                  
| 148 | 4x | 
                      object@stan,  | 
                  
| 149 | 4x | 
                              StanModule("lm-gsf/link.stan")
                     | 
                  
| 150 | 
                      )  | 
                  |
| 151 | 4x | 
                      object  | 
                  
| 152 | 
                      }  | 
                  |
| 153 | ||
| 154 | 
                      #' @export  | 
                  |
| 155 | 
                      linkDSLD.LongitudinalGSF <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 156 | 6x | 
                      LinkComponent(  | 
                  
| 157 | 6x | 
                      key = "link_dsld",  | 
                  
| 158 | 6x | 
                              stan = StanModule("lm-gsf/link_dsld.stan"),
                     | 
                  
| 159 | 6x | 
                      prior = prior  | 
                  
| 160 | 
                      )  | 
                  |
| 161 | 
                      }  | 
                  |
| 162 | ||
| 163 | 
                      #' @export  | 
                  |
| 164 | 
                      linkTTG.LongitudinalGSF <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 165 | 4x | 
                      LinkComponent(  | 
                  
| 166 | 4x | 
                      key = "link_ttg",  | 
                  
| 167 | 4x | 
                              stan = StanModule("lm-gsf/link_ttg.stan"),
                     | 
                  
| 168 | 4x | 
                      prior = prior  | 
                  
| 169 | 
                      )  | 
                  |
| 170 | 
                      }  | 
                  |
| 171 | ||
| 172 | 
                      #' @export  | 
                  |
| 173 | 
                      linkIdentity.LongitudinalGSF <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 174 | 3x | 
                      LinkComponent(  | 
                  
| 175 | 3x | 
                      key = "link_identity",  | 
                  
| 176 | 3x | 
                              stan = StanModule("lm-gsf/link_identity.stan"),
                     | 
                  
| 177 | 3x | 
                      prior = prior  | 
                  
| 178 | 
                      )  | 
                  |
| 179 | 
                      }  | 
                  |
| 180 | ||
| 181 | 
                      #' @export  | 
                  |
| 182 | 
                      linkGrowth.LongitudinalGSF <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 183 | 1x | 
                      LinkComponent(  | 
                  
| 184 | 1x | 
                      key = "link_growth",  | 
                  
| 185 | 1x | 
                              stan = StanModule("lm-gsf/link_growth.stan"),
                     | 
                  
| 186 | 1x | 
                      prior = prior  | 
                  
| 187 | 
                      )  | 
                  |
| 188 | 
                      }  | 
                  |
| 189 | ||
| 190 | ||
| 191 | 
                      #' @rdname getPredictionNames  | 
                  |
| 192 | 
                      #' @export  | 
                  |
| 193 | 
                      getPredictionNames.LongitudinalGSF <- function(object, ...) {
                     | 
                  |
| 194 | 3x | 
                          c("b", "s", "g", "phi")
                     | 
                  
| 195 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include utilities.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' Re-used documentation for `DataLongitudinal`  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' @param object ([`DataLongitudinal`]) \cr Longitudinal Data.  | 
                  |
| 8 | 
                      #' @param x ([`DataLongitudinal`]) \cr Longitudinal Data.  | 
                  |
| 9 | 
                      #' @param ... Not Used.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @name DataLongitudinal-Shared  | 
                  |
| 12 | 
                      #' @keywords internal  | 
                  |
| 13 | 
                      NULL  | 
                  |
| 14 | ||
| 15 | ||
| 16 | 
                      # DataLongitudinal-class ----  | 
                  |
| 17 | ||
| 18 | 
                      #' Longitudinal Data Object and Constructor Function  | 
                  |
| 19 | 
                      #'  | 
                  |
| 20 | 
                      #' The [`DataLongitudinal`] class handles the processing of the longitudinal data for fitting a Joint Model.  | 
                  |
| 21 | 
                      #'  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #' @slot data (`data.frame`)\cr See Arguments for details; Note that  | 
                  |
| 24 | 
                      #' observations that contain missing values in the required variables are removed.  | 
                  |
| 25 | 
                      #' @slot formula (`formula`)\cr See Arguments for details  | 
                  |
| 26 | 
                      #' @slot threshold (`numeric`)\cr See Arguments for details  | 
                  |
| 27 | 
                      #'  | 
                  |
| 28 | 
                      #' @family DataObjects  | 
                  |
| 29 | 
                      #' @family DataLongitudinal  | 
                  |
| 30 | 
                      #' @export DataLongitudinal  | 
                  |
| 31 | 
                      #' @exportClass DataLongitudinal  | 
                  |
| 32 | 
                      .DataLongitudinal <- setClass(  | 
                  |
| 33 | 
                      Class = "DataLongitudinal",  | 
                  |
| 34 | 
                      representation = list(  | 
                  |
| 35 | 
                      data = "data.frame",  | 
                  |
| 36 | 
                      formula = "formula",  | 
                  |
| 37 | 
                      threshold = "numeric_or_NULL"  | 
                  |
| 38 | 
                      )  | 
                  |
| 39 | 
                      )  | 
                  |
| 40 | ||
| 41 | ||
| 42 | 
                      #' @param data (`data.frame`)\cr containing the observed longitudinal data.  | 
                  |
| 43 | 
                      #' @param formula (`formula`)\cr of the form `outcome ~ time`, and cannot contain any additional covariates.  | 
                  |
| 44 | 
                      #' @param threshold (`numeric`)\cr cut-off value to be used to declare an observation as censored  | 
                  |
| 45 | 
                      #' (below detection limit).  | 
                  |
| 46 | 
                      #' @rdname DataLongitudinal-class  | 
                  |
| 47 | 
                      DataLongitudinal <- function(data, formula, threshold = NULL) {
                     | 
                  |
| 48 | 45x | 
                      .DataLongitudinal(  | 
                  
| 49 | 45x | 
                      data = remove_missing_rows(data, formula),  | 
                  
| 50 | 45x | 
                      formula = formula,  | 
                  
| 51 | 45x | 
                      threshold = threshold  | 
                  
| 52 | 
                      )  | 
                  |
| 53 | 
                      }  | 
                  |
| 54 | ||
| 55 | 
                      setValidity(  | 
                  |
| 56 | 
                      "DataLongitudinal",  | 
                  |
| 57 | 
                          function(object) {
                     | 
                  |
| 58 | 
                              if (!length(object@formula) == 3) {
                     | 
                  |
| 59 | 
                                  return("`formula` should be a 2 sided formula")
                     | 
                  |
| 60 | 
                      }  | 
                  |
| 61 | 
                              if (!length(object@formula[[3]]) == 1) {
                     | 
                  |
| 62 | 
                                  return("the RHS of `formula` should only have 1 value")
                     | 
                  |
| 63 | 
                      }  | 
                  |
| 64 | 
                              if (!length(object@threshold) <= 1) {
                     | 
                  |
| 65 | 
                                  return("`threshold` must be of length 1 or `NULL`")
                     | 
                  |
| 66 | 
                      }  | 
                  |
| 67 | 
                      vars <- extractVariableNames(object)  | 
                  |
| 68 | 
                      vars$threshold <- NULL  | 
                  |
| 69 | 
                      vars$frm <- NULL  | 
                  |
| 70 | 
                              for (i in unlist(vars)) {
                     | 
                  |
| 71 | 
                                  if (! i %in% names(object@data)) {
                     | 
                  |
| 72 | 
                                      return(sprintf("Variable `%s` is not in data", i))
                     | 
                  |
| 73 | 
                      }  | 
                  |
| 74 | 
                      }  | 
                  |
| 75 | 
                      return(TRUE)  | 
                  |
| 76 | 
                      }  | 
                  |
| 77 | 
                      )  | 
                  |
| 78 | ||
| 79 | ||
| 80 | ||
| 81 | ||
| 82 | 
                      #' @rdname harmonise  | 
                  |
| 83 | 
                      harmonise.DataLongitudinal <- function(object, subject_var, subject_ord, ...) {
                     | 
                  |
| 84 | 23x | 
                      data <- as.data.frame(object)  | 
                  
| 85 | 23x | 
                      vars <- extractVariableNames(object)  | 
                  
| 86 | 23x | 
                      assert_string(subject_var, na.ok = FALSE)  | 
                  
| 87 | 23x | 
                      assert_character(subject_ord, any.missing = FALSE)  | 
                  
| 88 | 23x | 
                      assert_that(  | 
                  
| 89 | 23x | 
                      subject_var %in% names(data),  | 
                  
| 90 | 23x | 
                              msg = sprintf("Subject variable `%s` not found in `longitudinal`", subject_var)
                     | 
                  
| 91 | 
                      )  | 
                  |
| 92 | 22x | 
                      assert_that(  | 
                  
| 93 | 22x | 
                      all(data[[subject_var]] %in% subject_ord),  | 
                  
| 94 | 22x | 
                      msg = "There are subjects in `longitudinal` that are not present in `subjects`"  | 
                  
| 95 | 
                      )  | 
                  |
| 96 | 21x | 
                      assert_that(  | 
                  
| 97 | 21x | 
                      all(subject_ord %in% data[[subject_var]]),  | 
                  
| 98 | 21x | 
                      msg = "There are subjects in `subjects` that are not present in `longitudinal`"  | 
                  
| 99 | 
                      )  | 
                  |
| 100 | 20x | 
                      data[[subject_var]] <- factor(  | 
                  
| 101 | 20x | 
                      as.character(data[[subject_var]]),  | 
                  
| 102 | 20x | 
                      levels = subject_ord  | 
                  
| 103 | 
                      )  | 
                  |
| 104 | 20x | 
                      data_re_ord <- order(  | 
                  
| 105 | 20x | 
                      data[[subject_var]],  | 
                  
| 106 | 20x | 
                      data[[vars$time]],  | 
                  
| 107 | 20x | 
                      data[[vars$outcome]]  | 
                  
| 108 | 
                      )  | 
                  |
| 109 | 20x | 
                      data_ord <- data[data_re_ord, ]  | 
                  
| 110 | 20x | 
                      DataLongitudinal(  | 
                  
| 111 | 20x | 
                      data = data_ord,  | 
                  
| 112 | 20x | 
                      formula = object@formula,  | 
                  
| 113 | 20x | 
                      threshold = object@threshold  | 
                  
| 114 | 
                      )  | 
                  |
| 115 | 
                      }  | 
                  |
| 116 | ||
| 117 | ||
| 118 | ||
| 119 | 
                      #' `DataLongitudinal` -> `data.frame`  | 
                  |
| 120 | 
                      #'  | 
                  |
| 121 | 
                      #' @inheritParams DataLongitudinal-Shared  | 
                  |
| 122 | 
                      #'  | 
                  |
| 123 | 
                      #' @description  | 
                  |
| 124 | 
                      #' Converts a [`DataLongitudinal`] object into a `data.frame`.  | 
                  |
| 125 | 
                      #' The subject variable is cast to factor.  | 
                  |
| 126 | 
                      #' @family DataLongitudinal  | 
                  |
| 127 | 
                      #' @export  | 
                  |
| 128 | 
                      as.data.frame.DataLongitudinal <- function(x, ...) {
                     | 
                  |
| 129 | 325x | 
                      x <- x@data  | 
                  
| 130 | 325x | 
                      rownames(x) <- NULL  | 
                  
| 131 | 325x | 
                      x  | 
                  
| 132 | 
                      }  | 
                  |
| 133 | ||
| 134 | ||
| 135 | ||
| 136 | ||
| 137 | 
                      #' @inheritParams DataLongitudinal-Shared  | 
                  |
| 138 | 
                      #' @inherit extractVariableNames description title  | 
                  |
| 139 | 
                      #'  | 
                  |
| 140 | 
                      #' @returns  | 
                  |
| 141 | 
                      #' A list with the following named elements:  | 
                  |
| 142 | 
                      #' - `subject` (`character`)\cr The name of the variable containing the subject identifier  | 
                  |
| 143 | 
                      #' - `frm` (`formula`)\cr of the form `outcome ~ time`  | 
                  |
| 144 | 
                      #' - `time` (`character`)\cr The name of the variable containing the outcome time  | 
                  |
| 145 | 
                      #' - `outcome` (`character`)\cr The name of the variable containing the outcome values  | 
                  |
| 146 | 
                      #' - `threshold` (`numeric`)\cr cut-off value to be used to declare an observation as censored  | 
                  |
| 147 | 
                      #' (below detection limit).  | 
                  |
| 148 | 
                      #' @family DataLongitudinal  | 
                  |
| 149 | 
                      #' @family extractVariableNames  | 
                  |
| 150 | 
                      extractVariableNames.DataLongitudinal <- function(object) {
                     | 
                  |
| 151 | 349x | 
                      list(  | 
                  
| 152 | 349x | 
                      frm = object@formula,  | 
                  
| 153 | 349x | 
                      time = as.character(object@formula[[3]]),  | 
                  
| 154 | 349x | 
                      outcome = as.character(object@formula[[2]]),  | 
                  
| 155 | 349x | 
                      threshold = object@threshold  | 
                  
| 156 | 
                      )  | 
                  |
| 157 | 
                      }  | 
                  |
| 158 | ||
| 159 | ||
| 160 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 161 | 
                      #' @family DataLongitudinal  | 
                  |
| 162 | 
                      #' @export  | 
                  |
| 163 | 
                      as_stan_list.DataLongitudinal <- function(object, subject_var, ...) {
                     | 
                  |
| 164 | ||
| 165 | 279x | 
                      df <- as.data.frame(object)  | 
                  
| 166 | 279x | 
                      vars <- extractVariableNames(object)  | 
                  
| 167 | ||
| 168 | 279x | 
                      assert_factor(df[[subject_var]])  | 
                  
| 169 | ||
| 170 | 279x | 
                      mat_sld_index <- stats::model.matrix(  | 
                  
| 171 | 279x | 
                              stats::as.formula(paste("~ -1 + ", subject_var)),
                     | 
                  
| 172 | 279x | 
                      data = df  | 
                  
| 173 | 
                      ) |>  | 
                  |
| 174 | 279x | 
                      t()  | 
                  
| 175 | ||
| 176 | 279x | 
                          adj_threshold <- if (is.null(vars$threshold)) {
                     | 
                  
| 177 | 56x | 
                      -999999  | 
                  
| 178 | 
                          } else {
                     | 
                  |
| 179 | 223x | 
                      vars$threshold  | 
                  
| 180 | 
                      }  | 
                  |
| 181 | ||
| 182 | 279x | 
                      index_obs <- which(df[[vars$outcome]] >= adj_threshold)  | 
                  
| 183 | 279x | 
                      index_cen <- which(df[[vars$outcome]] < adj_threshold)  | 
                  
| 184 | ||
| 185 | 279x | 
                      sparse_mat_inds_all_y <- rstan::extract_sparse_parts(mat_sld_index)  | 
                  
| 186 | 279x | 
                      sparse_mat_inds_obs_y <- rstan::extract_sparse_parts(mat_sld_index[, index_obs])  | 
                  
| 187 | 279x | 
                      sparse_mat_inds_cens_y <- rstan::extract_sparse_parts(mat_sld_index[, index_cen])  | 
                  
| 188 | ||
| 189 | 279x | 
                      model_data <- list(  | 
                  
| 190 | 279x | 
                      n_tumour_all = nrow(df),  | 
                  
| 191 | ||
| 192 | 
                      # Number of individuals and tumour assessments.  | 
                  |
| 193 | 279x | 
                      n_tumour_obs = length(index_obs),  | 
                  
| 194 | 279x | 
                      n_tumour_cens = length(index_cen),  | 
                  
| 195 | ||
| 196 | 
                      # Index vectors  | 
                  |
| 197 | 279x | 
                      subject_tumour_index = as.numeric(df[[subject_var]]),  | 
                  
| 198 | 279x | 
                      subject_tumour_index_obs = index_obs,  | 
                  
| 199 | 279x | 
                      subject_tumour_index_cens = index_cen,  | 
                  
| 200 | ||
| 201 | 279x | 
                      tumour_value = df[[vars$outcome]],  | 
                  
| 202 | 279x | 
                      tumour_time = df[[vars$time]],  | 
                  
| 203 | 279x | 
                      tumour_value_lloq = adj_threshold,  | 
                  
| 204 | ||
| 205 | 
                      # Sparse matrix parameters  | 
                  |
| 206 | 
                      # Matrix of individuals x observed tumour assessments.  | 
                  |
| 207 | 279x | 
                      n_mat_inds_obs_y = c(  | 
                  
| 208 | 279x | 
                      length(sparse_mat_inds_obs_y$w),  | 
                  
| 209 | 279x | 
                      length(sparse_mat_inds_obs_y$v),  | 
                  
| 210 | 279x | 
                      length(sparse_mat_inds_obs_y$u)  | 
                  
| 211 | 
                      ),  | 
                  |
| 212 | 279x | 
                      w_mat_inds_obs_y = sparse_mat_inds_obs_y$w,  | 
                  
| 213 | 279x | 
                      v_mat_inds_obs_y = sparse_mat_inds_obs_y$v,  | 
                  
| 214 | 279x | 
                      u_mat_inds_obs_y = sparse_mat_inds_obs_y$u,  | 
                  
| 215 | ||
| 216 | 
                      # Matrix of individuals x censored tumour assessments.  | 
                  |
| 217 | 279x | 
                      n_mat_inds_cens_y = c(  | 
                  
| 218 | 279x | 
                      length(sparse_mat_inds_cens_y$w),  | 
                  
| 219 | 279x | 
                      length(sparse_mat_inds_cens_y$v),  | 
                  
| 220 | 279x | 
                      length(sparse_mat_inds_cens_y$u)  | 
                  
| 221 | 
                      ),  | 
                  |
| 222 | 279x | 
                      w_mat_inds_cens_y = sparse_mat_inds_cens_y$w,  | 
                  
| 223 | 279x | 
                      v_mat_inds_cens_y = sparse_mat_inds_cens_y$v,  | 
                  
| 224 | 279x | 
                      u_mat_inds_cens_y = sparse_mat_inds_cens_y$u,  | 
                  
| 225 | ||
| 226 | 
                      # Matrix of all individuals tumour assessments  | 
                  |
| 227 | 279x | 
                      n_mat_inds_all_y = c(  | 
                  
| 228 | 279x | 
                      length(sparse_mat_inds_all_y$w),  | 
                  
| 229 | 279x | 
                      length(sparse_mat_inds_all_y$v),  | 
                  
| 230 | 279x | 
                      length(sparse_mat_inds_all_y$u)  | 
                  
| 231 | 
                      ),  | 
                  |
| 232 | 279x | 
                      w_mat_inds_all_y = sparse_mat_inds_all_y$w,  | 
                  
| 233 | 279x | 
                      v_mat_inds_all_y = sparse_mat_inds_all_y$v,  | 
                  
| 234 | 279x | 
                      u_mat_inds_all_y = sparse_mat_inds_all_y$u  | 
                  
| 235 | ||
| 236 | 
                      )  | 
                  |
| 237 | ||
| 238 | 279x | 
                      return(model_data)  | 
                  
| 239 | 
                      }  | 
                  |
| 240 | ||
| 241 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 242 | 
                      #' @export  | 
                  |
| 243 | 
                      as.list.DataLongitudinal <- function(x, ...) {
                     | 
                  |
| 244 | ! | 
                      as_stan_list(x, ...)  | 
                  
| 245 | 
                      }  | 
                  |
| 246 | ||
| 247 | ||
| 248 | 
                      #' `DataLongitudinal` -> Printable `Character`  | 
                  |
| 249 | 
                      #'  | 
                  |
| 250 | 
                      #' Converts [`DataLongitudinal`] object into a printable string.  | 
                  |
| 251 | 
                      #' @inheritParams DataLongitudinal-Shared  | 
                  |
| 252 | 
                      #' @family DataLongitudinal  | 
                  |
| 253 | 
                      #' @param indent (`numeric`)\cr how much white space to prefix the print string with.  | 
                  |
| 254 | 
                      #' @keywords internal  | 
                  |
| 255 | 
                      #' @export  | 
                  |
| 256 | 
                      as_print_string.DataLongitudinal <- function(object, indent = 1, ...) {
                     | 
                  |
| 257 | 2x | 
                      template <- c(  | 
                  
| 258 | 2x | 
                      "Longitudinal-Data Object:",  | 
                  
| 259 | 2x | 
                      " # of Rows = %d",  | 
                  
| 260 | 2x | 
                      " # of Columns = %d",  | 
                  
| 261 | 2x | 
                      " # of Cen-Obvs = %d",  | 
                  
| 262 | 2x | 
                      " Formula = %s"  | 
                  
| 263 | 
                      )  | 
                  |
| 264 | 2x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 265 | 2x | 
                      template_padded <- paste(pad, template)  | 
                  
| 266 | 2x | 
                      vars <- extractVariableNames(object)  | 
                  
| 267 | 2x | 
                      sprintf(  | 
                  
| 268 | 2x | 
                      paste(template_padded, collapse = "\n"),  | 
                  
| 269 | 2x | 
                      nrow(object@data),  | 
                  
| 270 | 2x | 
                      ncol(object@data),  | 
                  
| 271 | 2x | 
                      sum(object@data[[vars$outcome]] < vars$threshold),  | 
                  
| 272 | 2x | 
                      Reduce(paste, deparse(vars$frm))  | 
                  
| 273 | 
                      )  | 
                  |
| 274 | 
                      }  | 
                  |
| 275 | ||
| 276 | 
                      #' @rdname show-object  | 
                  |
| 277 | 
                      #' @export  | 
                  |
| 278 | 
                      setMethod(  | 
                  |
| 279 | 
                      f = "show",  | 
                  |
| 280 | 
                      signature = "DataLongitudinal",  | 
                  |
| 281 | 
                          definition = function(object) {
                     | 
                  |
| 282 | 1x | 
                      string <- as_print_string(object)  | 
                  
| 283 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 284 | 
                      }  | 
                  |
| 285 | 
                      )  | 
                  
| 1 | 
                      #' @include StanModule.R  | 
                  |
| 2 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 3 | 
                      #' @include ParameterList.R  | 
                  |
| 4 | 
                      #' @include LinkComponent.R  | 
                  |
| 5 | 
                      #' @include Prior.R  | 
                  |
| 6 | 
                      NULL  | 
                  |
| 7 | ||
| 8 | ||
| 9 | 
                      #' `Link` Function Arguments  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' This exists just to contain all the common arguments for [`Link`] methods.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @param x ([`Link`])\cr a link object.  | 
                  |
| 14 | 
                      #' @param object ([`Link`])\cr a link object.  | 
                  |
| 15 | 
                      #' @param ... Not Used.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @name Link-Shared  | 
                  |
| 18 | 
                      #' @keywords internal  | 
                  |
| 19 | 
                      NULL  | 
                  |
| 20 | ||
| 21 | ||
| 22 | ||
| 23 | 
                      #' `Link`  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @slot components (`list`)\cr a list of [`LinkComponent`] or [`PromiseLinkComponent`] objects.  | 
                  |
| 26 | 
                      #' @slot resolved (`logical`)\cr indicates if all the `components` have been resolved.  | 
                  |
| 27 | 
                      #'  | 
                  |
| 28 | 
                      #' @param ... ([`LinkComponent`] or [`PromiseLinkComponent`])\cr  | 
                  |
| 29 | 
                      #' an arbitrary number of link components.  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @description  | 
                  |
| 32 | 
                      #' Simple container class to enable the use of multiple link components in a joint model.  | 
                  |
| 33 | 
                      #' Note that the constructor of this object is idempotent e.g. `Link(Link(x)) == Link(x)`  | 
                  |
| 34 | 
                      #'  | 
                  |
| 35 | 
                      #' @examples  | 
                  |
| 36 | 
                      #' Link(  | 
                  |
| 37 | 
                      #' linkDSLD(),  | 
                  |
| 38 | 
                      #' linkTTG()  | 
                  |
| 39 | 
                      #' )  | 
                  |
| 40 | 
                      #'  | 
                  |
| 41 | 
                      #' @family Link  | 
                  |
| 42 | 
                      #' @name Link-class  | 
                  |
| 43 | 
                      #' @exportClass Link  | 
                  |
| 44 | 
                      .Link <- setClass(  | 
                  |
| 45 | 
                      Class = "Link",  | 
                  |
| 46 | 
                      slots = list(  | 
                  |
| 47 | 
                      components = "list",  | 
                  |
| 48 | 
                      resolved = "logical"  | 
                  |
| 49 | 
                      )  | 
                  |
| 50 | 
                      )  | 
                  |
| 51 | ||
| 52 | 
                      #' @rdname Link-class  | 
                  |
| 53 | 
                      #' @export  | 
                  |
| 54 | 
                      Link <- function(...) {
                     | 
                  |
| 55 | 87x | 
                      components <- list(...)  | 
                  
| 56 | ||
| 57 | 
                      # If the input is already a Link object, return it (e.g. implement  | 
                  |
| 58 | 
                      # a constructor that is idempotent)  | 
                  |
| 59 | 87x | 
                          if (length(components) == 1 && is(components[[1]], "Link")) {
                     | 
                  
| 60 | 32x | 
                      return(components[[1]])  | 
                  
| 61 | 
                      }  | 
                  |
| 62 | ||
| 63 | 55x | 
                      .Link(  | 
                  
| 64 | 55x | 
                      components = components,  | 
                  
| 65 | 55x | 
                      resolved = !any(vapply(components, \(x) is(x, "PromiseLinkComponent"), logical(1)))  | 
                  
| 66 | 
                      )  | 
                  |
| 67 | 
                      }  | 
                  |
| 68 | ||
| 69 | ||
| 70 | 
                      #' Resolve any promises  | 
                  |
| 71 | 
                      #'  | 
                  |
| 72 | 
                      #' Loops over all components and ensures that any [`PromiseLinkComponent`] objects  | 
                  |
| 73 | 
                      #' are resolved to [`LinkComponent`] objects.  | 
                  |
| 74 | 
                      #'  | 
                  |
| 75 | 
                      #' @param object ([`Link`])\cr a link object.  | 
                  |
| 76 | 
                      #' @param model ([`LongitudinalModel`])\cr the model object.  | 
                  |
| 77 | 
                      #' @param ... Not Used.  | 
                  |
| 78 | 
                      #'  | 
                  |
| 79 | 
                      #' @export  | 
                  |
| 80 | 
                      resolvePromise.Link <- function(object, model, ...) {
                     | 
                  |
| 81 | 37x | 
                          if (length(object) == 0) {
                     | 
                  
| 82 | 25x | 
                      return(object)  | 
                  
| 83 | 
                      }  | 
                  |
| 84 | 12x | 
                      assert_that(  | 
                  
| 85 | 12x | 
                      is(model, "LongitudinalModel"),  | 
                  
| 86 | 12x | 
                      msg = "model must be of class `LongitudinalModel`"  | 
                  
| 87 | 
                      )  | 
                  |
| 88 | 12x | 
                      do.call(Link, lapply(object@components, resolvePromise, model = model))  | 
                  
| 89 | 
                      }  | 
                  |
| 90 | ||
| 91 | ||
| 92 | 
                      setValidity(  | 
                  |
| 93 | 
                      Class = "Link",  | 
                  |
| 94 | 
                          method = function(object) {
                     | 
                  |
| 95 | ||
| 96 | 
                              for (i in object@components) {
                     | 
                  |
| 97 | 
                                  if (!(is(i, "LinkComponent") || is(i, "PromiseLinkComponent"))) {
                     | 
                  |
| 98 | 
                                      return("All components must be of class `LinkComponent` or `PromiseLinkComponent`")
                     | 
                  |
| 99 | 
                      }  | 
                  |
| 100 | 
                      }  | 
                  |
| 101 | ||
| 102 | 
                      contains_promise <- any(  | 
                  |
| 103 | 
                      vapply(  | 
                  |
| 104 | 
                      object@components,  | 
                  |
| 105 | 
                      \(x) is(x, "PromiseLinkComponent"),  | 
                  |
| 106 | 
                      logical(1)  | 
                  |
| 107 | 
                      )  | 
                  |
| 108 | 
                      )  | 
                  |
| 109 | 
                              if (contains_promise & object@resolved) {
                     | 
                  |
| 110 | 
                                  return("Object cannot be resolved if it contains promises")
                     | 
                  |
| 111 | 
                      }  | 
                  |
| 112 | ||
| 113 | 
                              if (length(object@resolved) > 1) {
                     | 
                  |
| 114 | 
                                  return("The `resolved` slot must be a logical scalar")
                     | 
                  |
| 115 | 
                      }  | 
                  |
| 116 | 
                      return(TRUE)  | 
                  |
| 117 | 
                      }  | 
                  |
| 118 | 
                      )  | 
                  |
| 119 | ||
| 120 | ||
| 121 | ||
| 122 | ||
| 123 | 
                      #' `Link` -> `StanModule`  | 
                  |
| 124 | 
                      #'  | 
                  |
| 125 | 
                      #' Converts a [`Link`] object to a [`StanModule`] object  | 
                  |
| 126 | 
                      #'  | 
                  |
| 127 | 
                      #' @inheritParams Link-Shared  | 
                  |
| 128 | 
                      #'  | 
                  |
| 129 | 
                      #' @family Link  | 
                  |
| 130 | 
                      #' @family as.StanModule  | 
                  |
| 131 | 
                      #' @export  | 
                  |
| 132 | 
                      as.StanModule.Link <- function(object, ...) {
                     | 
                  |
| 133 | ||
| 134 | 71x | 
                          if (length(object@components) == 0) {
                     | 
                  
| 135 | 60x | 
                              return(StanModule("base/link_none.stan"))
                     | 
                  
| 136 | 
                      }  | 
                  |
| 137 | ||
| 138 | 11x | 
                      keys <- vapply(  | 
                  
| 139 | 11x | 
                      object@components,  | 
                  
| 140 | 11x | 
                      function(x) x@key,  | 
                  
| 141 | 11x | 
                      character(1)  | 
                  
| 142 | 
                      )  | 
                  |
| 143 | ||
| 144 | 11x | 
                      base_stan <- StanModule(  | 
                  
| 145 | 11x | 
                      decorated_render(  | 
                  
| 146 | 11x | 
                                  .x = read_stan("base/link.stan"),
                     | 
                  
| 147 | 11x | 
                      items = as.list(keys)  | 
                  
| 148 | 
                      )  | 
                  |
| 149 | 
                      )  | 
                  |
| 150 | ||
| 151 | 11x | 
                      stan_list <- lapply(  | 
                  
| 152 | 11x | 
                      object@components,  | 
                  
| 153 | 11x | 
                      as.StanModule  | 
                  
| 154 | 
                      )  | 
                  |
| 155 | ||
| 156 | 11x | 
                      stan <- Reduce(  | 
                  
| 157 | 11x | 
                      merge,  | 
                  
| 158 | 11x | 
                      append(base_stan, stan_list)  | 
                  
| 159 | 
                      )  | 
                  |
| 160 | 11x | 
                      return(stan)  | 
                  
| 161 | 
                      }  | 
                  |
| 162 | ||
| 163 | ||
| 164 | ||
| 165 | ||
| 166 | 
                      #' `Link` -> `list`  | 
                  |
| 167 | 
                      #'  | 
                  |
| 168 | 
                      #' @inheritParams Link-Shared  | 
                  |
| 169 | 
                      #'  | 
                  |
| 170 | 
                      #' @description  | 
                  |
| 171 | 
                      #' Returns a named list where each element of the list corresponds  | 
                  |
| 172 | 
                      #' to a Stan modelling block e.g. `data`, `model`, etc.  | 
                  |
| 173 | 
                      #'  | 
                  |
| 174 | 
                      #' @family Link  | 
                  |
| 175 | 
                      #' @export  | 
                  |
| 176 | 
                      as.list.Link <- function(x, ...) {
                     | 
                  |
| 177 | 70x | 
                      as.list(as.StanModule(x, ...))  | 
                  
| 178 | 
                      }  | 
                  |
| 179 | ||
| 180 | ||
| 181 | ||
| 182 | 
                      #' @export  | 
                  |
| 183 | 
                      #' @rdname getParameters  | 
                  |
| 184 | 
                      getParameters.Link <- function(object, ...) {
                     | 
                  |
| 185 | 37x | 
                      parameters_list <- lapply(  | 
                  
| 186 | 37x | 
                      object@components,  | 
                  
| 187 | 37x | 
                      getParameters,  | 
                  
| 188 | 
                      ...  | 
                  |
| 189 | 
                      )  | 
                  |
| 190 | 37x | 
                      Reduce(  | 
                  
| 191 | 37x | 
                      merge,  | 
                  
| 192 | 37x | 
                      parameters_list  | 
                  
| 193 | 
                      )  | 
                  |
| 194 | 
                      }  | 
                  |
| 195 | ||
| 196 | ||
| 197 | 
                      #' @rdname initialValues  | 
                  |
| 198 | 
                      #' @export  | 
                  |
| 199 | 
                      initialValues.Link <- function(object, ...) {
                     | 
                  |
| 200 | ! | 
                      unlist(  | 
                  
| 201 | ! | 
                      lapply(object@components, initialValues),  | 
                  
| 202 | ! | 
                      recursive = FALSE  | 
                  
| 203 | 
                      )  | 
                  |
| 204 | 
                      }  | 
                  |
| 205 | ||
| 206 | ||
| 207 | 
                      #' `Link` -> `list`  | 
                  |
| 208 | 
                      #'  | 
                  |
| 209 | 
                      #' @inheritParams Link-Shared  | 
                  |
| 210 | 
                      #'  | 
                  |
| 211 | 
                      #' @description  | 
                  |
| 212 | 
                      #' Returns the number of link components within the [`Link`] object  | 
                  |
| 213 | 
                      #'  | 
                  |
| 214 | 
                      #' @family Link  | 
                  |
| 215 | 
                      #' @export  | 
                  |
| 216 | 
                      length.Link <- function(x) {
                     | 
                  |
| 217 | 77x | 
                      length(x@components)  | 
                  
| 218 | 
                      }  | 
                  |
| 219 | ||
| 220 | ||
| 221 | 
                      #' @export  | 
                  |
| 222 | 
                      as_print_string.Link <- function(object, ...) {
                     | 
                  |
| 223 | 2x | 
                          if (length(object) == 0) {
                     | 
                  
| 224 | 1x | 
                              return("\nNo Link")
                     | 
                  
| 225 | 
                      }  | 
                  |
| 226 | ||
| 227 | 1x | 
                      strings <- vapply(object@components, as_print_string, character(1))  | 
                  
| 228 | ||
| 229 | 1x | 
                      paste(  | 
                  
| 230 | 1x | 
                      c(  | 
                  
| 231 | 1x | 
                      "\nLink with the following components/parameters:",  | 
                  
| 232 | 1x | 
                                  paste0("    ", strings)
                     | 
                  
| 233 | 
                      ),  | 
                  |
| 234 | 1x | 
                      collapse = "\n"  | 
                  
| 235 | 
                      )  | 
                  |
| 236 | 
                      }  | 
                  |
| 237 | ||
| 238 | ||
| 239 | 
                      #' @rdname show-object  | 
                  |
| 240 | 
                      #' @export  | 
                  |
| 241 | 
                      setMethod(  | 
                  |
| 242 | 
                      f = "show",  | 
                  |
| 243 | 
                      signature = "Link",  | 
                  |
| 244 | 
                          definition = function(object) {
                     | 
                  |
| 245 | 1x | 
                      cat(paste0(as_print_string(object), "\n"))  | 
                  
| 246 | 
                      }  | 
                  |
| 247 | 
                      )  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include GridFixed.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | 
                      #' @rdname Grid-Dev  | 
                  |
| 7 | 
                      .GridGrouped <- setClass(  | 
                  |
| 8 | 
                      "GridGrouped",  | 
                  |
| 9 | 
                      contains = "Grid",  | 
                  |
| 10 | 
                      slots = c(  | 
                  |
| 11 | 
                      "groups" = "list",  | 
                  |
| 12 | 
                      "times" = "numeric_or_NULL"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | 
                      #' @rdname Grid-Functions  | 
                  |
| 17 | 
                      #' @export  | 
                  |
| 18 | 
                      GridGrouped <- function(groups, times = NULL) {
                     | 
                  |
| 19 | 13x | 
                      .GridGrouped(  | 
                  
| 20 | 13x | 
                      groups = groups,  | 
                  
| 21 | 13x | 
                      times = times  | 
                  
| 22 | 
                      )  | 
                  |
| 23 | 
                      }  | 
                  |
| 24 | ||
| 25 | ||
| 26 | 
                      setValidity(  | 
                  |
| 27 | 
                      "GridGrouped",  | 
                  |
| 28 | 
                          function(object) {
                     | 
                  |
| 29 | 
                              if (!all(vapply(object@groups, is.character, logical(1)))) {
                     | 
                  |
| 30 | 
                                  return("Each element of `groups` must be a character vector")
                     | 
                  |
| 31 | 
                      }  | 
                  |
| 32 | 
                      gnames <- names(object@groups)  | 
                  |
| 33 | 
                      gnames <- gnames[!is.na(gnames) & gnames != ""]  | 
                  |
| 34 | 
                              if (length(gnames) != length(object@groups)) {
                     | 
                  |
| 35 | 
                                  return("Each element of `groups` must be named")
                     | 
                  |
| 36 | 
                      }  | 
                  |
| 37 | 
                      return(TRUE)  | 
                  |
| 38 | 
                      }  | 
                  |
| 39 | 
                      )  | 
                  |
| 40 | ||
| 41 | ||
| 42 | 
                      #' @rdname Quant-Dev  | 
                  |
| 43 | 
                      #' @export  | 
                  |
| 44 | 
                      as.QuantityGenerator.GridGrouped <- function(object, data, ...) {
                     | 
                  |
| 45 | 17x | 
                      assert_class(data, "DataJoint")  | 
                  
| 46 | 17x | 
                      data_list <- as.list(data)  | 
                  
| 47 | 17x | 
                      subjects_unique <- unique(unlist(object@groups))  | 
                  
| 48 | 17x | 
                      assert_that(  | 
                  
| 49 | 17x | 
                      all(subjects_unique %in% names(data_list$subject_to_index))  | 
                  
| 50 | 
                      )  | 
                  |
| 51 | 17x | 
                      as.QuantityGenerator(  | 
                  
| 52 | 17x | 
                      GridFixed(  | 
                  
| 53 | 17x | 
                      times = object@times,  | 
                  
| 54 | 17x | 
                      subjects = subjects_unique  | 
                  
| 55 | 
                      ),  | 
                  |
| 56 | 17x | 
                      data = data  | 
                  
| 57 | 
                      )  | 
                  |
| 58 | 
                      }  | 
                  |
| 59 | ||
| 60 | ||
| 61 | 
                      #' @rdname Quant-Dev  | 
                  |
| 62 | 
                      #' @export  | 
                  |
| 63 | 
                      as.QuantityCollapser.GridGrouped <- function(object, data, ...) {
                     | 
                  |
| 64 | 8x | 
                      assert_class(data, "DataJoint")  | 
                  
| 65 | 8x | 
                      data_list <- as.list(data)  | 
                  
| 66 | 8x | 
                      assert_that(  | 
                  
| 67 | 8x | 
                      all(unique(unlist(object@groups)) %in% names(data_list$subject_to_index))  | 
                  
| 68 | 
                      )  | 
                  |
| 69 | ||
| 70 | 8x | 
                      validate_time_grid(object@times)  | 
                  
| 71 | ||
| 72 | 8x | 
                      group_grid <- expand.grid(  | 
                  
| 73 | 8x | 
                      group = names(object@groups),  | 
                  
| 74 | 8x | 
                      time = object@times,  | 
                  
| 75 | 8x | 
                      stringsAsFactors = FALSE  | 
                  
| 76 | 
                      )  | 
                  |
| 77 | ||
| 78 | 8x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 79 | ||
| 80 | 8x | 
                      select_indexes <- mapply(  | 
                  
| 81 | 8x | 
                              function(group, time) {
                     | 
                  
| 82 | 490x | 
                      correct_subject <- generator@subjects %in% object@groups[[group]]  | 
                  
| 83 | 490x | 
                      correct_time <- generator@times == time  | 
                  
| 84 | 490x | 
                      seq_along(correct_time)[correct_subject & correct_time]  | 
                  
| 85 | 
                      },  | 
                  |
| 86 | 8x | 
                      group_grid$group,  | 
                  
| 87 | 8x | 
                      group_grid$time,  | 
                  
| 88 | 8x | 
                      SIMPLIFY = FALSE  | 
                  
| 89 | 
                      )  | 
                  |
| 90 | 8x | 
                      names(select_indexes) <- NULL  | 
                  
| 91 | ||
| 92 | 8x | 
                      QuantityCollapser(  | 
                  
| 93 | 8x | 
                      times = group_grid$time,  | 
                  
| 94 | 8x | 
                      groups = group_grid$group,  | 
                  
| 95 | 8x | 
                      indexes = select_indexes  | 
                  
| 96 | 
                      )  | 
                  |
| 97 | 
                      }  | 
                  |
| 98 | ||
| 99 | 
                      #' @export  | 
                  |
| 100 | 
                      as.list.GridGrouped <- function(x, ...) {
                     | 
                  |
| 101 | 1x | 
                      x@groups  | 
                  
| 102 | 
                      }  | 
                  |
| 103 | ||
| 104 | 
                      #' @rdname coalesceGridTime  | 
                  |
| 105 | 
                      #' @export  | 
                  |
| 106 | 
                      coalesceGridTime.GridGrouped <- function(object, times, ...) {
                     | 
                  |
| 107 | 10x | 
                          if (is.null(object@times)) {
                     | 
                  
| 108 | 2x | 
                      object <- GridGrouped(  | 
                  
| 109 | 2x | 
                      groups = object@groups,  | 
                  
| 110 | 2x | 
                      times = times  | 
                  
| 111 | 
                      )  | 
                  |
| 112 | 
                      }  | 
                  |
| 113 | 10x | 
                      object  | 
                  
| 114 | 
                      }  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include generics.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | ||
| 6 | 
                      #' @rdname Grid-Dev  | 
                  |
| 7 | 
                      .GridPrediction <- setClass(  | 
                  |
| 8 | 
                      "GridPrediction",  | 
                  |
| 9 | 
                      contains = "Grid",  | 
                  |
| 10 | 
                      slots = c(  | 
                  |
| 11 | 
                      "times" = "numeric_or_NULL",  | 
                  |
| 12 | 
                      "newdata" = "data.frame",  | 
                  |
| 13 | 
                      "params" = "list"  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | 
                      #' @rdname Grid-Functions  | 
                  |
| 17 | 
                      #' @export  | 
                  |
| 18 | 
                      GridPrediction <- function(times = NULL, newdata, params = list()) {
                     | 
                  |
| 19 | 7x | 
                      .GridPrediction(  | 
                  
| 20 | 7x | 
                      times = times,  | 
                  
| 21 | 7x | 
                      params = params,  | 
                  
| 22 | 7x | 
                      newdata = newdata  | 
                  
| 23 | 
                      )  | 
                  |
| 24 | 
                      }  | 
                  |
| 25 | 
                      setValidity(  | 
                  |
| 26 | 
                      "GridPrediction",  | 
                  |
| 27 | 
                          function(object) {
                     | 
                  |
| 28 | 
                              for (param in names(object@params)) {
                     | 
                  |
| 29 | 
                                  if (length(object@params[[param]]) != 1) {
                     | 
                  |
| 30 | 
                                      return(sprintf("Parameter '%s' must be length 1", param))
                     | 
                  |
| 31 | 
                      }  | 
                  |
| 32 | 
                      }  | 
                  |
| 33 | 
                              if (length(object@params) != length(names(object@params))) {
                     | 
                  |
| 34 | 
                                  return("All elements of `params` must be named")
                     | 
                  |
| 35 | 
                      }  | 
                  |
| 36 | 
                              if (!is.null(object@newdata[["..new_subject.."]])) {
                     | 
                  |
| 37 | 
                                  return("`newdata` must not contain a column named '..new_subject..'")
                     | 
                  |
| 38 | 
                      }  | 
                  |
| 39 | 
                      return(TRUE)  | 
                  |
| 40 | 
                      }  | 
                  |
| 41 | 
                      )  | 
                  |
| 42 | ||
| 43 | ||
| 44 | 
                      #' @rdname Quant-Dev  | 
                  |
| 45 | 
                      #' @export  | 
                  |
| 46 | 
                      as.QuantityGenerator.GridPrediction <- function(object, data, ...) {
                     | 
                  |
| 47 | ||
| 48 | 6x | 
                      assert_class(data, "DataJoint")  | 
                  
| 49 | 6x | 
                      data_list <- as.list(data)  | 
                  
| 50 | 6x | 
                      validate_time_grid(object@times)  | 
                  
| 51 | ||
| 52 | 6x | 
                      n_times <- length(object@times)  | 
                  
| 53 | 6x | 
                      n_obs <- nrow(object@newdata)  | 
                  
| 54 | 6x | 
                      newdata <- object@newdata  | 
                  
| 55 | 6x | 
                      newdata[["..new_subject.."]] <- sprintf(  | 
                  
| 56 | 6x | 
                      "new_subject_%i",  | 
                  
| 57 | 6x | 
                      seq_len(nrow(newdata))  | 
                  
| 58 | 
                      )  | 
                  |
| 59 | ||
| 60 | 6x | 
                      QuantityGeneratorPrediction(  | 
                  
| 61 | 6x | 
                      times = rep(object@times, each = n_obs),  | 
                  
| 62 | 6x | 
                      newdata = replicate(newdata, n = n_times, simplify = FALSE) |> dplyr::bind_rows(),  | 
                  
| 63 | 6x | 
                      params = object@params  | 
                  
| 64 | 
                      )  | 
                  |
| 65 | 
                      }  | 
                  |
| 66 | ||
| 67 | 
                      #' @rdname Quant-Dev  | 
                  |
| 68 | 
                      #' @export  | 
                  |
| 69 | 
                      as.QuantityCollapser.GridPrediction <- function(object, data, ...) {
                     | 
                  |
| 70 | 2x | 
                      assert_class(data, "DataJoint")  | 
                  
| 71 | 2x | 
                      data_list <- as.list(data)  | 
                  
| 72 | 2x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 73 | 2x | 
                      QuantityCollapser(  | 
                  
| 74 | 2x | 
                      times = generator@times,  | 
                  
| 75 | 2x | 
                      groups = generator@newdata[["..new_subject.."]],  | 
                  
| 76 | 2x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 77 | 
                      )  | 
                  |
| 78 | 
                      }  | 
                  |
| 79 | ||
| 80 | ||
| 81 | 
                      #' @export  | 
                  |
| 82 | 
                      as.list.GridPrediction <- function(x, data, ...) {
                     | 
                  |
| 83 | ! | 
                          stop("`as.list()` is not implemented for `GridPrediction` objects")
                     | 
                  
| 84 | 
                      }  | 
                  |
| 85 | ||
| 86 | ||
| 87 | 
                      #' @rdname coalesceGridTime  | 
                  |
| 88 | 
                      #' @export  | 
                  |
| 89 | 
                      coalesceGridTime.GridPrediction <- function(object, times, ...) {
                     | 
                  |
| 90 | 4x | 
                          if (is.null(object@times)) {
                     | 
                  
| 91 | ! | 
                      object <- GridPrediction(  | 
                  
| 92 | ! | 
                      times = times,  | 
                  
| 93 | ! | 
                      newdata = object@newdata,  | 
                  
| 94 | ! | 
                      params = object@params  | 
                  
| 95 | 
                      )  | 
                  |
| 96 | 
                      }  | 
                  |
| 97 | 4x | 
                      object  | 
                  
| 98 | 
                      }  | 
                  
| 1 | 
                      #' @include DataSurvival.R  | 
                  |
| 2 | 
                      #' @include DataLongitudinal.R  | 
                  |
| 3 | 
                      #' @include DataSubject.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | 
                      #' Re-used documentation for `DataJoint`  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' @param object ([`DataJoint`]) \cr Survival and Longitudinal Data.  | 
                  |
| 10 | 
                      #' @param x ([`DataJoint`]) \cr Survival and Longitudinal Data.  | 
                  |
| 11 | 
                      #' @param ... Not Used.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @name DataJoint-Shared  | 
                  |
| 14 | 
                      #' @keywords internal  | 
                  |
| 15 | 
                      NULL  | 
                  |
| 16 | ||
| 17 | 
                      setClassUnion("DataLongitudinal_or_NULL", c("DataLongitudinal", "NULL"))
                     | 
                  |
| 18 | 
                      setClassUnion("DataSurvival_or_NULL", c("DataSurvival", "NULL"))
                     | 
                  |
| 19 | ||
| 20 | ||
| 21 | 
                      # DataJoint-class ----  | 
                  |
| 22 | ||
| 23 | 
                      #' @title  | 
                  |
| 24 | 
                      #' Joint Data Object and Constructor Function  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @description  | 
                  |
| 27 | 
                      #' The `DataJoint` class handles combining data from a [`DataSurvival`] object and a  | 
                  |
| 28 | 
                      #' [`DataLongitudinal`] object.  | 
                  |
| 29 | 
                      #'  | 
                  |
| 30 | 
                      #' @slot subject (`DataSubject`)\cr See Argument for details.  | 
                  |
| 31 | 
                      #' @slot survival (`DataSurvival`)\cr See Argument for details.  | 
                  |
| 32 | 
                      #' @slot longitudinal (`DataLongitudinal`)\cr See Argument for details.  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' @family DataObjects  | 
                  |
| 35 | 
                      #' @family DataJoint  | 
                  |
| 36 | 
                      #' @export DataJoint  | 
                  |
| 37 | 
                      #' @exportClass DataJoint  | 
                  |
| 38 | 
                      .DataJoint <- setClass(  | 
                  |
| 39 | 
                      Class = "DataJoint",  | 
                  |
| 40 | 
                      representation = list(  | 
                  |
| 41 | 
                      subject = "DataSubject",  | 
                  |
| 42 | 
                      survival = "DataSurvival_or_NULL",  | 
                  |
| 43 | 
                      longitudinal = "DataLongitudinal_or_NULL"  | 
                  |
| 44 | 
                      )  | 
                  |
| 45 | 
                      )  | 
                  |
| 46 | ||
| 47 | 
                      #' @param subject (`DataSubject`)\cr object created by [DataSubject()].  | 
                  |
| 48 | 
                      #' @param survival (`DataSurvival`)\cr object created by [DataSurvival()].  | 
                  |
| 49 | 
                      #' @param longitudinal (`DataLongitudinal`)\cr object created by [DataLongitudinal()].  | 
                  |
| 50 | 
                      #' @rdname DataJoint-class  | 
                  |
| 51 | 
                      DataJoint <- function(subject, survival = NULL, longitudinal = NULL) {
                     | 
                  |
| 52 | ||
| 53 | 32x | 
                      subject_suited <- harmonise(subject)  | 
                  
| 54 | 31x | 
                      vars <- extractVariableNames(subject)  | 
                  
| 55 | 31x | 
                      subject_var <- vars$subject  | 
                  
| 56 | 31x | 
                      subject_ord <- levels(as.data.frame(subject_suited)[[vars$subject]])  | 
                  
| 57 | ||
| 58 | 31x | 
                      survival_suited <- harmonise(  | 
                  
| 59 | 31x | 
                      survival,  | 
                  
| 60 | 31x | 
                      subject_var = subject_var,  | 
                  
| 61 | 31x | 
                      subject_ord = subject_ord  | 
                  
| 62 | 
                      )  | 
                  |
| 63 | ||
| 64 | 28x | 
                      longitudinal_suited <- harmonise(  | 
                  
| 65 | 28x | 
                      longitudinal,  | 
                  
| 66 | 28x | 
                      subject_var = subject_var,  | 
                  
| 67 | 28x | 
                      subject_ord = subject_ord  | 
                  
| 68 | 
                      )  | 
                  |
| 69 | ||
| 70 | 25x | 
                      .DataJoint(  | 
                  
| 71 | 25x | 
                      subject = subject_suited,  | 
                  
| 72 | 25x | 
                      survival = survival_suited,  | 
                  
| 73 | 25x | 
                      longitudinal = longitudinal_suited  | 
                  
| 74 | 
                      )  | 
                  |
| 75 | 
                      }  | 
                  |
| 76 | ||
| 77 | ||
| 78 | ||
| 79 | 
                      setValidity(  | 
                  |
| 80 | 
                      Class = "DataJoint",  | 
                  |
| 81 | 
                          method = function(object) {
                     | 
                  |
| 82 | 
                      vars <- extractVariableNames(object@subject)  | 
                  |
| 83 | 
                      subject_var <- vars$subject  | 
                  |
| 84 | 
                      subject_ord <- as.character(as.data.frame(object@subject)[[vars$subject]])  | 
                  |
| 85 | 
                              if (!is.null(object@survival)) {
                     | 
                  |
| 86 | 
                      survival_df <- as.data.frame(object@survival)  | 
                  |
| 87 | 
                                  if (!subject_var %in% names(survival_df)) {
                     | 
                  |
| 88 | 
                                      return(sprintf("Unable to find `%s` in `survival`", sujbect_var))
                     | 
                  |
| 89 | 
                      }  | 
                  |
| 90 | 
                                  if (!all(survival_df[[subject_var]] %in% subject_ord)) {
                     | 
                  |
| 91 | 
                                      return("There are subjects in `survival` that are not in `subject`")
                     | 
                  |
| 92 | 
                      }  | 
                  |
| 93 | 
                                  if (!nrow(survival_df) == length(unique(survival_df[[subject_var]]))) {
                     | 
                  |
| 94 | 
                                      return("There are duplicate subjects in `survival`")
                     | 
                  |
| 95 | 
                      }  | 
                  |
| 96 | 
                      }  | 
                  |
| 97 | 
                              if (!is.null(object@longitudinal)) {
                     | 
                  |
| 98 | 
                      long_df <- as.data.frame(object@longitudinal)  | 
                  |
| 99 | 
                                  if (!subject_var %in% names(long_df)) {
                     | 
                  |
| 100 | 
                                      return(sprintf("Unable to find `%s` in `longitudinal`", sujbect_var))
                     | 
                  |
| 101 | 
                      }  | 
                  |
| 102 | 
                                  if (!all(long_df[[subject_var]] %in% subject_ord)) {
                     | 
                  |
| 103 | 
                                      return("There are subjects in `longitudinal` that are not in `subject`")
                     | 
                  |
| 104 | 
                      }  | 
                  |
| 105 | 
                      }  | 
                  |
| 106 | 
                      subject_df <- as.data.frame(object@subject)  | 
                  |
| 107 | 
                              if (!subject_var %in% names(subject_df)) {
                     | 
                  |
| 108 | 
                                  return(sprintf("Unable to find `%s` in `subject`", sujbect_var))
                     | 
                  |
| 109 | 
                      }  | 
                  |
| 110 | 
                              if (!nrow(subject_df) == length(unique(subject_df[[subject_var]]))) {
                     | 
                  |
| 111 | 
                                  return("There are duplicate subjects in `subject`")
                     | 
                  |
| 112 | 
                      }  | 
                  |
| 113 | 
                      return(TRUE)  | 
                  |
| 114 | 
                      }  | 
                  |
| 115 | 
                      )  | 
                  |
| 116 | ||
| 117 | ||
| 118 | 
                      # DataJoint-as.list ----  | 
                  |
| 119 | ||
| 120 | ||
| 121 | ||
| 122 | ||
| 123 | 
                      #' Data Object -> `list`  | 
                  |
| 124 | 
                      #'  | 
                  |
| 125 | 
                      #' @param object (`DataSubject` or `DataLongitudinal` or `DataSurvival`) \cr  | 
                  |
| 126 | 
                      #' data object to convert to a `list`.  | 
                  |
| 127 | 
                      #' @param x (`DataSubject` or `DataLongitudinal` or `DataSurvival`) \cr  | 
                  |
| 128 | 
                      #' data object to convert to a `list`.  | 
                  |
| 129 | 
                      #' @param subject_var (`character`) \cr the name of the variable  | 
                  |
| 130 | 
                      #' containing the subject identifier.  | 
                  |
| 131 | 
                      #' @param ... not used.  | 
                  |
| 132 | 
                      #'  | 
                  |
| 133 | 
                      #' @description  | 
                  |
| 134 | 
                      #' Coerces a data object into a `list` of data components required  | 
                  |
| 135 | 
                      #' for fitting a [`JointModel`]. See the "Extending jmpost" vignette for more details.  | 
                  |
| 136 | 
                      #'  | 
                  |
| 137 | 
                      #' @name as_stan_list.DataObject  | 
                  |
| 138 | 
                      #' @family as_stan_list  | 
                  |
| 139 | 
                      #' @family DataJoint  | 
                  |
| 140 | 
                      #' @export  | 
                  |
| 141 | 
                      as_stan_list.DataJoint <- function(object, ...) {
                     | 
                  |
| 142 | 292x | 
                      vars <- extractVariableNames(object@subject)  | 
                  
| 143 | 292x | 
                      subject_var <- vars$subject  | 
                  
| 144 | 292x | 
                      as_stan_list(object@subject) |>  | 
                  
| 145 | 292x | 
                      append(as_stan_list(object@survival)) |>  | 
                  
| 146 | 292x | 
                      append(as_stan_list(  | 
                  
| 147 | 292x | 
                      object@longitudinal,  | 
                  
| 148 | 292x | 
                      subject_var = subject_var  | 
                  
| 149 | 
                      ))  | 
                  |
| 150 | 
                      }  | 
                  |
| 151 | ||
| 152 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 153 | 
                      #' @export  | 
                  |
| 154 | 
                      as.list.DataJoint <- function(x, ...) {
                     | 
                  |
| 155 | 241x | 
                      as_stan_list(x, ...)  | 
                  
| 156 | 
                      }  | 
                  |
| 157 | ||
| 158 | ||
| 159 | ||
| 160 | 
                      #' Subsetting `DataJoint` as a `data.frame`  | 
                  |
| 161 | 
                      #'  | 
                  |
| 162 | 
                      #' @param x (`DataJoint`) \cr object created by [DataJoint()].  | 
                  |
| 163 | 
                      #' @param subjects (`character` or `list`)\cr subjects that you wish to subset the `data.frame`  | 
                  |
| 164 | 
                      #' to contain. See details.  | 
                  |
| 165 | 
                      #' @param ... Not used.  | 
                  |
| 166 | 
                      #'  | 
                  |
| 167 | 
                      #' @description  | 
                  |
| 168 | 
                      #'  | 
                  |
| 169 | 
                      #' Coerces the object into a `data.frame` containing just event times and status  | 
                  |
| 170 | 
                      #' filtering for specific subjects If `subjects` is a list then an additional variable `group` will be added  | 
                  |
| 171 | 
                      #' onto the dataset specifying which group the row belongs to.  | 
                  |
| 172 | 
                      #'  | 
                  |
| 173 | 
                      #' @examples  | 
                  |
| 174 | 
                      #' \dontrun{
                     | 
                  |
| 175 | 
                      #' subjects <- c("SUB1", "SUB2", "SUB3", "SUB4")
                     | 
                  |
| 176 | 
                      #' subset(x, subjects)  | 
                  |
| 177 | 
                      #'  | 
                  |
| 178 | 
                      #' groups <- list(  | 
                  |
| 179 | 
                      #'     "g1" = c("SUB1", "SUB3", "SUB4"),
                     | 
                  |
| 180 | 
                      #'     "g2" = c("SUB2", "SUB3")
                     | 
                  |
| 181 | 
                      #' )  | 
                  |
| 182 | 
                      #' subset(x, groups)  | 
                  |
| 183 | 
                      #' }  | 
                  |
| 184 | 
                      #' @family DataJoint  | 
                  |
| 185 | 
                      #' @export  | 
                  |
| 186 | 
                      subset.DataJoint <- function(x, subjects, ...) {
                     | 
                  |
| 187 | 2x | 
                      data <- as.list(x)  | 
                  
| 188 | 2x | 
                      dat <- data.frame(  | 
                  
| 189 | 2x | 
                      time = data[["event_times"]],  | 
                  
| 190 | 2x | 
                      event = as.numeric(seq_along(data[["event_times"]]) %in% data[["subject_event_index"]]),  | 
                  
| 191 | 2x | 
                      subject = names(data[["subject_to_index"]])  | 
                  
| 192 | 
                      )  | 
                  |
| 193 | 2x | 
                      subset_and_add_grouping(dat, subjects)  | 
                  
| 194 | 
                      }  | 
                  |
| 195 | ||
| 196 | ||
| 197 | ||
| 198 | 
                      #' `subset_and_add_grouping`  | 
                  |
| 199 | 
                      #'  | 
                  |
| 200 | 
                      #' @param dat (`data.frame`) \cr must have a column called `subject` which corresponds to the  | 
                  |
| 201 | 
                      #' values passed to `groupings`.  | 
                  |
| 202 | 
                      #' @param groupings (`character` or `list`)\cr subjects that you wish to subset the dataset  | 
                  |
| 203 | 
                      #' to contain. If `groupings` is a list then an additional variable `group` will be added  | 
                  |
| 204 | 
                      #' onto the dataset specifying which group the row belongs to.  | 
                  |
| 205 | 
                      #'  | 
                  |
| 206 | 
                      #' @details  | 
                  |
| 207 | 
                      #' Example of usage  | 
                  |
| 208 | 
                      #' ```  | 
                  |
| 209 | 
                      #' subjects <- c("SUB1", "SUB2", "SUB3", "SUB4")
                     | 
                  |
| 210 | 
                      #' subset_and_add_grouping(dat, subjects)  | 
                  |
| 211 | 
                      #'  | 
                  |
| 212 | 
                      #' groups <- list(  | 
                  |
| 213 | 
                      #'     "g1" = c("SUB1", "SUB3", "SUB4"),
                     | 
                  |
| 214 | 
                      #'     "g2" = c("SUB2", "SUB3")
                     | 
                  |
| 215 | 
                      #' )  | 
                  |
| 216 | 
                      #' subset_and_add_grouping(dat, groups)  | 
                  |
| 217 | 
                      #' ```  | 
                  |
| 218 | 
                      #'  | 
                  |
| 219 | 
                      #' @keywords internal  | 
                  |
| 220 | 
                      subset_and_add_grouping <- function(dat, groupings) {
                     | 
                  |
| 221 | 8x | 
                      groupings <- decompose_subjects(groupings, dat$subject)$groups  | 
                  
| 222 | 5x | 
                      dat_subset_list <- lapply(  | 
                  
| 223 | 5x | 
                      seq_along(groupings),  | 
                  
| 224 | 5x | 
                              \(i) {
                     | 
                  
| 225 | 13x | 
                      dat_reduced <- dat[dat$subject %in% groupings[[i]], , drop = FALSE]  | 
                  
| 226 | 13x | 
                      dat_reduced[["group"]] <- names(groupings)[[i]]  | 
                  
| 227 | 13x | 
                      dat_reduced  | 
                  
| 228 | 
                      }  | 
                  |
| 229 | 
                      )  | 
                  |
| 230 | 5x | 
                      x <- Reduce(rbind, dat_subset_list)  | 
                  
| 231 | 5x | 
                      row.names(x) <- NULL  | 
                  
| 232 | 5x | 
                      x  | 
                  
| 233 | 
                      }  | 
                  |
| 234 | ||
| 235 | ||
| 236 | 
                      #' Extract Observed Longitudinal Values  | 
                  |
| 237 | 
                      #'  | 
                  |
| 238 | 
                      #' Utility function to extract the observed longitudinal values from a [`DataJoint`] object  | 
                  |
| 239 | 
                      #' @param object ([`DataJoint`])\cr data used to fit a [`JointModel`].  | 
                  |
| 240 | 
                      #' @return A data.frame with the following columns  | 
                  |
| 241 | 
                      #' - `subject` (`character`)\cr The subject identifier  | 
                  |
| 242 | 
                      #' - `time` (`numeric`)\cr The time at which the observation occurred  | 
                  |
| 243 | 
                      #' - `Yob` (`numeric`)\cr The observed value  | 
                  |
| 244 | 
                      #' @keywords internal  | 
                  |
| 245 | 
                      extract_observed_values <- function(object) {
                     | 
                  |
| 246 | 2x | 
                      assert_class(object, "DataJoint")  | 
                  
| 247 | 2x | 
                      data <- as.list(object)  | 
                  
| 248 | 2x | 
                      x <- data.frame(  | 
                  
| 249 | 2x | 
                      subject = names(data$subject_to_index)[data$subject_tumour_index],  | 
                  
| 250 | 2x | 
                      time = data$tumour_time,  | 
                  
| 251 | 2x | 
                      Yob = data$tumour_value  | 
                  
| 252 | 
                      )  | 
                  |
| 253 | 2x | 
                      row.names(x) <- NULL  | 
                  
| 254 | 2x | 
                      x  | 
                  
| 255 | 
                      }  | 
                  |
| 256 | ||
| 257 | 
                      #' @rdname show-object  | 
                  |
| 258 | 
                      #' @export  | 
                  |
| 259 | 
                      setMethod(  | 
                  |
| 260 | 
                      f = "show",  | 
                  |
| 261 | 
                      signature = "DataJoint",  | 
                  |
| 262 | 
                          definition = function(object) {
                     | 
                  |
| 263 | 1x | 
                              string_survival <- if (is.null(object@survival)) {
                     | 
                  
| 264 | ! | 
                      " Survival-Data Object:\n Not Specified"  | 
                  
| 265 | 
                              } else {
                     | 
                  |
| 266 | 1x | 
                      as_print_string(object@survival, indent = 5)  | 
                  
| 267 | 
                      }  | 
                  |
| 268 | ||
| 269 | 1x | 
                              string_longitudinal <- if (is.null(object@longitudinal)) {
                     | 
                  
| 270 | ! | 
                      " Longitudinal-Data Object:\n Not Specified"  | 
                  
| 271 | 
                              } else {
                     | 
                  |
| 272 | 1x | 
                      as_print_string(object@longitudinal, indent = 5)  | 
                  
| 273 | 
                      }  | 
                  |
| 274 | ||
| 275 | 1x | 
                      template <- c(  | 
                  
| 276 | 1x | 
                      "Joint-Data Object Containing:",  | 
                  
| 277 | 
                      "",  | 
                  |
| 278 | 1x | 
                      as_print_string(object@subject, indent = 5),  | 
                  
| 279 | 
                      "",  | 
                  |
| 280 | 1x | 
                      string_survival,  | 
                  
| 281 | 
                      "",  | 
                  |
| 282 | 1x | 
                      string_longitudinal  | 
                  
| 283 | 
                      )  | 
                  |
| 284 | 1x | 
                              cat("\n", paste(template, collapse = "\n"), "\n\n")
                     | 
                  
| 285 | 
                      }  | 
                  |
| 286 | 
                      )  | 
                  
| 1 | ||
| 2 | 
                      #' Re-used documentation for `Quantities`  | 
                  |
| 3 | 
                      #'  | 
                  |
| 4 | 
                      #' @param x ([`Quantities`]) \cr generated quantities.  | 
                  |
| 5 | 
                      #' @param object ([`Quantities`]) \cr generated quantities.  | 
                  |
| 6 | 
                      #' @param type (`character`)\cr sets the `type` variable.  | 
                  |
| 7 | 
                      #' @param conf.level (`numeric`) \cr confidence level of the interval.  | 
                  |
| 8 | 
                      #' @param ... not used.  | 
                  |
| 9 | 
                      #'  | 
                  |
| 10 | 
                      #' @keywords internal  | 
                  |
| 11 | 
                      #' @name Quantities-Shared  | 
                  |
| 12 | 
                      NULL  | 
                  |
| 13 | ||
| 14 | ||
| 15 | 
                      #' Generated Quantities Container  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' A simple wrapper around a `matrix` to store required metadata  | 
                  |
| 18 | 
                      #'  | 
                  |
| 19 | 
                      #' @param quantities (`matrix`)\cr of generated quantities.  | 
                  |
| 20 | 
                      #' @param times (`numeric`)\cr labels specifying which time point the quantity was generated at.  | 
                  |
| 21 | 
                      #' @param groups (`character`)\cr labels for which group the quantity belongs to.  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #' @slot quantities (`matrix`)\cr See Arguments for details.  | 
                  |
| 24 | 
                      #' @slot times (`numeric`)\cr See Arguments for details.  | 
                  |
| 25 | 
                      #' @slot groups (`character`)\cr See Arguments for details.  | 
                  |
| 26 | 
                      #'  | 
                  |
| 27 | 
                      #' @details  | 
                  |
| 28 | 
                      #' Each row of the matrix represents a sample and each column represents a distinct quantity.  | 
                  |
| 29 | 
                      #' As such the number of columns in the matrix should equal the length of `times` and `groups`  | 
                  |
| 30 | 
                      #' which provide metadata for who the quantity belongs to and at what time point it was generated at.  | 
                  |
| 31 | 
                      #'  | 
                  |
| 32 | 
                      #' @keywords internal  | 
                  |
| 33 | 
                      #' @name Quantities-class  | 
                  |
| 34 | 
                      #' @family Quantities  | 
                  |
| 35 | 
                      .Quantities <- setClass(  | 
                  |
| 36 | 
                      "Quantities",  | 
                  |
| 37 | 
                      slots = list(  | 
                  |
| 38 | 
                      "quantities" = "matrix",  | 
                  |
| 39 | 
                      "times" = "numeric",  | 
                  |
| 40 | 
                      "groups" = "character"  | 
                  |
| 41 | 
                      )  | 
                  |
| 42 | 
                      )  | 
                  |
| 43 | 
                      #' @rdname Quantities-class  | 
                  |
| 44 | 
                      Quantities <- function(quantities, times, groups) {
                     | 
                  |
| 45 | 34x | 
                      .Quantities(  | 
                  
| 46 | 34x | 
                      quantities = quantities,  | 
                  
| 47 | 34x | 
                      times = times,  | 
                  
| 48 | 34x | 
                      groups = groups  | 
                  
| 49 | 
                      )  | 
                  |
| 50 | 
                      }  | 
                  |
| 51 | ||
| 52 | 
                      setValidity(  | 
                  |
| 53 | 
                      Class = "Quantities",  | 
                  |
| 54 | 
                          method = function(object) {
                     | 
                  |
| 55 | 
                              if (length(object@times) != length(object@groups)) {
                     | 
                  |
| 56 | 
                                  return("Length of `times` must be equal to the length of `groups`")
                     | 
                  |
| 57 | 
                      }  | 
                  |
| 58 | 
                              if (length(object@times) != ncol(object@quantities)) {
                     | 
                  |
| 59 | 
                                  return("Length of `times` must be equal to the number of columns in `quantities`")
                     | 
                  |
| 60 | 
                      }  | 
                  |
| 61 | 
                      return(TRUE)  | 
                  |
| 62 | 
                      }  | 
                  |
| 63 | 
                      )  | 
                  |
| 64 | ||
| 65 | ||
| 66 | ||
| 67 | 
                      #' @export  | 
                  |
| 68 | 
                      dim.Quantities <- function(x) {
                     | 
                  |
| 69 | 9x | 
                      dim(x@quantities)  | 
                  
| 70 | 
                      }  | 
                  |
| 71 | ||
| 72 | ||
| 73 | 
                      #' `Quantities` -> `data.frame`  | 
                  |
| 74 | 
                      #'  | 
                  |
| 75 | 
                      #' @inheritParams Quantities-Shared  | 
                  |
| 76 | 
                      #'  | 
                  |
| 77 | 
                      #' @keywords internal  | 
                  |
| 78 | 
                      #' @family Quantities  | 
                  |
| 79 | 
                      #' @export  | 
                  |
| 80 | 
                      as.data.frame.Quantities <- function(x, ...) {
                     | 
                  |
| 81 | 2x | 
                      data.frame(  | 
                  
| 82 | 2x | 
                      group = rep(x@groups, each = nrow(x@quantities)),  | 
                  
| 83 | 2x | 
                      time = rep(x@times, each = nrow(x@quantities)),  | 
                  
| 84 | 2x | 
                      values = as.vector(x@quantities)  | 
                  
| 85 | 
                      )  | 
                  |
| 86 | 
                      }  | 
                  |
| 87 | ||
| 88 | ||
| 89 | 
                      #' summary  | 
                  |
| 90 | 
                      #'  | 
                  |
| 91 | 
                      #' @description  | 
                  |
| 92 | 
                      #' This method returns a summary statistic `data.frame` of the quantities. Note that this  | 
                  |
| 93 | 
                      #' is just an internal utility method in order to share common code between  | 
                  |
| 94 | 
                      #' [LongitudinalQuantities] and [SurvivalQuantities]  | 
                  |
| 95 | 
                      #'  | 
                  |
| 96 | 
                      #' @inheritParams Quantities-Shared  | 
                  |
| 97 | 
                      #'  | 
                  |
| 98 | 
                      #' @returns  | 
                  |
| 99 | 
                      #' A `data.frame` with the following variables:  | 
                  |
| 100 | 
                      #' - `median` (`numeric`) \cr the median value of the quantity.  | 
                  |
| 101 | 
                      #' - `lower` (`numeric`) \cr the lower CI value of the quantity.  | 
                  |
| 102 | 
                      #' - `upper` (`numeric`) \cr the upper CI value of the quantity.  | 
                  |
| 103 | 
                      #' - `time` (`numeric`) \cr the time point which the quantity is for.  | 
                  |
| 104 | 
                      #' - `group` (`character`) \cr which group the quantity belongs to.  | 
                  |
| 105 | 
                      #' - `type` (`character`) \cr what type of quantity is it.  | 
                  |
| 106 | 
                      #'  | 
                  |
| 107 | 
                      #' @keywords internal  | 
                  |
| 108 | 
                      #' @family Quantities  | 
                  |
| 109 | 
                      #' @export  | 
                  |
| 110 | 
                      summary.Quantities <- function(object, conf.level = 0.95, ...) {
                     | 
                  |
| 111 | 32x | 
                      quantities_summarised <- samples_median_ci(  | 
                  
| 112 | 32x | 
                      object@quantities,  | 
                  
| 113 | 32x | 
                      level = conf.level  | 
                  
| 114 | 
                      )  | 
                  |
| 115 | ||
| 116 | 32x | 
                      quantities_summarised$group <- object@groups  | 
                  
| 117 | 32x | 
                      quantities_summarised$time <- object@times  | 
                  
| 118 | 32x | 
                          quantities_summarised[, c("group", "time", "median", "lower", "upper")]
                     | 
                  
| 119 | 
                      }  | 
                  |
| 120 | ||
| 121 | ||
| 122 | ||
| 123 | 
                      #' Create Grouped Quantities  | 
                  |
| 124 | 
                      #'  | 
                  |
| 125 | 
                      #' This function takes a matrix of quantity samples and aggregates them by calculating the  | 
                  |
| 126 | 
                      #' pointwise average.  | 
                  |
| 127 | 
                      #'  | 
                  |
| 128 | 
                      #' @param quantities_raw (`matrix`)\cr of samples with 1 row per sample and 1 column per  | 
                  |
| 129 | 
                      #' distinct quantity.  | 
                  |
| 130 | 
                      #'  | 
                  |
| 131 | 
                      #' @param collapser ([`QuantityCollapser`])\cr specifies which columns to combine together.  | 
                  |
| 132 | 
                      #'  | 
                  |
| 133 | 
                      #' @details  | 
                  |
| 134 | 
                      #' This function essentially implements the group wise average by collapsing multiple columns  | 
                  |
| 135 | 
                      #' together based on the specification provided by the `QuantityCollapser` object.  | 
                  |
| 136 | 
                      #' The [Grid-Dev] page provides an example of what this function implements  | 
                  |
| 137 | 
                      #'  | 
                  |
| 138 | 
                      #' @keywords internal  | 
                  |
| 139 | 
                      collapse_quantities <- function(quantities_raw, collapser) {
                     | 
                  |
| 140 | 34x | 
                      assert_class(quantities_raw, "matrix")  | 
                  
| 141 | 34x | 
                      assert_class(collapser, "QuantityCollapser")  | 
                  
| 142 | ||
| 143 | 34x | 
                      quantities <- matrix(  | 
                  
| 144 | 34x | 
                      NA,  | 
                  
| 145 | 34x | 
                      nrow = nrow(quantities_raw),  | 
                  
| 146 | 34x | 
                      ncol = length(collapser)  | 
                  
| 147 | 
                      )  | 
                  |
| 148 | ||
| 149 | 34x | 
                          for (idx in seq_len(length(collapser))) {
                     | 
                  
| 150 | 12704x | 
                      quantities[, idx] <- quantities_raw[  | 
                  
| 151 | 
                      ,  | 
                  |
| 152 | 12704x | 
                      collapser@indexes[[idx]],  | 
                  
| 153 | 12704x | 
                      drop = FALSE  | 
                  
| 154 | 12704x | 
                      ] |> rowMeans()  | 
                  
| 155 | 
                      }  | 
                  |
| 156 | ||
| 157 | 34x | 
                      return(quantities)  | 
                  
| 158 | 
                      }  | 
                  |
| 159 | ||
| 160 | 
                      #' Extract Survival Quantities  | 
                  |
| 161 | 
                      #'  | 
                  |
| 162 | 
                      #' Utility function to extract generated quantities from a [cmdstanr::CmdStanGQ] object.  | 
                  |
| 163 | 
                      #' Multiple quantities are generated by default so this is a convenience function to extract  | 
                  |
| 164 | 
                      #' the desired ones and return them them as a user friendly [posterior::draws_matrix] object  | 
                  |
| 165 | 
                      #'  | 
                  |
| 166 | 
                      #' @param gq (`CmdStanGQ`) \cr a [cmdstanr::CmdStanGQ] object created by [generateQuantities()].  | 
                  |
| 167 | 
                      #' @param type (`character`)\cr quantity to be generated.  | 
                  |
| 168 | 
                      #' Must be one of `surv`, `haz`, `loghaz`, `cumhaz`, `lm_identity`.  | 
                  |
| 169 | 
                      #' @keywords internal  | 
                  |
| 170 | 
                      extract_quantities <- function(gq, type = c("surv", "haz", "loghaz", "cumhaz", "lm_identity")) {
                     | 
                  |
| 171 | 35x | 
                      type <- match.arg(type)  | 
                  
| 172 | 35x | 
                      assert_class(gq, "CmdStanGQ")  | 
                  
| 173 | 35x | 
                      meta <- switch(type,  | 
                  
| 174 | 35x | 
                              surv = list("log_surv_fit_at_time_grid", exp),
                     | 
                  
| 175 | 35x | 
                              cumhaz = list("log_surv_fit_at_time_grid", \(x) -x),
                     | 
                  
| 176 | 35x | 
                              haz = list("log_haz_fit_at_time_grid", exp),
                     | 
                  
| 177 | 35x | 
                              loghaz = list("log_haz_fit_at_time_grid", identity),
                     | 
                  
| 178 | 35x | 
                              lm_identity = list("y_fit_at_time_grid", identity)
                     | 
                  
| 179 | 
                      )  | 
                  |
| 180 | 35x | 
                      result <- gq$draws(meta[[1]], format = "draws_matrix")  | 
                  
| 181 | 35x | 
                      result_transformed <- meta[[2]](result)  | 
                  
| 182 | 35x | 
                      cnames <- colnames(result_transformed)  | 
                  
| 183 | 35x | 
                      colnames(result_transformed) <- gsub(meta[[1]], "quantity", cnames)  | 
                  
| 184 | 35x | 
                      result_transformed  | 
                  
| 185 | 
                      }  | 
                  |
| 186 | ||
| 187 | ||
| 188 | 
                      #' `Quantities` -> Printable `Character`  | 
                  |
| 189 | 
                      #'  | 
                  |
| 190 | 
                      #' Converts [`Quantities`] object into a printable string.  | 
                  |
| 191 | 
                      #' @inheritParams Quantities-Shared  | 
                  |
| 192 | 
                      #' @family Quantities  | 
                  |
| 193 | 
                      #' @keywords internal  | 
                  |
| 194 | 
                      #' @export  | 
                  |
| 195 | 
                      as_print_string.Quantities <- function(object, indent = 1, ...) {
                     | 
                  |
| 196 | 1x | 
                      template <- c(  | 
                  
| 197 | 1x | 
                      "Quantities Object:",  | 
                  
| 198 | 1x | 
                      " # of samples = %d",  | 
                  
| 199 | 1x | 
                      " # of quantities = %d"  | 
                  
| 200 | 
                      )  | 
                  |
| 201 | 1x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 202 | 1x | 
                      template_padded <- paste(pad, template)  | 
                  
| 203 | 1x | 
                      sprintf(  | 
                  
| 204 | 1x | 
                      paste(template_padded, collapse = "\n"),  | 
                  
| 205 | 1x | 
                      nrow(object),  | 
                  
| 206 | 1x | 
                      ncol(object)  | 
                  
| 207 | 
                      )  | 
                  |
| 208 | 
                      }  | 
                  |
| 209 | ||
| 210 | ||
| 211 | 
                      #' @rdname show-object  | 
                  |
| 212 | 
                      #' @export  | 
                  |
| 213 | 
                      setMethod(  | 
                  |
| 214 | 
                      f = "show",  | 
                  |
| 215 | 
                      signature = "Quantities",  | 
                  |
| 216 | 
                          definition = function(object) {
                     | 
                  |
| 217 | 1x | 
                      string <- as_print_string(object)  | 
                  
| 218 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 219 | 
                      }  | 
                  |
| 220 | 
                      )  | 
                  
| 1 | ||
| 2 | 
                      #' `SimSurvival` Function Arguments  | 
                  |
| 3 | 
                      #'  | 
                  |
| 4 | 
                      #' The documentation lists all the conventional arguments for [`SimSurvival`]  | 
                  |
| 5 | 
                      #' constructors.  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' @param time_max (`number`)\cr the maximum time to simulate to.  | 
                  |
| 8 | 
                      #' @param time_step (`number`)\cr the time interval between evaluating the log-hazard function.  | 
                  |
| 9 | 
                      #' @param lambda_censor (`number`)\cr the censoring rate.  | 
                  |
| 10 | 
                      #' @param beta_cont (`number`)\cr the continuous covariate coefficient.  | 
                  |
| 11 | 
                      #' @param beta_cat (`numeric`)\cr the categorical covariate coefficients.  | 
                  |
| 12 | 
                      #' @param loghazard (`function`)\cr the log hazard function.  | 
                  |
| 13 | 
                      #' @param name (`character`)\cr the name of the object.  | 
                  |
| 14 | 
                      #' @param ... Not Used.  | 
                  |
| 15 | 
                      #'  | 
                  |
| 16 | 
                      #' @section Hazard Evaluation:  | 
                  |
| 17 | 
                      #'  | 
                  |
| 18 | 
                      #' Event times are simulated by sampling a cumulative hazard limit from a \eqn{U(0, 1)} distribution
                     | 
                  |
| 19 | 
                      #' for  | 
                  |
| 20 | 
                      #' each subject and then counting how much hazard they've been exposed to by evaluating the  | 
                  |
| 21 | 
                      #' log-hazard function at a set interval. The `time_max` argument sets the upper bound for the  | 
                  |
| 22 | 
                      #' number of time points to evaluate the log-hazard function at with subjects who have not had an  | 
                  |
| 23 | 
                      #' event being censored at `time_max`. The `time_step` argument sets the interval at which to  | 
                  |
| 24 | 
                      #' evaluate the log-hazard function. Setting smaller values for `time_step` will increase the  | 
                  |
| 25 | 
                      #' precision of the simulation at the cost of increased computation time. Likewise, setting large  | 
                  |
| 26 | 
                      #' values for `time_max` will minimize the number of censored subjects at the cost of  | 
                  |
| 27 | 
                      #' increased computation time.  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @name SimSurvival-Shared  | 
                  |
| 30 | 
                      #' @keywords internal  | 
                  |
| 31 | 
                      NULL  | 
                  |
| 32 | ||
| 33 | ||
| 34 | 
                      #' Abstract Simulation Class for Survival Data  | 
                  |
| 35 | 
                      #'  | 
                  |
| 36 | 
                      #' @inheritParams SimSurvival-Shared  | 
                  |
| 37 | 
                      #' @inheritSection SimSurvival-Shared Hazard Evaluation  | 
                  |
| 38 | 
                      #'  | 
                  |
| 39 | 
                      #' @slot time_max (`numeric`)\cr See arguments.  | 
                  |
| 40 | 
                      #' @slot time_step (`numeric`)\cr See arguments.  | 
                  |
| 41 | 
                      #' @slot lambda_censor (`numeric`)\cr See arguments.  | 
                  |
| 42 | 
                      #' @slot beta_cont (`numeric`)\cr See arguments.  | 
                  |
| 43 | 
                      #' @slot beta_cat (`numeric`)\cr See arguments.  | 
                  |
| 44 | 
                      #' @slot loghazard (`function`)\cr See arguments.  | 
                  |
| 45 | 
                      #' @slot name (`character`)\cr See arguments.  | 
                  |
| 46 | 
                      #'  | 
                  |
| 47 | 
                      #' @family SimSurvival  | 
                  |
| 48 | 
                      #' @exportClass SimSurvival  | 
                  |
| 49 | 
                      #' @name SimSurvival-class  | 
                  |
| 50 | 
                      .SimSurvival <- setClass(  | 
                  |
| 51 | 
                      "SimSurvival",  | 
                  |
| 52 | 
                      slots = c(  | 
                  |
| 53 | 
                      time_max = "numeric",  | 
                  |
| 54 | 
                      time_step = "numeric",  | 
                  |
| 55 | 
                      lambda_censor = "numeric",  | 
                  |
| 56 | 
                      beta_cont = "numeric",  | 
                  |
| 57 | 
                      beta_cat = "numeric",  | 
                  |
| 58 | 
                      loghazard = "function",  | 
                  |
| 59 | 
                      name = "character"  | 
                  |
| 60 | 
                      )  | 
                  |
| 61 | 
                      )  | 
                  |
| 62 | ||
| 63 | 
                      #' @rdname SimSurvival-class  | 
                  |
| 64 | 
                      #' @export  | 
                  |
| 65 | 
                      SimSurvival <- function(  | 
                  |
| 66 | 
                      time_max = 2000,  | 
                  |
| 67 | 
                      time_step = 1,  | 
                  |
| 68 | 
                      lambda_censor = 1 / 3000,  | 
                  |
| 69 | 
                      beta_cont = 0.2,  | 
                  |
| 70 | 
                          beta_cat = c("A" = 0, "B" = -0.4, "C" = 0.2),
                     | 
                  |
| 71 | 
                      loghazard,  | 
                  |
| 72 | 
                      name = "SimSurvival"  | 
                  |
| 73 | 
                      ) {
                     | 
                  |
| 74 | 24x | 
                      .SimSurvival(  | 
                  
| 75 | 24x | 
                      time_max = time_max,  | 
                  
| 76 | 24x | 
                      time_step = time_step,  | 
                  
| 77 | 24x | 
                      lambda_censor = lambda_censor,  | 
                  
| 78 | 24x | 
                      beta_cont = beta_cont,  | 
                  
| 79 | 24x | 
                      beta_cat = beta_cat,  | 
                  
| 80 | 24x | 
                      loghazard = loghazard,  | 
                  
| 81 | 24x | 
                      name = name  | 
                  
| 82 | 
                      )  | 
                  |
| 83 | 
                      }  | 
                  |
| 84 | ||
| 85 | ||
| 86 | 
                      #' @rdname show-object  | 
                  |
| 87 | 
                      #' @export  | 
                  |
| 88 | 
                      setMethod(  | 
                  |
| 89 | 
                      f = "show",  | 
                  |
| 90 | 
                      signature = "SimSurvival",  | 
                  |
| 91 | 
                          definition = function(object) {
                     | 
                  |
| 92 | 1x | 
                              x <- sprintf("\nA %s Object\n\n", as_print_string(object))
                     | 
                  
| 93 | 1x | 
                      cat(x)  | 
                  
| 94 | 1x | 
                      return(object)  | 
                  
| 95 | 
                      }  | 
                  |
| 96 | 
                      )  | 
                  |
| 97 | ||
| 98 | 
                      #' @rdname as_print_string  | 
                  |
| 99 | 
                      as_print_string.SimSurvival <- function(object) {
                     | 
                  |
| 100 | 1x | 
                      return(object@name)  | 
                  
| 101 | 
                      }  | 
                  |
| 102 | ||
| 103 | ||
| 104 | 
                      #' Construct Time Intervals  | 
                  |
| 105 | 
                      #'  | 
                  |
| 106 | 
                      #' @param object (`SimSurvival`)\cr the survival simulation object to create evaluation points for.  | 
                  |
| 107 | 
                      #'  | 
                  |
| 108 | 
                      #' @return A `tibble` with `lower`, `upper`, `time`, `eval` and `width`.  | 
                  |
| 109 | 
                      #' @keywords internal  | 
                  |
| 110 | 
                      hazardWindows.SimSurvival <- function(object) {
                     | 
                  |
| 111 | 22x | 
                      times <- seq(0, object@time_max, object@time_step)  | 
                  
| 112 | 22x | 
                      bound_lower <- times[-length(times)]  | 
                  
| 113 | 22x | 
                      bound_upper <- times[-1]  | 
                  
| 114 | 22x | 
                      bound_width <- bound_upper - bound_lower  | 
                  
| 115 | 22x | 
                      mid_point <- bound_upper - (bound_width / 2)  | 
                  
| 116 | 22x | 
                      tibble::tibble(  | 
                  
| 117 | 22x | 
                      lower = bound_lower,  | 
                  
| 118 | 22x | 
                      upper = bound_upper,  | 
                  
| 119 | 22x | 
                      midpoint = mid_point,  | 
                  
| 120 | 22x | 
                      width = bound_width  | 
                  
| 121 | 
                      )  | 
                  |
| 122 | 
                      }  | 
                  |
| 123 | ||
| 124 | 
                      #' @rdname sampleSubjects  | 
                  |
| 125 | 
                      #' @export  | 
                  |
| 126 | 
                      sampleSubjects.SimSurvival <- function(object, subjects_df) {
                     | 
                  |
| 127 | 22x | 
                      subjects_df |>  | 
                  
| 128 | 22x | 
                      dplyr::mutate(cov_cont = stats::rnorm(dplyr::n())) |>  | 
                  
| 129 | 22x | 
                      dplyr::mutate(cov_cat = factor(  | 
                  
| 130 | 22x | 
                      sample(names(object@beta_cat), replace = TRUE, size = dplyr::n()),  | 
                  
| 131 | 22x | 
                      levels = names(object@beta_cat)  | 
                  
| 132 | 
                      )) |>  | 
                  |
| 133 | 22x | 
                      dplyr::mutate(log_haz_cov = .data$cov_cont * object@beta_cont + object@beta_cat[.data$cov_cat]) |>  | 
                  
| 134 | 22x | 
                      dplyr::mutate(survival = stats::runif(dplyr::n())) |>  | 
                  
| 135 | 22x | 
                      dplyr::mutate(chazard_limit = -log(.data$survival)) |>  | 
                  
| 136 | 22x | 
                      dplyr::mutate(time_cen = stats::rexp(dplyr::n(), object@lambda_censor))  | 
                  
| 137 | 
                      }  | 
                  |
| 138 | ||
| 139 | ||
| 140 | 
                      #' @rdname sampleObservations  | 
                  |
| 141 | 
                      #' @export  | 
                  |
| 142 | 
                      sampleObservations.SimSurvival <- function(object, times_df) {
                     | 
                  |
| 143 | ||
| 144 | 22x | 
                      assert_that(  | 
                  
| 145 | 22x | 
                      all(times_df$time >= 0),  | 
                  
| 146 | 22x | 
                      msg = "All time points must be greater than or equal to 0"  | 
                  
| 147 | 
                      )  | 
                  |
| 148 | ||
| 149 | 22x | 
                      os_dat_chaz <- times_df |>  | 
                  
| 150 | 22x | 
                      dplyr::mutate(log_bl_haz = object@loghazard(.data$midpoint)) |>  | 
                  
| 151 | 
                      # Fix to avoid issue with log(0) = NaN values  | 
                  |
| 152 | 22x | 
                      dplyr::mutate(log_bl_haz = dplyr::if_else(.data$midpoint == 0, -999, .data$log_bl_haz)) |>  | 
                  
| 153 | 22x | 
                      dplyr::mutate(hazard_instant = exp(.data$log_bl_haz + .data$log_haz_cov + .data$log_haz_link)) |>  | 
                  
| 154 | 
                      # Reset Inf values to large number to avoid NaN issues downstream  | 
                  |
| 155 | 
                      # This is suitable as Hazard limits tend to be in the range of -10 to 10 so large numbers  | 
                  |
| 156 | 
                      # are essentially equivalent to infinity for simulation purposes  | 
                  |
| 157 | 22x | 
                      dplyr::mutate(hazard_instant = dplyr::if_else(.data$hazard_instant == Inf, 999, .data$hazard_instant)) |>  | 
                  
| 158 | 22x | 
                      dplyr::mutate(hazard_instant = dplyr::if_else(.data$hazard_instant == -Inf, -999, .data$hazard_instant)) |>  | 
                  
| 159 | 22x | 
                      dplyr::mutate(hazard_interval = .data$hazard_instant * .data$width) |>  | 
                  
| 160 | 22x | 
                      dplyr::group_by(.data$subject) |>  | 
                  
| 161 | 22x | 
                      dplyr::mutate(chazard = cumsum(.data$hazard_interval)) |>  | 
                  
| 162 | 22x | 
                      dplyr::ungroup()  | 
                  
| 163 | ||
| 164 | 22x | 
                      os_had_event <- os_dat_chaz |>  | 
                  
| 165 | 22x | 
                      dplyr::filter(.data$chazard >= .data$chazard_limit) |>  | 
                  
| 166 | 22x | 
                      dplyr::group_by(.data$subject) |>  | 
                  
| 167 | 22x | 
                      dplyr::slice(1) |>  | 
                  
| 168 | 22x | 
                      dplyr::ungroup() |>  | 
                  
| 169 | 22x | 
                      dplyr::mutate(event = 1)  | 
                  
| 170 | ||
| 171 | 22x | 
                      os_had_censor <- os_dat_chaz |>  | 
                  
| 172 | 22x | 
                      dplyr::filter(!.data$subject %in% os_had_event$subject) |>  | 
                  
| 173 | 22x | 
                      dplyr::group_by(.data$subject) |>  | 
                  
| 174 | 22x | 
                      dplyr::slice(dplyr::n()) |>  | 
                  
| 175 | 22x | 
                      dplyr::ungroup() |>  | 
                  
| 176 | 22x | 
                      dplyr::mutate(event = 0)  | 
                  
| 177 | ||
| 178 | 22x | 
                          if (!(nrow(os_had_censor) == 0)) {
                     | 
                  
| 179 | 10x | 
                              message(sprintf("INFO: %i subjects did not die before max(times)", nrow(os_had_censor)))
                     | 
                  
| 180 | 
                      }  | 
                  |
| 181 | ||
| 182 | 22x | 
                      os_dat_complete <- os_had_event |>  | 
                  
| 183 | 22x | 
                      dplyr::bind_rows(os_had_censor) |>  | 
                  
| 184 | 22x | 
                      dplyr::mutate(real_time = .data$time) |>  | 
                  
| 185 | 22x | 
                      dplyr::mutate(event = dplyr::if_else(.data$real_time <= .data$time_cen, .data$event, 0)) |>  | 
                  
| 186 | 22x | 
                      dplyr::mutate(time = dplyr::if_else(.data$real_time <= .data$time_cen, .data$real_time, .data$time_cen)) |>  | 
                  
| 187 | 22x | 
                      dplyr::arrange(.data$subject)  | 
                  
| 188 | ||
| 189 | 22x | 
                          os_dat_complete[, c("subject", "study", "arm", "time", "event", "cov_cont", "cov_cat")]
                     | 
                  
| 190 | 
                      }  | 
                  |
| 191 | ||
| 192 | ||
| 193 | 
                      #' Simulate Survival Data from a Weibull Proportional Hazard Model  | 
                  |
| 194 | 
                      #'  | 
                  |
| 195 | 
                      #' @param lambda (`number`)\cr the scale parameter.  | 
                  |
| 196 | 
                      #' @param gamma (`number`)\cr the shape parameter.  | 
                  |
| 197 | 
                      #'  | 
                  |
| 198 | 
                      #' @inheritParams SimSurvival-Shared  | 
                  |
| 199 | 
                      #' @inheritSection SimSurvival-Shared Hazard Evaluation  | 
                  |
| 200 | 
                      #'  | 
                  |
| 201 | 
                      #' @family SimSurvival  | 
                  |
| 202 | 
                      #'  | 
                  |
| 203 | 
                      #' @export  | 
                  |
| 204 | 
                      SimSurvivalWeibullPH <- function(  | 
                  |
| 205 | 
                      lambda,  | 
                  |
| 206 | 
                      gamma,  | 
                  |
| 207 | 
                      time_max = 2000,  | 
                  |
| 208 | 
                      time_step = 1,  | 
                  |
| 209 | 
                      lambda_censor = 1 / 3000,  | 
                  |
| 210 | 
                      beta_cont = 0.2,  | 
                  |
| 211 | 
                          beta_cat = c("A" = 0, "B" = -0.4, "C" = 0.2)
                     | 
                  |
| 212 | 
                      ) {
                     | 
                  |
| 213 | 4x | 
                      SimSurvival(  | 
                  
| 214 | 4x | 
                      time_max = time_max,  | 
                  
| 215 | 4x | 
                      time_step = time_step,  | 
                  
| 216 | 4x | 
                      lambda_censor = lambda_censor,  | 
                  
| 217 | 4x | 
                      beta_cont = beta_cont,  | 
                  
| 218 | 4x | 
                      beta_cat = beta_cat,  | 
                  
| 219 | 4x | 
                              loghazard = function(time) {
                     | 
                  
| 220 | 4x | 
                      log(lambda) + log(gamma) + (gamma - 1) * log(time)  | 
                  
| 221 | 
                      },  | 
                  |
| 222 | 4x | 
                      name = "SimSurvivalWeibullPH"  | 
                  
| 223 | 
                      )  | 
                  |
| 224 | 
                      }  | 
                  |
| 225 | ||
| 226 | 
                      #' Simulate Survival Data from a Log-Logistic Proportional Hazard Model  | 
                  |
| 227 | 
                      #'  | 
                  |
| 228 | 
                      #' @param a (`number`)\cr the scale parameter.  | 
                  |
| 229 | 
                      #' @param b (`number`)\cr the shape parameter.  | 
                  |
| 230 | 
                      #'  | 
                  |
| 231 | 
                      #' @inheritParams SimSurvival-Shared  | 
                  |
| 232 | 
                      #' @inheritSection SimSurvival-Shared Hazard Evaluation  | 
                  |
| 233 | 
                      #'  | 
                  |
| 234 | 
                      #' @family SimSurvival  | 
                  |
| 235 | 
                      #' @export  | 
                  |
| 236 | 
                      SimSurvivalLogLogistic <- function(  | 
                  |
| 237 | 
                      a,  | 
                  |
| 238 | 
                      b,  | 
                  |
| 239 | 
                      time_max = 2000,  | 
                  |
| 240 | 
                      time_step = 1,  | 
                  |
| 241 | 
                      lambda_censor = 1 / 3000,  | 
                  |
| 242 | 
                      beta_cont = 0.2,  | 
                  |
| 243 | 
                          beta_cat = c("A" = 0, "B" = -0.4, "C" = 0.2)
                     | 
                  |
| 244 | 
                      ) {
                     | 
                  |
| 245 | 2x | 
                      SimSurvival(  | 
                  
| 246 | 2x | 
                      time_max = time_max,  | 
                  
| 247 | 2x | 
                      time_step = time_step,  | 
                  
| 248 | 2x | 
                      lambda_censor = lambda_censor,  | 
                  
| 249 | 2x | 
                      beta_cont = beta_cont,  | 
                  
| 250 | 2x | 
                      beta_cat = beta_cat,  | 
                  
| 251 | 2x | 
                              loghazard = function(time) {
                     | 
                  
| 252 | 2x | 
                      c1 <- - log(a) + log(b) + (b - 1) * (- log(a) + log(time))  | 
                  
| 253 | 2x | 
                      c2 <- log(1 + (time / a)^b)  | 
                  
| 254 | 2x | 
                      return(c1 - c2)  | 
                  
| 255 | 
                      },  | 
                  |
| 256 | 2x | 
                      name = "SimSurvivalLogLogistic"  | 
                  
| 257 | 
                      )  | 
                  |
| 258 | 
                      }  | 
                  |
| 259 | ||
| 260 | ||
| 261 | ||
| 262 | 
                      #' Simulate Survival Data from a Exponential Proportional Hazard Model  | 
                  |
| 263 | 
                      #'  | 
                  |
| 264 | 
                      #' @param lambda (`number`)\cr the rate parameter.  | 
                  |
| 265 | 
                      #'  | 
                  |
| 266 | 
                      #' @inheritParams SimSurvival-Shared  | 
                  |
| 267 | 
                      #' @inheritSection SimSurvival-Shared Hazard Evaluation  | 
                  |
| 268 | 
                      #'  | 
                  |
| 269 | 
                      #' @family SimSurvival  | 
                  |
| 270 | 
                      #'  | 
                  |
| 271 | 
                      #' @export  | 
                  |
| 272 | 
                      SimSurvivalExponential <- function(  | 
                  |
| 273 | 
                      lambda,  | 
                  |
| 274 | 
                      time_max = 2000,  | 
                  |
| 275 | 
                      time_step = 1,  | 
                  |
| 276 | 
                      lambda_censor = 1 / 3000,  | 
                  |
| 277 | 
                      beta_cont = 0.2,  | 
                  |
| 278 | 
                          beta_cat = c("A" = 0, "B" = -0.4, "C" = 0.2)
                     | 
                  |
| 279 | 
                      ) {
                     | 
                  |
| 280 | 17x | 
                      SimSurvival(  | 
                  
| 281 | 17x | 
                      time_max = time_max,  | 
                  
| 282 | 17x | 
                      time_step = time_step,  | 
                  
| 283 | 17x | 
                      lambda_censor = lambda_censor,  | 
                  
| 284 | 17x | 
                      beta_cont = beta_cont,  | 
                  
| 285 | 17x | 
                      beta_cat = beta_cat,  | 
                  
| 286 | 17x | 
                              loghazard = function(time) {
                     | 
                  
| 287 | 17x | 
                      log(lambda)  | 
                  
| 288 | 
                      },  | 
                  |
| 289 | 17x | 
                      name = "SimSurvivalExponential"  | 
                  
| 290 | 
                      )  | 
                  |
| 291 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include DataJoint.R  | 
                  |
| 3 | 
                      #' @include Quantities.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | 
                      #' Re-used documentation for `LongitudinalQuantities`  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' @param x ([`LongitudinalQuantities`]) \cr longitudinal quantities.  | 
                  |
| 10 | 
                      #' @param object ([`LongitudinalQuantities`]) \cr longitudinal quantities.  | 
                  |
| 11 | 
                      #' @param ... not used.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @keywords internal  | 
                  |
| 14 | 
                      #' @name LongitudinalQuantities-Shared  | 
                  |
| 15 | 
                      NULL  | 
                  |
| 16 | ||
| 17 | ||
| 18 | 
                      #' `LongitudinalQuantities` Object & Constructor Function  | 
                  |
| 19 | 
                      #'  | 
                  |
| 20 | 
                      #' Constructor function to generate a `LongitudinalQuantities` object.  | 
                  |
| 21 | 
                      #'  | 
                  |
| 22 | 
                      #' @details  | 
                  |
| 23 | 
                      #' Note that unlike [`SurvivalQuantities`], [`LongitudinalQuantities`] does not support  | 
                  |
| 24 | 
                      #' group aggregation.  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @slot quantities (`Quantities`)\cr The sampled quantities. Should contain 1 element per  | 
                  |
| 27 | 
                      #' element of `group`  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @slot data (`DataJoint`)\cr Survival and Longitudinal Data.  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @family LongitudinalQuantities  | 
                  |
| 32 | 
                      #' @name LongitudinalQuantities-class  | 
                  |
| 33 | 
                      #' @export LongitudinalQuantities  | 
                  |
| 34 | 
                      .LongitudinalQuantities <- setClass(  | 
                  |
| 35 | 
                      "LongitudinalQuantities",  | 
                  |
| 36 | 
                      slots = c(  | 
                  |
| 37 | 
                      "quantities" = "Quantities",  | 
                  |
| 38 | 
                      "data" = "DataJoint"  | 
                  |
| 39 | 
                      )  | 
                  |
| 40 | 
                      )  | 
                  |
| 41 | ||
| 42 | 
                      #' @param object ([`JointModelSamples`]) \cr samples as drawn from a Joint Model.  | 
                  |
| 43 | 
                      #'  | 
                  |
| 44 | 
                      #' @param grid (`Grid`) \cr object that specifies which subjects and time points to calculate the  | 
                  |
| 45 | 
                      #' quantities for. See [Grid-Functions].  | 
                  |
| 46 | 
                      #' @rdname LongitudinalQuantities-class  | 
                  |
| 47 | 
                      LongitudinalQuantities <- function(  | 
                  |
| 48 | 
                      object,  | 
                  |
| 49 | 
                      grid  | 
                  |
| 50 | 
                      ) {
                     | 
                  |
| 51 | 13x | 
                      assert_class(object, "JointModelSamples")  | 
                  
| 52 | 13x | 
                      assert_class(grid, "Grid")  | 
                  
| 53 | 13x | 
                      assert_that(  | 
                  
| 54 | 13x | 
                      !is(grid, "GridPrediction"),  | 
                  
| 55 | 13x | 
                      msg = "`GridPrediction` objects are not supported for `LongitudinalQuantities`"  | 
                  
| 56 | 
                      )  | 
                  |
| 57 | ||
| 58 | 13x | 
                      time_grid <- seq(  | 
                  
| 59 | 13x | 
                      from = 0,  | 
                  
| 60 | 13x | 
                      to = max(as.list(object@data)[["tumour_time"]]),  | 
                  
| 61 | 13x | 
                      length = 201  | 
                  
| 62 | 
                      )  | 
                  |
| 63 | ||
| 64 | 13x | 
                      grid <- coalesceGridTime(grid, time_grid)  | 
                  
| 65 | ||
| 66 | 13x | 
                      gq <- generateQuantities(  | 
                  
| 67 | 13x | 
                      object,  | 
                  
| 68 | 13x | 
                      generator = as.QuantityGenerator(grid, object@data),  | 
                  
| 69 | 13x | 
                      type = "longitudinal"  | 
                  
| 70 | 
                      )  | 
                  |
| 71 | ||
| 72 | 13x | 
                      quantities_raw <- extract_quantities(gq, type = "lm_identity")  | 
                  
| 73 | ||
| 74 | 13x | 
                      collapser <- as.QuantityCollapser(grid, object@data)  | 
                  
| 75 | 13x | 
                      quantities <- collapse_quantities(quantities_raw, collapser)  | 
                  
| 76 | ||
| 77 | 13x | 
                      .LongitudinalQuantities(  | 
                  
| 78 | 13x | 
                      quantities = Quantities(  | 
                  
| 79 | 13x | 
                      quantities,  | 
                  
| 80 | 13x | 
                      groups = collapser@groups,  | 
                  
| 81 | 13x | 
                      times = collapser@times  | 
                  
| 82 | 
                      ),  | 
                  |
| 83 | 13x | 
                      data = object@data  | 
                  
| 84 | 
                      )  | 
                  |
| 85 | 
                      }  | 
                  |
| 86 | ||
| 87 | ||
| 88 | ||
| 89 | 
                      #' `as.data.frame`  | 
                  |
| 90 | 
                      #'  | 
                  |
| 91 | 
                      #' @param x ([`LongitudinalQuantities`]) \cr longitudinal quantities.  | 
                  |
| 92 | 
                      #' @param ... not used.  | 
                  |
| 93 | 
                      #' @family LongitudinalQuantities  | 
                  |
| 94 | 
                      #' @export  | 
                  |
| 95 | 
                      as.data.frame.LongitudinalQuantities <- function(x, ...) {
                     | 
                  |
| 96 | 1x | 
                      as.data.frame(x@quantities)  | 
                  
| 97 | 
                      }  | 
                  |
| 98 | ||
| 99 | ||
| 100 | ||
| 101 | 
                      #' summary  | 
                  |
| 102 | 
                      #'  | 
                  |
| 103 | 
                      #' @description  | 
                  |
| 104 | 
                      #' This method returns a `data.frame` of the longitudinal quantities.  | 
                  |
| 105 | 
                      #'  | 
                  |
| 106 | 
                      #' @param conf.level (`numeric`) \cr confidence level of the interval.  | 
                  |
| 107 | 
                      #' @inheritParams LongitudinalQuantities-Shared  | 
                  |
| 108 | 
                      #'  | 
                  |
| 109 | 
                      #' @family LongitudinalQuantities  | 
                  |
| 110 | 
                      #' @family summary  | 
                  |
| 111 | 
                      #' @export  | 
                  |
| 112 | 
                      summary.LongitudinalQuantities <- function(  | 
                  |
| 113 | 
                      object,  | 
                  |
| 114 | 
                      conf.level = 0.95,  | 
                  |
| 115 | 
                      ...  | 
                  |
| 116 | 
                      ) {
                     | 
                  |
| 117 | 12x | 
                      summary(object@quantities, conf.level = conf.level)  | 
                  
| 118 | 
                      }  | 
                  |
| 119 | ||
| 120 | ||
| 121 | 
                      #' Longitudinal Plot  | 
                  |
| 122 | 
                      #'  | 
                  |
| 123 | 
                      #' Internal plotting function to create longitudinal plots  | 
                  |
| 124 | 
                      #' This function predominately exists to extract core logic into its own function  | 
                  |
| 125 | 
                      #' to enable easier unit testing.  | 
                  |
| 126 | 
                      #'  | 
                  |
| 127 | 
                      #' @param data (`data.frame`)\cr summary statistics for longitudinal  | 
                  |
| 128 | 
                      #' value estimates. See details.  | 
                  |
| 129 | 
                      #' @param data_obs (`data.frame`)\cr real observed values to be  | 
                  |
| 130 | 
                      #' overlaid for reference. See details.  | 
                  |
| 131 | 
                      #' @param add_ci (`logical`)\cr Should confidence intervals be added? Default = `TRUE`.  | 
                  |
| 132 | 
                      #' @details  | 
                  |
| 133 | 
                      #'  | 
                  |
| 134 | 
                      #' ## `data`  | 
                  |
| 135 | 
                      #' Should contain the following columns:  | 
                  |
| 136 | 
                      #' - `time` (`numeric`) \cr time point for the summary statistic.  | 
                  |
| 137 | 
                      #' - `group` (`character`) \cr the group in which the observation belongs to.  | 
                  |
| 138 | 
                      #' - `median` (`numeric`) \cr the median value for the summary statistic.  | 
                  |
| 139 | 
                      #' - `upper` (`numeric`) \cr the upper 95% CI for the summary statistic.  | 
                  |
| 140 | 
                      #' - `lower` (`numeric`) \cr the lower 95% CI for the summary statistic.  | 
                  |
| 141 | 
                      #'  | 
                  |
| 142 | 
                      #' ## `data_obs`  | 
                  |
| 143 | 
                      #' Should contain the following columns:  | 
                  |
| 144 | 
                      #' - `time` (`numeric`) \cr the time at which the observed value occurred.  | 
                  |
| 145 | 
                      #' - `Yob` (`numeric`) \cr the real observed value.  | 
                  |
| 146 | 
                      #' - `group` (`character`) \cr which group the event belongs to, should correspond to  | 
                  |
| 147 | 
                      #' values in `data$group`.  | 
                  |
| 148 | 
                      #' @keywords internal  | 
                  |
| 149 | 
                      longitudinal_plot <- function(  | 
                  |
| 150 | 
                      data,  | 
                  |
| 151 | 
                      data_obs = NULL,  | 
                  |
| 152 | 
                      add_ci = FALSE  | 
                  |
| 153 | 
                      ) {
                     | 
                  |
| 154 | 3x | 
                      p <- ggplot() +  | 
                  
| 155 | 3x | 
                      geom_line(aes(x = .data$time, y = .data$median), data = data) +  | 
                  
| 156 | 3x | 
                      xlab(expression(t)) +  | 
                  
| 157 | 3x | 
                      ylab(expression(y)) +  | 
                  
| 158 | 3x | 
                      facet_wrap(~group) +  | 
                  
| 159 | 3x | 
                      theme_bw()  | 
                  
| 160 | ||
| 161 | 3x | 
                          if (add_ci) {
                     | 
                  
| 162 | 2x | 
                      p <- p + geom_ribbon(  | 
                  
| 163 | 2x | 
                      aes(x = .data$time, ymin = .data$lower, ymax = .data$upper),  | 
                  
| 164 | 2x | 
                      data = data,  | 
                  
| 165 | 2x | 
                      alpha = 0.3  | 
                  
| 166 | 
                      )  | 
                  |
| 167 | 
                      }  | 
                  |
| 168 | ||
| 169 | 3x | 
                          if (!is.null(data_obs)) {
                     | 
                  
| 170 | 3x | 
                      p <- p + geom_point(aes(x = .data$time, y = .data$Yob), data = data_obs)  | 
                  
| 171 | 
                      }  | 
                  |
| 172 | 3x | 
                      return(p)  | 
                  
| 173 | 
                      }  | 
                  |
| 174 | ||
| 175 | ||
| 176 | 
                      #' Automatic Plotting for `LongitudinalQuantities`  | 
                  |
| 177 | 
                      #'  | 
                  |
| 178 | 
                      #' @param conf.level (`numeric`) \cr confidence level of the interval. If values of `FALSE`,  | 
                  |
| 179 | 
                      #' `NULL` or `0` are provided then confidence regions will not be added to the plot.  | 
                  |
| 180 | 
                      #' @inheritParams LongitudinalQuantities-Shared  | 
                  |
| 181 | 
                      #'  | 
                  |
| 182 | 
                      #' @family LongitudinalQuantities  | 
                  |
| 183 | 
                      #' @family autoplot  | 
                  |
| 184 | 
                      #' @export  | 
                  |
| 185 | 
                      autoplot.LongitudinalQuantities <- function(object, conf.level = 0.95, ...) {
                     | 
                  |
| 186 | 2x | 
                      include_ci <- !is.null(conf.level) && is.numeric(conf.level) && conf.level > 0  | 
                  
| 187 | 
                      # If CI aren't needed supply a default 0.95 to summary function as it needs  | 
                  |
| 188 | 
                      # a value to be specified to work.  | 
                  |
| 189 | 2x | 
                      conf.level <- if (include_ci) conf.level else 0.95  | 
                  
| 190 | 2x | 
                      data_sum <- summary(object, conf.level = conf.level)  | 
                  
| 191 | 2x | 
                      data_obs <- extract_observed_values(object@data)  | 
                  
| 192 | 2x | 
                      assert_that(  | 
                  
| 193 | 2x | 
                      "group" %in% names(data_sum),  | 
                  
| 194 | 2x | 
                      "subject" %in% names(data_obs)  | 
                  
| 195 | 
                      )  | 
                  |
| 196 | 2x | 
                      data_obs$group <- data_obs$subject  | 
                  
| 197 | 2x | 
                      data_obs <- data_obs[data_obs$group %in% data_sum$group, ]  | 
                  
| 198 | 2x | 
                      longitudinal_plot(  | 
                  
| 199 | 2x | 
                      data = data_sum,  | 
                  
| 200 | 2x | 
                      data_obs = data_obs,  | 
                  
| 201 | 2x | 
                      add_ci = include_ci  | 
                  
| 202 | 
                      )  | 
                  |
| 203 | 
                      }  | 
                  |
| 204 | ||
| 205 | ||
| 206 | ||
| 207 | 
                      #' @rdname show-object  | 
                  |
| 208 | 
                      #' @export  | 
                  |
| 209 | 
                      setMethod(  | 
                  |
| 210 | 
                      f = "show",  | 
                  |
| 211 | 
                      signature = "LongitudinalQuantities",  | 
                  |
| 212 | 
                          definition = function(object) {
                     | 
                  |
| 213 | 1x | 
                      template <- c(  | 
                  
| 214 | 1x | 
                      "LongitudinalQuantities Object:",  | 
                  
| 215 | 1x | 
                      " # of samples = %d",  | 
                  
| 216 | 1x | 
                      " # of quantities = %d"  | 
                  
| 217 | 
                      )  | 
                  |
| 218 | 1x | 
                      string <- sprintf(  | 
                  
| 219 | 1x | 
                      paste(template, collapse = "\n"),  | 
                  
| 220 | 1x | 
                      nrow(object@quantities),  | 
                  
| 221 | 1x | 
                      ncol(object@quantities)  | 
                  
| 222 | 
                      )  | 
                  |
| 223 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 224 | 
                      }  | 
                  |
| 225 | 
                      )  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include generics.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' @rdname Grid-Dev  | 
                  |
| 6 | 
                      .GridObserved <- setClass(  | 
                  |
| 7 | 
                      "GridObserved",  | 
                  |
| 8 | 
                      contains = "Grid",  | 
                  |
| 9 | 
                      slots = c(  | 
                  |
| 10 | 
                      "subjects" = "character_or_NULL"  | 
                  |
| 11 | 
                      )  | 
                  |
| 12 | 
                      )  | 
                  |
| 13 | ||
| 14 | ||
| 15 | 
                      #' @rdname Grid-Functions  | 
                  |
| 16 | 
                      #' @export  | 
                  |
| 17 | 
                      GridObserved <- function(subjects = NULL) {
                     | 
                  |
| 18 | 2x | 
                      .GridObserved(  | 
                  
| 19 | 2x | 
                      subjects = subjects  | 
                  
| 20 | 
                      )  | 
                  |
| 21 | 
                      }  | 
                  |
| 22 | ||
| 23 | 
                      #' @rdname Quant-Dev  | 
                  |
| 24 | 
                      #' @export  | 
                  |
| 25 | 
                      as.QuantityGenerator.GridObserved <- function(object, data, ...) {
                     | 
                  |
| 26 | 4x | 
                      assert_class(data, "DataJoint")  | 
                  
| 27 | 4x | 
                      data_list <- as.list(data)  | 
                  
| 28 | 4x | 
                      subjects <- unlist(as.list(object, data = data), use.names = FALSE)  | 
                  
| 29 | 4x | 
                      unique_visits <- tapply(data_list$tumour_time, data_list$subject_tumour_index, unique)  | 
                  
| 30 | 4x | 
                      subject_visits <- unique_visits[data_list$subject_to_index[subjects]]  | 
                  
| 31 | 4x | 
                      visit_lengths <- vapply(subject_visits, length, numeric(1))  | 
                  
| 32 | 4x | 
                      QuantityGeneratorSubject(  | 
                  
| 33 | 4x | 
                      times = unlist(subject_visits, use.names = FALSE),  | 
                  
| 34 | 4x | 
                      subjects = rep(subjects, visit_lengths)  | 
                  
| 35 | 
                      )  | 
                  |
| 36 | 
                      }  | 
                  |
| 37 | ||
| 38 | 
                      #' @rdname Quant-Dev  | 
                  |
| 39 | 
                      #' @export  | 
                  |
| 40 | 
                      as.QuantityCollapser.GridObserved <- function(object, data, ...) {
                     | 
                  |
| 41 | 2x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 42 | ||
| 43 | 2x | 
                      QuantityCollapser(  | 
                  
| 44 | 2x | 
                      times = generator@times,  | 
                  
| 45 | 2x | 
                      groups = generator@subjects,  | 
                  
| 46 | 2x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 47 | 
                      )  | 
                  |
| 48 | 
                      }  | 
                  |
| 49 | ||
| 50 | 
                      #' @export  | 
                  |
| 51 | 
                      as.list.GridObserved <- function(x, data, ...) {
                     | 
                  |
| 52 | 4x | 
                      subjects_to_list(x@subjects, data)  | 
                  
| 53 | 
                      }  | 
                  
| 1 | 
                      #' @include JointModel.R  | 
                  |
| 2 | 
                      #' @include SurvivalQuantities.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      setOldClass("CmdStanMCMC")
                     | 
                  |
| 6 | ||
| 7 | 
                      # JointModelSamples-class ----  | 
                  |
| 8 | ||
| 9 | 
                      #' `JointModelSamples`  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' Contains samples from a [`JointModel`].  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @slot model ([`JointModel`])\cr the model that the samples were drawn from.  | 
                  |
| 14 | 
                      #' @slot data ([`DataJoint`])\cr the data that the model was fitted on.  | 
                  |
| 15 | 
                      #' @slot results ([`cmdstanr::CmdStanMCMC`])\cr the STAN samples.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @aliases JointModelSamples  | 
                  |
| 18 | 
                      #' @export  | 
                  |
| 19 | 
                      .JointModelSamples <- setClass(  | 
                  |
| 20 | 
                      "JointModelSamples",  | 
                  |
| 21 | 
                      slots = c(  | 
                  |
| 22 | 
                      model = "JointModel",  | 
                  |
| 23 | 
                      data = "DataJoint",  | 
                  |
| 24 | 
                      results = "CmdStanMCMC"  | 
                  |
| 25 | 
                      )  | 
                  |
| 26 | 
                      )  | 
                  |
| 27 | ||
| 28 | ||
| 29 | 
                      #' @rdname generateQuantities  | 
                  |
| 30 | 
                      #' @param generator (`QuantityGenerator`)\cr object that specifies which subjects and time points  | 
                  |
| 31 | 
                      #' to calculate the quantities at  | 
                  |
| 32 | 
                      #' @param type (`character`)\cr type of quantities to be generated, must be either "survival" or  | 
                  |
| 33 | 
                      #' "longitudinal".  | 
                  |
| 34 | 
                      #' @export  | 
                  |
| 35 | 
                      generateQuantities.JointModelSamples <- function(object, generator, type, ...) {
                     | 
                  |
| 36 | ||
| 37 | 31x | 
                      data <- as_stan_list(object@data) |>  | 
                  
| 38 | 31x | 
                      append(as_stan_list(object@model@parameters)) |>  | 
                  
| 39 | 31x | 
                      append(as_stan_list(generator, data = object@data, model = object@model))  | 
                  
| 40 | ||
| 41 | 30x | 
                      stanobj <- as.StanModule(object, generator = generator, type = type)  | 
                  
| 42 | 30x | 
                      model <- compileStanModel(stanobj)  | 
                  
| 43 | ||
| 44 | 30x | 
                      devnull <- utils::capture.output(  | 
                  
| 45 | 30x | 
                      results <- model$generate_quantities(  | 
                  
| 46 | 30x | 
                      data = data,  | 
                  
| 47 | 30x | 
                      fitted_params = object@results  | 
                  
| 48 | 
                      )  | 
                  |
| 49 | 
                      )  | 
                  |
| 50 | 30x | 
                      return(results)  | 
                  
| 51 | 
                      }  | 
                  |
| 52 | ||
| 53 | ||
| 54 | 
                      #' `JointModelSamples` -> `StanModule`  | 
                  |
| 55 | 
                      #'  | 
                  |
| 56 | 
                      #' Converts a `JointModelSamples` object into a `StanModule` object ensuring  | 
                  |
| 57 | 
                      #' that the resulting `StanModule` object is able to generate post sampling  | 
                  |
| 58 | 
                      #' quantities.  | 
                  |
| 59 | 
                      #'  | 
                  |
| 60 | 
                      #' @inheritParams generateQuantities  | 
                  |
| 61 | 
                      #' @export  | 
                  |
| 62 | 
                      as.StanModule.JointModelSamples <- function(object, generator, type, ...) {
                     | 
                  |
| 63 | 38x | 
                      assert_that(  | 
                  
| 64 | 38x | 
                      is(generator, "QuantityGenerator"),  | 
                  
| 65 | 38x | 
                      length(type) == 1,  | 
                  
| 66 | 38x | 
                              type %in% c("survival", "longitudinal")
                     | 
                  
| 67 | 
                      )  | 
                  |
| 68 | ||
| 69 | 38x | 
                          quant_stanobj <- read_stan("base/quantities.stan") |>
                     | 
                  
| 70 | 38x | 
                      decorated_render(  | 
                  
| 71 | 38x | 
                      include_gq_longitudinal_idv = (type == "longitudinal") & is(generator, "QuantityGeneratorSubject"),  | 
                  
| 72 | 38x | 
                      include_gq_longitudinal_pop = (type == "longitudinal") & is(generator, "QuantityGeneratorPopulation"),  | 
                  
| 73 | 38x | 
                      include_gq_survival_idv = (type == "survival") & is(generator, "QuantityGeneratorSubject"),  | 
                  
| 74 | 38x | 
                      include_gq_survival_pred = (type == "survival") & is(generator, "QuantityGeneratorPrediction")  | 
                  
| 75 | 
                      ) |>  | 
                  |
| 76 | 38x | 
                      StanModule()  | 
                  
| 77 | ||
| 78 | 38x | 
                      stanobj <- Reduce(  | 
                  
| 79 | 38x | 
                      merge,  | 
                  
| 80 | 38x | 
                      list(  | 
                  
| 81 | 38x | 
                      as.StanModule(object@model),  | 
                  
| 82 | 38x | 
                      enableGQ(object@model),  | 
                  
| 83 | 38x | 
                      quant_stanobj  | 
                  
| 84 | 
                      )  | 
                  |
| 85 | 
                      )  | 
                  |
| 86 | 38x | 
                      stanobj  | 
                  
| 87 | 
                      }  | 
                  |
| 88 | ||
| 89 | ||
| 90 | ||
| 91 | 
                      #' `JointModelSamples` -> Printable `Character`  | 
                  |
| 92 | 
                      #'  | 
                  |
| 93 | 
                      #' Converts [`JointModelSamples`] object into a printable string.  | 
                  |
| 94 | 
                      #' @param object ([`JointModelSamples`])\cr samples as drawn from a [`JointModel`].  | 
                  |
| 95 | 
                      #' @family JointModelSamples  | 
                  |
| 96 | 
                      #' @param indent (`numeric`)\cr how much white space to prefix the print string with.  | 
                  |
| 97 | 
                      #' @keywords internal  | 
                  |
| 98 | 
                      #' @export  | 
                  |
| 99 | 
                      as_print_string.JointModelSamples <- function(object, indent = 1, ...) {
                     | 
                  |
| 100 | 17x | 
                      sizes <- vapply(  | 
                  
| 101 | 17x | 
                      as.CmdStanMCMC(object)$metadata()[["stan_variable_sizes"]],  | 
                  
| 102 | 17x | 
                              \(x) {
                     | 
                  
| 103 | 91x | 
                                  if (length(x) == 1 && x == 1) return("")
                     | 
                  
| 104 | 154x | 
                                  paste0("[", paste(x, collapse = ", "), "]")
                     | 
                  
| 105 | 
                      },  | 
                  |
| 106 | 17x | 
                      character(1)  | 
                  
| 107 | 
                      )  | 
                  |
| 108 | 17x | 
                      variable_string <- paste0(  | 
                  
| 109 | 
                      " ",  | 
                  |
| 110 | 17x | 
                      as.CmdStanMCMC(object)$metadata()[["stan_variables"]],  | 
                  
| 111 | 17x | 
                      sizes  | 
                  
| 112 | 
                      )  | 
                  |
| 113 | 17x | 
                      template <- c(  | 
                  
| 114 | 17x | 
                      "JointModelSamples Object with:",  | 
                  
| 115 | 
                      "",  | 
                  |
| 116 | 17x | 
                      " # of samples per chain = %d",  | 
                  
| 117 | 17x | 
                      " # of chains = %d",  | 
                  
| 118 | 
                      "",  | 
                  |
| 119 | 17x | 
                      " Variables:",  | 
                  
| 120 | 17x | 
                      variable_string[order(variable_string)]  | 
                  
| 121 | 
                      )  | 
                  |
| 122 | 17x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 123 | 17x | 
                      template_padded <- paste(pad, template)  | 
                  
| 124 | 17x | 
                      sprintf(  | 
                  
| 125 | 17x | 
                      paste(template_padded, collapse = "\n"),  | 
                  
| 126 | 17x | 
                      as.CmdStanMCMC(object)$metadata()$iter_sampling,  | 
                  
| 127 | 17x | 
                      as.CmdStanMCMC(object)$num_chains()  | 
                  
| 128 | 
                      )  | 
                  |
| 129 | 
                      }  | 
                  |
| 130 | ||
| 131 | 
                      #' @rdname show-object  | 
                  |
| 132 | 
                      #' @export  | 
                  |
| 133 | 
                      setMethod(  | 
                  |
| 134 | 
                      f = "show",  | 
                  |
| 135 | 
                      signature = "JointModelSamples",  | 
                  |
| 136 | 
                          definition = function(object) {
                     | 
                  |
| 137 | 17x | 
                      string <- as_print_string(object)  | 
                  
| 138 | 17x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 139 | 
                      }  | 
                  |
| 140 | 
                      )  | 
                  |
| 141 | ||
| 142 | ||
| 143 | 
                      #' @rdname as.CmdStanMCMC  | 
                  |
| 144 | 
                      #' @export  | 
                  |
| 145 | 
                      as.CmdStanMCMC.JointModelSamples <- function(object, ...) {
                     | 
                  |
| 146 | 81x | 
                      return(object@results)  | 
                  
| 147 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Link.R  | 
                  |
| 3 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 4 | 
                      #' @include SurvivalModel.R  | 
                  |
| 5 | 
                      #' @include StanModule.R  | 
                  |
| 6 | 
                      #' @include StanModel.R  | 
                  |
| 7 | 
                      #' @include Parameter.R  | 
                  |
| 8 | 
                      NULL  | 
                  |
| 9 | ||
| 10 | ||
| 11 | ||
| 12 | 
                      #' @rdname getParameters  | 
                  |
| 13 | 
                      #' @export  | 
                  |
| 14 | 
                      getParameters.default <- function(object, ...) {
                     | 
                  |
| 15 | 15x | 
                          if (missing(object) || is.null(object)) {
                     | 
                  
| 16 | 15x | 
                      return(NULL)  | 
                  
| 17 | 
                      }  | 
                  |
| 18 | ! | 
                          stop(sprintf("No default method implemented for getParameters(<%s>)", typeof(object)))
                     | 
                  
| 19 | 
                      }  | 
                  |
| 20 | ||
| 21 | ||
| 22 | 
                      # merge ----  | 
                  |
| 23 | ||
| 24 | 
                      ## merge-StanModel,NULL ----  | 
                  |
| 25 | ||
| 26 | 
                      #' @rdname merge  | 
                  |
| 27 | 
                      setMethod(  | 
                  |
| 28 | 
                      "merge",  | 
                  |
| 29 | 
                          signature = c("StanModel", "NULL"),
                     | 
                  |
| 30 | ! | 
                      definition = function(x, y, ...) x@stan  | 
                  
| 31 | 
                      )  | 
                  |
| 32 | ||
| 33 | 
                      ## merge-NULL,StanModel ----  | 
                  |
| 34 | ||
| 35 | 
                      #' @rdname merge  | 
                  |
| 36 | 
                      setMethod(  | 
                  |
| 37 | 
                      "merge",  | 
                  |
| 38 | 
                          signature = c("NULL", "StanModel"),
                     | 
                  |
| 39 | ! | 
                      definition = function(x, y, ...) y@stan  | 
                  
| 40 | 
                      )  | 
                  |
| 41 | ||
| 42 | 
                      ## merge-StanModule,NULL ----  | 
                  |
| 43 | ||
| 44 | 
                      #' @rdname merge  | 
                  |
| 45 | 
                      setMethod(  | 
                  |
| 46 | 
                      "merge",  | 
                  |
| 47 | 
                          signature = c("StanModule", "NULL"),
                     | 
                  |
| 48 | ! | 
                      definition = function(x, y, ...) x  | 
                  
| 49 | 
                      )  | 
                  |
| 50 | ||
| 51 | 
                      ## merge-NULL,StanModule ----  | 
                  |
| 52 | ||
| 53 | 
                      #' @rdname merge  | 
                  |
| 54 | 
                      setMethod(  | 
                  |
| 55 | 
                      "merge",  | 
                  |
| 56 | 
                          signature = c("NULL", "StanModule"),
                     | 
                  |
| 57 | ! | 
                      definition = function(x, y, ...) y  | 
                  
| 58 | 
                      )  | 
                  |
| 59 | ||
| 60 | 
                      ## merge-ParameterList,NULL ----  | 
                  |
| 61 | ||
| 62 | 
                      #' @rdname merge  | 
                  |
| 63 | 
                      setMethod(  | 
                  |
| 64 | 
                      "merge",  | 
                  |
| 65 | 
                          signature = c("ParameterList", "NULL"),
                     | 
                  |
| 66 | 36x | 
                      definition = function(x, y, ...) x  | 
                  
| 67 | 
                      )  | 
                  |
| 68 | ||
| 69 | 
                      ## merge-NULL,ParameterList ----  | 
                  |
| 70 | ||
| 71 | 
                      #' @rdname merge  | 
                  |
| 72 | 
                      setMethod(  | 
                  |
| 73 | 
                      "merge",  | 
                  |
| 74 | 
                          signature = c("NULL", "ParameterList"),
                     | 
                  |
| 75 | 4x | 
                      definition = function(x, y, ...) y  | 
                  
| 76 | 
                      )  | 
                  |
| 77 | ||
| 78 | 
                      ## merge-NULL,NULL ----  | 
                  |
| 79 | ||
| 80 | 
                      #' @rdname merge  | 
                  |
| 81 | 
                      setMethod(  | 
                  |
| 82 | 
                      "merge",  | 
                  |
| 83 | 
                          signature = c("NULL", "NULL"),
                     | 
                  |
| 84 | ! | 
                      definition = function(x, y, ...) NULL  | 
                  
| 85 | 
                      )  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Grid.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' @rdname Quant-Dev  | 
                  |
| 6 | 
                      .QuantityGeneratorPrediction <- setClass(  | 
                  |
| 7 | 
                      "QuantityGeneratorPrediction",  | 
                  |
| 8 | 
                      contains = "QuantityGenerator",  | 
                  |
| 9 | 
                      slots = c(  | 
                  |
| 10 | 
                      "times" = "numeric",  | 
                  |
| 11 | 
                      "newdata" = "data.frame",  | 
                  |
| 12 | 
                      "params" = "list"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | ||
| 17 | 
                      #' @rdname Quant-Dev  | 
                  |
| 18 | 
                      QuantityGeneratorPrediction <- function(times, newdata = NULL, params = NULL) {
                     | 
                  |
| 19 | 6x | 
                      .QuantityGeneratorPrediction(  | 
                  
| 20 | 6x | 
                      times = times,  | 
                  
| 21 | 6x | 
                      newdata = newdata,  | 
                  
| 22 | 6x | 
                      params = params  | 
                  
| 23 | 
                      )  | 
                  |
| 24 | 
                      }  | 
                  |
| 25 | 
                      setValidity(  | 
                  |
| 26 | 
                      "QuantityGeneratorPrediction",  | 
                  |
| 27 | 
                          function(object) {
                     | 
                  |
| 28 | 
                              if (length(object@times) != nrow(object@newdata)) {
                     | 
                  |
| 29 | 
                                  return("Length of `times` and `newdata` must be equal")
                     | 
                  |
| 30 | 
                      }  | 
                  |
| 31 | 
                      return(TRUE)  | 
                  |
| 32 | 
                      }  | 
                  |
| 33 | 
                      )  | 
                  |
| 34 | ||
| 35 | ||
| 36 | ||
| 37 | ||
| 38 | 
                      #' @rdname as_stan_list.QuantityGenerator  | 
                  |
| 39 | 
                      #' @export  | 
                  |
| 40 | 
                      as_stan_list.QuantityGeneratorPrediction <- function(object, data, model, ...) {
                     | 
                  |
| 41 | 3x | 
                      assert_that(  | 
                  
| 42 | 3x | 
                      is(data, "DataJoint")  | 
                  
| 43 | 
                      )  | 
                  |
| 44 | 3x | 
                      ret <- list()  | 
                  
| 45 | 3x | 
                      data_list <- as_stan_list(data)  | 
                  
| 46 | ||
| 47 | 3x | 
                      ret[["gq_times"]] <- object@times  | 
                  
| 48 | 3x | 
                      ret[["gq_n_quant"]] <- length(object@times)  | 
                  
| 49 | ||
| 50 | 
                      # Get a list of which longutidunal parameters need to be defined based  | 
                  |
| 51 | 
                      # on the selected longitudinal model  | 
                  |
| 52 | 3x | 
                      par_names <- getPredictionNames(model@longitudinal)  | 
                  
| 53 | 3x | 
                          for (nam in par_names) {
                     | 
                  
| 54 | 8x | 
                      assert_that(  | 
                  
| 55 | 8x | 
                      nam %in% names(object@params),  | 
                  
| 56 | 8x | 
                                  msg = sprintf("Parameter '%s' not found in `params`", nam)
                     | 
                  
| 57 | 
                      )  | 
                  |
| 58 | 8x | 
                      assert_that(  | 
                  
| 59 | 8x | 
                      is.numeric(object@params[[nam]]),  | 
                  
| 60 | 8x | 
                                  msg = sprintf("Parameter '%s' must be numeric", nam)
                     | 
                  
| 61 | 
                      )  | 
                  |
| 62 | 8x | 
                      assert_that(  | 
                  
| 63 | 8x | 
                      length(object@params[[nam]]) == 1,  | 
                  
| 64 | 8x | 
                                  msg = sprintf("Parameter '%s' must be length 1", nam)
                     | 
                  
| 65 | 
                      )  | 
                  |
| 66 | 
                      }  | 
                  |
| 67 | ||
| 68 | 3x | 
                      par_vals <- object@params[par_names]  | 
                  
| 69 | 3x | 
                          if (length(par_vals) == 0) {
                     | 
                  
| 70 | 1x | 
                      par_vals <- 0  | 
                  
| 71 | 1x | 
                      par_names <- "null_model"  | 
                  
| 72 | 
                      }  | 
                  |
| 73 | ||
| 74 | 3x | 
                      ret[["gq_n_par"]] <- length(par_names)  | 
                  
| 75 | ||
| 76 | 
                      # Replicate the longitudinal parameters so the same parameter values are used  | 
                  |
| 77 | 
                      # for all observations that are being predicted  | 
                  |
| 78 | 3x | 
                      ret[["gq_link_function_inputs"]] <- matrix(  | 
                  
| 79 | 3x | 
                      rep(unlist(par_vals), each = ret[["gq_n_quant"]]),  | 
                  
| 80 | 3x | 
                      ncol = ret[["gq_n_par"]],  | 
                  
| 81 | 3x | 
                      nrow = ret[["gq_n_quant"]]  | 
                  
| 82 | 
                      )  | 
                  |
| 83 | ||
| 84 | 
                      # Create design matrix from new data ensuring that it has the same  | 
                  |
| 85 | 
                      # structure as the original design matrix  | 
                  |
| 86 | 3x | 
                      ret[["gq_os_cov_design"]] <- mirror_design_matrix(  | 
                  
| 87 | 3x | 
                      data@survival,  | 
                  
| 88 | 3x | 
                      object@newdata  | 
                  
| 89 | 
                      )  | 
                  |
| 90 | ||
| 91 | 
                      # dummy pop indexes in order for stan code to actualy compile. In this setting  | 
                  |
| 92 | 
                      # this matrix isn't actually used so doesn't matter what these values are  | 
                  |
| 93 | 
                      # but don't want to have to burden individual longitudinal models with the  | 
                  |
| 94 | 
                      # conditional logic to check if they are generating population quantities or not  | 
                  |
| 95 | 2x | 
                      ret[["gq_long_pop_arm_index"]] <- rep(1, ret[["gq_n_quant"]])  | 
                  
| 96 | 2x | 
                      ret[["gq_long_pop_study_index"]] <- rep(1, ret[["gq_n_quant"]])  | 
                  
| 97 | ||
| 98 | ||
| 99 | 
                      # Sanity checks  | 
                  |
| 100 | 2x | 
                      assert_that(  | 
                  
| 101 | 2x | 
                      nrow(ret[["gq_os_cov_design"]]) == ret[["gq_n_quant"]],  | 
                  
| 102 | 2x | 
                      ncol(ret[["gq_os_cov_design"]]) == data_list[["p_os_cov_design"]],  | 
                  
| 103 | 2x | 
                      all(!is.na(ret[["gq_link_function_inputs"]]))  | 
                  
| 104 | 
                      )  | 
                  |
| 105 | ||
| 106 | 2x | 
                      return(ret)  | 
                  
| 107 | 
                      }  | 
                  
| 1 | ||
| 2 | ||
| 3 | 
                      #' Re-used documentation for `DataSubject`  | 
                  |
| 4 | 
                      #'  | 
                  |
| 5 | 
                      #' @param object ([`DataSubject`]) \cr subject-level data.  | 
                  |
| 6 | 
                      #' @param x ([`DataSubject`]) \cr subject-level data.  | 
                  |
| 7 | 
                      #' @param ... Not Used.  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' @name DataSubject-Shared  | 
                  |
| 10 | 
                      #' @keywords internal  | 
                  |
| 11 | 
                      NULL  | 
                  |
| 12 | ||
| 13 | ||
| 14 | ||
| 15 | 
                      #' Subject Data Object and Constructor Function  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' The [`DataSubject`] class handles the processing of the subject data for  | 
                  |
| 18 | 
                      #' fitting a [`JointModel`].  | 
                  |
| 19 | 
                      #'  | 
                  |
| 20 | 
                      #' @slot data (`data.frame`)\cr the subject-level data.  | 
                  |
| 21 | 
                      #' @slot subject (`character`)\cr the name of the variable containing the subject identifier.  | 
                  |
| 22 | 
                      #' @slot arm (`character`)\cr the name of the variable containing the arm identifier.  | 
                  |
| 23 | 
                      #' @slot study (`character`)\cr the name of the variable containing the study identifier.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @family DataObjects  | 
                  |
| 26 | 
                      #' @family DataSubject  | 
                  |
| 27 | 
                      #' @exportClass DataSubject  | 
                  |
| 28 | 
                      #' @export DataSubject  | 
                  |
| 29 | 
                      .DataSubject <- setClass(  | 
                  |
| 30 | 
                      Class = "DataSubject",  | 
                  |
| 31 | 
                      representation = list(  | 
                  |
| 32 | 
                      data = "data.frame",  | 
                  |
| 33 | 
                      subject = "character",  | 
                  |
| 34 | 
                      arm = "character",  | 
                  |
| 35 | 
                      study = "character"  | 
                  |
| 36 | 
                      )  | 
                  |
| 37 | 
                      )  | 
                  |
| 38 | ||
| 39 | ||
| 40 | 
                      #' @param data (`data.frame`)\cr the subject-level data.  | 
                  |
| 41 | 
                      #' @param subject (`character`)\cr the name of the variable containing the subject identifier.  | 
                  |
| 42 | 
                      #' @param arm (`character`)\cr the name of the variable containing the arm identifier.  | 
                  |
| 43 | 
                      #' @param study (`character`)\cr the name of the variable containing the study identifier.  | 
                  |
| 44 | 
                      #' @rdname DataSubject-class  | 
                  |
| 45 | 
                      #' @export  | 
                  |
| 46 | 
                      DataSubject <- function(data, subject, arm, study) {
                     | 
                  |
| 47 | 358x | 
                      vars <- c(subject, arm, study)  | 
                  
| 48 | 358x | 
                          vars_frm_chr <- paste0("~ ", paste(vars, collapse = " + "))
                     | 
                  
| 49 | 358x | 
                      .DataSubject(  | 
                  
| 50 | 358x | 
                      data = remove_missing_rows(data, stats::as.formula(vars_frm_chr)),  | 
                  
| 51 | 358x | 
                      subject = subject,  | 
                  
| 52 | 358x | 
                      arm = arm,  | 
                  
| 53 | 358x | 
                      study = study  | 
                  
| 54 | 
                      )  | 
                  |
| 55 | 
                      }  | 
                  |
| 56 | ||
| 57 | 
                      setValidity(  | 
                  |
| 58 | 
                      "DataSubject",  | 
                  |
| 59 | 
                          method = function(object) {
                     | 
                  |
| 60 | 
                              if (length(object@subject) != 1) {
                     | 
                  |
| 61 | 
                                  return("`subject` must be a length 1 character")
                     | 
                  |
| 62 | 
                      }  | 
                  |
| 63 | 
                              if (length(object@arm) != 1) {
                     | 
                  |
| 64 | 
                                  return("`arm` must be a length 1 character")
                     | 
                  |
| 65 | 
                      }  | 
                  |
| 66 | 
                              if (length(object@study) != 1) {
                     | 
                  |
| 67 | 
                                  return("`study` must be a length 1 character")
                     | 
                  |
| 68 | 
                      }  | 
                  |
| 69 | 
                              if (nrow(object@data) == 0) {
                     | 
                  |
| 70 | 
                                  return("`data` should not have 0 rows")
                     | 
                  |
| 71 | 
                      }  | 
                  |
| 72 | 
                      sbj <- object@data[[object@subject]]  | 
                  |
| 73 | 
                              if (!(is(sbj, "character") | is(sbj, "factor"))) {
                     | 
                  |
| 74 | 
                                  return("`data[[subject]]` should be of type character or factor")
                     | 
                  |
| 75 | 
                      }  | 
                  |
| 76 | 
                      }  | 
                  |
| 77 | 
                      )  | 
                  |
| 78 | ||
| 79 | ||
| 80 | ||
| 81 | 
                      #' @inheritParams DataSubject-Shared  | 
                  |
| 82 | 
                      #' @inherit extractVariableNames description title  | 
                  |
| 83 | 
                      #'  | 
                  |
| 84 | 
                      #' @returns  | 
                  |
| 85 | 
                      #' A list with the following named elements:  | 
                  |
| 86 | 
                      #' - `subject` (`character`)\cr the name of the variable containing the subject identifier.  | 
                  |
| 87 | 
                      #' - `arm` (`character`)\cr the name of the variable containing the arm identifier.  | 
                  |
| 88 | 
                      #' - `study` (`character`) \cr the name of the variable containing the study identifier.  | 
                  |
| 89 | 
                      #' @family DataSubject  | 
                  |
| 90 | 
                      #' @family extractVariableNames  | 
                  |
| 91 | 
                      #' @export  | 
                  |
| 92 | 
                      #' @keywords internal  | 
                  |
| 93 | 
                      extractVariableNames.DataSubject <- function(object) {
                     | 
                  |
| 94 | 970x | 
                      list(  | 
                  
| 95 | 970x | 
                      subject = object@subject,  | 
                  
| 96 | 970x | 
                      arm = object@arm,  | 
                  
| 97 | 970x | 
                      study = object@study  | 
                  
| 98 | 
                      )  | 
                  |
| 99 | 
                      }  | 
                  |
| 100 | ||
| 101 | ||
| 102 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 103 | 
                      #' @family DataSubject  | 
                  |
| 104 | 
                      #' @export  | 
                  |
| 105 | 
                      as_stan_list.DataSubject <- function(object, ...) {
                     | 
                  |
| 106 | 293x | 
                      df <- as.data.frame(harmonise(object))  | 
                  
| 107 | 293x | 
                      vars <- extractVariableNames(object)  | 
                  
| 108 | ||
| 109 | 293x | 
                      unique_arm_study_combos <- unique(  | 
                  
| 110 | 293x | 
                      data.frame(  | 
                  
| 111 | 293x | 
                      arm = as.numeric(df[[vars$arm]]),  | 
                  
| 112 | 293x | 
                      study = as.numeric(df[[vars$study]])  | 
                  
| 113 | 
                      )  | 
                  |
| 114 | 
                      )  | 
                  |
| 115 | ||
| 116 | 293x | 
                      list(  | 
                  
| 117 | 293x | 
                      n_subjects = nrow(df),  | 
                  
| 118 | 293x | 
                      n_studies = length(unique(df[[vars$study]])),  | 
                  
| 119 | 293x | 
                      n_arms = length(unique(df[[vars$arm]])),  | 
                  
| 120 | 293x | 
                      subject_study_index = as.numeric(df[[vars$study]]),  | 
                  
| 121 | 293x | 
                      subject_arm_index = as.numeric(df[[vars$arm]]),  | 
                  
| 122 | 293x | 
                      subject_to_index = stats::setNames(  | 
                  
| 123 | 293x | 
                      seq_len(nlevels(df[[vars$subject]])),  | 
                  
| 124 | 293x | 
                      levels(df[[vars$subject]])  | 
                  
| 125 | 
                      ),  | 
                  |
| 126 | 293x | 
                      arm_to_index = stats::setNames(  | 
                  
| 127 | 293x | 
                      seq_len(nlevels(df[[vars$arm]])),  | 
                  
| 128 | 293x | 
                      levels(df[[vars$arm]])  | 
                  
| 129 | 
                      ),  | 
                  |
| 130 | 293x | 
                      study_to_index = stats::setNames(  | 
                  
| 131 | 293x | 
                      seq_len(nlevels(df[[vars$study]])),  | 
                  
| 132 | 293x | 
                      levels(df[[vars$study]])  | 
                  
| 133 | 
                      ),  | 
                  |
| 134 | 293x | 
                      pop_arm_index = unique_arm_study_combos$arm,  | 
                  
| 135 | 293x | 
                      pop_study_index = unique_arm_study_combos$study  | 
                  
| 136 | 
                      )  | 
                  |
| 137 | 
                      }  | 
                  |
| 138 | ||
| 139 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 140 | 
                      #' @export  | 
                  |
| 141 | 
                      as.list.DataSubject <- function(x, ...) {
                     | 
                  |
| 142 | ! | 
                      as_stan_list(x, ...)  | 
                  
| 143 | 
                      }  | 
                  |
| 144 | ||
| 145 | ||
| 146 | 
                      #' `DataSubject` -> `data.frame`  | 
                  |
| 147 | 
                      #'  | 
                  |
| 148 | 
                      #' @inheritParams DataSubject-Shared  | 
                  |
| 149 | 
                      #'  | 
                  |
| 150 | 
                      #' @description  | 
                  |
| 151 | 
                      #' Converts a [`DataSubject`] object into a `data.frame`.  | 
                  |
| 152 | 
                      #' The subject variable is cast to factor.  | 
                  |
| 153 | 
                      #' @family DataSubject  | 
                  |
| 154 | 
                      #' @export  | 
                  |
| 155 | 
                      as.data.frame.DataSubject <- function(x, ...) {
                     | 
                  |
| 156 | 703x | 
                      x <- x@data  | 
                  
| 157 | 703x | 
                      rownames(x) <- NULL  | 
                  
| 158 | 703x | 
                      x  | 
                  
| 159 | 
                      }  | 
                  |
| 160 | ||
| 161 | ||
| 162 | ||
| 163 | 
                      #' @rdname harmonise  | 
                  |
| 164 | 
                      harmonise.DataSubject <- function(object, ...) {
                     | 
                  |
| 165 | 325x | 
                      data <- as.data.frame(object)  | 
                  
| 166 | 325x | 
                      vars <- extractVariableNames(object)  | 
                  
| 167 | 325x | 
                      assert_that(  | 
                  
| 168 | 325x | 
                      vars$subject %in% names(data),  | 
                  
| 169 | 325x | 
                      vars$arm %in% names(data),  | 
                  
| 170 | 325x | 
                      vars$study %in% names(data)  | 
                  
| 171 | 
                      )  | 
                  |
| 172 | 325x | 
                      assert_character(  | 
                  
| 173 | 325x | 
                      as.character(data[[vars$subject]]),  | 
                  
| 174 | 325x | 
                      any.missing = FALSE,  | 
                  
| 175 | 325x | 
                      unique = TRUE  | 
                  
| 176 | 
                      )  | 
                  |
| 177 | 324x | 
                      data[[vars$subject]] <- factor(data[[vars$subject]])  | 
                  
| 178 | 324x | 
                      data[[vars$arm]] <- factor(data[[vars$arm]])  | 
                  
| 179 | 324x | 
                      data[[vars$study]] <- factor(data[[vars$study]])  | 
                  
| 180 | 324x | 
                      data <- data[order(data[[vars$subject]]), ]  | 
                  
| 181 | 324x | 
                      DataSubject(  | 
                  
| 182 | 324x | 
                      data = data,  | 
                  
| 183 | 324x | 
                      subject = object@subject,  | 
                  
| 184 | 324x | 
                      arm = object@arm,  | 
                  
| 185 | 324x | 
                      study = object@study  | 
                  
| 186 | 
                      )  | 
                  |
| 187 | 
                      }  | 
                  |
| 188 | ||
| 189 | 
                      #' `DataSubject` -> Printable `Character`  | 
                  |
| 190 | 
                      #'  | 
                  |
| 191 | 
                      #' Converts [`DataSubject`] object into a printable string.  | 
                  |
| 192 | 
                      #' @inheritParams DataSubject-Shared  | 
                  |
| 193 | 
                      #' @family DataSubject  | 
                  |
| 194 | 
                      #' @keywords internal  | 
                  |
| 195 | 
                      #' @param indent (`numeric`)\cr how much white space to prefix the print string with.  | 
                  |
| 196 | 
                      #' @export  | 
                  |
| 197 | 
                      as_print_string.DataSubject <- function(object, indent = 1, ...) {
                     | 
                  |
| 198 | 2x | 
                      template <- c(  | 
                  
| 199 | 2x | 
                      "Subject-Data Object:",  | 
                  
| 200 | 2x | 
                      " # of Subjects = %d",  | 
                  
| 201 | 2x | 
                      " # of Studies = %d",  | 
                  
| 202 | 2x | 
                      " # of Arms = %d"  | 
                  
| 203 | 
                      )  | 
                  |
| 204 | 2x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 205 | 2x | 
                      template_padded <- paste(pad, template)  | 
                  
| 206 | 2x | 
                      vars <- extractVariableNames(object)  | 
                  
| 207 | 2x | 
                      sprintf(  | 
                  
| 208 | 2x | 
                      paste(template_padded, collapse = "\n"),  | 
                  
| 209 | 2x | 
                      nrow(object@data),  | 
                  
| 210 | 2x | 
                      length(unique(object@data[[vars$study]])),  | 
                  
| 211 | 2x | 
                      length(unique(object@data[[vars$arm]]))  | 
                  
| 212 | 
                      )  | 
                  |
| 213 | 
                      }  | 
                  |
| 214 | ||
| 215 | 
                      #' @rdname show-object  | 
                  |
| 216 | 
                      #' @export  | 
                  |
| 217 | 
                      setMethod(  | 
                  |
| 218 | 
                      f = "show",  | 
                  |
| 219 | 
                      signature = "DataSubject",  | 
                  |
| 220 | 
                          definition = function(object) {
                     | 
                  |
| 221 | 1x | 
                      string <- as_print_string(object)  | 
                  
| 222 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 223 | 
                      }  | 
                  |
| 224 | 
                      )  | 
                  
| 1 | ||
| 2 | ||
| 3 | 
                      #' Re-used documentation for Brier Score components  | 
                  |
| 4 | 
                      #'  | 
                  |
| 5 | 
                      #' @param t (`numeric`)\cr timepoints to calculate the desired quantity at.  | 
                  |
| 6 | 
                      #' @param times (`numeric`)\cr observed times.  | 
                  |
| 7 | 
                      #' @param events (`numeric`)\cr event indicator for `times`. Either 1 for an event or 0 for censor.  | 
                  |
| 8 | 
                      #' @param event_offset (`logical`)\cr If `TRUE` then \eqn{G(T_i)} is evaluated at \eqn{G(T_i-)}.
                     | 
                  |
| 9 | 
                      #' Setting this as `TRUE` mirrors the implementation of the `{pec}` package.
                     | 
                  |
| 10 | 
                      #' @param maintain_cen_order (`logical`)\cr If `TRUE` then, in the case of ties,  | 
                  |
| 11 | 
                      #' censor times are always considered  | 
                  |
| 12 | 
                      #' to have occurred after the event times when calculating the "reverse Kaplan-Meier" for the  | 
                  |
| 13 | 
                      #' IPCW estimates. Setting this to `TRUE` mirrors the implementation of the `{prodlim}`
                     | 
                  |
| 14 | 
                      #' package.  | 
                  |
| 15 | 
                      #' @param ... not used.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @name Brier-Score-Shared  | 
                  |
| 18 | 
                      #' @keywords internal  | 
                  |
| 19 | 
                      NULL  | 
                  |
| 20 | ||
| 21 | ||
| 22 | ||
| 23 | ||
| 24 | 
                      #' Reverse Kaplan-Meier  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @inheritParams Brier-Score-Shared  | 
                  |
| 27 | 
                      #' @description  | 
                  |
| 28 | 
                      #' Calculates the survival estimates of the censoring distribution  | 
                  |
| 29 | 
                      #' using the Kaplan-Meier estimate.  | 
                  |
| 30 | 
                      #' This is primarily used in the calculation of the IPCW estimates.  | 
                  |
| 31 | 
                      #'  | 
                  |
| 32 | 
                      #' @details  | 
                  |
| 33 | 
                      #' With regards to ties between censor and event times; the standard  | 
                  |
| 34 | 
                      #' approach is to regard events as occurring before censors. However,  | 
                  |
| 35 | 
                      #' when modelling the censoring distribution we are regarding the  | 
                  |
| 36 | 
                      #' censors as "events" so which should come first in the case of ties?  | 
                  |
| 37 | 
                      #'  | 
                  |
| 38 | 
                      #' The `reverse_km_event_first()` function maintains the rule  | 
                  |
| 39 | 
                      #' that events always come first even if we are regarding the censors  | 
                  |
| 40 | 
                      #' as "events". This matches the implementation of  | 
                  |
| 41 | 
                      #' `prodlim::prodlim(..., reverse = TRUE)`.  | 
                  |
| 42 | 
                      #'  | 
                  |
| 43 | 
                      #' The `reverse_km_cen_first()` function provides the alternative  | 
                  |
| 44 | 
                      #' implementation assuming that in the case of ties the censor "events"  | 
                  |
| 45 | 
                      #' come before the event "censors". This is essentially a thin wrapper  | 
                  |
| 46 | 
                      #' around `survival::survfit(Surv(time, 1 - event), ...)`  | 
                  |
| 47 | 
                      #'  | 
                  |
| 48 | 
                      #' @name reverse_km  | 
                  |
| 49 | 
                      #' @keywords internal  | 
                  |
| 50 | 
                      reverse_km_event_first <- function(t, times, events) {
                     | 
                  |
| 51 | 5x | 
                      assert_numeric(t, any.missing = FALSE, finite = TRUE)  | 
                  
| 52 | 5x | 
                      assert_numeric(times, any.missing = FALSE, finite = TRUE)  | 
                  
| 53 | 5x | 
                      assert_numeric(events, any.missing = FALSE, finite = TRUE)  | 
                  
| 54 | 5x | 
                      assert_that(  | 
                  
| 55 | 5x | 
                      length(times) == length(events),  | 
                  
| 56 | 5x | 
                      all(events == 1 | events == 0)  | 
                  
| 57 | 
                      )  | 
                  |
| 58 | 5x | 
                      events_cen <- 1 - events  | 
                  
| 59 | 5x | 
                      ord <- order(times, events_cen)  | 
                  
| 60 | 5x | 
                      times <- times[ord]  | 
                  
| 61 | 5x | 
                      events <- events[ord]  | 
                  
| 62 | 5x | 
                      events_cen <- events_cen[ord]  | 
                  
| 63 | 5x | 
                      cs_events <- cumsum(events)  | 
                  
| 64 | 5x | 
                      cs_censor <- cumsum(events_cen)  | 
                  
| 65 | ||
| 66 | 5x | 
                      g_times <- unique(times)  | 
                  
| 67 | 5x | 
                      g_n_events_cen <- tapply(events_cen, times, sum)  | 
                  
| 68 | 5x | 
                      g_cs_events_cen <- tapply(cs_censor, times, max)  | 
                  
| 69 | 5x | 
                      g_cs_events <- tapply(cs_events, times, max)  | 
                  
| 70 | 5x | 
                      g_is_cen <- tapply(events_cen, times, max)  | 
                  
| 71 | ||
| 72 | 5x | 
                      nrisk <- length(times) - g_cs_events - g_cs_events_cen + g_n_events_cen  | 
                  
| 73 | 5x | 
                      surv_interval <- 1 - g_n_events_cen / nrisk  | 
                  
| 74 | 5x | 
                      surv_interval <- ifelse(nrisk == 0, 1, surv_interval)  | 
                  
| 75 | 5x | 
                      surv <- cumprod(surv_interval)  | 
                  
| 76 | ||
| 77 | 5x | 
                      ct <- g_times[which(g_is_cen == 1)]  | 
                  
| 78 | 5x | 
                      sv <- surv[which(g_is_cen == 1)]  | 
                  
| 79 | ||
| 80 | 5x | 
                      names(surv) <- NULL  | 
                  
| 81 | 5x | 
                      names(ct) <- NULL  | 
                  
| 82 | 5x | 
                      names(sv) <- NULL  | 
                  
| 83 | 5x | 
                      list(  | 
                  
| 84 | 5x | 
                      t = t,  | 
                  
| 85 | 5x | 
                      surv = c(1, sv)[findInterval(t, ct) + 1]  | 
                  
| 86 | 
                      )  | 
                  |
| 87 | 
                      }  | 
                  |
| 88 | ||
| 89 | ||
| 90 | 
                      #' @rdname reverse_km  | 
                  |
| 91 | 
                      reverse_km_cen_first <- function(t, times, events) {
                     | 
                  |
| 92 | 1x | 
                      assert_numeric(t, any.missing = FALSE, finite = TRUE)  | 
                  
| 93 | 1x | 
                      assert_numeric(times, any.missing = FALSE, finite = TRUE)  | 
                  
| 94 | 1x | 
                      assert_numeric(events, any.missing = FALSE, finite = TRUE)  | 
                  
| 95 | 1x | 
                      assert_that(  | 
                  
| 96 | 1x | 
                      length(times) == length(events),  | 
                  
| 97 | 1x | 
                      all(events == 1 | events == 0)  | 
                  
| 98 | 
                      )  | 
                  |
| 99 | 1x | 
                      dat <- data.frame(  | 
                  
| 100 | 1x | 
                      times = times,  | 
                  
| 101 | 1x | 
                      events = events,  | 
                  
| 102 | 1x | 
                      cen_events = 1 - events  | 
                  
| 103 | 
                      )  | 
                  |
| 104 | 1x | 
                      mod <- survival::survfit(  | 
                  
| 105 | 1x | 
                      survival::Surv(times, cen_events) ~ 1,  | 
                  
| 106 | 1x | 
                      data = dat  | 
                  
| 107 | 
                      )  | 
                  |
| 108 | 1x | 
                      preds <- summary(mod, times = t[order(t)], extend = TRUE)$surv  | 
                  
| 109 | ||
| 110 | 1x | 
                      assert_that(  | 
                  
| 111 | 1x | 
                      length(preds) == length(t)  | 
                  
| 112 | 
                      )  | 
                  |
| 113 | 1x | 
                      list(  | 
                  
| 114 | 1x | 
                      t = t,  | 
                  
| 115 | 1x | 
                      surv = preds[match_order(t)]  | 
                  
| 116 | 
                      )  | 
                  |
| 117 | 
                      }  | 
                  |
| 118 | ||
| 119 | 
                      #' Match Order  | 
                  |
| 120 | 
                      #'  | 
                  |
| 121 | 
                      #' @param x (`numeric`)\cr a vector for which we want to generate an index so other  | 
                  |
| 122 | 
                      #' vectors can be put into the same sort order  | 
                  |
| 123 | 
                      #'  | 
                  |
| 124 | 
                      #' Assuming we have a vector that is sorted then this function  | 
                  |
| 125 | 
                      #' will return the index vector to convert that sorted vector  | 
                  |
| 126 | 
                      #' into the same sort order as the input vector `x`.  | 
                  |
| 127 | 
                      #' For example let `x = 8, 7, 9 , 7`. If sorted we would get  | 
                  |
| 128 | 
                      #' `x_sort = 7, 7, 8, 9`. So in order to convert `x_sort`  | 
                  |
| 129 | 
                      #' back into `x` we'd need an index vector of `3, 1, 4, 2`.  | 
                  |
| 130 | 
                      #' This function is used to determine that corresponding  | 
                  |
| 131 | 
                      #' index vector for an arbitrarily sorted vector `x`.  | 
                  |
| 132 | 
                      #'  | 
                  |
| 133 | 
                      #' There is no specific handling of ties. It is assuming that in the case  | 
                  |
| 134 | 
                      #' of ties for `x` that the vector you are re-indexing also has tied values  | 
                  |
| 135 | 
                      #' thus the specific tied element selection does not matter.  | 
                  |
| 136 | 
                      #' @keywords internal  | 
                  |
| 137 | 
                      match_order <- function(x) {
                     | 
                  |
| 138 | 2x | 
                      order(order(x))  | 
                  
| 139 | 
                      }  | 
                  |
| 140 | ||
| 141 | ||
| 142 | 
                      #' Brier Score  | 
                  |
| 143 | 
                      #'  | 
                  |
| 144 | 
                      #' @inheritParams Brier-Score-Shared  | 
                  |
| 145 | 
                      #'  | 
                  |
| 146 | 
                      #' @description  | 
                  |
| 147 | 
                      #' Implements the Brier Score as detailed in \insertCite{blanche2015}{jmpost}
                     | 
                  |
| 148 | 
                      #'  | 
                  |
| 149 | 
                      #' @details  | 
                  |
| 150 | 
                      #' - `bs_get_squared_dist()` - implements the squared distance part  | 
                  |
| 151 | 
                      #' of the formula.  | 
                  |
| 152 | 
                      #' - `bs_get_weights()` - implements the IPCW weighting  | 
                  |
| 153 | 
                      #'  | 
                  |
| 154 | 
                      #' @references  | 
                  |
| 155 | 
                      #' \insertAllCited{}
                     | 
                  |
| 156 | 
                      #'  | 
                  |
| 157 | 
                      #' @keywords internal  | 
                  |
| 158 | 
                      brier_score <- function(  | 
                  |
| 159 | 
                      t,  | 
                  |
| 160 | 
                      times,  | 
                  |
| 161 | 
                      events,  | 
                  |
| 162 | 
                      pred_mat,  | 
                  |
| 163 | 
                      maintain_cen_order = TRUE,  | 
                  |
| 164 | 
                      event_offset = TRUE  | 
                  |
| 165 | 
                      ) {
                     | 
                  |
| 166 | ||
| 167 | 2x | 
                      square_diff_mat <- bs_get_squared_dist(  | 
                  
| 168 | 2x | 
                      t = t,  | 
                  
| 169 | 2x | 
                      times = times,  | 
                  
| 170 | 2x | 
                      events = events,  | 
                  
| 171 | 2x | 
                      pred_mat = pred_mat  | 
                  
| 172 | 
                      )  | 
                  |
| 173 | ||
| 174 | 2x | 
                      weight_mat <- bs_get_weights(  | 
                  
| 175 | 2x | 
                      t = t,  | 
                  
| 176 | 2x | 
                      times = times,  | 
                  
| 177 | 2x | 
                      events = events,  | 
                  
| 178 | 2x | 
                      event_offset = event_offset,  | 
                  
| 179 | 2x | 
                      maintain_cen_order = maintain_cen_order  | 
                  
| 180 | 
                      )  | 
                  |
| 181 | ||
| 182 | 
                      # the following is a computational shortcut for diag(A %*% B)  | 
                  |
| 183 | 
                      # as we don't want to compute the off-diagonal entries of the  | 
                  |
| 184 | 
                      # matrix multiplication  | 
                  |
| 185 | 2x | 
                      x <- colSums(weight_mat * square_diff_mat)  | 
                  
| 186 | 2x | 
                      names(x) <- t  | 
                  
| 187 | 2x | 
                      x / length(times)  | 
                  
| 188 | 
                      }  | 
                  |
| 189 | ||
| 190 | ||
| 191 | 
                      #' @rdname brier_score  | 
                  |
| 192 | 
                      bs_get_squared_dist <- function(t, times, events, pred_mat) {
                     | 
                  |
| 193 | ||
| 194 | 3x | 
                      assert_numeric(  | 
                  
| 195 | 3x | 
                      times,  | 
                  
| 196 | 3x | 
                      finite = TRUE,  | 
                  
| 197 | 3x | 
                      any.missing = FALSE  | 
                  
| 198 | 
                      )  | 
                  |
| 199 | 3x | 
                      assert_numeric(  | 
                  
| 200 | 3x | 
                      t,  | 
                  
| 201 | 3x | 
                      finite = TRUE,  | 
                  
| 202 | 3x | 
                      any.missing = FALSE  | 
                  
| 203 | 
                      )  | 
                  |
| 204 | 3x | 
                      assert_numeric(  | 
                  
| 205 | 3x | 
                      events,  | 
                  
| 206 | 3x | 
                      finite = TRUE,  | 
                  
| 207 | 3x | 
                      any.missing = FALSE,  | 
                  
| 208 | 3x | 
                      lower = 0,  | 
                  
| 209 | 3x | 
                      upper = 1  | 
                  
| 210 | 
                      )  | 
                  |
| 211 | 3x | 
                      assert_matrix(  | 
                  
| 212 | 3x | 
                      pred_mat,  | 
                  
| 213 | 3x | 
                      any.missing = FALSE,  | 
                  
| 214 | 3x | 
                      nrows = length(times),  | 
                  
| 215 | 3x | 
                      ncols = length(t)  | 
                  
| 216 | 
                      )  | 
                  |
| 217 | 3x | 
                      assert_that(  | 
                  
| 218 | 3x | 
                      length(events) == length(times)  | 
                  
| 219 | 
                      )  | 
                  |
| 220 | ||
| 221 | ||
| 222 | 3x | 
                      expected_mat <- mapply(  | 
                  
| 223 | 3x | 
                      \(ti, event) (ti <= t) * event * 1,  | 
                  
| 224 | 3x | 
                      ti = times,  | 
                  
| 225 | 3x | 
                      event = events,  | 
                  
| 226 | 3x | 
                      SIMPLIFY = FALSE  | 
                  
| 227 | 
                      ) |>  | 
                  |
| 228 | 3x | 
                      unlist() |>  | 
                  
| 229 | 3x | 
                      matrix(ncol = length(t), byrow = TRUE)  | 
                  
| 230 | ||
| 231 | 3x | 
                      assert_that(  | 
                  
| 232 | 3x | 
                      nrow(pred_mat) == nrow(expected_mat),  | 
                  
| 233 | 3x | 
                      ncol(pred_mat) == ncol(expected_mat)  | 
                  
| 234 | 
                      )  | 
                  |
| 235 | ||
| 236 | 3x | 
                      (expected_mat - pred_mat)^2  | 
                  
| 237 | 
                      }  | 
                  |
| 238 | ||
| 239 | ||
| 240 | 
                      #' @rdname brier_score  | 
                  |
| 241 | 
                      bs_get_weights <- function(  | 
                  |
| 242 | 
                      t,  | 
                  |
| 243 | 
                      times,  | 
                  |
| 244 | 
                      events,  | 
                  |
| 245 | 
                      event_offset = TRUE,  | 
                  |
| 246 | 
                      maintain_cen_order = TRUE  | 
                  |
| 247 | 
                      ) {
                     | 
                  |
| 248 | 3x | 
                      assert_numeric(  | 
                  
| 249 | 3x | 
                      times,  | 
                  
| 250 | 3x | 
                      finite = TRUE,  | 
                  
| 251 | 3x | 
                      any.missing = FALSE  | 
                  
| 252 | 
                      )  | 
                  |
| 253 | 3x | 
                      assert_numeric(  | 
                  
| 254 | 3x | 
                      t,  | 
                  
| 255 | 3x | 
                      finite = TRUE,  | 
                  
| 256 | 3x | 
                      any.missing = FALSE  | 
                  
| 257 | 
                      )  | 
                  |
| 258 | 3x | 
                      assert_numeric(  | 
                  
| 259 | 3x | 
                      events,  | 
                  
| 260 | 3x | 
                      finite = TRUE,  | 
                  
| 261 | 3x | 
                      any.missing = FALSE,  | 
                  
| 262 | 3x | 
                      lower = 0,  | 
                  
| 263 | 3x | 
                      upper = 1  | 
                  
| 264 | 
                      )  | 
                  |
| 265 | 3x | 
                      assert_flag(event_offset, na.ok = FALSE, null.ok = FALSE)  | 
                  
| 266 | 3x | 
                      assert_flag(maintain_cen_order, na.ok = FALSE, null.ok = FALSE)  | 
                  
| 267 | 3x | 
                      n_col <- length(t)  | 
                  
| 268 | 3x | 
                      n_row <- length(times)  | 
                  
| 269 | ||
| 270 | 3x | 
                      reverse_km <- if (maintain_cen_order) reverse_km_event_first else reverse_km_cen_first  | 
                  
| 271 | 3x | 
                      offset <- if (event_offset) -.Machine$double.eps^(1 / 2) else 0  | 
                  
| 272 | ||
| 273 | 3x | 
                      censor_dist_t <- reverse_km(t, times, events)  | 
                  
| 274 | 3x | 
                      weight_mat_t <- 1 / matrix(  | 
                  
| 275 | 3x | 
                      rep(censor_dist_t$surv, n_row),  | 
                  
| 276 | 3x | 
                      nrow = n_row,  | 
                  
| 277 | 3x | 
                      byrow = TRUE  | 
                  
| 278 | 
                      )  | 
                  |
| 279 | ||
| 280 | 3x | 
                      censor_dist_ti <- reverse_km(times + offset, times, events)  | 
                  
| 281 | 3x | 
                      weight_mat_ti <- 1 / matrix(  | 
                  
| 282 | 3x | 
                      rep(censor_dist_ti$surv, n_col),  | 
                  
| 283 | 3x | 
                      nrow = n_row  | 
                  
| 284 | 
                      )  | 
                  |
| 285 | ||
| 286 | 3x | 
                      indicator_mat_t <- mapply(  | 
                  
| 287 | 3x | 
                      \(ti) (ti > t) * 1,  | 
                  
| 288 | 3x | 
                      ti = times,  | 
                  
| 289 | 3x | 
                      SIMPLIFY = FALSE  | 
                  
| 290 | 
                      ) |>  | 
                  |
| 291 | 3x | 
                      unlist() |>  | 
                  
| 292 | 3x | 
                      matrix(ncol = n_col, byrow = TRUE)  | 
                  
| 293 | ||
| 294 | 3x | 
                      indicator_mat_ti <- mapply(  | 
                  
| 295 | 3x | 
                      \(ti, event) (ti <= t) * event * 1,  | 
                  
| 296 | 3x | 
                      ti = times,  | 
                  
| 297 | 3x | 
                      event = events,  | 
                  
| 298 | 3x | 
                      SIMPLIFY = FALSE  | 
                  
| 299 | 
                      ) |>  | 
                  |
| 300 | 3x | 
                      unlist() |>  | 
                  
| 301 | 3x | 
                      matrix(ncol = n_col, byrow = TRUE)  | 
                  
| 302 | ||
| 303 | 3x | 
                      assert_that(  | 
                  
| 304 | 3x | 
                      all(indicator_mat_t + indicator_mat_ti <= 1)  | 
                  
| 305 | 
                      )  | 
                  |
| 306 | ||
| 307 | 3x | 
                      weight_mat_t[indicator_mat_t == 0] <- 0  | 
                  
| 308 | 3x | 
                      weight_mat_ti[indicator_mat_ti == 0] <- 0  | 
                  
| 309 | ||
| 310 | 3x | 
                      (weight_mat_t + weight_mat_ti)  | 
                  
| 311 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include StanModule.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      #' @include ParameterList.R  | 
                  |
| 5 | 
                      #' @include DataJoint.R  | 
                  |
| 6 | 
                      #' @include DataSurvival.R  | 
                  |
| 7 | 
                      #' @include DataLongitudinal.R  | 
                  |
| 8 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 9 | 
                      #' @include SurvivalModel.R  | 
                  |
| 10 | 
                      #' @include Link.R  | 
                  |
| 11 | 
                      #' @include constants.R  | 
                  |
| 12 | 
                      NULL  | 
                  |
| 13 | ||
| 14 | ||
| 15 | 
                      #' Re-used documentation for `JointModel-Shared`  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @param object ([`JointModel`]) \cr Joint model specification.  | 
                  |
| 18 | 
                      #' @param x ([`JointModel`]) \cr Joint model specification.  | 
                  |
| 19 | 
                      #' @param ... Not Used.  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @name JointModel-Shared  | 
                  |
| 22 | 
                      #' @keywords internal  | 
                  |
| 23 | 
                      NULL  | 
                  |
| 24 | ||
| 25 | 
                      setClassUnion("LongitudinalModel_OR_NULL", c("LongitudinalModel", "NULL"))
                     | 
                  |
| 26 | 
                      setClassUnion("SurvivalModel_OR_NULL", c("SurvivalModel", "NULL"))
                     | 
                  |
| 27 | ||
| 28 | 
                      # JointModel-class ----  | 
                  |
| 29 | ||
| 30 | 
                      #' Joint Model Object and Constructor Function  | 
                  |
| 31 | 
                      #'  | 
                  |
| 32 | 
                      #' @slot longitudinal ([`LongitudinalModel`] or `NULL`)\cr the longitudinal model.  | 
                  |
| 33 | 
                      #' @slot survival ([`SurvivalModel`] or `NULL`)\cr the survival model.  | 
                  |
| 34 | 
                      #' @slot link (`Link`)\cr the link.  | 
                  |
| 35 | 
                      #' @slot parameters (`ParameterList`)\cr the parameter specification.  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' @family JointModel  | 
                  |
| 38 | 
                      #' @export JointModel  | 
                  |
| 39 | 
                      #' @exportClass JointModel  | 
                  |
| 40 | 
                      .JointModel <- setClass(  | 
                  |
| 41 | 
                      Class = "JointModel",  | 
                  |
| 42 | 
                      slots = list(  | 
                  |
| 43 | 
                      longitudinal = "LongitudinalModel_OR_NULL",  | 
                  |
| 44 | 
                      survival = "SurvivalModel_OR_NULL",  | 
                  |
| 45 | 
                      link = "Link",  | 
                  |
| 46 | 
                      parameters = "ParameterList"  | 
                  |
| 47 | 
                      )  | 
                  |
| 48 | 
                      )  | 
                  |
| 49 | ||
| 50 | 
                      #' @param longitudinal ([`LongitudinalModel`] or `NULL`)\cr the longitudinal model.  | 
                  |
| 51 | 
                      #' @param survival ([`SurvivalModel`] or `NULL`)\cr the survival model.  | 
                  |
| 52 | 
                      #' @param link (`Link`)\cr the link.  | 
                  |
| 53 | 
                      #' @rdname JointModel-class  | 
                  |
| 54 | 
                      JointModel <- function(  | 
                  |
| 55 | 
                      longitudinal = NULL,  | 
                  |
| 56 | 
                      survival = NULL,  | 
                  |
| 57 | 
                      link = Link()  | 
                  |
| 58 | 
                      ) {
                     | 
                  |
| 59 | 36x | 
                      link <- resolvePromise(Link(link), longitudinal)  | 
                  
| 60 | ||
| 61 | 36x | 
                          if (length(link) > 0) {
                     | 
                  
| 62 | 11x | 
                      longitudinal <- enableLink(longitudinal)  | 
                  
| 63 | 
                      }  | 
                  |
| 64 | ||
| 65 | 36x | 
                      parameters <- Reduce(  | 
                  
| 66 | 36x | 
                      merge,  | 
                  
| 67 | 36x | 
                      list(  | 
                  
| 68 | 36x | 
                      getParameters(longitudinal),  | 
                  
| 69 | 36x | 
                      getParameters(survival),  | 
                  
| 70 | 36x | 
                      getParameters(link)  | 
                  
| 71 | 
                      )  | 
                  |
| 72 | 
                      )  | 
                  |
| 73 | ||
| 74 | 36x | 
                      .JointModel(  | 
                  
| 75 | 36x | 
                      longitudinal = longitudinal,  | 
                  
| 76 | 36x | 
                      survival = survival,  | 
                  
| 77 | 36x | 
                      link = link,  | 
                  
| 78 | 36x | 
                      parameters = parameters  | 
                  
| 79 | 
                      )  | 
                  |
| 80 | 
                      }  | 
                  |
| 81 | ||
| 82 | ||
| 83 | 
                      #' @export  | 
                  |
| 84 | 
                      enableGQ.JointModel <- function(object, ...) {
                     | 
                  |
| 85 | 38x | 
                      merge(  | 
                  
| 86 | 38x | 
                      enableGQ(object@survival),  | 
                  
| 87 | 38x | 
                      enableGQ(object@longitudinal)  | 
                  
| 88 | 
                      )  | 
                  |
| 89 | 
                      }  | 
                  |
| 90 | ||
| 91 | ||
| 92 | 
                      #' `JointModel` -> `StanModule`  | 
                  |
| 93 | 
                      #'  | 
                  |
| 94 | 
                      #' Converts a [`JointModel`] object to a [`StanModule`] object  | 
                  |
| 95 | 
                      #'  | 
                  |
| 96 | 
                      #' @inheritParams JointModel-Shared  | 
                  |
| 97 | 
                      #' @family JointModel  | 
                  |
| 98 | 
                      #' @family as.StanModule  | 
                  |
| 99 | 
                      #' @export  | 
                  |
| 100 | 
                      as.StanModule.JointModel <- function(object, ...) {
                     | 
                  |
| 101 | ||
| 102 | 70x | 
                          base_model <- read_stan("base/base.stan")
                     | 
                  
| 103 | ||
| 104 | 70x | 
                      stan_full <- decorated_render(  | 
                  
| 105 | 70x | 
                      .x = base_model,  | 
                  
| 106 | 70x | 
                      longitudinal = add_missing_stan_blocks(as.list(object@longitudinal)),  | 
                  
| 107 | 70x | 
                      survival = add_missing_stan_blocks(as.list(object@survival)),  | 
                  
| 108 | 70x | 
                      link = add_missing_stan_blocks(as.list(object@link)),  | 
                  
| 109 | 70x | 
                      priors = add_missing_stan_blocks(as.list(object@parameters))  | 
                  
| 110 | 
                      )  | 
                  |
| 111 | 
                      # Unresolved Jinja code within the longitudinal / Survival / Link  | 
                  |
| 112 | 
                      # models won't be resolved by the above call to `decorated_render`.  | 
                  |
| 113 | 
                      # Instead they it will just be inserted into the template asis. Thus  | 
                  |
| 114 | 
                      # we run `decorated_render` again to resolve any lingering Jinja code  | 
                  |
| 115 | 
                      # Main example being models that don't have any Jinja code but still  | 
                  |
| 116 | 
                      # use the `decorated_render` constants `machine_double_eps`.  | 
                  |
| 117 | 70x | 
                      stan_full <- decorated_render(.x = stan_full)  | 
                  
| 118 | ||
| 119 | 70x | 
                      x <- merge(  | 
                  
| 120 | 70x | 
                              StanModule("base/functions.stan"),
                     | 
                  
| 121 | 70x | 
                      StanModule(stan_full)  | 
                  
| 122 | 
                      )  | 
                  |
| 123 | ||
| 124 | 70x | 
                      return(x)  | 
                  
| 125 | 
                      }  | 
                  |
| 126 | ||
| 127 | ||
| 128 | ||
| 129 | 
                      #' `JointModel` -> `character`  | 
                  |
| 130 | 
                      #'  | 
                  |
| 131 | 
                      #' Renders a [`JointModel`] object to a stan program  | 
                  |
| 132 | 
                      #'  | 
                  |
| 133 | 
                      #' @inheritParams JointModel-Shared  | 
                  |
| 134 | 
                      #' @family JointModel  | 
                  |
| 135 | 
                      #' @export  | 
                  |
| 136 | 
                      as.character.JointModel <- function(x, ...) {
                     | 
                  |
| 137 | 3x | 
                      as.character(as.StanModule(x))  | 
                  
| 138 | 
                      }  | 
                  |
| 139 | ||
| 140 | ||
| 141 | 
                      # write_stan-JointModel ----  | 
                  |
| 142 | ||
| 143 | 
                      #' @rdname write_stan  | 
                  |
| 144 | 
                      #' @export  | 
                  |
| 145 | 
                      write_stan.JointModel <- function(object, destination, ...) {
                     | 
                  |
| 146 | ! | 
                          if (is_connection(destination)) {
                     | 
                  
| 147 | ! | 
                      return(writeLines(as.character(object), con = destination))  | 
                  
| 148 | 
                      }  | 
                  |
| 149 | ! | 
                      fi <- file(destination, open = "w")  | 
                  
| 150 | ! | 
                      writeLines(as.character(object), con = fi)  | 
                  
| 151 | ! | 
                      close(fi)  | 
                  
| 152 | 
                      }  | 
                  |
| 153 | ||
| 154 | ||
| 155 | 
                      # compileStanModel-JointModel ----  | 
                  |
| 156 | ||
| 157 | 
                      #' @rdname compileStanModel  | 
                  |
| 158 | 
                      #' @export  | 
                  |
| 159 | 
                      compileStanModel.JointModel <- function(object) {
                     | 
                  |
| 160 | 17x | 
                      object |>  | 
                  
| 161 | 17x | 
                      as.StanModule() |>  | 
                  
| 162 | 17x | 
                      compileStanModel() |>  | 
                  
| 163 | 17x | 
                      invisible()  | 
                  
| 164 | 
                      }  | 
                  |
| 165 | ||
| 166 | ||
| 167 | 
                      # sampleStanModel-JointModel ----  | 
                  |
| 168 | ||
| 169 | 
                      #' @rdname sampleStanModel  | 
                  |
| 170 | 
                      #'  | 
                  |
| 171 | 
                      #' @param data (`DataJoint` or `list`)\cr input data.  | 
                  |
| 172 | 
                      #' @export  | 
                  |
| 173 | 
                      sampleStanModel.JointModel <- function(object, data, ...) {
                     | 
                  |
| 174 | ||
| 175 | 17x | 
                      assert_class(data, "DataJoint")  | 
                  
| 176 | ||
| 177 | 17x | 
                          if (!is.null(object@survival)) {
                     | 
                  
| 178 | 14x | 
                      assert_that(  | 
                  
| 179 | 14x | 
                      !is.null(data@survival),  | 
                  
| 180 | 14x | 
                      msg = "`DataSurvival` can't be missing if a `SurvivalModel` has been specified"  | 
                  
| 181 | 
                      )  | 
                  |
| 182 | 
                      }  | 
                  |
| 183 | 
                          if (!is.null(object@longitudinal)) {
                     | 
                  |
| 184 | 13x | 
                      assert_that(  | 
                  
| 185 | 13x | 
                      !is.null(data@longitudinal),  | 
                  
| 186 | 13x | 
                      msg = "`DataLongitudinal` can't be missing if a `LongitudinalModel` has been specified"  | 
                  
| 187 | 
                      )  | 
                  |
| 188 | 
                      }  | 
                  |
| 189 | ||
| 190 | 17x | 
                      args <- list(...)  | 
                  
| 191 | ||
| 192 | 17x | 
                      args[["data"]] <- append(  | 
                  
| 193 | 17x | 
                      as_stan_list(data),  | 
                  
| 194 | 17x | 
                      as_stan_list(object@parameters)  | 
                  
| 195 | 
                      )  | 
                  |
| 196 | ||
| 197 | 17x | 
                          args[["chains"]] <- if ("chains" %in% names(args)) {
                     | 
                  
| 198 | 17x | 
                      args[["chains"]]  | 
                  
| 199 | 
                          } else {
                     | 
                  |
| 200 | 
                      # Magic constant from R/constants.R  | 
                  |
| 201 | ! | 
                      CMDSTAN_DEFAULT_CHAINS  | 
                  
| 202 | 
                      }  | 
                  |
| 203 | ||
| 204 | 17x | 
                          initial_values <- if ("init" %in% names(args)) {
                     | 
                  
| 205 | ! | 
                      args[["init"]]  | 
                  
| 206 | 
                          } else {
                     | 
                  |
| 207 | 17x | 
                      initialValues(object, n_chains = args[["chains"]])  | 
                  
| 208 | 
                      }  | 
                  |
| 209 | ||
| 210 | 17x | 
                      args[["init"]] <- ensure_initial_values(  | 
                  
| 211 | 17x | 
                      initial_values,  | 
                  
| 212 | 17x | 
                      args[["data"]],  | 
                  
| 213 | 17x | 
                      object@parameters  | 
                  
| 214 | 
                      )  | 
                  |
| 215 | ||
| 216 | 17x | 
                      model <- compileStanModel(object)  | 
                  
| 217 | ||
| 218 | 17x | 
                      results <- do.call(  | 
                  
| 219 | 17x | 
                      model$sample,  | 
                  
| 220 | 17x | 
                      args  | 
                  
| 221 | 
                      )  | 
                  |
| 222 | ||
| 223 | 17x | 
                      .JointModelSamples(  | 
                  
| 224 | 17x | 
                      model = object,  | 
                  
| 225 | 17x | 
                      data = data,  | 
                  
| 226 | 17x | 
                      results = results  | 
                  
| 227 | 
                      )  | 
                  |
| 228 | 
                      }  | 
                  |
| 229 | ||
| 230 | ||
| 231 | 
                      #' Ensure that initial values are correctly specified  | 
                  |
| 232 | 
                      #'  | 
                  |
| 233 | 
                      #' @param initial_values (`list`)\cr A list of lists containing the initial values  | 
                  |
| 234 | 
                      #' must be 1 list per desired chain. All elements should have identical names  | 
                  |
| 235 | 
                      #' @param data (`list`)\cr specifies the size to expand each of our initial values to be.  | 
                  |
| 236 | 
                      #' That is elements of size 1 in `initial_values` will be expanded to be the same  | 
                  |
| 237 | 
                      #' size as the corresponding element in `data` by broadcasting the value.  | 
                  |
| 238 | 
                      #' @param parameters ([`ParameterList`])\cr the parameters object  | 
                  |
| 239 | 
                      #'  | 
                  |
| 240 | 
                      #' @details  | 
                  |
| 241 | 
                      #' This function is mostly a thin wrapper around `expand_initial_values` to  | 
                  |
| 242 | 
                      #' enable easier unit testing.  | 
                  |
| 243 | 
                      #'  | 
                  |
| 244 | 
                      #' @keywords internal  | 
                  |
| 245 | 
                      ensure_initial_values <- function(initial_values, data, parameters) {
                     | 
                  |
| 246 | 18x | 
                          if (is.function(initial_values)) {
                     | 
                  
| 247 | ! | 
                      return(initial_values)  | 
                  
| 248 | 
                      }  | 
                  |
| 249 | ||
| 250 | 18x | 
                      assert_class(data, "list")  | 
                  
| 251 | 18x | 
                      assert_class(parameters, "ParameterList")  | 
                  
| 252 | 18x | 
                      assert_class(initial_values, "list")  | 
                  
| 253 | ||
| 254 | 18x | 
                      values_sizes <- size(parameters)  | 
                  
| 255 | 18x | 
                      values_sizes_complete <- replace_with_lookup(  | 
                  
| 256 | 18x | 
                      values_sizes,  | 
                  
| 257 | 18x | 
                      data  | 
                  
| 258 | 
                      )  | 
                  |
| 259 | 18x | 
                      lapply(  | 
                  
| 260 | 18x | 
                      initial_values,  | 
                  
| 261 | 18x | 
                      expand_initial_values,  | 
                  
| 262 | 18x | 
                      sizes = values_sizes_complete  | 
                  
| 263 | 
                      )  | 
                  |
| 264 | 
                      }  | 
                  |
| 265 | ||
| 266 | ||
| 267 | ||
| 268 | 
                      #' @rdname initialValues  | 
                  |
| 269 | 
                      #' @export  | 
                  |
| 270 | 
                      initialValues.JointModel <- function(object, n_chains, ...) {
                     | 
                  |
| 271 | 19x | 
                      initialValues(object@parameters, n_chains)  | 
                  
| 272 | 
                      }  | 
                  |
| 273 | ||
| 274 | ||
| 275 | 
                      pad_with_white_space <- function(x, pad = 4) {
                     | 
                  |
| 276 | 3x | 
                          padding <- paste0(rep(" ", each = pad), collapse = "")
                     | 
                  
| 277 | 3x | 
                      x_sep <- x |>  | 
                  
| 278 | 3x | 
                      strsplit(split = "\n") |>  | 
                  
| 279 | 3x | 
                      unlist()  | 
                  
| 280 | 3x | 
                      x_padded <- paste(padding, x_sep) |>  | 
                  
| 281 | 3x | 
                      paste(collapse = "\n")  | 
                  
| 282 | 3x | 
                      return(x_padded)  | 
                  
| 283 | 
                      }  | 
                  |
| 284 | ||
| 285 | ||
| 286 | 
                      #' @rdname show-object  | 
                  |
| 287 | 
                      #' @export  | 
                  |
| 288 | 
                      setMethod(  | 
                  |
| 289 | 
                      f = "show",  | 
                  |
| 290 | 
                      signature = "JointModel",  | 
                  |
| 291 | 
                          definition = function(object) {
                     | 
                  |
| 292 | 1x | 
                              survival_string <- if (is.null(object@survival)) {
                     | 
                  
| 293 | ! | 
                      "\n Not Specified\n"  | 
                  
| 294 | 
                              } else {
                     | 
                  |
| 295 | 1x | 
                      as_print_string(object@survival) |> pad_with_white_space()  | 
                  
| 296 | 
                      }  | 
                  |
| 297 | ||
| 298 | 1x | 
                              longitudinal_string <- if (is.null(object@longitudinal)) {
                     | 
                  
| 299 | ! | 
                      "\n Not Specified\n"  | 
                  
| 300 | 
                              } else {
                     | 
                  |
| 301 | 1x | 
                      as_print_string(object@longitudinal) |> pad_with_white_space()  | 
                  
| 302 | 
                      }  | 
                  |
| 303 | ||
| 304 | 1x | 
                      link_string <- as_print_string(object@link) |> pad_with_white_space()  | 
                  
| 305 | ||
| 306 | 1x | 
                      string <- "\nA Joint Model with:\n\n Survival:%s\n Longitudinal:%s\n Link:%s\n"  | 
                  
| 307 | 1x | 
                      cat(sprintf(  | 
                  
| 308 | 1x | 
                      string,  | 
                  
| 309 | 1x | 
                      survival_string,  | 
                  
| 310 | 1x | 
                      longitudinal_string,  | 
                  
| 311 | 1x | 
                      link_string  | 
                  
| 312 | 
                      ))  | 
                  |
| 313 | 
                      }  | 
                  |
| 314 | 
                      )  | 
                  
| 1 | 
                      #' Simulating Joint Longitudinal and Time-to-Event Data  | 
                  |
| 2 | 
                      #'  | 
                  |
| 3 | 
                      #' @param design (`list`)\cr a list of [`SimGroup`] objects. See details.  | 
                  |
| 4 | 
                      #' @param longitudinal ([`SimLongitudinal`])\cr object specifying how to simulate the longitudinal data  | 
                  |
| 5 | 
                      #' @param survival ([`SimSurvival`])\cr object specifying how to simulate the survival data  | 
                  |
| 6 | 
                      #' @param .silent (`flag`)\cr whether to suppress info messages  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @slot longitudinal (`data.frame`)\cr the simulated longitudinal data.  | 
                  |
| 9 | 
                      #' @slot survival (`data.frame`)\cr the simulated survival data.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @details  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' The `design` argument is used to specify how many distinct groups should be simulated  | 
                  |
| 14 | 
                      #' including key information such as the number of subjects within the group as well as  | 
                  |
| 15 | 
                      #' which treatment arm and study the group belongs to. The `design` argument should be a  | 
                  |
| 16 | 
                      #' list of [`SimGroup`] objects e.g.  | 
                  |
| 17 | 
                      #' ```  | 
                  |
| 18 | 
                      #' design = list(  | 
                  |
| 19 | 
                      #' SimGroup(n = 50, study = "Study-1", arm = "Arm-A"),  | 
                  |
| 20 | 
                      #' SimGroup(n = 50, study = "Study-1", arm = "Arm-B")  | 
                  |
| 21 | 
                      #' )  | 
                  |
| 22 | 
                      #' ```  | 
                  |
| 23 | 
                      #'  | 
                  |
| 24 | 
                      #' @name SimJointData-class  | 
                  |
| 25 | 
                      #' @exportClass SimJointData  | 
                  |
| 26 | 
                      .SimJointData <- setClass(  | 
                  |
| 27 | 
                      "SimJointData",  | 
                  |
| 28 | 
                      slots = list(  | 
                  |
| 29 | 
                      longitudinal = "data.frame",  | 
                  |
| 30 | 
                      survival = "data.frame"  | 
                  |
| 31 | 
                      )  | 
                  |
| 32 | 
                      )  | 
                  |
| 33 | ||
| 34 | ||
| 35 | ||
| 36 | 
                      #' @rdname SimJointData-class  | 
                  |
| 37 | 
                      #' @export  | 
                  |
| 38 | 
                      SimJointData <- function(  | 
                  |
| 39 | 
                      design = list(  | 
                  |
| 40 | 
                      SimGroup(n = 50, study = "Study-1", arm = "Arm-A"),  | 
                  |
| 41 | 
                      SimGroup(n = 50, study = "Study-1", arm = "Arm-B")  | 
                  |
| 42 | 
                      ),  | 
                  |
| 43 | 
                      longitudinal,  | 
                  |
| 44 | 
                      survival,  | 
                  |
| 45 | 
                      .silent = FALSE  | 
                  |
| 46 | 
                      ) {
                     | 
                  |
| 47 | ||
| 48 | 22x | 
                      assert(  | 
                  
| 49 | 22x | 
                      all(vapply(design, \(x) is(x, "SimGroup"), logical(1))),  | 
                  
| 50 | 22x | 
                      msg = "All elements of `design` must be of class `SimGroup`"  | 
                  
| 51 | 
                      )  | 
                  |
| 52 | ||
| 53 | 22x | 
                      hazard_evaluation_info <- hazardWindows(survival)  | 
                  
| 54 | ||
| 55 | 22x | 
                      n_group <- vapply(design, function(x) x@n, numeric(1))  | 
                  
| 56 | 22x | 
                      arms <- vapply(design, function(x) x@arm, character(1))  | 
                  
| 57 | 22x | 
                      studies <- vapply(design, function(x) x@study, character(1))  | 
                  
| 58 | 22x | 
                      n_subjects <- sum(n_group)  | 
                  
| 59 | 22x | 
                      n_times <- length(hazard_evaluation_info$midpoint)  | 
                  
| 60 | ||
| 61 | 22x | 
                          sprintf_string <- paste0("subject_%0", ceiling(log(n_subjects, 10)) + 1, "i")
                     | 
                  
| 62 | ||
| 63 | 22x | 
                      baseline <- dplyr::tibble(subject = sprintf(sprintf_string, seq_len(n_subjects))) |>  | 
                  
| 64 | 22x | 
                      dplyr::mutate(arm = factor(rep(arms, times = n_group), levels = unique(arms))) |>  | 
                  
| 65 | 22x | 
                      dplyr::mutate(study = factor(rep(studies, times = n_group), levels = unique(studies)))  | 
                  
| 66 | ||
| 67 | 22x | 
                      os_baseline <- sampleSubjects(survival, subjects_df = baseline)  | 
                  
| 68 | 22x | 
                      lm_baseline <- sampleSubjects(longitudinal, subjects_df = baseline)  | 
                  
| 69 | ||
| 70 | 22x | 
                      lm_dat_no_obvs <- lapply(  | 
                  
| 71 | 22x | 
                      longitudinal@times,  | 
                  
| 72 | 22x | 
                              \(time) {
                     | 
                  
| 73 | 4544x | 
                      baseline[["time"]] <- time  | 
                  
| 74 | 4544x | 
                      baseline  | 
                  
| 75 | 
                      }  | 
                  |
| 76 | 
                      ) |>  | 
                  |
| 77 | 22x | 
                      dplyr::bind_rows() |>  | 
                  
| 78 | 22x | 
                              dplyr::left_join(lm_baseline, by = c("subject", "study", "arm"))
                     | 
                  
| 79 | ||
| 80 | 22x | 
                      lm_dat <- sampleObservations(longitudinal, lm_dat_no_obvs)  | 
                  
| 81 | ||
| 82 | ||
| 83 | 22x | 
                      hazard_eval_df <- dplyr::tibble(  | 
                  
| 84 | 22x | 
                      subject = rep(lm_baseline$subject, each = n_times),  | 
                  
| 85 | 22x | 
                      arm = rep(lm_baseline$arm, each = n_times),  | 
                  
| 86 | 22x | 
                      study = rep(lm_baseline$study, each = n_times),  | 
                  
| 87 | 22x | 
                      midpoint = rep(as.double(hazard_evaluation_info$midpoint), times = n_subjects),  | 
                  
| 88 | 22x | 
                      time = rep(as.double(hazard_evaluation_info$upper), times = n_subjects),  | 
                  
| 89 | 22x | 
                      width = rep(as.double(hazard_evaluation_info$width), times = n_subjects)  | 
                  
| 90 | 
                      )  | 
                  |
| 91 | ||
| 92 | 22x | 
                      lm_link_dat <- sampleObservations(  | 
                  
| 93 | 22x | 
                      longitudinal,  | 
                  
| 94 | 22x | 
                              dplyr::left_join(hazard_eval_df, lm_baseline, by = c("subject", "study", "arm"))
                     | 
                  
| 95 | 22x | 
                          )[, c("subject", "study", "arm", "log_haz_link", "time", "width", "midpoint")]
                     | 
                  
| 96 | ||
| 97 | 22x | 
                      os_eval_df <- lm_link_dat |>  | 
                  
| 98 | 22x | 
                              dplyr::left_join(os_baseline, by = c("subject", "study", "arm"))
                     | 
                  
| 99 | ||
| 100 | 22x | 
                      withCallingHandlers(  | 
                  
| 101 | 22x | 
                      os_dat <- sampleObservations(survival, os_eval_df),  | 
                  
| 102 | 22x | 
                              message = function(e) {
                     | 
                  
| 103 | ! | 
                      if (!.silent) message(e)  | 
                  
| 104 | 10x | 
                                  invokeRestart("muffleMessage")
                     | 
                  
| 105 | 
                      }  | 
                  |
| 106 | 
                      )  | 
                  |
| 107 | ||
| 108 | 22x | 
                      lm_dat2 <- lm_dat |>  | 
                  
| 109 | 22x | 
                      dplyr::left_join(dplyr::select(os_dat, "subject", os_time = "time"), by = "subject") |>  | 
                  
| 110 | 22x | 
                      dplyr::mutate(observed = (.data$time <= .data$os_time)) |>  | 
                  
| 111 | 22x | 
                              dplyr::arrange(dplyr::pick(c("subject", "time")))
                     | 
                  
| 112 | ||
| 113 | 22x | 
                      assert_that(  | 
                  
| 114 | 22x | 
                      length(unique(os_dat$subject)) == length(os_dat$subject),  | 
                  
| 115 | 22x | 
                      length(os_dat$subject) == n_subjects,  | 
                  
| 116 | 22x | 
                      all(os_dat$time >= 0),  | 
                  
| 117 | 22x | 
                      all(os_dat$event %in% c(0, 1)),  | 
                  
| 118 | 22x | 
                      msg = "Assumptions for the Survival data are not met (please report this issue)"  | 
                  
| 119 | 
                      )  | 
                  |
| 120 | ||
| 121 | 22x | 
                      assert_that(  | 
                  
| 122 | 22x | 
                      nrow(lm_dat2) == n_subjects * length(longitudinal@times),  | 
                  
| 123 | 22x | 
                      length(unique(lm_dat2$subject)) == n_subjects,  | 
                  
| 124 | 22x | 
                      msg = "Assumptions for the Longitudinal data are not met (please report this issue)"  | 
                  
| 125 | 
                      )  | 
                  |
| 126 | ||
| 127 | 22x | 
                      return(  | 
                  
| 128 | 22x | 
                      .SimJointData(  | 
                  
| 129 | 22x | 
                      survival = os_dat,  | 
                  
| 130 | 22x | 
                                  longitudinal = lm_dat2[, c("subject", "arm", "study", "time", "sld", "observed")]
                     | 
                  
| 131 | 
                      )  | 
                  |
| 132 | 
                      )  | 
                  |
| 133 | 
                      }  | 
                  |
| 134 | ||
| 135 | 
                      #' @rdname show-object  | 
                  |
| 136 | 
                      #' @export  | 
                  |
| 137 | 
                      setMethod(  | 
                  |
| 138 | 
                      f = "show",  | 
                  |
| 139 | 
                      signature = "SimJointData",  | 
                  |
| 140 | 
                          definition = function(object) {
                     | 
                  |
| 141 | 1x | 
                              x <- sprintf("\nA SimJointData Object\n\n")
                     | 
                  
| 142 | 1x | 
                      cat(x)  | 
                  
| 143 | 1x | 
                      return(object)  | 
                  
| 144 | 
                      }  | 
                  |
| 145 | 
                      )  | 
                  
| 1 | ||
| 2 | 
                      #' Quantity Grid Specification  | 
                  |
| 3 | 
                      #'  | 
                  |
| 4 | 
                      #' @param subjects (`character` or `NULL`)\cr vector of subjects to extract quantities for.  | 
                  |
| 5 | 
                      #' If `NULL` will default to all subjects within the dataset.  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' @param times (`numeric` or `NULL`)\cr vector of time points to extract quantities at.  | 
                  |
| 8 | 
                      #' If `NULL` will default to 201 evenly spaced timepoints between 0 and either the max  | 
                  |
| 9 | 
                      #' observation time (for [`LongitudinalQuantities`]) or max event time (for [`SurvivalQuantities`]).  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @param groups (`list`)\cr named list of subjects to extract quantities for. See Group Specification.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @param spec (`list`)\cr named list of subjects to extract quantities for. The names of each  | 
                  |
| 14 | 
                      #' element should be the required subjects with the element itself being a numeric vector of timepoints  | 
                  |
| 15 | 
                      #' to generate the quantity at.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @param length.out (`numeric`)\cr number of evenly spaced timepoints to generate quantities at.  | 
                  |
| 18 | 
                      #'  | 
                  |
| 19 | 
                      #' @param newdata (`data.frame`) \cr new data to generate quantities for. Must contain the same columns  | 
                  |
| 20 | 
                      #' and factor levels of the original data used in the [`DataSurvival`] object.  | 
                  |
| 21 | 
                      #'  | 
                  |
| 22 | 
                      #' @param params (`list`)\cr named list of parameters to fix the longitudinal model parameters at when  | 
                  |
| 23 | 
                      #' predicting survival quantities. See [`getPredictionNames()`] for the required parameters.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @description  | 
                  |
| 26 | 
                      #' These functions are used to specify which subjects and timepoints should be generated  | 
                  |
| 27 | 
                      #' when calculating quantities via [`SurvivalQuantities`] and [`LongitudinalQuantities`].  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @details  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' - `GridFixed()` is used to specify a fixed set of timepoints to generate quantities at for  | 
                  |
| 32 | 
                      #' all the specified subjects.  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' - `GridGrouped()` is similar to `GridFixed()` but allows for groupwise averaging  | 
                  |
| 35 | 
                      #' (see Group Specification).  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' - `GridObserved()` generates quantities at the observed longitudinal timepoints for each  | 
                  |
| 38 | 
                      #' subject.  | 
                  |
| 39 | 
                      #'  | 
                  |
| 40 | 
                      #' - `GridManual()` allows for individual timepoint specification for each subject.  | 
                  |
| 41 | 
                      #'  | 
                  |
| 42 | 
                      #' - `GridEven()` generates quantities for each subject at N evenly spaced timepoints  | 
                  |
| 43 | 
                      #' between each subjects first and last longitudinal observations.  | 
                  |
| 44 | 
                      #'  | 
                  |
| 45 | 
                      #' - `GridEvent()` generates one quantity for each subject at their event/censor time  | 
                  |
| 46 | 
                      #' as indicated by the `time` variable in the survival dataset.  | 
                  |
| 47 | 
                      #'  | 
                  |
| 48 | 
                      #' - `GridPopulation()` generates longitudinal model quantities based on the population parameters at the  | 
                  |
| 49 | 
                      #' specified time points. Generates 1 set of quantities for each distinct combination of `arm`  | 
                  |
| 50 | 
                      #' and `study` within the [`DataSubject`] object provided to the [`JointModel`].  | 
                  |
| 51 | 
                      #'  | 
                  |
| 52 | 
                      #' - `GridPrediction()` generates survival quantities based on any user-defined values at the  | 
                  |
| 53 | 
                      #' specified time points. This is useful for generating quantities for a new dataset  | 
                  |
| 54 | 
                      #' on specific longitudinal model parameters. See [`getPredictionNames()`] to determine which  | 
                  |
| 55 | 
                      #' longitudinal model parameters need to be defined for a given longitudinal model.  | 
                  |
| 56 | 
                      #'  | 
                  |
| 57 | 
                      #' @section Group Specification:  | 
                  |
| 58 | 
                      #' For `GridGrouped()`, `groups` must be a named list of character vectors. Each element of the list  | 
                  |
| 59 | 
                      #' must be a character vector of the subjects that will form the group where the element name  | 
                  |
| 60 | 
                      #' is the corresponding name of the group. For example if the goal was to create two groups  | 
                  |
| 61 | 
                      #' named `Group-1` and `Group-2` which are composed of the subjects `sub-1`, `sub-2` and  | 
                  |
| 62 | 
                      #' `sub-3`, `sub-4` respectively then this would be specified as:  | 
                  |
| 63 | 
                      #' ```  | 
                  |
| 64 | 
                      #' GridGrouped(  | 
                  |
| 65 | 
                      #' groups = list(  | 
                  |
| 66 | 
                      #'         "Group-1" = c("sub-1", "sub-2"),
                     | 
                  |
| 67 | 
                      #'         "Group-2" = c("sub-3", "sub-4")
                     | 
                  |
| 68 | 
                      #' )  | 
                  |
| 69 | 
                      #' )  | 
                  |
| 70 | 
                      #' ```  | 
                  |
| 71 | 
                      #' @seealso [`SurvivalQuantities`], [`LongitudinalQuantities`]  | 
                  |
| 72 | 
                      #' @name Grid-Functions  | 
                  |
| 73 | 
                      NULL  | 
                  |
| 74 | ||
| 75 | ||
| 76 | ||
| 77 | ||
| 78 | ||
| 79 | ||
| 80 | 
                      #' Grid Developer Notes  | 
                  |
| 81 | 
                      #'  | 
                  |
| 82 | 
                      #' @description  | 
                  |
| 83 | 
                      #' Developer details for implementing / extending `Grid` objects for defining  | 
                  |
| 84 | 
                      #' generated quantities for [`SurvivalQuantities`] and [`LongitudinalQuantities`].  | 
                  |
| 85 | 
                      #'  | 
                  |
| 86 | 
                      #' @slot subjects (`character` or `NULL`)\cr vector of subjects to extract quantities for.  | 
                  |
| 87 | 
                      #' If `NULL` will default to all subjects within the dataset.  | 
                  |
| 88 | 
                      #' @slot times (`numeric` or `NULL`)\cr vector of time points to extract quantities at.  | 
                  |
| 89 | 
                      #' If `NULL` will default to 201 evenly spaced timepoints between 0 and either the max  | 
                  |
| 90 | 
                      #' @slot groups (`list`)\cr named list of subjects to extract quantities for. See details.  | 
                  |
| 91 | 
                      #'  | 
                  |
| 92 | 
                      #' @details  | 
                  |
| 93 | 
                      #' All grid classes must inherit from the abstract `Grid` class.  | 
                  |
| 94 | 
                      #' All grid classes must provide `as.QuantityGenerator(object, data)` and  | 
                  |
| 95 | 
                      #' `as.QuantityCollapser(object, data)` methods where `data` is a [`DataJoint`] object.  | 
                  |
| 96 | 
                      #' These methods must return a `QuantityGenerator` and `QuantityCollapser` object respectively.  | 
                  |
| 97 | 
                      #' The `QuantityGenerator` object specifies unique subject/timepoint combinations that samples  | 
                  |
| 98 | 
                      #' should be generated at.  | 
                  |
| 99 | 
                      #' The `QuantityCollapser` object specifies how to combine these generated samples  | 
                  |
| 100 | 
                      #' to form the desired quantities.  | 
                  |
| 101 | 
                      #' As an example say we want to generate grouped samples for the groups `Group-1` and `Group-2`  | 
                  |
| 102 | 
                      #' which consist of the subjects `sub-1`, `sub-2` and `sub-3`, `sub-4` respectively at two time points  | 
                  |
| 103 | 
                      #' `10` and `20`. We can achieve this as follows:  | 
                  |
| 104 | 
                      #' ```  | 
                  |
| 105 | 
                      #' QuantityGenerator(  | 
                  |
| 106 | 
                      #' times = c(10, 10, 10, 10, 20, 20, 20, 20),  | 
                  |
| 107 | 
                      #'     subjects = c("sub-1" "sub-2", "sub-3", "sub-4", "sub-1" "sub-2", "sub-3", "sub-4")
                     | 
                  |
| 108 | 
                      #' )  | 
                  |
| 109 | 
                      #' QuantityCollapser(  | 
                  |
| 110 | 
                      #' times = c(10, 20, 10 , 20),  | 
                  |
| 111 | 
                      #'     groups = c("Group-1", "Group-1", "Group-2", "Group-2"),
                     | 
                  |
| 112 | 
                      #' indexes = list(c(1, 2), c(5, 6), c(3, 4), c(7, 8))  | 
                  |
| 113 | 
                      #' )  | 
                  |
| 114 | 
                      #' ```  | 
                  |
| 115 | 
                      #' For population based quantities use the `arms` and `studies` arguments of `QuantityGenerator`  | 
                  |
| 116 | 
                      #' instead of `subjects`.  | 
                  |
| 117 | 
                      #'  | 
                  |
| 118 | 
                      #' @inheritSection Grid-Functions Group Specification  | 
                  |
| 119 | 
                      #'  | 
                  |
| 120 | 
                      #' @keywords internal  | 
                  |
| 121 | 
                      #' @seealso `Quant-Dev`  | 
                  |
| 122 | 
                      #' @name Grid-Dev  | 
                  |
| 123 | 
                      NULL  | 
                  |
| 124 | ||
| 125 | ||
| 126 | ||
| 127 | 
                      #' Quantity Developer Notes  | 
                  |
| 128 | 
                      #'  | 
                  |
| 129 | 
                      #' @description  | 
                  |
| 130 | 
                      #' Developer details for `QuantityX` objects/methods. This page just outlines the arguments  | 
                  |
| 131 | 
                      #' and slots of these objects/methods. For the full implementation details please see [Grid-Dev]  | 
                  |
| 132 | 
                      #'  | 
                  |
| 133 | 
                      #' @slot times (`numeric`)\cr See Arguments for details.  | 
                  |
| 134 | 
                      #' @slot subjects (`character`)\cr See Arguments for details.  | 
                  |
| 135 | 
                      #' @slot groups (`character`)\cr See Arguments for details.  | 
                  |
| 136 | 
                      #' @slot indexes (`list`)\cr See Arguments for details.  | 
                  |
| 137 | 
                      #'  | 
                  |
| 138 | 
                      #' @param times (`numeric`)\cr vector of time points to extract quantities at.  | 
                  |
| 139 | 
                      #' @param subjects (`character`)\cr vector of subjects to extract quantities for.  | 
                  |
| 140 | 
                      #' @param groups (`character`)\cr vector of labels to apply to the generated quantities.  | 
                  |
| 141 | 
                      #' @param indexes (`list`)\cr list of indexes that specify which observations from a  | 
                  |
| 142 | 
                      #' `QuantityGenerator` should be combined to form the desired quantities.  | 
                  |
| 143 | 
                      #'  | 
                  |
| 144 | 
                      #' @param object (`Grid`)\cr object to convert to a `QuantityGenerator` or `QuantityCollapser`.  | 
                  |
| 145 | 
                      #' @param data (`DataJoint`)\cr Survival and Longitudinal Data.  | 
                  |
| 146 | 
                      #' @param ... Not currently used.  | 
                  |
| 147 | 
                      #'  | 
                  |
| 148 | 
                      #' @details  | 
                  |
| 149 | 
                      #' The `as.QuantityGenerator` must return a `QuantityGenerator` object.  | 
                  |
| 150 | 
                      #' The `as.QuantityCollapser` must return a `QuantityCollapser` object.  | 
                  |
| 151 | 
                      #' @keywords internal  | 
                  |
| 152 | 
                      #' @name Quant-Dev  | 
                  |
| 153 | 
                      NULL  | 
                  |
| 154 | ||
| 155 | ||
| 156 | 
                      #' @rdname Grid-Dev  | 
                  |
| 157 | 
                      .Grid <- setClass("Grid")
                     | 
                  |
| 158 | ||
| 159 | ||
| 160 | 
                      #' @rdname Quant-Dev  | 
                  |
| 161 | 
                      .QuantityGenerator <- setClass(  | 
                  |
| 162 | 
                      "QuantityGenerator"  | 
                  |
| 163 | 
                      )  | 
                  |
| 164 | 
                      #' `QuantityGenerator` -> `list`  | 
                  |
| 165 | 
                      #' @description  | 
                  |
| 166 | 
                      #' Converts a `QuantityGenerator` object to a list containing the required input data for a stan  | 
                  |
| 167 | 
                      #' model.  | 
                  |
| 168 | 
                      #' @param object (`QuantityGenerator`)\cr object to convert to a list.  | 
                  |
| 169 | 
                      #' @param data (`DataJoint`)\cr Survival and Longitudinal Data.  | 
                  |
| 170 | 
                      #' @param ... Not currently used.  | 
                  |
| 171 | 
                      #' @keywords internal  | 
                  |
| 172 | 
                      as_stan_list.QuantityGenerator <- function(object, data, ...) {
                     | 
                  |
| 173 | ! | 
                          stop("as_stan_list.QuantityGenerator not implemented")
                     | 
                  
| 174 | 
                      }  | 
                  |
| 175 | ||
| 176 | ||
| 177 | ||
| 178 | 
                      #' @rdname Quant-Dev  | 
                  |
| 179 | 
                      .QuantityCollapser <- setClass(  | 
                  |
| 180 | 
                      "QuantityCollapser",  | 
                  |
| 181 | 
                      slots = c(  | 
                  |
| 182 | 
                      "times" = "numeric",  | 
                  |
| 183 | 
                      "groups" = "character",  | 
                  |
| 184 | 
                      "indexes" = "list"  | 
                  |
| 185 | 
                      )  | 
                  |
| 186 | 
                      )  | 
                  |
| 187 | 
                      #' @rdname Quant-Dev  | 
                  |
| 188 | 
                      QuantityCollapser <- function(times, groups, indexes) {
                     | 
                  |
| 189 | 47x | 
                      .QuantityCollapser(  | 
                  
| 190 | 47x | 
                      times = times,  | 
                  
| 191 | 47x | 
                      groups = groups,  | 
                  
| 192 | 47x | 
                      indexes = indexes  | 
                  
| 193 | 
                      )  | 
                  |
| 194 | 
                      }  | 
                  |
| 195 | ||
| 196 | 
                      setValidity(  | 
                  |
| 197 | 
                      "QuantityCollapser",  | 
                  |
| 198 | 
                          function(object) {
                     | 
                  |
| 199 | 
                      if (  | 
                  |
| 200 | 
                      length(object@times) != length(object@groups) ||  | 
                  |
| 201 | 
                      length(object@times) != length(object@indexes)  | 
                  |
| 202 | 
                              ) {
                     | 
                  |
| 203 | 
                                  return("Length of `times`, `groups`, and `indexes` must be equal")
                     | 
                  |
| 204 | 
                      }  | 
                  |
| 205 | 
                      }  | 
                  |
| 206 | 
                      )  | 
                  |
| 207 | ||
| 208 | 
                      #' @export  | 
                  |
| 209 | 
                      length.QuantityCollapser <- function(x) {
                     | 
                  |
| 210 | 68x | 
                      length(x@indexes)  | 
                  
| 211 | 
                      }  | 
                  |
| 212 | ||
| 213 | ||
| 214 | 
                      #' Expand and Validate Subjects  | 
                  |
| 215 | 
                      #'  | 
                  |
| 216 | 
                      #' @param subjects (`character`)\cr vector of subjects that should exist in `data`  | 
                  |
| 217 | 
                      #' @param data (`DataJoint`)\cr Survival and Longitudinal Data.  | 
                  |
| 218 | 
                      #'  | 
                  |
| 219 | 
                      #' @description  | 
                  |
| 220 | 
                      #' If `subjects` is `NULL` this will return a named list of all subjects in `data`.  | 
                  |
| 221 | 
                      #' Else it will return `subjects` as a named list ensuring that all subjects exist in `data`.  | 
                  |
| 222 | 
                      #'  | 
                  |
| 223 | 
                      #' @keywords internal  | 
                  |
| 224 | 
                      subjects_to_list <- function(subjects = NULL, data) {
                     | 
                  |
| 225 | 66x | 
                      data_list <- as.list(data)  | 
                  
| 226 | 66x | 
                          subjects_exp <- if (is.null(subjects)) {
                     | 
                  
| 227 | 10x | 
                      subs <- as.list(names(data_list$subject_to_index))  | 
                  
| 228 | 10x | 
                      names(subs) <- names(data_list$subject_to_index)  | 
                  
| 229 | 10x | 
                      subs  | 
                  
| 230 | 
                          } else {
                     | 
                  |
| 231 | 56x | 
                      subs <- as.list(subjects)  | 
                  
| 232 | 56x | 
                      names(subs) <- subjects  | 
                  
| 233 | 56x | 
                      subs  | 
                  
| 234 | 
                      }  | 
                  |
| 235 | 66x | 
                      subjects_exp_vec <- unlist(subjects_exp, use.names = FALSE)  | 
                  
| 236 | 66x | 
                      assert_that(  | 
                  
| 237 | 66x | 
                      identical(subjects_exp_vec, unique(subjects_exp_vec)),  | 
                  
| 238 | 66x | 
                      msg = "All subject names must be unique"  | 
                  
| 239 | 
                      )  | 
                  |
| 240 | 66x | 
                      assert_that(  | 
                  
| 241 | 66x | 
                      all(subjects_exp_vec %in% names(data_list$subject_to_index)),  | 
                  
| 242 | 66x | 
                      msg = "Not all subjects exist within the data object"  | 
                  
| 243 | 
                      )  | 
                  |
| 244 | 65x | 
                      subjects_exp  | 
                  
| 245 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include Grid.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | 
                      #' @rdname Grid-Dev  | 
                  |
| 8 | 
                      .GridManual <- setClass(  | 
                  |
| 9 | 
                      "GridManual",  | 
                  |
| 10 | 
                      contains = "Grid",  | 
                  |
| 11 | 
                      slots = c(  | 
                  |
| 12 | 
                      "spec" = "list"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | ||
| 17 | 
                      #' @rdname Grid-Functions  | 
                  |
| 18 | 
                      #' @export  | 
                  |
| 19 | 
                      GridManual <- function(spec) {
                     | 
                  |
| 20 | 5x | 
                      .GridManual(  | 
                  
| 21 | 5x | 
                      spec = spec  | 
                  
| 22 | 
                      )  | 
                  |
| 23 | 
                      }  | 
                  |
| 24 | ||
| 25 | ||
| 26 | 
                      setValidity(  | 
                  |
| 27 | 
                      "GridManual",  | 
                  |
| 28 | 
                          function(object) {
                     | 
                  |
| 29 | 
                      subject_names <- names(object@spec)  | 
                  |
| 30 | 
                      subject_names_valid <- subject_names[!is.na(subject_names) & subject_names != ""]  | 
                  |
| 31 | 
                              if (length(subject_names_valid) != length(object@spec)) {
                     | 
                  |
| 32 | 
                                  return("Each element of `subjects` must be named")
                     | 
                  |
| 33 | 
                      }  | 
                  |
| 34 | 
                              for (times in object@spec) {
                     | 
                  |
| 35 | 
                                  if (!is.numeric(times)) {
                     | 
                  |
| 36 | 
                                      return("Each element of `spec` must be a numeric vector")
                     | 
                  |
| 37 | 
                      }  | 
                  |
| 38 | 
                                  if (length(times) != length(unique(times))) {
                     | 
                  |
| 39 | 
                                      return("Each time vector per subject must be unique")
                     | 
                  |
| 40 | 
                      }  | 
                  |
| 41 | 
                      }  | 
                  |
| 42 | 
                      return(TRUE)  | 
                  |
| 43 | 
                      }  | 
                  |
| 44 | 
                      )  | 
                  |
| 45 | ||
| 46 | ||
| 47 | 
                      #' @rdname Quant-Dev  | 
                  |
| 48 | 
                      #' @export  | 
                  |
| 49 | 
                      as.QuantityGenerator.GridManual <- function(object, data, ...) {
                     | 
                  |
| 50 | 8x | 
                      assert_class(data, "DataJoint")  | 
                  
| 51 | 8x | 
                      data_list <- as.list(data)  | 
                  
| 52 | 8x | 
                      assert_that(  | 
                  
| 53 | 8x | 
                      all(names(object@spec) %in% names(data_list$subject_to_index)),  | 
                  
| 54 | 8x | 
                      msg = "All subject names must be in the `DataSubject` object"  | 
                  
| 55 | 
                      )  | 
                  |
| 56 | 8x | 
                      lens <- vapply(object@spec, length, numeric(1))  | 
                  
| 57 | 8x | 
                      QuantityGeneratorSubject(  | 
                  
| 58 | 8x | 
                      times = unlist(object@spec, use.names = FALSE),  | 
                  
| 59 | 8x | 
                      subjects = rep(names(object@spec), lens)  | 
                  
| 60 | 
                      )  | 
                  |
| 61 | 
                      }  | 
                  |
| 62 | ||
| 63 | ||
| 64 | 
                      #' @rdname Quant-Dev  | 
                  |
| 65 | 
                      #' @export  | 
                  |
| 66 | 
                      as.QuantityCollapser.GridManual <- function(object, data, ...) {
                     | 
                  |
| 67 | 3x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 68 | 3x | 
                      QuantityCollapser(  | 
                  
| 69 | 3x | 
                      times = generator@times,  | 
                  
| 70 | 3x | 
                      groups = generator@subjects,  | 
                  
| 71 | 3x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 72 | 
                      )  | 
                  |
| 73 | 
                      }  | 
                  |
| 74 | ||
| 75 | ||
| 76 | 
                      #' @export  | 
                  |
| 77 | 
                      as.list.GridManual <- function(x, data, ...) {
                     | 
                  |
| 78 | ! | 
                      subs <- as.list(names(x@spec))  | 
                  
| 79 | ! | 
                      names(subs) <- names(x@spec)  | 
                  
| 80 | ! | 
                      subs  | 
                  
| 81 | 
                      }  | 
                  
| 1 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 2 | 
                      #' @include StanModule.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      #' @include ParameterList.R  | 
                  |
| 5 | 
                      #' @include Parameter.R  | 
                  |
| 6 | 
                      #' @include Link.R  | 
                  |
| 7 | 
                      NULL  | 
                  |
| 8 | ||
| 9 | ||
| 10 | 
                      #' `LongitudinalSteinFojo`  | 
                  |
| 11 | 
                      #'  | 
                  |
| 12 | 
                      #' This class extends the general [`LongitudinalModel`] class for using the  | 
                  |
| 13 | 
                      #' Stein-Fojo model for the longitudinal outcome.  | 
                  |
| 14 | 
                      #'  | 
                  |
| 15 | 
                      #' @section Available Links:  | 
                  |
| 16 | 
                      #' - [`linkDSLD()`]  | 
                  |
| 17 | 
                      #' - [`linkTTG()`]  | 
                  |
| 18 | 
                      #' - [`linkIdentity()`]  | 
                  |
| 19 | 
                      #' - [`linkGrowth()`]  | 
                  |
| 20 | 
                      #' @exportClass LongitudinalSteinFojo  | 
                  |
| 21 | 
                      .LongitudinalSteinFojo <- setClass(  | 
                  |
| 22 | 
                      Class = "LongitudinalSteinFojo",  | 
                  |
| 23 | 
                      contains = "LongitudinalModel"  | 
                  |
| 24 | 
                      )  | 
                  |
| 25 | ||
| 26 | ||
| 27 | 
                      #' @rdname LongitudinalSteinFojo-class  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @param mu_bsld (`Prior`)\cr for the mean baseline value `mu_bsld`.  | 
                  |
| 30 | 
                      #' @param mu_ks (`Prior`)\cr for the mean shrinkage rate `mu_ks`.  | 
                  |
| 31 | 
                      #' @param mu_kg (`Prior`)\cr for the mean growth rate `mu_kg`.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #' @param omega_bsld (`Prior`)\cr for the baseline value standard deviation `omega_bsld`.  | 
                  |
| 34 | 
                      #' @param omega_ks (`Prior`)\cr for the shrinkage rate standard deviation `omega_ks`.  | 
                  |
| 35 | 
                      #' @param omega_kg (`Prior`)\cr for the growth rate standard deviation `omega_kg`.  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' @param sigma (`Prior`)\cr for the variance of the longitudinal values `sigma`.  | 
                  |
| 38 | 
                      #'  | 
                  |
| 39 | 
                      #' @param centred (`logical`)\cr whether to use the centred parameterization.  | 
                  |
| 40 | 
                      #'  | 
                  |
| 41 | 
                      #' @export  | 
                  |
| 42 | 
                      LongitudinalSteinFojo <- function(  | 
                  |
| 43 | ||
| 44 | 
                      mu_bsld = prior_normal(log(60), 1),  | 
                  |
| 45 | 
                      mu_ks = prior_normal(log(0.5), 1),  | 
                  |
| 46 | 
                      mu_kg = prior_normal(log(0.3), 1),  | 
                  |
| 47 | ||
| 48 | 
                      omega_bsld = prior_lognormal(log(0.2), 1),  | 
                  |
| 49 | 
                      omega_ks = prior_lognormal(log(0.2), 1),  | 
                  |
| 50 | 
                      omega_kg = prior_lognormal(log(0.2), 1),  | 
                  |
| 51 | ||
| 52 | 
                      sigma = prior_lognormal(log(0.1), 1),  | 
                  |
| 53 | ||
| 54 | 
                      centred = FALSE  | 
                  |
| 55 | 
                      ) {
                     | 
                  |
| 56 | ||
| 57 | 14x | 
                      sf_model <- StanModule(decorated_render(  | 
                  
| 58 | 14x | 
                              .x = read_stan("lm-stein-fojo/model.stan"),
                     | 
                  
| 59 | 14x | 
                      centred = centred  | 
                  
| 60 | 
                      ))  | 
                  |
| 61 | ||
| 62 | 
                      # Apply constriants  | 
                  |
| 63 | 14x | 
                      omega_bsld <- set_limits(omega_bsld, lower = 0)  | 
                  
| 64 | 14x | 
                      omega_ks <- set_limits(omega_ks, lower = 0)  | 
                  
| 65 | 14x | 
                      omega_kg <- set_limits(omega_kg, lower = 0)  | 
                  
| 66 | 14x | 
                      sigma <- set_limits(sigma, lower = 0)  | 
                  
| 67 | ||
| 68 | 14x | 
                      parameters <- list(  | 
                  
| 69 | 14x | 
                      Parameter(name = "lm_sf_mu_bsld", prior = mu_bsld, size = "n_studies"),  | 
                  
| 70 | 14x | 
                      Parameter(name = "lm_sf_mu_ks", prior = mu_ks, size = "n_arms"),  | 
                  
| 71 | 14x | 
                      Parameter(name = "lm_sf_mu_kg", prior = mu_kg, size = "n_arms"),  | 
                  
| 72 | ||
| 73 | 14x | 
                      Parameter(name = "lm_sf_omega_bsld", prior = omega_bsld, size = 1),  | 
                  
| 74 | 14x | 
                      Parameter(name = "lm_sf_omega_ks", prior = omega_ks, size = 1),  | 
                  
| 75 | 14x | 
                      Parameter(name = "lm_sf_omega_kg", prior = omega_kg, size = 1),  | 
                  
| 76 | ||
| 77 | 14x | 
                      Parameter(name = "lm_sf_sigma", prior = sigma, size = 1)  | 
                  
| 78 | 
                      )  | 
                  |
| 79 | ||
| 80 | 14x | 
                      assert_flag(centred)  | 
                  
| 81 | 14x | 
                          parameters_extra <- if (centred) {
                     | 
                  
| 82 | 3x | 
                      list(  | 
                  
| 83 | 3x | 
                      Parameter(  | 
                  
| 84 | 3x | 
                      name = "lm_sf_psi_bsld",  | 
                  
| 85 | 3x | 
                      prior = prior_init_only(prior_lognormal(median(mu_bsld), median(omega_bsld))),  | 
                  
| 86 | 3x | 
                      size = "n_subjects"  | 
                  
| 87 | 
                      ),  | 
                  |
| 88 | 3x | 
                      Parameter(  | 
                  
| 89 | 3x | 
                      name = "lm_sf_psi_ks",  | 
                  
| 90 | 3x | 
                      prior = prior_init_only(prior_lognormal(median(mu_ks), median(omega_ks))),  | 
                  
| 91 | 3x | 
                      size = "n_subjects"  | 
                  
| 92 | 
                      ),  | 
                  |
| 93 | 3x | 
                      Parameter(  | 
                  
| 94 | 3x | 
                      name = "lm_sf_psi_kg",  | 
                  
| 95 | 3x | 
                      prior = prior_init_only(prior_lognormal(median(mu_kg), median(omega_kg))),  | 
                  
| 96 | 3x | 
                      size = "n_subjects"  | 
                  
| 97 | 
                      )  | 
                  |
| 98 | 
                      )  | 
                  |
| 99 | 
                          } else {
                     | 
                  |
| 100 | 11x | 
                      list(  | 
                  
| 101 | 11x | 
                      Parameter(name = "lm_sf_eta_tilde_bsld", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 102 | 11x | 
                      Parameter(name = "lm_sf_eta_tilde_ks", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 103 | 11x | 
                      Parameter(name = "lm_sf_eta_tilde_kg", prior = prior_std_normal(), size = "n_subjects")  | 
                  
| 104 | 
                      )  | 
                  |
| 105 | 
                      }  | 
                  |
| 106 | 14x | 
                      parameters <- append(parameters, parameters_extra)  | 
                  
| 107 | ||
| 108 | 14x | 
                      x <- LongitudinalModel(  | 
                  
| 109 | 14x | 
                      name = "Stein-Fojo",  | 
                  
| 110 | 14x | 
                      stan = merge(  | 
                  
| 111 | 14x | 
                      sf_model,  | 
                  
| 112 | 14x | 
                                  StanModule("lm-stein-fojo/functions.stan")
                     | 
                  
| 113 | 
                      ),  | 
                  |
| 114 | 14x | 
                      parameters = do.call(ParameterList, parameters)  | 
                  
| 115 | 
                      )  | 
                  |
| 116 | 14x | 
                      .LongitudinalSteinFojo(x)  | 
                  
| 117 | 
                      }  | 
                  |
| 118 | ||
| 119 | ||
| 120 | ||
| 121 | 
                      #' @export  | 
                  |
| 122 | 
                      enableGQ.LongitudinalSteinFojo <- function(object, ...) {
                     | 
                  |
| 123 | 2x | 
                          StanModule("lm-stein-fojo/quantities.stan")
                     | 
                  
| 124 | 
                      }  | 
                  |
| 125 | ||
| 126 | 
                      #' @export  | 
                  |
| 127 | 
                      enableLink.LongitudinalSteinFojo <- function(object, ...) {
                     | 
                  |
| 128 | 1x | 
                      object@stan <- merge(  | 
                  
| 129 | 1x | 
                      object@stan,  | 
                  
| 130 | 1x | 
                              StanModule("lm-stein-fojo/link.stan")
                     | 
                  
| 131 | 
                      )  | 
                  |
| 132 | 1x | 
                      object  | 
                  
| 133 | 
                      }  | 
                  |
| 134 | ||
| 135 | 
                      #' @export  | 
                  |
| 136 | 
                      linkDSLD.LongitudinalSteinFojo <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 137 | 1x | 
                      LinkComponent(  | 
                  
| 138 | 1x | 
                      key = "link_dsld",  | 
                  
| 139 | 1x | 
                              stan = StanModule("lm-stein-fojo/link_dsld.stan"),
                     | 
                  
| 140 | 1x | 
                      prior = prior  | 
                  
| 141 | 
                      )  | 
                  |
| 142 | 
                      }  | 
                  |
| 143 | ||
| 144 | 
                      #' @export  | 
                  |
| 145 | 
                      linkTTG.LongitudinalSteinFojo <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 146 | 1x | 
                      LinkComponent(  | 
                  
| 147 | 1x | 
                      key = "link_ttg",  | 
                  
| 148 | 1x | 
                              stan = StanModule("lm-stein-fojo/link_ttg.stan"),
                     | 
                  
| 149 | 1x | 
                      prior = prior  | 
                  
| 150 | 
                      )  | 
                  |
| 151 | 
                      }  | 
                  |
| 152 | ||
| 153 | 
                      #' @export  | 
                  |
| 154 | 
                      linkIdentity.LongitudinalSteinFojo <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 155 | ! | 
                      LinkComponent(  | 
                  
| 156 | ! | 
                      key = "link_identity",  | 
                  
| 157 | ! | 
                              stan = StanModule("lm-stein-fojo/link_identity.stan"),
                     | 
                  
| 158 | ! | 
                      prior = prior  | 
                  
| 159 | 
                      )  | 
                  |
| 160 | 
                      }  | 
                  |
| 161 | ||
| 162 | 
                      #' @export  | 
                  |
| 163 | 
                      linkGrowth.LongitudinalSteinFojo <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 164 | 1x | 
                      LinkComponent(  | 
                  
| 165 | 1x | 
                      key = "link_growth",  | 
                  
| 166 | 1x | 
                              stan = StanModule("lm-stein-fojo/link_growth.stan"),
                     | 
                  
| 167 | 1x | 
                      prior = prior  | 
                  
| 168 | 
                      )  | 
                  |
| 169 | 
                      }  | 
                  |
| 170 | ||
| 171 | 
                      #' @rdname getPredictionNames  | 
                  |
| 172 | 
                      #' @export  | 
                  |
| 173 | 
                      getPredictionNames.LongitudinalSteinFojo <- function(object, ...) {
                     | 
                  |
| 174 | 1x | 
                          c("b", "s", "g")
                     | 
                  
| 175 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include utilities.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' Re-used documentation for `DataSurvival`  | 
                  |
| 6 | 
                      #'  | 
                  |
| 7 | 
                      #' @param object ([`DataSurvival`]) \cr Survival Data.  | 
                  |
| 8 | 
                      #' @param x ([`DataSurvival`]) \cr Survival Data.  | 
                  |
| 9 | 
                      #' @param ... Not Used.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @name DataSurvival-Shared  | 
                  |
| 12 | 
                      #' @keywords internal  | 
                  |
| 13 | 
                      NULL  | 
                  |
| 14 | ||
| 15 | ||
| 16 | ||
| 17 | 
                      # DataSurvival-class ----  | 
                  |
| 18 | ||
| 19 | 
                      #' Survival Data Object and Constructor Function  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' The [`DataSurvival`] class handles the processing of the survival data  | 
                  |
| 22 | 
                      #' for fitting a [`JointModel`].  | 
                  |
| 23 | 
                      #'  | 
                  |
| 24 | 
                      #' @slot data (`data.frame`)\cr See Arguments for details.  | 
                  |
| 25 | 
                      #' @slot formula (`formula`)\cr See Arguments for details.  | 
                  |
| 26 | 
                      #'  | 
                  |
| 27 | 
                      #' @family DataObjects  | 
                  |
| 28 | 
                      #' @family DataSurvival  | 
                  |
| 29 | 
                      #' @exportClass DataSurvival  | 
                  |
| 30 | 
                      #' @export DataSurvival  | 
                  |
| 31 | 
                      .DataSurvival <- setClass(  | 
                  |
| 32 | 
                      Class = "DataSurvival",  | 
                  |
| 33 | 
                      representation = list(  | 
                  |
| 34 | 
                      data = "data.frame",  | 
                  |
| 35 | 
                      formula = "formula"  | 
                  |
| 36 | 
                      )  | 
                  |
| 37 | 
                      )  | 
                  |
| 38 | ||
| 39 | 
                      #' @param data (`data.frame`)\cr the observed time-to-event data.  | 
                  |
| 40 | 
                      #' @param formula (`formula`)\cr of the form `Surv(time, event) ~ cov1 + cov2 + ...`.  | 
                  |
| 41 | 
                      #' See [survival::Surv()] for more details, though note that this package only supports right censoring.  | 
                  |
| 42 | 
                      #' @rdname DataSurvival-class  | 
                  |
| 43 | 
                      DataSurvival <- function(data, formula) {
                     | 
                  |
| 44 | 50x | 
                      .DataSurvival(  | 
                  
| 45 | 50x | 
                      data = remove_missing_rows(data, formula),  | 
                  
| 46 | 50x | 
                      formula = formula  | 
                  
| 47 | 
                      )  | 
                  |
| 48 | 
                      }  | 
                  |
| 49 | ||
| 50 | 
                      setValidity(  | 
                  |
| 51 | 
                      "DataSurvival",  | 
                  |
| 52 | 
                          method = function(object) {
                     | 
                  |
| 53 | 
                      dat <- object@data  | 
                  |
| 54 | 
                      x <- extractVariableNames(object)  | 
                  |
| 55 | 
                      dnames <- names(dat)  | 
                  |
| 56 | 
                              if (nrow(object@data) == 0) {
                     | 
                  |
| 57 | 
                                  return("`data` should not have 0 rows")
                     | 
                  |
| 58 | 
                      }  | 
                  |
| 59 | 
                              if (length(x$frm) != 3) {
                     | 
                  |
| 60 | 
                                  return("`formula` should be a 2 sided formula")
                     | 
                  |
| 61 | 
                      }  | 
                  |
| 62 | 
                      LHS <- as.character(x$frm[[2]][[1]])  | 
                  |
| 63 | 
                              if (!(identical(LHS, "Surv") || identical(LHS, c("::", "survival", "Surv")))) {
                     | 
                  |
| 64 | 
                                  return("The LHS of `formula` should be a call to survival::Surv()")
                     | 
                  |
| 65 | 
                      }  | 
                  |
| 66 | 
                              for (v in c(x$time, x$event)) {
                     | 
                  |
| 67 | 
                                  if (! v %in% dnames) {
                     | 
                  |
| 68 | 
                                      return(sprintf("Variable %s is not in `data`", x$subject))
                     | 
                  |
| 69 | 
                      }  | 
                  |
| 70 | 
                      }  | 
                  |
| 71 | 
                      return(TRUE)  | 
                  |
| 72 | 
                      }  | 
                  |
| 73 | 
                      )  | 
                  |
| 74 | ||
| 75 | ||
| 76 | ||
| 77 | ||
| 78 | ||
| 79 | ||
| 80 | 
                      #' @inheritParams DataSurvival-Shared  | 
                  |
| 81 | 
                      #' @inherit extractVariableNames description title  | 
                  |
| 82 | 
                      #'  | 
                  |
| 83 | 
                      #' @returns  | 
                  |
| 84 | 
                      #' A list with the following named elements:  | 
                  |
| 85 | 
                      #' - `frm` (`formula`)\cr a symbolic description of the survival model to be fitted  | 
                  |
| 86 | 
                      #' - `time` (`character`)\cr The name of the variable containing the event time  | 
                  |
| 87 | 
                      #' - `event` (`character`) \cr The name of the variable containing the event status  | 
                  |
| 88 | 
                      #' @export  | 
                  |
| 89 | 
                      #' @family DataSurvival  | 
                  |
| 90 | 
                      #' @family extractVariableNames  | 
                  |
| 91 | 
                      #' @keywords internal  | 
                  |
| 92 | 
                      extractVariableNames.DataSurvival <- function(object) {
                     | 
                  |
| 93 | 353x | 
                      list(  | 
                  
| 94 | 353x | 
                      frm = object@formula,  | 
                  
| 95 | 353x | 
                      time = as.character(object@formula[[2]][[2]]),  | 
                  
| 96 | 353x | 
                      event = as.character(object@formula[[2]][[3]])  | 
                  
| 97 | 
                      )  | 
                  |
| 98 | 
                      }  | 
                  |
| 99 | ||
| 100 | ||
| 101 | 
                      #' `DataSurvival` -> `data.frame`  | 
                  |
| 102 | 
                      #'  | 
                  |
| 103 | 
                      #' @inheritParams DataSurvival-Shared  | 
                  |
| 104 | 
                      #'  | 
                  |
| 105 | 
                      #' @description  | 
                  |
| 106 | 
                      #' Converts a [`DataSurvival`] object into a `data.frame`.  | 
                  |
| 107 | 
                      #' The subject variable is cast to factor.  | 
                  |
| 108 | 
                      #' @family DataSurvival  | 
                  |
| 109 | 
                      #' @export  | 
                  |
| 110 | 
                      as.data.frame.DataSurvival <- function(x, ...) {
                     | 
                  |
| 111 | 353x | 
                      x <- x@data  | 
                  
| 112 | 353x | 
                      rownames(x) <- NULL  | 
                  
| 113 | 353x | 
                      x  | 
                  
| 114 | 
                      }  | 
                  |
| 115 | ||
| 116 | ||
| 117 | ||
| 118 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 119 | 
                      #' @family DataSurvival  | 
                  |
| 120 | 
                      #' @export  | 
                  |
| 121 | 
                      as_stan_list.DataSurvival <- function(object, ...) {
                     | 
                  |
| 122 | 292x | 
                      df <- as.data.frame(object)  | 
                  
| 123 | 292x | 
                      vars <- extractVariableNames(object)  | 
                  
| 124 | ||
| 125 | 292x | 
                      design_mat <- stats::model.matrix(vars$frm, data = df)  | 
                  
| 126 | 292x | 
                          remove_index <- grep("(Intercept)", colnames(design_mat), fixed = TRUE)
                     | 
                  
| 127 | 292x | 
                      design_mat <- design_mat[, -remove_index, drop = FALSE]  | 
                  
| 128 | 292x | 
                      rownames(design_mat) <- NULL  | 
                  
| 129 | ||
| 130 | 
                      # Parameters for efficient integration of hazard function -> survival function  | 
                  |
| 131 | 292x | 
                      gh_parameters <- statmod::gauss.quad(  | 
                  
| 132 | 292x | 
                              n = getOption("jmpost.gauss_quad_n"),
                     | 
                  
| 133 | 292x | 
                      kind = "legendre"  | 
                  
| 134 | 
                      )  | 
                  |
| 135 | ||
| 136 | 292x | 
                      model_data <- list(  | 
                  
| 137 | 292x | 
                      n_subject_event = sum(df[[vars$event]]),  | 
                  
| 138 | 292x | 
                      subject_event_index = which(df[[vars$event]] == 1),  | 
                  
| 139 | 292x | 
                      event_times = df[[vars$time]],  | 
                  
| 140 | 292x | 
                      p_os_cov_design = ncol(design_mat),  | 
                  
| 141 | 292x | 
                      os_cov_design = design_mat,  | 
                  
| 142 | 292x | 
                      n_nodes = length(gh_parameters$nodes),  | 
                  
| 143 | 292x | 
                      nodes = gh_parameters$nodes,  | 
                  
| 144 | 292x | 
                      weights = gh_parameters$weights  | 
                  
| 145 | 
                      )  | 
                  |
| 146 | 292x | 
                      return(model_data)  | 
                  
| 147 | 
                      }  | 
                  |
| 148 | ||
| 149 | 
                      #' @rdname as_stan_list.DataObject  | 
                  |
| 150 | 
                      #' @export  | 
                  |
| 151 | 
                      as.list.DataSurvival <- function(x, ...) {
                     | 
                  |
| 152 | 2x | 
                      as_stan_list(x, ...)  | 
                  
| 153 | 
                      }  | 
                  |
| 154 | ||
| 155 | 
                      #' @rdname harmonise  | 
                  |
| 156 | 
                      harmonise.DataSurvival <- function(object, subject_var, subject_ord, ...) {
                     | 
                  |
| 157 | ||
| 158 | 23x | 
                      data <- as.data.frame(object)  | 
                  
| 159 | ||
| 160 | 23x | 
                      assert_string(subject_var, na.ok = FALSE)  | 
                  
| 161 | 23x | 
                      assert_character(subject_ord, any.missing = FALSE)  | 
                  
| 162 | 23x | 
                      assert_that(  | 
                  
| 163 | 23x | 
                      subject_var %in% names(data),  | 
                  
| 164 | 23x | 
                              msg = sprintf("Subject variable `%s` not found in `survival`", subject_var)
                     | 
                  
| 165 | 
                      )  | 
                  |
| 166 | 22x | 
                      assert_that(  | 
                  
| 167 | 22x | 
                      all(data[[subject_var]] %in% subject_ord),  | 
                  
| 168 | 22x | 
                      msg = "There are subjects in `survival` that are not present in `subjects`"  | 
                  
| 169 | 
                      )  | 
                  |
| 170 | 21x | 
                      assert_that(  | 
                  
| 171 | 21x | 
                      all(subject_ord %in% data[[subject_var]]),  | 
                  
| 172 | 21x | 
                      msg = "There are subjects in `subjects` that are not present in `survival`"  | 
                  
| 173 | 
                      )  | 
                  |
| 174 | ||
| 175 | 20x | 
                      data[[subject_var]] <- factor(  | 
                  
| 176 | 20x | 
                      as.character(data[[subject_var]]),  | 
                  
| 177 | 20x | 
                      levels = subject_ord  | 
                  
| 178 | 
                      )  | 
                  |
| 179 | ||
| 180 | 20x | 
                      data_ord <- data[order(data[[subject_var]]), ]  | 
                  
| 181 | ||
| 182 | 20x | 
                      DataSurvival(  | 
                  
| 183 | 20x | 
                      data = data_ord,  | 
                  
| 184 | 20x | 
                      formula = object@formula  | 
                  
| 185 | 
                      )  | 
                  |
| 186 | 
                      }  | 
                  |
| 187 | ||
| 188 | ||
| 189 | ||
| 190 | 
                      #' `DataSurvival` -> Printable `Character`  | 
                  |
| 191 | 
                      #'  | 
                  |
| 192 | 
                      #' Converts [`DataSurvival`] object into a printable string.  | 
                  |
| 193 | 
                      #' @inheritParams DataSurvival-Shared  | 
                  |
| 194 | 
                      #' @family DataSurvival  | 
                  |
| 195 | 
                      #' @param indent (`numeric`)\cr how much white space to prefix the print string with.  | 
                  |
| 196 | 
                      #' @keywords internal  | 
                  |
| 197 | 
                      #' @export  | 
                  |
| 198 | 
                      as_print_string.DataSurvival <- function(object, indent = 1, ...) {
                     | 
                  |
| 199 | 2x | 
                      template <- c(  | 
                  
| 200 | 2x | 
                      "Survival-Data Object:",  | 
                  
| 201 | 2x | 
                      " # of Rows = %d",  | 
                  
| 202 | 2x | 
                      " # of Columns = %d",  | 
                  
| 203 | 2x | 
                      " # of Events = %d",  | 
                  
| 204 | 2x | 
                      " Formula = %s"  | 
                  
| 205 | 
                      )  | 
                  |
| 206 | 2x | 
                          pad <- rep(" ", indent) |> paste(collapse = "")
                     | 
                  
| 207 | 2x | 
                      template_padded <- paste(pad, template)  | 
                  
| 208 | 2x | 
                      vars <- extractVariableNames(object)  | 
                  
| 209 | 2x | 
                      sprintf(  | 
                  
| 210 | 2x | 
                      paste(template_padded, collapse = "\n"),  | 
                  
| 211 | 2x | 
                      nrow(object@data),  | 
                  
| 212 | 2x | 
                      ncol(object@data),  | 
                  
| 213 | 2x | 
                      sum(object@data[[vars$event]]),  | 
                  
| 214 | 2x | 
                      Reduce(paste, deparse(vars$frm))  | 
                  
| 215 | 
                      )  | 
                  |
| 216 | 
                      }  | 
                  |
| 217 | ||
| 218 | 
                      #' @rdname show-object  | 
                  |
| 219 | 
                      #' @export  | 
                  |
| 220 | 
                      setMethod(  | 
                  |
| 221 | 
                      f = "show",  | 
                  |
| 222 | 
                      signature = "DataSurvival",  | 
                  |
| 223 | 
                          definition = function(object) {
                     | 
                  |
| 224 | 1x | 
                      string <- as_print_string(object)  | 
                  
| 225 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 226 | 
                      }  | 
                  |
| 227 | 
                      )  | 
                  |
| 228 | ||
| 229 | 
                      #' Build design matrix for prediction data  | 
                  |
| 230 | 
                      #'  | 
                  |
| 231 | 
                      #' @description  | 
                  |
| 232 | 
                      #' This function takes a `DataSurvival` object and a `data.frame` object and generates  | 
                  |
| 233 | 
                      #' a design matrix for the `data.frame` that has the identical structure to the  | 
                  |
| 234 | 
                      #' design matrix of the `DataSurvival` object.  | 
                  |
| 235 | 
                      #'  | 
                  |
| 236 | 
                      #' This is used for predicting new data using a model that was trained on a different  | 
                  |
| 237 | 
                      #' original data source  | 
                  |
| 238 | 
                      #'  | 
                  |
| 239 | 
                      #' @param olddata ([`DataSurvival`]) \cr The original data to be used as a template for the new data  | 
                  |
| 240 | 
                      #' @param newdata ([`data.frame`]) \cr The new data to be used to generate the design matrix  | 
                  |
| 241 | 
                      #' @importFrom stats .checkMFClasses terms delete.response model.frame model.matrix  | 
                  |
| 242 | 
                      #' @importFrom survival coxph  | 
                  |
| 243 | 
                      #' @keywords internal  | 
                  |
| 244 | 
                      mirror_design_matrix <- function(olddata, newdata) {
                     | 
                  |
| 245 | 7x | 
                      frm <- as_formula(olddata)  | 
                  
| 246 | 
                      # Dummy model to generate a bunch of meta information that we can use to  | 
                  |
| 247 | 
                      # re-construct the design matrix  | 
                  |
| 248 | 7x | 
                      model <- coxph(data = as.data.frame(olddata), formula = frm)  | 
                  
| 249 | 7x | 
                      model_terms <- delete.response(terms(model))  | 
                  
| 250 | 7x | 
                      model_frame <- model.frame(  | 
                  
| 251 | 7x | 
                      model_terms,  | 
                  
| 252 | 7x | 
                      newdata,  | 
                  
| 253 | 7x | 
                      xlev = model$xlevels  | 
                  
| 254 | 
                      )  | 
                  |
| 255 | 
                      if (  | 
                  |
| 256 | 4x | 
                              !is.null(data_classes <- attr(model_terms, "dataClasses"))) {
                     | 
                  
| 257 | 4x | 
                      .checkMFClasses(data_classes, model_frame)  | 
                  
| 258 | 
                      }  | 
                  |
| 259 | 3x | 
                      design_mat <- model.matrix(  | 
                  
| 260 | 3x | 
                      model_terms,  | 
                  
| 261 | 3x | 
                      model_frame,  | 
                  
| 262 | 3x | 
                      contrasts.arg = model$contrasts  | 
                  
| 263 | 
                      )  | 
                  |
| 264 | 3x | 
                          remove_index <- grep("(Intercept)", colnames(design_mat), fixed = TRUE)
                     | 
                  
| 265 | 3x | 
                      design_mat <- design_mat[, -remove_index, drop = FALSE]  | 
                  
| 266 | 3x | 
                      rownames(design_mat) <- NULL  | 
                  
| 267 | 3x | 
                      design_mat  | 
                  
| 268 | 
                      }  | 
                  |
| 269 | ||
| 270 | ||
| 271 | 
                      #' @export  | 
                  |
| 272 | 
                      as_formula.DataSurvival <- function(x, ...) {
                     | 
                  |
| 273 | 7x | 
                      vars <- extractVariableNames(x)  | 
                  
| 274 | 7x | 
                      vars$frm  | 
                  
| 275 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include DataJoint.R  | 
                  |
| 3 | 
                      #' @include Quantities.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | ||
| 8 | 
                      #' Re-used documentation for `SurvivalQuantities`  | 
                  |
| 9 | 
                      #'  | 
                  |
| 10 | 
                      #' @param object ([`SurvivalQuantities`]) \cr survival quantities.  | 
                  |
| 11 | 
                      #' @param x ([`SurvivalQuantities`]) \cr survival quantities.  | 
                  |
| 12 | 
                      #' @param ... not used.  | 
                  |
| 13 | 
                      #'  | 
                  |
| 14 | 
                      #' @keywords internal  | 
                  |
| 15 | 
                      #' @name SurvivalQuantities-Shared  | 
                  |
| 16 | 
                      NULL  | 
                  |
| 17 | ||
| 18 | ||
| 19 | ||
| 20 | 
                      #' `SurvivalQuantities` Object & Constructor Function  | 
                  |
| 21 | 
                      #'  | 
                  |
| 22 | 
                      #' Constructor function to generate a `SurvivalQuantities` object.  | 
                  |
| 23 | 
                      #'  | 
                  |
| 24 | 
                      #' @slot quantities (`Quantities`)\cr The sampled quantities. Should contain 1 element per  | 
                  |
| 25 | 
                      #' element of `group`  | 
                  |
| 26 | 
                      #' @slot groups (`list`)\cr See argument section for details  | 
                  |
| 27 | 
                      #' @slot type (`character`)\cr See See argument section for details  | 
                  |
| 28 | 
                      #' @slot time_grid (`numeric`)\cr See argument section for details  | 
                  |
| 29 | 
                      #' @slot data ([`DataJoint`])\cr The data that the Joint Model was fitted to to produce  | 
                  |
| 30 | 
                      #' the samples/quantities  | 
                  |
| 31 | 
                      #'  | 
                  |
| 32 | 
                      #' @section Group Specification:  | 
                  |
| 33 | 
                      #' If `groups` is a character vector of subject IDs then the survival quantities will  | 
                  |
| 34 | 
                      #' only be calculated for those specific subjects.  | 
                  |
| 35 | 
                      #'  | 
                  |
| 36 | 
                      #' If `groups` is a list then any elements with more than 1 subject ID will be grouped together  | 
                  |
| 37 | 
                      #' and their quantities will be calculated by taking a point-wise average.  | 
                  |
| 38 | 
                      #' For example: `groups = list("g1" = c("sub1", "sub2"), "g2" = c("sub3", "sub4"))` would result
                     | 
                  |
| 39 | 
                      #' in 2 groups being created whose values are the pointwise average  | 
                  |
| 40 | 
                      #' of `c("sub1", "sub2")` and `c("sub3", "sub4")` respectively.
                     | 
                  |
| 41 | 
                      #'  | 
                  |
| 42 | 
                      #' If `groups=NULL` then all subjects from original dataset will be selected  | 
                  |
| 43 | 
                      #'  | 
                  |
| 44 | 
                      #' @family SurvivalQuantities  | 
                  |
| 45 | 
                      #' @name SurvivalQuantities-class  | 
                  |
| 46 | 
                      #' @export SurvivalQuantities  | 
                  |
| 47 | 
                      .SurvivalQuantities <- setClass(  | 
                  |
| 48 | 
                      Class = "SurvivalQuantities",  | 
                  |
| 49 | 
                      slots = c(  | 
                  |
| 50 | 
                      "quantities" = "Quantities",  | 
                  |
| 51 | 
                      "grid" = "Grid",  | 
                  |
| 52 | 
                      "type" = "character",  | 
                  |
| 53 | 
                      "data" = "DataJoint"  | 
                  |
| 54 | 
                      )  | 
                  |
| 55 | 
                      )  | 
                  |
| 56 | ||
| 57 | 
                      #' @param object ([`JointModelSamples`]) \cr samples as drawn from a Joint Model.  | 
                  |
| 58 | 
                      #'  | 
                  |
| 59 | 
                      #' @param grid (`Grid`) \cr object that specifies which subjects and time points to calculate the  | 
                  |
| 60 | 
                      #' quantities for. See [Grid-Functions].  | 
                  |
| 61 | 
                      #'  | 
                  |
| 62 | 
                      #' @param type (`character`)\cr quantity to be generated.  | 
                  |
| 63 | 
                      #' Must be one of `surv`, `haz`, `loghaz`, `cumhaz`.  | 
                  |
| 64 | 
                      #'  | 
                  |
| 65 | 
                      #' @rdname SurvivalQuantities-class  | 
                  |
| 66 | 
                      SurvivalQuantities <- function(  | 
                  |
| 67 | 
                      object,  | 
                  |
| 68 | 
                      grid,  | 
                  |
| 69 | 
                          type = c("surv", "haz", "loghaz", "cumhaz")
                     | 
                  |
| 70 | 
                      ) {
                     | 
                  |
| 71 | 23x | 
                      type <- match.arg(type)  | 
                  
| 72 | 23x | 
                      assert_class(object, "JointModelSamples")  | 
                  
| 73 | 23x | 
                      assert_class(grid, "Grid")  | 
                  
| 74 | 21x | 
                      assert_that(  | 
                  
| 75 | 21x | 
                      !is(grid, "GridPopulation"),  | 
                  
| 76 | 21x | 
                      msg = "GridPopulation objects are not supported for `SurvivalQuantities`"  | 
                  
| 77 | 
                      )  | 
                  |
| 78 | ||
| 79 | 20x | 
                      time_grid <- seq(  | 
                  
| 80 | 20x | 
                      from = 0,  | 
                  
| 81 | 20x | 
                      to = max(as.list(object@data)[["event_times"]]),  | 
                  
| 82 | 20x | 
                      length = 201  | 
                  
| 83 | 
                      )  | 
                  |
| 84 | ||
| 85 | 20x | 
                      grid <- coalesceGridTime(grid, time_grid)  | 
                  
| 86 | ||
| 87 | 20x | 
                      generator <- as.QuantityGenerator(grid, data = object@data)  | 
                  
| 88 | ||
| 89 | 20x | 
                      assert_that(  | 
                  
| 90 | 20x | 
                      all(generator@times >= 0),  | 
                  
| 91 | 20x | 
                      msg = "Time points must be greater than or equal to 0"  | 
                  
| 92 | 
                      )  | 
                  |
| 93 | ||
| 94 | 18x | 
                      gq <- generateQuantities(  | 
                  
| 95 | 18x | 
                      object,  | 
                  
| 96 | 18x | 
                      generator = generator,  | 
                  
| 97 | 18x | 
                      type = "survival"  | 
                  
| 98 | 
                      )  | 
                  |
| 99 | ||
| 100 | 17x | 
                      quantities_raw <- extract_quantities(gq, type)  | 
                  
| 101 | 17x | 
                      collapser <- as.QuantityCollapser(grid, object@data)  | 
                  
| 102 | 17x | 
                      quantities <- collapse_quantities(quantities_raw, collapser)  | 
                  
| 103 | ||
| 104 | 17x | 
                      .SurvivalQuantities(  | 
                  
| 105 | 17x | 
                      quantities = Quantities(  | 
                  
| 106 | 17x | 
                      quantities,  | 
                  
| 107 | 17x | 
                      groups = collapser@groups,  | 
                  
| 108 | 17x | 
                      times = collapser@times  | 
                  
| 109 | 
                      ),  | 
                  |
| 110 | 17x | 
                      grid = grid,  | 
                  
| 111 | 17x | 
                      data = object@data,  | 
                  
| 112 | 17x | 
                      type = type  | 
                  
| 113 | 
                      )  | 
                  |
| 114 | 
                      }  | 
                  |
| 115 | ||
| 116 | ||
| 117 | ||
| 118 | 
                      #' `as.data.frame`  | 
                  |
| 119 | 
                      #'  | 
                  |
| 120 | 
                      #' @param x ([`SurvivalQuantities`]) \cr longitudinal quantities.  | 
                  |
| 121 | 
                      #' @param ... not used.  | 
                  |
| 122 | 
                      #' @family SurvivalQuantities  | 
                  |
| 123 | 
                      #' @export  | 
                  |
| 124 | 
                      as.data.frame.SurvivalQuantities <- function(x, ...) {
                     | 
                  |
| 125 | ! | 
                      as.data.frame(x@quantities)  | 
                  
| 126 | 
                      }  | 
                  |
| 127 | ||
| 128 | ||
| 129 | ||
| 130 | 
                      #' summary  | 
                  |
| 131 | 
                      #'  | 
                  |
| 132 | 
                      #' @description  | 
                  |
| 133 | 
                      #' This method returns a `data.frame` of the longitudinal quantities.  | 
                  |
| 134 | 
                      #'  | 
                  |
| 135 | 
                      #' @param conf.level (`numeric`) \cr confidence level of the interval.  | 
                  |
| 136 | 
                      #' @inheritParams SurvivalQuantities-Shared  | 
                  |
| 137 | 
                      #'  | 
                  |
| 138 | 
                      #' @family SurvivalQuantities  | 
                  |
| 139 | 
                      #' @family summary  | 
                  |
| 140 | 
                      #' @export  | 
                  |
| 141 | 
                      summary.SurvivalQuantities <- function(  | 
                  |
| 142 | 
                      object,  | 
                  |
| 143 | 
                      conf.level = 0.95,  | 
                  |
| 144 | 
                      ...  | 
                  |
| 145 | 
                      ) {
                     | 
                  |
| 146 | 19x | 
                      summary(object@quantities, conf.level = conf.level)  | 
                  
| 147 | 
                      }  | 
                  |
| 148 | ||
| 149 | ||
| 150 | 
                      #' Automatic Plotting for `SurvivalQuantities``  | 
                  |
| 151 | 
                      #'  | 
                  |
| 152 | 
                      #' @inheritParams SurvivalQuantities-Shared  | 
                  |
| 153 | 
                      #' @param add_km (`logical`) \cr if `TRUE` Kaplan-Meier curves will be added to the plot for  | 
                  |
| 154 | 
                      #' each group/subject.  | 
                  |
| 155 | 
                      #' @param add_wrap (`logical`) \cr if `TRUE` will apply a [ggplot2::facet_wrap()] to the plot  | 
                  |
| 156 | 
                      #' by each group/subject.  | 
                  |
| 157 | 
                      #' @param conf.level (`numeric`) \cr confidence level of the interval. If values of `FALSE`,  | 
                  |
| 158 | 
                      #' `NULL` or `0` are provided then confidence regions will not be added to the plot  | 
                  |
| 159 | 
                      #' @param ... not used.  | 
                  |
| 160 | 
                      #'  | 
                  |
| 161 | 
                      #' @family SurvivalQuantities  | 
                  |
| 162 | 
                      #' @family autoplot  | 
                  |
| 163 | 
                      #' @export  | 
                  |
| 164 | 
                      autoplot.SurvivalQuantities <- function(  | 
                  |
| 165 | 
                      object,  | 
                  |
| 166 | 
                      conf.level = 0.95,  | 
                  |
| 167 | 
                      add_km = FALSE,  | 
                  |
| 168 | 
                      add_wrap = TRUE,  | 
                  |
| 169 | 
                      ...  | 
                  |
| 170 | 
                      ) {
                     | 
                  |
| 171 | 3x | 
                      include_ci <- !is.null(conf.level) && is.numeric(conf.level) && conf.level > 0  | 
                  
| 172 | 
                      # If CI aren't needed supply a default 0.95 to summary function as it needs  | 
                  |
| 173 | 
                      # a value to be specified to work  | 
                  |
| 174 | 3x | 
                      conf.level <- if (include_ci) conf.level else 0.95  | 
                  
| 175 | 3x | 
                      assert_that(  | 
                  
| 176 | 3x | 
                      is.flag(add_km),  | 
                  
| 177 | 3x | 
                      length(conf.level) == 1,  | 
                  
| 178 | 3x | 
                      conf.level < 1,  | 
                  
| 179 | 3x | 
                      is.flag(add_wrap)  | 
                  
| 180 | 
                      )  | 
                  |
| 181 | 3x | 
                          kmdf <- if (add_km) {
                     | 
                  
| 182 | 1x | 
                      subset(  | 
                  
| 183 | 1x | 
                      object@data,  | 
                  
| 184 | 1x | 
                      as.list(object@grid, data = object@data)  | 
                  
| 185 | 
                      )  | 
                  |
| 186 | 
                          } else {
                     | 
                  |
| 187 | 2x | 
                      NULL  | 
                  
| 188 | 
                      }  | 
                  |
| 189 | 3x | 
                      all_fit_df <- summary(object, conf.level = conf.level)  | 
                  
| 190 | 3x | 
                      label <- switch(  | 
                  
| 191 | 3x | 
                      object@type,  | 
                  
| 192 | 3x | 
                      "surv" = expression(S(t)),  | 
                  
| 193 | 3x | 
                      "cumhaz" = expression(H(t)),  | 
                  
| 194 | 3x | 
                      "haz" = expression(h(t)),  | 
                  
| 195 | 3x | 
                      "loghaz" = expression(log(h(t)))  | 
                  
| 196 | 
                      )  | 
                  |
| 197 | 3x | 
                      survival_plot(  | 
                  
| 198 | 3x | 
                      data = all_fit_df,  | 
                  
| 199 | 3x | 
                      add_ci = include_ci,  | 
                  
| 200 | 3x | 
                      add_wrap = add_wrap,  | 
                  
| 201 | 3x | 
                      kmdf = kmdf,  | 
                  
| 202 | 3x | 
                      y_label = label  | 
                  
| 203 | 
                      )  | 
                  |
| 204 | 
                      }  | 
                  |
| 205 | ||
| 206 | ||
| 207 | ||
| 208 | ||
| 209 | 
                      #' Survival Plot  | 
                  |
| 210 | 
                      #'  | 
                  |
| 211 | 
                      #' Internal plotting function to create survival plots with KM curve overlays  | 
                  |
| 212 | 
                      #' This function predominately exists to extract core logic into its own function  | 
                  |
| 213 | 
                      #' to enable easier unit testing.  | 
                  |
| 214 | 
                      #'  | 
                  |
| 215 | 
                      #' @param data (`data.frame`)\cr summary statistics for a survival  | 
                  |
| 216 | 
                      #' curve to be plotted. See details.  | 
                  |
| 217 | 
                      #' @param add_ci (`logical`)\cr should confidence intervals be added? Default = `TRUE`.  | 
                  |
| 218 | 
                      #' @param add_wrap (`logical`)\cr should the plots be wrapped by `data$group`? Default = `TRUE`.  | 
                  |
| 219 | 
                      #' @param kmdf (`data.frame` or `NULL`)\cr event times and status used to plot  | 
                  |
| 220 | 
                      #' overlaying KM curves. If `NULL` no KM curve will be plotted. See details.  | 
                  |
| 221 | 
                      #' @param y_label (`character` or `expression`) \cr label to display on the y-axis.  | 
                  |
| 222 | 
                      #' Default = `expression(S(t))`.  | 
                  |
| 223 | 
                      #' @param x_label (`character` or `expression`) \cr label to display on the x-axis.  | 
                  |
| 224 | 
                      #'  | 
                  |
| 225 | 
                      #' @details  | 
                  |
| 226 | 
                      #'  | 
                  |
| 227 | 
                      #' ## `data`  | 
                  |
| 228 | 
                      #' Should contain the following columns:  | 
                  |
| 229 | 
                      #' - `time` (`numeric`) \cr time point for the summary statistic.  | 
                  |
| 230 | 
                      #' - `group` (`character`) \cr the group in which the observation belongs to.  | 
                  |
| 231 | 
                      #' - `median` (`numeric`) \cr the median value for the summary statistic.  | 
                  |
| 232 | 
                      #' - `upper` (`numeric`) \cr the upper 95% CI for the summary statistic.  | 
                  |
| 233 | 
                      #' - `lower` (`numeric`) \cr the lower 95% CI for the summary statistic.  | 
                  |
| 234 | 
                      #'  | 
                  |
| 235 | 
                      #' ## `kmdf`  | 
                  |
| 236 | 
                      #' Should contain the following columns:  | 
                  |
| 237 | 
                      #' - `time` (`numeric`) \cr the time at which an event occurred.  | 
                  |
| 238 | 
                      #' - `event` (`numeric`) \cr 1/0 status indicator for the event.  | 
                  |
| 239 | 
                      #' - `group` (`character`) \cr which group the event belongs to, should correspond to values in `data$group`.  | 
                  |
| 240 | 
                      #' @keywords internal  | 
                  |
| 241 | 
                      survival_plot <- function(  | 
                  |
| 242 | 
                      data,  | 
                  |
| 243 | 
                      add_ci = TRUE,  | 
                  |
| 244 | 
                      add_wrap = TRUE,  | 
                  |
| 245 | 
                      kmdf = NULL,  | 
                  |
| 246 | 
                      y_label = expression(S(t)),  | 
                  |
| 247 | 
                      x_label = expression(t)  | 
                  |
| 248 | 
                      ) {
                     | 
                  |
| 249 | 6x | 
                      assert_that(  | 
                  
| 250 | 6x | 
                      is.flag(add_ci),  | 
                  
| 251 | 6x | 
                      is.flag(add_wrap),  | 
                  
| 252 | 6x | 
                      is.expression(y_label) || is.character(y_label),  | 
                  
| 253 | 6x | 
                      is.expression(x_label) || is.character(x_label),  | 
                  
| 254 | 6x | 
                      is.null(kmdf) | is.data.frame(kmdf)  | 
                  
| 255 | 
                      )  | 
                  |
| 256 | ||
| 257 | 6x | 
                      p <- ggplot() +  | 
                  
| 258 | 6x | 
                      xlab(x_label) +  | 
                  
| 259 | 6x | 
                      ylab(y_label) +  | 
                  
| 260 | 6x | 
                      theme_bw()  | 
                  
| 261 | ||
| 262 | 6x | 
                          if (add_wrap) {
                     | 
                  
| 263 | 2x | 
                      p <- p + facet_wrap(~group)  | 
                  
| 264 | 2x | 
                      aes_ci <- aes(x = .data$time, ymin = .data$lower, ymax = .data$upper)  | 
                  
| 265 | 2x | 
                      aes_line <- aes(x = .data$time, y = .data$median)  | 
                  
| 266 | 2x | 
                      aes_km <- aes(time = .data$time, status = .data$event)  | 
                  
| 267 | 
                          } else {
                     | 
                  |
| 268 | 4x | 
                      aes_ci <- aes(  | 
                  
| 269 | 4x | 
                      x = .data$time,  | 
                  
| 270 | 4x | 
                      ymin = .data$lower,  | 
                  
| 271 | 4x | 
                      ymax = .data$upper,  | 
                  
| 272 | 4x | 
                      fill = .data$group,  | 
                  
| 273 | 4x | 
                      group = .data$group  | 
                  
| 274 | 
                      )  | 
                  |
| 275 | 4x | 
                      aes_line <- aes(  | 
                  
| 276 | 4x | 
                      x = .data$time,  | 
                  
| 277 | 4x | 
                      y = .data$median,  | 
                  
| 278 | 4x | 
                      colour = .data$group,  | 
                  
| 279 | 4x | 
                      group = .data$group  | 
                  
| 280 | 
                      )  | 
                  |
| 281 | 4x | 
                      aes_km <- aes(  | 
                  
| 282 | 4x | 
                      time = .data$time,  | 
                  
| 283 | 4x | 
                      status = .data$event,  | 
                  
| 284 | 4x | 
                      group = .data$group,  | 
                  
| 285 | 4x | 
                      colour = .data$group  | 
                  
| 286 | 
                      )  | 
                  |
| 287 | 
                      }  | 
                  |
| 288 | 6x | 
                      p <- p + geom_line(aes_line, data = data)  | 
                  
| 289 | 6x | 
                          if (add_ci) {
                     | 
                  
| 290 | 2x | 
                      p <- p + geom_ribbon(aes_ci, data = data, alpha = 0.3)  | 
                  
| 291 | 
                      }  | 
                  |
| 292 | 6x | 
                          if (!is.null(kmdf)) {
                     | 
                  
| 293 | 2x | 
                      p <- p +  | 
                  
| 294 | 2x | 
                      ggplot2.utils::geom_km(aes_km, data = kmdf) +  | 
                  
| 295 | 2x | 
                      ggplot2.utils::geom_km_ticks(aes_km, data = kmdf)  | 
                  
| 296 | 
                      }  | 
                  |
| 297 | 6x | 
                      p  | 
                  
| 298 | 
                      }  | 
                  |
| 299 | ||
| 300 | ||
| 301 | 
                      #' @rdname show-object  | 
                  |
| 302 | 
                      #' @export  | 
                  |
| 303 | 
                      setMethod(  | 
                  |
| 304 | 
                      f = "show",  | 
                  |
| 305 | 
                      signature = "SurvivalQuantities",  | 
                  |
| 306 | 
                          definition = function(object) {
                     | 
                  |
| 307 | 1x | 
                      template <- c(  | 
                  
| 308 | 1x | 
                      "SurvivalQuantities Object:",  | 
                  
| 309 | 1x | 
                      " # of samples = %d",  | 
                  
| 310 | 1x | 
                      " # of quantities = %d",  | 
                  
| 311 | 1x | 
                      " Type = %s"  | 
                  
| 312 | 
                      )  | 
                  |
| 313 | 1x | 
                      string <- sprintf(  | 
                  
| 314 | 1x | 
                      paste(template, collapse = "\n"),  | 
                  
| 315 | 1x | 
                      nrow(object@quantities),  | 
                  
| 316 | 1x | 
                      ncol(object@quantities),  | 
                  
| 317 | 1x | 
                      object@type  | 
                  
| 318 | 
                      )  | 
                  |
| 319 | 1x | 
                              cat("\n", string, "\n\n")
                     | 
                  
| 320 | 
                      }  | 
                  |
| 321 | 
                      )  | 
                  |
| 322 | ||
| 323 | ||
| 324 | ||
| 325 | 
                      #' `brierScore`  | 
                  |
| 326 | 
                      #'  | 
                  |
| 327 | 
                      #' @description  | 
                  |
| 328 | 
                      #' Derives the Brier Scores (using Inverse Probability of Censoring Weighting)  | 
                  |
| 329 | 
                      #' for the Survival estimates as detailed in \insertCite{blanche2015}{jmpost}.
                     | 
                  |
| 330 | 
                      #'  | 
                  |
| 331 | 
                      #' @inheritParams SurvivalQuantities-Shared  | 
                  |
| 332 | 
                      #' @inheritParams Brier-Score-Shared  | 
                  |
| 333 | 
                      #'  | 
                  |
| 334 | 
                      #' @family brierScore  | 
                  |
| 335 | 
                      #' @family SurvivalQuantities  | 
                  |
| 336 | 
                      #' @references  | 
                  |
| 337 | 
                      #' \insertAllCited{}
                     | 
                  |
| 338 | 
                      #' @export  | 
                  |
| 339 | 
                      brierScore.SurvivalQuantities <- function(  | 
                  |
| 340 | 
                      object,  | 
                  |
| 341 | 
                      maintain_cen_order = TRUE,  | 
                  |
| 342 | 
                      event_offset = TRUE,  | 
                  |
| 343 | 
                      ...  | 
                  |
| 344 | 
                      ) {
                     | 
                  |
| 345 | 1x | 
                      assert_that(  | 
                  
| 346 | 1x | 
                      object@type == "surv",  | 
                  
| 347 | 1x | 
                      msg = paste(  | 
                  
| 348 | 1x | 
                      "Brier Score can only be calculated when the survival quantities were",  | 
                  
| 349 | 1x | 
                      "generated with `type = 'surv'`",  | 
                  
| 350 | 1x | 
                      collapse = " "  | 
                  
| 351 | 
                      )  | 
                  |
| 352 | 
                      )  | 
                  |
| 353 | 1x | 
                      assert_that(  | 
                  
| 354 | 1x | 
                      is(object@grid, "GridFixed"),  | 
                  
| 355 | 1x | 
                      msg = paste(  | 
                  
| 356 | 1x | 
                      "Brier Score can only be calculated when the survival quantities were",  | 
                  
| 357 | 1x | 
                      "generated with `grid = GridFixed()`",  | 
                  
| 358 | 1x | 
                      collapse = " "  | 
                  
| 359 | 
                      )  | 
                  |
| 360 | 
                      )  | 
                  |
| 361 | ||
| 362 | 1x | 
                      sdat <- summary(object)  | 
                  
| 363 | 1x | 
                      times <- unique(as.QuantityGenerator(object@grid, object@data)@times)  | 
                  
| 364 | 1x | 
                      times <- times[order(times)]  | 
                  
| 365 | 1x | 
                      assert_that(  | 
                  
| 366 | 1x | 
                      nrow(sdat) == length(times) * length(unique(sdat$group))  | 
                  
| 367 | 
                      )  | 
                  |
| 368 | ||
| 369 | 1x | 
                      subject_col <- extractVariableNames(object@data@subject)$subject  | 
                  
| 370 | 1x | 
                      time_col <- extractVariableNames(object@data@survival)$time  | 
                  
| 371 | 1x | 
                      event_col <- extractVariableNames(object@data@survival)$event  | 
                  
| 372 | 1x | 
                      groups <- as.character(object@data@survival@data[[subject_col]])  | 
                  
| 373 | 1x | 
                      orig_times <- object@data@survival@data[[time_col]]  | 
                  
| 374 | 1x | 
                      events <- object@data@survival@data[[event_col]]  | 
                  
| 375 | ||
| 376 | 1x | 
                      pred_mat <- matrix(  | 
                  
| 377 | 1x | 
                      ncol = length(times),  | 
                  
| 378 | 1x | 
                      nrow = length(unique(sdat$group))  | 
                  
| 379 | 
                      )  | 
                  |
| 380 | 1x | 
                          for (i in seq_along(times)) {
                     | 
                  
| 381 | 5x | 
                      pred_mat[, i] <- sdat[sdat["time"] == times[i], "median"]  | 
                  
| 382 | 5x | 
                      assert_that(  | 
                  
| 383 | 5x | 
                      all(groups == sdat[sdat["time"] == times[i], "group"])  | 
                  
| 384 | 
                      )  | 
                  |
| 385 | 
                      }  | 
                  |
| 386 | 1x | 
                      brier_score(  | 
                  
| 387 | 1x | 
                      t = times,  | 
                  
| 388 | 1x | 
                      times = orig_times,  | 
                  
| 389 | 1x | 
                      events = events,  | 
                  
| 390 | 1x | 
                      pred_mat = 1 - pred_mat,  | 
                  
| 391 | 1x | 
                      maintain_cen_order = maintain_cen_order,  | 
                  
| 392 | 1x | 
                      event_offset = event_offset  | 
                  
| 393 | 
                      )  | 
                  |
| 394 | 
                      }  | 
                  
| 1 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 2 | 
                      #' @include Link.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      # LongitudinalRandomSlope-class ----  | 
                  |
| 6 | ||
| 7 | 
                      #' `LongitudinalRandomSlope`  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' This class extends the general [`LongitudinalModel`] class for using the  | 
                  |
| 10 | 
                      #' random slope linear model for the longitudinal outcome.  | 
                  |
| 11 | 
                      #'  | 
                  |
| 12 | 
                      #' @section Available Links:  | 
                  |
| 13 | 
                      #' - [`linkDSLD()`]  | 
                  |
| 14 | 
                      #' - [`linkIdentity()`]  | 
                  |
| 15 | 
                      #' @exportClass LongitudinalRandomSlope  | 
                  |
| 16 | 
                      .LongitudinalRandomSlope <- setClass(  | 
                  |
| 17 | 
                      Class = "LongitudinalRandomSlope",  | 
                  |
| 18 | 
                      contains = "LongitudinalModel"  | 
                  |
| 19 | 
                      )  | 
                  |
| 20 | ||
| 21 | ||
| 22 | 
                      # LongitudinalRandomSlope-constructors ----  | 
                  |
| 23 | ||
| 24 | 
                      #' @rdname LongitudinalRandomSlope-class  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @param intercept (`Prior`)\cr for the `intercept`.  | 
                  |
| 27 | 
                      #' @param slope_mu (`Prior`)\cr for the population slope `slope_mu`.  | 
                  |
| 28 | 
                      #' @param slope_sigma (`Prior`)\cr for the random slope standard deviation `slope_sigma`.  | 
                  |
| 29 | 
                      #' @param sigma (`Prior`)\cr for the variance of the longitudinal values `sigma`.  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @export  | 
                  |
| 32 | 
                      LongitudinalRandomSlope <- function(  | 
                  |
| 33 | 
                      intercept = prior_normal(30, 10),  | 
                  |
| 34 | 
                      slope_mu = prior_normal(1, 3),  | 
                  |
| 35 | 
                      slope_sigma = prior_lognormal(0, 1.5),  | 
                  |
| 36 | 
                      sigma = prior_lognormal(0, 1.5)  | 
                  |
| 37 | 
                      ) {
                     | 
                  |
| 38 | ||
| 39 | 25x | 
                      stan <- StanModule(  | 
                  
| 40 | 25x | 
                      x = "lm-random-slope/model.stan"  | 
                  
| 41 | 
                      )  | 
                  |
| 42 | ||
| 43 | 
                      # Apply constriants  | 
                  |
| 44 | 25x | 
                      sigma <- set_limits(sigma, lower = 0)  | 
                  
| 45 | 25x | 
                      slope_sigma <- set_limits(slope_sigma, lower = 0)  | 
                  
| 46 | ||
| 47 | 25x | 
                      .LongitudinalRandomSlope(  | 
                  
| 48 | 25x | 
                      LongitudinalModel(  | 
                  
| 49 | 25x | 
                      name = "Random Slope",  | 
                  
| 50 | 25x | 
                      stan = stan,  | 
                  
| 51 | 25x | 
                      parameters = ParameterList(  | 
                  
| 52 | 25x | 
                      Parameter(name = "lm_rs_intercept", prior = intercept, size = "n_studies"),  | 
                  
| 53 | 25x | 
                      Parameter(name = "lm_rs_slope_mu", prior = slope_mu, size = "n_arms"),  | 
                  
| 54 | 25x | 
                      Parameter(name = "lm_rs_slope_sigma", prior = slope_sigma, size = 1),  | 
                  
| 55 | 25x | 
                      Parameter(name = "lm_rs_sigma", prior = sigma, size = 1),  | 
                  
| 56 | 25x | 
                      Parameter(  | 
                  
| 57 | 25x | 
                      name = "lm_rs_ind_rnd_slope",  | 
                  
| 58 | 25x | 
                      prior = prior_init_only(prior_normal(median(slope_mu), median(slope_sigma))),  | 
                  
| 59 | 25x | 
                      size = "n_subjects"  | 
                  
| 60 | 
                      )  | 
                  |
| 61 | 
                      )  | 
                  |
| 62 | 
                      )  | 
                  |
| 63 | 
                      )  | 
                  |
| 64 | 
                      }  | 
                  |
| 65 | ||
| 66 | ||
| 67 | 
                      #' @export  | 
                  |
| 68 | 
                      enableGQ.LongitudinalRandomSlope <- function(object, ...) {
                     | 
                  |
| 69 | 26x | 
                          StanModule("lm-random-slope/quantities.stan")
                     | 
                  
| 70 | 
                      }  | 
                  |
| 71 | ||
| 72 | 
                      #' @export  | 
                  |
| 73 | 
                      enableLink.LongitudinalRandomSlope <- function(object, ...) {
                     | 
                  |
| 74 | 5x | 
                      object@stan <- merge(  | 
                  
| 75 | 5x | 
                      object@stan,  | 
                  
| 76 | 5x | 
                              StanModule("lm-random-slope/link.stan")
                     | 
                  
| 77 | 
                      )  | 
                  |
| 78 | 5x | 
                      object  | 
                  
| 79 | 
                      }  | 
                  |
| 80 | ||
| 81 | ||
| 82 | 
                      #' @export  | 
                  |
| 83 | 
                      linkDSLD.LongitudinalRandomSlope <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 84 | 6x | 
                      LinkComponent(  | 
                  
| 85 | 6x | 
                      key = "link_dsld",  | 
                  
| 86 | 6x | 
                              stan = StanModule("lm-random-slope/link_dsld.stan"),
                     | 
                  
| 87 | 6x | 
                      prior = prior  | 
                  
| 88 | 
                      )  | 
                  |
| 89 | 
                      }  | 
                  |
| 90 | ||
| 91 | 
                      #' @export  | 
                  |
| 92 | 
                      linkIdentity.LongitudinalRandomSlope <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 93 | 2x | 
                      LinkComponent(  | 
                  
| 94 | 2x | 
                      key = "link_identity",  | 
                  
| 95 | 2x | 
                              stan = StanModule("lm-random-slope/link_identity.stan"),
                     | 
                  
| 96 | 2x | 
                      prior = prior  | 
                  
| 97 | 
                      )  | 
                  |
| 98 | 
                      }  | 
                  |
| 99 | ||
| 100 | 
                      #' @export  | 
                  |
| 101 | 
                      linkGrowth.LongitudinalRandomSlope <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 102 | ! | 
                      LinkComponent(  | 
                  
| 103 | ! | 
                      key = "link_growth",  | 
                  
| 104 | ! | 
                              stan = StanModule("lm-random-slope/link_growth.stan"),
                     | 
                  
| 105 | ! | 
                      prior = prior  | 
                  
| 106 | 
                      )  | 
                  |
| 107 | 
                      }  | 
                  |
| 108 | ||
| 109 | 
                      #' @rdname getPredictionNames  | 
                  |
| 110 | 
                      #' @export  | 
                  |
| 111 | 
                      getPredictionNames.LongitudinalRandomSlope <- function(object, ...) {
                     | 
                  |
| 112 | 1x | 
                          c("intercept", "slope")
                     | 
                  
| 113 | 
                      }  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include generics.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' @rdname Grid-Dev  | 
                  |
| 6 | 
                      .GridEvent <- setClass(  | 
                  |
| 7 | 
                      "GridEvent",  | 
                  |
| 8 | 
                      contains = "Grid",  | 
                  |
| 9 | 
                      slots = c(  | 
                  |
| 10 | 
                      "subjects" = "character_or_NULL"  | 
                  |
| 11 | 
                      )  | 
                  |
| 12 | 
                      )  | 
                  |
| 13 | ||
| 14 | ||
| 15 | 
                      #' @rdname Grid-Functions  | 
                  |
| 16 | 
                      #' @export  | 
                  |
| 17 | 
                      GridEvent <- function(subjects = NULL) {
                     | 
                  |
| 18 | 1x | 
                      .GridEvent(  | 
                  
| 19 | 1x | 
                      subjects = subjects  | 
                  
| 20 | 
                      )  | 
                  |
| 21 | 
                      }  | 
                  |
| 22 | ||
| 23 | 
                      #' @rdname Quant-Dev  | 
                  |
| 24 | 
                      #' @export  | 
                  |
| 25 | 
                      as.QuantityGenerator.GridEvent <- function(object, data, ...) {
                     | 
                  |
| 26 | 3x | 
                      assert_class(data, "DataJoint")  | 
                  
| 27 | 3x | 
                      assert_that(  | 
                  
| 28 | 3x | 
                      !is.null(data@survival),  | 
                  
| 29 | 3x | 
                      msg = "Survival data must have been provided to `DataJoint()` in order to use `GridEvent()`"  | 
                  
| 30 | 
                      )  | 
                  |
| 31 | 2x | 
                      data_list <- as.list(data)  | 
                  
| 32 | 2x | 
                      subjects <- unlist(as.list(object, data = data), use.names = FALSE)  | 
                  
| 33 | 2x | 
                      event_times <- data_list$event_times[data_list$subject_to_index[subjects]]  | 
                  
| 34 | 2x | 
                      QuantityGeneratorSubject(  | 
                  
| 35 | 2x | 
                      times = event_times,  | 
                  
| 36 | 2x | 
                      subjects = subjects  | 
                  
| 37 | 
                      )  | 
                  |
| 38 | 
                      }  | 
                  |
| 39 | ||
| 40 | 
                      #' @rdname Quant-Dev  | 
                  |
| 41 | 
                      #' @export  | 
                  |
| 42 | 
                      as.QuantityCollapser.GridEvent <- function(object, data, ...) {
                     | 
                  |
| 43 | 1x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 44 | 1x | 
                      QuantityCollapser(  | 
                  
| 45 | 1x | 
                      times = generator@times,  | 
                  
| 46 | 1x | 
                      groups = generator@subjects,  | 
                  
| 47 | 1x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 48 | 
                      )  | 
                  |
| 49 | 
                      }  | 
                  |
| 50 | ||
| 51 | 
                      #' @export  | 
                  |
| 52 | 
                      as.list.GridEvent <- function(x, data, ...) {
                     | 
                  |
| 53 | 2x | 
                      subjects_to_list(x@subjects, data)  | 
                  
| 54 | 
                      }  | 
                  
| 1 | 
                      # "missing" = no argument provided  | 
                  |
| 2 | 
                      # "NULL" = explicit NULL  | 
                  |
| 3 | 
                      setClassUnion("empty", c("missing", "NULL"))
                     | 
                  |
| 4 | 
                      setClassUnion("numeric_or_NULL", c("numeric", "NULL"))
                     | 
                  |
| 5 | 
                      setClassUnion("character_or_NULL", c("character", "NULL"))
                     | 
                  |
| 6 | ||
| 7 | 
                      # merge ----  | 
                  |
| 8 | ||
| 9 | 
                      #' `merge`  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' Merge two `StanModule` or `ParameterList` objects.  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' @param x first module.  | 
                  |
| 14 | 
                      #' @param y second module.  | 
                  |
| 15 | 
                      #' @param ... additional arguments.  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @export  | 
                  |
| 18 | 
                      # Needs to be S4 for multiple dispatch !  | 
                  |
| 19 | 
                      setGeneric(  | 
                  |
| 20 | 
                      name = "merge",  | 
                  |
| 21 | 
                          def = function(x, y, ...) standardGeneric("merge")
                     | 
                  |
| 22 | 
                      )  | 
                  |
| 23 | ||
| 24 | ||
| 25 | 
                      # show ----  | 
                  |
| 26 | ||
| 27 | 
                      #' Printing of Different Classes  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' These methods print objects of different classes.  | 
                  |
| 30 | 
                      #'  | 
                  |
| 31 | 
                      #' @name show  | 
                  |
| 32 | 
                      #' @aliases show  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' @param object what to print.  | 
                  |
| 35 | 
                      #'  | 
                  |
| 36 | 
                      #' @export  | 
                  |
| 37 | 
                      NULL  | 
                  |
| 38 | ||
| 39 | ||
| 40 | 
                      # write_stan ----  | 
                  |
| 41 | ||
| 42 | 
                      #' `write_stan`  | 
                  |
| 43 | 
                      #'  | 
                  |
| 44 | 
                      #' Write the Stan code for a Stan module.  | 
                  |
| 45 | 
                      #'  | 
                  |
| 46 | 
                      #' @param object the module.  | 
                  |
| 47 | 
                      #' @param destination (`character` or `connection`)\cr Where to write stan code to.  | 
                  |
| 48 | 
                      #' @param ... Additional arguments  | 
                  |
| 49 | 
                      #'  | 
                  |
| 50 | 
                      #' @export  | 
                  |
| 51 | 
                      write_stan <- function(object, destination, ...) {
                     | 
                  |
| 52 | ! | 
                          UseMethod("write_stan")
                     | 
                  
| 53 | 
                      }  | 
                  |
| 54 | ||
| 55 | 
                      # compileStanModel ----  | 
                  |
| 56 | ||
| 57 | 
                      #' `compileStanModel`  | 
                  |
| 58 | 
                      #'  | 
                  |
| 59 | 
                      #' Compile the Stan module.  | 
                  |
| 60 | 
                      #'  | 
                  |
| 61 | 
                      #' @param object the module.  | 
                  |
| 62 | 
                      #'  | 
                  |
| 63 | 
                      #' @export  | 
                  |
| 64 | 
                      compileStanModel <- function(object) {
                     | 
                  |
| 65 | 65x | 
                          UseMethod("compileStanModel")
                     | 
                  
| 66 | 
                      }  | 
                  |
| 67 | ||
| 68 | ||
| 69 | 
                      # sampleStanModel ----  | 
                  |
| 70 | ||
| 71 | 
                      #' `sampleStanModel`  | 
                  |
| 72 | 
                      #'  | 
                  |
| 73 | 
                      #' Sample from a Stan Module.  | 
                  |
| 74 | 
                      #'  | 
                  |
| 75 | 
                      #' @param object the module.  | 
                  |
| 76 | 
                      #' @param ... additional arguments.  | 
                  |
| 77 | 
                      #'  | 
                  |
| 78 | 
                      #' @export  | 
                  |
| 79 | 
                      sampleStanModel <- function(object, ...) {
                     | 
                  |
| 80 | 17x | 
                          UseMethod("sampleStanModel")
                     | 
                  
| 81 | 
                      }  | 
                  |
| 82 | ||
| 83 | ||
| 84 | 
                      # as.StanModule ----  | 
                  |
| 85 | ||
| 86 | 
                      #' `as.StanModule`  | 
                  |
| 87 | 
                      #'  | 
                  |
| 88 | 
                      #' Converts an object into a [`StanModule`].  | 
                  |
| 89 | 
                      #'  | 
                  |
| 90 | 
                      #' @param object what to convert.  | 
                  |
| 91 | 
                      #' @param ... additional options.  | 
                  |
| 92 | 
                      #' @family as.StanModule  | 
                  |
| 93 | 
                      #' @keywords internal  | 
                  |
| 94 | 
                      as.StanModule <- function(object, ...) {
                     | 
                  |
| 95 | 1579x | 
                          UseMethod("as.StanModule")
                     | 
                  
| 96 | 
                      }  | 
                  |
| 97 | ||
| 98 | ||
| 99 | ||
| 100 | 
                      #' `getParameters`  | 
                  |
| 101 | 
                      #'  | 
                  |
| 102 | 
                      #' Extract any modelling parameters as a [`ParameterList`] object  | 
                  |
| 103 | 
                      #' from a model.  | 
                  |
| 104 | 
                      #'  | 
                  |
| 105 | 
                      #' @param object where to obtain the parameters from.  | 
                  |
| 106 | 
                      #' @param ... additional options.  | 
                  |
| 107 | 
                      #'  | 
                  |
| 108 | 
                      #' @export  | 
                  |
| 109 | 
                      getParameters <- function(object, ...) {
                     | 
                  |
| 110 | 134x | 
                          UseMethod("getParameters")
                     | 
                  
| 111 | 
                      }  | 
                  |
| 112 | ||
| 113 | ||
| 114 | 
                      # extractVariableNames ----  | 
                  |
| 115 | ||
| 116 | 
                      #' Extract Mapping to Standardised Variable Names  | 
                  |
| 117 | 
                      #'  | 
                  |
| 118 | 
                      #' @description  | 
                  |
| 119 | 
                      #' Extract a `list` that maps the variable names in a user-defined  | 
                  |
| 120 | 
                      #' `data.frame` to standardised values.  | 
                  |
| 121 | 
                      #'  | 
                  |
| 122 | 
                      #' @param object the data object.  | 
                  |
| 123 | 
                      #' @family extractVariableNames  | 
                  |
| 124 | 
                      #' @keywords internal  | 
                  |
| 125 | 
                      extractVariableNames <- function(object) {
                     | 
                  |
| 126 | 1672x | 
                          UseMethod("extractVariableNames")
                     | 
                  
| 127 | 
                      }  | 
                  |
| 128 | ||
| 129 | ||
| 130 | ||
| 131 | 
                      # initialValues ----  | 
                  |
| 132 | ||
| 133 | 
                      #' `initialValues`  | 
                  |
| 134 | 
                      #'  | 
                  |
| 135 | 
                      #' Obtain the `list` of initial values to be passed to the Stan sampler.  | 
                  |
| 136 | 
                      #'  | 
                  |
| 137 | 
                      #' @param object where to get the initial values from.  | 
                  |
| 138 | 
                      #' @param n_chains the number of initial values to generate. See details.  | 
                  |
| 139 | 
                      #' @param ... Not currently used.  | 
                  |
| 140 | 
                      #'  | 
                  |
| 141 | 
                      #' @details  | 
                  |
| 142 | 
                      #' There are multiple ways of specifying initial values to Stan, see the `init` argument  | 
                  |
| 143 | 
                      #' in [cmdstanr::model-method-sample] for full details. Within this package we supply  | 
                  |
| 144 | 
                      #' initial values via a list of lists where each inner list contains the initial values  | 
                  |
| 145 | 
                      #' for a single chain. As such the `n_chains` argument specifies the number of inner lists  | 
                  |
| 146 | 
                      #' to generate.  | 
                  |
| 147 | 
                      #'  | 
                  |
| 148 | 
                      #' See the Vignette for further details of how to specify initial values.  | 
                  |
| 149 | 
                      #'  | 
                  |
| 150 | 
                      #' @export  | 
                  |
| 151 | 
                      initialValues <- function(object, ...) {
                     | 
                  |
| 152 | 78501x | 
                          UseMethod("initialValues")
                     | 
                  
| 153 | 
                      }  | 
                  |
| 154 | ||
| 155 | ||
| 156 | 
                      # size ----  | 
                  |
| 157 | ||
| 158 | 
                      #' `size`  | 
                  |
| 159 | 
                      #'  | 
                  |
| 160 | 
                      #' Obtain the `list` of parameter sizes.  | 
                  |
| 161 | 
                      #'  | 
                  |
| 162 | 
                      #' @param object where to get the parameter sizes from.  | 
                  |
| 163 | 
                      #'  | 
                  |
| 164 | 
                      #' @keywords internal  | 
                  |
| 165 | 
                      size <- function(object) {
                     | 
                  |
| 166 | 136x | 
                          UseMethod("size")
                     | 
                  
| 167 | 
                      }  | 
                  |
| 168 | ||
| 169 | ||
| 170 | 
                      # generateQuantities ----  | 
                  |
| 171 | ||
| 172 | 
                      #' `generateQuantities`  | 
                  |
| 173 | 
                      #'  | 
                  |
| 174 | 
                      #' Obtain the generated quantities from a Stan Model.  | 
                  |
| 175 | 
                      #'  | 
                  |
| 176 | 
                      #' @param object object to obtain generated quantities from  | 
                  |
| 177 | 
                      #' @param ... additional options.  | 
                  |
| 178 | 
                      #'  | 
                  |
| 179 | 
                      #' @export  | 
                  |
| 180 | 
                      generateQuantities <- function(object, ...) {
                     | 
                  |
| 181 | 31x | 
                          UseMethod("generateQuantities")
                     | 
                  
| 182 | 
                      }  | 
                  |
| 183 | ||
| 184 | ||
| 185 | 
                      #' Prepare Data Object  | 
                  |
| 186 | 
                      #'  | 
                  |
| 187 | 
                      #' @param object (`DataSubject` or `DataLongitudinal` or `DataSurvival`) \cr data object to "harmonise"  | 
                  |
| 188 | 
                      #' @param subject_var (`character`) \cr the name of the variable containing the subject identifier.  | 
                  |
| 189 | 
                      #' @param subject_ord (`character`) \cr the expected levels (in order) of the subject identifier.  | 
                  |
| 190 | 
                      #' @param ... not used.  | 
                  |
| 191 | 
                      #'  | 
                  |
| 192 | 
                      #' @details  | 
                  |
| 193 | 
                      #' This utility function prepares the datasets in the data objects in order to ensure they  | 
                  |
| 194 | 
                      #' are consistent and compatible with each other.  | 
                  |
| 195 | 
                      #'  | 
                  |
| 196 | 
                      #' In particular it ensures that the `subject` variable, as specified by `DataSubject`,  | 
                  |
| 197 | 
                      #' is available in `DataLongitudinal` and `DataSurvival` and that all levels are present  | 
                  |
| 198 | 
                      #' in all 3 data objects.  | 
                  |
| 199 | 
                      #'  | 
                  |
| 200 | 
                      #' It also sorts the datasets to ensure that indexes are consistent e.g. index 1 for  | 
                  |
| 201 | 
                      #' `DataSubject@data` corresponds to the same subject as index 1 for `DataSurvival@data`.  | 
                  |
| 202 | 
                      #' For `DataLongitudinal` the data is additionally sorted by time and outcome value.  | 
                  |
| 203 | 
                      #'  | 
                  |
| 204 | 
                      #' @seealso [`DataJoint`], [`DataSurvival`], [`DataSubject`], [`DataLongitudinal`]  | 
                  |
| 205 | 
                      #'  | 
                  |
| 206 | 
                      #' @keywords internal  | 
                  |
| 207 | 
                      #' @return Returns the original object but with the data standardised (see details)  | 
                  |
| 208 | 
                      harmonise <- function(object, ...) {
                     | 
                  |
| 209 | 384x | 
                          UseMethod("harmonise")
                     | 
                  
| 210 | 
                      }  | 
                  |
| 211 | ||
| 212 | ||
| 213 | 
                      #' @rdname harmonise  | 
                  |
| 214 | 
                      harmonise.default <- function(object, ...) {
                     | 
                  |
| 215 | 13x | 
                      NULL  | 
                  
| 216 | 
                      }  | 
                  |
| 217 | ||
| 218 | ||
| 219 | 
                      #' `as_stan_list`  | 
                  |
| 220 | 
                      #'  | 
                  |
| 221 | 
                      #' @description  | 
                  |
| 222 | 
                      #' Extracts a list of data elements from an object to be used as input  | 
                  |
| 223 | 
                      #' to a Stan Model  | 
                  |
| 224 | 
                      #'  | 
                  |
| 225 | 
                      #' @param object to be converted.  | 
                  |
| 226 | 
                      #' @param ... additional options.  | 
                  |
| 227 | 
                      #'  | 
                  |
| 228 | 
                      #' @family as_stan_list  | 
                  |
| 229 | 
                      #' @export  | 
                  |
| 230 | 
                      as_stan_list <- function(object, ...) {
                     | 
                  |
| 231 | 2023x | 
                          UseMethod("as_stan_list")
                     | 
                  
| 232 | 
                      }  | 
                  |
| 233 | ||
| 234 | 
                      #' @rdname as_stan_list  | 
                  |
| 235 | 
                      #' @export  | 
                  |
| 236 | 
                      as_stan_list.default <- function(object, ...) {
                     | 
                  |
| 237 | 21x | 
                      NULL  | 
                  
| 238 | 
                      }  | 
                  |
| 239 | ||
| 240 | ||
| 241 | 
                      #' `as_print_string`  | 
                  |
| 242 | 
                      #'  | 
                  |
| 243 | 
                      #' @description  | 
                  |
| 244 | 
                      #' Returns the character representation of an object which is suitable  | 
                  |
| 245 | 
                      #' for printing to the console  | 
                  |
| 246 | 
                      #'  | 
                  |
| 247 | 
                      #' @param object to be converted to string.  | 
                  |
| 248 | 
                      #' @param ... additional options.  | 
                  |
| 249 | 
                      #'  | 
                  |
| 250 | 
                      #' @family as_print_string  | 
                  |
| 251 | 
                      #' @keywords internal  | 
                  |
| 252 | 
                      as_print_string <- function(object, ...) {
                     | 
                  |
| 253 | 57x | 
                          UseMethod("as_print_string")
                     | 
                  
| 254 | 
                      }  | 
                  |
| 255 | ||
| 256 | 
                      #' Show an Object  | 
                  |
| 257 | 
                      #'  | 
                  |
| 258 | 
                      #' Prints an object to the console.  | 
                  |
| 259 | 
                      #'  | 
                  |
| 260 | 
                      #' @param object Object to be printed  | 
                  |
| 261 | 
                      #'  | 
                  |
| 262 | 
                      #' @name show-object  | 
                  |
| 263 | 
                      NULL  | 
                  |
| 264 | ||
| 265 | ||
| 266 | ||
| 267 | 
                      #' `brierScore`  | 
                  |
| 268 | 
                      #'  | 
                  |
| 269 | 
                      #' @description  | 
                  |
| 270 | 
                      #' Returns the Brier Score for a given model  | 
                  |
| 271 | 
                      #'  | 
                  |
| 272 | 
                      #' @param object to calculate Brier Score for.  | 
                  |
| 273 | 
                      #' @param ... additional options.  | 
                  |
| 274 | 
                      #'  | 
                  |
| 275 | 
                      #' @family brierScore  | 
                  |
| 276 | 
                      #' @export  | 
                  |
| 277 | 
                      brierScore <- function(object, ...) {
                     | 
                  |
| 278 | 1x | 
                          UseMethod("brierScore")
                     | 
                  
| 279 | 
                      }  | 
                  |
| 280 | ||
| 281 | ||
| 282 | ||
| 283 | 
                      #' Generate Simulated Observations  | 
                  |
| 284 | 
                      #'  | 
                  |
| 285 | 
                      #' @param object (`SimLongitudinal` or `SimSurvival`) \cr object to generate observations from.  | 
                  |
| 286 | 
                      #' @param times_df (`data.frame`) \cr the times at which to generate observations. See details.  | 
                  |
| 287 | 
                      #'  | 
                  |
| 288 | 
                      #' @details  | 
                  |
| 289 | 
                      #' The `times_df` argument should be a `data.frame` as created by `sampleSubjects` but  | 
                  |
| 290 | 
                      #' replicated for each time point at which observations are to be generated. That is if you want  | 
                  |
| 291 | 
                      #' to generate observations for times `c(0, 1, 2, 3)` then `times_df` should be created as:  | 
                  |
| 292 | 
                      #' ```  | 
                  |
| 293 | 
                      #' subject_dat <- sampleSubjects(object, ...)  | 
                  |
| 294 | 
                      #' times_df <- tidyr::expand_grid(  | 
                  |
| 295 | 
                      #' subject_dat,  | 
                  |
| 296 | 
                      #' time = c(0, 1, 2, 3)  | 
                  |
| 297 | 
                      #' )  | 
                  |
| 298 | 
                      #' ```  | 
                  |
| 299 | 
                      #'  | 
                  |
| 300 | 
                      #' @export  | 
                  |
| 301 | 
                      sampleObservations <- function(object, times_df) {
                     | 
                  |
| 302 | 70x | 
                          UseMethod("sampleObservations")
                     | 
                  
| 303 | 
                      }  | 
                  |
| 304 | ||
| 305 | ||
| 306 | 
                      #' Generate Simulated Subjects  | 
                  |
| 307 | 
                      #'  | 
                  |
| 308 | 
                      #' @param object (`SimLongitudinal` or `SimSurvival`) \cr object to generate subjects from.  | 
                  |
| 309 | 
                      #' @param subjects_df (`data.frame`) \cr the subjects to generate observations for. See details.  | 
                  |
| 310 | 
                      #'  | 
                  |
| 311 | 
                      #' @details  | 
                  |
| 312 | 
                      #' The `subjects_df` argument should be a `data.frame` with 1 row per desired subject to create  | 
                  |
| 313 | 
                      #' with the following columns:  | 
                  |
| 314 | 
                      #' - `study` (`factor`) the study identifier.  | 
                  |
| 315 | 
                      #' - `arm` (`factor`) the treatment arm identifier.  | 
                  |
| 316 | 
                      #' - `subject` (`character`) the subject identifier.  | 
                  |
| 317 | 
                      #'  | 
                  |
| 318 | 
                      #' This method takes care of generating all the individual subject data required for the  | 
                  |
| 319 | 
                      #' [`sampleObservations`] method to generate the observations.  | 
                  |
| 320 | 
                      #' @export  | 
                  |
| 321 | 
                      sampleSubjects <- function(object, subjects_df) {
                     | 
                  |
| 322 | 48x | 
                          UseMethod("sampleSubjects")
                     | 
                  
| 323 | 
                      }  | 
                  |
| 324 | ||
| 325 | ||
| 326 | 
                      #' Generate time windows for evaluating a hazard function  | 
                  |
| 327 | 
                      #'  | 
                  |
| 328 | 
                      #' @param object (`SurvivalModel`) \cr object to generate time windows for.  | 
                  |
| 329 | 
                      #' @param ... Not used.  | 
                  |
| 330 | 
                      #'  | 
                  |
| 331 | 
                      hazardWindows <- function(object, ...) {
                     | 
                  |
| 332 | 22x | 
                          UseMethod("hazardWindows")
                     | 
                  
| 333 | 
                      }  | 
                  |
| 334 | ||
| 335 | ||
| 336 | 
                      #' Coerce to `CmdStanMCMC`  | 
                  |
| 337 | 
                      #'  | 
                  |
| 338 | 
                      #' @param object to be converted  | 
                  |
| 339 | 
                      #' @param ... additional options  | 
                  |
| 340 | 
                      #'  | 
                  |
| 341 | 
                      #' @description  | 
                  |
| 342 | 
                      #' Coerces an object to a [`cmdstanr::CmdStanMCMC`] object  | 
                  |
| 343 | 
                      #'  | 
                  |
| 344 | 
                      #' @export  | 
                  |
| 345 | 
                      as.CmdStanMCMC <- function(object, ...) {
                     | 
                  |
| 346 | 81x | 
                          UseMethod("as.CmdStanMCMC")
                     | 
                  
| 347 | 
                      }  | 
                  |
| 348 | ||
| 349 | 
                      #' @rdname Quant-Dev  | 
                  |
| 350 | 
                      #' @export  | 
                  |
| 351 | 
                      as.QuantityGenerator <- function(object, ...) {
                     | 
                  |
| 352 | 98x | 
                          UseMethod("as.QuantityGenerator")
                     | 
                  
| 353 | 
                      }  | 
                  |
| 354 | ||
| 355 | 
                      #' @rdname Quant-Dev  | 
                  |
| 356 | 
                      #' @export  | 
                  |
| 357 | 
                      as.QuantityCollapser <- function(object, ...) {
                     | 
                  |
| 358 | 37x | 
                          UseMethod("as.QuantityCollapser")
                     | 
                  
| 359 | 
                      }  | 
                  |
| 360 | ||
| 361 | ||
| 362 | 
                      #' Coalesce Time  | 
                  |
| 363 | 
                      #'  | 
                  |
| 364 | 
                      #' @param object ([`Grid`]) \cr object to coalesce time for.  | 
                  |
| 365 | 
                      #' @param times (`numeric`) \cr the times to coalesce to.  | 
                  |
| 366 | 
                      #' @param ... Not used  | 
                  |
| 367 | 
                      #'  | 
                  |
| 368 | 
                      #' Method used to replace NULL times on grid objects (if appropriate)  | 
                  |
| 369 | 
                      #'  | 
                  |
| 370 | 
                      #' @keywords internal  | 
                  |
| 371 | 
                      coalesceGridTime <- function(object, times, ...) {
                     | 
                  |
| 372 | 37x | 
                          UseMethod("coalesceGridTime")
                     | 
                  
| 373 | 
                      }  | 
                  |
| 374 | 
                      #' @export  | 
                  |
| 375 | 
                      coalesceGridTime.default <- function(object, times, ...) {
                     | 
                  |
| 376 | 2x | 
                      object  | 
                  
| 377 | 
                      }  | 
                  |
| 378 | ||
| 379 | ||
| 380 | 
                      #' Resolve a Promise  | 
                  |
| 381 | 
                      #'  | 
                  |
| 382 | 
                      #' @param object (`ANY`)\cr an object to resolve.  | 
                  |
| 383 | 
                      #' @param ... (`ANY`)\cr additional arguments.  | 
                  |
| 384 | 
                      #'  | 
                  |
| 385 | 
                      #' If `object` is not a promise will just return itself else will resolve the promise  | 
                  |
| 386 | 
                      #' and return the promised object.  | 
                  |
| 387 | 
                      #'  | 
                  |
| 388 | 
                      #' @export  | 
                  |
| 389 | 
                      resolvePromise <- function(object, ...) {
                     | 
                  |
| 390 | 62x | 
                          UseMethod("resolvePromise")
                     | 
                  
| 391 | 
                      }  | 
                  |
| 392 | ||
| 393 | 
                      #' @rdname resolvePromise  | 
                  |
| 394 | 
                      #' @export  | 
                  |
| 395 | 
                      resolvePromise.default <- function(object, ...) {
                     | 
                  |
| 396 | ! | 
                      object  | 
                  
| 397 | 
                      }  | 
                  |
| 398 | ||
| 399 | 
                      #' Enable Link Generic  | 
                  |
| 400 | 
                      #'  | 
                  |
| 401 | 
                      #' @param object ([`LongitudinalModel`])\cr to enable link for.  | 
                  |
| 402 | 
                      #' @param ... Not used.  | 
                  |
| 403 | 
                      #'  | 
                  |
| 404 | 
                      #' Optional hook method that is called on a [`LongitudinalModel`] only if a link method  | 
                  |
| 405 | 
                      #' is provided to [`JointModel`]. This can be used to allow the model to include any  | 
                  |
| 406 | 
                      #' optional stan code that is only required if there are links present.  | 
                  |
| 407 | 
                      #'  | 
                  |
| 408 | 
                      #' @return [`LongitudinalModel`] object  | 
                  |
| 409 | 
                      #'  | 
                  |
| 410 | 
                      #' @export  | 
                  |
| 411 | 
                      enableLink <- function(object, ...) {
                     | 
                  |
| 412 | 11x | 
                          UseMethod("enableLink")
                     | 
                  
| 413 | 
                      }  | 
                  |
| 414 | 
                      #' @export  | 
                  |
| 415 | 
                      enableLink.default <- function(object, ...) {
                     | 
                  |
| 416 | ! | 
                      object  | 
                  
| 417 | 
                      }  | 
                  |
| 418 | ||
| 419 | ||
| 420 | 
                      #' Enable Generated Quantities Generic  | 
                  |
| 421 | 
                      #'  | 
                  |
| 422 | 
                      #' @param object ([`StanModel`])\cr to enable generated quantities for.  | 
                  |
| 423 | 
                      #' @param ... Not used.  | 
                  |
| 424 | 
                      #'  | 
                  |
| 425 | 
                      #' Optional hook method that is called on a [`StanModel`] if attempting to use  | 
                  |
| 426 | 
                      #' either [`LongitudinalQuantities`] or [`SurvivalQuantities`]  | 
                  |
| 427 | 
                      #'  | 
                  |
| 428 | 
                      #' @return [`StanModule`] object  | 
                  |
| 429 | 
                      #'  | 
                  |
| 430 | 
                      #' @export  | 
                  |
| 431 | 
                      enableGQ <- function(object, ...) {
                     | 
                  |
| 432 | 114x | 
                          UseMethod("enableGQ")
                     | 
                  
| 433 | 
                      }  | 
                  |
| 434 | 
                      #' @export  | 
                  |
| 435 | 
                      enableGQ.default <- function(object, ...) {
                     | 
                  |
| 436 | 39x | 
                      StanModule()  | 
                  
| 437 | 
                      }  | 
                  |
| 438 | ||
| 439 | ||
| 440 | ||
| 441 | 
                      #' Get Prediction Names  | 
                  |
| 442 | 
                      #'  | 
                  |
| 443 | 
                      #' Utility function that returns the names of the required parameters for predicting  | 
                  |
| 444 | 
                      #' survival quantities with [`GridPrediction`].  | 
                  |
| 445 | 
                      #'  | 
                  |
| 446 | 
                      #' @param object (`LongitudinalModel`) \cr A longitudinal model object  | 
                  |
| 447 | 
                      #' @param ... Not used.  | 
                  |
| 448 | 
                      #' @export  | 
                  |
| 449 | 
                      getPredictionNames <- function(object, ...) {
                     | 
                  |
| 450 | 6x | 
                          UseMethod("getPredictionNames")
                     | 
                  
| 451 | 
                      }  | 
                  |
| 452 | ||
| 453 | 
                      #' @rdname getPredictionNames  | 
                  |
| 454 | 
                      getPredictionNames.default <- function(object, ...) {
                     | 
                  |
| 455 | 1x | 
                      NULL  | 
                  
| 456 | 
                      }  | 
                  |
| 457 | ||
| 458 | 
                      #' As Formula  | 
                  |
| 459 | 
                      #'  | 
                  |
| 460 | 
                      #' Utility wrapper function to convert an object to a formula.  | 
                  |
| 461 | 
                      #' @param x (`ANY`) \cr object to convert to a formula.  | 
                  |
| 462 | 
                      #' @param ... Not used.  | 
                  |
| 463 | 
                      #' @export  | 
                  |
| 464 | 
                      as_formula <- function(x, ...) {
                     | 
                  |
| 465 | 7x | 
                          UseMethod("as_formula")
                     | 
                  
| 466 | 
                      }  | 
                  |
| 467 | ||
| 468 | 
                      #' @importFrom stats as.formula  | 
                  |
| 469 | 
                      #' @export  | 
                  |
| 470 | 
                      as_formula.default <- function(x, ...) {
                     | 
                  |
| 471 | ! | 
                      as.formula(x, ...)  | 
                  
| 472 | 
                      }  | 
                  |
| 473 | ||
| 474 | ||
| 475 | 
                      #' Set Constraints  | 
                  |
| 476 | 
                      #'  | 
                  |
| 477 | 
                      #' Applies constraints to a prior distribution to ensure any sampled numbers  | 
                  |
| 478 | 
                      #' from the distribution fall within the constraints  | 
                  |
| 479 | 
                      #'  | 
                  |
| 480 | 
                      #' @param object (`Prior`)\cr a prior distribution to apply constraints to  | 
                  |
| 481 | 
                      #' @param lower (`numeric`)\cr lower constraint boundary  | 
                  |
| 482 | 
                      #' @param upper (`numeric`)\cr upper constraint boundary  | 
                  |
| 483 | 
                      #'  | 
                  |
| 484 | 
                      #' @export  | 
                  |
| 485 | 
                      set_limits <- function(object, lower = -Inf, upper = Inf) {
                     | 
                  |
| 486 | 285x | 
                          UseMethod("set_limits")
                     | 
                  
| 487 | 
                      }  | 
                  
| 1 | ||
| 2 | ||
| 3 | 
                      #' Promise  | 
                  |
| 4 | 
                      #'  | 
                  |
| 5 | 
                      #' Abstract class for promise objects to inherit off of  | 
                  |
| 6 | 
                      #' @aliases Promise  | 
                  |
| 7 | 
                      #' @exportClass Promise  | 
                  |
| 8 | 
                      .Promise <- setClass("Promise")
                     | 
                  |
| 9 | ||
| 10 | ||
| 11 | 
                      #' Promise of a `LongitudinalModel`  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' An object that promises to resolve to a [`LongitudinalModel`] object.  | 
                  |
| 14 | 
                      #'  | 
                  |
| 15 | 
                      #' @exportClass PromiseLongitudinalModel  | 
                  |
| 16 | 
                      .PromiseLongitudinalModel <- setClass(  | 
                  |
| 17 | 
                      "PromiseLongitudinalModel",  | 
                  |
| 18 | 
                      contains = "Promise"  | 
                  |
| 19 | 
                      )  | 
                  |
| 20 | ||
| 21 | 
                      #' @rdname PromiseLongitudinalModel-class  | 
                  |
| 22 | 
                      #' @export  | 
                  |
| 23 | 
                      PromiseLongitudinalModel <- function() {
                     | 
                  |
| 24 | 26x | 
                      .PromiseLongitudinalModel()  | 
                  
| 25 | 
                      }  | 
                  |
| 26 | ||
| 27 | ||
| 28 | ||
| 29 | ||
| 30 | 
                      #' Promise of a `LinkComponent`  | 
                  |
| 31 | 
                      #'  | 
                  |
| 32 | 
                      #' An object that promises to resolve to a [`LinkComponent`] object.  | 
                  |
| 33 | 
                      #' Inheriting from [`Promise`] and [`LinkComponent`].  | 
                  |
| 34 | 
                      #'  | 
                  |
| 35 | 
                      #' @slot fun (`function`) \cr a function that returns a `LinkComponent`. See details.  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' @param fun (`function`) \cr a function that returns a `LinkComponent`. See details.  | 
                  |
| 38 | 
                      #' @inheritParams LinkComponent  | 
                  |
| 39 | 
                      #'  | 
                  |
| 40 | 
                      #' @details  | 
                  |
| 41 | 
                      #'  | 
                  |
| 42 | 
                      #' The `fun` slot should be a function of signature `function(prior, model)` and should return  | 
                  |
| 43 | 
                      #' a [`LinkComponent`] object. An error will be thrown if the returned [`LinkComponent`] object  | 
                  |
| 44 | 
                      #' does not have the same `key` slot value as the original `PromiseLinkComponent`.  | 
                  |
| 45 | 
                      #'  | 
                  |
| 46 | 
                      #' @exportClass PromiseLinkComponent  | 
                  |
| 47 | 
                      .PromiseLinkComponent <- setClass(  | 
                  |
| 48 | 
                      "PromiseLinkComponent",  | 
                  |
| 49 | 
                          contains = c("Promise", "LinkComponent"),
                     | 
                  |
| 50 | 
                      slots = list(  | 
                  |
| 51 | 
                      fun = "function"  | 
                  |
| 52 | 
                      )  | 
                  |
| 53 | 
                      )  | 
                  |
| 54 | ||
| 55 | 
                      #' @rdname PromiseLinkComponent-class  | 
                  |
| 56 | 
                      #' @export  | 
                  |
| 57 | 
                      PromiseLinkComponent <- function(fun, prior, key) {
                     | 
                  |
| 58 | 28x | 
                      .PromiseLinkComponent(  | 
                  
| 59 | 28x | 
                      fun = fun,  | 
                  
| 60 | 28x | 
                      stan = StanModule(),  | 
                  
| 61 | 28x | 
                      parameters = ParameterList(Parameter(name = key, prior = prior, size = 1)),  | 
                  
| 62 | 28x | 
                      key = key  | 
                  
| 63 | 
                      )  | 
                  |
| 64 | 
                      }  | 
                  |
| 65 | ||
| 66 | ||
| 67 | 
                      #' @export  | 
                  |
| 68 | 
                      as.StanModule.PromiseLinkComponent <- function(object, model, ...) {
                     | 
                  |
| 69 | 1x | 
                      resolved_object <- resolvePromise(object, model = model)  | 
                  
| 70 | 1x | 
                      as.StanModule(resolved_object, ...)  | 
                  
| 71 | 
                      }  | 
                  |
| 72 | ||
| 73 | 
                      #' Resolve a `PromiseLinkComponent`  | 
                  |
| 74 | 
                      #'  | 
                  |
| 75 | 
                      #' Resolves a [`PromiseLinkComponent`] object to a [`LinkComponent`] object.  | 
                  |
| 76 | 
                      #' An error will be thrown if the returned [`LinkComponent`] object  | 
                  |
| 77 | 
                      #' does not have the same `key` slot value as the original [`PromiseLinkComponent`].  | 
                  |
| 78 | 
                      #'  | 
                  |
| 79 | 
                      #' @param object ([`PromiseLinkComponent`]) \cr the promise to resolve  | 
                  |
| 80 | 
                      #' @param model ([`LongitudinalModel`]) \cr the model to resolve the promise with  | 
                  |
| 81 | 
                      #' @param ... Not used.  | 
                  |
| 82 | 
                      #' @return ([`LinkComponent`]) \cr the resolved `LinkComponent` object  | 
                  |
| 83 | 
                      #'  | 
                  |
| 84 | 
                      #' @export  | 
                  |
| 85 | 
                      resolvePromise.PromiseLinkComponent <- function(object, model, ...) {
                     | 
                  |
| 86 | 25x | 
                      x <- object@fun(  | 
                  
| 87 | 25x | 
                      prior = object@parameters@parameters[[1]]@prior,  | 
                  
| 88 | 25x | 
                      model = model  | 
                  
| 89 | 
                      )  | 
                  |
| 90 | 25x | 
                      assert_that(  | 
                  
| 91 | 25x | 
                      is(x, "LinkComponent"),  | 
                  
| 92 | 25x | 
                      msg = "Resolved `PromiseLinkComponent` did not produce a `LinkComponent` object"  | 
                  
| 93 | 
                      )  | 
                  |
| 94 | 25x | 
                      assert_that(  | 
                  
| 95 | 25x | 
                      names(object) == names(x),  | 
                  
| 96 | 25x | 
                      msg = paste(  | 
                  
| 97 | 25x | 
                      "Resolved `PromiseLinkComponent` did not produce a `LinkComponent` object",  | 
                  
| 98 | 25x | 
                      "with the same key as the promise"  | 
                  
| 99 | 
                      )  | 
                  |
| 100 | 
                      )  | 
                  |
| 101 | 24x | 
                      x  | 
                  
| 102 | 
                      }  | 
                  
| 1 | 
                      #' @include StanModel.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # LongitudinalModel-class ----  | 
                  |
| 5 | ||
| 6 | 
                      #' `LongitudinalModel`  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' This class extends the general [`StanModel`] class to comprise the longitudinal  | 
                  |
| 9 | 
                      #' model specification.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @exportClass LongitudinalModel  | 
                  |
| 12 | 
                      .LongitudinalModel <- setClass(  | 
                  |
| 13 | 
                      Class = "LongitudinalModel",  | 
                  |
| 14 | 
                      contains = "StanModel"  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | 
                      # LongitudinalModel-constructors ----  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname LongitudinalModel-class  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @inheritParams stanmodel_arguments  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #' @export  | 
                  |
| 24 | 
                      LongitudinalModel <- function(  | 
                  |
| 25 | 
                      stan = StanModule(),  | 
                  |
| 26 | 
                      parameters = ParameterList(),  | 
                  |
| 27 | 
                      name = "<Unnamed>",  | 
                  |
| 28 | 
                      ...  | 
                  |
| 29 | 
                      ) {
                     | 
                  |
| 30 | 74x | 
                          base_stan <- read_stan("base/longitudinal.stan")
                     | 
                  
| 31 | ||
| 32 | 74x | 
                      stan_full <- decorated_render(  | 
                  
| 33 | 74x | 
                      .x = base_stan,  | 
                  
| 34 | 74x | 
                      stan = add_missing_stan_blocks(as.list(stan))  | 
                  
| 35 | 
                      )  | 
                  |
| 36 | ||
| 37 | 74x | 
                      .LongitudinalModel(  | 
                  
| 38 | 74x | 
                      StanModel(  | 
                  
| 39 | 74x | 
                      stan = StanModule(stan_full),  | 
                  
| 40 | 74x | 
                      parameters = parameters,  | 
                  
| 41 | 74x | 
                      name = name,  | 
                  
| 42 | 
                      ...  | 
                  |
| 43 | 
                      )  | 
                  |
| 44 | 
                      )  | 
                  |
| 45 | 
                      }  | 
                  |
| 46 | ||
| 47 | 
                      #' @export  | 
                  |
| 48 | 
                      as_print_string.LongitudinalModel <- function(object, ...) {
                     | 
                  |
| 49 | 5x | 
                      string <- sprintf(  | 
                  
| 50 | 5x | 
                      "\n%s Longitudinal Model with parameters:\n%s\n\n",  | 
                  
| 51 | 5x | 
                      object@name,  | 
                  
| 52 | 5x | 
                              paste("   ", as_print_string(object@parameters)) |> paste(collapse = "\n")
                     | 
                  
| 53 | 
                      )  | 
                  |
| 54 | 5x | 
                      return(string)  | 
                  
| 55 | 
                      }  | 
                  
| 1 | ||
| 2 | ||
| 3 | ||
| 4 | 
                      #' jmpost settings  | 
                  |
| 5 | 
                      #'  | 
                  |
| 6 | 
                      #' @description  | 
                  |
| 7 | 
                      #' Define settings that modify the behaviour of the `jmpost` package  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' Each of the following are the name of options that can be set via:  | 
                  |
| 10 | 
                      #' ```  | 
                  |
| 11 | 
                      #' options(<option_name> = <value>)  | 
                  |
| 12 | 
                      #' ```  | 
                  |
| 13 | 
                      #'  | 
                  |
| 14 | 
                      #' ## `jmpost.prior_shrinkage`  | 
                  |
| 15 | 
                      #'  | 
                  |
| 16 | 
                      #' Default = `0.5`  | 
                  |
| 17 | 
                      #'  | 
                  |
| 18 | 
                      #' By default all initial values are drawn as random sample from the respective prior  | 
                  |
| 19 | 
                      #' distribution with a shrinkage factor towards the mean. That is:  | 
                  |
| 20 | 
                      #' ```  | 
                  |
| 21 | 
                      #' initial_value = prior_mean * prior_shrinkage + (1 - prior_shrinkage) * prior_sample  | 
                  |
| 22 | 
                      #' ```  | 
                  |
| 23 | 
                      #' This setting controls the shrinkage factor. A value of 0 means no shrinkage (i.e.  | 
                  |
| 24 | 
                      #' pure random draw) whilst a value of 1 means the initial value is just the mean.  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' ## `jmpost.cache_dir`  | 
                  |
| 27 | 
                      #'  | 
                  |
| 28 | 
                      #' Default = `tempfile()`  | 
                  |
| 29 | 
                      #'  | 
                  |
| 30 | 
                      #' Directory to store compiled stan models in. If not set, a temporary directory is used for  | 
                  |
| 31 | 
                      #' the given R session. Can also be set via the environment variable `JMPOST_CACHE_DIR`.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #'  | 
                  |
| 35 | 
                      #' ## `jmpost.gauss_quad_n`  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' Default = 15  | 
                  |
| 38 | 
                      #'  | 
                  |
| 39 | 
                      #' In most cases the survival function of the joint model does not have a closed form  | 
                  |
| 40 | 
                      #' and as such it is calculated by integrating the hazard function. `jmpost` estimates this  | 
                  |
| 41 | 
                      #' via Gaussian Quadrature, in particular it uses [`statmod::gauss.quad`] with  | 
                  |
| 42 | 
                      #' `kind = "legendre"` to create the nodes and weights.  | 
                  |
| 43 | 
                      #'  | 
                  |
| 44 | 
                      #' This option specifies the `n` argument in the call to [`statmod::gauss.quad`]. In general  | 
                  |
| 45 | 
                      #' higher values of `n` lead to better accuracy of the approximation but at the cost of  | 
                  |
| 46 | 
                      #' increased computational time.  | 
                  |
| 47 | 
                      #'  | 
                  |
| 48 | 
                      #' @examples  | 
                  |
| 49 | 
                      #' \dontrun{
                     | 
                  |
| 50 | 
                      #' options(jmpost.prior_shrinkage = 0.5)  | 
                  |
| 51 | 
                      #' }  | 
                  |
| 52 | 
                      #' @name jmpost-settings  | 
                  |
| 53 | 
                      set_options <- function() {
                     | 
                  |
| 54 | ||
| 55 | ! | 
                          cache_dir <- Sys.getenv("JMPOST_CACHE_DIR")
                     | 
                  
| 56 | ||
| 57 | ! | 
                          if (cache_dir == "" || is.null(cache_dir)) {
                     | 
                  
| 58 | ! | 
                      cache_dir <- tempfile()  | 
                  
| 59 | 
                      }  | 
                  |
| 60 | ||
| 61 | ! | 
                      current_opts <- names(options())  | 
                  
| 62 | ! | 
                      jmpost_opts <- list(  | 
                  
| 63 | ! | 
                      jmpost.cache_dir = cache_dir,  | 
                  
| 64 | ! | 
                      jmpost.prior_shrinkage = 0.5,  | 
                  
| 65 | ! | 
                      jmpost.gauss_quad_n = 15  | 
                  
| 66 | 
                      )  | 
                  |
| 67 | ! | 
                          for (opt in names(jmpost_opts)) {
                     | 
                  
| 68 | ! | 
                              if (!opt %in% current_opts) {
                     | 
                  
| 69 | ! | 
                      options(jmpost_opts[opt])  | 
                  
| 70 | 
                      }  | 
                  |
| 71 | 
                      }  | 
                  |
| 72 | 
                      }  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include generics.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | ||
| 6 | 
                      #' @rdname Grid-Dev  | 
                  |
| 7 | 
                      .GridPopulation <- setClass(  | 
                  |
| 8 | 
                      "GridPopulation",  | 
                  |
| 9 | 
                      contains = "Grid",  | 
                  |
| 10 | 
                      slots = c(  | 
                  |
| 11 | 
                      "times" = "numeric_or_NULL"  | 
                  |
| 12 | 
                      )  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | ||
| 15 | 
                      #' @rdname Grid-Functions  | 
                  |
| 16 | 
                      #' @export  | 
                  |
| 17 | 
                      GridPopulation <- function(times = NULL) {
                     | 
                  |
| 18 | 3x | 
                      .GridPopulation(  | 
                  
| 19 | 3x | 
                      times = times  | 
                  
| 20 | 
                      )  | 
                  |
| 21 | 
                      }  | 
                  |
| 22 | ||
| 23 | 
                      #' @rdname Quant-Dev  | 
                  |
| 24 | 
                      #' @export  | 
                  |
| 25 | 
                      as.QuantityGenerator.GridPopulation <- function(object, data, ...) {
                     | 
                  |
| 26 | ||
| 27 | 4x | 
                      assert_class(data, "DataJoint")  | 
                  
| 28 | 4x | 
                      data_list <- as.list(data)  | 
                  
| 29 | 4x | 
                      validate_time_grid(object@times)  | 
                  
| 30 | ||
| 31 | 4x | 
                      n_times <- length(object@times)  | 
                  
| 32 | 4x | 
                      n_quant <- length(data_list$pop_study_index)  | 
                  
| 33 | ||
| 34 | 4x | 
                      QuantityGeneratorPopulation(  | 
                  
| 35 | 4x | 
                      times = rep(object@times, each = n_quant),  | 
                  
| 36 | 4x | 
                      arms = rep(names(data_list$arm_to_index)[data_list$pop_arm_index], n_times),  | 
                  
| 37 | 4x | 
                      studies = rep(names(data_list$study_to_index)[data_list$pop_study_index], n_times)  | 
                  
| 38 | 
                      )  | 
                  |
| 39 | 
                      }  | 
                  |
| 40 | ||
| 41 | 
                      #' @rdname Quant-Dev  | 
                  |
| 42 | 
                      #' @export  | 
                  |
| 43 | 
                      as.QuantityCollapser.GridPopulation <- function(object, data, ...) {
                     | 
                  |
| 44 | 2x | 
                      assert_class(data, "DataJoint")  | 
                  
| 45 | 2x | 
                      data_list <- as.list(data)  | 
                  
| 46 | 2x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 47 | 2x | 
                      QuantityCollapser(  | 
                  
| 48 | 2x | 
                      times = generator@times,  | 
                  
| 49 | 2x | 
                      groups = sprintf(  | 
                  
| 50 | 2x | 
                      "arm=%s; study=%s",  | 
                  
| 51 | 2x | 
                      generator@arms,  | 
                  
| 52 | 2x | 
                      generator@studies  | 
                  
| 53 | 
                      ),  | 
                  |
| 54 | 2x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 55 | 
                      )  | 
                  |
| 56 | 
                      }  | 
                  |
| 57 | ||
| 58 | ||
| 59 | 
                      #' @export  | 
                  |
| 60 | 
                      as.list.GridPopulation <- function(x, data, ...) {
                     | 
                  |
| 61 | ! | 
                          stop("`as.list()` is not implemented for `GridPopulation` objects")
                     | 
                  
| 62 | 
                      }  | 
                  |
| 63 | ||
| 64 | ||
| 65 | 
                      #' @rdname coalesceGridTime  | 
                  |
| 66 | 
                      #' @export  | 
                  |
| 67 | 
                      coalesceGridTime.GridPopulation <- function(object, times, ...) {
                     | 
                  |
| 68 | 2x | 
                          if (is.null(object@times)) {
                     | 
                  
| 69 | ! | 
                      object <- GridPopulation(  | 
                  
| 70 | ! | 
                      times = times  | 
                  
| 71 | 
                      )  | 
                  |
| 72 | 
                      }  | 
                  |
| 73 | 2x | 
                      object  | 
                  
| 74 | 
                      }  | 
                  
| 1 | 
                      #' @include SurvivalModel.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # SurvivalExponential-class ----  | 
                  |
| 5 | ||
| 6 | 
                      #' `SurvivalExponential`  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' This class extends the general [`SurvivalModel`] class for using the  | 
                  |
| 9 | 
                      #' exponential survival model.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @exportClass SurvivalExponential  | 
                  |
| 12 | 
                      .SurvivalExponential <- setClass(  | 
                  |
| 13 | 
                      Class = "SurvivalExponential",  | 
                  |
| 14 | 
                      contains = "SurvivalModel"  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | 
                      # SurvivalExponential-constructors ----  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname SurvivalExponential-class  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @param lambda (`Prior`)\cr for the exponential rate `lambda`.  | 
                  |
| 22 | 
                      #' @param beta (`Prior`)\cr for covariates coefficients `beta`.  | 
                  |
| 23 | 
                      #'  | 
                  |
| 24 | 
                      #' @export  | 
                  |
| 25 | 
                      SurvivalExponential <- function(  | 
                  |
| 26 | 
                      lambda = prior_gamma(2, 5),  | 
                  |
| 27 | 
                      beta = prior_normal(0, 2)  | 
                  |
| 28 | 
                      ) {
                     | 
                  |
| 29 | 13x | 
                      .SurvivalExponential(  | 
                  
| 30 | 13x | 
                      SurvivalModel(  | 
                  
| 31 | 13x | 
                      name = "Exponential",  | 
                  
| 32 | 13x | 
                                  stan = StanModule("sm-exponential/model.stan"),
                     | 
                  
| 33 | 13x | 
                      parameters = ParameterList(  | 
                  
| 34 | 13x | 
                      Parameter(name = "sm_exp_lambda", prior = lambda, size = 1),  | 
                  
| 35 | 13x | 
                      Parameter(name = "beta_os_cov", prior = beta, size = "p_os_cov_design")  | 
                  
| 36 | 
                      )  | 
                  |
| 37 | 
                      )  | 
                  |
| 38 | 
                      )  | 
                  |
| 39 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Parameter.R  | 
                  |
| 3 | 
                      #' @include Prior.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | 
                      #' ParameterList-Shared  | 
                  |
| 8 | 
                      #' @param object (`ParameterList`) \cr A List of [`Parameter`] Objects.  | 
                  |
| 9 | 
                      #' @param x (`ParameterList`) \cr A List of [`Parameter`] Objects.  | 
                  |
| 10 | 
                      #' @param ... Not Used.  | 
                  |
| 11 | 
                      #' @keywords internal  | 
                  |
| 12 | 
                      #' @name ParameterList-Shared  | 
                  |
| 13 | 
                      NULL  | 
                  |
| 14 | ||
| 15 | ||
| 16 | 
                      # ParameterList-class ----  | 
                  |
| 17 | ||
| 18 | 
                      #' `ParameterList`  | 
                  |
| 19 | 
                      #'  | 
                  |
| 20 | 
                      #' This class extends the general [`list`] type for containing [`Parameter`]  | 
                  |
| 21 | 
                      #' specifications.  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #'  | 
                  |
| 24 | ||
| 25 | 
                      #' @slot parameters (`list`) \cr a list of [`Parameter`] objects  | 
                  |
| 26 | 
                      #' @family ParameterList  | 
                  |
| 27 | 
                      #' @export ParameterList  | 
                  |
| 28 | 
                      #' @exportClass ParameterList  | 
                  |
| 29 | 
                      .ParameterList <- setClass(  | 
                  |
| 30 | 
                      Class = "ParameterList",  | 
                  |
| 31 | 
                      slots = c(  | 
                  |
| 32 | 
                      parameters = "list"  | 
                  |
| 33 | 
                      )  | 
                  |
| 34 | 
                      )  | 
                  |
| 35 | 
                      #' @param ... (`Parameter`)\cr which parameter specifications to include.  | 
                  |
| 36 | 
                      #' @rdname ParameterList-class  | 
                  |
| 37 | 
                      ParameterList <- function(...) {
                     | 
                  |
| 38 | 211x | 
                      .ParameterList(parameters = list(...))  | 
                  
| 39 | 
                      }  | 
                  |
| 40 | ||
| 41 | 
                      # ParameterList-validity ----  | 
                  |
| 42 | ||
| 43 | 
                      setValidity(  | 
                  |
| 44 | 
                      Class = "ParameterList",  | 
                  |
| 45 | 
                          method = function(object) {
                     | 
                  |
| 46 | 
                      is_parameters <- vapply(object@parameters, function(x) is(x, "Parameter"), logical(1))  | 
                  |
| 47 | 
                              if (!all(is_parameters)) {
                     | 
                  |
| 48 | 
                                  return("all elements must be of class 'Parameter'")
                     | 
                  |
| 49 | 
                      }  | 
                  |
| 50 | 
                      return(TRUE)  | 
                  |
| 51 | 
                      }  | 
                  |
| 52 | 
                      )  | 
                  |
| 53 | ||
| 54 | ||
| 55 | ||
| 56 | 
                      # as.StanModule-ParameterList ----  | 
                  |
| 57 | ||
| 58 | 
                      #' `ParameterList` -> `StanModule`  | 
                  |
| 59 | 
                      #'  | 
                  |
| 60 | 
                      #' Converts a [`ParameterList`] object to a [`StanModule`] object  | 
                  |
| 61 | 
                      #'  | 
                  |
| 62 | 
                      #' @inheritParams ParameterList-Shared  | 
                  |
| 63 | 
                      #'  | 
                  |
| 64 | 
                      #' @family ParameterList  | 
                  |
| 65 | 
                      #' @family as.StanModule  | 
                  |
| 66 | 
                      #' @export  | 
                  |
| 67 | 
                      as.StanModule.ParameterList <- function(object, ...) {
                     | 
                  |
| 68 | 71x | 
                      stan_modules <- lapply(  | 
                  
| 69 | 71x | 
                      object@parameters,  | 
                  
| 70 | 71x | 
                      as.StanModule  | 
                  
| 71 | 
                      )  | 
                  |
| 72 | 71x | 
                      assert_that(  | 
                  
| 73 | 71x | 
                      all(vapply(stan_modules, inherits, logical(1), "StanModule"))  | 
                  
| 74 | 
                      )  | 
                  |
| 75 | 71x | 
                      Reduce(merge, stan_modules)  | 
                  
| 76 | 
                      }  | 
                  |
| 77 | ||
| 78 | ||
| 79 | ||
| 80 | 
                      #' `ParameterList` -> `list`  | 
                  |
| 81 | 
                      #'  | 
                  |
| 82 | 
                      #' Converts a ParameterList object to a list of parameter data values  | 
                  |
| 83 | 
                      #' for a Stan model.  | 
                  |
| 84 | 
                      #'  | 
                  |
| 85 | 
                      #' @inheritParams ParameterList-Shared  | 
                  |
| 86 | 
                      #'  | 
                  |
| 87 | 
                      #' @family as_stan_list  | 
                  |
| 88 | 
                      #' @family ParameterList  | 
                  |
| 89 | 
                      #' @export  | 
                  |
| 90 | 
                      as_stan_list.ParameterList <- function(object, ...) {
                     | 
                  |
| 91 | 49x | 
                      stan_lists <- lapply(  | 
                  
| 92 | 49x | 
                      object@parameters,  | 
                  
| 93 | 49x | 
                      as_stan_list  | 
                  
| 94 | 
                      )  | 
                  |
| 95 | 49x | 
                      assert_that(  | 
                  
| 96 | 49x | 
                      all(vapply(stan_lists, is.list, logical(1)))  | 
                  
| 97 | 
                      )  | 
                  |
| 98 | 49x | 
                      Reduce(append, stan_lists)  | 
                  
| 99 | 
                      }  | 
                  |
| 100 | ||
| 101 | ||
| 102 | 
                      # merge-ParameterList,ParameterList ----  | 
                  |
| 103 | ||
| 104 | 
                      #' @rdname merge  | 
                  |
| 105 | 
                      setMethod(  | 
                  |
| 106 | 
                      f = "merge",  | 
                  |
| 107 | 
                      signature = c(x = "ParameterList", y = "ParameterList"),  | 
                  |
| 108 | 
                          definition = function(x, y) {
                     | 
                  |
| 109 | 43x | 
                      parameters <- append(x@parameters, y@parameters)  | 
                  
| 110 | 43x | 
                      do.call(ParameterList, parameters)  | 
                  
| 111 | 
                      }  | 
                  |
| 112 | 
                      )  | 
                  |
| 113 | ||
| 114 | 
                      # as.list-ParameterList ----  | 
                  |
| 115 | ||
| 116 | 
                      #' `ParameterList` -> `list`  | 
                  |
| 117 | 
                      #' @description  | 
                  |
| 118 | 
                      #' Returns a named list where each element of the list corresponds  | 
                  |
| 119 | 
                      #' to a Stan modelling block e.g. `data`, `model`, etc.  | 
                  |
| 120 | 
                      #' @inheritParams ParameterList-Shared  | 
                  |
| 121 | 
                      #' @family ParameterList  | 
                  |
| 122 | 
                      #' @export  | 
                  |
| 123 | 
                      as.list.ParameterList <- function(x, ...) {
                     | 
                  |
| 124 | 70x | 
                      as.list(as.StanModule(x))  | 
                  
| 125 | 
                      }  | 
                  |
| 126 | ||
| 127 | ||
| 128 | ||
| 129 | ||
| 130 | 
                      #' Parameter-List Getter Functions  | 
                  |
| 131 | 
                      #' @description  | 
                  |
| 132 | 
                      #' Getter functions for the slots of a [`ParameterList`] object  | 
                  |
| 133 | 
                      #' @inheritParams ParameterList-Shared  | 
                  |
| 134 | 
                      #' @family ParameterList  | 
                  |
| 135 | 
                      #' @param n_chains (`integer`) \cr the number of chains.  | 
                  |
| 136 | 
                      #' @name ParameterList-Getter-Methods  | 
                  |
| 137 | 
                      NULL  | 
                  |
| 138 | ||
| 139 | ||
| 140 | 
                      #' @describeIn ParameterList-Getter-Methods The parameter-list's parameter names  | 
                  |
| 141 | 
                      #' @export  | 
                  |
| 142 | 
                      names.ParameterList <- function(x) {
                     | 
                  |
| 143 | 89x | 
                      vapply(x@parameters, names, character(1))  | 
                  
| 144 | 
                      }  | 
                  |
| 145 | ||
| 146 | ||
| 147 | 
                      #' @describeIn ParameterList-Getter-Methods The parameter-list's parameter initial values  | 
                  |
| 148 | 
                      #' @export  | 
                  |
| 149 | 
                      initialValues.ParameterList <- function(object, n_chains, ...) {
                     | 
                  |
| 150 | 
                      # Generate initial values as a list of lists. This is to ensure it is in the required  | 
                  |
| 151 | 
                      # format as specified by cmdstanr see the `init` argument of  | 
                  |
| 152 | 
                          # `help("model-method-sample", "cmdstanr")` for more details
                     | 
                  |
| 153 | 45x | 
                      lapply(  | 
                  
| 154 | 45x | 
                      seq_len(n_chains),  | 
                  
| 155 | 45x | 
                              \(i) {
                     | 
                  
| 156 | 951x | 
                      vals <- lapply(object@parameters, initialValues)  | 
                  
| 157 | 936x | 
                      name <- vapply(object@parameters, names, character(1))  | 
                  
| 158 | 936x | 
                      names(vals) <- name  | 
                  
| 159 | 936x | 
                      vals  | 
                  
| 160 | 
                      }  | 
                  |
| 161 | 
                      )  | 
                  |
| 162 | 
                      }  | 
                  |
| 163 | ||
| 164 | ||
| 165 | 
                      #' @describeIn ParameterList-Getter-Methods The parameter-list's parameter dimensionality  | 
                  |
| 166 | 
                      #' @export  | 
                  |
| 167 | 
                      size.ParameterList <- function(object) {
                     | 
                  |
| 168 | 18x | 
                      x <- lapply(object@parameters, size)  | 
                  
| 169 | 18x | 
                      names(x) <- names(object)  | 
                  
| 170 | 18x | 
                      return(x)  | 
                  
| 171 | 
                      }  | 
                  |
| 172 | ||
| 173 | ||
| 174 | 
                      #' `ParameterList` -> Printable `Character`  | 
                  |
| 175 | 
                      #'  | 
                  |
| 176 | 
                      #' Converts [`ParameterList`] object into a printable string.  | 
                  |
| 177 | 
                      #' @inheritParams ParameterList-Shared  | 
                  |
| 178 | 
                      #' @family ParameterList  | 
                  |
| 179 | 
                      #' @keywords internal  | 
                  |
| 180 | 
                      #' @export  | 
                  |
| 181 | 
                      as_print_string.ParameterList <- function(object, ...) {
                     | 
                  |
| 182 | 13x | 
                      x <- vapply(object@parameters, as.character, character(1))  | 
                  
| 183 | 13x | 
                          if (length(x) == 0) {
                     | 
                  
| 184 | ! | 
                      x <- "<No Parameters>"  | 
                  
| 185 | 
                      }  | 
                  |
| 186 | 13x | 
                      return(x)  | 
                  
| 187 | 
                      }  | 
                  |
| 188 | ||
| 189 | ||
| 190 | ||
| 191 | 
                      #' @rdname show-object  | 
                  |
| 192 | 
                      #' @export  | 
                  |
| 193 | 
                      setMethod(  | 
                  |
| 194 | 
                      f = "show",  | 
                  |
| 195 | 
                      signature = "ParameterList",  | 
                  |
| 196 | 
                          definition = function(object) {
                     | 
                  |
| 197 | 1x | 
                      chrs <- as_print_string(object)  | 
                  
| 198 | 1x | 
                              string <- paste("   ", chrs) |> paste(collapse = "\n")
                     | 
                  
| 199 | 1x | 
                              x <- sprintf("\nParameterList Object:\n%s\n\n", string)
                     | 
                  
| 200 | 1x | 
                      cat(x)  | 
                  
| 201 | 1x | 
                      return(object)  | 
                  
| 202 | 
                      }  | 
                  |
| 203 | 
                      )  | 
                  
| 1 | ||
| 2 | ||
| 3 | 
                      #' @include SimLongitudinal.R  | 
                  |
| 4 | 
                      #' @include generics.R  | 
                  |
| 5 | 
                      NULL  | 
                  |
| 6 | ||
| 7 | 
                      #' Simulate Longitudinal Data from a GSF Model  | 
                  |
| 8 | 
                      #'  | 
                  |
| 9 | 
                      #' @param times (`numeric`)\cr the times to generate observations at.  | 
                  |
| 10 | 
                      #' @param sigma (`number`)\cr the variance of the longitudinal values.  | 
                  |
| 11 | 
                      #' @param mu_s (`numeric`)\cr the mean shrinkage rates.  | 
                  |
| 12 | 
                      #' @param mu_g (`numeric`)\cr the mean growth rates.  | 
                  |
| 13 | 
                      #' @param mu_b (`numeric`)\cr the mean baseline values.  | 
                  |
| 14 | 
                      #' @param mu_phi (`numeric`)\cr the mean proportion of cells affected by the treatment  | 
                  |
| 15 | 
                      #' @param omega_b (`number`)\cr the baseline value standard deviation.  | 
                  |
| 16 | 
                      #' @param omega_s (`number`)\cr the shrinkage rate standard deviation.  | 
                  |
| 17 | 
                      #' @param omega_g (`number`)\cr the growth rate standard deviation.  | 
                  |
| 18 | 
                      #' @param omega_phi (`number`)\cr for the standard deviation of the proportion of cells  | 
                  |
| 19 | 
                      #' affected by the treatment `omega_phi`.  | 
                  |
| 20 | 
                      #' @param link_dsld (`number`)\cr the link coefficient for the derivative contribution.  | 
                  |
| 21 | 
                      #' @param link_ttg (`number`)\cr the link coefficient for the time-to-growth contribution.  | 
                  |
| 22 | 
                      #' @param link_identity (`number`)\cr the link coefficient for the SLD Identity contribution.  | 
                  |
| 23 | 
                      #' @param link_growth (`number`)\cr the link coefficient for the growth parameter contribution.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @slot sigma (`numeric`)\cr See arguments.  | 
                  |
| 26 | 
                      #' @slot mu_s (`numeric`)\cr See arguments.  | 
                  |
| 27 | 
                      #' @slot mu_g (`numeric`)\cr See arguments.  | 
                  |
| 28 | 
                      #' @slot mu_b (`numeric`)\cr See arguments.  | 
                  |
| 29 | 
                      #' @slot mu_phi (`numeric`)\cr See arguments.  | 
                  |
| 30 | 
                      #' @slot omega_b (`numeric`)\cr See arguments.  | 
                  |
| 31 | 
                      #' @slot omega_s (`numeric`)\cr See arguments.  | 
                  |
| 32 | 
                      #' @slot omega_g (`numeric`)\cr See arguments.  | 
                  |
| 33 | 
                      #' @slot omega_phi (`numeric`)\cr See arguments.  | 
                  |
| 34 | 
                      #' @slot link_dsld (`numeric`)\cr See arguments.  | 
                  |
| 35 | 
                      #' @slot link_ttg (`numeric`)\cr See arguments.  | 
                  |
| 36 | 
                      #' @slot link_identity (`numeric`)\cr See arguments.  | 
                  |
| 37 | 
                      #' @slot link_growth (`numeric`)\cr See arguments.  | 
                  |
| 38 | 
                      #' @family SimLongitudinal  | 
                  |
| 39 | 
                      #' @name SimLongitudinalGSF-class  | 
                  |
| 40 | 
                      #' @exportClass SimLongitudinalGSF  | 
                  |
| 41 | 
                      .SimLongitudinalGSF <- setClass(  | 
                  |
| 42 | 
                      "SimLongitudinalGSF",  | 
                  |
| 43 | 
                      contains = "SimLongitudinal",  | 
                  |
| 44 | 
                      slots = c(  | 
                  |
| 45 | 
                      sigma = "numeric",  | 
                  |
| 46 | 
                      mu_s = "numeric",  | 
                  |
| 47 | 
                      mu_g = "numeric",  | 
                  |
| 48 | 
                      mu_b = "numeric",  | 
                  |
| 49 | 
                      mu_phi = "numeric",  | 
                  |
| 50 | 
                      omega_b = "numeric",  | 
                  |
| 51 | 
                      omega_s = "numeric",  | 
                  |
| 52 | 
                      omega_g = "numeric",  | 
                  |
| 53 | 
                      omega_phi = "numeric",  | 
                  |
| 54 | 
                      link_dsld = "numeric",  | 
                  |
| 55 | 
                      link_ttg = "numeric",  | 
                  |
| 56 | 
                      link_identity = "numeric",  | 
                  |
| 57 | 
                      link_growth = "numeric"  | 
                  |
| 58 | 
                      )  | 
                  |
| 59 | 
                      )  | 
                  |
| 60 | ||
| 61 | 
                      #' @rdname SimLongitudinalGSF-class  | 
                  |
| 62 | 
                      #' @export  | 
                  |
| 63 | 
                      SimLongitudinalGSF <- function(  | 
                  |
| 64 | 
                      times = c(-100, -50, 0, 50, 100, 150, 250, 350, 450, 550) / 365,  | 
                  |
| 65 | 
                      sigma = 0.01,  | 
                  |
| 66 | 
                      mu_s = log(c(0.6, 0.4)),  | 
                  |
| 67 | 
                      mu_g = log(c(0.25, 0.35)),  | 
                  |
| 68 | 
                      mu_b = log(60),  | 
                  |
| 69 | 
                      mu_phi = qlogis(c(0.4, 0.6)),  | 
                  |
| 70 | 
                      omega_b = 0.2,  | 
                  |
| 71 | 
                      omega_s = 0.2,  | 
                  |
| 72 | 
                      omega_g = 0.2,  | 
                  |
| 73 | 
                      omega_phi = 0.2,  | 
                  |
| 74 | 
                      link_dsld = 0,  | 
                  |
| 75 | 
                      link_ttg = 0,  | 
                  |
| 76 | 
                      link_identity = 0,  | 
                  |
| 77 | 
                      link_growth = 0  | 
                  |
| 78 | 
                      ) {
                     | 
                  |
| 79 | 8x | 
                      .SimLongitudinalGSF(  | 
                  
| 80 | 8x | 
                      times = times,  | 
                  
| 81 | 8x | 
                      sigma = sigma,  | 
                  
| 82 | 8x | 
                      mu_s = mu_s,  | 
                  
| 83 | 8x | 
                      mu_g = mu_g,  | 
                  
| 84 | 8x | 
                      mu_b = mu_b,  | 
                  
| 85 | 8x | 
                      mu_phi = mu_phi,  | 
                  
| 86 | 8x | 
                      omega_b = omega_b,  | 
                  
| 87 | 8x | 
                      omega_s = omega_s,  | 
                  
| 88 | 8x | 
                      omega_g = omega_g,  | 
                  
| 89 | 8x | 
                      omega_phi = omega_phi,  | 
                  
| 90 | 8x | 
                      link_dsld = link_dsld,  | 
                  
| 91 | 8x | 
                      link_ttg = link_ttg,  | 
                  
| 92 | 8x | 
                      link_identity = link_identity,  | 
                  
| 93 | 8x | 
                      link_growth = link_growth  | 
                  
| 94 | 
                      )  | 
                  |
| 95 | 
                      }  | 
                  |
| 96 | ||
| 97 | ||
| 98 | 
                      setValidity(  | 
                  |
| 99 | 
                      "SimLongitudinalGSF",  | 
                  |
| 100 | 
                          function(object) {
                     | 
                  |
| 101 | 
                      par_lengths <- c(  | 
                  |
| 102 | 
                      length(object@mu_s),  | 
                  |
| 103 | 
                      length(object@mu_g),  | 
                  |
| 104 | 
                      length(object@mu_phi)  | 
                  |
| 105 | 
                      )  | 
                  |
| 106 | 
                              if (length(unique(par_lengths)) != 1) {
                     | 
                  |
| 107 | 
                                  return("The parameters `mu_s`, `mu_g` and `mu_phi` must have the same length.")
                     | 
                  |
| 108 | 
                      }  | 
                  |
| 109 | ||
| 110 | 
                      len_1_pars <- c(  | 
                  |
| 111 | 
                      "sigma", "omega_b", "omega_s", "omega_g", "omega_phi",  | 
                  |
| 112 | 
                      "link_dsld", "link_ttg", "link_identity", "link_growth"  | 
                  |
| 113 | 
                      )  | 
                  |
| 114 | 
                              for (par in len_1_pars) {
                     | 
                  |
| 115 | 
                                  if (length(slot(object, par)) != 1) {
                     | 
                  |
| 116 | 
                                      return(sprintf("The `%s` parameter must be a length 1 numeric.", par))
                     | 
                  |
| 117 | 
                      }  | 
                  |
| 118 | 
                      }  | 
                  |
| 119 | ||
| 120 | 
                      return(TRUE)  | 
                  |
| 121 | 
                      }  | 
                  |
| 122 | 
                      )  | 
                  |
| 123 | ||
| 124 | 
                      #' @rdname as_print_string  | 
                  |
| 125 | 
                      as_print_string.SimLongitudinalGSF <- function(object) {
                     | 
                  |
| 126 | 1x | 
                          return("SimLongitudinalGSF")
                     | 
                  
| 127 | 
                      }  | 
                  |
| 128 | ||
| 129 | 
                      #' @rdname sampleObservations  | 
                  |
| 130 | 
                      #' @export  | 
                  |
| 131 | 
                      sampleObservations.SimLongitudinalGSF <- function(object, times_df) {
                     | 
                  |
| 132 | 13x | 
                      times_df |>  | 
                  
| 133 | 13x | 
                      dplyr::mutate(mu_sld = gsf_sld(.data$time, .data$psi_b, .data$psi_s, .data$psi_g, .data$psi_phi)) |>  | 
                  
| 134 | 13x | 
                      dplyr::mutate(dsld = gsf_dsld(.data$time, .data$psi_b, .data$psi_s, .data$psi_g, .data$psi_phi)) |>  | 
                  
| 135 | 13x | 
                      dplyr::mutate(ttg = gsf_ttg(.data$time, .data$psi_b, .data$psi_s, .data$psi_g, .data$psi_phi)) |>  | 
                  
| 136 | 13x | 
                      dplyr::mutate(sld = stats::rnorm(dplyr::n(), .data$mu_sld, .data$mu_sld * object@sigma)) |>  | 
                  
| 137 | 13x | 
                      dplyr::mutate(  | 
                  
| 138 | 13x | 
                      log_haz_link =  | 
                  
| 139 | 13x | 
                      (object@link_dsld * .data$dsld) +  | 
                  
| 140 | 13x | 
                      (object@link_ttg * .data$ttg) +  | 
                  
| 141 | 13x | 
                      (object@link_identity * .data$mu_sld) +  | 
                  
| 142 | 13x | 
                      (object@link_growth * log(.data$psi_g))  | 
                  
| 143 | 
                      )  | 
                  |
| 144 | 
                      }  | 
                  |
| 145 | ||
| 146 | ||
| 147 | 
                      #' @rdname sampleSubjects  | 
                  |
| 148 | 
                      #' @export  | 
                  |
| 149 | 
                      sampleSubjects.SimLongitudinalGSF <- function(object, subjects_df) {
                     | 
                  |
| 150 | 7x | 
                      assert_that(  | 
                  
| 151 | 7x | 
                      is.factor(subjects_df$study),  | 
                  
| 152 | 7x | 
                      is.factor(subjects_df$arm),  | 
                  
| 153 | 7x | 
                      length(levels(subjects_df$study)) == length(object@mu_b),  | 
                  
| 154 | 7x | 
                      length(levels(subjects_df$arm)) == length(object@mu_s),  | 
                  
| 155 | 7x | 
                      length(levels(subjects_df$arm)) == length(object@mu_g),  | 
                  
| 156 | 7x | 
                      length(levels(subjects_df$arm)) == length(object@mu_phi)  | 
                  
| 157 | 
                      )  | 
                  |
| 158 | ||
| 159 | 7x | 
                      res <- subjects_df |>  | 
                  
| 160 | 7x | 
                      dplyr::distinct(.data$subject, .data$arm, .data$study) |>  | 
                  
| 161 | 7x | 
                      dplyr::mutate(study_idx = as.numeric(.data$study)) |>  | 
                  
| 162 | 7x | 
                      dplyr::mutate(arm_idx = as.numeric(.data$arm)) |>  | 
                  
| 163 | 7x | 
                      dplyr::mutate(psi_b = stats::rlnorm(dplyr::n(), object@mu_b[.data$study_idx], object@omega_b)) |>  | 
                  
| 164 | 7x | 
                      dplyr::mutate(psi_s = stats::rlnorm(dplyr::n(), object@mu_s[.data$arm_idx], object@omega_s)) |>  | 
                  
| 165 | 7x | 
                      dplyr::mutate(psi_g = stats::rlnorm(dplyr::n(), object@mu_g[.data$arm_idx], object@omega_g)) |>  | 
                  
| 166 | 7x | 
                      dplyr::mutate(psi_phi_logit = stats::rnorm(  | 
                  
| 167 | 7x | 
                      dplyr::n(),  | 
                  
| 168 | 7x | 
                      object@mu_phi[.data$arm_idx],  | 
                  
| 169 | 7x | 
                      object@omega_phi  | 
                  
| 170 | 
                      )) |>  | 
                  |
| 171 | 7x | 
                      dplyr::mutate(psi_phi = stats::plogis(.data$psi_phi_logit))  | 
                  
| 172 | ||
| 173 | 7x | 
                          res[, c("subject", "arm", "study", "psi_b", "psi_s", "psi_g", "psi_phi")]
                     | 
                  
| 174 | 
                      }  | 
                  |
| 175 | ||
| 176 | ||
| 177 | ||
| 178 | ||
| 179 | 
                      ## sim_lm_gsf ----  | 
                  |
| 180 | ||
| 181 | 
                      #' Generalized Stein-Fojo Functionals  | 
                  |
| 182 | 
                      #'  | 
                  |
| 183 | 
                      #' @param time (`numeric`)\cr time grid.  | 
                  |
| 184 | 
                      #' @param b (`number`)\cr baseline.  | 
                  |
| 185 | 
                      #' @param s (`number`)\cr shrinkage.  | 
                  |
| 186 | 
                      #' @param g (`number`)\cr growth.  | 
                  |
| 187 | 
                      #' @param phi (`number`)\cr shrinkage proportion.  | 
                  |
| 188 | 
                      #'  | 
                  |
| 189 | 
                      #' @returns The function results.  | 
                  |
| 190 | 
                      #'  | 
                  |
| 191 | 
                      #' @keywords internal  | 
                  |
| 192 | 
                      gsf_sld <- function(time, b, s, g, phi) {
                     | 
                  |
| 193 | 18x | 
                      phi <- dplyr::if_else(time >= 0, phi, 0)  | 
                  
| 194 | 18x | 
                      b * (phi * exp(-s * time) + (1 - phi) * exp(g * time))  | 
                  
| 195 | 
                      }  | 
                  |
| 196 | ||
| 197 | ||
| 198 | 
                      #' @rdname gsf_sld  | 
                  |
| 199 | 
                      gsf_ttg <- function(time, b, s, g, phi) {
                     | 
                  |
| 200 | 16x | 
                      t1 <- (log(s * phi / (g * (1 - phi))) / (g + s))  | 
                  
| 201 | 16x | 
                      t1[t1 <= 0] <- 0  | 
                  
| 202 | 16x | 
                      return(t1)  | 
                  
| 203 | 
                      }  | 
                  |
| 204 | ||
| 205 | ||
| 206 | 
                      #' @rdname gsf_sld  | 
                  |
| 207 | 
                      gsf_dsld <- function(time, b, s, g, phi) {
                     | 
                  |
| 208 | 16x | 
                      phi <- dplyr::if_else(time >= 0, phi, 0)  | 
                  
| 209 | 16x | 
                      t1 <- (1 - phi) * g * exp(g * time)  | 
                  
| 210 | 16x | 
                      t2 <- phi * s * exp(-s * time)  | 
                  
| 211 | 16x | 
                      return(b * (t1 - t2))  | 
                  
| 212 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include SimLongitudinal.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | 
                      #' Simulate Longitudinal Data from a Stein-Fojo Model  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @param times (`numeric`)\cr the times to generate observations at.  | 
                  |
| 9 | 
                      #' @param sigma (`number`)\cr the variance of the longitudinal values.  | 
                  |
| 10 | 
                      #' @param mu_s (`numeric`)\cr the mean shrinkage rates for the two treatment arms.  | 
                  |
| 11 | 
                      #' @param mu_g (`numeric`)\cr the mean growth rates for the two treatment arms.  | 
                  |
| 12 | 
                      #' @param mu_b (`numeric`)\cr the mean baseline values for the two treatment arms.  | 
                  |
| 13 | 
                      #' @param omega_b (`number`)\cr the baseline value standard deviation.  | 
                  |
| 14 | 
                      #' @param omega_s (`number`)\cr the shrinkage rate standard deviation.  | 
                  |
| 15 | 
                      #' @param omega_g (`number`)\cr the growth rate standard deviation.  | 
                  |
| 16 | 
                      #' @param link_dsld (`number`)\cr the link coefficient for the derivative contribution.  | 
                  |
| 17 | 
                      #' @param link_ttg (`number`)\cr the link coefficient for the time-to-growth contribution.  | 
                  |
| 18 | 
                      #' @param link_identity (`number`)\cr the link coefficient for the SLD Identity contribution.  | 
                  |
| 19 | 
                      #' @param link_growth (`number`)\cr the link coefficient for the growth parameter contribution.  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @slot sigma (`numeric`)\cr See arguments.  | 
                  |
| 22 | 
                      #' @slot mu_s (`numeric`)\cr See arguments.  | 
                  |
| 23 | 
                      #' @slot mu_g (`numeric`)\cr See arguments.  | 
                  |
| 24 | 
                      #' @slot mu_b (`numeric`)\cr See arguments.  | 
                  |
| 25 | 
                      #' @slot omega_b (`numeric`)\cr See arguments.  | 
                  |
| 26 | 
                      #' @slot omega_s (`numeric`)\cr See arguments.  | 
                  |
| 27 | 
                      #' @slot omega_g (`numeric`)\cr See arguments.  | 
                  |
| 28 | 
                      #' @slot link_dsld (`numeric`)\cr See arguments.  | 
                  |
| 29 | 
                      #' @slot link_ttg (`numeric`)\cr See arguments.  | 
                  |
| 30 | 
                      #' @slot link_identity (`numeric`)\cr See arguments.  | 
                  |
| 31 | 
                      #' @slot link_growth (`numeric`)\cr See arguments.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #' @family SimLongitudinal  | 
                  |
| 34 | 
                      #' @name SimLongitudinalSteinFojo-class  | 
                  |
| 35 | 
                      #' @exportClass SimLongitudinalSteinFojo  | 
                  |
| 36 | 
                      .SimLongitudinalSteinFojo <- setClass(  | 
                  |
| 37 | 
                      "SimLongitudinalSteinFojo",  | 
                  |
| 38 | 
                      contains = "SimLongitudinal",  | 
                  |
| 39 | 
                      slots = c(  | 
                  |
| 40 | 
                      sigma = "numeric",  | 
                  |
| 41 | 
                      mu_s = "numeric",  | 
                  |
| 42 | 
                      mu_g = "numeric",  | 
                  |
| 43 | 
                      mu_b = "numeric",  | 
                  |
| 44 | 
                      omega_b = "numeric",  | 
                  |
| 45 | 
                      omega_s = "numeric",  | 
                  |
| 46 | 
                      omega_g = "numeric",  | 
                  |
| 47 | 
                      link_dsld = "numeric",  | 
                  |
| 48 | 
                      link_ttg = "numeric",  | 
                  |
| 49 | 
                      link_identity = "numeric",  | 
                  |
| 50 | 
                      link_growth = "numeric"  | 
                  |
| 51 | 
                      )  | 
                  |
| 52 | 
                      )  | 
                  |
| 53 | ||
| 54 | 
                      #' @rdname SimLongitudinalSteinFojo-class  | 
                  |
| 55 | 
                      #' @export  | 
                  |
| 56 | 
                      SimLongitudinalSteinFojo <- function(  | 
                  |
| 57 | 
                      times = c(-100, -50, 0, 50, 100, 150, 250, 350, 450, 550) / 365,  | 
                  |
| 58 | 
                      sigma = 0.01,  | 
                  |
| 59 | 
                      mu_s = log(c(0.6, 0.4)),  | 
                  |
| 60 | 
                      mu_g = log(c(0.25, 0.35)),  | 
                  |
| 61 | 
                      mu_b = log(60),  | 
                  |
| 62 | 
                      omega_b = 0.2,  | 
                  |
| 63 | 
                      omega_s = 0.2,  | 
                  |
| 64 | 
                      omega_g = 0.2,  | 
                  |
| 65 | 
                      link_dsld = 0,  | 
                  |
| 66 | 
                      link_ttg = 0,  | 
                  |
| 67 | 
                      link_identity = 0,  | 
                  |
| 68 | 
                      link_growth = 0  | 
                  |
| 69 | 
                      ) {
                     | 
                  |
| 70 | 2x | 
                      .SimLongitudinalSteinFojo(  | 
                  
| 71 | 2x | 
                      times = times,  | 
                  
| 72 | 2x | 
                      sigma = sigma,  | 
                  
| 73 | 2x | 
                      mu_s = mu_s,  | 
                  
| 74 | 2x | 
                      mu_g = mu_g,  | 
                  
| 75 | 2x | 
                      mu_b = mu_b,  | 
                  
| 76 | 2x | 
                      omega_b = omega_b,  | 
                  
| 77 | 2x | 
                      omega_s = omega_s,  | 
                  
| 78 | 2x | 
                      omega_g = omega_g,  | 
                  
| 79 | 2x | 
                      link_dsld = link_dsld,  | 
                  
| 80 | 2x | 
                      link_ttg = link_ttg,  | 
                  
| 81 | 2x | 
                      link_identity = link_identity,  | 
                  
| 82 | 2x | 
                      link_growth = link_growth  | 
                  
| 83 | 
                      )  | 
                  |
| 84 | 
                      }  | 
                  |
| 85 | ||
| 86 | ||
| 87 | 
                      setValidity(  | 
                  |
| 88 | 
                      "SimLongitudinalSteinFojo",  | 
                  |
| 89 | 
                          function(object) {
                     | 
                  |
| 90 | 
                      par_lengths <- c(  | 
                  |
| 91 | 
                      length(object@mu_s),  | 
                  |
| 92 | 
                      length(object@mu_g)  | 
                  |
| 93 | 
                      )  | 
                  |
| 94 | 
                              if (length(unique(par_lengths)) != 1) {
                     | 
                  |
| 95 | 
                                  return("The parameters `mu_s` and `mu_g` must have the same length.")
                     | 
                  |
| 96 | 
                      }  | 
                  |
| 97 | 
                      len_1_pars <- c(  | 
                  |
| 98 | 
                      "sigma", "omega_b", "omega_s", "omega_g",  | 
                  |
| 99 | 
                      "link_dsld", "link_ttg", "link_identity",  | 
                  |
| 100 | 
                      "link_growth"  | 
                  |
| 101 | 
                      )  | 
                  |
| 102 | 
                              for (par in len_1_pars) {
                     | 
                  |
| 103 | 
                                  if (length(slot(object, par)) != 1) {
                     | 
                  |
| 104 | 
                                      return(sprintf("The `%s` parameter must be a length 1 numeric.", par))
                     | 
                  |
| 105 | 
                      }  | 
                  |
| 106 | 
                      }  | 
                  |
| 107 | 
                      return(TRUE)  | 
                  |
| 108 | 
                      }  | 
                  |
| 109 | 
                      )  | 
                  |
| 110 | ||
| 111 | 
                      #' @rdname as_print_string  | 
                  |
| 112 | 
                      as_print_string.SimLongitudinalSteinFojo <- function(object) {
                     | 
                  |
| 113 | 1x | 
                          return("SimLongitudinalSteinFojo")
                     | 
                  
| 114 | 
                      }  | 
                  |
| 115 | ||
| 116 | 
                      #' @rdname sampleObservations  | 
                  |
| 117 | 
                      #' @export  | 
                  |
| 118 | 
                      sampleObservations.SimLongitudinalSteinFojo <- function(object, times_df) {
                     | 
                  |
| 119 | 1x | 
                      times_df |>  | 
                  
| 120 | 1x | 
                      dplyr::mutate(mu_sld = sf_sld(.data$time, .data$psi_b, .data$psi_s, .data$psi_g)) |>  | 
                  
| 121 | 1x | 
                      dplyr::mutate(dsld = sf_dsld(.data$time, .data$psi_b, .data$psi_s, .data$psi_g)) |>  | 
                  
| 122 | 1x | 
                      dplyr::mutate(ttg = sf_ttg(.data$time, .data$psi_b, .data$psi_s, .data$psi_g)) |>  | 
                  
| 123 | 1x | 
                      dplyr::mutate(sld = stats::rnorm(dplyr::n(), .data$mu_sld, .data$mu_sld * object@sigma)) |>  | 
                  
| 124 | 1x | 
                      dplyr::mutate(  | 
                  
| 125 | 1x | 
                      log_haz_link =  | 
                  
| 126 | 1x | 
                      (object@link_dsld * .data$dsld) +  | 
                  
| 127 | 1x | 
                      (object@link_ttg * .data$ttg) +  | 
                  
| 128 | 1x | 
                      (object@link_identity * .data$mu_sld) +  | 
                  
| 129 | 1x | 
                      (object@link_growth * log(.data$psi_g))  | 
                  
| 130 | 
                      )  | 
                  |
| 131 | 
                      }  | 
                  |
| 132 | ||
| 133 | ||
| 134 | 
                      #' @rdname sampleSubjects  | 
                  |
| 135 | 
                      #' @export  | 
                  |
| 136 | 
                      sampleSubjects.SimLongitudinalSteinFojo <- function(object, subjects_df) {
                     | 
                  |
| 137 | 1x | 
                      assert_that(  | 
                  
| 138 | 1x | 
                      is.factor(subjects_df$study),  | 
                  
| 139 | 1x | 
                      is.factor(subjects_df$arm),  | 
                  
| 140 | 1x | 
                      length(levels(subjects_df$study)) == length(object@mu_b),  | 
                  
| 141 | 1x | 
                      length(levels(subjects_df$arm)) == length(object@mu_s)  | 
                  
| 142 | 
                      )  | 
                  |
| 143 | ||
| 144 | 1x | 
                      res <- subjects_df |>  | 
                  
| 145 | 1x | 
                      dplyr::distinct(.data$subject, .data$arm, .data$study) |>  | 
                  
| 146 | 1x | 
                      dplyr::mutate(study_idx = as.numeric(.data$study)) |>  | 
                  
| 147 | 1x | 
                      dplyr::mutate(arm_idx = as.numeric(.data$arm)) |>  | 
                  
| 148 | 1x | 
                      dplyr::mutate(psi_b = stats::rlnorm(dplyr::n(), object@mu_b[.data$study_idx], object@omega_b)) |>  | 
                  
| 149 | 1x | 
                      dplyr::mutate(psi_s = stats::rlnorm(dplyr::n(), object@mu_s[.data$arm_idx], object@omega_s)) |>  | 
                  
| 150 | 1x | 
                      dplyr::mutate(psi_g = stats::rlnorm(dplyr::n(), object@mu_g[.data$arm_idx], object@omega_g))  | 
                  
| 151 | ||
| 152 | 1x | 
                          res[, c("subject", "arm", "study", "psi_b", "psi_s", "psi_g")]
                     | 
                  
| 153 | 
                      }  | 
                  |
| 154 | ||
| 155 | ||
| 156 | 
                      #' Stein-Fojo Functionals  | 
                  |
| 157 | 
                      #'  | 
                  |
| 158 | 
                      #' @param time (`numeric`)\cr time grid.  | 
                  |
| 159 | 
                      #' @param b (`number`)\cr baseline.  | 
                  |
| 160 | 
                      #' @param s (`number`)\cr shrinkage.  | 
                  |
| 161 | 
                      #' @param g (`number`)\cr growth.  | 
                  |
| 162 | 
                      #'  | 
                  |
| 163 | 
                      #' @returns The function results.  | 
                  |
| 164 | 
                      #' @keywords internal  | 
                  |
| 165 | 
                      sf_sld <- function(time, b, s, g) {
                     | 
                  |
| 166 | 1x | 
                      s <- dplyr::if_else(time >= 0, s, 0)  | 
                  
| 167 | 1x | 
                      b * (exp(-s * time) + exp(g * time) - 1)  | 
                  
| 168 | 
                      }  | 
                  |
| 169 | ||
| 170 | ||
| 171 | 
                      #' @rdname sf_sld  | 
                  |
| 172 | 
                      sf_ttg <- function(time, b, s, g) {
                     | 
                  |
| 173 | 1x | 
                      t1 <- (log(s) - log(g)) / (g + s)  | 
                  
| 174 | 1x | 
                      t1[t1 <= 0] <- 0  | 
                  
| 175 | 1x | 
                      return(t1)  | 
                  
| 176 | 
                      }  | 
                  |
| 177 | ||
| 178 | ||
| 179 | 
                      #' @rdname sf_sld  | 
                  |
| 180 | 
                      sf_dsld <- function(time, b, s, g) {
                     | 
                  |
| 181 | 1x | 
                      s <- dplyr::if_else(time >= 0, s, 0)  | 
                  
| 182 | 1x | 
                      t1 <- g * exp(g * time)  | 
                  
| 183 | 1x | 
                      t2 <- s * exp(-s * time)  | 
                  
| 184 | 1x | 
                      return(b * (t1 - t2))  | 
                  
| 185 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include SimLongitudinal.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | 
                      #' Simulate Longitudinal Data from a Claret-Bruno Model  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @param times (`numeric`)\cr the times to generate observations at.  | 
                  |
| 9 | 
                      #' @param sigma (`number`)\cr the variance of the longitudinal values.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @param mu_b (`numeric`)\cr the mean population baseline sld value.  | 
                  |
| 12 | 
                      #' @param mu_g (`numeric`)\cr the mean population growth rate.  | 
                  |
| 13 | 
                      #' @param mu_c (`numeric`)\cr the mean population resistance rate.  | 
                  |
| 14 | 
                      #' @param mu_p (`numeric`)\cr the mean population growth inhibition.  | 
                  |
| 15 | 
                      #'  | 
                  |
| 16 | 
                      #' @param omega_b (`number`)\cr the population standard deviation for the baseline sld value.  | 
                  |
| 17 | 
                      #' @param omega_g (`number`)\cr the population standard deviation for the growth rate.  | 
                  |
| 18 | 
                      #' @param omega_c (`number`)\cr the population standard deviation for the resistance rate.  | 
                  |
| 19 | 
                      #' @param omega_p (`number`)\cr the population standard deviation for the growth inhibition.  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @param link_dsld (`number`)\cr the link coefficient for the derivative contribution.  | 
                  |
| 22 | 
                      #' @param link_ttg (`number`)\cr the link coefficient for the time-to-growth contribution.  | 
                  |
| 23 | 
                      #' @param link_identity (`number`)\cr the link coefficient for the SLD Identity contribution.  | 
                  |
| 24 | 
                      #' @param link_growth (`number`)\cr the link coefficient for the growth parameter contribution.  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @slot sigma (`numeric`)\cr See arguments.  | 
                  |
| 27 | 
                      #'  | 
                  |
| 28 | 
                      #' @slot mu_b (`numeric`)\cr See arguments.  | 
                  |
| 29 | 
                      #' @slot mu_g (`numeric`)\cr See arguments.  | 
                  |
| 30 | 
                      #' @slot mu_c (`numeric`)\cr See arguments.  | 
                  |
| 31 | 
                      #' @slot mu_p (`numeric`)\cr See arguments.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #' @slot omega_b (`numeric`)\cr See arguments.  | 
                  |
| 34 | 
                      #' @slot omega_g (`numeric`)\cr See arguments.  | 
                  |
| 35 | 
                      #' @slot omega_c (`numeric`)\cr See arguments.  | 
                  |
| 36 | 
                      #' @slot omega_p (`numeric`)\cr See arguments.  | 
                  |
| 37 | 
                      #'  | 
                  |
| 38 | 
                      #' @slot link_dsld (`numeric`)\cr See arguments.  | 
                  |
| 39 | 
                      #' @slot link_ttg (`numeric`)\cr See arguments.  | 
                  |
| 40 | 
                      #' @slot link_identity (`numeric`)\cr See arguments.  | 
                  |
| 41 | 
                      #' @slot link_growth (`numeric`)\cr See arguments.  | 
                  |
| 42 | 
                      #'  | 
                  |
| 43 | 
                      #' @family SimLongitudinal  | 
                  |
| 44 | 
                      #' @name SimLongitudinalClaretBruno-class  | 
                  |
| 45 | 
                      #' @exportClass SimLongitudinalClaretBruno  | 
                  |
| 46 | 
                      .SimLongitudinalClaretBruno <- setClass(  | 
                  |
| 47 | 
                      "SimLongitudinalClaretBruno",  | 
                  |
| 48 | 
                      contains = "SimLongitudinal",  | 
                  |
| 49 | 
                      slots = c(  | 
                  |
| 50 | 
                      sigma = "numeric",  | 
                  |
| 51 | 
                      mu_b = "numeric",  | 
                  |
| 52 | 
                      mu_g = "numeric",  | 
                  |
| 53 | 
                      mu_c = "numeric",  | 
                  |
| 54 | 
                      mu_p = "numeric",  | 
                  |
| 55 | 
                      omega_b = "numeric",  | 
                  |
| 56 | 
                      omega_g = "numeric",  | 
                  |
| 57 | 
                      omega_c = "numeric",  | 
                  |
| 58 | 
                      omega_p = "numeric",  | 
                  |
| 59 | 
                      link_dsld = "numeric",  | 
                  |
| 60 | 
                      link_ttg = "numeric",  | 
                  |
| 61 | 
                      link_identity = "numeric",  | 
                  |
| 62 | 
                      link_growth = "numeric"  | 
                  |
| 63 | 
                      )  | 
                  |
| 64 | 
                      )  | 
                  |
| 65 | ||
| 66 | 
                      #' @rdname SimLongitudinalClaretBruno-class  | 
                  |
| 67 | 
                      #' @export  | 
                  |
| 68 | 
                      SimLongitudinalClaretBruno <- function(  | 
                  |
| 69 | 
                      times = c(-100, -50, 0, 50, 100, 150, 250, 350, 450, 550) / 365,  | 
                  |
| 70 | 
                      sigma = 0.01,  | 
                  |
| 71 | 
                      mu_b = log(60),  | 
                  |
| 72 | 
                      mu_g = log(c(0.9, 1.1)),  | 
                  |
| 73 | 
                      mu_c = log(c(0.25, 0.35)),  | 
                  |
| 74 | 
                      mu_p = log(c(1.5, 2)),  | 
                  |
| 75 | 
                      omega_b = 0.2,  | 
                  |
| 76 | 
                      omega_g = 0.2,  | 
                  |
| 77 | 
                      omega_c = 0.2,  | 
                  |
| 78 | 
                      omega_p = 0.2,  | 
                  |
| 79 | 
                      link_dsld = 0,  | 
                  |
| 80 | 
                      link_ttg = 0,  | 
                  |
| 81 | 
                      link_identity = 0,  | 
                  |
| 82 | 
                      link_growth = 0  | 
                  |
| 83 | 
                      ) {
                     | 
                  |
| 84 | 2x | 
                      .SimLongitudinalClaretBruno(  | 
                  
| 85 | 2x | 
                      times = times,  | 
                  
| 86 | 2x | 
                      sigma = sigma,  | 
                  
| 87 | 2x | 
                      mu_b = mu_b,  | 
                  
| 88 | 2x | 
                      mu_g = mu_g,  | 
                  
| 89 | 2x | 
                      mu_c = mu_c,  | 
                  
| 90 | 2x | 
                      mu_p = mu_p,  | 
                  
| 91 | 2x | 
                      omega_b = omega_b,  | 
                  
| 92 | 2x | 
                      omega_g = omega_g,  | 
                  
| 93 | 2x | 
                      omega_c = omega_c,  | 
                  
| 94 | 2x | 
                      omega_p = omega_p,  | 
                  
| 95 | 2x | 
                      link_dsld = link_dsld,  | 
                  
| 96 | 2x | 
                      link_ttg = link_ttg,  | 
                  
| 97 | 2x | 
                      link_identity = link_identity,  | 
                  
| 98 | 2x | 
                      link_growth = link_growth  | 
                  
| 99 | 
                      )  | 
                  |
| 100 | 
                      }  | 
                  |
| 101 | ||
| 102 | ||
| 103 | 
                      setValidity(  | 
                  |
| 104 | 
                      "SimLongitudinalClaretBruno",  | 
                  |
| 105 | 
                          function(object) {
                     | 
                  |
| 106 | 
                      par_lengths <- c(  | 
                  |
| 107 | 
                      length(object@mu_g),  | 
                  |
| 108 | 
                      length(object@mu_c),  | 
                  |
| 109 | 
                      length(object@mu_p)  | 
                  |
| 110 | 
                      )  | 
                  |
| 111 | 
                              if (length(unique(par_lengths)) != 1) {
                     | 
                  |
| 112 | 
                                  return("The parameters `mu_g`, `mu_c` & `mu_p` must have the same length.")
                     | 
                  |
| 113 | 
                      }  | 
                  |
| 114 | 
                      len_1_pars <- c(  | 
                  |
| 115 | 
                      "sigma", "omega_b", "omega_g", "omega_c", "omega_p",  | 
                  |
| 116 | 
                      "link_dsld", "link_ttg", "link_identity",  | 
                  |
| 117 | 
                      "link_growth"  | 
                  |
| 118 | 
                      )  | 
                  |
| 119 | 
                              for (par in len_1_pars) {
                     | 
                  |
| 120 | 
                                  if (length(slot(object, par)) != 1) {
                     | 
                  |
| 121 | 
                                      return(sprintf("The `%s` parameter must be a length 1 numeric.", par))
                     | 
                  |
| 122 | 
                      }  | 
                  |
| 123 | 
                      }  | 
                  |
| 124 | 
                      return(TRUE)  | 
                  |
| 125 | 
                      }  | 
                  |
| 126 | 
                      )  | 
                  |
| 127 | ||
| 128 | 
                      #' @rdname as_print_string  | 
                  |
| 129 | 
                      as_print_string.SimLongitudinalClaretBruno <- function(object) {
                     | 
                  |
| 130 | 1x | 
                          return("SimLongitudinalClaretBruno")
                     | 
                  
| 131 | 
                      }  | 
                  |
| 132 | ||
| 133 | 
                      #' @rdname sampleObservations  | 
                  |
| 134 | 
                      #' @export  | 
                  |
| 135 | 
                      sampleObservations.SimLongitudinalClaretBruno <- function(object, times_df) {
                     | 
                  |
| 136 | 1x | 
                      times_df |>  | 
                  
| 137 | 1x | 
                      dplyr::mutate(mu_sld = clbr_sld(.data$time, .data$ind_b, .data$ind_g, .data$ind_c, .data$ind_p)) |>  | 
                  
| 138 | 1x | 
                      dplyr::mutate(dsld = clbr_dsld(.data$time, .data$ind_b, .data$ind_g, .data$ind_c, .data$ind_p)) |>  | 
                  
| 139 | 1x | 
                      dplyr::mutate(ttg = clbr_ttg(.data$time, .data$ind_b, .data$ind_g, .data$ind_c, .data$ind_p)) |>  | 
                  
| 140 | 1x | 
                      dplyr::mutate(sld = stats::rnorm(dplyr::n(), .data$mu_sld, .data$mu_sld * object@sigma)) |>  | 
                  
| 141 | 1x | 
                      dplyr::mutate(  | 
                  
| 142 | 1x | 
                      log_haz_link =  | 
                  
| 143 | 1x | 
                      (object@link_dsld * .data$dsld) +  | 
                  
| 144 | 1x | 
                      (object@link_ttg * .data$ttg) +  | 
                  
| 145 | 1x | 
                      (object@link_identity * .data$mu_sld) +  | 
                  
| 146 | 1x | 
                      (object@link_growth * log(.data$ind_g))  | 
                  
| 147 | 
                      )  | 
                  |
| 148 | 
                      }  | 
                  |
| 149 | ||
| 150 | ||
| 151 | 
                      #' @rdname sampleSubjects  | 
                  |
| 152 | 
                      #' @export  | 
                  |
| 153 | 
                      sampleSubjects.SimLongitudinalClaretBruno <- function(object, subjects_df) {
                     | 
                  |
| 154 | 1x | 
                      assert_that(  | 
                  
| 155 | 1x | 
                      is.factor(subjects_df$study),  | 
                  
| 156 | 1x | 
                      is.factor(subjects_df$arm),  | 
                  
| 157 | 1x | 
                      length(levels(subjects_df$study)) == length(object@mu_b),  | 
                  
| 158 | 1x | 
                      length(levels(subjects_df$arm)) == length(object@mu_g),  | 
                  
| 159 | 1x | 
                      length(levels(subjects_df$arm)) == length(object@mu_c),  | 
                  
| 160 | 1x | 
                      length(levels(subjects_df$arm)) == length(object@mu_p)  | 
                  
| 161 | 
                      )  | 
                  |
| 162 | ||
| 163 | 1x | 
                      res <- subjects_df |>  | 
                  
| 164 | 1x | 
                      dplyr::distinct(.data$subject, .data$arm, .data$study) |>  | 
                  
| 165 | 1x | 
                      dplyr::mutate(study_idx = as.numeric(.data$study)) |>  | 
                  
| 166 | 1x | 
                      dplyr::mutate(arm_idx = as.numeric(.data$arm)) |>  | 
                  
| 167 | 1x | 
                      dplyr::mutate(ind_b = stats::rlnorm(dplyr::n(), object@mu_b[.data$study_idx], object@omega_b)) |>  | 
                  
| 168 | 1x | 
                      dplyr::mutate(ind_g = stats::rlnorm(dplyr::n(), object@mu_g[.data$arm_idx], object@omega_g)) |>  | 
                  
| 169 | 1x | 
                      dplyr::mutate(ind_c = stats::rlnorm(dplyr::n(), object@mu_c[.data$arm_idx], object@omega_c)) |>  | 
                  
| 170 | 1x | 
                      dplyr::mutate(ind_p = stats::rlnorm(dplyr::n(), object@mu_p[.data$arm_idx], object@omega_p))  | 
                  
| 171 | ||
| 172 | 1x | 
                          res[, c("subject", "arm", "study", "ind_b", "ind_g", "ind_c", "ind_p")]
                     | 
                  
| 173 | 
                      }  | 
                  |
| 174 | ||
| 175 | ||
| 176 | 
                      #' Claret-Bruno Functionals  | 
                  |
| 177 | 
                      #'  | 
                  |
| 178 | 
                      #' @param t (`numeric`)\cr time grid.  | 
                  |
| 179 | 
                      #' @param b (`number`)\cr baseline sld.  | 
                  |
| 180 | 
                      #' @param g (`number`)\cr growth rate.  | 
                  |
| 181 | 
                      #' @param c (`number`)\cr resistance rate.  | 
                  |
| 182 | 
                      #' @param p (`number`)\cr growth inhibition.  | 
                  |
| 183 | 
                      #'  | 
                  |
| 184 | 
                      #' @returns The function results.  | 
                  |
| 185 | 
                      #' @keywords internal  | 
                  |
| 186 | 
                      clbr_sld <- function(t, b, g, c, p) {
                     | 
                  |
| 187 | 2x | 
                      p <- ifelse(t >= 0, p, 0)  | 
                  
| 188 | 2x | 
                      b * exp((g * t) - (p / c) * (1 - exp(-c * t)))  | 
                  
| 189 | 
                      }  | 
                  |
| 190 | ||
| 191 | 
                      #' @rdname clbr_sld  | 
                  |
| 192 | 
                      clbr_ttg <- function(t, b, g, c, p) {
                     | 
                  |
| 193 | 1x | 
                      log(p / g) / c  | 
                  
| 194 | 
                      }  | 
                  |
| 195 | ||
| 196 | 
                      #' @rdname clbr_sld  | 
                  |
| 197 | 
                      clbr_dsld <- function(t, b, g, c, p) {
                     | 
                  |
| 198 | 1x | 
                      lt0 <- b * g * exp(g * t)  | 
                  
| 199 | 1x | 
                      gt0 <- (g - p * exp(-c * t)) * clbr_sld(t, b, g, c, p)  | 
                  
| 200 | 1x | 
                      ifelse(t >= 0, gt0, lt0)  | 
                  
| 201 | 
                      }  | 
                  
| 1 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 2 | 
                      #' @include StanModule.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      #' @include ParameterList.R  | 
                  |
| 5 | 
                      #' @include Parameter.R  | 
                  |
| 6 | 
                      #' @include Link.R  | 
                  |
| 7 | 
                      NULL  | 
                  |
| 8 | ||
| 9 | ||
| 10 | 
                      #' `LongitudinalClaretBruno`  | 
                  |
| 11 | 
                      #'  | 
                  |
| 12 | 
                      #' This class extends the general [`LongitudinalModel`] class for using the  | 
                  |
| 13 | 
                      #' Claret-Bruno model for the longitudinal outcome.  | 
                  |
| 14 | 
                      #'  | 
                  |
| 15 | 
                      #' @section Available Links:  | 
                  |
| 16 | 
                      #' - [`linkDSLD()`]  | 
                  |
| 17 | 
                      #' - [`linkTTG()`]  | 
                  |
| 18 | 
                      #' - [`linkIdentity()`]  | 
                  |
| 19 | 
                      #' - [`linkGrowth()`]  | 
                  |
| 20 | 
                      #' @exportClass LongitudinalClaretBruno  | 
                  |
| 21 | 
                      .LongitudinalClaretBruno <- setClass(  | 
                  |
| 22 | 
                      Class = "LongitudinalClaretBruno",  | 
                  |
| 23 | 
                      contains = "LongitudinalModel"  | 
                  |
| 24 | 
                      )  | 
                  |
| 25 | ||
| 26 | ||
| 27 | 
                      #' @rdname LongitudinalClaretBruno-class  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @param mu_b (`Prior`)\cr for the mean population baseline sld value.  | 
                  |
| 30 | 
                      #' @param mu_g (`Prior`)\cr for the mean population growth rate.  | 
                  |
| 31 | 
                      #' @param mu_c (`Prior`)\cr for the mean population resistance rate.  | 
                  |
| 32 | 
                      #' @param mu_p (`Prior`)\cr for the mean population growth inhibition  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' @param omega_b (`Prior`)\cr for the population standard deviation for the baseline sld value.  | 
                  |
| 35 | 
                      #' @param omega_g (`Prior`)\cr for the population standard deviation for the growth rate.  | 
                  |
| 36 | 
                      #' @param omega_c (`Prior`)\cr for the population standard deviation for the resistance rate.  | 
                  |
| 37 | 
                      #' @param omega_p (`Prior`)\cr for the population standard deviation for the growth inhibition.  | 
                  |
| 38 | 
                      #'  | 
                  |
| 39 | 
                      #' @param sigma (`Prior`)\cr for the variance of the longitudinal values.  | 
                  |
| 40 | 
                      #'  | 
                  |
| 41 | 
                      #' @param centred (`logical`)\cr whether to use the centred parameterization.  | 
                  |
| 42 | 
                      #'  | 
                  |
| 43 | 
                      #' @export  | 
                  |
| 44 | 
                      LongitudinalClaretBruno <- function(  | 
                  |
| 45 | ||
| 46 | 
                      mu_b = prior_normal(log(60), 0.5),  | 
                  |
| 47 | 
                      mu_g = prior_normal(log(1), 0.5),  | 
                  |
| 48 | 
                      mu_c = prior_normal(log(0.4), 0.5),  | 
                  |
| 49 | 
                      mu_p = prior_normal(log(2), 0.5),  | 
                  |
| 50 | ||
| 51 | 
                      omega_b = prior_lognormal(log(0.2), 0.5),  | 
                  |
| 52 | 
                      omega_g = prior_lognormal(log(0.2), 0.5),  | 
                  |
| 53 | 
                      omega_c = prior_lognormal(log(0.2), 0.5),  | 
                  |
| 54 | 
                      omega_p = prior_lognormal(log(0.2), 0.5),  | 
                  |
| 55 | ||
| 56 | 
                      sigma = prior_lognormal(log(0.1), 0.5),  | 
                  |
| 57 | ||
| 58 | 
                      centred = FALSE  | 
                  |
| 59 | 
                      ) {
                     | 
                  |
| 60 | ||
| 61 | 14x | 
                      sf_model <- StanModule(decorated_render(  | 
                  
| 62 | 14x | 
                              .x = read_stan("lm-claret-bruno/model.stan"),
                     | 
                  
| 63 | 14x | 
                      centred = centred  | 
                  
| 64 | 
                      ))  | 
                  |
| 65 | ||
| 66 | 
                      # Apply constraints  | 
                  |
| 67 | 14x | 
                      omega_b <- set_limits(omega_b, lower = 0)  | 
                  
| 68 | 14x | 
                      omega_g <- set_limits(omega_g, lower = 0)  | 
                  
| 69 | 14x | 
                      omega_c <- set_limits(omega_c, lower = 0)  | 
                  
| 70 | 14x | 
                      omega_p <- set_limits(omega_p, lower = 0)  | 
                  
| 71 | 14x | 
                      sigma <- set_limits(sigma, lower = 0)  | 
                  
| 72 | ||
| 73 | ||
| 74 | 14x | 
                      parameters <- list(  | 
                  
| 75 | 14x | 
                      Parameter(name = "lm_clbr_mu_b", prior = mu_b, size = "n_studies"),  | 
                  
| 76 | 14x | 
                      Parameter(name = "lm_clbr_mu_g", prior = mu_g, size = "n_arms"),  | 
                  
| 77 | 14x | 
                      Parameter(name = "lm_clbr_mu_c", prior = mu_c, size = "n_arms"),  | 
                  
| 78 | 14x | 
                      Parameter(name = "lm_clbr_mu_p", prior = mu_p, size = "n_arms"),  | 
                  
| 79 | ||
| 80 | 14x | 
                      Parameter(name = "lm_clbr_omega_b", prior = omega_b, size = 1),  | 
                  
| 81 | 14x | 
                      Parameter(name = "lm_clbr_omega_g", prior = omega_g, size = 1),  | 
                  
| 82 | 14x | 
                      Parameter(name = "lm_clbr_omega_c", prior = omega_c, size = 1),  | 
                  
| 83 | 14x | 
                      Parameter(name = "lm_clbr_omega_p", prior = omega_p, size = 1),  | 
                  
| 84 | ||
| 85 | 14x | 
                      Parameter(name = "lm_clbr_sigma", prior = sigma, size = 1)  | 
                  
| 86 | 
                      )  | 
                  |
| 87 | ||
| 88 | 14x | 
                      assert_flag(centred)  | 
                  
| 89 | 14x | 
                          parameters_extra <- if (centred) {
                     | 
                  
| 90 | 2x | 
                      list(  | 
                  
| 91 | 2x | 
                      Parameter(  | 
                  
| 92 | 2x | 
                      name = "lm_clbr_ind_b",  | 
                  
| 93 | 2x | 
                      prior = prior_init_only(prior_lognormal(median(mu_b), median(omega_b))),  | 
                  
| 94 | 2x | 
                      size = "n_subjects"  | 
                  
| 95 | 
                      ),  | 
                  |
| 96 | 2x | 
                      Parameter(  | 
                  
| 97 | 2x | 
                      name = "lm_clbr_ind_g",  | 
                  
| 98 | 2x | 
                      prior = prior_init_only(prior_lognormal(median(mu_g), median(omega_g))),  | 
                  
| 99 | 2x | 
                      size = "n_subjects"  | 
                  
| 100 | 
                      ),  | 
                  |
| 101 | 2x | 
                      Parameter(  | 
                  
| 102 | 2x | 
                      name = "lm_clbr_ind_c",  | 
                  
| 103 | 2x | 
                      prior = prior_init_only(prior_lognormal(median(mu_c), median(omega_c))),  | 
                  
| 104 | 2x | 
                      size = "n_subjects"  | 
                  
| 105 | 
                      ),  | 
                  |
| 106 | 2x | 
                      Parameter(  | 
                  
| 107 | 2x | 
                      name = "lm_clbr_ind_p",  | 
                  
| 108 | 2x | 
                      prior = prior_init_only(prior_lognormal(median(mu_p), median(omega_p))),  | 
                  
| 109 | 2x | 
                      size = "n_subjects"  | 
                  
| 110 | 
                      )  | 
                  |
| 111 | 
                      )  | 
                  |
| 112 | 
                          } else {
                     | 
                  |
| 113 | 12x | 
                      list(  | 
                  
| 114 | 12x | 
                      Parameter(name = "lm_clbr_eta_b", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 115 | 12x | 
                      Parameter(name = "lm_clbr_eta_g", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 116 | 12x | 
                      Parameter(name = "lm_clbr_eta_c", prior = prior_std_normal(), size = "n_subjects"),  | 
                  
| 117 | 12x | 
                      Parameter(name = "lm_clbr_eta_p", prior = prior_std_normal(), size = "n_subjects")  | 
                  
| 118 | 
                      )  | 
                  |
| 119 | 
                      }  | 
                  |
| 120 | 14x | 
                      parameters <- append(parameters, parameters_extra)  | 
                  
| 121 | ||
| 122 | 14x | 
                      x <- LongitudinalModel(  | 
                  
| 123 | 14x | 
                      name = "Claret-Bruno",  | 
                  
| 124 | 14x | 
                      stan = merge(  | 
                  
| 125 | 14x | 
                      sf_model,  | 
                  
| 126 | 14x | 
                                  StanModule("lm-claret-bruno/functions.stan")
                     | 
                  
| 127 | 
                      ),  | 
                  |
| 128 | 14x | 
                      parameters = do.call(ParameterList, parameters)  | 
                  
| 129 | 
                      )  | 
                  |
| 130 | 14x | 
                      .LongitudinalClaretBruno(x)  | 
                  
| 131 | 
                      }  | 
                  |
| 132 | ||
| 133 | ||
| 134 | ||
| 135 | 
                      #' @export  | 
                  |
| 136 | 
                      enableLink.LongitudinalClaretBruno <- function(object, ...) {
                     | 
                  |
| 137 | 1x | 
                      object@stan <- merge(  | 
                  
| 138 | 1x | 
                      object@stan,  | 
                  
| 139 | 1x | 
                              StanModule("lm-claret-bruno/link.stan")
                     | 
                  
| 140 | 
                      )  | 
                  |
| 141 | 1x | 
                      object  | 
                  
| 142 | 
                      }  | 
                  |
| 143 | ||
| 144 | 
                      #' @export  | 
                  |
| 145 | 
                      linkDSLD.LongitudinalClaretBruno <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 146 | 1x | 
                      LinkComponent(  | 
                  
| 147 | 1x | 
                      key = "link_dsld",  | 
                  
| 148 | 1x | 
                              stan = StanModule("lm-claret-bruno/link_dsld.stan"),
                     | 
                  
| 149 | 1x | 
                      prior = prior  | 
                  
| 150 | 
                      )  | 
                  |
| 151 | 
                      }  | 
                  |
| 152 | ||
| 153 | 
                      #' @export  | 
                  |
| 154 | 
                      linkTTG.LongitudinalClaretBruno <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 155 | 1x | 
                      LinkComponent(  | 
                  
| 156 | 1x | 
                      key = "link_ttg",  | 
                  
| 157 | 1x | 
                              stan = StanModule("lm-claret-bruno/link_ttg.stan"),
                     | 
                  
| 158 | 1x | 
                      prior = prior  | 
                  
| 159 | 
                      )  | 
                  |
| 160 | 
                      }  | 
                  |
| 161 | ||
| 162 | 
                      #' @export  | 
                  |
| 163 | 
                      linkIdentity.LongitudinalClaretBruno <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 164 | ! | 
                      LinkComponent(  | 
                  
| 165 | ! | 
                      key = "link_identity",  | 
                  
| 166 | ! | 
                              stan = StanModule("lm-claret-bruno/link_identity.stan"),
                     | 
                  
| 167 | ! | 
                      prior = prior  | 
                  
| 168 | 
                      )  | 
                  |
| 169 | 
                      }  | 
                  |
| 170 | ||
| 171 | 
                      #' @export  | 
                  |
| 172 | 
                      linkGrowth.LongitudinalClaretBruno <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 173 | 1x | 
                      LinkComponent(  | 
                  
| 174 | 1x | 
                      key = "link_growth",  | 
                  
| 175 | 1x | 
                              stan = StanModule("lm-claret-bruno/link_growth.stan"),
                     | 
                  
| 176 | 1x | 
                      prior = prior  | 
                  
| 177 | 
                      )  | 
                  |
| 178 | 
                      }  | 
                  |
| 179 | ||
| 180 | 
                      #' @rdname getPredictionNames  | 
                  |
| 181 | 
                      #' @export  | 
                  |
| 182 | 
                      getPredictionNames.LongitudinalClaretBruno <- function(object, ...) {
                     | 
                  |
| 183 | ! | 
                          c("b", "g", "c", "p")
                     | 
                  
| 184 | 
                      }  | 
                  |
| 185 | ||
| 186 | 
                      #' @export  | 
                  |
| 187 | 
                      enableGQ.LongitudinalClaretBruno <- function(object, ...) {
                     | 
                  |
| 188 | 2x | 
                          StanModule("lm-claret-bruno/quantities.stan")
                     | 
                  
| 189 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' @include SimLongitudinal.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | 
                      #' Simulate Longitudinal Data from a Random Slope Model  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @param times (`numeric`)\cr the times to generate observations at.  | 
                  |
| 9 | 
                      #' @param intercept (`number`)\cr the mean baseline value for each study.  | 
                  |
| 10 | 
                      #' @param slope_mu (`numeric`)\cr the population slope for each treatment arm.  | 
                  |
| 11 | 
                      #' @param slope_sigma (`number`)\cr the random slope standard deviation.  | 
                  |
| 12 | 
                      #' @param sigma (`number`)\cr the variance of the longitudinal values.  | 
                  |
| 13 | 
                      #' @param link_dsld (`number`)\cr the link coefficient for the DSLD contribution.  | 
                  |
| 14 | 
                      #' @param link_identity (`number`)\cr the link coefficient for the identity contribution.  | 
                  |
| 15 | 
                      #'  | 
                  |
| 16 | 
                      #' @slot intercept (`numeric`)\cr See arguments.  | 
                  |
| 17 | 
                      #' @slot slope_mu (`numeric`)\cr See arguments.  | 
                  |
| 18 | 
                      #' @slot slope_sigma (`numeric`)\cr See arguments.  | 
                  |
| 19 | 
                      #' @slot sigma (`numeric`)\cr See arguments.  | 
                  |
| 20 | 
                      #' @slot link_dsld (`numeric`)\cr See arguments.  | 
                  |
| 21 | 
                      #' @slot link_identity (`numeric`)\cr See arguments.  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #' @family SimLongitudinal  | 
                  |
| 24 | 
                      #' @name SimLongitudinalRandomSlope-class  | 
                  |
| 25 | 
                      #' @exportClass SimLongitudinalRandomSlope  | 
                  |
| 26 | 
                      .SimLongitudinalRandomSlope <- setClass(  | 
                  |
| 27 | 
                      "SimLongitudinalRandomSlope",  | 
                  |
| 28 | 
                      contains = "SimLongitudinal",  | 
                  |
| 29 | 
                      slots = c(  | 
                  |
| 30 | 
                      intercept = "numeric",  | 
                  |
| 31 | 
                      slope_mu = "numeric",  | 
                  |
| 32 | 
                      slope_sigma = "numeric",  | 
                  |
| 33 | 
                      sigma = "numeric",  | 
                  |
| 34 | 
                      link_dsld = "numeric",  | 
                  |
| 35 | 
                      link_identity = "numeric"  | 
                  |
| 36 | 
                      )  | 
                  |
| 37 | 
                      )  | 
                  |
| 38 | ||
| 39 | 
                      #' @rdname SimLongitudinalRandomSlope-class  | 
                  |
| 40 | 
                      #' @export  | 
                  |
| 41 | 
                      SimLongitudinalRandomSlope <- function(  | 
                  |
| 42 | 
                      times = c(-100, -50, 0, 50, 100, 150, 250, 350, 450, 550),  | 
                  |
| 43 | 
                      intercept = 50,  | 
                  |
| 44 | 
                      slope_mu = c(0.01, 0.03),  | 
                  |
| 45 | 
                      slope_sigma = 0.5,  | 
                  |
| 46 | 
                      sigma = 2,  | 
                  |
| 47 | 
                      link_dsld = 0,  | 
                  |
| 48 | 
                      link_identity = 0  | 
                  |
| 49 | 
                      ) {
                     | 
                  |
| 50 | 18x | 
                      .SimLongitudinalRandomSlope(  | 
                  
| 51 | 18x | 
                      times = times,  | 
                  
| 52 | 18x | 
                      intercept = intercept,  | 
                  
| 53 | 18x | 
                      slope_mu = slope_mu,  | 
                  
| 54 | 18x | 
                      slope_sigma = slope_sigma,  | 
                  
| 55 | 18x | 
                      sigma = sigma,  | 
                  
| 56 | 18x | 
                      link_dsld = link_dsld,  | 
                  
| 57 | 18x | 
                      link_identity = link_identity  | 
                  
| 58 | 
                      )  | 
                  |
| 59 | 
                      }  | 
                  |
| 60 | ||
| 61 | 
                      #' @rdname as_print_string  | 
                  |
| 62 | 
                      as_print_string.SimLongitudinalRandomSlope <- function(object) {
                     | 
                  |
| 63 | 1x | 
                          return("SimLongitudinalRandomSlope")
                     | 
                  
| 64 | 
                      }  | 
                  |
| 65 | ||
| 66 | 
                      #' @rdname sampleObservations  | 
                  |
| 67 | 
                      #' @export  | 
                  |
| 68 | 
                      sampleObservations.SimLongitudinalRandomSlope <- function(object, times_df) {
                     | 
                  |
| 69 | 33x | 
                      times_df |>  | 
                  
| 70 | 33x | 
                      dplyr::mutate(err = stats::rnorm(dplyr::n(), 0, object@sigma)) |>  | 
                  
| 71 | 33x | 
                      dplyr::mutate(sld_mu = .data$intercept + .data$slope_ind * .data$time) |>  | 
                  
| 72 | 33x | 
                      dplyr::mutate(sld = .data$sld_mu + .data$err) |>  | 
                  
| 73 | 33x | 
                      dplyr::mutate(  | 
                  
| 74 | 33x | 
                      log_haz_link =  | 
                  
| 75 | 33x | 
                      object@link_dsld * .data$slope_ind +  | 
                  
| 76 | 33x | 
                      object@link_identity * .data$sld_mu  | 
                  
| 77 | 
                      )  | 
                  |
| 78 | 
                      }  | 
                  |
| 79 | ||
| 80 | 
                      #' @rdname sampleSubjects  | 
                  |
| 81 | 
                      #' @export  | 
                  |
| 82 | 
                      sampleSubjects.SimLongitudinalRandomSlope <- function(object, subjects_df) {
                     | 
                  |
| 83 | 17x | 
                      assert_that(  | 
                  
| 84 | 17x | 
                      is.factor(subjects_df[["study"]]),  | 
                  
| 85 | 17x | 
                      is.factor(subjects_df[["arm"]])  | 
                  
| 86 | 
                      )  | 
                  |
| 87 | ||
| 88 | 17x | 
                      assert_that(  | 
                  
| 89 | 17x | 
                      length(object@slope_mu) == length(unique(subjects_df[["arm"]])),  | 
                  
| 90 | 17x | 
                      msg = "`length(slope_mu)` should be equal to the number of unique arms"  | 
                  
| 91 | 
                      )  | 
                  |
| 92 | ||
| 93 | 17x | 
                      assert_that(  | 
                  
| 94 | 17x | 
                      length(object@intercept) == length(unique(subjects_df[["study"]])),  | 
                  
| 95 | 17x | 
                      msg = "`length(intercept)` should be equal to the number of unique studies"  | 
                  
| 96 | 
                      )  | 
                  |
| 97 | ||
| 98 | 17x | 
                      assert_that(  | 
                  
| 99 | 17x | 
                      nrow(subjects_df) == length(unique(subjects_df[["subject"]])),  | 
                  
| 100 | 17x | 
                      msg = "The number of rows in `subjects_df` should be equal to the number of unique subjects"  | 
                  
| 101 | 
                      )  | 
                  |
| 102 | ||
| 103 | 17x | 
                      subjects_df |>  | 
                  
| 104 | 17x | 
                      dplyr::mutate(intercept = object@intercept[as.numeric(.data$study)]) |>  | 
                  
| 105 | 17x | 
                      dplyr::mutate(slope_ind = stats::rnorm(  | 
                  
| 106 | 17x | 
                      n = dplyr::n(),  | 
                  
| 107 | 17x | 
                      mean = object@slope_mu[as.numeric(.data$arm)],  | 
                  
| 108 | 17x | 
                      sd = object@slope_sigma  | 
                  
| 109 | 
                      ))  | 
                  |
| 110 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Prior.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | ||
| 6 | 
                      #' `Parameter` Function Arguments  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' The documentation lists all the conventional arguments for [`Parameter`]  | 
                  |
| 9 | 
                      #' constructors.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @param x ([`Parameter`])\cr a prior Distribution  | 
                  |
| 12 | 
                      #' @param object ([`Parameter`])\cr a prior Distribution  | 
                  |
| 13 | 
                      #' @param ... Not Used.  | 
                  |
| 14 | 
                      #'  | 
                  |
| 15 | 
                      #' @name Parameter-Shared  | 
                  |
| 16 | 
                      #' @keywords internal  | 
                  |
| 17 | 
                      NULL  | 
                  |
| 18 | ||
| 19 | ||
| 20 | 
                      setClassUnion(name = "numeric_OR_character", c("numeric", "character"))
                     | 
                  |
| 21 | ||
| 22 | 
                      # Parameter-class ----  | 
                  |
| 23 | ||
| 24 | 
                      #' `Parameter`  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' Stores the name, the prior distribution and the size of a parameter.  | 
                  |
| 27 | 
                      #' If `size` is a string then this indicates the name of the variable  | 
                  |
| 28 | 
                      #' within the stan data object that specifies the size of this parameter.  | 
                  |
| 29 | 
                      #'  | 
                  |
| 30 | 
                      #' @slot name (`string`)\cr of the parameter.  | 
                  |
| 31 | 
                      #' @slot prior (`Prior`)\cr for the parameter.  | 
                  |
| 32 | 
                      #' @slot size (`numeric` or `string`)\cr dimension of the parameter.  | 
                  |
| 33 | 
                      #'  | 
                  |
| 34 | 
                      #' @family Parameter  | 
                  |
| 35 | 
                      #' @exportClass Parameter  | 
                  |
| 36 | 
                      #' @export Parameter  | 
                  |
| 37 | 
                      .Parameter <- setClass(  | 
                  |
| 38 | 
                      Class = "Parameter",  | 
                  |
| 39 | 
                      slots = list(  | 
                  |
| 40 | 
                      "name" = "character",  | 
                  |
| 41 | 
                      "prior" = "Prior",  | 
                  |
| 42 | 
                      "size" = "numeric_OR_character"  | 
                  |
| 43 | 
                      )  | 
                  |
| 44 | 
                      )  | 
                  |
| 45 | 
                      #' @param prior (`Prior`)\cr for the parameter.  | 
                  |
| 46 | 
                      #' @param name (`string`)\cr of the parameter.  | 
                  |
| 47 | 
                      #' @param size (`numeric` or `string`)\cr dimension of the parameter.  | 
                  |
| 48 | 
                      #' @rdname Parameter-class  | 
                  |
| 49 | 
                      Parameter <- function(prior, name, size = 1) {
                     | 
                  |
| 50 | 867x | 
                      .Parameter(  | 
                  
| 51 | 867x | 
                      prior = prior,  | 
                  
| 52 | 867x | 
                      name = name,  | 
                  
| 53 | 867x | 
                      size = size  | 
                  
| 54 | 
                      )  | 
                  |
| 55 | 
                      }  | 
                  |
| 56 | 
                      setValidity(  | 
                  |
| 57 | 
                      Class = "Parameter",  | 
                  |
| 58 | 
                          method = function(object) {
                     | 
                  |
| 59 | 
                              if (!length(object@name) == 1) {
                     | 
                  |
| 60 | 
                                  return("Name must be a length 1 character vector")
                     | 
                  |
| 61 | 
                      }  | 
                  |
| 62 | 
                              if (is.character(object@size)) {
                     | 
                  |
| 63 | 
                                  if (!length(object@size) == 1) {
                     | 
                  |
| 64 | 
                                      return("Size must be a numeric vector or length 1 character vector")
                     | 
                  |
| 65 | 
                      }  | 
                  |
| 66 | 
                      }  | 
                  |
| 67 | 
                      return(TRUE)  | 
                  |
| 68 | 
                      }  | 
                  |
| 69 | 
                      )  | 
                  |
| 70 | ||
| 71 | ||
| 72 | 
                      #' `Parameter` -> `StanModule`  | 
                  |
| 73 | 
                      #'  | 
                  |
| 74 | 
                      #' Converts a [`Parameter`] object to a [`StanModule`] object  | 
                  |
| 75 | 
                      #'  | 
                  |
| 76 | 
                      #' @inheritParams Parameter-Shared  | 
                  |
| 77 | 
                      #'  | 
                  |
| 78 | 
                      #' @family Parameter  | 
                  |
| 79 | 
                      #' @family as.StanModule  | 
                  |
| 80 | 
                      #' @export  | 
                  |
| 81 | 
                      as.StanModule.Parameter <- function(object, ...) {
                     | 
                  |
| 82 | 645x | 
                      as.StanModule(object@prior, name = object@name)  | 
                  
| 83 | 
                      }  | 
                  |
| 84 | ||
| 85 | ||
| 86 | 
                      #' `Parameter` -> `list`  | 
                  |
| 87 | 
                      #'  | 
                  |
| 88 | 
                      #' Converts a Parameter object to a list of parameter data values  | 
                  |
| 89 | 
                      #' for a Stan model.  | 
                  |
| 90 | 
                      #'  | 
                  |
| 91 | 
                      #' @inheritParams Parameter-Shared  | 
                  |
| 92 | 
                      #'  | 
                  |
| 93 | 
                      #' @family as_stan_list  | 
                  |
| 94 | 
                      #' @family Parameter  | 
                  |
| 95 | 
                      #' @export  | 
                  |
| 96 | 
                      as_stan_list.Parameter <- function(object, ...) {
                     | 
                  |
| 97 | 382x | 
                      as_stan_list(object@prior, name = object@name)  | 
                  
| 98 | 
                      }  | 
                  |
| 99 | ||
| 100 | ||
| 101 | 
                      #' Parameter Getter Functions  | 
                  |
| 102 | 
                      #'  | 
                  |
| 103 | 
                      #' @param x (`Paramater`) \cr A model parameter  | 
                  |
| 104 | 
                      #' @param object (`Paramater`) \cr A model parameter  | 
                  |
| 105 | 
                      #' @param ... Not used.  | 
                  |
| 106 | 
                      #'  | 
                  |
| 107 | 
                      #' @description  | 
                  |
| 108 | 
                      #' Getter functions for the slots of a [`Parameter`] object  | 
                  |
| 109 | 
                      #' @family Parameter  | 
                  |
| 110 | 
                      #' @name Parameter-Getter-Methods  | 
                  |
| 111 | 
                      NULL  | 
                  |
| 112 | ||
| 113 | 
                      #' @describeIn Parameter-Getter-Methods The parameter's name  | 
                  |
| 114 | 
                      #' @export  | 
                  |
| 115 | 10215x | 
                      names.Parameter <- function(x) x@name  | 
                  
| 116 | ||
| 117 | 
                      #' @describeIn Parameter-Getter-Methods The parameter's initial values  | 
                  |
| 118 | 
                      #' @export  | 
                  |
| 119 | 9853x | 
                      initialValues.Parameter <- function(object, ...) initialValues(object@prior)  | 
                  
| 120 | ||
| 121 | 
                      #' @describeIn Parameter-Getter-Methods The parameter's dimensionality  | 
                  |
| 122 | 
                      #' @export  | 
                  |
| 123 | 118x | 
                      size.Parameter <- function(object) object@size  | 
                  
| 124 | ||
| 125 | ||
| 126 | 
                      #' `Parameter` -> `Character`  | 
                  |
| 127 | 
                      #'  | 
                  |
| 128 | 
                      #' Converts a [`Parameter`] object to a character vector  | 
                  |
| 129 | 
                      #' @inheritParams Parameter-Shared  | 
                  |
| 130 | 
                      #' @family Parameter  | 
                  |
| 131 | 
                      #' @export  | 
                  |
| 132 | 
                      as.character.Parameter <- function(x, ...) {
                     | 
                  |
| 133 | 66x | 
                      paste0(x@name, " ~ ", as.character(x@prior))  | 
                  
| 134 | 
                      }  | 
                  |
| 135 | ||
| 136 | ||
| 137 | 
                      #' @rdname show-object  | 
                  |
| 138 | 
                      #' @export  | 
                  |
| 139 | 
                      setMethod(  | 
                  |
| 140 | 
                      f = "show",  | 
                  |
| 141 | 
                      signature = "Parameter",  | 
                  |
| 142 | 
                          definition = function(object) {
                     | 
                  |
| 143 | 1x | 
                              x <- sprintf("\nParameter Object:\n   %s\n\n", as.character(object))
                     | 
                  
| 144 | 1x | 
                      cat(x)  | 
                  
| 145 | 1x | 
                      return(object)  | 
                  
| 146 | 
                      }  | 
                  |
| 147 | 
                      )  | 
                  
| 1 | ||
| 2 | 
                      #' @include Grid.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | ||
| 7 | 
                      #' @rdname Grid-Dev  | 
                  |
| 8 | 
                      .GridEven <- setClass(  | 
                  |
| 9 | 
                      "GridEven",  | 
                  |
| 10 | 
                      contains = "Grid",  | 
                  |
| 11 | 
                      slots = c(  | 
                  |
| 12 | 
                      "subjects" = "character",  | 
                  |
| 13 | 
                      "length.out" = "numeric"  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | ||
| 18 | 
                      #' @rdname Grid-Functions  | 
                  |
| 19 | 
                      #' @export  | 
                  |
| 20 | 
                      GridEven <- function(subjects = NULL, length.out = 30) {
                     | 
                  |
| 21 | 1x | 
                      .GridEven(  | 
                  
| 22 | 1x | 
                      subjects = subjects,  | 
                  
| 23 | 1x | 
                      length.out = length.out  | 
                  
| 24 | 
                      )  | 
                  |
| 25 | 
                      }  | 
                  |
| 26 | ||
| 27 | ||
| 28 | 
                      setValidity(  | 
                  |
| 29 | 
                      "GridEven",  | 
                  |
| 30 | 
                          function(object) {
                     | 
                  |
| 31 | 
                              if (length(object@length.out) != 1 || all(object@length.out <= 0)) {
                     | 
                  |
| 32 | 
                                  return("The `length.out` argument must be a positive integer")
                     | 
                  |
| 33 | 
                      }  | 
                  |
| 34 | 
                      }  | 
                  |
| 35 | 
                      )  | 
                  |
| 36 | ||
| 37 | ||
| 38 | 
                      #' @rdname Quant-Dev  | 
                  |
| 39 | 
                      #' @export  | 
                  |
| 40 | 
                      as.QuantityGenerator.GridEven <- function(object, data, ...) {
                     | 
                  |
| 41 | 2x | 
                      assert_class(data, "DataJoint")  | 
                  
| 42 | 2x | 
                      data_list <- as.list(data)  | 
                  
| 43 | 2x | 
                      subjects <- unlist(as.list(object, data = data), use.names = FALSE)  | 
                  
| 44 | 2x | 
                      assert_that(  | 
                  
| 45 | 2x | 
                      all(subjects %in% names(data_list$subject_to_index)),  | 
                  
| 46 | 2x | 
                      msg = "All subject names must be in the `DataSubject` object"  | 
                  
| 47 | 
                      )  | 
                  |
| 48 | ||
| 49 | 2x | 
                      spec <- lapply(  | 
                  
| 50 | 2x | 
                      subjects,  | 
                  
| 51 | 2x | 
                              \(sub) {
                     | 
                  
| 52 | 4x | 
                      subject_index <- data_list$subject_to_index[[sub]]  | 
                  
| 53 | 4x | 
                      time_index <- data_list$subject_tumour_index == subject_index  | 
                  
| 54 | 4x | 
                      subject_times <- data_list$tumour_time[time_index]  | 
                  
| 55 | 4x | 
                      seq(min(subject_times), max(subject_times), length.out = object@length.out)  | 
                  
| 56 | 
                      }  | 
                  |
| 57 | 
                      )  | 
                  |
| 58 | 2x | 
                      names(spec) <- subjects  | 
                  
| 59 | ||
| 60 | 2x | 
                      as.QuantityGenerator(  | 
                  
| 61 | 2x | 
                      GridManual(spec),  | 
                  
| 62 | 2x | 
                      data = data  | 
                  
| 63 | 
                      )  | 
                  |
| 64 | 
                      }  | 
                  |
| 65 | ||
| 66 | ||
| 67 | 
                      #' @rdname Quant-Dev  | 
                  |
| 68 | 
                      #' @export  | 
                  |
| 69 | 
                      as.QuantityCollapser.GridEven <- function(object, data, ...) {
                     | 
                  |
| 70 | 1x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 71 | 1x | 
                      QuantityCollapser(  | 
                  
| 72 | 1x | 
                      times = generator@times,  | 
                  
| 73 | 1x | 
                      groups = generator@subjects,  | 
                  
| 74 | 1x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 75 | 
                      )  | 
                  |
| 76 | 
                      }  | 
                  |
| 77 | ||
| 78 | ||
| 79 | 
                      #' @export  | 
                  |
| 80 | 
                      as.list.GridEven <- function(x, data, ...) {
                     | 
                  |
| 81 | 2x | 
                      subjects_to_list(x@subjects, data)  | 
                  
| 82 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Grid.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | ||
| 6 | 
                      #' @rdname Quant-Dev  | 
                  |
| 7 | 
                      .QuantityGeneratorSubject <- setClass(  | 
                  |
| 8 | 
                      "QuantityGeneratorSubject",  | 
                  |
| 9 | 
                      contains = "QuantityGenerator",  | 
                  |
| 10 | 
                      slots = c(  | 
                  |
| 11 | 
                      "times" = "numeric",  | 
                  |
| 12 | 
                      "subjects" = "character_or_NULL"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | ||
| 17 | 
                      #' @rdname Quant-Dev  | 
                  |
| 18 | 
                      QuantityGeneratorSubject <- function(times, subjects = NULL) {
                     | 
                  |
| 19 | 78x | 
                      .QuantityGeneratorSubject(  | 
                  
| 20 | 78x | 
                      times = times,  | 
                  
| 21 | 78x | 
                      subjects = subjects  | 
                  
| 22 | 
                      )  | 
                  |
| 23 | 
                      }  | 
                  |
| 24 | ||
| 25 | ||
| 26 | 
                      setValidity(  | 
                  |
| 27 | 
                      "QuantityGeneratorSubject",  | 
                  |
| 28 | 
                          function(object) {
                     | 
                  |
| 29 | 
                              if (length(object@times) != length(object@subjects)) {
                     | 
                  |
| 30 | 
                                  return("Length of `times` and `subjects` must be equal")
                     | 
                  |
| 31 | 
                      }  | 
                  |
| 32 | 
                      return(TRUE)  | 
                  |
| 33 | 
                      }  | 
                  |
| 34 | 
                      )  | 
                  |
| 35 | ||
| 36 | ||
| 37 | 
                      #' @rdname as_stan_list.QuantityGenerator  | 
                  |
| 38 | 
                      #' @export  | 
                  |
| 39 | 
                      as_stan_list.QuantityGeneratorSubject <- function(object, data, ...) {
                     | 
                  |
| 40 | 26x | 
                      assert_that(  | 
                  
| 41 | 26x | 
                      is(data, "DataJoint")  | 
                  
| 42 | 
                      )  | 
                  |
| 43 | 26x | 
                      ret <- list()  | 
                  
| 44 | 26x | 
                      data_list <- as.list(data)  | 
                  
| 45 | 26x | 
                      ret[["gq_subject_index"]] <- data_list$subject_to_index[as.character(object@subjects)]  | 
                  
| 46 | 26x | 
                      ret[["gq_n_quant"]] <- length(object@subjects)  | 
                  
| 47 | 26x | 
                      ret[["gq_times"]] <- object@times  | 
                  
| 48 | ||
| 49 | 
                      # dummy pop indexes in order for stan code to actualy compile. In this setting  | 
                  |
| 50 | 
                      # this matrix isn't actually used so doesn't matter what these values are  | 
                  |
| 51 | 
                      # but don't want to have to burden individual longitudinal models with the  | 
                  |
| 52 | 
                      # conditional logic to check if they are generating population quantities or not  | 
                  |
| 53 | 26x | 
                      ret[["gq_long_pop_arm_index"]] <- rep(1, ret[["gq_n_quant"]])  | 
                  
| 54 | 26x | 
                      ret[["gq_long_pop_study_index"]] <- rep(1, ret[["gq_n_quant"]])  | 
                  
| 55 | ||
| 56 | 
                      # Sanity checks  | 
                  |
| 57 | 26x | 
                      assert_that(  | 
                  
| 58 | 26x | 
                      length(ret[["gq_times"]]) == ret[["gq_n_quant"]],  | 
                  
| 59 | 26x | 
                      all(object@subjects %in% names(data_list$subject_to_index))  | 
                  
| 60 | 
                      )  | 
                  |
| 61 | 26x | 
                      return(ret)  | 
                  
| 62 | 
                      }  | 
                  
| 1 | 
                      #' @include Grid.R  | 
                  |
| 2 | 
                      #' @include generics.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | ||
| 6 | 
                      #' @rdname Grid-Dev  | 
                  |
| 7 | 
                      .GridFixed <- setClass(  | 
                  |
| 8 | 
                      "GridFixed",  | 
                  |
| 9 | 
                      contains = "Grid",  | 
                  |
| 10 | 
                      slots = c(  | 
                  |
| 11 | 
                      "subjects" = "character_or_NULL",  | 
                  |
| 12 | 
                      "times" = "numeric_or_NULL"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | 
                      #' @rdname Grid-Functions  | 
                  |
| 17 | 
                      #' @export  | 
                  |
| 18 | 
                      GridFixed <- function(subjects = NULL, times = NULL) {
                     | 
                  |
| 19 | 42x | 
                      .GridFixed(  | 
                  
| 20 | 42x | 
                      subjects = subjects,  | 
                  
| 21 | 42x | 
                      times = times  | 
                  
| 22 | 
                      )  | 
                  |
| 23 | 
                      }  | 
                  |
| 24 | ||
| 25 | 
                      #' @rdname Quant-Dev  | 
                  |
| 26 | 
                      #' @export  | 
                  |
| 27 | 
                      as.QuantityGenerator.GridFixed <- function(object, data, ...) {
                     | 
                  |
| 28 | ||
| 29 | 54x | 
                      assert_class(data, "DataJoint")  | 
                  
| 30 | 54x | 
                      data_list <- as.list(data)  | 
                  
| 31 | 54x | 
                      subjects <- unlist(as.list(object, data = data), use.names = FALSE)  | 
                  
| 32 | ||
| 33 | 54x | 
                      validate_time_grid(object@times)  | 
                  
| 34 | 54x | 
                      subject_times <- expand.grid(  | 
                  
| 35 | 54x | 
                      subject = subjects,  | 
                  
| 36 | 54x | 
                      time = object@times,  | 
                  
| 37 | 54x | 
                      stringsAsFactors = FALSE  | 
                  
| 38 | 
                      )  | 
                  |
| 39 | ||
| 40 | 54x | 
                      QuantityGeneratorSubject(  | 
                  
| 41 | 54x | 
                      times = subject_times$time,  | 
                  
| 42 | 54x | 
                      subjects = subject_times$subject  | 
                  
| 43 | 
                      )  | 
                  |
| 44 | 
                      }  | 
                  |
| 45 | ||
| 46 | 
                      #' @rdname Quant-Dev  | 
                  |
| 47 | 
                      #' @export  | 
                  |
| 48 | 
                      as.QuantityCollapser.GridFixed <- function(object, data, ...) {
                     | 
                  |
| 49 | 18x | 
                      generator <- as.QuantityGenerator(object, data)  | 
                  
| 50 | 18x | 
                      QuantityCollapser(  | 
                  
| 51 | 18x | 
                      times = generator@times,  | 
                  
| 52 | 18x | 
                      groups = generator@subjects,  | 
                  
| 53 | 18x | 
                      indexes = as.list(seq_along(generator@times))  | 
                  
| 54 | 
                      )  | 
                  |
| 55 | 
                      }  | 
                  |
| 56 | ||
| 57 | ||
| 58 | 
                      #' @export  | 
                  |
| 59 | 
                      as.list.GridFixed <- function(x, data, ...) {
                     | 
                  |
| 60 | 54x | 
                      subjects_to_list(x@subjects, data)  | 
                  
| 61 | 
                      }  | 
                  |
| 62 | ||
| 63 | 
                      #' @rdname coalesceGridTime  | 
                  |
| 64 | 
                      #' @export  | 
                  |
| 65 | 
                      coalesceGridTime.GridFixed <- function(object, times, ...) {
                     | 
                  |
| 66 | 19x | 
                          if (is.null(object@times)) {
                     | 
                  
| 67 | 5x | 
                      object <- GridFixed(  | 
                  
| 68 | 5x | 
                      subjects = object@subjects,  | 
                  
| 69 | 5x | 
                      times = times  | 
                  
| 70 | 
                      )  | 
                  |
| 71 | 
                      }  | 
                  |
| 72 | 19x | 
                      object  | 
                  
| 73 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | ||
| 5 | ||
| 6 | 
                      #' Standard Links  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' @param prior ([`Prior`]) \cr A [`Prior`] object.  | 
                  |
| 9 | 
                      #' @param model ([`LongitudinalModel`]) \cr A [`LongitudinalModel`] object.  | 
                  |
| 10 | 
                      #' @param ... Not used.  | 
                  |
| 11 | 
                      #'  | 
                  |
| 12 | 
                      #' @description  | 
                  |
| 13 | 
                      #' These functions are used to enable the use of the corresponding link function between  | 
                  |
| 14 | 
                      #' the survival and longitudinal models in a joint model. Note that the exact implementation  | 
                  |
| 15 | 
                      #' of the link function is model specific, see  | 
                  |
| 16 | 
                      #' \code{vignette("Statistical Specifications", package = "jmpost")} for more details.
                     | 
                  |
| 17 | 
                      #'  | 
                  |
| 18 | 
                      #' @name standard-link-user  | 
                  |
| 19 | 
                      NULL  | 
                  |
| 20 | ||
| 21 | ||
| 22 | ||
| 23 | ||
| 24 | 
                      #' @describeIn standard-link-user No link (fit the survival and longitudinal models independently)  | 
                  |
| 25 | 
                      #' @export  | 
                  |
| 26 | 
                      linkNone <- function() {
                     | 
                  |
| 27 | 1x | 
                      Link()  | 
                  
| 28 | 
                      }  | 
                  |
| 29 | ||
| 30 | ||
| 31 | 
                      #' @describeIn standard-link-user Time to growth link  | 
                  |
| 32 | 
                      #' @export  | 
                  |
| 33 | 
                      linkTTG <- function(prior, model = PromiseLongitudinalModel(), ...) {
                     | 
                  |
| 34 | 12x | 
                          UseMethod("linkTTG", model)
                     | 
                  
| 35 | 
                      }  | 
                  |
| 36 | 
                      #' @export  | 
                  |
| 37 | 
                      linkTTG.PromiseLongitudinalModel <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 38 | 5x | 
                      PromiseLinkComponent(fun = linkTTG, prior = prior, key = "link_ttg")  | 
                  
| 39 | 
                      }  | 
                  |
| 40 | 
                      #' @export  | 
                  |
| 41 | 
                      linkTTG.default <- function(prior, model, ...) {
                     | 
                  |
| 42 | 1x | 
                          stop(sprintf("Method `linkTTG` is not available for `%s`", class(model)[[1]]))
                     | 
                  
| 43 | 
                      }  | 
                  |
| 44 | ||
| 45 | ||
| 46 | ||
| 47 | ||
| 48 | 
                      #' @describeIn standard-link-user Derivative of the SLD over time link  | 
                  |
| 49 | 
                      #' @export  | 
                  |
| 50 | 
                      linkDSLD <- function(prior, model = PromiseLongitudinalModel(), ...) {
                     | 
                  |
| 51 | 29x | 
                          UseMethod("linkDSLD", model)
                     | 
                  
| 52 | 
                      }  | 
                  |
| 53 | 
                      #' @export  | 
                  |
| 54 | 
                      linkDSLD.PromiseLongitudinalModel <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 55 | 15x | 
                      PromiseLinkComponent(fun = linkDSLD, prior = prior, key = "link_dsld")  | 
                  
| 56 | 
                      }  | 
                  |
| 57 | 
                      #' @export  | 
                  |
| 58 | 
                      linkDSLD.default <- function(prior, model, ...) {
                     | 
                  |
| 59 | ! | 
                          stop(sprintf("Method `linkDSLD` is not available for `%s`", class(model)[[1]]))
                     | 
                  
| 60 | 
                      }  | 
                  |
| 61 | ||
| 62 | ||
| 63 | ||
| 64 | ||
| 65 | 
                      #' @describeIn standard-link-user Current SLD value link  | 
                  |
| 66 | 
                      #' @export  | 
                  |
| 67 | 
                      linkIdentity <- function(prior, model = PromiseLongitudinalModel(), ...) {
                     | 
                  |
| 68 | 8x | 
                          UseMethod("linkIdentity", model)
                     | 
                  
| 69 | 
                      }  | 
                  |
| 70 | 
                      #' @export  | 
                  |
| 71 | 
                      linkIdentity.PromiseLongitudinalModel <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 72 | 3x | 
                      PromiseLinkComponent(fun = linkIdentity, prior = prior, key = "link_identity")  | 
                  
| 73 | 
                      }  | 
                  |
| 74 | 
                      #' @export  | 
                  |
| 75 | 
                      linkIdentity.default <- function(prior, model, ...) {
                     | 
                  |
| 76 | ! | 
                          stop(sprintf("Method `linkIdentity` is not available for `%s`", class(model)[[1]]))
                     | 
                  
| 77 | 
                      }  | 
                  |
| 78 | ||
| 79 | ||
| 80 | 
                      #' @describeIn standard-link-user Growth Parameter link  | 
                  |
| 81 | 
                      #' @export  | 
                  |
| 82 | 
                      linkGrowth <- function(prior, model = PromiseLongitudinalModel(), ...) {
                     | 
                  |
| 83 | 6x | 
                          UseMethod("linkGrowth", model)
                     | 
                  
| 84 | 
                      }  | 
                  |
| 85 | 
                      #' @export  | 
                  |
| 86 | 
                      linkGrowth.PromiseLongitudinalModel <- function(prior = prior_normal(0, 2), model, ...) {
                     | 
                  |
| 87 | 3x | 
                      PromiseLinkComponent(fun = linkGrowth, prior = prior, key = "link_growth")  | 
                  
| 88 | 
                      }  | 
                  |
| 89 | 
                      #' @export  | 
                  |
| 90 | 
                      linkGrowth.default <- function(prior, model, ...) {
                     | 
                  |
| 91 | ! | 
                          stop(sprintf("Method `linkGrowth` is not available for `%s`", class(model)[[1]]))
                     | 
                  
| 92 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      .onLoad <- function(libname, pkgname) {
                     | 
                  |
| 3 | ! | 
                      set_options()  | 
                  
| 4 | 
                      }  | 
                  |
| 5 | ||
| 6 | 
                      .onAttach <- function(libname, pkgname) {
                     | 
                  |
| 7 | 4x | 
                          if (!is_cmdstanr_available()) {
                     | 
                  
| 8 | ! | 
                      packageStartupMessage(  | 
                  
| 9 | ! | 
                      "jmpost uses cmdstanr for compiling and sampling from models, but it does not seem to be installed.\n",  | 
                  
| 10 | ! | 
                      "To install:\n",  | 
                  
| 11 | ! | 
                      "install.packages(\"cmdstanr\", repos = c(\"https://stan-dev.r-universe.dev/\", getOption(\"repos\")))"  | 
                  
| 12 | 
                      )  | 
                  |
| 13 | 4x | 
                          } else if (is.null(cmdstanr::cmdstan_version(error_on_NA = FALSE))) {
                     | 
                  
| 14 | ! | 
                      possible_paths <- unique(c(  | 
                  
| 15 | ! | 
                      cmdstanr::cmdstan_default_install_path(),  | 
                  
| 16 | ! | 
                                  Sys.getenv("CMDSTAN"),
                     | 
                  
| 17 | ! | 
                                  Sys.getenv("CMDSTAN_PATH"),
                     | 
                  
| 18 | ! | 
                      "/root/.cmdstan",  | 
                  
| 19 | ! | 
                      "~/.cmdstan"  | 
                  
| 20 | 
                      ))  | 
                  |
| 21 | ! | 
                      possible_paths <- possible_paths[dir.exists(possible_paths)]  | 
                  
| 22 | ||
| 23 | ! | 
                              if (length(possible_paths)) {
                     | 
                  
| 24 | ! | 
                                  for (try_path in possible_paths) {
                     | 
                  
| 25 | ! | 
                      new_path <- tryCatch(  | 
                  
| 26 | ! | 
                      suppressMessages(cmdstanr::set_cmdstan_path(try_path)),  | 
                  
| 27 | ! | 
                      warning = function(w) NULL,  | 
                  
| 28 | ! | 
                      error = function(e) NULL  | 
                  
| 29 | 
                      )  | 
                  |
| 30 | 
                      }  | 
                  |
| 31 | ! | 
                                  if (!is.null(new_path)) {
                     | 
                  
| 32 | ! | 
                                      packageStartupMessage("CmdStan path set to: ", new_path)
                     | 
                  
| 33 | 
                      }  | 
                  |
| 34 | 
                              } else {
                     | 
                  |
| 35 | ! | 
                                  packageStartupMessage("jmpost could not identify CmdStan path. Please use cmdstanr::set_cmdstan_path()")
                     | 
                  
| 36 | 
                      }  | 
                  |
| 37 | 
                      }  | 
                  |
| 38 | 4x | 
                      return(invisible(NULL))  | 
                  
| 39 | 
                      }  | 
                  |
| 40 | ||
| 41 | ||
| 42 | 
                      # This only exists to silence the false positive R CMD CHECK warning about  | 
                  |
| 43 | 
                      # importing but not using the posterior package. posterior is a dependency  | 
                  |
| 44 | 
                      # of rcmdstan that we use a lot implicitly. Also we link to their documentation  | 
                  |
| 45 | 
                      # pages in ours  | 
                  |
| 46 | 
                      .never_run <- function() {
                     | 
                  |
| 47 | ! | 
                      posterior::as_draws()  | 
                  
| 48 | 
                      }  | 
                  
| 1 | 
                      #' @include StanModel.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # SurvivalModel-class ----  | 
                  |
| 5 | ||
| 6 | 
                      #' `SurvivalModel`  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' This class extends the general [`StanModel`] class to comprise the survival  | 
                  |
| 9 | 
                      #' model specification.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @exportClass SurvivalModel  | 
                  |
| 12 | 
                      .SurvivalModel <- setClass(  | 
                  |
| 13 | 
                      Class = "SurvivalModel",  | 
                  |
| 14 | 
                      contains = "StanModel"  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | 
                      # SurvivalModel-constructors ----  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname SurvivalModel-class  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @inheritParams stanmodel_arguments  | 
                  |
| 22 | 
                      #'  | 
                  |
| 23 | 
                      #' @export  | 
                  |
| 24 | 
                      SurvivalModel <- function(  | 
                  |
| 25 | 
                      stan = StanModule(),  | 
                  |
| 26 | 
                      parameters = ParameterList(),  | 
                  |
| 27 | 
                      name = "<Unnamed>",  | 
                  |
| 28 | 
                      ...  | 
                  |
| 29 | 
                      ) {
                     | 
                  |
| 30 | 28x | 
                          base_stan <- read_stan("base/survival.stan")
                     | 
                  
| 31 | 28x | 
                      stan_full <- decorated_render(  | 
                  
| 32 | 28x | 
                      .x = base_stan,  | 
                  
| 33 | 28x | 
                      stan = add_missing_stan_blocks(as.list(stan))  | 
                  
| 34 | 
                      )  | 
                  |
| 35 | 28x | 
                      .SurvivalModel(  | 
                  
| 36 | 28x | 
                      StanModel(  | 
                  
| 37 | 28x | 
                      name = name,  | 
                  
| 38 | 28x | 
                      stan = StanModule(stan_full),  | 
                  
| 39 | 28x | 
                      parameters = parameters,  | 
                  
| 40 | 
                      ...  | 
                  |
| 41 | 
                      )  | 
                  |
| 42 | 
                      )  | 
                  |
| 43 | 
                      }  | 
                  |
| 44 | ||
| 45 | 
                      #' @export  | 
                  |
| 46 | 
                      as_print_string.SurvivalModel <- function(object, ...) {
                     | 
                  |
| 47 | 4x | 
                      string <- sprintf(  | 
                  
| 48 | 4x | 
                      "\n%s Survival Model with parameters:\n%s\n\n",  | 
                  
| 49 | 4x | 
                      object@name,  | 
                  
| 50 | 4x | 
                              paste("   ", as_print_string(object@parameters)) |> paste(collapse = "\n")
                     | 
                  
| 51 | 
                      )  | 
                  |
| 52 | 4x | 
                      return(string)  | 
                  
| 53 | 
                      }  | 
                  
| 1 | 
                      #' @include StanModule.R  | 
                  |
| 2 | 
                      #' @include LongitudinalModel.R  | 
                  |
| 3 | 
                      #' @include ParameterList.R  | 
                  |
| 4 | 
                      #' @include generics.R  | 
                  |
| 5 | 
                      #' @include Prior.R  | 
                  |
| 6 | 
                      NULL  | 
                  |
| 7 | ||
| 8 | ||
| 9 | ||
| 10 | ||
| 11 | 
                      #' `LinkComponent` Function Arguments  | 
                  |
| 12 | 
                      #'  | 
                  |
| 13 | 
                      #' This exists to contain all the common arguments for [`LinkComponent`] methods.  | 
                  |
| 14 | 
                      #'  | 
                  |
| 15 | 
                      #' @param stan (`StanModule`)\cr Stan code.  | 
                  |
| 16 | 
                      #' @param x ([`LinkComponent`])\cr a link component.  | 
                  |
| 17 | 
                      #' @param object ([`LinkComponent`])\cr a link component.  | 
                  |
| 18 | 
                      #' @param ... Not Used.  | 
                  |
| 19 | 
                      #'  | 
                  |
| 20 | 
                      #' @name LinkComponent-Shared  | 
                  |
| 21 | 
                      #' @keywords internal  | 
                  |
| 22 | 
                      NULL  | 
                  |
| 23 | ||
| 24 | ||
| 25 | ||
| 26 | ||
| 27 | 
                      #' `LinkComponent`  | 
                  |
| 28 | 
                      #'  | 
                  |
| 29 | 
                      #' @slot stan (`StanModule`)\cr See Arguments.  | 
                  |
| 30 | 
                      #' @slot name (`character`)\cr See Arguments.  | 
                  |
| 31 | 
                      #' @slot parameters (`ParameterList`)\cr The parameter specification.  | 
                  |
| 32 | 
                      #'  | 
                  |
| 33 | 
                      #' @param stan (`StanModule`)\cr Stan code. See Details.  | 
                  |
| 34 | 
                      #' @param prior (`Prior`)\cr The prior for the scaling coeficient.  | 
                  |
| 35 | 
                      #' @param key (`character`)\cr Link identifier. See Details.  | 
                  |
| 36 | 
                      #'  | 
                  |
| 37 | 
                      #' @details  | 
                  |
| 38 | 
                      #'  | 
                  |
| 39 | 
                      #' This object provides key information needed to construct a link contribution in the  | 
                  |
| 40 | 
                      #' survival model based on the parameters of the longitudinal model.  | 
                  |
| 41 | 
                      #'  | 
                  |
| 42 | 
                      #' Each link component defines a stan function of the longitudinal model parameters which is  | 
                  |
| 43 | 
                      #' multiplied by a model coefficient and added to the survival models hazard function.  | 
                  |
| 44 | 
                      #'  | 
                  |
| 45 | 
                      #' For full details about the specification of a `LinkComponent` please see  | 
                  |
| 46 | 
                      #' \code{vignette("extending-jmpost", package = "jmpost")}.
                     | 
                  |
| 47 | 
                      #'  | 
                  |
| 48 | 
                      #' @inheritParams stanmodel_arguments  | 
                  |
| 49 | 
                      #' @family LinkComponent  | 
                  |
| 50 | 
                      #' @name LinkComponent-class  | 
                  |
| 51 | 
                      #' @exportClass Link  | 
                  |
| 52 | 
                      .LinkComponent <- setClass(  | 
                  |
| 53 | 
                      Class = "LinkComponent",  | 
                  |
| 54 | 
                      slots = list(  | 
                  |
| 55 | 
                      "stan" = "StanModule",  | 
                  |
| 56 | 
                      "parameters" = "ParameterList",  | 
                  |
| 57 | 
                      "key" = "character"  | 
                  |
| 58 | 
                      )  | 
                  |
| 59 | 
                      )  | 
                  |
| 60 | ||
| 61 | ||
| 62 | 
                      #' @rdname LinkComponent-class  | 
                  |
| 63 | 
                      #' @export  | 
                  |
| 64 | 
                      LinkComponent <- function(stan, prior, key, ...) {
                     | 
                  |
| 65 | 31x | 
                      .LinkComponent(  | 
                  
| 66 | 31x | 
                      stan = stan,  | 
                  
| 67 | 31x | 
                      key = key,  | 
                  
| 68 | 31x | 
                      parameters = ParameterList(Parameter(name = key, prior = prior, size = 1)),  | 
                  
| 69 | 
                      ...  | 
                  |
| 70 | 
                      )  | 
                  |
| 71 | 
                      }  | 
                  |
| 72 | ||
| 73 | ||
| 74 | ||
| 75 | ||
| 76 | 
                      #' @family LinkComponent  | 
                  |
| 77 | 
                      #' @rdname getParameters  | 
                  |
| 78 | 
                      #' @export  | 
                  |
| 79 | 
                      getParameters.LinkComponent <- function(object, ...) {
                     | 
                  |
| 80 | 25x | 
                      object@parameters  | 
                  
| 81 | 
                      }  | 
                  |
| 82 | ||
| 83 | ||
| 84 | 
                      #' @family LinkComponent  | 
                  |
| 85 | 
                      #' @rdname initialValues  | 
                  |
| 86 | 
                      #' @export  | 
                  |
| 87 | 
                      initialValues.LinkComponent <- function(object, n_chains, ...) {
                     | 
                  |
| 88 | ! | 
                      initialValues(object@parameters, n_chains)  | 
                  
| 89 | 
                      }  | 
                  |
| 90 | ||
| 91 | ||
| 92 | ||
| 93 | ||
| 94 | 
                      #' `LinkComponent` -> `StanModule`  | 
                  |
| 95 | 
                      #'  | 
                  |
| 96 | 
                      #' Converts a [`LinkComponent`] object to a [`StanModule`] object  | 
                  |
| 97 | 
                      #'  | 
                  |
| 98 | 
                      #' @inheritParams LinkComponent-Shared  | 
                  |
| 99 | 
                      #'  | 
                  |
| 100 | 
                      #' @family LinkComponent  | 
                  |
| 101 | 
                      #' @family as.StanModule  | 
                  |
| 102 | 
                      #' @export  | 
                  |
| 103 | 
                      as.StanModule.LinkComponent <- function(object, ...) {
                     | 
                  |
| 104 | 30x | 
                      object@stan  | 
                  
| 105 | 
                      }  | 
                  |
| 106 | ||
| 107 | ||
| 108 | ||
| 109 | 
                      #' `LinkComponent` -> `list`  | 
                  |
| 110 | 
                      #'  | 
                  |
| 111 | 
                      #' @inheritParams LinkComponent-Shared  | 
                  |
| 112 | 
                      #'  | 
                  |
| 113 | 
                      #' @description  | 
                  |
| 114 | 
                      #' Returns a named list where each element of the list corresponds  | 
                  |
| 115 | 
                      #' to a Stan modelling block e.g. `data`, `model`, etc.  | 
                  |
| 116 | 
                      #'  | 
                  |
| 117 | 
                      #' @family LinkComponent  | 
                  |
| 118 | 
                      #' @export  | 
                  |
| 119 | 
                      as.list.LinkComponent <- function(x, ...) {
                     | 
                  |
| 120 | ! | 
                      stan <- as.StanModule(x, ...)  | 
                  
| 121 | ! | 
                      as.list(stan)  | 
                  
| 122 | 
                      }  | 
                  |
| 123 | ||
| 124 | 
                      #' @family LinkComponent  | 
                  |
| 125 | 
                      #' @export  | 
                  |
| 126 | 
                      as_print_string.LinkComponent <- function(object, ...) {
                     | 
                  |
| 127 | 2x | 
                      as_print_string(object@parameters)  | 
                  
| 128 | 
                      }  | 
                  |
| 129 | ||
| 130 | ||
| 131 | 
                      #' @rdname show-object  | 
                  |
| 132 | 
                      #' @export  | 
                  |
| 133 | 
                      setMethod(  | 
                  |
| 134 | 
                      f = "show",  | 
                  |
| 135 | 
                      signature = "LinkComponent",  | 
                  |
| 136 | 
                          definition = function(object) {
                     | 
                  |
| 137 | 1x | 
                      cat(  | 
                  
| 138 | 1x | 
                      paste0(  | 
                  
| 139 | 1x | 
                      "\nLinkComponent with parameter:\n ",  | 
                  
| 140 | 1x | 
                      as_print_string(object), "\n\n"  | 
                  
| 141 | 
                      )  | 
                  |
| 142 | 
                      )  | 
                  |
| 143 | 
                      }  | 
                  |
| 144 | 
                      )  | 
                  |
| 145 | ||
| 146 | 
                      #' @family LinkComponent  | 
                  |
| 147 | 
                      #' @export  | 
                  |
| 148 | 
                      names.LinkComponent <- function(x, ...) {
                     | 
                  |
| 149 | 50x | 
                      names(x@parameters)  | 
                  
| 150 | 
                      }  | 
                  
| 1 | 
                      #' @include generics.R  | 
                  |
| 2 | 
                      #' @include Grid.R  | 
                  |
| 3 | 
                      NULL  | 
                  |
| 4 | ||
| 5 | 
                      #' @rdname Quant-Dev  | 
                  |
| 6 | 
                      .QuantityGeneratorPopulation <- setClass(  | 
                  |
| 7 | 
                      "QuantityGeneratorPopulation",  | 
                  |
| 8 | 
                      contains = "QuantityGenerator",  | 
                  |
| 9 | 
                      slots = c(  | 
                  |
| 10 | 
                      "times" = "numeric",  | 
                  |
| 11 | 
                      "studies" = "character_or_NULL",  | 
                  |
| 12 | 
                      "arms" = "character_or_NULL"  | 
                  |
| 13 | 
                      )  | 
                  |
| 14 | 
                      )  | 
                  |
| 15 | ||
| 16 | ||
| 17 | 
                      #' @rdname Quant-Dev  | 
                  |
| 18 | 
                      QuantityGeneratorPopulation <- function(times, studies = NULL, arms = NULL) {
                     | 
                  |
| 19 | 8x | 
                      .QuantityGeneratorPopulation(  | 
                  
| 20 | 8x | 
                      times = times,  | 
                  
| 21 | 8x | 
                      studies = studies,  | 
                  
| 22 | 8x | 
                      arms = arms  | 
                  
| 23 | 
                      )  | 
                  |
| 24 | 
                      }  | 
                  |
| 25 | ||
| 26 | ||
| 27 | 
                      setValidity(  | 
                  |
| 28 | 
                      "QuantityGeneratorPopulation",  | 
                  |
| 29 | 
                          function(object) {
                     | 
                  |
| 30 | 
                              if (length(object@times) != length(object@arms)) {
                     | 
                  |
| 31 | 
                                  return("Length of `times` and `arms` must be equal")
                     | 
                  |
| 32 | 
                      }  | 
                  |
| 33 | 
                              if (length(object@times) != length(object@studies)) {
                     | 
                  |
| 34 | 
                                  return("Length of `times` and `studies` must be equal")
                     | 
                  |
| 35 | 
                      }  | 
                  |
| 36 | 
                      return(TRUE)  | 
                  |
| 37 | 
                      }  | 
                  |
| 38 | 
                      )  | 
                  |
| 39 | ||
| 40 | ||
| 41 | 
                      #' @rdname as_stan_list.QuantityGenerator  | 
                  |
| 42 | 
                      #' @export  | 
                  |
| 43 | 
                      as_stan_list.QuantityGeneratorPopulation <- function(object, data, ...) {
                     | 
                  |
| 44 | 2x | 
                      assert_that(  | 
                  
| 45 | 2x | 
                      is(data, "DataJoint")  | 
                  
| 46 | 
                      )  | 
                  |
| 47 | 2x | 
                      ret <- list()  | 
                  
| 48 | 2x | 
                      data_list <- as.list(data)  | 
                  
| 49 | 2x | 
                      ret[["gq_times"]] <- object@times  | 
                  
| 50 | 2x | 
                      ret[["gq_n_quant"]] <- length(object@arms)  | 
                  
| 51 | 2x | 
                      ret[["gq_long_pop_arm_index"]] <- data_list$arm_to_index[object@arms]  | 
                  
| 52 | 2x | 
                      ret[["gq_long_pop_study_index"]] <- data_list$study_to_index[object@studies]  | 
                  
| 53 | ||
| 54 | 
                      # Sanity checks  | 
                  |
| 55 | 2x | 
                      assert_that(  | 
                  
| 56 | 2x | 
                      length(ret[["gq_long_pop_arm_index"]]) == length(ret[["gq_long_pop_study_index"]]),  | 
                  
| 57 | 2x | 
                      length(ret[["gq_long_pop_study_index"]]) == length(ret[["gq_times"]]),  | 
                  
| 58 | 2x | 
                      length(ret[["gq_long_pop_study_index"]]) == ret[["gq_n_quant"]],  | 
                  
| 59 | 2x | 
                      all(!is.na(ret[["gq_long_pop_arm_index"]])),  | 
                  
| 60 | 2x | 
                      all(!is.na(ret[["gq_long_pop_study_index"]]))  | 
                  
| 61 | 
                      )  | 
                  |
| 62 | 2x | 
                      return(ret)  | 
                  
| 63 | 
                      }  | 
                  
| 1 | 
                      #' @include SurvivalModel.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # SurvivalLogLogistic-class ----  | 
                  |
| 5 | ||
| 6 | 
                      #' `SurvivalLogLogistic`  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' This class extends the general [`SurvivalModel`] class for using the  | 
                  |
| 9 | 
                      #' log-logistic survival model.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @exportClass SurvivalLogLogistic  | 
                  |
| 12 | 
                      .SurvivalLogLogistic <- setClass(  | 
                  |
| 13 | 
                      Class = "SurvivalLogLogistic",  | 
                  |
| 14 | 
                      contains = "SurvivalModel"  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | 
                      # SurvivalLogLogistic-constructors ----  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname SurvivalLogLogistic-class  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @param a (`Prior`)\cr Prior distribution for the scale parameter `a`.  | 
                  |
| 22 | 
                      #' @param b (`Prior`)\cr Prior distribution for the shape parameter `b`.  | 
                  |
| 23 | 
                      #' @param beta (`Prior`)\cr Prior distribution for covariates coefficients `beta`.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @export  | 
                  |
| 26 | 
                      SurvivalLogLogistic <- function(  | 
                  |
| 27 | 
                      a = prior_lognormal(log(0.1), 5),  | 
                  |
| 28 | 
                      b = prior_gamma(2, 5),  | 
                  |
| 29 | 
                      beta = prior_normal(0, 2)  | 
                  |
| 30 | 
                      ) {
                     | 
                  |
| 31 | 4x | 
                      .SurvivalLogLogistic(  | 
                  
| 32 | 4x | 
                      SurvivalModel(  | 
                  
| 33 | 4x | 
                      name = "Log-Logistic",  | 
                  
| 34 | 4x | 
                                  stan = StanModule("sm-loglogistic/model.stan"),
                     | 
                  
| 35 | 4x | 
                      parameters = ParameterList(  | 
                  
| 36 | 4x | 
                      Parameter(name = "sm_loglogis_a", prior = a, size = 1),  | 
                  
| 37 | 4x | 
                      Parameter(name = "sm_loglogis_b", prior = b, size = 1),  | 
                  
| 38 | 4x | 
                      Parameter(name = "beta_os_cov", prior = beta, size = "p_os_cov_design")  | 
                  
| 39 | 
                      )  | 
                  |
| 40 | 
                      )  | 
                  |
| 41 | 
                      )  | 
                  |
| 42 | 
                      }  | 
                  
| 1 | ||
| 2 | 
                      #' Define Simulation Group  | 
                  |
| 3 | 
                      #'  | 
                  |
| 4 | 
                      #' Specifies a simulation group to be used by [`SimJointData()`].  | 
                  |
| 5 | 
                      #'  | 
                  |
| 6 | 
                      #' @param n (`numeric`)\cr number of subjects in the group.  | 
                  |
| 7 | 
                      #' @param arm (`character`)\cr treatment arm.  | 
                  |
| 8 | 
                      #' @param study (`character`)\cr study name.  | 
                  |
| 9 | 
                      #'  | 
                  |
| 10 | 
                      #' @slot n (`numeric`)\cr See arguments.  | 
                  |
| 11 | 
                      #' @slot arm (`character`)\cr See arguments.  | 
                  |
| 12 | 
                      #' @slot study (`character`)\cr See arguments.  | 
                  |
| 13 | 
                      #'  | 
                  |
| 14 | 
                      #' @examples  | 
                  |
| 15 | 
                      #' SimGroup(n = 50, arm = "Arm-A", study = "Study-1")  | 
                  |
| 16 | 
                      #' @name SimGroup-class  | 
                  |
| 17 | 
                      #' @exportClass SimGroup  | 
                  |
| 18 | 
                      .SimGroup <- setClass(  | 
                  |
| 19 | 
                      "SimGroup",  | 
                  |
| 20 | 
                      slots = c(  | 
                  |
| 21 | 
                      n = "numeric",  | 
                  |
| 22 | 
                      arm = "character",  | 
                  |
| 23 | 
                      study = "character"  | 
                  |
| 24 | 
                      )  | 
                  |
| 25 | 
                      )  | 
                  |
| 26 | ||
| 27 | 
                      #' @export  | 
                  |
| 28 | 
                      #' @rdname SimGroup-class  | 
                  |
| 29 | 
                      SimGroup <- function(n, arm, study) {
                     | 
                  |
| 30 | 49x | 
                      .SimGroup(  | 
                  
| 31 | 49x | 
                      n = n,  | 
                  
| 32 | 49x | 
                      arm = arm,  | 
                  
| 33 | 49x | 
                      study = study  | 
                  
| 34 | 
                      )  | 
                  |
| 35 | 
                      }  | 
                  |
| 36 | ||
| 37 | ||
| 38 | 
                      setValidity(  | 
                  |
| 39 | 
                      "SimGroup",  | 
                  |
| 40 | 
                          function(object) {
                     | 
                  |
| 41 | 
                              if (length(object@n) != 1) {
                     | 
                  |
| 42 | 
                                  return("`n` must be a length 1 integer")
                     | 
                  |
| 43 | 
                      }  | 
                  |
| 44 | 
                              if (length(object@arm) != 1) {
                     | 
                  |
| 45 | 
                                  return("`arm` must be a length 1 string")
                     | 
                  |
| 46 | 
                      }  | 
                  |
| 47 | 
                              if (length(object@study) != 1) {
                     | 
                  |
| 48 | 
                                  return("`study` must be a length 1 string")
                     | 
                  |
| 49 | 
                      }  | 
                  |
| 50 | 
                              if (any(object@n < 1) | any(object@n %% 1 != 0)) {
                     | 
                  |
| 51 | 
                                  return("`n` must be positive integer")
                     | 
                  |
| 52 | 
                      }  | 
                  |
| 53 | 
                      return(TRUE)  | 
                  |
| 54 | 
                      }  | 
                  |
| 55 | 
                      )  | 
                  
| 1 | ||
| 2 | 
                      #' Abstract Simulation Class for Longitudinal Data  | 
                  |
| 3 | 
                      #'  | 
                  |
| 4 | 
                      #' @param times (`numeric`) the times to generate observations at.  | 
                  |
| 5 | 
                      #'  | 
                  |
| 6 | 
                      #' @description  | 
                  |
| 7 | 
                      #' This class exists to be extended by other classes that simulate longitudinal data.  | 
                  |
| 8 | 
                      #' It is not intended to be used directly.  | 
                  |
| 9 | 
                      #' @name SimLongitudinal-class  | 
                  |
| 10 | 
                      #' @family SimLongitudinal  | 
                  |
| 11 | 
                      #' @exportClass SimLongitudinal  | 
                  |
| 12 | 
                      .SimLongitudinal <- setClass(  | 
                  |
| 13 | 
                      "SimLongitudinal",  | 
                  |
| 14 | 
                      slots = list(  | 
                  |
| 15 | 
                      times = "numeric"  | 
                  |
| 16 | 
                      )  | 
                  |
| 17 | 
                      )  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname SimLongitudinal-class  | 
                  |
| 20 | 
                      #' @export  | 
                  |
| 21 | 
                      SimLongitudinal <- function(times = seq(0, 100, 50)) {
                     | 
                  |
| 22 | ! | 
                      .SimLongitudinal(times = times)  | 
                  
| 23 | 
                      }  | 
                  |
| 24 | ||
| 25 | ||
| 26 | 
                      #' @rdname show-object  | 
                  |
| 27 | 
                      #' @export  | 
                  |
| 28 | 
                      setMethod(  | 
                  |
| 29 | 
                      f = "show",  | 
                  |
| 30 | 
                      signature = "SimLongitudinal",  | 
                  |
| 31 | 
                          definition = function(object) {
                     | 
                  |
| 32 | 4x | 
                              x <- sprintf("\nA %s Object\n\n", as_print_string(object))
                     | 
                  
| 33 | 4x | 
                      cat(x)  | 
                  
| 34 | 4x | 
                      return(object)  | 
                  
| 35 | 
                      }  | 
                  |
| 36 | 
                      )  | 
                  |
| 37 | ||
| 38 | 
                      #' @rdname as_print_string  | 
                  |
| 39 | 
                      as_print_string.SimLongitudinal <- function(object) {
                     | 
                  |
| 40 | ! | 
                          return("SimLongitudinal")
                     | 
                  
| 41 | 
                      }  | 
                  
| 1 | 
                      #' @include StanModule.R  | 
                  |
| 2 | 
                      #' @include ParameterList.R  | 
                  |
| 3 | 
                      #' @include generics.R  | 
                  |
| 4 | 
                      NULL  | 
                  |
| 5 | ||
| 6 | 
                      #' `StanModel` Function Arguments  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' The documentation lists all the conventional arguments for wrappers around  | 
                  |
| 9 | 
                      #' [StanModel()].  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @param stan (`StanModule`)\cr code containing the Stan code specification.  | 
                  |
| 12 | 
                      #' @param parameters (`ParameterList`)\cr the parameter specification.  | 
                  |
| 13 | 
                      #' @param parameter (`ParameterList`)\cr the (single) parameter specification.  | 
                  |
| 14 | 
                      #' @param name (`character`)\cr display name for the model object.  | 
                  |
| 15 | 
                      #' @param ... additional arguments for [StanModel()].  | 
                  |
| 16 | 
                      #'  | 
                  |
| 17 | 
                      #' @name stanmodel_arguments  | 
                  |
| 18 | 
                      #' @keywords internal  | 
                  |
| 19 | 
                      NULL  | 
                  |
| 20 | ||
| 21 | 
                      # StanModel-class ----  | 
                  |
| 22 | ||
| 23 | ||
| 24 | 
                      #' Stan Model Object and Constructor Function  | 
                  |
| 25 | 
                      #'  | 
                  |
| 26 | 
                      #' @slot stan (`StanModule`)\cr See Arguments.  | 
                  |
| 27 | 
                      #' @slot parameters (`ParameterList`)\cr See Arguments.  | 
                  |
| 28 | 
                      #' @slot name (`character`)\cr display name for the model object.  | 
                  |
| 29 | 
                      #'  | 
                  |
| 30 | 
                      #' @export StanModel  | 
                  |
| 31 | 
                      #' @exportClass StanModel  | 
                  |
| 32 | 
                      #' @family StanModel  | 
                  |
| 33 | 
                      .StanModel <- setClass(  | 
                  |
| 34 | 
                      Class = "StanModel",  | 
                  |
| 35 | 
                      slots = list(  | 
                  |
| 36 | 
                      "stan" = "StanModule",  | 
                  |
| 37 | 
                      "parameters" = "ParameterList",  | 
                  |
| 38 | 
                      "name" = "character"  | 
                  |
| 39 | 
                      )  | 
                  |
| 40 | 
                      )  | 
                  |
| 41 | ||
| 42 | 
                      # StanModel-constructor ----  | 
                  |
| 43 | ||
| 44 | 
                      #' @inheritParams stanmodel_arguments  | 
                  |
| 45 | 
                      #' @rdname StanModel-class  | 
                  |
| 46 | 
                      StanModel <- function(stan, parameters, name = "<Unnamed>") {
                     | 
                  |
| 47 | 103x | 
                      .StanModel(  | 
                  
| 48 | 103x | 
                      stan = stan,  | 
                  
| 49 | 103x | 
                      parameters = parameters,  | 
                  
| 50 | 103x | 
                      name = name  | 
                  
| 51 | 
                      )  | 
                  |
| 52 | 
                      }  | 
                  |
| 53 | ||
| 54 | 
                      # as.list-StanModel ----  | 
                  |
| 55 | ||
| 56 | 
                      #' `StanModel` -> `list`  | 
                  |
| 57 | 
                      #' @description  | 
                  |
| 58 | 
                      #' Returns a named list where each element of the list corresponds  | 
                  |
| 59 | 
                      #' to a Stan modelling block e.g. `data`, `model`, etc.  | 
                  |
| 60 | 
                      #' @param x ([`StanModel`])\cr A Stan Model  | 
                  |
| 61 | 
                      #' @param ... Not Used.  | 
                  |
| 62 | 
                      #' @family StanModel  | 
                  |
| 63 | 
                      #' @export  | 
                  |
| 64 | 
                      as.list.StanModel <- function(x, ...) {
                     | 
                  |
| 65 | 120x | 
                      as.list(x@stan)  | 
                  
| 66 | 
                      }  | 
                  |
| 67 | ||
| 68 | 
                      # getParameters-StanModel ----  | 
                  |
| 69 | ||
| 70 | 
                      #' @rdname getParameters  | 
                  |
| 71 | 
                      #' @export  | 
                  |
| 72 | 57x | 
                      getParameters.StanModel <- function(object, ...) object@parameters  | 
                  
| 73 | ||
| 74 | ||
| 75 | 
                      #' @export  | 
                  |
| 76 | 
                      as_print_string.StanModel <- function(object, ...) {
                     | 
                  |
| 77 | 1x | 
                      string <- sprintf(  | 
                  
| 78 | 1x | 
                      "\n%s Model Object with parameters:\n%s\n\n",  | 
                  
| 79 | 1x | 
                      object@name,  | 
                  
| 80 | 1x | 
                              paste("   ", as_print_string(object@parameters)) |> paste(collapse = "\n")
                     | 
                  
| 81 | 
                      )  | 
                  |
| 82 | 1x | 
                      return(string)  | 
                  
| 83 | 
                      }  | 
                  |
| 84 | ||
| 85 | 
                      #' @rdname show-object  | 
                  |
| 86 | 
                      #' @export  | 
                  |
| 87 | 
                      setMethod(  | 
                  |
| 88 | 
                      f = "show",  | 
                  |
| 89 | 
                      signature = "StanModel",  | 
                  |
| 90 | 
                          definition = function(object) {
                     | 
                  |
| 91 | 8x | 
                      cat(as_print_string(object))  | 
                  
| 92 | 
                      }  | 
                  |
| 93 | 
                      )  | 
                  |
| 94 | ||
| 95 | 
                      #' @rdname initialValues  | 
                  |
| 96 | 
                      #' @export  | 
                  |
| 97 | 
                      initialValues.StanModel <- function(object, n_chains, ...) {
                     | 
                  |
| 98 | 24x | 
                      initialValues(object@parameters, n_chains)  | 
                  
| 99 | 
                      }  | 
                  
| 1 | 
                      #' @include SurvivalModel.R  | 
                  |
| 2 | 
                      NULL  | 
                  |
| 3 | ||
| 4 | 
                      # SurvivalWeibullPH-class ----  | 
                  |
| 5 | ||
| 6 | 
                      #' `SurvivalWeibullPH`  | 
                  |
| 7 | 
                      #'  | 
                  |
| 8 | 
                      #' This class extends the general [`SurvivalModel`] class for using the  | 
                  |
| 9 | 
                      #' Weibull proportional hazards survival model.  | 
                  |
| 10 | 
                      #'  | 
                  |
| 11 | 
                      #' @exportClass SurvivalWeibullPH  | 
                  |
| 12 | 
                      .SurvivalWeibullPH <- setClass(  | 
                  |
| 13 | 
                      Class = "SurvivalWeibullPH",  | 
                  |
| 14 | 
                      contains = "SurvivalModel"  | 
                  |
| 15 | 
                      )  | 
                  |
| 16 | ||
| 17 | 
                      # SurvivalWeibullPH-constructors ----  | 
                  |
| 18 | ||
| 19 | 
                      #' @rdname SurvivalWeibullPH-class  | 
                  |
| 20 | 
                      #'  | 
                  |
| 21 | 
                      #' @param lambda (`Prior`)\cr for the scale `lambda`.  | 
                  |
| 22 | 
                      #' @param gamma (`Prior`)\cr for the shape `gamma`.  | 
                  |
| 23 | 
                      #' @param beta (`Prior`)\cr for covariates coefficients `beta`.  | 
                  |
| 24 | 
                      #'  | 
                  |
| 25 | 
                      #' @export  | 
                  |
| 26 | 
                      SurvivalWeibullPH <- function(  | 
                  |
| 27 | 
                      lambda = prior_gamma(2, 0.5),  | 
                  |
| 28 | 
                      gamma = prior_gamma(2, 0.5),  | 
                  |
| 29 | 
                      beta = prior_normal(0, 2)  | 
                  |
| 30 | 
                      ) {
                     | 
                  |
| 31 | 11x | 
                      .SurvivalWeibullPH(  | 
                  
| 32 | 11x | 
                      SurvivalModel(  | 
                  
| 33 | 11x | 
                      name = "Weibull-PH",  | 
                  
| 34 | 11x | 
                      stan = StanModule(x = "sm-weibull-ph/model.stan"),  | 
                  
| 35 | 11x | 
                      parameters = ParameterList(  | 
                  
| 36 | 11x | 
                      Parameter(name = "sm_weibull_ph_lambda", prior = lambda, size = 1),  | 
                  
| 37 | 11x | 
                      Parameter(name = "sm_weibull_ph_gamma", prior = gamma, size = 1),  | 
                  
| 38 | 11x | 
                      Parameter(name = "beta_os_cov", prior = beta, size = "p_os_cov_design")  | 
                  
| 39 | 
                      )  | 
                  |
| 40 | 
                      )  | 
                  |
| 41 | 
                      )  | 
                  |
| 42 | 
                      }  |