Case study: scoring the CDISC pilot ADaM package

knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
has_pkgs <- all(vapply(
  c("metacore", "pharmaverseadam", "r4subscore"),
  requireNamespace, logical(1), quietly = TRUE
))
knitr::opts_chunk$set(eval = has_pkgs)

This case study scores a real, public ADaM package end to end. Nothing is hand-tuned: we take two artifacts that were produced independently and ask how ready the result is for submission.

Because the spec and the data were not made to match each other, the score is not a formality. It tells us where the package stands.

if (!has_pkgs) {
  cat("> The packages needed to run this case study (metacore,",
      "pharmaverseadam, r4subscore) are not installed, so the code below is",
      "shown but not evaluated.\n")
}

The inputs

library(r4subpharma)

# The CDISC pilot ADaM specification (covers ADSL, ADAE, ADLBC, ADADAS, ADTTE)
e <- new.env()
load(metacore::metacore_example("pilot_ADaM.rda"), envir = e)
spec <- e$metacore

# One of the admiral-built datasets
adsl <- pharmaverseadam::adsl
dim(adsl)

One call to a score

submission_readiness() harvests documentation evidence from the spec and conformance evidence from the dataset, then computes the Submission Confidence Index.

ctx <- r4subcore::r4sub_run_context("CDISCPILOT01", "PROD")
spec_adsl <- metacore::select_dataset(spec, "ADSL", verbose = "silent")

res <- submission_readiness(list(ADSL = adsl), spec_adsl, ctx)
res

Reading the score

The pillar breakdown shows where the number comes from.

as.data.frame(res$sci$pillar_scores)

Quality (documentation and types) and usability (labels) are strong. The weak pillar is traceability: the specification lists variables that the built dataset does not yet contain. That single gap is what holds the score back.

The gap, made actionable

The value of a score is the fix list behind it. The failing traceability checks name exactly which specified variables are missing from the data.

ev <- res$evidence
missing <- ev[ev$indicator_id == "T-ADAM-001" & ev$result == "fail", ]
nrow(missing)
sub(".*: ", "", missing$message)

These are the CDISC pilot analysis variables: treatment-coded flags, age and site groupings, and completion flags. An analysis-ready ADSL is expected to carry them, so their absence is a real readiness finding, not a formatting nit.

We can also see the smaller quality signals: any variable whose type does not match the specification.

ev[ev$indicator_id == "Q-ADAM-001" & ev$result == "warn",
   c("location", "message")]

Scoring more of the package

The same call scales to several datasets at once; the score then reflects the whole set of evidence.

res_pkg <- submission_readiness(
  list(ADSL = pharmaverseadam::adsl, ADAE = pharmaverseadam::adae),
  spec,
  ctx
)
res_pkg$sci$SCI
as.data.frame(res_pkg$sci$pillar_scores)

Takeaways



Try the r4subpharma package in your browser

Any scripts or data that you put into this service are public.

r4subpharma documentation built on Sept. 11, 2026, 5:08 p.m.