This page is the repository's own document docs/conformance.md, shown as it is, so that it never drifts from the product.
sapling adam conform checks the ADaM data sets of a study (out/adam/data/*.xpt) against rules of the ADaM
Implementation Guide v1.2 (CDISC, 2019). It reads the data sets themselves: the names, labels, types and lengths of
the variables, and their values. It writes out/adam/conformance.md.
sapling run # the ADaM data sets
sapling adam conform # ADAM CONFORMANCE PASS / FAIL: 27 rules of the ADaMIG v1.2 on n data set(s): e error(s), w warning(s)
What this is, and what it is not. Each rule is a sentence of the guide, named by its section and item. This is Sapling's reading of the guide. It is not the list "ADaM Conformance Rules" that CDISC publishes (about 2,000 checks with their own ids), and it is not CDISC CORE. A finding here is real. No finding here does not prove conformance: use a validator (Pinnacle 21) before a submission.
The rules#
| Rule | From the ADaMIG v1.2 | What it says |
|---|---|---|
name | 3.1.1 item 1 | A variable name has at most 8 characters, starts with a letter, and has only letters, digits and the underscore. |
label | 3.1.1 item 1 | A variable label has at most 40 characters (and is there). |
length | 3.1.1 item 1 | A character variable has at most 200 characters. |
sdtm-copy | 3.1.1 item 3 | A variable with the name of an SDTM variable is a copy of it: its label is not changed. |
pair-primary | 3.1.1 items 6 and 7 | The numeric *N of a character variable is there only with that variable. |
pair-one-to-one | 3.1.1 items 5 and 6 | The two variables of a pair have a one-to-one relationship where both have a value. |
flag-values | 3.1.1 item 8, 3.1.4 item 9 | A flag (*FL) is a character variable with the values Y, N or null. |
flag-numeric | 3.1.1 item 8, 3.1.4 item 9 | A numeric flag (*FN) is 1, 0 or null, and is there only with its *FL. |
population-flag-null | 3.1.4 item 4 | A subject-level population flag is Y or N on every row. |
population-flag | 3.1.4 item 2 | ADSL has at least one population flag. |
date-numeric | 3.1.2 items 2 to 4, table 3.1.5.1 | A name that ends in DT, TM or DTM is a numeric date, time or datetime. |
day-zero | 3.1.2 item 8 | A relative day (*DY) is never 0. |
imputation-flag | 3.1.3 items 1 and 2 | *DTF is Y, M, D or null; *TMF is H, M, S or null. |
required | 3.2 (ADSL), 3.3 (BDS): core Req | The variables the guide requires in the data structure are there. |
ig-type | 3.2, 3.3 | A standard variable has the type the guide gives it. |
ig-label | 3.2, 3.3 | A standard variable has the label the guide gives it (a warning). |
flag-y-only | 3.3.4.3, 3.3.8.1: codelist Y | A flag the guide gives the value Y only (ABLFL, ANLzzFL) is Y or null, never N. |
datetime-parts | 3.1.2 item 5 | Where a datetime (*DTM) has a value, its date (*DT) is the date part of it. |
baseline | 3.3.4.1 (BASE), 3.3.8.1 (ABLFL) | A data set with BASE has ABLFL; a subject and parameter with a baseline value has a flagged record; BASE is the AVAL of that record. More than one flagged record for a subject and parameter is a warning (the guide wants BASETYPE then). |
change | 3.3.4.1 (CHG, PCHG) | CHG is AVAL - BASE; PCHG is ((AVAL - BASE) / BASE) * 100, and is null where BASE is 0. |
censor | 3.3.6 (CNSR) | CNSR is numeric: 0 for an event, a positive integer for a censored time. |
paramcd | 3.3.4.1 | PARAMCD: at most 8 characters, a letter first, only A-Z, digits and underscore; a value on every record; one-to-one with PARAM; a BDS data set has AVAL or AVALC. |
adsl-one-record | 3.2 | ADSL has one record for each subject. |
subject-in-adsl | 2.3.1, 3.3.1 (USUBJID) | A subject of another data set has its record in ADSL. |
adsl-dm | 3.2.1, 3.2.2, 3.2.4 | A variable of ADSL that the guide takes from DM (DM.AGE, DM.SEX, DM.ARM, ...) has the value of DM for the subject, and a subject of ADSL is in DM. Checked when sdtm/dm.xpt is there. |
criterion | 3.3.4.3 (CRITy, CRITyFL) | CRITy and CRITyFL come together; where CRITyFL has a value, CRITy has one. |
baseline-indicator | 3.3.7 (BNRIND, BTOXGR) | BNRIND is the ANRIND, and BTOXGR the ATOXGR, of the baseline record: ANRIND (ATOXGR) and ABLFL are there, and the two are equal on the baseline record. |
The standard variables (name, label, type, required or not) come from standards/adamig_v1.2_variables.csv. The
structure of a data set (ADSL, BDS) comes from its specification (out/adam/spec/<ds>.json); a data set of another
structure (an occurrence data set) gets the rules of names, labels and flags, not the rules of a structure.
Not checked#
- The values of a variable with an SDTM name against the SDTM data, other than ADSL against DM (only its label is compared).
- The order of a start and an end date, controlled terminology, and the consistency with define.xml (rules of Pinnacle 21 that are not sentences of the guide's variable tables).
- Rules that need the meaning of the data: the traceability of a derivation, whether a baseline is the right one.
- The conditions of a conditionally required variable (core Cond).
- ADaMIG v1.3, the occurrence data structure (OCCDS) and the time-to-event guide.
- SDTM conformance: Sapling has no SDTM checker.
Other checkers#
- Pinnacle 21 is the validator that sponsors run before a submission. Its public list has 310 rules for the ADaMIG v1.2 (https://standards.pinnacle21.certara.net/validation-rules/ADaM). Sapling's rules are written from the guide, with their own names; they grow toward that list.
- CDISC CORE (the CDISC Open Rules Engine, open source) has rules for SDTM, and no rules for ADaM (version 1.0.0, November 2026). Sapling does not run it: SDTM is the input of Sapling, not a product of it.