Use case · SDTM & ADaM mapping

Mapping raw data to SDTM and ADaM — with the programs written for you.

The mapping usually lives in three places at once: a specification, the programs that implement it, and a Define.xml that describes them. Verdatic keeps one — you confirm the mapping, and the SAS, R and Python come out of it, along with the metadata and the record of every decision.

The problem

Raw data is shaped like the forms it was collected on. SDTM is shaped like the standard. Somebody has to write that translation down, somebody else has to program it, and on the derived side a third person commonly programs it again, independently, to prove the first one right. Then a Define.xml is assembled at the end to describe what the programs did.

  • Three artifacts that must agree, and usually don’t. The mapping spec, the program, and the Define.xml are maintained separately. Every change has to be found and landed in all three, and the one that gets missed is discovered by a validator, late.
  • The reasoning isn’t written down anywhere. Six months on, nobody remembers why a result came from that field rather than the one next to it — and the person who decided has moved to another study.
  • Nothing can be executed until data exists. Programs written against a spec are proven syntactically and hopefully. The real test is first-patient-in, which is also the week nobody has spare.
  • Language lock-in. The programs exist in whichever language the group standardized on. Handing the work to a partner who lives in another one means rewriting it.

Risk and cost profile

We don’t publish savings percentages, and there is no benchmark study behind this page. These are the drivers and the units they’re measured in — put your own rates in the last column.

The structural point is simple: most of the cost here is transcription, not judgement. Deciding that a raw field maps to a particular SDTM variable is skilled work. Copying that decision into a spreadsheet, then into a program, then into a Define.xml, then into a QC listing is not — and it is where the errors come from.

Cost driverHow it shows upPrice it with your own numbers
Writing it down twice Once as a mapping specification, again as the program that implements it. datasets in scope × hours per dataset for spec + program
Independent QC programming Derived datasets are commonly programmed a second time, on purpose, to prove the first. the QC hours you already budget per dataset
Spec, code and metadata drift Three artifacts that have to agree; each change must land in all of them. spec revisions per study × the time to propagate one change everywhere
Waiting for data Transformation programs can’t truly be exercised until real records arrive. weeks between build and first-patient-in — and what your programmers do in them
Handover and onboarding A new programmer reconstructs intent by reading code and asking around. hours spent answering “why is it mapped that way” per handover

What we won’t claim: that this removes review, QC or judgement. Generated programs are meant to be read, and every mapping decision is meant to be confirmed by a person. What goes away is the re-typing between spec, code and metadata — they come out of one source, so they can’t quietly disagree.

The workflow, at a glance

The mapping is the artifact. Programs, the Define.xml and the lineage record are all emitted from it, and the official CDISC CORE engine grades what the programs actually produced.

From raw study data to mapped datasets and generated programs Raw study data shaped like the forms it came from Field links proposed with a score, confirmed by a person Mapped to SDTM, and on to ADaM Programs written SAS · R · Python, plus a Define.xml Run and checked by the official CDISC CORE engine One record, kept as you go every value traces back through its method and its standard definition to the dated catalog snapshot it resolved against
The spec, the programs and the Define.xml are produced from the same mapping — which is why they can’t drift apart between releases.

The Verdatic workflow

Real screens from the product, in the order you’d meet them. The first two steps are a Rave casebook built to the shape one actually arrives in — 171 fields across 14 pages, named the way a production EDC build names things, with the collection layer standing on its own and no SDTM structure anywhere in it. From step three the screens come from a study already carried through to programs, so you can see what a confirmed mapping produces.

STEP 01

Start from the design you already have

Import a Rave Architect Loader Spreadsheet, a USDM protocol file, or a Veeva casebook design export — or clone the shape of an existing dataset. What arrives is a project with real schedules, forms, fields and dictionaries, which is what the mapping needs to be anchored to.

The Import / Create New Study Design screen, with tabs for USDM (JSON), Rave ALS (XLSX), Veeva (CDE JSON) in beta, a demo study and a dataset cloner. The Rave ALS tab is open, offering to build a project with schedules, forms, fields, dictionaries and edit checks from a spreadsheet.
Four ways in, plus a dataset cloner. Designs can also go back out as a round-tripped ALS or a USDM export, with an audit sheet listing anything that could not be translated.
A casebook imported from a Rave loader spreadsheet: form pages listed down the left as 12-Lead ECG (EG), Adverse Event Log (AE), Concomitant Medication Log (CM), Demography (DM), End of Study / Early Termination (EOS) and End of Treatment (EOT), and the Vital Signs page open on the right with nine fields — VSDAT, VSLAT, VSLOC, VSPOS, SYSBP, DIABP, PULSE, RESPRT and TEMP — against human CRF questions such as 'Systolic blood pressure, seated after 5 minutes rest'.
This is what a collected casebook actually looks like. Pages named for what a coordinator opens — Vital Signs, 12-Lead ECG, Adverse Event Log — and fields carrying the CDASH-derived mnemonics a build really uses: SYSBP, PULSE, RESPRT, VSDAT. Recognisable, and still not SDTM: this is what was collected, and the mapping from here to a submission dataset is the work.
STEP 02

Link each collected field to a standard definition

Verdatic proposes the link between a collected field and the biomedical concept behind it, and shows the confidence and the method that produced each proposal. On this casebook it linked 151 of 171 fields and auto-confirmed 125 of them, leaving 26 for a person and 20 it would not guess at. Where the evidence is strong the work is simply done. Where a label identifies the concept — “Pulse Rate” is unmistakably pulse rate — without identifying the dataset specialization underneath it, Verdatic will not promote a guess about the second from evidence about the first. Those land in a curator’s queue with their evidence attached, which is a short list rather than all of it.

Field-link review filtered to the VS vital-signs page, nine rows covering the whole confidence ladder: DIABP, PULSE, SYSBP and TEMP each confirmed against their VSORRES specialization by value-level metadata at 0.92; RESPRT reaching the Respiratory Rate concept by label at 0.85 with no specialization resolved; VSDAT Assessment Date reaching only a generic Date concept at 0.65; VSLAT Side matched to a sideroblast measurement concept at 0.65; and VSLOC Measurement Site and VSPOS Subject Position unlinked. Header tallies read All 171, Pending 4, Confirmed 125, Unresolved 22, Unlinked 20.
Nine collected fields, every rung of the ladder. The four real measurements land on their specialization by value-level metadata at 0.92 and confirm themselves — SYSBP.VSORRES, DIABP.VSORRES, PULSE.VSORRES, TEMP.VSORRES. RESPRT reaches the right concept by label at 0.85 with no specialization under it. VSDAT reaches only Date, because CDASH collects a date as --DAT where SDTM wants --DTC. Two qualifiers are unlinked. And Side matched Sideroblast Measurement at 0.65 — plainly wrong, correctly left unconfirmed, and exactly why the last rung needs a person.
The post-import setup page: status chips reading source Rave ALS, catalog snapshot, and 151 linked · 26 pending, with an auto-confirm threshold of 0.90; and the auto-link step reporting 125 confirmed · 4 pending · 22 unresolved and a confidence spread of 0 exact, 126 high, 4 mid, 21 low, with one-click queues to review the 4 pending and triage the 22 unresolved.
Where the line fell, in one frame. The bar is 0.90; the run came back 0 exact · 126 high · 4 mid · 21 low. Everything above the bar confirmed itself; everything below it stayed a proposal, and the two buttons underneath are where a curator starts. The threshold is yours to set, and it is the only thing standing between a proposal and a confirmed link.
Field-link advisories over the review list: 22 fields linked to a biomedical concept but with no specialization resolved, with a Triage button; 20 fields not linked to any specialization, with Show unlinked; an offer to propose links for the unlinked tail; and 4 links pending confirmation, with Review. Below them the adverse-event page, where fields such as AEACN, AEBODSYS, AECAT and AECONTRT are each confirmed against their AE specialization by spec variable at 0.97.
The same 171 fields as queues rather than a list: 22 that found a concept but not a specialization, 20 that found nothing, 4 waiting on a yes or a no. Underneath, the adverse-event page confirming itself row after row at 0.97 — which is the point. The queue is what is left after the engine has done everything the evidence supports, so a curator spends their attention on the 26 cases that actually need judgement.
STEP 03

Map to SDTM — and on to the analysis layer

Confirmed links are what mapping is built on, so from here the screens come from a study whose curator has already been through that queue. Mapping resolves against a dated snapshot of the CDISC library: biomedical concepts, dataset specializations, controlled terminology and conformance rules, all pinned. The same route continues into the analysis layer, where a subject-level dataset, basic data-structure datasets for findings, and occurrence datasets for events are mapped from the SDTM ones — in dependency order, subject-level first.

A traceability view of the vital-signs dataset: the result variable expanded to show its five per-test source passes, then a table linking each test to a biomedical concept — diastolic blood pressure C25299, pulse C49676 — with every link marked AI proposed and Human confirmed at 92% confidence.
One vital-signs result variable opened up: five per-test source passes above, and below them the value-level detail — each test tied to its biomedical concept and specialization, with the assistant’s proposal and the human confirmation recorded side by side.
STEP 04

Generate the programs — in all three languages

The same mapping emits complete, runnable transformation programs in SAS, R and Python. Same logic, same results, whichever language your team — or your partner’s team — works in. Each derived column carries a comment naming the method behind it, so the program reads as documentation of the mapping rather than as a black box.

Verdatic's generated-code panel for the AE dataset, with tabs for SAS data step, Python (pandas) and R (dplyr). The SAS tab shows libname statements, a data step, and attrib statements giving every variable its label.
The adverse-events transformation as a SAS data step — real libname, length and attrib statements, with the Python and R versions of the same logic one tab away.
Generated R code for the adverse-events dataset: library(dplyr), a build_ae function piping the input data frame into mutate(), with a comment above each derived column naming the method that produced it.
The same dataset in R. Choosing a language is a tab, not a rewrite — and not a decision you have to make once for the whole study.
STEP 05

Package it so somebody else can run it

Programs ship as a versioned bundle: a dependency-aware build plan that resolves the order domains must be built in, shared library functions, a Define.xml, and a lineage manifest — checksummed, so the package you hand over is provably the package you built. Analysis datasets are bundled separately from the tabulation ones, each with its own Define.xml.

A build plan for the study: an 18-domain resolved emission order, and a code bundle set to SDTM and SAS with buttons to preview, generate the bundle, open Define.xml and open traceability — the packed ZIP is 481.4 KB with a sha256 checksum.
An 18-domain build order resolved automatically, and the bundle controls beneath it: pick the standard, pick the language, preview, generate, open the Define.xml or the traceability report. The ZIP carries a sha256 checksum.
STEP 06

Run it, and let the official engine grade the result

Python and R bundles can be executed without leaving the app, dropping every domain out twice — as a SAS transport file and as Dataset-JSON — and the official CDISC CORE conformance engine checks what the programs produced. Findings become a worklist with a recorded decision on each one and run-over-run deltas, so a resolved issue stays resolved.

A code bundle that has been run: a Succeeded badge reading Python 3.12.10 with pandas and pyreadstat, exit 0; a CDISC CORE banner covering 430 rules with 7 issues and define.xml included; chips listing every output file as both .json and .xpt; and a preview grid of the AE dataset.
A bundle executed in place: Python 3.12.10, exit 0, every domain written as both .xpt and Dataset-JSON, with the CORE result attached. Running in-app needs the language toolchain present; SAS bundles are made to be downloaded and run where SAS lives.
The CDISC CORE findings worklist: 315 of 430 rules pass, none open, seven waived, 49 not applicable and 60 conditional, no change from the previous run — and a disposition recorded against each remaining rule.
The verdict as a worklist rather than a PDF: 315 of 430 rules pass, nothing open, seven waived with written reasons, and no change since the previous run.

Executive summary

  • The problem. The mapping lives in three places — a spec, a program and a Define.xml — that must agree and slowly stop agreeing, and none of it can be run until real data arrives.
  • The cost. Transcription, not judgement: writing the same decision down repeatedly, QC-programming it a second time, and propagating every change through every artifact.
  • What Verdatic does. Proposes each field’s link to a standard definition with a confidence score and the method behind it, confirms what clears your threshold and holds the rest for a person — on the casebook above, 125 of 171 fields confirmed and 26 queued — and treats the confirmed mapping as the single source the rest is generated from.
  • What comes out. Runnable SAS, R and Python for the same mapping, a build plan in dependency order, a Define.xml, and a lineage manifest — checksummed and versioned, with tabulation and analysis bundles separated.
  • The check. The official CDISC CORE engine grades what the programs produced, and its findings become a worklist with recorded decisions and run-over-run deltas.

Bring us a mapping you already know the answer to.

The most useful first session is a study you’ve already mapped by hand — so you can compare what Verdatic proposes against what your team decided, line by line.

Request access

Or email hello@verdatic.com. The CDISC challenge entry follows one measurement through this whole path in six minutes.

The other three use cases