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: build one RS record per subject and scheduled tumor
assessment holding the visit order (AVISITN), the assessment date
(ADT), a per-subject record number (RSSEQ), the response test
(RSTESTCD/RSTEST), the response (RSSTRESC), and the completion
status (RSSTAT).
Input: long-form Operational Data Model (ODM) item data. Each
scheduled tumor assessment (IG.VISIT) carries its visit name, visit
order, and date. Each lesion measured at an assessment is a repeated
item group, IG.TRTARGET for a target lesion and IG.TRNT for a
non-target one, carrying the lesion link and the longest diameter. The
lesions chosen at study entry are listed in IG.TUTARGET and
IG.TUNT.
Variables:
AVISITNis the numeric order of the assessment, carried from the scheduled assessment; it orders the assessments of a subject.ADTis the date of the assessment, carried from the scheduled assessment.RSSEQnumbers a subject's response records in visit order, starting at 1.RSTESTCDisTRGRESPandRSTESTisTarget Responseon every record: the response of the target lesions alone.RSSTRESCis the response at the assessment:NE(not evaluable) at baseline, when fewer target lesions were measured than were chosen, when the subject has non-target disease only, or when no percent change can be computed (for example a zero or missing baseline sum);CR(complete response) when every target lesion has disappeared;PR(partial response) when the target sum shrank at least 30% from baseline;PD(progressive disease) when it grew at least 20% from baseline;SD(stable disease) otherwise. It stays blank when the assessment was not done.RSSTATisNOT DONEfor a scheduled assessment with no tumor measurement records at all; blank otherwise.
Note: a baseline assessment is never compared against itself, so
its response is NE whenever it was done. An assessment with some but
not all chosen target lesions measured is still done, and its response
is NE rather than a guess from partial data.
Inputs
Under review1 source fileinput/odm.csv
Edit66 rows| StudyOID | MetaDataVersionOID | SubjectKey | StudyEventOID | StudyEventRepeatKey | ItemGroupOID | ItemGroupRepeatKey | ItemOID | Value |
|---|---|---|---|---|---|---|---|---|
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | BASELINE |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 0 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-01-05 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | WEEK 8 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 8 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-03-02 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.LDIAM | 40 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.TRLNKID | L2 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.LDIAM | 25 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 3 | IT.TR.TRLNKID | L3 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 3 | IT.TR.LDIAM | 15 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TRTARGET | 3 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.LDIAM | 30 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.TRLNKID | L2 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.LDIAM | 20 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 3 | IT.TR.TRLNKID | L3 |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 3 | IT.TR.LDIAM | — |
| PILOT7 | MDV.1 | P7-921 | WEEK8 | 1 | IG.TRTARGET | 3 | IT.TR.TRSTAT | NOT DONE |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TUTARGET | 1 | IT.TU.TULNKID | L1 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TUTARGET | 2 | IT.TU.TULNKID | L2 |
| PILOT7 | MDV.1 | P7-921 | BASELINE | 1 | IG.TUTARGET | 3 | IT.TU.TULNKID | L3 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | BASELINE |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 0 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-01-12 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | WEEK 8 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 8 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-03-09 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.LDIAM | 22 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.TRLNKID | L2 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.LDIAM | 18 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TRTARGET | 2 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.LDIAM | 12 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.TRLNKID | L2 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.LDIAM | 10 |
| PILOT7 | MDV.1 | P7-922 | WEEK8 | 1 | IG.TRTARGET | 2 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TUTARGET | 1 | IT.TU.TULNKID | L1 |
| PILOT7 | MDV.1 | P7-922 | BASELINE | 1 | IG.TUTARGET | 2 | IT.TU.TULNKID | L2 |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | BASELINE |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 0 |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-01-19 |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | WEEK 8 |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 8 |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-03-16 |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.TRNT | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.TRNT | 1 | IT.TR.LDIAM | 20 |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.TRNT | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.TRNT | 1 | IT.TR.TRLNKID | L1 |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.TRNT | 1 | IT.TR.LDIAM | 22 |
| PILOT7 | MDV.1 | P7-923 | WEEK8 | 1 | IG.TRNT | 1 | IT.TR.TRSTAT | — |
| PILOT7 | MDV.1 | P7-923 | BASELINE | 1 | IG.TUNT | 1 | IT.TU.TULNKID | L1 |
| PILOT7 | MDV.1 | P7-924 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | BASELINE |
| PILOT7 | MDV.1 | P7-924 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 0 |
| PILOT7 | MDV.1 | P7-924 | BASELINE | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-02-02 |
| PILOT7 | MDV.1 | P7-924 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISIT | WEEK 8 |
| PILOT7 | MDV.1 | P7-924 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.AVISITN | 8 |
| PILOT7 | MDV.1 | P7-924 | WEEK8 | 1 | IG.VISIT | 1 | IT.VISIT.ADT | 2025-03-30 |
Expected output
Under review8 expected rowsexpected/rs.csv
Edit8 rows| STUDYID | USUBJID | AVISIT | AVISITN | ADT | RSSEQ | RSTESTCD | RSTEST | RSSTRESC | RSSTAT |
|---|---|---|---|---|---|---|---|---|---|
| PILOT7 | BASELINE | 0 | 2025-01-05 | 1 | TRGRESP | Target Response | NE | — | |
| PILOT7 | WEEK 8 | 8 | 2025-03-02 | 2 | TRGRESP | Target Response | NE | — | |
| PILOT7 | BASELINE | 0 | 2025-01-12 | 1 | TRGRESP | Target Response | NE | — | |
| PILOT7 | WEEK 8 | 8 | 2025-03-09 | 2 | TRGRESP | Target Response | PR | — | |
| PILOT7 | BASELINE | 0 | 2025-01-19 | 1 | TRGRESP | Target Response | NE | — | |
| PILOT7 | WEEK 8 | 8 | 2025-03-16 | 2 | TRGRESP | Target Response | NE | — | |
| PILOT7 | BASELINE | 0 | 2025-02-02 | 1 | TRGRESP | Target Response | — | NOT DONE | |
| PILOT7 | WEEK 8 | 8 | 2025-03-30 | 2 | TRGRESP | Target Response | — | NOT DONE |
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 |
|---|---|---|---|---|---|---|---|---|---|---|
| STUDYID | Study Identifier | Char | Collected | Copy value from ODM.StudyOID. | SDTM | 1 | ||||
| USUBJID | Unique Subject Identifier | Char | Collected | Copy value from ODM.SubjectKey. | SDTM | 2 | ||||
| AVISIT | Analysis Visit | Char | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 3 | ||||
| AVISITN | Analysis Visit (N) | Num | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 4 | ||||
| ADT | Analysis Date | Char | ISO 8601 | Derived | Set per constructed row; see the Row construction sheet. | SDTM | 5 | |||
| RSSEQ | Sequence Number | Num | Derived | Row number within each group of STUDYID, USUBJID, ordered by AVISITN. | SDTM | 6 | ||||
| RSTESTCD | Response Test Short Name | Char | Assigned | Set constant value "TRGRESP". | SDTM | 7 | ||||
| RSTEST | Response Test Name | Char | Assigned | Set constant value "Target Response". | SDTM | 8 | ||||
| RSSTAT | Completion Status | Char | Derived | If NTR IS NULL OR NTR = 0 then "NOT DONE"; otherwise blank. | SDTM | 9 | ||||
| RSSTRESC | Result or Finding in Standard Format | Char | CR, PR, SD, PD, NE | Derived | If RSSTAT = 'NOT DONE' then "None"; If AVISIT = 'BASELINE' then "NE"; If NTARGET IS NULL OR NTARGET = 0 then "NE"; If NMEAS IS NULL OR NMEAS < NTARGET then "NE"; If PCHG IS NULL then "NE"; If SUMV = 0 then "CR"; If PCHG <= -30 then "PR"; If PCHG >= 20 then "PD"; otherwise "SD". | SDTM | 10 |
| Template | Include when | AVISIT | AVISITN | ADT |
|---|---|---|---|---|
| visit | AVISITN IS NOT NULL | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.VISIT.AVISIT' | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.VISIT.AVISITN' | Aggregate ONLY(ODM.Value) over records matching on the shared output keys, where ODM.ItemOID = 'IT.VISIT.ADT' |
| Variable | Permitted values |
|---|---|
| RSSTRESC | CR, PR, SD, PD, NE |
| 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-rs-timepoint-response/full.md
Edit29 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an RS dataset with one record per subject and scheduled tumor assessment.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, AVISIT, AVISITN, ADT, RSSEQ, RSTESTCD, RSTEST, RSSTRESC, RSSTAT
STUDYID is the ODM study OID and USUBJID is the ODM subject key, each as given. AVISIT is the name of the scheduled assessment, AVISITN is its numeric order, and ADT is its date. RSSEQ numbers a subject's records in visit order, starting at 1. RSTESTCD is "TRGRESP" and RSTEST is "Target Response" on every record. RSSTAT is "NOT DONE" for a scheduled assessment with no tumor measurement records at all, and has no value otherwise. RSSTRESC has no value when the assessment was not done. A baseline assessment is never compared against itself, so its response is "NE" whenever it was done. RSSTRESC is "NE" when fewer target lesions were measured at the assessment than were chosen at study entry. An assessment at which some but not all of the chosen target lesions were measured is still done, and its response is "NE". RSSTRESC is "NE" when the subject has non-target disease only. RSSTRESC is "NE" when no percent change from baseline can be computed, for example when the baseline target sum is zero or missing. The target sum at an assessment is the sum of the longest diameters of the target lesions measured at that assessment. RSSTRESC is "CR" when every target lesion has disappeared. RSSTRESC is "PR" when the target sum shrank at least 30% from baseline. RSSTRESC is "PD" when the target sum grew at least 20% from baseline. RSSTRESC is "SD" otherwise.
Read the source datasets from /app/input and save the completed dataset as /app/output/rs.csv.
prompts/sdtm-rs-timepoint-response/conventions.md
Edit13 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an RS dataset with one record per subject and scheduled tumor assessment.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, AVISIT, AVISITN, ADT, RSSEQ, RSTESTCD, RSTEST, RSSTRESC, RSSTAT
RSTESTCD is "TRGRESP" and RSTEST is "Target Response" on every record. RSSTRESC is "CR", "PR", "SD", or "NE", or has no value. RSSTAT is "NOT DONE" or has no value.
Read the source datasets from /app/input and save the completed dataset as /app/output/rs.csv.
prompts/sdtm-rs-timepoint-response/brief.md
Edit9 linesFollowing CDISC SDTM standards, use the provided ODM dataset to create an RS dataset with one record per subject and scheduled tumor assessment.
The output dataset should contain the following columns in this order: STUDYID, USUBJID, AVISIT, AVISITN, ADT, RSSEQ, RSTESTCD, RSTEST, RSSTRESC, RSSTAT
Read the source datasets from /app/input and save the completed dataset as /app/output/rs.csv.
R
Edit3 lineslibrary(yamaa)yamaa_spec("spec.yaml")$run()$outputPython
Edit3 linesimport yamaayamaa.spec("spec.yaml").run().outputsolutions/sdtm-rs-timepoint-response/result.R
Edit136 lines# Reference solution for the yamaa benchmark sdtm-rs-timepoint-response (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()))visits <- odm |> filter(ItemGroupOID == "IG.VISIT") |> pivot_wider( id_cols = c(StudyOID, SubjectKey, StudyEventOID), names_from = ItemOID, values_from = Value, values_fn = function(x) x[[1]] )tr_target <- odm |> filter(grepl("TARGET", ItemGroupOID, fixed = TRUE), startsWith(ItemGroupOID, "IG.TR")) |> pivot_wider( id_cols = c(StudyOID, SubjectKey, StudyEventOID, ItemGroupRepeatKey), names_from = ItemOID, values_from = Value, values_fn = function(x) x[[1]] )tr_any <- odm |> filter(startsWith(ItemGroupOID, "IG.TR")) |> count(SubjectKey, StudyEventOID, name = "n_tr")tu_target <- odm |> filter(grepl("TARGET", ItemGroupOID, fixed = TRUE), startsWith(ItemGroupOID, "IG.TU"), StudyEventOID == "BASELINE", ItemOID == "IT.TU.TULNKID", !is.na(Value) & Value != "") |> distinct(SubjectKey, Value)response_one <- function(subj, event, avisitn, base_sum, n_chosen, post_diams, has_records) { if (!has_records) { return(list(rsstresc = NA_character_, rsstat = "NOT DONE")) } if (event == "BASELINE") { return(list(rsstresc = "NE", rsstat = NA_character_)) } if (n_chosen == 0) { return(list(rsstresc = "NE", rsstat = NA_character_)) } measured <- post_diams[!is.na(post_diams) & post_diams != ""] if (length(measured) < n_chosen) { return(list(rsstresc = "NE", rsstat = NA_character_)) } if (is.na(base_sum) || base_sum == 0) { return(list(rsstresc = "NE", rsstat = NA_character_)) } post <- sum(suppressWarnings(as.numeric(measured))) if (all(suppressWarnings(as.numeric(measured)) == 0)) { return(list(rsstresc = "CR", rsstat = NA_character_)) } if ((base_sum - post) / base_sum >= 0.30) { return(list(rsstresc = "PR", rsstat = NA_character_)) } if ((post - base_sum) / base_sum >= 0.20) { return(list(rsstresc = "PD", rsstat = NA_character_)) } list(rsstresc = "SD", rsstat = NA_character_)}subjects <- unique(visits$SubjectKey)out <- list()for (subj in subjects) { chosen <- nrow(tu_target |> filter(SubjectKey == subj)) if (chosen == 0) { chosen <- nrow(tr_target |> filter(SubjectKey == subj, StudyEventOID == "BASELINE")) } base_rows <- tr_target |> filter(SubjectKey == subj, StudyEventOID == "BASELINE") base_diams <- base_rows$IT.TR.LDIAM base_sum <- if (chosen == 0) { NA_real_ } else if (any(is.na(base_diams) | base_diams == "")) { NA_real_ } else { sum(suppressWarnings(as.numeric(base_diams))) } subj_visits <- visits |> filter(SubjectKey == subj) |> arrange(suppressWarnings(as.integer(IT.VISIT.AVISITN))) seq <- 0L for (i in seq_len(nrow(subj_visits))) { seq <- seq + 1L event <- subj_visits$StudyEventOID[[i]] n_rec <- tr_any |> filter(SubjectKey == subj, StudyEventOID == event) |> pull(n_tr) has_records <- length(n_rec) > 0 && n_rec[[1]] > 0 post_diams <- tr_target |> filter(SubjectKey == subj, StudyEventOID == event) |> pull(IT.TR.LDIAM) resp <- response_one( subj, event, subj_visits$IT.VISIT.AVISITN[[i]], base_sum, chosen, post_diams, has_records ) out[[length(out) + 1]] <- tibble( STUDYID = subj_visits$StudyOID[[i]], USUBJID = subj, AVISIT = subj_visits$IT.VISIT.AVISIT[[i]], AVISITN = subj_visits$IT.VISIT.AVISITN[[i]], ADT = subj_visits$IT.VISIT.ADT[[i]], RSSEQ = seq, RSTESTCD = "TRGRESP", RSTEST = "Target Response", RSSTRESC = resp$rsstresc, RSSTAT = resp$rsstat ) }}rs <- bind_rows(out) |> arrange(USUBJID, suppressWarnings(as.integer(AVISITN))) |> select( STUDYID, USUBJID, AVISIT, AVISITN, ADT, RSSEQ, RSTESTCD, RSTEST, RSSTRESC, RSSTAT )dir.create("/app/output", showWarnings = FALSE)write_csv(rs, "/app/output/rs.csv", na = "")solutions/sdtm-rs-timepoint-response/result.py
Edit159 lines# Reference solution for the yamaa benchmark sdtm-rs-timepoint-response (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.import csvimport osfrom collections import defaultdictINPUT = "/app/input"OUTPUT = "/app/output"COLUMNS = [ "STUDYID", "USUBJID", "AVISIT", "AVISITN", "ADT", "RSSEQ", "RSTESTCD", "RSTEST", "RSSTRESC", "RSSTAT",]def load_items(path): """Pivot the long ODM extract into per-group item dictionaries.""" groups = {} order = [] with open(path, newline="") as handle: for row in csv.DictReader(handle): key = ( row["StudyOID"], row["SubjectKey"], row["StudyEventOID"], row["StudyEventRepeatKey"], row["ItemGroupOID"], row["ItemGroupRepeatKey"], ) if key not in groups: groups[key] = { "study": row["StudyOID"], "subject": row["SubjectKey"], "event": row["StudyEventOID"], "group": row["ItemGroupOID"], "items": {}, } order.append(key) groups[key]["items"][row["ItemOID"]] = (row["Value"] or "").strip() return [groups[key] for key in order]def to_number(text): if text in (None, ""): return None try: return float(text) except ValueError: return Nonedef main(): records = load_items(os.path.join(INPUT, "odm.csv")) visits = defaultdict(list) # subject -> [visit dicts] chosen_targets = defaultdict(set) # subject -> {lesion ids chosen} target_meas = defaultdict(dict) # (subject, event) -> {lesion: ldiam} any_meas = defaultdict(bool) # (subject, event) -> any tumor record for rec in records: subject = rec["subject"] items = rec["items"] if rec["group"] == "IG.VISIT": visits[subject].append({ "event": rec["event"], "avisit": items.get("IT.VISIT.AVISIT", ""), "avisitn": items.get("IT.VISIT.AVISITN", ""), "adt": items.get("IT.VISIT.ADT", ""), }) elif rec["group"] == "IG.TUTARGET": link = items.get("IT.TU.TULNKID", "") if link: chosen_targets[subject].add(link) elif rec["group"] == "IG.TRTARGET": link = items.get("IT.TR.TRLNKID", "") if link: key = (subject, rec["event"]) any_meas[key] = True target_meas[key][link] = to_number(items.get("IT.TR.LDIAM", "")) elif rec["group"] in ("IG.TRNT", "IG.TUNT"): any_meas[(subject, rec["event"])] = True rows = [] study_of = {} for rec in records: study_of.setdefault(rec["subject"], rec["study"]) for subject in sorted(visits): subject_visits = sorted( visits[subject], key=lambda v: (to_number(v["avisitn"]) is None, to_number(v["avisitn"]) or 0), ) if not subject_visits: continue baseline_event = subject_visits[0]["event"] chosen = chosen_targets.get(subject, set()) baseline_sum = None if chosen: base = target_meas.get((subject, baseline_event), {}) measured = [base[lesion] for lesion in chosen if base.get(lesion) is not None] if len(measured) == len(chosen): baseline_sum = sum(measured) for seq, visit in enumerate(subject_visits, start=1): event = visit["event"] done = any_meas.get((subject, event), False) rsstresc = "" rsstat = "" if not done: rsstat = "NOT DONE" elif event == baseline_event: rsstresc = "NE" elif not chosen: # Non-target disease only. rsstresc = "NE" else: meas = target_meas.get((subject, event), {}) measured = {lesion: meas[lesion] for lesion in chosen if meas.get(lesion) is not None} if len(measured) < len(chosen): rsstresc = "NE" elif baseline_sum is None or baseline_sum == 0: rsstresc = "NE" else: total = sum(measured.values()) if all(value == 0 for value in measured.values()): rsstresc = "CR" else: change = 100.0 * (total - baseline_sum) / baseline_sum if change <= -30.0: rsstresc = "PR" elif change >= 20.0: rsstresc = "PD" else: rsstresc = "SD" rows.append({ "STUDYID": study_of.get(subject, ""), "USUBJID": subject, "AVISIT": visit["avisit"], "AVISITN": visit["avisitn"], "ADT": visit["adt"], "RSSEQ": seq, "RSTESTCD": "TRGRESP", "RSTEST": "Target Response", "RSSTRESC": rsstresc, "RSSTAT": rsstat, }) os.makedirs(OUTPUT, exist_ok=True) with open(os.path.join(OUTPUT, "rs.csv"), "w", newline="") as handle: writer = csv.DictWriter(handle, fieldnames=COLUMNS) writer.writeheader() writer.writerows(rows)if __name__ == "__main__": main()solutions/sdtm-rs-timepoint-response/result.sas
Edit59 lines/* opensas reference solution for the yamaa benchmark sdtm-rs-timepoint-response. 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;proc sort data=odm out=ordered; by StudyOID SubjectKey StudyEventOID; run;data visits; length AVISIT VISITORDER ADT $1024; retain AVISIT VISITORDER ADT; set ordered; where ItemGroupOID='IG.VISIT'; by StudyOID SubjectKey StudyEventOID; if first.StudyEventOID then do; AVISIT=''; VISITORDER=''; ADT=''; end; if ItemOID='IT.VISIT.AVISIT' then AVISIT=Value; if ItemOID='IT.VISIT.AVISITN' then VISITORDER=Value; if ItemOID='IT.VISIT.ADT' then ADT=Value; if last.StudyEventOID then output;run;proc sort data=odm out=ordered; by StudyOID SubjectKey StudyEventOID ItemGroupRepeatKey; run;data targetforms; length DIAM $1024; retain DIAM; set ordered; where ItemGroupOID='IG.TRTARGET'; by StudyOID SubjectKey StudyEventOID ItemGroupRepeatKey; if first.ItemGroupRepeatKey then do; DIAM=''; end; if ItemOID='IT.TR.LDIAM' then DIAM=Value; if last.ItemGroupRepeatKey then output;run;data targets; set targetforms; DIAMETER=input(DIAM,?? best32.); run;proc sql;create table chosen as select StudyOID,SubjectKey,count(distinct Value) as NCHOSEN from odm where ItemGroupOID='IG.TUTARGET' and StudyEventOID='BASELINE' and ItemOID='IT.TU.TULNKID' and not missing(Value) group by StudyOID,SubjectKey;create table baseline as select StudyOID,SubjectKey,count(*) as NBASE,count(DIAMETER) as NBASEDONE,sum(DIAMETER) as BASE from targets where StudyEventOID='BASELINE' group by StudyOID,SubjectKey;create table measures as select StudyOID,SubjectKey,StudyEventOID,count(DIAMETER) as NMEAS,sum(DIAMETER) as TOTAL,max(DIAMETER) as MAXDIAM from targets group by StudyOID,SubjectKey,StudyEventOID;create table done as select distinct StudyOID,SubjectKey,StudyEventOID from odm where ItemGroupOID in ('IG.TRTARGET','IG.TRNT');create table joined as select a.*,b.NCHOSEN,c.NBASE,c.NBASEDONE,c.BASE,d.NMEAS,d.TOTAL,d.MAXDIAM,e.StudyEventOID as DONEEVENT from visits a left join chosen b on a.StudyOID=b.StudyOID and a.SubjectKey=b.SubjectKey left join baseline c on a.StudyOID=c.StudyOID and a.SubjectKey=c.SubjectKey left join measures d on a.StudyOID=d.StudyOID and a.SubjectKey=d.SubjectKey and a.StudyEventOID=d.StudyEventOID left join done e on a.StudyOID=e.StudyOID and a.SubjectKey=e.SubjectKey and a.StudyEventOID=e.StudyEventOID; quit;data prepared; set joined; length STUDYID USUBJID RSTESTCD RSTEST RSSTRESC RSSTAT $1024; STUDYID=StudyOID; USUBJID=SubjectKey; AVISITN=input(VISITORDER,best32.); RSTESTCD='TRGRESP'; RSTEST='Target Response'; RSSTRESC='NE'; RSSTAT=''; NSELECTED=coalesce(NCHOSEN,NBASE,0);if missing(DONEEVENT) then do; RSSTRESC=''; RSSTAT='NOT DONE'; end;else if StudyEventOID ne 'BASELINE' and NSELECTED>0 and NMEAS>=NSELECTED and NBASEDONE=NBASE and not missing(BASE) and BASE ne 0 then do;if MAXDIAM=0 then RSSTRESC='CR'; else if (BASE-TOTAL)/BASE>=0.30 then RSSTRESC='PR'; else if (TOTAL-BASE)/BASE>=0.20 then RSSTRESC='PD'; else RSSTRESC='SD'; end; run;proc sort data=prepared; by STUDYID USUBJID AVISITN; run;data result; set prepared; by STUDYID USUBJID; retain RSSEQ; if first.USUBJID then RSSEQ=0; RSSEQ+1;run;proc sql; create table final as select STUDYID, USUBJID, AVISIT, AVISITN, ADT, RSSEQ, RSTESTCD, RSTEST, RSSTRESC, RSSTAT from result;quit;proc export data=final outfile="/app/output/rs.csv" dbms=csv replace; run;
yamaa