Clinwright Public work of Helper Software LLC · free Start free

ADTTE

Time to Event Analysis Dataset

BASIC DATA STRUCTURE · one record per subject per parameter · keys STUDYID, USUBJID, PARAMCD

Variables

VariableLabelTypeLengthDerivation
STUDYIDStudy IdentifiertextPredecessor ADSL.STUDYID
USUBJIDUnique Subject IdentifiertextPredecessor ADSL.USUBJID
SITEIDStudy Site IdentifiertextPredecessor ADSL.SITEID
AGEAgeinteger8Predecessor ADSL.AGE
SEXSextextPredecessor ADSL.SEX
TRT01PPlanned Treatment for Period 01textPredecessor ADSL.TRT01P
TRT01PNPlanned Treatment for Period 01 (N)integer8Predecessor ADSL.TRT01PN
TRT01AActual Treatment for Period 01textPredecessor ADSL.TRT01A
SAFFLSafety Population FlagtextPredecessor ADSL.SAFFL
ITTFLIntent-To-Treat Population FlagtextPredecessor ADSL.ITTFL
ASEQAnalysis Sequence Numberinteger8Sequence number of the records of a subject by PARAMCD: overall survival, progression-free survival, duration of response.
PARAMCDParameter CodetextOS (overall survival), PFS (progression-free survival) and, for responders, RSD (duration of response).
PARAMParametertextOverall Survival, Progression Free Survival, Duration of Response.
STARTDTTime to Event Origin Date for Subjectinteger8Randomization (RANDDT) for overall survival and progression-free survival; for duration of response the first response, ADRS.ADT where PARAMCD = 'RSP' and AVALC = 'Y'.
ADTAnalysis Dateinteger8The earliest event, ADRS.ADT of DEATH (overall survival) or of PD or DEATH (progression-free survival, duration of response); without one, the latest censoring date: ADSL.LSTALVDT, ADRS.ADT of LSTA (the last tumor assessment), ADSL.RANDDT.
AVALAnalysis Valueinteger8Days from STARTDT to ADT, both counted: ADT - STARTDT + 1 (overall survival, progression-free survival, duration of response).
CNSRCensorinteger80 for an event (death; disease progression for progression-free survival and duration of response), 1 for a censored subject.
EVNTDESCEvent or Censoring DescriptiontextDeath, Disease Progression; Alive, Last Tumor Assessment, Randomization for a censored subject.
CNSDTDSCCensor Date DescriptiontextFor a censored subject: Alive During Study, Last Tumor Assessment, Randomization.
SRCDOMSource DatatextADRS for death, disease progression and the last tumor assessment; ADSL for the last date known alive and randomization.
SRCVARSource VariabletextADT of ADRS; LSTALVDT or RANDDT of ADSL (overall survival, progression-free survival).
SRCSEQSource Sequence Numberinteger8ADRS.ASEQ of the record of the event or censoring (overall survival, progression-free survival).

Program adtte.sas

Version 1, written from Clinwright's patterns, 2026-10-17, checks passed.

/*==== 00-header ====*/
/*----------------------------------------------------------------------------
  Data set : ADTTE (Time to Event Analysis Dataset)
  Reporting effort : CSR
  ADaM     : ADRS, ADSL
  The header and the finalize step follow from the specification.
----------------------------------------------------------------------------*/
libname sdtm "/work/sdtm" access=readonly;
libname adam "/work/adam";
options validvarname=upcase nofmterr msglevel=i;

/*==== 10-inputs ====*/
/* The subjects of ADSL, with ADSL's variables. */
data work._ds;
  set adam.adsl;
run;

/*==== 20-parameters ====*/
/* ADTTE for oncology: overall survival (OS), progression-free survival (PFS) and duration of response (RSD), as
   admiralonco derives them (see SKILL.md).
   Inputs: ADAM.ADSL (RANDDT, LSTALVDT), ADAM.ADRS (PD, DEATH, LSTA, RSP by the evaluator analysed).
   Output: WORK.ADTTE, one record per subject per parameter. */

/* Each parameter's events and censorings: (parameter, E or C, its order among them, where the date comes from). */
data _rules;
  length PARAMCD $ 8 PARAM $ 40 _kind $ 1 _src $ 10 EVNTDESC CNSDTDSC $ 40;
  input PARAMCD $ _kind $ _order _src $ @;
  input EVNTDESC & $40. CNSDTDSC & $40.;
  select (PARAMCD);
    when ('OS') PARAM = 'Overall Survival';
    when ('PFS') PARAM = 'Progression Free Survival';
    when ('RSD') PARAM = 'Duration of Response';
    otherwise;
  end;
  datalines;
OS E 1 death Death  .
OS C 1 lastalive Alive  Alive During Study
OS C 2 rand Randomization  Randomization
PFS E 1 pd Disease Progression  .
PFS E 2 death Death  .
PFS C 1 lasta Last Tumor Assessment  Last Tumor Assessment
PFS C 2 rand Randomization  Randomization
RSD E 1 pd Disease Progression  .
RSD E 2 death Death  .
RSD C 1 lasta Last Tumor Assessment  Last Tumor Assessment
;
run;

/* The dates each source gives a subject. */
data _dates(keep=USUBJID _src ADT SRCDOM SRCVAR SRCSEQ);
  length _src $ 10 SRCDOM $ 8 SRCVAR $ 8;
  set adam.adrs(keep=USUBJID PARAMCD AVALC ANL01FL ADT ASEQ in=_r) adam.adsl(keep=USUBJID RANDDT LSTALVDT in=_s);
  if _r then do;
    SRCDOM = 'ADRS';
    SRCVAR = 'ADT';
    SRCSEQ = ASEQ;
    if PARAMCD = 'DEATH' and AVALC = 'Y' and ANL01FL = 'Y' then do; _src = 'death'; output; end;
    if PARAMCD = 'PD' and AVALC = 'Y' and ANL01FL = 'Y' then do; _src = 'pd'; output; end;
    if PARAMCD = 'LSTA' and ANL01FL = 'Y' then do; _src = 'lasta'; output; end;
  end;
  if _s then do;
    SRCDOM = 'ADSL';
    SRCSEQ = .;
    _src = 'lastalive'; SRCVAR = 'LSTALVDT'; ADT = LSTALVDT; output;
    _src = 'rand'; SRCVAR = 'RANDDT'; ADT = RANDDT; output;
  end;
run;

/* Each parameter's start: randomization; for the duration of response, the first response. */
data _start(keep=USUBJID PARAMCD STARTDT);
  length PARAMCD $ 8;
  set adam.adsl(keep=USUBJID RANDDT in=_s) adam.adrs(keep=USUBJID PARAMCD AVALC ANL01FL ADT in=_r rename=(PARAMCD=_p));
  if _s then do;
    STARTDT = RANDDT;
    PARAMCD = 'OS'; output;
    PARAMCD = 'PFS'; output;
  end;
  if _r and _p = 'RSP' and AVALC = 'Y' and ANL01FL = 'Y' then do;
    STARTDT = ADT;
    PARAMCD = 'RSD';
    output;
  end;
  format STARTDT yymmdd10.;
run;

/* Candidates: every dated event and censoring of a subject with a start. */
proc sql;
  create table _cand as
  select s.USUBJID, s.PARAMCD, s.STARTDT, r.PARAM, r._kind, r._order, r.EVNTDESC, r.CNSDTDSC,
         d.ADT, d.SRCDOM, d.SRCVAR, d.SRCSEQ
  from _start as s
       inner join _rules as r on r.PARAMCD = s.PARAMCD
       inner join _dates as d on d.USUBJID = s.USUBJID and d._src = r._src
  where s.STARTDT is not missing and d.ADT is not missing;
quit;

/* An event when there is one: the earliest (on one date, the event listed first); else a censoring: the latest
   (on one date, the one listed last). */
data _cand;
  set _cand;
  _event = (_kind = 'E');
  /* Sort key: events after censorings; among events the earliest, among censorings the latest, last. */
  if _event then _key = -ADT;
  else _key = ADT;
  _tie = ifn(_event, -_order, _order);
run;
proc sort data=_cand;
  by USUBJID PARAMCD _event _key _tie;
run;
data adtte;
  set _cand;
  by USUBJID PARAMCD;
  if last.PARAMCD;
  CNSR = 1 - _event;
  if _event then CNSDTDSC = '';
  AVAL = ADT - STARTDT + 1;
  format ADT yymmdd10.;
  drop _kind _order _event _key _tie;
run;

/* Sequence and ADSL's variables. */
proc sort data=adtte;
  by USUBJID PARAMCD;
run;
data work._ds;
  merge adtte(in=_in) adam.adsl;
  by USUBJID;
  if _in;
  if first.USUBJID then ASEQ = 0;
  ASEQ + 1;
run;

/*==== 89-final ====*/
/* The data set as derived; the finalize step keeps the specification's variables. */
data work._final;
  set work._ds;
run;

/*==== 90-finalize ====*/
/* 90-finalize: from the specification; the variables, their order and attributes are not changed here. */
/* The text variables the specification gives no length: as long as their longest value (at least 1). */
%let _len1 = 1; %let _len2 = 1; %let _len3 = 1; %let _len4 = 1; %let _len5 = 1; %let _len6 = 1; %let _len7 = 1; %let _len8 = 1; %let _len9 = 1; %let _len10 = 1; %let _len11 = 1; %let _len12 = 1; %let _len13 = 1; %let _len14 = 1;
data _null_;
  length _ren _asg _siz $32767;
  _dsid = open('work._final');
  if varnum(_dsid, 'STUDYID') > 0 then do; _ren = catx(' ', _ren, 'STUDYID=_rz1'); _asg = catx(' ', _asg, 'STUDYID = _rz1;');
    _siz = catx(' ', _siz, '_len1 = max(_len1, lengthn(STUDYID));'); end;
  if varnum(_dsid, 'USUBJID') > 0 then do; _ren = catx(' ', _ren, 'USUBJID=_rz2'); _asg = catx(' ', _asg, 'USUBJID = _rz2;');
    _siz = catx(' ', _siz, '_len2 = max(_len2, lengthn(USUBJID));'); end;
  if varnum(_dsid, 'SITEID') > 0 then do; _ren = catx(' ', _ren, 'SITEID=_rz3'); _asg = catx(' ', _asg, 'SITEID = _rz3;');
    _siz = catx(' ', _siz, '_len3 = max(_len3, lengthn(SITEID));'); end;
  if varnum(_dsid, 'SEX') > 0 then do; _ren = catx(' ', _ren, 'SEX=_rz4'); _asg = catx(' ', _asg, 'SEX = _rz4;');
    _siz = catx(' ', _siz, '_len4 = max(_len4, lengthn(SEX));'); end;
  if varnum(_dsid, 'TRT01P') > 0 then do; _ren = catx(' ', _ren, 'TRT01P=_rz5'); _asg = catx(' ', _asg, 'TRT01P = _rz5;');
    _siz = catx(' ', _siz, '_len5 = max(_len5, lengthn(TRT01P));'); end;
  if varnum(_dsid, 'TRT01A') > 0 then do; _ren = catx(' ', _ren, 'TRT01A=_rz6'); _asg = catx(' ', _asg, 'TRT01A = _rz6;');
    _siz = catx(' ', _siz, '_len6 = max(_len6, lengthn(TRT01A));'); end;
  if varnum(_dsid, 'SAFFL') > 0 then do; _ren = catx(' ', _ren, 'SAFFL=_rz7'); _asg = catx(' ', _asg, 'SAFFL = _rz7;');
    _siz = catx(' ', _siz, '_len7 = max(_len7, lengthn(SAFFL));'); end;
  if varnum(_dsid, 'ITTFL') > 0 then do; _ren = catx(' ', _ren, 'ITTFL=_rz8'); _asg = catx(' ', _asg, 'ITTFL = _rz8;');
    _siz = catx(' ', _siz, '_len8 = max(_len8, lengthn(ITTFL));'); end;
  if varnum(_dsid, 'PARAMCD') > 0 then do; _ren = catx(' ', _ren, 'PARAMCD=_rz9'); _asg = catx(' ', _asg, 'PARAMCD = _rz9;');
    _siz = catx(' ', _siz, '_len9 = max(_len9, lengthn(PARAMCD));'); end;
  if varnum(_dsid, 'PARAM') > 0 then do; _ren = catx(' ', _ren, 'PARAM=_rz10'); _asg = catx(' ', _asg, 'PARAM = _rz10;');
    _siz = catx(' ', _siz, '_len10 = max(_len10, lengthn(PARAM));'); end;
  if varnum(_dsid, 'EVNTDESC') > 0 then do; _ren = catx(' ', _ren, 'EVNTDESC=_rz11'); _asg = catx(' ', _asg, 'EVNTDESC = _rz11;');
    _siz = catx(' ', _siz, '_len11 = max(_len11, lengthn(EVNTDESC));'); end;
  if varnum(_dsid, 'CNSDTDSC') > 0 then do; _ren = catx(' ', _ren, 'CNSDTDSC=_rz12'); _asg = catx(' ', _asg, 'CNSDTDSC = _rz12;');
    _siz = catx(' ', _siz, '_len12 = max(_len12, lengthn(CNSDTDSC));'); end;
  if varnum(_dsid, 'SRCDOM') > 0 then do; _ren = catx(' ', _ren, 'SRCDOM=_rz13'); _asg = catx(' ', _asg, 'SRCDOM = _rz13;');
    _siz = catx(' ', _siz, '_len13 = max(_len13, lengthn(SRCDOM));'); end;
  if varnum(_dsid, 'SRCVAR') > 0 then do; _ren = catx(' ', _ren, 'SRCVAR=_rz14'); _asg = catx(' ', _asg, 'SRCVAR = _rz14;');
    _siz = catx(' ', _siz, '_len14 = max(_len14, lengthn(SRCVAR));'); end;
  _rc = close(_dsid);
  if _ren ne '' then _ren = cats('(rename=(', _ren, '))');
  call symputx('_ren', _ren);
  call symputx('_asg', _asg);
  call symputx('_siz', _siz);
run;
data _null_;
  set work._final end=_end;
  retain _len1 1 _len2 1 _len3 1 _len4 1 _len5 1 _len6 1 _len7 1 _len8 1 _len9 1 _len10 1 _len11 1 _len12 1 _len13 1 _len14 1;
  &_siz
  if _end then do;
    call symputx('_len1', _len1);
    call symputx('_len2', _len2);
    call symputx('_len3', _len3);
    call symputx('_len4', _len4);
    call symputx('_len5', _len5);
    call symputx('_len6', _len6);
    call symputx('_len7', _len7);
    call symputx('_len8', _len8);
    call symputx('_len9', _len9);
    call symputx('_len10', _len10);
    call symputx('_len11', _len11);
    call symputx('_len12', _len12);
    call symputx('_len13', _len13);
    call symputx('_len14', _len14);
  end;
run;
data adam.adtte(label="Time to Event Analysis Dataset");
  attrib
    STUDYID  length=$&_len1 label="Study Identifier"
    USUBJID  length=$&_len2 label="Unique Subject Identifier"
    SITEID   length=$&_len3 label="Study Site Identifier"
    AGE      length=8 label="Age"
    SEX      length=$&_len4 label="Sex"
    TRT01P   length=$&_len5 label="Planned Treatment for Period 01"
    TRT01PN  length=8 label="Planned Treatment for Period 01 (N)"
    TRT01A   length=$&_len6 label="Actual Treatment for Period 01"
    SAFFL    length=$&_len7 label="Safety Population Flag"
    ITTFL    length=$&_len8 label="Intent-To-Treat Population Flag"
    ASEQ     length=8 label="Analysis Sequence Number"
    PARAMCD  length=$&_len9 label="Parameter Code"
    PARAM    length=$&_len10 label="Parameter"
    STARTDT  length=8 label="Time to Event Origin Date for Subject" format=DATE9.
    ADT      length=8 label="Analysis Date" format=DATE9.
    AVAL     length=8 label="Analysis Value"
    CNSR     length=8 label="Censor"
    EVNTDESC length=$&_len11 label="Event or Censoring Description"
    CNSDTDSC length=$&_len12 label="Censor Date Description"
    SRCDOM   length=$&_len13 label="Source Data"
    SRCVAR   length=$&_len14 label="Source Variable"
    SRCSEQ   length=8 label="Source Sequence Number"
  ;
  set work._final&_ren;
  &_asg
  keep STUDYID USUBJID SITEID AGE SEX TRT01P TRT01PN TRT01A SAFFL ITTFL ASEQ PARAMCD PARAM STARTDT ADT AVAL CNSR EVNTDESC CNSDTDSC SRCDOM SRCVAR SRCSEQ;
run;
proc sort data=adam.adtte; by STUDYID USUBJID PARAMCD; run;

Data (first 20 of 690 records, simulated)

STUDYIDUSUBJIDSITEIDAGESEXTRT01PTRT01PNTRT01ASAFFLITTFLASEQPARAMCDPARAMSTARTDTADTAVALCNSREVNTDESCCNSDTDSCSRCDOMSRCVARSRCSEQ
ONCO-EXONCO-EX-70100270157FStandard of Care1Standard of CareYY1OSOverall Survival2022-02-112023-12-106681AliveAlive During StudyADSLLSTALVDT
ONCO-EXONCO-EX-70100270157FStandard of Care1Standard of CareYY2PFSProgression Free Survival2022-02-112022-11-292920Disease ProgressionADRSADT18
ONCO-EXONCO-EX-70100270157FStandard of Care1Standard of CareYY3RSDDuration of Response2022-03-232022-11-292520Disease ProgressionADRSADT18
ONCO-EXONCO-EX-70100370158MStandard of Care1Standard of CareYY1OSOverall Survival2022-03-162023-10-205841AliveAlive During StudyADSLLSTALVDT
ONCO-EXONCO-EX-70100370158MStandard of Care1Standard of CareYY2PFSProgression Free Survival2022-03-162022-10-162150Disease ProgressionADRSADT16
ONCO-EXONCO-EX-70100470160MClinwrightinib 200 mg2Clinwrightinib 200 mgYY1OSOverall Survival2022-03-172024-02-167021AliveAlive During StudyADSLLSTALVDT
ONCO-EXONCO-EX-70100470160MClinwrightinib 200 mg2Clinwrightinib 200 mgYY2PFSProgression Free Survival2022-03-172023-02-133341Last Tumor AssessmentLast Tumor AssessmentADRSADT9
ONCO-EXONCO-EX-70100470160MClinwrightinib 200 mg2Clinwrightinib 200 mgYY3RSDDuration of Response2022-06-142023-02-132451Last Tumor AssessmentLast Tumor AssessmentADRSADT9
ONCO-EXONCO-EX-70100570162MClinwrightinib 200 mg2Clinwrightinib 200 mgYY1OSOverall Survival2022-03-302024-02-297021AliveAlive During StudyADSLLSTALVDT
ONCO-EXONCO-EX-70100570162MClinwrightinib 200 mg2Clinwrightinib 200 mgYY2PFSProgression Free Survival2022-03-302023-02-243321Last Tumor AssessmentLast Tumor AssessmentADRSADT9
ONCO-EXONCO-EX-70100570162MClinwrightinib 200 mg2Clinwrightinib 200 mgYY3RSDDuration of Response2022-05-182023-02-242831Last Tumor AssessmentLast Tumor AssessmentADRSADT9
ONCO-EXONCO-EX-70100770163MStandard of Care1Standard of CareYY1OSOverall Survival2022-04-182023-10-045350DeathADRSADT8
ONCO-EXONCO-EX-70100770163MStandard of Care1Standard of CareYY2PFSProgression Free Survival2022-04-182023-02-072960Disease ProgressionADRSADT18
ONCO-EXONCO-EX-70100870154MClinwrightinib 200 mg2Clinwrightinib 200 mgYY1OSOverall Survival2022-04-252022-12-212410DeathADRSADT8
ONCO-EXONCO-EX-70100870154MClinwrightinib 200 mg2Clinwrightinib 200 mgYY2PFSProgression Free Survival2022-04-252022-11-192090Disease ProgressionADRSADT16
ONCO-EXONCO-EX-70100870154MClinwrightinib 200 mg2Clinwrightinib 200 mgYY3RSDDuration of Response2022-07-172022-11-191260Disease ProgressionADRSADT16
ONCO-EXONCO-EX-70100970158MClinwrightinib 200 mg2Clinwrightinib 200 mgYY1OSOverall Survival2022-04-172023-11-215841AliveAlive During StudyADSLLSTALVDT
ONCO-EXONCO-EX-70100970158MClinwrightinib 200 mg2Clinwrightinib 200 mgYY2PFSProgression Free Survival2022-04-172022-11-152130Disease ProgressionADRSADT16
ONCO-EXONCO-EX-70100970158MClinwrightinib 200 mg2Clinwrightinib 200 mgYY3RSDDuration of Response2022-05-262022-11-151740Disease ProgressionADRSADT16
ONCO-EXONCO-EX-70101070164FClinwrightinib 200 mg2Clinwrightinib 200 mgYY1OSOverall Survival2022-06-092024-05-107021AliveAlive During StudyADSLLSTALVDT