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 the flagged baseline value and compute the change for each laboratory result.
Input: SDTM laboratory results and subject-level treatment dates and names.
Variables:
PARAMCDandPARAMidentify alanine aminotransferase.ADTis the collection date andADYis its day relative to first treatment, with no day zero.TRT01Acarries the subject's treatment.AVALandAVALUretain the standardized result and its units.ABLFLretains the baseline flag.BASErepeats the flagged value for the subject and parameter.CHGis the result minus baseline; it is absent when baseline is absent.
Note: project.yaml declares ADaMIG 1.1. The data-definition document
records that guide and points to the SAS Transport version 5 dataset.
Inputs
Under review2 source filesExpected output
Under review3 expected rowsexpected/adlb.csv
Edit3 rows| STUDYID | USUBJID | PARAMCD | PARAM | ADT | TRT01A | ADY | AVAL | AVALU | ABLFL | BASE | CHG |
|---|---|---|---|---|---|---|---|---|---|---|---|
| CATH | ALT | Alanine Aminotransferase | 2025-01-07 | DRUG | -1 | 10 | U/L | Y | 10 | 0 | |
| CATH | ALT | Alanine Aminotransferase | 2025-01-09 | DRUG | 2 | 15 | U/L | — | 10 | 5 | |
| CATH | ALT | Alanine Aminotransferase | 2025-01-09 | PLACEBO | 2 | 20 | U/L | — | — | — |
expected/define.xml
EditDefine-XMLDefine-XML 2.1.11: CATH
Laboratory Analysis Dataset; CATH-01; ADaMIG 1.1
| Dataset | Description | Class | Structure | Purpose | Keys | Documentation | Location |
|---|---|---|---|---|---|---|---|
| ADLB | Laboratory Analysis Dataset | BASIC DATA STRUCTURE | One record per subject per parameter per date | Analysis | STUDYID, USUBJID, PARAMCD, ADT | adlb.xpt |
ADLB
| Variable | Label / Description | Type | Length or Display Format | Controlled Terms or ISO Format | Origin / Source / Method / Comment |
|---|---|---|---|---|---|
| STUDYID | Study Identifier | text | 4 | Predecessor; LB.STUDYID | |
| USUBJID | Unique Subject Identifier | text | 7 | Predecessor; LB.USUBJID | |
| PARAMCD | Parameter Code | text | 3 | Predecessor; LB.LBTESTCD | |
| PARAM | Parameter | text | 24 | Assigned; Sponsor | |
| ADT | Analysis Date | integer | DATE9. | Predecessor; LB.LBDTC | |
| TRT01A | Actual Treatment for Period 01 | text | 7 | Predecessor; ADSL.TRT01A | |
| ADY | Analysis Relative Day | integer | 8 | Derived; Sponsor Study day of ADT relative to TRTSDT, with no day zero. | |
| AVAL | Analysis Value | float | 8 | Predecessor; LB.LBSTRESN | |
| AVALU | Analysis Value Unit | text | 3 | Predecessor; LB.LBSTRESU | |
| ABLFL | Baseline Record Flag | text | 1 | Predecessor; LB.LBBLFL | |
| BASE | Baseline Value | float | 8 | Derived; Sponsor Repeat the flagged baseline value within subject and parameter. | |
| CHG | Change from Baseline | float | 8 | Derived; Sponsor Analysis value minus baseline; missing when no baseline exists. |
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>Laboratory Analysis Dataset</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.ADLB" Name="ADLB" Purpose="Analysis" SASDatasetName="ADLB" Repeating="Yes" IsReferenceData="No" def:Structure="One record per subject per parameter per date" def:ArchiveLocationID="LF.ADLB" def:StandardOID="STD.ADaMIG">
<Description>
<TranslatedText xml:lang="en">Laboratory Analysis Dataset</TranslatedText>
</Description>
<ItemRef ItemOID="IT.ADLB.STUDYID" OrderNumber="1" Mandatory="Yes" KeySequence="1"/>
<ItemRef ItemOID="IT.ADLB.USUBJID" OrderNumber="2" Mandatory="Yes" KeySequence="2"/>
<ItemRef ItemOID="IT.ADLB.PARAMCD" OrderNumber="3" Mandatory="Yes" KeySequence="3"/>
<ItemRef ItemOID="IT.ADLB.PARAM" OrderNumber="4" Mandatory="Yes"/>
<ItemRef ItemOID="IT.ADLB.ADT" OrderNumber="5" Mandatory="Yes" KeySequence="4"/>
<ItemRef ItemOID="IT.ADLB.TRT01A" OrderNumber="6" Mandatory="Yes"/>
<ItemRef ItemOID="IT.ADLB.ADY" OrderNumber="7" Mandatory="Yes" MethodOID="MT.ADLB.ADY"/>
<ItemRef ItemOID="IT.ADLB.AVAL" OrderNumber="8" Mandatory="Yes"/>
<ItemRef ItemOID="IT.ADLB.AVALU" OrderNumber="9" Mandatory="No"/>
<ItemRef ItemOID="IT.ADLB.ABLFL" OrderNumber="10" Mandatory="No"/>
<ItemRef ItemOID="IT.ADLB.BASE" OrderNumber="11" Mandatory="No" MethodOID="MT.ADLB.BASE"/>
<ItemRef ItemOID="IT.ADLB.CHG" OrderNumber="12" Mandatory="No" MethodOID="MT.ADLB.CHG"/>
<def:Class Name="BASIC DATA STRUCTURE"/>
<def:leaf ID="LF.ADLB" xlink:href="adlb.xpt">
<def:title>adlb.xpt</def:title>
</def:leaf>
</ItemGroupDef>
<ItemDef OID="IT.ADLB.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">LB.STUDYID</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.USUBJID" Name="USUBJID" DataType="text" Length="7" SASFieldName="USUBJID">
<Description>
<TranslatedText xml:lang="en">Unique Subject Identifier</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.USUBJID</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.PARAMCD" Name="PARAMCD" DataType="text" Length="3" SASFieldName="PARAMCD">
<Description>
<TranslatedText xml:lang="en">Parameter Code</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.LBTESTCD</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.PARAM" Name="PARAM" DataType="text" Length="24" SASFieldName="PARAM">
<Description>
<TranslatedText xml:lang="en">Parameter</TranslatedText>
</Description>
<def:Origin Type="Assigned" Source="Sponsor"/>
</ItemDef>
<ItemDef OID="IT.ADLB.ADT" Name="ADT" DataType="integer" Length="8" SASFieldName="ADT" def:DisplayFormat="DATE9.">
<Description>
<TranslatedText xml:lang="en">Analysis Date</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.LBDTC</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.TRT01A" Name="TRT01A" DataType="text" Length="7" SASFieldName="TRT01A">
<Description>
<TranslatedText xml:lang="en">Actual Treatment for Period 01</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">ADSL.TRT01A</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.ADY" Name="ADY" DataType="integer" Length="8" SASFieldName="ADY">
<Description>
<TranslatedText xml:lang="en">Analysis Relative Day</TranslatedText>
</Description>
<def:Origin Type="Derived" Source="Sponsor"/>
</ItemDef>
<ItemDef OID="IT.ADLB.AVAL" Name="AVAL" DataType="float" Length="8" SignificantDigits="1" SASFieldName="AVAL">
<Description>
<TranslatedText xml:lang="en">Analysis Value</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.LBSTRESN</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.AVALU" Name="AVALU" DataType="text" Length="3" SASFieldName="AVALU">
<Description>
<TranslatedText xml:lang="en">Analysis Value Unit</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.LBSTRESU</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.ABLFL" Name="ABLFL" DataType="text" Length="1" SASFieldName="ABLFL">
<Description>
<TranslatedText xml:lang="en">Baseline Record Flag</TranslatedText>
</Description>
<def:Origin Type="Predecessor">
<Description>
<TranslatedText xml:lang="en">LB.LBBLFL</TranslatedText>
</Description>
</def:Origin>
</ItemDef>
<ItemDef OID="IT.ADLB.BASE" Name="BASE" DataType="float" Length="8" SignificantDigits="1" SASFieldName="BASE">
<Description>
<TranslatedText xml:lang="en">Baseline Value</TranslatedText>
</Description>
<def:Origin Type="Derived" Source="Sponsor"/>
</ItemDef>
<ItemDef OID="IT.ADLB.CHG" Name="CHG" DataType="float" Length="8" SignificantDigits="1" SASFieldName="CHG">
<Description>
<TranslatedText xml:lang="en">Change from Baseline</TranslatedText>
</Description>
<def:Origin Type="Derived" Source="Sponsor"/>
</ItemDef>
<MethodDef OID="MT.ADLB.ADY" Name="ADLB.ADY" Type="Computation">
<Description>
<TranslatedText xml:lang="en">Study day of ADT relative to TRTSDT, with no day zero.</TranslatedText>
</Description>
</MethodDef>
<MethodDef OID="MT.ADLB.BASE" Name="ADLB.BASE" Type="Computation">
<Description>
<TranslatedText xml:lang="en">Repeat the flagged baseline value within subject and parameter.</TranslatedText>
</Description>
</MethodDef>
<MethodDef OID="MT.ADLB.CHG" Name="ADLB.CHG" Type="Computation">
<Description>
<TranslatedText xml:lang="en">Analysis value minus baseline; missing when no baseline exists.</TranslatedText>
</Description>
</MethodDef>
</MetaDataVersion>
</Study>
</ODM>
Human review and assessment
| Dataset Name | Variable Name | Variable Label | Type | Codelist/Controlled Terms | Core | Computational Method | Origin |
|---|---|---|---|---|---|---|---|
| ADLB | STUDYID | Study Identifier | character | Req | Copy value from LB.STUDYID. | Predecessor | |
| ADLB | USUBJID | Unique Subject Identifier | character | Req | Copy value from LB.USUBJID. | Predecessor | |
| ADLB | PARAMCD | Parameter Code | character | Req | Copy value from LB.LBTESTCD. | Predecessor | |
| ADLB | PARAM | Parameter | character | Req | Set constant value "Alanine Aminotransferase". | Assigned | |
| ADLB | ADT | Analysis Date | numeric | ISO 8601 | Cond | Copy value from LB.LBDTC. | Predecessor |
| ADLB | TRT01A | Actual Treatment for Period 01 | character | Cond | Copy value from ADSL.TRT01A. | Predecessor | |
| ADLB | ADY | Analysis Relative Day | numeric | Perm | Study day of ADT relative to TRTSDT, with no day zero. | Derived | |
| ADLB | AVAL | Analysis Value | numeric | Cond | Copy value from LB.LBSTRESN. | Predecessor | |
| ADLB | AVALU | Analysis Value Unit | character | Perm | Copy value from LB.LBSTRESU. | Predecessor | |
| ADLB | ABLFL | Baseline Record Flag | character | Cond | Copy value from LB.LBBLFL. | Predecessor | |
| ADLB | BASE | Baseline Value | numeric | Cond | Repeat the flagged baseline value within subject and parameter. | Derived | |
| ADLB | CHG | Change from Baseline | numeric | Cond | Analysis value minus baseline; missing when no baseline exists. | 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-adlb-adamig11/full.md
Edit20 linesFollowing CDISC ADaM standards, use the provided ADSL and LB datasets to create an ADLB dataset with one record per subject per parameter per collection date.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ADT, TRT01A, ADY, AVAL, AVALU, ABLFL, BASE, CHG
Use ADaMIG 1.1. PARAM is "Alanine Aminotransferase". ADY is relative to the subject's first treatment date in ADSL. BASE is the AVAL of the record with ABLFL "Y", repeated on every record for the same study, subject, and parameter. BASE has no value when no record is flagged "Y" for that study, subject, and parameter. CHG is AVAL minus BASE on every record, including the baseline record, and has no value when BASE has no value. BASE and CHG are not rounded.
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
prompts/adam-adlb-adamig11/conventions.md
Edit12 linesFollowing CDISC ADaM standards, use the provided ADSL and LB datasets to create an ADLB dataset with one record per subject per parameter per collection date.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ADT, TRT01A, ADY, AVAL, AVALU, ABLFL, BASE, CHG
Use ADaMIG 1.1. PARAM is "Alanine Aminotransferase". ABLFL is "Y". BASE and CHG are not rounded.
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
prompts/adam-adlb-adamig11/brief.md
Edit9 linesFollowing CDISC ADaM standards, use the provided ADSL and LB datasets to create an ADLB dataset with one record per subject per parameter per collection date.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, PARAMCD, PARAM, ADT, TRT01A, ADY, AVAL, AVALU, ABLFL, BASE, CHG
Read the source datasets from /app/input and save the completed dataset as /app/output/adlb.csv.
R
Edit3 lineslibrary(yamaa)yamaa_project("project.yaml")$spec("ADLB")$run()$outputPython
Edit3 linesimport yamaayamaa.project("project.yaml").spec("ADLB").run().outputsolutions/adam-adlb-adamig11/result.R
Edit47 lines# Create the ALT analysis dataset from the supplied subject and laboratory data.options(stringsAsFactors = FALSE)adsl <- read.csv("/app/input/adsl.csv", na.strings = c("", "NA"), check.names = FALSE)lb <- read.csv("/app/input/lb.csv", na.strings = c("", "NA"), check.names = FALSE)lb <- lb[lb$LBTESTCD == "ALT" & !is.na(lb$LBTESTCD), , drop = FALSE]subject_key <- paste(adsl$STUDYID, adsl$USUBJID, sep = "\r")stopifnot(!anyDuplicated(subject_key))subject_match <- match(paste(lb$STUDYID, lb$USUBJID, sep = "\r"), subject_key)stopifnot(!anyNA(subject_match))adt <- as.Date(substr(lb$LBDTC, 1L, 10L))trtsdt <- as.Date(adsl$TRTSDT[subject_match])day_difference <- as.integer(adt - trtsdt)ady <- ifelse(is.na(day_difference), NA_integer_, ifelse(day_difference >= 0L, day_difference + 1L, day_difference))aval <- as.numeric(lb$LBSTRESN)ablfl <- ifelse(!is.na(lb$LBBLFL) & lb$LBBLFL == "Y", "Y", "")out <- data.frame( STUDYID = lb$STUDYID, USUBJID = lb$USUBJID, PARAMCD = lb$LBTESTCD, PARAM = "Alanine Aminotransferase", ADT = adt, TRT01A = adsl$TRT01A[subject_match], ADY = as.integer(ady), AVAL = aval, AVALU = lb$LBSTRESU, ABLFL = ablfl, BASE = NA_real_, CHG = NA_real_, check.names = FALSE)parameter_key <- paste(out$STUDYID, out$USUBJID, out$PARAMCD, sep = "\r")for (key in unique(parameter_key)) { rows <- which(parameter_key == key) baseline_rows <- rows[out$ABLFL[rows] == "Y"] stopifnot(length(baseline_rows) <= 1L) if (length(baseline_rows) == 1L) { out$BASE[rows] <- out$AVAL[baseline_rows] }}out$CHG <- out$AVAL - out$BASEout <- out[order(out$STUDYID, out$USUBJID, out$PARAMCD, out$ADT), , drop = FALSE]stopifnot(!anyDuplicated(out[c("STUDYID", "USUBJID", "PARAMCD", "ADT")]))write.csv(out, "/app/output/adlb.csv", row.names = FALSE, na = "")solutions/adam-adlb-adamig11/result.py
Edit60 lines"""Create ADLB from the supplied ADSL and LB data (ADaMIG 1.1)."""from pathlib import Pathimport pandas as pddef main(): adsl = pd.read_csv(Path("/app/input") / "adsl.csv", dtype=str) lb = pd.read_csv(Path("/app/input") / "lb.csv", dtype=str) # The requested analysis parameter is ALT. adlb = lb.loc[lb["LBTESTCD"].eq("ALT")].copy() adlb = adlb.merge( adsl[["STUDYID", "USUBJID", "TRTSDT", "TRT01A"]], on=["STUDYID", "USUBJID"], how="left", validate="many_to_one", ) adlb["PARAMCD"] = "ALT" adlb["PARAM"] = "Alanine Aminotransferase" collection_date = pd.to_datetime(adlb["LBDTC"].str[:10], errors="coerce") treatment_date = pd.to_datetime(adlb["TRTSDT"], errors="coerce") adlb["ADT"] = collection_date.dt.strftime("%Y-%m-%d") day_difference = (collection_date - treatment_date).dt.days # ADaM study day has no day zero. adlb["ADY"] = (day_difference + day_difference.ge(0)).astype("Int64") adlb["AVAL"] = pd.to_numeric(adlb["LBSTRESN"], errors="coerce") adlb["AVALU"] = adlb["LBSTRESU"] adlb["ABLFL"] = adlb["LBBLFL"].where(adlb["LBBLFL"].eq("Y"), "") keys = ["STUDYID", "USUBJID", "PARAMCD"] baseline = adlb.loc[adlb["ABLFL"].eq("Y"), keys + ["AVAL"]].rename( columns={"AVAL": "BASE"} ) adlb = adlb.merge(baseline, on=keys, how="left", validate="many_to_one") adlb["CHG"] = adlb["AVAL"] - adlb["BASE"] columns = [ "STUDYID", "USUBJID", "PARAMCD", "PARAM", "ADT", "TRT01A", "ADY", "AVAL", "AVALU", "ABLFL", "BASE", "CHG", ] adlb = adlb[columns].sort_values(keys + ["ADT"], kind="stable") if adlb.duplicated(keys + ["ADT"]).any(): raise ValueError("More than one ALT record per subject and collection date") Path("/app/output").mkdir(exist_ok=True) adlb.to_csv(Path("/app/output") / "adlb.csv", index=False)if __name__ == "__main__": main()solutions/adam-adlb-adamig11/result.sas
Edit61 linesproc import datafile='/app/input/adsl.csv' out=adsl dbms=csv replace; getnames=yes;run;proc import datafile='/app/input/lb.csv' out=lb dbms=csv replace; getnames=yes;run;proc sql; create table source as select l.*, a.TRTSDT, a.TRT01A from lb as l left join adsl as a on l.STUDYID=a.STUDYID and l.USUBJID=a.USUBJID;quit;data derived; length PARAMCD $8 PARAM $40 AVALU $20 ABLFL $1; set source; PARAMCD=LBTESTCD; PARAM='Alanine Aminotransferase'; ADT=LBDTC; _TRTSDT=TRTSDT; if ADT ne . and _TRTSDT ne . then do; if ADT < _TRTSDT then ADY=ADT-_TRTSDT; else ADY=ADT-_TRTSDT+1; end; AVAL=LBSTRESN; AVALU=LBSTRESU; ABLFL=LBBLFL; format ADT yymmdd10.;run;proc sql; create table adlb_joined as select d.STUDYID, d.USUBJID, d.PARAMCD, d.PARAM, d.ADT format=yymmdd10., d.TRT01A, d.ADY, d.AVAL, d.AVALU, d.ABLFL, b.AVAL as BASE, case when d.AVAL is not null and b.AVAL is not null then d.AVAL-b.AVAL else . end as CHG from derived as d left join derived as b on d.STUDYID=b.STUDYID and d.USUBJID=b.USUBJID and d.PARAMCD=b.PARAMCD and b.ABLFL='Y' order by d.STUDYID, d.USUBJID, d.PARAMCD, d.ADT;quit;data adlb; set adlb_joined; format ADT yymmdd10.;run;proc sql; create table adlb_csv as select STUDYID, USUBJID, PARAMCD, PARAM, put(ADT,yymmdd10.) as ADT, TRT01A, ADY, AVAL, AVALU, ABLFL, BASE, CHG from adlb;quit;proc export data=adlb_csv outfile='/app/output/adlb.csv' dbms=csv replace;run;
yamaa