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: build one EC (Exposure as Collected) record per dosing-log
day, carrying ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE,
ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, and
ECADJ.
Input: a daily dosing log, one row per subject per day, carrying the date, tablets taken, whether the dose was taken, the reason a dose was missed, and any dose adjustment.
Variables:
ECSEQnumbers the subject's dosing days in date order. WithSTUDYIDandUSUBJIDit identifies the record.ECMOODisPERFORMEDon every record: these are administrations as collected.ECOCCURisYwhen the subject took the day's dose,Nwhen the dose was not taken.ECREASNDis the reason the dose was not taken, for exampleSUBJECT FORGOT DOSE; blank when the dose was taken.ECDOSEis the tablets taken that day; blank on a day the dose was not taken.ECSTDTCandECENDTCare the dosing day, since one record covers one day.ECADJis the adjustment reason the log records for that day, for exampleDOSE REDUCED; blank when the day records none.
Note: a dose reduced after an adverse event carries the adjustment
reason (DOSE REDUCED), not the event. A missed day keeps the
treatment's unit, form, frequency, and route with no dose and the
missed reason.
Inputs
Under review1 source fileinput/dosing_log.csv
Edit10 rows| STUDYID | USUBJID | LOGDATE | TABLETS | DOSE_TAKEN | MISSREAS | DOSE_ADJ |
|---|---|---|---|---|---|---|
| YAMAA-01 | 2025-01-02 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-03 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-04 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-05 | — | N | SUBJECT FORGOT DOSE | — | |
| YAMAA-01 | 2025-01-06 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-02 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-03 | 2 | Y | — | — | |
| YAMAA-01 | 2025-01-04 | 1 | Y | — | DOSE REDUCED | |
| YAMAA-01 | 2025-01-05 | 1 | Y | — | DOSE REDUCED | |
| YAMAA-01 | 2025-01-06 | 1 | Y | — | DOSE REDUCED |
Expected output
Under review10 expected rowsexpected/ec.csv
Edit10 rows| DOMAIN | STUDYID | USUBJID | ECSEQ | ECTRT | ECMOOD | ECOCCUR | ECREASND | ECDOSE | ECDOSU | ECDOSFRM | ECDOSFRQ | ECROUTE | ECSTDTC | ECENDTC | ECADJ |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| EC | YAMAA-01 | 1 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-02 | 2025-01-02 | — | |
| EC | YAMAA-01 | 2 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-03 | 2025-01-03 | — | |
| EC | YAMAA-01 | 3 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-04 | 2025-01-04 | — | |
| EC | YAMAA-01 | 4 | Study Drug | PERFORMED | N | SUBJECT FORGOT DOSE | — | tablet | TABLET | QD | ORAL | 2025-01-05 | 2025-01-05 | — | |
| EC | YAMAA-01 | 5 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-06 | 2025-01-06 | — | |
| EC | YAMAA-01 | 1 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-02 | 2025-01-02 | — | |
| EC | YAMAA-01 | 2 | Study Drug | PERFORMED | Y | — | 2 | tablet | TABLET | QD | ORAL | 2025-01-03 | 2025-01-03 | — | |
| EC | YAMAA-01 | 3 | Study Drug | PERFORMED | Y | — | 1 | tablet | TABLET | QD | ORAL | 2025-01-04 | 2025-01-04 | DOSE REDUCED | |
| EC | YAMAA-01 | 4 | Study Drug | PERFORMED | Y | — | 1 | tablet | TABLET | QD | ORAL | 2025-01-05 | 2025-01-05 | DOSE REDUCED | |
| EC | YAMAA-01 | 5 | Study Drug | PERFORMED | Y | — | 1 | tablet | TABLET | QD | ORAL | 2025-01-06 | 2025-01-06 | DOSE REDUCED |
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 "EC". | SDTM | 1 | ||||
| STUDYID | Study Identifier | Char | Collected | Copy value from LOG.STUDYID. | SDTM | 2 | ||||
| USUBJID | Unique Subject Identifier | Char | Collected | Copy value from LOG.USUBJID. | SDTM | 3 | ||||
| ECTRT | Name of Treatment | Char | Assigned | Set constant value "Study Drug". | SDTM | 4 | ||||
| ECMOOD | Mood | Char | Assigned | Set constant value "PERFORMED". | SDTM | 5 | ||||
| ECOCCUR | EC Occurrence | Char | Collected | Copy value from LOG.DOSE_TAKEN. | SDTM | 6 | ||||
| ECREASND | Reason Not Dosed | Char | Collected | Copy value from LOG.MISSREAS. | SDTM | 7 | ||||
| ECDOSE | Dose | Num | Derived | If ECOCCUR = 'Y' then "LOG.TABLETS"; otherwise blank. | SDTM | 8 | ||||
| ECDOSU | Dose Units | Char | Assigned | Set constant value "tablet". | SDTM | 9 | ||||
| ECDOSFRM | Dose Form | Char | Assigned | Set constant value "TABLET". | SDTM | 10 | ||||
| ECDOSFRQ | Dosing Frequency per Interval | Char | Assigned | Set constant value "QD". | SDTM | 11 | ||||
| ECROUTE | Route of Administration | Char | Assigned | Set constant value "ORAL". | SDTM | 12 | ||||
| ECSTDTC | Start Date/Time of Treatment | Char | ISO 8601 | Collected | Copy value from LOG.LOGDATE. | SDTM | 13 | |||
| ECENDTC | End Date/Time of Treatment | Char | ISO 8601 | Collected | Copy value from LOG.LOGDATE. | SDTM | 14 | |||
| ECADJ | Reason for Dose Adjustment | Char | Collected | Copy value from LOG.DOSE_ADJ. | SDTM | 15 | ||||
| ECSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by LOG.LOGDATE. | SDTM | 16 |
| 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-ec-collected-exposure/full.md
Edit21 linesFollowing CDISC SDTM standards, use the provided LOG dataset to create an EC dataset with one record per dosing-log day.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE, ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, ECADJ
ECSEQ numbers the subject's dosing days in date order. ECTRT is Study Drug and ECMOOD is PERFORMED on every record. ECOCCUR is Y when the subject took the day's dose and N when the dose was not taken. ECREASND is the reason the dose was not taken, as the log records it, and has no value when the dose was taken. ECDOSE is the tablets taken that day, with no value on a day the dose was not taken. ECDOSU is tablet, ECDOSFRM is TABLET, ECDOSFRQ is QD, and ECROUTE is ORAL. ECSTDTC and ECENDTC are both the dosing day, since one record covers one day. ECADJ is the adjustment reason the log records for that day, and has no value when the day records none. A missed day keeps the unit, form, frequency, and route with no dose and the missed reason.
Read the source datasets from /app/input and save the completed dataset as /app/output/ec.csv.
prompts/sdtm-ec-collected-exposure/conventions.md
Edit12 linesFollowing CDISC SDTM standards, use the provided LOG dataset to create an EC dataset with one record per dosing-log day.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE, ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, ECADJ
ECTRT is Study Drug and ECMOOD is PERFORMED on every record. ECOCCUR is Y or N. ECDOSFRM is TABLET, ECDOSFRQ is QD, and ECROUTE is ORAL.
Read the source datasets from /app/input and save the completed dataset as /app/output/ec.csv.
prompts/sdtm-ec-collected-exposure/brief.md
Edit9 linesFollowing CDISC SDTM standards, use the provided LOG dataset to create an EC dataset with one record per dosing-log day.
The output dataset should contain the following columns in this order: DOMAIN, STUDYID, USUBJID, ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE, ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, ECADJ
Read the source datasets from /app/input and save the completed dataset as /app/output/ec.csv.
run.R
Edit4 lineslibrary(yamaa)ec <- yamaa_domain("spec.yaml")$outputecrun.py
Edit4 linesimport yamaaec = yamaa.yamaa_domain("spec.yaml").outputecsolutions/sdtm-ec-collected-exposure/result.R
Edit41 lines# Reference solution for the yamaa benchmark sdtm-ec-collected-exposure (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)log <- read_csv( "/app/input/dosing_log.csv", col_types = cols(.default = col_character()))ec <- log |> mutate( DOMAIN = "EC", ECTRT = "Study Drug", ECMOOD = "PERFORMED", ECOCCUR = DOSE_TAKEN, ECREASND = ifelse(DOSE_TAKEN == "Y", NA_character_, na_if(MISSREAS, "")), ECDOSE = suppressWarnings(as.integer(ifelse(DOSE_TAKEN == "Y", TABLETS, NA_character_))), ECDOSU = "tablet", ECDOSFRM = "TABLET", ECDOSFRQ = "QD", ECROUTE = "ORAL", ECSTDTC = suppressWarnings(as.Date(LOGDATE)), ECENDTC = suppressWarnings(as.Date(LOGDATE)), ECADJ = na_if(DOSE_ADJ, "") ) |> arrange(STUDYID, USUBJID, ECSTDTC) |> group_by(STUDYID, USUBJID) |> mutate(ECSEQ = row_number()) |> ungroup() |> select( DOMAIN, STUDYID, USUBJID, ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE, ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, ECADJ )dir.create("/app/output", showWarnings = FALSE)write_csv(ec, "/app/output/ec.csv", na = "")solutions/sdtm-ec-collected-exposure/result.py
Edit61 lines# Reference solution for the yamaa benchmark sdtm-ec-collected-exposure (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 pllog = pl.read_csv("/app/input/dosing_log.csv", infer_schema=False)ec = ( log.with_columns( DOMAIN=pl.lit("EC"), ECTRT=pl.lit("Study Drug"), ECMOOD=pl.lit("PERFORMED"), ECOCCUR=pl.col("DOSE_TAKEN"), ECREASND=pl.when(pl.col("DOSE_TAKEN") == "Y") .then(None) .otherwise(pl.col("MISSREAS")) .map_elements(lambda v: None if v == "" else v, return_dtype=pl.String), ECDOSE=pl.when(pl.col("DOSE_TAKEN") == "Y") .then(pl.col("TABLETS").cast(pl.Int64, strict=False)) .otherwise(None), ECDOSU=pl.lit("tablet"), ECDOSFRM=pl.lit("TABLET"), ECDOSFRQ=pl.lit("QD"), ECROUTE=pl.lit("ORAL"), ECSTDTC=pl.col("LOGDATE"), ECENDTC=pl.col("LOGDATE"), ECADJ=pl.col("DOSE_ADJ").map_elements( lambda v: None if v == "" or v is None else v, return_dtype=pl.String ), ) .with_columns(LOGDATE_DT=pl.col("LOGDATE").str.to_date(strict=False)) .sort(["STUDYID", "USUBJID", "LOGDATE_DT"]) .with_columns(ECSEQ=pl.col("USUBJID").cum_count().over(["STUDYID", "USUBJID"])) .with_columns(ECSEQ=pl.col("ECSEQ").cast(pl.Int64)) .select( "DOMAIN", "STUDYID", "USUBJID", "ECSEQ", "ECTRT", "ECMOOD", "ECOCCUR", "ECREASND", "ECDOSE", "ECDOSU", "ECDOSFRM", "ECDOSFRQ", "ECROUTE", "ECSTDTC", "ECENDTC", "ECADJ", ))Path("/app/output").mkdir(exist_ok=True)ec.write_csv("/app/output/ec.csv")solutions/sdtm-ec-collected-exposure/result.sas
Edit24 lines/* opensas reference solution for the yamaa benchmark sdtm-ec-collected-exposure. Reads the benchmark inputs and derives the requested output. Execute with the existing opensas runtime: opensas /app/output/result.sas. */data dosing_log; length STUDYID USUBJID LOGDATE TABLETS DOSE_TAKEN MISSREAS DOSE_ADJ $1024; infile "/app/input/dosing_log.csv" dsd dlm="," firstobs=2 truncover lrecl=32767; input STUDYID : $char1024. USUBJID : $char1024. LOGDATE : $char1024. TABLETS : $char1024. DOSE_TAKEN : $char1024. MISSREAS : $char1024. DOSE_ADJ : $char1024.;run;data prepared; set dosing_log; length DOMAIN $2 ECTRT ECMOOD ECOCCUR ECREASND ECDOSU ECDOSFRM ECDOSFRQ ECROUTE ECSTDTC ECENDTC ECADJ $1024;DOMAIN='EC'; ECTRT='Study Drug'; ECMOOD='PERFORMED'; ECOCCUR=DOSE_TAKEN; ECDOSE=.; ECREASND='';if ECOCCUR='Y' then ECDOSE=input(TABLETS,best32.); else ECREASND=MISSREAS;ECDOSU='tablet'; ECDOSFRM='TABLET'; ECDOSFRQ='QD'; ECROUTE='ORAL'; ECSTDTC=LOGDATE; ECENDTC=LOGDATE; ECADJ=DOSE_ADJ; run;proc sort data=prepared; by STUDYID USUBJID ECSTDTC; run;data result; set prepared; by STUDYID USUBJID; retain ECSEQ; if first.USUBJID then ECSEQ=0; ECSEQ+1;run;proc sql; create table final as select DOMAIN, STUDYID, USUBJID, ECSEQ, ECTRT, ECMOOD, ECOCCUR, ECREASND, ECDOSE, ECDOSU, ECDOSFRM, ECDOSFRQ, ECROUTE, ECSTDTC, ECENDTC, ECADJ from result;quit;proc export data=final outfile="/app/output/ec.csv" dbms=csv replace; run;
yamaa
Comments
Signed in with GitHub; saved in repository Discussions