NICE DSU cross-reference
Reviewers navigate an appraisal by TSD number. This maps the three that govern survival extrapolation onto what the merlin family actually does, with the command for each in both languages.
Nothing here reproduces the guidance. Each entry is our own description of what the document is for, next to the command that answers it — the citation travels, the published text stays where it was published.
merlin’s HTA layer is a survival front end: it fits the candidate families, projects them past follow-up, anchors the tail to background mortality, and hands the parameter draws to pendragon for the value layer or morgana for Bayesian posteriors. One of us co-authored TSD 21.
Extrapolating survival from patient-level trial data
What it asks of an analysis
Fit the candidate parametric families to the same data, compare them on fit and on what each implies beyond the observed follow-up, and justify the one carried into the model rather than reporting a single curve.
What the merlin family does
merlin_extrap_grid() fits the whole candidate set in one call and returns one row per fit — log-likelihood, df, AIC, ΔAIC, BIC, landmark survival, RMST at the horizon, and whether it converged. The comparison becomes a table you can attach rather than a paragraph. The default set is exponential, Weibull, Gompertz, log-normal, log-logistic, generalised gamma and Royston–Parmar.
merlin_extrap_grid(
Surv(time, status) ~ trt, data = d,
families = c("exponential", "weibull", "gompertz",
"lognormal", "loglogistic", "ggamma", "rp"),
df = list(rp = c(3, 5, 7)),
landmarks = c(1, 5, 10), horizon = 50)
stmerlin trt, distribution(weibull) estimates store weib * repeat per family, then project the chosen fit: merlinextrap, generate(x) timevar(tgrid)
Flexible methods, when the standard families will not fit
What it asks of an analysis
Where the standard set cannot follow the shape of the hazard — a turning point, a plateau, a cured fraction — use a model flexible enough that it can, and be explicit about what the flexibility does at the horizon.
What the merlin family does
Royston–Parmar splines are a family like any other here, so moving from Weibull to a spline is one argument rather than a different package. M-splines are the safer choice when the extrapolation is what matters: the constant-hazard tail gives a flat hazard past the last knot, where Weibull and Gompertz can explode or vanish. Mixture and non-mixture cure forms use the same syntax.
merlin(Surv(time, status) ~ trt,
family = "rp", df = 3, data = d)
# flat-hazard tail, for a long horizon
merlin(Surv(time, status) ~ trt,
family = "mspline", df = 3, data = d)
stmerlin trt, distribution(rp) df(3) * flat-hazard tail, for a long horizon stmerlin trt, distribution(mspline) df(3)
Partitioned survival as a decision structure
What it asks of an analysis
The dominant oncology structure: progression-free and overall survival are modelled separately and the health states are read off as areas between the curves — which means the curves can cross and produce a negative state occupancy unless something stops them.
What the merlin family does
The explorer shows the structure and the curve-crossing failure directly, which is the quickest way to see why the assumption matters. For the analysis, fit the two curves in merlin and take occupancy, costs and the ICER through pendragon. A state-transition model fitted as a multi-state model avoids the crossing problem rather than checking for it.
# the two curves, then out to the value layer merlin(Surv(pfs, prog) ~ trt, family = "rp", df = 3, data = d) merlin(Surv(os, died) ~ trt, family = "rp", df = 3, data = d)
stmerlin trt, distribution(rp) df(3) // progression-free stmerlin trt, distribution(rp) df(3) // overall survival
What a reviewer asks for next
Background mortality. An extrapolated hazard that falls below the general population’s is a curve to reject. merlinextrap and merlin_extrap() anchor the tail to a lifetable — across the whole time axis, or only past an attained age — and re-derive survival and RMST from the anchored hazard.
Parameter uncertainty. merlin_psa and merlin_extrap_psa() draw from the fitted parameter vector and replay each draw through the prediction, giving bands on survival, hazard and RMST. That same draw matrix is the hand-off to pendragon, so uncertainty in the survival model becomes uncertainty in the ICER rather than a separate assumption.
Reproducibility. What the checks cover, and what they do not, is set out on the test suite page; qualified builds for regulated use are on Validated.