Appendix B — Reproducibility

B.1 Source data

The analysis datasets are the CDISC pilot study datasets (study identifier CDISCPILOT01) distributed in the pharmaverseadam package. R/00-adam.R reads those datasets, restricts them to the randomised treatment groups, derives the treatment-emergent flags used throughout the report, and derives the time-to-event dataset with admiral::derive_param_tte().

B.2 Metadata excerpt (define.xml style)

A define.xml documents every submitted dataset and variable: its name, label, data type and, where applicable, the controlled terminology codelist it draws from. Tools such as metacore build a validated metadata object from that specification; the excerpt below hand-curates a subset of ADSL variables used in this report in the same shape, without generating or validating a full define.xml.

Metadata excerpt: ADSL variables used in this report
define.xml-style excerpt, hand-curated
Dataset Variable Label Type Codelist
ADSL USUBJID Unique Subject Identifier text
ADSL TRT01P Planned Treatment for Period 01 text TRT01P
ADSL TRT01A Actual Treatment for Period 01 text TRT01P
ADSL AGE Age integer
ADSL AGEGR1 Pooled Age Group 1 text AGEGR1
ADSL SEX Sex text SEX
ADSL RACE Race text RACE
ADSL SAFFL Safety Population Flag text NY
ADSL ITTFL Intent-To-Treat Population Flag text NY
ADSL PPROTFL Per-Protocol Population Flag text NY
ADSL COMPFL Completers Population Flag text NY
ADSL DCSREAS Reason for Discontinuation from Study text
ADSL TRTDURD Total Treatment Duration (Days) integer
Illustrative excerpt only, covering the ADSL variables referenced elsewhere in this report; not a validated define.xml. NY is the CDISC controlled terminology codelist for No/Yes flags.

B.3 Analysis results traceability

Every summary table in this report is computed by gtsummary, which retains the Analysis Results Dataset (ARD) behind each statistic, following the CDISC Analysis Results Data standard. Each table’s ARD can be recovered from its table object, and cards::bind_ard() combines the ARDs from several tables into a single dataset, which is the mechanism used for quality control of the numbers reported here.

disposition_ard <- gtsummary::gather_ard(tlf_disposition(adsl))[[1L]]
demographics_ard <- gtsummary::gather_ard(tlf_demographics(adsl))[[1L]]
ae_overview_ard <- gtsummary::gather_ard(tlf_ae_overview(adae, adsl))[[1L]]

ard <- cards::bind_ard(disposition_ard, demographics_ard, ae_overview_ard, .quiet = TRUE)
head(as.data.frame(ard)[, c("variable", "stat_name", "stat")], 8)
                    variable stat_name      stat
1 Reason for discontinuation         n         8
2 Reason for discontinuation         N        28
3 Reason for discontinuation         p 0.2857143
4 Reason for discontinuation         n         9
5 Reason for discontinuation         N        28
6 Reason for discontinuation         p 0.3214286
7 Reason for discontinuation         n         2
8 Reason for discontinuation         N        28

The combined ARD traces every statistic back to the table (Table 14.1.2, Table 14.1.3 or Table 14.3.1.1) and variable that produced it:

as.data.frame(dplyr::count(ard, variable, name = "n_rows"))
                                      variable n_rows
1                              ..ard_total_n..      1
2                                          AGE     32
3                                       AGEGR1     36
4               Any TEAE leading to withdrawal     26
5                  Any TEAE with fatal outcome     26
6                        Any dermatologic TEAE     26
7                        Any drug-related TEAE     26
8                             Any serious TEAE     26
9                              Any severe TEAE     26
10 Any treatment-emergent adverse event (TEAE)     26
11                         Completed the study     26
12                                        Died     26
13                      Discontinued the study     26
14                                      ETHNIC     35
15                                        RACE     45
16                                  Randomised     26
17                  Reason for discontinuation     90
18                                         SEX     36
19                                      TRT01A     12
20                                      TRT01P     12
21                                     TRTDURD     32
22                 Treated (safety population)     26

B.4 Session information

Package versions used for this report
Package Version Source
dplyr 1.2.1 RSPM
ggplot2 4.0.3 RSPM
gtsummary 2.5.1 RSPM

Key packages are cited in the reference list: admiral (Mancini et al. 2026), gtsummary (Sjoberg et al. 2021), survival (Therneau 2026), ggsurvfit (Sjoberg et al. 2026), gt (Iannone et al. 2026).

B.5 Table shells

Table shells fix column layout, statistics and placeholder text at SAP sign-off, before database lock. The final report differs from the shell only in the numbers, not in structure. The mockup in Table B.1 is the pre-lock shell for Table 14.2.1; the populated table in Table B.2 is the same table after database lock, reproduced here for direct comparison.

Table B.1: Shell for Time to first dermatologic treatment-emergent adverse event. Intention-to-treat population. Pre-database-lock template.
Treatment group Subjects Subjects with an event Median time to event (days) Hazard ratio (95% CI) p-value
Placebo XX XX (XX.X%) XXX (XXX, XXX) Reference
Xanomeline low dose XX XX (XX.X%) XXX (XXX, XXX) X.XX (X.XX, X.XX) X.XXX
Xanomeline high dose XX XX (XX.X%) XXX (XXX, XXX) X.XX (X.XX, X.XX) X.XXX
XX marks cells populated only after database lock. Column layout and statistics are fixed at SAP sign-off.
Table B.2: Populated after database lock. Time to first dermatologic treatment-emergent adverse event. Intention-to-treat population.
Treatment group Subjects Subjects with an event Median time to event (days) Hazard ratio (95% CI) p-value
Placebo 86 20 (23.3%) Not reached Reference
Xanomeline Low Dose 84 39 (46.4%) 80 (55, NA) 2.98 (1.73, 5.13) <0.001
Xanomeline High Dose 84 39 (46.4%) 89 (50, NA) 3.34 (1.94, 5.75) <0.001
Medians and confidence intervals are Kaplan-Meier estimates. Hazard ratios come from a Cox proportional hazards model with planned treatment as the only covariate and placebo as the reference group. A median is reported as not reached where fewer than half the subjects in the group had an event.
quarto_version <- system2("quarto", "--version", stdout = TRUE, stderr = TRUE)
typst_version <- system2("quarto", c("typst", "--version"), stdout = TRUE, stderr = TRUE)

cat(
  "R:     ", R.version.string,
  "\nQuarto:", quarto_version,
  "\nTypst: ", sub("^typst ", "", typst_version)
)
R:      R version 4.6.1 (2026-06-24) 
Quarto: 1.11.1 
Typst:  0.15.1 (9dfd3a08)

The exact package versions are pinned in renv.lock. Running renv::restore() followed by quarto render reproduces this report from a clean checkout.