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: one record per reported result from serum, skin-biopsy,
saliva, and tape-strip forms, carrying LBTESTCD, LBTEST,
LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC,
LBSTRESN, LBSTRESU, LBSTAT, VISITNUM, and LBDTC.
Input: Operational Data Model (ODM) extract in long form, one record per collected item, with the collected entry in the value field; each form also carries its collection date as a sibling item record.
Variables:
VISITNUMis the visit number:1screening,2baseline,3day 21; each unscheduled visit is numbered after the baseline visit per occurrence (2.01,2.02), so repeated unscheduled visits stay distinct.VISITis the matching visit name.LBTESTCDis the short test code for the collected item:VITD25OH,IL13, orCAMPPRO.LBTESTis the full test name for that code:25-Hydroxyvitamin D,Interleukin 13 mRNA, orCathelicidin Protein.LBCATis the test category for that code:CHEMISTRY,GENE EXPRESSION, orANTIMICROBIAL PEPTIDE.LBSPECis the specimen type of the form the result came from:SERUM,SKIN BIOPSY,SALIVA, orTAPE STRIP.LBLOCis the sampled site where the form distinguishes one:LESIONALorNON-LESIONALfor biopsy and tape-strip results; blank for serum and saliva results.LBORRESis the collected result, exactly as reported; blank when the test was not done.LBORRESUis the unit fixed for each form:CYCLEfor biopsy results andng/mLotherwise; blank when the test was not done.LBSTRESCrepeats the reported result in standard form; blank when the test was not done.LBSTRESNis the numeric form of the reported result; missing when the test was not done.LBSTRESUis the standard unit, the same asLBORRESU; blank when the test was not done.LBSTATisNOT DONEwhen the test was not done; blank otherwise.LBDTCis the collection date from the date item on the same form.
Note: an item with no reported value produces no record, while
a collected zero is kept as a real result; an entry of NOT DONE
still produces a record, with the result and unit fields left blank
and the status recorded. Each record keeps the date of the form it
came from, so a form collected twice at one visit keeps each
occurrence's own date.
Inputs
Under review1 source fileinput/odm.csv
Edit38 rows| StudyOID | MetaDataVersionOID | SubjectKey | StudyEventOID | StudyEventRepeatKey | ItemGroupOID | ItemGroupRepeatKey | ItemOID | Value |
|---|---|---|---|---|---|---|---|---|
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.DM | 1 | IT.NCT00789880.DM.DIAGGRP | AD |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.LB | 1 | IT.NCT00789880.LB.LBDTC | 2025-01-01 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.LB | 1 | IT.NCT00789880.LB.VITD | 23.2 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.BXDTC | 2025-01-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_LES | 5.45 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_NONLES | 3.71 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SALDTC | 2025-01-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SAL_CAMP | 0 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TSDTC | 2025-01-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_LES | 0.34 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.BL | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_NONLES | 2.1 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.BXDTC | 2025-01-29 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_LES | 12.95 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_NONLES | 0 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SALDTC | 2025-01-29 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SAL_CAMP | NOT DONE |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TSDTC | 2025-01-29 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_LES | 0 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_NONLES | — |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.UNSCH | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SALDTC | 2025-01-15 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.UNSCH | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SAL_CAMP | 2.1 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.UNSCH | 1 | IG.NCT00789880.SAL | 2 | IT.NCT00789880.SAL.SALDTC | 2025-01-16 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0001 | SE.NCT00789880.UNSCH | 1 | IG.NCT00789880.SAL | 2 | IT.NCT00789880.SAL.SAL_CAMP | 2.3 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.DM | 1 | IT.NCT00789880.DM.DIAGGRP | NONAD |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.LB | 1 | IT.NCT00789880.LB.LBDTC | 2025-02-01 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.SCRN | 1 | IG.NCT00789880.LB | 1 | IT.NCT00789880.LB.VITD | 18.4 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.BXDTC | 2025-02-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_NONLES | 1.22 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SALDTC | 2025-02-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SAL_CAMP | — |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TSDTC | 2025-02-08 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.BL | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_NONLES | 4.49 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.BXDTC | 2025-03-01 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.BX | 1 | IT.NCT00789880.BX.IL13_NONLES | 1.87 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SALDTC | 2025-03-01 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.SAL | 1 | IT.NCT00789880.SAL.SAL_CAMP | 5.24 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TSDTC | 2025-03-01 |
| ST.NCT00789880 | MDV.NCT00789880.1 | CATH-UCSD-0002 | SE.NCT00789880.D21 | 1 | IG.NCT00789880.TS | 1 | IT.NCT00789880.TS.TS_CAMP_NONLES | 4.65 |
Expected output
Under review18 expected rowsexpected/lb.csv
Edit18 rows| DOMAIN | STUDYID | USUBJID | LBSEQ | VISIT | VISITNUM | LBTESTCD | LBTEST | LBCAT | LBSPEC | LBLOC | LBORRES | LBORRESU | LBSTRESC | LBSTRESN | LBSTRESU | LBSTAT | LBDTC |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| LB | ST.NCT00789880 | 1 | SCREENING | 1 | VITD25OH | 25-Hydroxyvitamin D | CHEMISTRY | SERUM | — | 23.2 | ng/mL | 23.2 | 23.2 | ng/mL | — | 2025-01-01 | |
| LB | ST.NCT00789880 | 1 | SCREENING | 1 | VITD25OH | 25-Hydroxyvitamin D | CHEMISTRY | SERUM | — | 18.4 | ng/mL | 18.4 | 18.4 | ng/mL | — | 2025-02-01 | |
| LB | ST.NCT00789880 | 5 | BASELINE | 2 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | LESIONAL | 5.45 | CYCLE | 5.45 | 5.45 | CYCLE | — | 2025-01-08 | |
| LB | ST.NCT00789880 | 11 | DAY 21 | 3 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | LESIONAL | 12.95 | CYCLE | 12.95 | 12.95 | CYCLE | — | 2025-01-29 | |
| LB | ST.NCT00789880 | 6 | BASELINE | 2 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | NON-LESIONAL | 3.71 | CYCLE | 3.71 | 3.71 | CYCLE | — | 2025-01-08 | |
| LB | ST.NCT00789880 | 12 | DAY 21 | 3 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | NON-LESIONAL | 0 | CYCLE | 0 | 0 | CYCLE | — | 2025-01-29 | |
| LB | ST.NCT00789880 | 3 | BASELINE | 2 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | NON-LESIONAL | 1.22 | CYCLE | 1.22 | 1.22 | CYCLE | — | 2025-02-08 | |
| LB | ST.NCT00789880 | 6 | DAY 21 | 3 | IL13 | Interleukin 13 mRNA | GENE EXPRESSION | SKIN BIOPSY | NON-LESIONAL | 1.87 | CYCLE | 1.87 | 1.87 | CYCLE | — | 2025-03-01 | |
| LB | ST.NCT00789880 | 2 | BASELINE | 2 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | SALIVA | — | 0 | ng/mL | 0 | 0 | ng/mL | — | 2025-01-08 | |
| LB | ST.NCT00789880 | 9 | DAY 21 | 3 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | SALIVA | — | — | — | — | — | — | NOT DONE | 2025-01-29 | |
| LB | ST.NCT00789880 | 7 | UNSCHEDULED | 2.01 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | SALIVA | — | 2.1 | ng/mL | 2.1 | 2.1 | ng/mL | — | 2025-01-15 | |
| LB | ST.NCT00789880 | 8 | UNSCHEDULED | 2.02 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | SALIVA | — | 2.3 | ng/mL | 2.3 | 2.3 | ng/mL | — | 2025-01-16 | |
| LB | ST.NCT00789880 | 4 | DAY 21 | 3 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | SALIVA | — | 5.24 | ng/mL | 5.24 | 5.24 | ng/mL | — | 2025-03-01 | |
| LB | ST.NCT00789880 | 3 | BASELINE | 2 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | TAPE STRIP | LESIONAL | 0.34 | ng/mL | 0.34 | 0.34 | ng/mL | — | 2025-01-08 | |
| LB | ST.NCT00789880 | 10 | DAY 21 | 3 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | TAPE STRIP | LESIONAL | 0 | ng/mL | 0 | 0 | ng/mL | — | 2025-01-29 | |
| LB | ST.NCT00789880 | 4 | BASELINE | 2 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | TAPE STRIP | NON-LESIONAL | 2.1 | ng/mL | 2.1 | 2.1 | ng/mL | — | 2025-01-08 | |
| LB | ST.NCT00789880 | 2 | BASELINE | 2 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | TAPE STRIP | NON-LESIONAL | 4.49 | ng/mL | 4.49 | 4.49 | ng/mL | — | 2025-02-08 | |
| LB | ST.NCT00789880 | 5 | DAY 21 | 3 | CAMPPRO | Cathelicidin Protein | ANTIMICROBIAL PEPTIDE | TAPE STRIP | NON-LESIONAL | 4.65 | ng/mL | 4.65 | 4.65 | ng/mL | — | 2025-03-01 |
Human review and assessment
| Variable Name | Variable Label | Type | Length | Controlled Terms or Format | Origin | Core | Conversion Definition | Variable Type | Variable Order | Comments for Define |
|---|---|---|---|---|---|---|---|---|---|---|
| DOMAIN | Domain Abbreviation | Char | LB | Assigned | Set constant value "LB". | SDTM | 1 | |||
| STUDYID | Study Identifier | Char | Collected | Copy value from ODM.StudyOID. | SDTM | 2 | ||||
| USUBJID | Unique Subject Identifier | Char | Collected | Copy value from ODM.SubjectKey. | SDTM | 3 | ||||
| VISIT | Visit Name | Char | SCREENING, BASELINE, DAY 21, UNSCHEDULED | Collected | Recode ODM.StudyEventOID: "SE.NCT00789880.SCRN" → "SCREENING", "SE.NCT00789880.BL" → "BASELINE", "SE.NCT00789880.D21" → "DAY 21", "SE.NCT00789880.UNSCH" → "UNSCHEDULED"; missing values stay missing; unlisted values are errors. | SDTM | 4 | |||
| VISITNUM | Visit Number | Num | 1, 2, 3, 2.01, 2.02 | Derived | If ODM.StudyEventOID = 'SE.NCT00789880.SCRN' then "1"; If ODM.StudyEventOID = 'SE.NCT00789880.BL' then "2"; If ODM.StudyEventOID = 'SE.NCT00789880.D21' then "3"; If ODM.StudyEventOID = 'SE.NCT00789880.UNSCH' then compute 2 + FORMREPEAT / 100; otherwise blank. | SDTM | 5 | |||
| LBTESTCD | Lab Test or Examination Short Name | Char | VITD25OH, IL13, CAMPPRO | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 6 | |||
| LBTEST | Lab Test or Examination Name | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 7 | ||||
| LBCAT | Category for Lab Test | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 8 | ||||
| LBSPEC | Specimen Material Type | Char | SERUM, SKIN BIOPSY, SALIVA, TAPE STRIP | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 9 | |||
| LBLOC | Location Used for Measurement | Char | LESIONAL, NON-LESIONAL | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 10 | |||
| LBORRES | Result or Finding in Original Units | Char | Derived | If RAWORRES = 'NOT DONE' then "None"; otherwise "RAWORRES". | SDTM | 11 | ||||
| LBORRESU | Original Units | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 12 | ||||
| LBSTRESC | Character Result/Finding in Std Format | Char | Derived | Copy value from LBORRES. | SDTM | 13 | ||||
| LBSTRESN | Numeric Result/Finding in Standard Units | Num | Derived | Copy value from LBORRES; a value that cannot be converted → blank. | SDTM | 14 | ||||
| LBSTRESU | Standard Units | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 15 | ||||
| LBSTAT | Completion Status | Char | NOT DONE | Derived | If RAWORRES = 'NOT DONE' then "NOT DONE"; otherwise blank. | SDTM | 16 | |||
| LBDTC | Date/Time of Specimen Collection | Char | ISO 8601 | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 17 | |||
| LBSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by LBDTC then LBTESTCD then LBSPEC. | SDTM | 18 |
| Template | Include when | LBTESTCD | LBTEST | LBCAT | LBSPEC | LBLOC | RAWORRES | LBORRESU | LBSTRESU | LBDTC |
|---|---|---|---|---|---|---|---|---|---|---|
| serum_vitamin_d | RAWORRES IS NOT NULL | Constant "VITD25OH" | Constant "25-Hydroxyvitamin D" | Constant "CHEMISTRY" | Constant "SERUM" | Constant "None" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.LB.VITD' | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.LB.LBDTC' |
| biopsy_il13_lesional | RAWORRES IS NOT NULL | Constant "IL13" | Constant "Interleukin 13 mRNA" | Constant "GENE EXPRESSION" | Constant "SKIN BIOPSY" | Constant "LESIONAL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.BX.IL13_LES' | If RAWORRES = 'NOT DONE' then "None"; otherwise "CYCLE" | If RAWORRES = 'NOT DONE' then "None"; otherwise "CYCLE" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.BX.BXDTC' |
| biopsy_il13_nonlesional | RAWORRES IS NOT NULL | Constant "IL13" | Constant "Interleukin 13 mRNA" | Constant "GENE EXPRESSION" | Constant "SKIN BIOPSY" | Constant "NON-LESIONAL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.BX.IL13_NONLES' | If RAWORRES = 'NOT DONE' then "None"; otherwise "CYCLE" | If RAWORRES = 'NOT DONE' then "None"; otherwise "CYCLE" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.BX.BXDTC' |
| saliva_cathelicidin | RAWORRES IS NOT NULL | Constant "CAMPPRO" | Constant "Cathelicidin Protein" | Constant "ANTIMICROBIAL PEPTIDE" | Constant "SALIVA" | Constant "None" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.SAL.SAL_CAMP' | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.SAL.SALDTC' |
| tape_cathelicidin_lesional | RAWORRES IS NOT NULL | Constant "CAMPPRO" | Constant "Cathelicidin Protein" | Constant "ANTIMICROBIAL PEPTIDE" | Constant "TAPE STRIP" | Constant "LESIONAL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.TS.TS_CAMP_LES' | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.TS.TSDTC' |
| tape_cathelicidin_nonlesional | RAWORRES IS NOT NULL | Constant "CAMPPRO" | Constant "Cathelicidin Protein" | Constant "ANTIMICROBIAL PEPTIDE" | Constant "TAPE STRIP" | Constant "NON-LESIONAL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.TS.TS_CAMP_NONLES' | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | If RAWORRES = 'NOT DONE' then "None"; otherwise "ng/mL" | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.NCT00789880.TS.TSDTC' |
| Variable | Permitted values |
|---|---|
| DOMAIN | LB |
| VISIT | SCREENING, BASELINE, DAY 21, UNSCHEDULED |
| VISITNUM | 1, 2, 3, 2.01, 2.02 |
| LBTESTCD | VITD25OH, IL13, CAMPPRO |
| LBSPEC | SERUM, SKIN BIOPSY, SALIVA, TAPE STRIP |
| LBLOC | LESIONAL, NON-LESIONAL |
| LBSTAT | NOT DONE |
| 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/sdtm-lb-multiform/full.md
Edit37 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an LB dataset with one record per reported result.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, LBSEQ, VISIT, VISITNUM, LBTESTCD, LBTEST, LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC, LBSTRESN, LBSTRESU, LBSTAT, LBDTC
DOMAIN is "LB" on every record. STUDYID is the study OID as given and USUBJID the subject key as given. VISIT is "SCREENING" for the screening visit, "BASELINE" for the baseline visit, "DAY 21" for the day 21 visit, and "UNSCHEDULED" for an unscheduled visit. VISITNUM is 1 for the screening visit, 2 for the baseline visit, and 3 for the day 21 visit; an unscheduled visit is numbered after the baseline visit by its occurrence at that visit, 2.01 for the first occurrence and 2.02 for the second, so repeated unscheduled visits stay distinct. A serum result has LBTESTCD "VITD25OH", LBTEST "25-Hydroxyvitamin D", LBCAT "CHEMISTRY", and LBSPEC "SERUM". A skin biopsy result has LBTESTCD "IL13", LBTEST "Interleukin 13 mRNA", LBCAT "GENE EXPRESSION", and LBSPEC "SKIN BIOPSY". A saliva result has LBTESTCD "CAMPPRO", LBTEST "Cathelicidin Protein", LBCAT "ANTIMICROBIAL PEPTIDE", and LBSPEC "SALIVA". A tape-strip result has LBTESTCD "CAMPPRO", LBTEST "Cathelicidin Protein", LBCAT "ANTIMICROBIAL PEPTIDE", and LBSPEC "TAPE STRIP". LBLOC is "LESIONAL" on a lesional biopsy or tape-strip result and "NON-LESIONAL" on a non-lesional one, and has no value on a serum or saliva result. LBORRES is the collected result exactly as reported, and LBSTRESC holds the same value. LBORRESU is "CYCLE" on a skin biopsy record and "ng/mL" on every other record, and LBSTRESU is the same unit as LBORRESU. LBSTRESN is the numeric form of the reported result. An item with no reported value gives no record, while a collected zero is kept as a real result. An entry of "NOT DONE" still gives a record: LBSTAT is "NOT DONE", and LBORRES, LBORRESU, LBSTRESC, LBSTRESN, and LBSTRESU have no value on it. LBSTAT has no value on every other record. LBDTC is the collection date collected on the same form as the result, so a form collected twice at one visit keeps each occurrence's own date. LBSEQ numbers each subject's records from 1 by collection date, then test code, then specimen type.
Read the source datasets from /app/input and save the completed dataset as /app/output/lb.csv.
prompts/sdtm-lb-multiform/conventions.md
Edit20 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an LB dataset with one record per reported result.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, LBSEQ, VISIT, VISITNUM, LBTESTCD, LBTEST, LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC, LBSTRESN, LBSTRESU, LBSTAT, LBDTC
DOMAIN is "LB" on every record. VISIT is "SCREENING", "BASELINE", "DAY 21", or "UNSCHEDULED". VISITNUM is 1 for the screening visit, 2 for the baseline visit, and 3 for the day 21 visit. A serum result has LBTESTCD "VITD25OH", LBTEST "25-Hydroxyvitamin D", LBCAT "CHEMISTRY", and LBSPEC "SERUM". A skin biopsy result has LBTESTCD "IL13", LBTEST "Interleukin 13 mRNA", LBCAT "GENE EXPRESSION", and LBSPEC "SKIN BIOPSY". A saliva result has LBTESTCD "CAMPPRO", LBTEST "Cathelicidin Protein", LBCAT "ANTIMICROBIAL PEPTIDE", and LBSPEC "SALIVA", and a tape-strip result has the same values with LBSPEC "TAPE STRIP". LBLOC is "LESIONAL" or "NON-LESIONAL", or has no value. LBSTAT is "NOT DONE" or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/lb.csv.
prompts/sdtm-lb-multiform/brief.md
Edit9 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an LB dataset with one record per reported result.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, LBSEQ, VISIT, VISITNUM, LBTESTCD, LBTEST, LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC, LBSTRESN, LBSTRESU, LBSTAT, LBDTC
Read the source datasets from /app/input and save the completed dataset as /app/output/lb.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/sdtm-lb-multiform/result.R
Edit89 lines# Reference solution for the yamaa benchmark sdtm-lb-multiform (R track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1.library(dplyr, warn.conflicts = FALSE)library(readr)library(tidyr)odm <- read_csv( "/app/input/odm.csv", col_types = cols(.default = col_character()))test_meta <- tribble( ~short, ~LBTESTCD, ~LBTEST, ~LBCAT, ~LBSPEC, ~LBLOC, ~unit, "VITD", "VITD25OH", "25-Hydroxyvitamin D", "CHEMISTRY", "SERUM", NA_character_, "ng/mL", "IL13_LES", "IL13", "Interleukin 13 mRNA", "GENE EXPRESSION", "SKIN BIOPSY", "LESIONAL", "CYCLE", "IL13_NONLES", "IL13", "Interleukin 13 mRNA", "GENE EXPRESSION", "SKIN BIOPSY", "NON-LESIONAL", "CYCLE", "SAL_CAMP", "CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "SALIVA", NA_character_, "ng/mL", "TS_CAMP_LES", "CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "TAPE STRIP", "LESIONAL", "ng/mL", "TS_CAMP_NONLES", "CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "TAPE STRIP", "NON-LESIONAL", "ng/mL")wide <- odm |> mutate( short = sub(".*\\.", "", ItemOID), is_date = grepl("DTC$", short) )dates <- wide |> filter(is_date, !is.na(Value) & Value != "") |> select( StudyOID, SubjectKey, StudyEventOID, ItemGroupOID, ItemGroupRepeatKey, LBDTC = Value )results <- wide |> filter(!is_date, short %in% test_meta$short, !is.na(Value) & Value != "") |> left_join(dates, by = c( "StudyOID", "SubjectKey", "StudyEventOID", "ItemGroupOID", "ItemGroupRepeatKey" ) ) |> left_join(test_meta, by = "short") |> mutate( event_short = sub(".*\\.", "", StudyEventOID), VISIT = case_when( event_short == "SCRN" ~ "SCREENING", event_short == "BL" ~ "BASELINE", event_short == "D21" ~ "DAY 21", event_short == "UNSCH" ~ "UNSCHEDULED" ), VISITNUM = case_when( event_short == "SCRN" ~ 1, event_short == "BL" ~ 2, event_short == "D21" ~ 3, event_short == "UNSCH" ~ 2 + as.numeric(ItemGroupRepeatKey) / 100, TRUE ~ NA_real_ ), not_done = Value == "NOT DONE", LBORRES = if_else(not_done, NA_character_, Value), LBORRESU = if_else(not_done, NA_character_, unit), LBSTRESC = if_else(not_done, NA_character_, Value), LBSTRESN = suppressWarnings(as.numeric(if_else(not_done, NA_character_, Value))), LBSTRESU = if_else(not_done, NA_character_, unit), LBSTAT = if_else(not_done, "NOT DONE", NA_character_), loc_rank = case_when( LBLOC == "LESIONAL" ~ 0L, LBLOC == "NON-LESIONAL" ~ 1L, TRUE ~ 2L ) ) |> arrange(SubjectKey, LBDTC, LBTESTCD, LBSPEC, loc_rank) |> group_by(SubjectKey) |> mutate(LBSEQ = row_number()) |> ungroup() |> mutate(DOMAIN = "LB") |> arrange(SubjectKey, LBSEQ) |> select( DOMAIN, STUDYID = StudyOID, USUBJID = SubjectKey, LBSEQ, VISIT, VISITNUM, LBTESTCD, LBTEST, LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC, LBSTRESN, LBSTRESU, LBSTAT, LBDTC )dir.create("/app/output", showWarnings = FALSE)write_csv(results, "/app/output/lb.csv", na = "")solutions/sdtm-lb-multiform/result.py
Edit173 lines# Reference solution for the yamaa benchmark sdtm-lb-multiform (Python track).## Written from the benchmark's full prompt and its inputs alone, as an agent# would write it. Harbor's oracle agent runs it to check that the prompt can# be solved and that the grader scores a correct answer 1.from pathlib import Pathimport polars as pldef _present(value) -> bool: return value is not None and str(value) != ""odm = pl.read_csv("/app/input/odm.csv", infer_schema=False)# Each form occurrence keeps its own date; lesional comes before# non-lesional from the same form.test_meta = { "VITD": ("VITD25OH", "25-Hydroxyvitamin D", "CHEMISTRY", "SERUM", None, "ng/mL"), "IL13_LES": ("IL13", "Interleukin 13 mRNA", "GENE EXPRESSION", "SKIN BIOPSY", "LESIONAL", "CYCLE"), "IL13_NONLES": ("IL13", "Interleukin 13 mRNA", "GENE EXPRESSION", "SKIN BIOPSY", "NON-LESIONAL", "CYCLE"), "SAL_CAMP": ("CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "SALIVA", None, "ng/mL"), "TS_CAMP_LES": ("CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "TAPE STRIP", "LESIONAL", "ng/mL"), "TS_CAMP_NONLES": ("CAMPPRO", "Cathelicidin Protein", "ANTIMICROBIAL PEPTIDE", "TAPE STRIP", "NON-LESIONAL", "ng/mL"),}visit_meta = { "SCRN": ("SCREENING", 1.0), "BL": ("BASELINE", 2.0), "D21": ("DAY 21", 3.0),}def _result_key(itemoid: str) -> str | None: short = itemoid.split(".")[-1] return short if short in test_meta else Nonegroups: dict[tuple, dict] = {}for row in odm.to_dicts(): key = ( str(row["StudyOID"]), str(row["SubjectKey"]), str(row["StudyEventOID"]), str(row["ItemGroupOID"]), str(row["ItemGroupRepeatKey"]), ) groups.setdefault(key, {})[str(row["ItemOID"])] = row["Value"]rows = []for (studyid, subj, event_oid, _group_oid, group_rep), values in groups.items(): event_short = event_oid.split(".")[-1] # The collection date from the date item on the same form. lbdtc = None for oid, val in values.items(): if oid.split(".")[-1].endswith("DTC") and _present(val): lbdtc = str(val).strip() if event_short == "UNSCH": visit, visitnum = "UNSCHEDULED", 2 + float(group_rep) / 100 else: visit, visitnum = visit_meta.get(event_short, (None, None)) for oid, val in values.items(): rkey = _result_key(oid) if rkey is None: continue text = str(val) if _present(val) else "" # An item with no reported value produces no record. if text == "": continue testcd, test, cat, spec, loc, unit = test_meta[rkey] if text == "NOT DONE": rows.append( { "DOMAIN": "LB", "STUDYID": studyid, "USUBJID": subj, "VISIT": visit, "VISITNUM": visitnum, "LBTESTCD": testcd, "LBTEST": test, "LBCAT": cat, "LBSPEC": spec, "LBLOC": loc, "LBORRES": None, "LBORRESU": None, "LBSTRESC": None, "LBSTRESN": None, "LBSTRESU": None, "LBSTAT": "NOT DONE", "LBDTC": lbdtc, } ) else: try: number = float(text) except ValueError: number = None rows.append( { "DOMAIN": "LB", "STUDYID": studyid, "USUBJID": subj, "VISIT": visit, "VISITNUM": visitnum, "LBTESTCD": testcd, "LBTEST": test, "LBCAT": cat, "LBSPEC": spec, "LBLOC": loc, "LBORRES": text, "LBORRESU": unit, "LBSTRESC": text, "LBSTRESN": number, "LBSTRESU": unit, "LBSTAT": None, "LBDTC": lbdtc, } )loc_rank = {"LESIONAL": 0, "NON-LESIONAL": 1, None: 2}rows.sort( key=lambda r: ( r["USUBJID"], r["LBDTC"] or "", r["LBTESTCD"], r["LBSPEC"], loc_rank[r["LBLOC"]], ))seq_by_subject: dict[str, int] = {}for row in rows: seq_by_subject[row["USUBJID"]] = seq_by_subject.get(row["USUBJID"], 0) + 1 row["LBSEQ"] = str(seq_by_subject[row["USUBJID"]])lb = ( pl.DataFrame( rows, schema={ "DOMAIN": pl.String, "STUDYID": pl.String, "USUBJID": pl.String, "LBSEQ": pl.String, "VISIT": pl.String, "VISITNUM": pl.Float64, "LBTESTCD": pl.String, "LBTEST": pl.String, "LBCAT": pl.String, "LBSPEC": pl.String, "LBLOC": pl.String, "LBORRES": pl.String, "LBORRESU": pl.String, "LBSTRESC": pl.String, "LBSTRESN": pl.Float64, "LBSTRESU": pl.String, "LBSTAT": pl.String, "LBDTC": pl.String, }, ) .with_columns( pl.col("LBSEQ").cast(pl.Int64).alias("_seq"), pl.col("VISITNUM").cast(pl.Float64).alias("_visitnum"), ) .sort(["USUBJID", "_seq"]) .select( "DOMAIN", "STUDYID", "USUBJID", "LBSEQ", "VISIT", "VISITNUM", "LBTESTCD", "LBTEST", "LBCAT", "LBSPEC", "LBLOC", "LBORRES", "LBORRESU", "LBSTRESC", "LBSTRESN", "LBSTRESU", "LBSTAT", "LBDTC", ))Path("/app/output").mkdir(exist_ok=True)lb.write_csv("/app/output/lb.csv")solutions/sdtm-lb-multiform/result.sas
Edit34 lines/* opensas reference solution for the yamaa benchmark sdtm-lb-multiform. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data odm; length StudyOID MetaDataVersionOID SubjectKey StudyEventOID StudyEventRepeatKey ItemGroupOID ItemGroupRepeatKey ItemOID Value $1024; infile "/app/input/odm.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input StudyOID : $char1024. MetaDataVersionOID : $char1024. SubjectKey : $char1024. StudyEventOID : $char1024. StudyEventRepeatKey : $char1024. ItemGroupOID : $char1024. ItemGroupRepeatKey : $char1024. ItemOID : $char1024. Value : $char1024.;run;data dateitems; set odm; if scan(ItemOID,-1,'.') in ('LBDTC','BXDTC','SALDTC','TSDTC'); run;proc sql; create table dates as select StudyOID,SubjectKey,StudyEventOID,StudyEventRepeatKey,ItemGroupOID,ItemGroupRepeatKey,max(Value) as LBDTC from dateitems group by StudyOID,SubjectKey,StudyEventOID,StudyEventRepeatKey,ItemGroupOID,ItemGroupRepeatKey;create table joined as select a.*,b.LBDTC from odm a inner join dates b on a.StudyOID=b.StudyOID and a.SubjectKey=b.SubjectKey and a.StudyEventOID=b.StudyEventOID and a.StudyEventRepeatKey=b.StudyEventRepeatKey and a.ItemGroupOID=b.ItemGroupOID and a.ItemGroupRepeatKey=b.ItemGroupRepeatKey; quit;data prepared; set joined; length DOMAIN $2 STUDYID USUBJID VISIT LBTESTCD LBTEST LBCAT LBSPEC LBLOC LBORRES LBORRESU LBSTRESC LBSTRESU LBSTAT KEY EVENT $1024;KEY=scan(ItemOID,-1,'.'); EVENT=scan(StudyEventOID,-1,'.'); if not missing(Value) and KEY in ('VITD','IL13_LES','IL13_NONLES','SAL_CAMP','TS_CAMP_LES','TS_CAMP_NONLES');DOMAIN='LB'; STUDYID=StudyOID; USUBJID=SubjectKey; LBORRES=Value; LBSTRESC=Value; LBSTRESN=.; LBORRESU='ng/mL'; LBLOC=''; LBSTAT=''; LOCORD=2;if Value ne 'NOT DONE' then LBSTRESN=input(Value,?? best32.);if KEY='VITD' then do; LBTESTCD='VITD25OH'; LBTEST='25-Hydroxyvitamin D'; LBCAT='CHEMISTRY'; LBSPEC='SERUM'; end;else if KEY in ('IL13_LES','IL13_NONLES') then do; LBTESTCD='IL13'; LBTEST='Interleukin 13 mRNA'; LBCAT='GENE EXPRESSION'; LBSPEC='SKIN BIOPSY'; LBORRESU='CYCLE'; end;else do; LBTESTCD='CAMPPRO'; LBTEST='Cathelicidin Protein'; LBCAT='ANTIMICROBIAL PEPTIDE'; if KEY='SAL_CAMP' then LBSPEC='SALIVA'; else LBSPEC='TAPE STRIP'; end;if KEY in ('IL13_LES','TS_CAMP_LES') then do; LBLOC='LESIONAL'; LOCORD=0; end;if KEY in ('IL13_NONLES','TS_CAMP_NONLES') then do; LBLOC='NON-LESIONAL'; LOCORD=1; end;VISITNUM=.; if EVENT='SCRN' then do; VISIT='SCREENING'; VISITNUM=1; end; if EVENT='BL' then do; VISIT='BASELINE'; VISITNUM=2; end; if EVENT='D21' then do; VISIT='DAY 21'; VISITNUM=3; end; if EVENT='UNSCH' then do; VISIT='UNSCHEDULED'; VISITNUM=2+input(ItemGroupRepeatKey,best32.)/100; end;LBSTRESU=LBORRESU; if Value='NOT DONE' then do; LBORRES=''; LBORRESU=''; LBSTRESC=''; LBSTRESN=.; LBSTRESU=''; LBSTAT='NOT DONE'; end; run;proc sort data=prepared; by STUDYID USUBJID LBDTC LBTESTCD LBSPEC LOCORD; run;data result; set prepared; by STUDYID USUBJID; retain LBSEQ; if first.USUBJID then LBSEQ=0; LBSEQ+1;run;proc sql; create table final as select DOMAIN, STUDYID, USUBJID, LBSEQ, VISIT, VISITNUM, LBTESTCD, LBTEST, LBCAT, LBSPEC, LBLOC, LBORRES, LBORRESU, LBSTRESC, LBSTRESN, LBSTRESU, LBSTAT, LBDTC from result;quit;proc export data=final outfile="/app/output/lb.csv" dbms=csv replace; run;
yamaa