As a clinical trial statistician or programmer, challenge anything in this benchmark: describe a problem in Comments, or propose a fix with the Edit button on any source file.
- Task: Would a real study need this derivation, specified this way? Does it follow CDISC SDTM: variable names, controlled terms, record structure? Flag any rule that is ambiguous or that a sponsor would handle differently.
- Inputs: Do they look like data collected in a real trial, and do they include the situations you would expect to meet in one?
- Expected output: Would independent QC programming reproduce every value from these inputs and rules?
The other tabs beside Comments are background for assessment, not under review.
Summary
README.mdGoal: map a pre-specified medical history checklist into MH and carry any number of volunteered free-text conditions alongside it.
Input: the ODM extract has one item record for each checklist condition asked, with a blank value when it was not answered. An item-definition table gives each checklist item its reported term and form order. Each volunteered condition has its own repeated free-text record. Repeat numbers can be reused at another visit.
Variables:
MHTERMis the checklist condition from the item-definition table, or the volunteered text exactly as reported. A checklist item the table does not define stops the run.MHCATisDISEASE-SPECIFIC HISTORYfor checklist records andGENERAL HISTORYfor volunteered records.MHPRESPisYfor checklist records and blank for volunteered records.MHOCCURisYorNfor an answered checklist condition and blank otherwise.MHSTATisNOT DONEfor an unanswered checklist condition and blank otherwise.MHSEQorders checklist conditions as shown on the form, then volunteered conditions by visit and form repeat.
Note: an unanswered checklist item still has an ODM record. A question entirely absent from the extract is not assumed to have been asked. Each volunteered condition is its own MH record, even when its repeat number is reused at another visit.
Inputs
Under review2 source filesinput/mh_items.csv
Edit3 rows| ItemOID | MHTERM | SORTORD |
|---|---|---|
| IT.MH.DIABETES | DIABETES MELLITUS | 1 |
| IT.MH.HYPERTENSION | HYPERTENSION | 2 |
| IT.MH.ASTHMA | ASTHMA | 3 |
input/odm.csv
Edit10 rows| StudyOID | MetaDataVersionOID | SubjectKey | StudyEventOID | StudyEventRepeatKey | ItemGroupOID | ItemGroupRepeatKey | ItemOID | Value |
|---|---|---|---|---|---|---|---|---|
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.DIABETES | Y |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.HYPERTENSION | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.ASTHMA | — |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Seasonal allergies |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.DIABETES | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.HYPERTENSION | Y |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.CHECKLIST | 1 | IT.MH.ASTHMA | N |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | SCREENING | 1 | IG.MH.FREETEXT | 2 | IT.MH.MHTERM | Migraine |
| YAMAA-01 | MDV.1 | YAMAA-01-0001 | BASELINE | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Back pain |
| YAMAA-01 | MDV.1 | YAMAA-01-0002 | SCREENING | 1 | IG.MH.FREETEXT | 1 | IT.MH.MHTERM | Appendectomy |
Expected output
Under review10 expected rowsexpected/mh.csv
Edit10 rows| DOMAIN | STUDYID | USUBJID | MHSEQ | MHTERM | MHCAT | MHPRESP | MHOCCUR | MHSTAT |
|---|---|---|---|---|---|---|---|---|
| MH | YAMAA-01 | 1 | DIABETES MELLITUS | DISEASE-SPECIFIC HISTORY | Y | Y | — | |
| MH | YAMAA-01 | 2 | HYPERTENSION | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 3 | ASTHMA | DISEASE-SPECIFIC HISTORY | Y | — | NOT DONE | |
| MH | YAMAA-01 | 4 | Seasonal allergies | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 5 | Migraine | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 6 | Back pain | GENERAL HISTORY | — | — | — | |
| MH | YAMAA-01 | 1 | DIABETES MELLITUS | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 2 | HYPERTENSION | DISEASE-SPECIFIC HISTORY | Y | Y | — | |
| MH | YAMAA-01 | 3 | ASTHMA | DISEASE-SPECIFIC HISTORY | Y | N | — | |
| MH | YAMAA-01 | 4 | Appendectomy | GENERAL HISTORY | — | — | — |
Comments and assessment materials
| 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 | Assigned | Set constant value "MH". | 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 | ||||
| MHTERM | Reported Term for the Medical History | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 4 | ||||
| MHCAT | Category for Medical History | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 5 | ||||
| MHPRESP | Pre-Specified Medical History Indicator | Char | Y | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 6 | |||
| MHOCCUR | Medical History Occurrence | Char | Y, N | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 7 | |||
| MHSTAT | Completion Status | Char | NOT DONE | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 8 | |||
| MHSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by SORTORD then EVENTORD then EVENTREPEAT then REPEATKEY. | SDTM | 9 |
| Template | Include when | MHTERM | MHCAT | MHPRESP | MHOCCUR | MHSTAT | SORTORD | EVENTORD |
|---|---|---|---|---|---|---|---|---|
| checklist | ODM.StudyEventOID = 'SCREENING' AND ODM.ItemGroupOID = 'IG.MH.CHECKLIST' | If ODM.ItemGroupOID = 'IG.MH.CHECKLIST' then "MH_MAP.MHTERM"; otherwise "None" | Constant "DISEASE-SPECIFIC HISTORY" | Constant "Y" | If ODM.Value = 'Y' then "Y"; If ODM.Value = 'N' then "N"; otherwise "None" | If ODM.Value IS NULL then "NOT DONE"; otherwise "None" | If ODM.ItemGroupOID = 'IG.MH.CHECKLIST' then "MH_MAP.SORTORD"; otherwise "None" | If ODM.StudyEventOID IN ('SCREENING', 'BASELINE') then recode ODM.StudyEventOID: "SCREENING" → "1", "BASELINE" → "2"; missing or unlisted values are errors; otherwise "99" |
| volunteered | ODM.ItemGroupOID = 'IG.MH.FREETEXT' AND ODM.ItemOID = 'IT.MH.MHTERM' AND ODM.Value IS NOT NULL | Copy ODM.Value | Constant "GENERAL HISTORY" | Constant "None" | Constant "None" | Constant "None" | Constant "4" | If ODM.ItemGroupOID = 'IG.MH.FREETEXT' AND ODM.ItemOID = 'IT.MH.MHTERM' AND ODM.Value IS NOT NULL then recode ODM.StudyEventOID: "SCREENING" → "1", "BASELINE" → "2"; missing or unlisted values are errors; otherwise "99" |
| Variable | Permitted values |
|---|---|
| MHPRESP | Y |
| MHOCCUR | Y, N |
| MHSTAT | NOT DONE |
| Version | Date | Author | Description | Reviewer | Sign-off |
|---|---|---|---|---|---|
| 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-mh-prespecified-conditions/full.md
Edit26 linesFollowing CDISC SDTM standards, use the provided ODM and MH_ITEMS datasets to create an MH dataset with one record per checklist condition and per volunteered free-text condition.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
STUDYID is the ODM StudyOID and USUBJID is the SubjectKey, each as given.
MHTERM is the checklist condition from the item-definition table, or the volunteered text exactly as reported. MHCAT is DISEASE-SPECIFIC HISTORY for checklist records and GENERAL HISTORY for volunteered records. MHPRESP is Y for checklist records and has no value for volunteered records. MHOCCUR is Y or N for an answered checklist condition and has no value otherwise. MHSTAT is NOT DONE for an unanswered checklist condition and has no value otherwise. MHSEQ numbers each subject's records from 1: checklist conditions in the table's SORTORD order, then volunteered conditions by visit (SCREENING before BASELINE) and form repeat.
An unanswered checklist item still has an extract record. A question entirely absent from the extract is not assumed to have been asked. Each volunteered condition is its own MH record, even when its repeat number is reused at another visit.
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
prompts/sdtm-mh-prespecified-conditions/conventions.md
Edit13 linesFollowing CDISC SDTM standards, use the provided ODM and MH_ITEMS datasets to create an MH dataset with one record per checklist condition and per volunteered free-text condition.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
MHCAT is DISEASE-SPECIFIC HISTORY for checklist records and GENERAL HISTORY for volunteered records. MHPRESP is Y or has no value. MHOCCUR is Y or N, or has no value. MHSTAT is NOT DONE or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
prompts/sdtm-mh-prespecified-conditions/brief.md
Edit9 linesFollowing CDISC SDTM standards, use the provided ODM and MH_ITEMS datasets to create an MH dataset with one record per checklist condition and per volunteered free-text condition.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT
Read the source datasets from /app/input and save the completed dataset as /app/output/mh.csv.
run.R
Edit4 lineslibrary(yamaa)mh <- yamaa_domain("spec.yaml")$outputmhrun.py
Edit4 linesimport yamaamh = yamaa.yamaa_domain("spec.yaml").outputmhsolutions/sdtm-mh-prespecified-conditions/result.R
Edit76 lines# Reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions (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)items <- read_csv( "/app/input/mh_items.csv", col_types = cols(SORTORD = col_integer(), .default = col_character()))odm <- read_csv( "/app/input/odm.csv", col_types = cols(.default = col_character()))checklist_oids <- intersect(items$ItemOID, unique(odm$ItemOID))checklist <- odm |> filter(ItemOID %in% checklist_oids) |> group_by(StudyOID, SubjectKey, ItemOID) |> slice_tail(n = 1) |> ungroup() |> left_join(items |> select(ItemOID, MHTERM, SORTORD), by = "ItemOID") |> mutate( answered = Value %in% c("Y", "N"), MHTERM = MHTERM, MHCAT = "DISEASE-SPECIFIC HISTORY", MHPRESP = "Y", MHOCCUR = if_else(answered, Value, NA_character_), MHSTAT = if_else(answered, NA_character_, "NOT DONE"), visit_rank = 0L, repeat_no = 0L ) |> select( STUDYID = StudyOID, USUBJID = SubjectKey, ItemOID, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT, SORTORD, visit_rank, repeat_no )volunteered <- odm |> filter(!ItemOID %in% checklist_oids, !is.na(Value) & Value != "") |> mutate( MHTERM = Value, MHCAT = "GENERAL HISTORY", MHPRESP = NA_character_, MHOCCUR = NA_character_, MHSTAT = NA_character_, SORTORD = NA_integer_, visit_rank = case_when( StudyEventOID == "SCREENING" ~ 0L, StudyEventOID == "BASELINE" ~ 1L, TRUE ~ 99L ), repeat_no = suppressWarnings(as.integer(ItemGroupRepeatKey)) ) |> select( STUDYID = StudyOID, USUBJID = SubjectKey, ItemOID, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT, SORTORD, visit_rank, repeat_no )mh <- bind_rows(checklist, volunteered) |> arrange(USUBJID, is.na(SORTORD), SORTORD, visit_rank, repeat_no) |> group_by(USUBJID) |> mutate(MHSEQ = row_number()) |> ungroup() |> mutate(DOMAIN = "MH") |> arrange(USUBJID, MHSEQ) |> select( DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT )dir.create("/app/output", showWarnings = FALSE)write_csv(mh, "/app/output/mh.csv", na = "")solutions/sdtm-mh-prespecified-conditions/result.py
Edit114 lines# Reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions (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) != ""items = pl.read_csv("/app/input/mh_items.csv", infer_schema=False)odm = pl.read_csv("/app/input/odm.csv", infer_schema=False)meta = {row["ItemOID"]: (row["MHTERM"], int(row["SORTORD"])) for row in items.to_dicts()}checklist_oids = {oid for oid in meta if (odm["ItemOID"] == oid).any()}visit_order = {"SCREENING": 0, "BASELINE": 1}records_by_subject: dict[tuple[str, str], dict] = {}for row in odm.to_dicts(): studyid, usubjid = str(row["StudyOID"]), str(row["SubjectKey"]) key = (studyid, usubjid) records_by_subject.setdefault(key, {"checklist": {}, "volunteered": []})for row in odm.to_dicts(): key = (str(row["StudyOID"]), str(row["SubjectKey"])) oid, value = str(row["ItemOID"]), row["Value"] if oid in checklist_oids: # Last collected answer wins when an item repeats, including blanks. records_by_subject[key]["checklist"][oid] = value if _present(value) else None elif not _present(value): continue else: # Each volunteered condition is its own record, even when its # repeat number is reused at another visit. event = str(row["StudyEventOID"]) records_by_subject[key]["volunteered"].append( { "term": str(value), "visit_rank": visit_order.get(event, 99), "repeat": int(row["ItemGroupRepeatKey"] or 1), } )rows = []for (studyid, usubjid), parts in records_by_subject.items(): ordered = sorted(parts["checklist"].items(), key=lambda kv: meta[kv[0]][1]) seq = 0 for oid, answer in ordered: seq += 1 term, _ = meta[oid] answered = answer in ("Y", "N") rows.append( { "DOMAIN": "MH", "STUDYID": studyid, "USUBJID": usubjid, "MHSEQ": str(seq), "MHTERM": term, "MHCAT": "DISEASE-SPECIFIC HISTORY", "MHPRESP": "Y", "MHOCCUR": answer if answered else None, "MHSTAT": None if answered else "NOT DONE", } ) volunteered = sorted( parts["volunteered"], key=lambda v: (v["visit_rank"], v["repeat"]) ) for entry in volunteered: seq += 1 rows.append( { "DOMAIN": "MH", "STUDYID": studyid, "USUBJID": usubjid, "MHSEQ": str(seq), "MHTERM": entry["term"], "MHCAT": "GENERAL HISTORY", "MHPRESP": None, "MHOCCUR": None, "MHSTAT": None, } )mh = ( pl.DataFrame( rows, schema={ "DOMAIN": pl.String, "STUDYID": pl.String, "USUBJID": pl.String, "MHSEQ": pl.String, "MHTERM": pl.String, "MHCAT": pl.String, "MHPRESP": pl.String, "MHOCCUR": pl.String, "MHSTAT": pl.String, }, ) .with_columns(pl.col("MHSEQ").cast(pl.Int64).alias("_seq")) .sort(["USUBJID", "_seq"]) .select( "DOMAIN", "STUDYID", "USUBJID", "MHSEQ", "MHTERM", "MHCAT", "MHPRESP", "MHOCCUR", "MHSTAT", ))Path("/app/output").mkdir(exist_ok=True)mh.write_csv("/app/output/mh.csv")solutions/sdtm-mh-prespecified-conditions/result.sas
Edit33 lines/* opensas reference solution for the yamaa benchmark sdtm-mh-prespecified-conditions. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data mh_items; length ItemOID MHTERM SORTORD $1024; infile "/app/input/mh_items.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input ItemOID : $char1024. MHTERM : $char1024. SORTORD : $char1024.;run;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 authored; set odm; ordinal=_n_; run;proc sql; create table checklist as select a.*,b.MHTERM,b.SORTORD from authored a inner join mh_items b on a.ItemOID=b.ItemOID; quit;proc sort data=checklist; by StudyOID SubjectKey ItemOID ordinal; run;data checklistlast; set checklist; by StudyOID SubjectKey ItemOID; if last.ItemOID; run;data checklistout; set checklistlast; length DOMAIN $2 STUDYID USUBJID MHCAT MHPRESP MHOCCUR MHSTAT $1024; DOMAIN='MH'; STUDYID=StudyOID; USUBJID=SubjectKey; MHCAT='DISEASE-SPECIFIC HISTORY'; MHPRESP='Y'; MHOCCUR=''; MHSTAT='NOT DONE'; if Value in ('Y','N') then do; MHOCCUR=Value; MHSTAT=''; end; SECTION=0; ORD=input(SORTORD,best32.); VISITORD=0; REP=0; run;data volunteered; set odm; where ItemOID='IT.MH.MHTERM' and not missing(Value); length DOMAIN $2 STUDYID USUBJID MHTERM MHCAT MHPRESP MHOCCUR MHSTAT $1024; DOMAIN='MH'; STUDYID=StudyOID; USUBJID=SubjectKey; MHTERM=Value; MHCAT='GENERAL HISTORY'; MHPRESP=''; MHOCCUR=''; MHSTAT=''; SECTION=1; ORD=0; VISITORD=0; if StudyEventOID='BASELINE' then VISITORD=1; REP=input(ItemGroupRepeatKey,best32.); run;data prepared; set checklistout volunteered; run;proc sort data=prepared; by STUDYID USUBJID SECTION ORD VISITORD REP; run;data result; set prepared; by STUDYID USUBJID; retain MHSEQ; if first.USUBJID then MHSEQ=0; MHSEQ+1;run;proc sql; create table final as select DOMAIN, STUDYID, USUBJID, MHSEQ, MHTERM, MHCAT, MHPRESP, MHOCCUR, MHSTAT from result;quit;proc export data=final outfile="/app/output/mh.csv" dbms=csv replace; run;
yamaa
Comments
Signed in with GitHub; saved in repository Discussions