As a clinical trial statistician or programmer, answer three short questions in Your review: the task, the inputs and outputs, and the AI-assisted review. Agreeing with all three approves this benchmark; disagreeing with any needs a comment. Propose a fix with the Edit button on any source file, or add it to your comments.
We suggest spending no more than 5 minutes on a review. The other tabs beside Your review are background for assessment, not under review.
Summary
README.mdPublic entries: Python and R. Passing coverage requires an installed inventory.
Goal: carry TRT01A, AGE, HEIGHTBL, TRTSDT and TRTSDTM into
ADSL and submit it as the SAS transport file adsl.xpt, with the dates as
SAS numeric dates.
Input: one pre-analysis row per subject carrying the actual treatment, age, baseline height and the collected date and time of first exposure.
Variables:
TRT01Ais the actual treatment.AGEis the age in years, shown in three positions.HEIGHTBLis the baseline height in centimetres, shown with one decimal; missing when not measured.TRTSDTis the date part ofTRTSDTM; missing when the subject was never treated.TRTSDTMis the date and time of first exposure; missing when the subject was never treated.
Note: in the transport file TRTSDT counts days and TRTSDTM seconds
from 1 January 1960, shown as DATE9. and DATETIME20., and the
data-definition document describes both as eight-byte integers with those
formats. Each text variable is exactly as wide as its longest value.
The project.yaml guide declaration is ADaMIG 1.1; the data-definition
document records it and points to the SAS Transport version 5 dataset.
Inputs
Under review1 source fileinput/adsl_raw.csv
Edit3 rows| STUDYID | USUBJID | TRT01A | AGE | HEIGHTBL | TRTSDTC |
|---|---|---|---|---|---|
| CATH | VITAMIN D3 | 34 | 172.5 | 2025-01-08T08:30 | |
| CATH | PLACEBO | 67 | — | 2025-01-15T09:05:30 | |
| CATH | NOT TREATED | 52 | 165.2 | — |
Expected output
Under review3 expected rowsexpected/adsl.csv
Edit3 rows| STUDYID | USUBJID | TRT01A | AGE | HEIGHTBL | TRTSDT | TRTSDTM |
|---|---|---|---|---|---|---|
| CATH | VITAMIN D3 | 34 | 172.5 | 2025-01-08 | 2025-01-08T08:30:00 | |
| CATH | PLACEBO | 67 | — | 2025-01-15 | 2025-01-15T09:05:30 | |
| CATH | NOT TREATED | 52 | 165.2 | — | — |
expected/define.xml
EditDefine-XMLDefine-XML 2.1.11: CATH
Example study submitting subject-level analysis data in SAS transport; CATH-01; ADaMIG 1.1
| Dataset | Description | Class | Structure | Purpose | Keys | Documentation | Location |
|---|---|---|---|---|---|---|---|
| ADSL | Subject-Level Analysis Dataset | SUBJECT LEVEL ANALYSIS DATASET | One record per subject | Analysis | STUDYID, USUBJID | adsl.xpt |
ADSL
| Variable | Label / Description | Type | Length or Display Format | Controlled Terms or ISO Format | Origin / Source / Method / Comment |
|---|---|---|---|---|---|
| STUDYID | Study Identifier | text | 4 | Predecessor; ADSL_RAW.STUDYID | |
| USUBJID | Unique Subject Identifier | text | 16 | Predecessor; ADSL_RAW.USUBJID | |
| TRT01A | Actual Treatment for Period 01 | text | 11 | Predecessor; ADSL_RAW.TRT01A | |
| AGE | Age | integer | 3. | Predecessor; ADSL_RAW.AGE | |
| HEIGHTBL | Baseline Height (cm) | float | 5.1 | Predecessor; ADSL_RAW.HEIGHTBL | |
| TRTSDT | Date of First Exposure to Treatment | integer | DATE9. | Derived; Sponsor Date part of TRTSDTM. | |
| TRTSDTM | Datetime of First Exposure to Treatment | integer | DATETIME20. | Predecessor; ADSL_RAW.TRTSDTC |
Original source
<?xml version="1.0" encoding="UTF-8"?>
<ODM xmlns="http://www.cdisc.org/ns/odm/v1.3" xmlns:def="http://www.cdisc.org/ns/def/v2.1" xmlns:xlink="http://www.w3.org/1999/xlink" ODMVersion="1.3.2" FileType="Snapshot" FileOID="CATH.adam.Define-XML_2.1" CreationDateTime="2026-09-11T00:00:00" SourceSystem="yamaa" SourceSystemVersion="1.0" def:Context="Submission">
<Study OID="STDY.CATH">
<GlobalVariables>
<StudyName>CATH</StudyName>
<StudyDescription>Example study submitting subject-level analysis data in SAS transport</StudyDescription>
<ProtocolName>CATH-01</ProtocolName>
</GlobalVariables>
<MetaDataVersion OID="MDV.CATH.adam" Name="CATH adam metadata" def:DefineVersion="2.1.11">
<def:Standards>
<def:Standard OID="STD.ADaMIG" Name="ADaMIG" Type="IG" Version="1.1" Status="Final"/>
</def:Standards>
<ItemGroupDef OID="IG.ADSL" Name="ADSL" Purpose="Analysis" SASDatasetName="ADSL" Repeating="No" IsReferenceData="No" def:Structure="One record per subject" def:ArchiveLocationID="LF.ADSL" def:StandardOID="STD.ADaMIG">
<Description>
<TranslatedText xml:lang="en">Subject-Level Analysis Dataset</TranslatedText>
</Description>
<ItemRef ItemOID="IT.ADSL.STUDYID" OrderNumber="1" Mandatory="Yes" KeySequence="1"/>
<ItemRef ItemOID="IT.ADSL.USUBJID" OrderNumber="2" Mandatory="Yes" KeySequence="2"/>
<ItemRef ItemOID="IT.ADSL.TRT01A" OrderNumber="3" Mandatory="Yes"/>
<ItemRef ItemOID="IT.ADSL.AGE" OrderNumber="4" Mandatory="Yes"/>
<ItemRef ItemOID="IT.ADSL.HEIGHTBL" OrderNumber="5" Mandatory="No"/>
<ItemRef ItemOID="IT.ADSL.TRTSDT" OrderNumber="6" Mandatory="No" MethodOID="MT.ADSL.TRTSDT"/>
<ItemRef ItemOID="IT.ADSL.TRTSDTM" OrderNumber="7" Mandatory="No"/>
<def:Class Name="SUBJECT LEVEL ANALYSIS DATASET"/>
<def:leaf ID="LF.ADSL" xlink:href="adsl.xpt">
<def:title>adsl.xpt</def:title>
</def:leaf>
</ItemGroupDef>
<ItemDef OID="IT.ADSL.STUDYID" Name="STUDYID" DataType="text" Length="4" SASFieldName="STUDYID">
<Description>
<TranslatedText xml:lang="en">Study Identifier</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.STUDYID</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADSL.USUBJID" Name="USUBJID" DataType="text" Length="16" SASFieldName="USUBJID">
<Description>
<TranslatedText xml:lang="en">Unique Subject Identifier</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.USUBJID</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADSL.TRT01A" Name="TRT01A" DataType="text" Length="11" SASFieldName="TRT01A">
<Description>
<TranslatedText xml:lang="en">Actual Treatment for Period 01</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.TRT01A</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADSL.AGE" Name="AGE" DataType="integer" Length="3" SASFieldName="AGE" def:DisplayFormat="3.">
<Description>
<TranslatedText xml:lang="en">Age</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.AGE</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADSL.HEIGHTBL" Name="HEIGHTBL" DataType="float" Length="5" SignificantDigits="1" SASFieldName="HEIGHTBL" def:DisplayFormat="5.1">
<Description>
<TranslatedText xml:lang="en">Baseline Height (cm)</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.HEIGHTBL</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADSL.TRTSDT" Name="TRTSDT" DataType="integer" Length="8" SASFieldName="TRTSDT" def:DisplayFormat="DATE9.">
<Description>
<TranslatedText xml:lang="en">Date of First Exposure to Treatment</TranslatedText>
</Description>
<def:Origin Type="Derived" Source="Sponsor"/>
</ItemDef>
<ItemDef OID="IT.ADSL.TRTSDTM" Name="TRTSDTM" DataType="integer" Length="8" SASFieldName="TRTSDTM" def:DisplayFormat="DATETIME20.">
<Description>
<TranslatedText xml:lang="en">Datetime of First Exposure to Treatment</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL_RAW.TRTSDTC</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<MethodDef OID="MT.ADSL.TRTSDT" Name="ADSL.TRTSDT" Type="Computation">
<Description>
<TranslatedText xml:lang="en">Date part of TRTSDTM.</TranslatedText>
</Description>
</MethodDef>
</MetaDataVersion>
</Study>
</ODM>
Human review and assessment
| Dataset Name | Variable Name | Variable Label | Type | Codelist/Controlled Terms | Core | Computational Method | Origin |
|---|---|---|---|---|---|---|---|
| ADSL | STUDYID | Study Identifier | character | Req | Copy value from ADSL_RAW.STUDYID. | Predecessor | |
| ADSL | USUBJID | Unique Subject Identifier | character | Req | Copy value from ADSL_RAW.USUBJID. | Predecessor | |
| ADSL | TRT01A | Actual Treatment for Period 01 | character | Cond | Copy value from ADSL_RAW.TRT01A. | Predecessor | |
| ADSL | AGE | Age | numeric | Req | Copy value from ADSL_RAW.AGE. | Predecessor | |
| ADSL | HEIGHTBL | Baseline Height (cm) | numeric | Perm | Copy value from ADSL_RAW.HEIGHTBL. | Predecessor | |
| ADSL | TRTSDTM | Datetime of First Exposure to Treatment | numeric | ISO 8601 | Perm | Copy value from ADSL_RAW.TRTSDTC. | Predecessor |
| ADSL | TRTSDT | Date of First Exposure to Treatment | numeric | ISO 8601 | Cond | Date part of TRTSDTM. | Derived |
| Version | Date | Author | Description | Reviewer | Sign-off |
|---|---|---|---|---|---|
| 1.7 | 2026-10-20 | yamaa docs build | Read a specification in the 1.0 surface as its 0.5 counterpart; state that missing values stay missing where a mapping declares no missing handler, and leave out a declared missing answer that restates a handler's default | ||
| 1.6 | 2026-10-17 | yamaa docs build | Describe collected date parts written as ISO 8601 date text and times of day counted in seconds since midnight | ||
| 1.5 | 2026-10-17 | yamaa docs build | Name collected precision in words instead of letter codes; state imputation fallbacks, minimum source precision, bounds ignored outside the collected period, and invalid text with no handler as an error; describe date and datetime shifts, imputation flag codes, and partial text giving no date part | ||
| 1.4 | 2026-10-15 | yamaa docs build | State datetime precision codes through the hour and minute, and complete only the time parts a collected datetime lacks | ||
| 1.3 | 2026-09-29 | yamaa docs build | Show study codelist names, external dictionaries, and ISO 8601 formats in variable rows; list the document's codelist values and metadata | ||
| 1.2 | 2026-09-29 | yamaa docs build | Classify ADaM copies from a declared input as Predecessor and recodes as Derived, and SDTM recodes of locally derived columns as Derived | ||
| 1.1 | 2026-09-29 | yamaa docs build | Resolve lookups into the donor record they select, and give every derivation shape a plain-language rule instead of its raw YAML | ||
| 1.0 | yamaa docs build | Initial generation from spec.yaml |
prompts/adam-adsl-adamig11/full.md
Edit14 linesFollowing CDISC ADaM standards, use the provided ADSL_RAW dataset to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, AGE, HEIGHTBL, TRTSDT, TRTSDTM
TRTSDTM is the first exposure date and time from ADSL_RAW.TRTSDTC, expressed as YYYY-MM-DDThh:mm:ss with seconds 00 when the collected value ends at the minute. TRTSDT is the calendar date of TRTSDTM. TRTSDT and TRTSDTM have no value for a subject who was never treated. HEIGHTBL has no value when baseline height was not measured.
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
prompts/adam-adsl-adamig11/conventions.md
Edit10 linesFollowing CDISC ADaM standards, use the provided ADSL_RAW dataset to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, AGE, HEIGHTBL, TRTSDT, TRTSDTM
TRTSDTM is expressed as YYYY-MM-DDThh:mm:ss or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
prompts/adam-adsl-adamig11/brief.md
Edit8 linesFollowing CDISC ADaM standards, use the provided ADSL_RAW dataset to create an ADSL dataset with one record per subject.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, TRT01A, AGE, HEIGHTBL, TRTSDT, TRTSDTM
Read the source datasets from /app/input and save the completed dataset as /app/output/adsl.csv.
R
Edit3 lineslibrary(yamaa)yamaa_project("project.yaml")$spec("ADSL")$run()$outputPython
Edit3 linesimport yamaayamaa.project("project.yaml").spec("ADSL").run().outputsolutions/adam-adsl-adamig11/result.R
Edit27 lines# Create the subject-level ADaM ADSL dataset from the supplied source.raw <- read.csv("/app/input/adsl_raw.csv", stringsAsFactors = FALSE, na.strings = c("", "NA"), check.names = FALSE)required <- c("STUDYID", "USUBJID", "TRT01A", "AGE", "HEIGHTBL", "TRTSDTC")stopifnot(all(required %in% names(raw)), !anyNA(raw$USUBJID), !anyDuplicated(raw$USUBJID))# Complete minute-resolution collection values with zero seconds.trtsdtm <- trimws(raw$TRTSDTC)minute_only <- !is.na(trtsdtm) & grepl("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}$", trtsdtm)trtsdtm[minute_only] <- paste0(trtsdtm[minute_only], ":00")trtsdtm[is.na(trtsdtm) | trtsdtm == ""] <- NA_character_trtsdt <- as.Date(substr(trtsdtm, 1L, 10L), format = "%Y-%m-%d")adsl <- data.frame( STUDYID = raw$STUDYID, USUBJID = raw$USUBJID, TRT01A = raw$TRT01A, AGE = raw$AGE, HEIGHTBL = raw$HEIGHTBL, TRTSDT = trtsdt, TRTSDTM = trtsdtm, stringsAsFactors = FALSE)write.csv(adsl, "/app/output/adsl.csv", row.names = FALSE, na = "")solutions/adam-adsl-adamig11/result.py
Edit42 lines"""Create the subject-level ADSL dataset from ADSL_RAW."""import csvfrom datetime import datetimefrom pathlib import PathINPUT = Path("/app/input/adsl_raw.csv")OUTPUT = Path("/app/output/adsl.csv")COLUMNS = ["STUDYID", "USUBJID", "TRT01A", "AGE", "HEIGHTBL", "TRTSDT", "TRTSDTM"]def main(): with INPUT.open(newline="", encoding="utf-8-sig") as source: records = list(csv.DictReader(source)) subjects = {} for raw in records: key = (raw["STUDYID"], raw["USUBJID"]) if key not in subjects: subjects[key] = {name: raw.get(name, "") for name in COLUMNS[:5]} subjects[key]["TRTSDT"] = "" subjects[key]["TRTSDTM"] = "" collected = raw.get("TRTSDTC", "").strip() if collected: # Missing seconds in a collected minute-level timestamp become 00. exposure = datetime.fromisoformat(collected) timestamp = exposure.strftime("%Y-%m-%dT%H:%M:%S") existing = subjects[key]["TRTSDTM"] if not existing or timestamp < existing: subjects[key]["TRTSDTM"] = timestamp subjects[key]["TRTSDT"] = exposure.date().isoformat() OUTPUT.parent.mkdir(parents=True, exist_ok=True) with OUTPUT.open("w", newline="", encoding="utf-8") as target: writer = csv.DictWriter(target, fieldnames=COLUMNS) writer.writeheader() writer.writerows(subjects.values())if __name__ == "__main__": main()solutions/adam-adsl-adamig11/result.sas
Edit17 linesproc import datafile="/app/input/adsl_raw.csv" out=adsl_raw dbms=csv replace; getnames=yes;run;data adsl; length STUDYID $20 USUBJID $40 TRT01A $40 AGE 8 HEIGHTBL 8 TRTSDT $10 TRTSDTM $19; set adsl_raw; if not missing(TRTSDTC) then do; TRTSDTM=strip(TRTSDTC); if length(TRTSDTM)=16 then TRTSDTM=cats(TRTSDTM,':00'); TRTSDT=substr(TRTSDTM,1,10); end; keep STUDYID USUBJID TRT01A AGE HEIGHTBL TRTSDT TRTSDTM;run;proc export data=adsl outfile="/app/output/adsl.csv" dbms=csv replace;run;
yamaa