crossover() for milestone-triggered treatment crossover. Called inside a milestone's action function, it lets patients still in the trial switch treatment at (or after) the milestone, altering only their post-switch endpoint values. Regimens are unified under one contract keyed off an earliest crossover time; the classic enrollment regimen added via add_regimen() is the T = 0 case.how() may now only modify post-switch outcomes: returning a value that differs from the original for an endpoint whose readout/event is at or before switch_time (a pre-switch or already-observed outcome) raises an error. Guard such how() functions accordingly, e.g. os = ifelse(os > switch_time, new_os, os).Surv() and strata() from the survival package so that user-supplied formulas in action functions (e.g. Surv(os, os_event) ~ arm) work after library(TrialSimulator) alone, without requiring library(survival) or the survival:: prefix. This fixes errors in parallel runs (n_workers > 1) where each worker only attaches TrialSimulator (reported in #14).'or' would error out when not all of its branches could be reached, instead of resolving to the reachable branch.eventNumber() and enrollment() conditions. Wall-time reduction ranges from a few percent to ~20% depending on how condition-evaluation-heavy the design is, with no change to results. Set options(trialsimulator.use_cpp = FALSE) to fall back to the original R implementation.doseRanging.Rmd now loads pre-computed simulation output; simulatePfsAndOsGumbel.Rmd uses a smaller validation sample).CorrelatedPfsAndOs2() to simulate correlated PFS and OS using a Gumbel copula while targeting marginal PFS/OS medians and Kendall's tau between observed, uncensored PFS and OS times.dplyr::filter() call in Trials$get_event_tables() when no filter expression is provided, reducing total simulation wall time by roughly 5-10% in trials with frequent milestone condition checks.n_switches column to locked data returned by get_locked_data(), counting the number of treatment switches per patient within the data lock window.expandRegimen() to expand the regimen_trajectory column in locked data into a long-format data frame with one row per regimen segment per patient.trial() using argument stratification_factors.... in regimen() to pass arguments to what(), when() and how().regimen() to support both single or multiple switching.regimen().enrollment() to define milestone. This bug does not affect milestone triggering.tidy (default: TRUE) in Controllers$run() to stop computing and saving event count per arm per endpoint for 40% shorter run time.solvePiecewiseConstantExponentialDistribution() to compute event rates in time windows given survival probabilities at changepoints.qPiecewiseExponent(), the quantile function of piecewise exponential distribution. This function is useful to simulate time-to-event endpoint that is correlated to other endpoints using the copula method. For example, the simdata package needs marginal quantile functions.Controllers$run() through new argument n_workers. The package mirai is used. Although mirai advocates the use of L'Ecuyer-CMRG streams to maintain independence between multiple streams, however, TrialSimulator resets it to be Mersenne-Twister streams to force identical behavior between n_workers = 1 and n_workers > 1. This enables debuggability and reproduciability under single-process mode by setting seed that causes issues under multi-process mode.remove_arms(), add_arms(), update_sample_ratio(), set_duration(), resize() and update_generator().Trials$resize() that resizes an ongoing trial.get_output() by setting new argument tidy = TRUE.Trials$update_generator().enforce = TRUE is no longer needed when adding new arms to an existing trial with at least one arm through Trials$add_arms(). However, for backward compatibility, legacy codes with enforce = TRUE still behaves as expected and no need to update.milestone_name. Now action function only requires argument trial and supports optional arguments.milestone() now support ... to pass arguments to action functions.enrollment() now supports min_treatment_duration to ensure minimum treatment duration received by patients at a milestone. With its default value 0, milestone is triggered when a specific number of patients are enrolled.invisible(NULL) is no longer recommended as return value of action function.event_plot() for plot of cumulative events number when endpoint name is "ep". This is due to data masking in dplyr.update_sample_ratio. This test is probably broken by randomness (it is okay).summarizeMilestoneTime and its plot method to summarize triggering time of milestones.update_sample_ratio() now supports updating multiple arms simultaneously. When ratio is not a whole number, sample() is used to replace the permuted block algorithm to randomize patients to arms. This enable response-adaptive design.update_sample_ratio().-Add vignette of fixed design. -Add vignette of wrapper functions of commom statistical tests.
enroll_patients. This is useful when a milestone is triggered after all patients are recruited.... in eventNumber to count event in subset of trial data. This is useful in enrichment design when milestone is defined based on biomarker.get as alias of get_custom_data in the Trials class.trial$dunnettTest(..., planned_info = "default") triggers an error.Trials$dunnettTest to be compatible to one-sided logrank test.fitLogrank now supports formula. strata(...) can be in
formula. No covariate is accepted.fitLogistic.fitLogistic now supports scale = "coefficient" to compute regression coefficient as main effect of arm in the presence of covariates. It is also equivalent to scale = "log odds ratio" in the absence of covariates.fitLogistic.fitCoxph now supports formula to compute log hazard ratio or hazard ratio as main effect of arm. It will detect whether arm's main effect is specified in formula. It allows covariates and interaction between covariates and arm. However, only the main effect of arm is tested and returned.fitCoxph.fitLogistic now supports computing log odds ratio, odds ratio, risk ratio, and risk difference using emmeans contrast, in the presence of covariates.fitLogistic and fitLinear.fitLogistic now supports formula with covariates, and uses emmeans contrast to compute average treatment effect (ATE) on the logit scale.fitLinear now supports formula with covariates, and uses emmeans contrast to compute average treatment effect (ATE) on the mean scale.trigger_condition in the function milestone is deprecated and is replaced with when. Note that trigger_condition is still supported in the R6 class Milestones.trial$get_custom_data throws an error when n > 1 in controller$run(n) because custom data is wiped out in trial$reset.arm through the ... argument.rmarkdown.rmarkdown.controller() as per suggestion from CRAN team.message() so that Shiny app can display it properly.solveMixtureExponentialDistribution to compute median of exponential endpoint of subgroup or the overall population.endpoints, arm, trial, event, listener and controller for Endpoint$new, Arm$new, Trial$new, Event$new, Listener$new and Controller$new.Trial$set_duration.enroll_a_patient. Use enroll_patients only.n > 1 in Controller$run when an arm can possibly be removed adaptively during a trial.enrollment. This is useful to count randomized patients of all arms even if some are removed adaptively.GraphicalTesting and graphicalMCP to repository TrialSimulatorDocuments.Controller$run now can specify number of simulation replicates by newly added argument n. If n is greater than 1, simulation results can be accessed in Controller$get_output().StaggeredRecruiter to force the enrollment time of the first patient is zero. This is an known issue but I was too lazy to fix it. Earlier version may have overestimated time of events.fitFarringtonManning of Farrington-Manning test for rate difference.Trial$bind to row bind data frame in action functions. It is useful to prepare inputs of group sequential or graphical test.weibullDropout to compute parameters of Weibull distribution when using it for dropout distribution.1e-5 while no alpha should have been propagated.enrollment, eventNumber and calendarTime can be combined with & and |. Nested combination is supported by using parentheses.TriggerByEventNumbers and TriggerByCalendarTime are therefore deprecated.fitLogistic to fit logistic regression model.generator in Endpoint.GraphicalTesting when a hypothesis is tested multiple times at the same stage because more alpha is passed from other rejected hypothesis.do_nothing() if users have no intent to do anything at a triggered event. This function can be passed to the argument action when creating a new event, e.g., Event$new(name = 'interim', trigger_condition = TriggerByCalendarTime, action = do_nothing, calendar_time = 64).Controller$run() and insert error message into output (see Trial$get_output()$error_message). It helps to integrate TrialSimulator with targets.Trial$get_seed().GraphicalTesting based on simplified interface of GroupSequentialTest.