*************************************************************************************************; * * CLIENT: ModernaTX, Inc. * PROTOCOL: mRNA-1273-P301 * * PURPOSE: Create analysis dataset advs * * INPUT FILES: SDTM domains * OUTPUT FILES: ADVS.sas7bdat * * USAGE NOTES: * *************************************************************************************************; * Copyright 2020 Pharmaceutical Product Development, Inc. * All Rights Reserved. *************************************************************************************************; options noquotelenmax; %include "madam.sas"; **Assign global macro variable DSETNAME to reflect the name of the final ADaM dataset**; %global DSETNAME; %let dsetname = advs; %let adslvar=tr01sdt tr01edt dose2dt dos2dtm tr01sdtm tr01edtm dose1fl dose2fl eosdt dthdt tr02sdt tr02sdtm oldos2dt oldo2dtm randfl OLDOS1FL OLDOS2FL AP02SSDT; proc format; value $unit 'BMI' = 'kg/m2' 'DIABP' = 'mmHg' 'HEIGHT' = 'cm' 'PULSE' = 'beats/min' 'RESP' = 'breaths/min' 'SYSBP' = 'mmHg' 'TEMP' = 'C' 'WEIGHT' = 'kg'; quit; proc contents data=trans.vs out=cont; run; proc sql noprint; select length into:visit_len from cont where NAME='VISIT'; select length into:vstest_len from cont where NAME='VSTEST'; select length into:vstestcd_len from cont where NAME='VSTESTCD'; select length into:vsorres_len from cont where NAME='VSORRES'; select length into:vsorresu_len from cont where NAME='VSORRESU'; select length into:vsstresc_len from cont where NAME='VSSTRESC'; select length into:vsstresu_len from cont where NAME='VSSTRESU'; quit; **Merge supplemental data onto parent domain**; %revsupp(libin=trans,libout=work,ds=vs,supp=suppvs,outds=vs_all); proc sort tagsort data=vs_all; by usubjid subjid vscat vstestcd vsdtc; where missing(vsstat) and vscat not in ('REACTOGENICITY' 'EFFICACY'); run; **INSERT CODE TO GENERATE DATASET**; data vs_adsl; merge vs_all(in=a) adb.adsl(in=b keep=USUBJID subjid &adslvar.); by usubjid subjid; if a and b; run; data vs_adsl; length _war $200 PARAMCD $8 PARAM $50 _: $200; set vs_adsl; if missing(vsorres) then do; _war='Put Aler'||'t_C: vsORRES is missing when '||strip(subjid)||', vsTESTCD='|| strip(vstestcd)||', vsCAT='||strip(vscat)||', vsDTC='||strip(vsdtc)||'.'; *put _war; end; * paramcd; PARAMCD = vstestcd; _unit = put(PARAMCD,$unit.); if (missing(_unit) and ^missing(vsstresu)) or lengthn(param)>50 then do; _war='Put Aler'||'t_R: PARAM needs update.'; put _war SUBJID= VSTESTCD= VSSTRESU= _unit= PARAM=; end; * param; PARAM = trim(vstest)||' ('||strip(_unit)||')'; * results AVAL; AVAL = vsstresn; AVALC = vsstresc; * Analysis Date/time; %ISO2SAS(isodate=vsdtc, datec=_vsdtc, daten=ADT, timec=_atmc); if index(_atmc,'--')=0 and ^missing(_atmc) then ATM = input(_atmc,time5.); if index(_atmc,'--')=0 and ^missing(_atmc) and ^missing(ADT) then ori_ADTM = input(compress(put(ADT,date9.)||':'||_atmc),datetime20.); if index(_atmc,'--')=0 and ^missing(_atmc) and _atmc^='00:00' and ^missing(ADT) then ADTM = input(compress(put(ADT,date9.)||':'||_atmc),datetime20.); %caldy(stdt=ADT,endt=TR01SDT,outdy=ADY); ori_visit = visit; if visit=:'Illness Visit Day 3 - Day 21' then visit = 'Illness Visit Day 3 Unscheduled 1'; length addsortn $200; if visit=:'Visit' and index(visit,'Uns')=0 then addsortn = ''; else if (missing(visit) or index(visit,'Uns')) and ^missing(adt) then addsortn = put(adt,yymmdd10.)||' - 999'; else if ori_visit=:'Illness Visit Day 3 - Day 21' and index(visit,'Uns') then addsortn = put(adt,yymmdd10.)||' - 998'; else if (visit=:'Ill' or visit=:'Conva' or index(visit,'OL-D')) and adt>tr01sdt>. and index(visit,'Uns') then addsortn = put(adt,yymmdd10.)||' - 999'; else if (visit=:'Ill' or visit=:'Conva' or index(visit,'OL-D')) and adt>tr01sdt>. then addsortn = put(adt,yymmdd10.); else if (visit=:'Ill' or visit=:'Conva' or index(visit,'OL-D')) and missing(vsdtc) then addsortn = '0000'; format ADTM datetime20. ADT date9. ATM time5.; run; * Baseline Record Flag & Analysis Windows & CHG/PCHG; %ablfl(indst=vs_adsl,outdst=base_chg, seq=vsseq, basec=Y, avisit_type=1, stresc=vsstresc, tpt=vstpt, tptnum=descending vstptnum, addsortn=addsortn); * Stage - Vaccine Stage OR Surveillance stage; proc sort tagsort data=trans.sv out=sv nodupkey; by usubjid subjid visit svstdtc; where VISITNUM in (6 10 38 40) and ^missing(svstdtc); run; data sv; set sv; by usubjid subjid visit svstdtc; if first.visit then output; run; proc sort tagsort data=base_chg; by usubjid subjid; run; data base_chg_sv; merge base_chg(in=a) sv(where=(_visit4='Visit 2 Day 29') rename=(domain=_dom_v4 visit=_visit4 svstdtc=_svstdtc4) keep=usubjid subjid domain visit svstdtc) sv(where=(_visit7='Visit 3 Day 57') rename=(domain=_dom_v7 visit=_visit7 svstdtc=_svstdtc7) keep=usubjid subjid domain visit svstdtc) sv(where=(_visit29='OL-D29') rename=(domain=_dom_v29 visit=_visit29 svstdtc=_svstdtc29) keep=usubjid subjid domain visit svstdtc) sv(where=(_visit57='OL-D57') rename=(domain=_dom_v57 visit=_visit57 svstdtc=_svstdtc57) keep=usubjid subjid domain visit svstdtc); by usubjid subjid; if a; run; data aperiod; length ASTAGE $30; set base_chg_sv; *** Period; if .0)) and ._svstdtn7>. then ASTAGE = 'Follow up stage'; else if min(_svstdtn7,_eosdt,_dthdt)>"&SYSDATE9."d and (index(VSTPT,'POST') or ori_adtm>tr01sdtm>. or (cmiss(ori_adtm,tr01sdtm)>0 and adt>tr01sdt)) and not (.0)) and ._svstdtn4>. then ASTAGE = 'Follow up stage'; else if min(_svstdtn4,_eosdt,_dthdt)>"&SYSDATE9."d and (index(VSTPT,'POST') or ori_adtm>tr01sdtm>. or (cmiss(ori_adtm,tr01sdtm)>0 and adt>tr01sdt)) and not (.0)) and ._svstdtn57>. then ASTAGE = 'Follow up stage'; else if min(_svstdtn57,_eosdt,_dthdt)>"&SYSDATE9."d and (index(VSTPT,'POST') or ori_adtm>tr02sdtm>. or (cmiss(ori_adtm,tr02sdtm)>0 and adt>tr02sdt)) and not (.0)) and ._svstdtn29>. then ASTAGE = 'Follow up stage'; else if min(_svstdtn29,_eosdt,_dthdt)>"&SYSDATE9."d and (index(VSTPT,'POST') or ori_adtm>tr02sdtm>. or (cmiss(ori_adtm,tr02sdtm)>0 and adt>tr02sdt)) and not (.34 then do; ATPT = ''; AWRANGE = ''; AWTARGET = .; AWTDIFF = .; end; else if index(ori_visit,'Uns') and missing(_ill_dat) and first.avisit then do; ATPT = ''; AWRANGE = ''; AWTARGET = .; AWTDIFF = .; end; else if index(ori_visit,'Uns') and missing(_ill_dat) then do; ATPT = ''; AWRANGE = ''; AWTARGET = .; AWTDIFF = .; end; else if visit='Illness Visit Day 3 - Day 21' and missing(_ill_dat) then do; ATPT = ''; AWRANGE = ''; AWTARGET = .; AWTDIFF = .; end; end; if ^missing(ATPT) then ATPTN = input(compress(scan(ATPT,2,' ')),best.); ori_aval = aval; * Analysis Toxicity Grade Low/High; if PARAMCD='PULSE' then do; aval = input(strip(put(aval,8.0)),8.0); ATOXDSCL='Bradycardia'; if 50<=aval<=54 then ATOXGRLN = 1; else if 45<=aval<50 then ATOXGRLN = 2; else if .130 then ATOXGRHN = 3; else if .155 then ATOXGRHN = 3; else if .40.0 then ATOXGRHN = 4; else if .100 then ATOXGRHN = 3; else if .25 then ATOXGRHN = 3; else if .0 and grade4fl='Y' then ATOXGRLN = 4; if PARAMCD in ('TEMP' 'DIABP' 'PULSE' 'RESP' 'SYSBP') and ATOXGRHN>0 and grade4fl='Y' then ATOXGRHN = 4; if ^missing(ATOXGRLN) then ATOXGRL = 'Grade '||strip(put(ATOXGRLN,best.)); if ^missing(ATOXGRHN) then ATOXGRH = 'Grade '||strip(put(ATOXGRHN,best.)); * Baseline Record Flag; retain BTOXGRL BTOXGRLN BTOXGRH BTOXGRHN; if first.paramcd and ablfl='Y' then do; BTOXGRL = ATOXGRL; BTOXGRLN = ATOXGRLN; BTOXGRH = ATOXGRH; BTOXGRHN = ATOXGRHN; end; else if first.paramcd then do; BTOXGRLN = .; BTOXGRL = ''; BTOXGRHN = .; BTOXGRH = ''; end; * Change from Baseline; * Shift1 or Shift2; if postfl='Y' and cmiss(ATOXGRL,BTOXGRL)=0 then SHIFT1 = strip(BTOXGRL)||' to '||strip(ATOXGRL); else if postfl='Y' and missing(BTOXGRL) and ^missing(ATOXGRL) then SHIFT1 = 'UNK to '||strip(ATOXGRL); else if postfl='Y' and ^missing(BTOXGRL) and missing(ATOXGRL) then SHIFT1 = strip(BTOXGRL)||' to UNK'; if postfl='Y' and cmiss(ATOXGRH,BTOXGRH)=0 then SHIFT2 = strip(BTOXGRH)||' to '||strip(ATOXGRH); else if postfl='Y' and missing(BTOXGRH) and ^missing(ATOXGRH) then SHIFT2 = 'UNK to '||strip(ATOXGRH); else if postfl='Y' and ^missing(BTOXGRH) and missing(ATOXGRH) then SHIFT2 = strip(BTOXGRH)||' to UNK'; run; * Analysis Flag 01; proc sort tagsort data=atoxgr out=anl01fl; by usubjid paramcd avisitn atptn descending postfl descending _avaln2 _uns _awtdiff descending adt descending vsseq; run; data anl01fl; set anl01fl; by usubjid paramcd avisitn atptn descending postfl descending _avaln2 _uns _awtdiff descending adt descending vsseq; if first.atptn and ^missing(avisitn) and postfl='Y' and _avaln2=1 then ANL01FL = 'Y'; if ABLFL='Y' then ANL01FL='Y'; run; * Analysis Flag 02; proc sort tagsort data=ANL01FL; by usubjid paramcd avisitn atptn descending postfl descending atoxgrln adt vsseq; run; data anl02fl; set ANL01FL; by usubjid paramcd avisitn atptn descending postfl descending atoxgrln adt vsseq; if first.atptn and postfl='Y' and ^missing(atoxgrln) then ANL02FL = 'Y'; run; * Analysis Flag 03; proc sort tagsort data=anl02fl; by usubjid paramcd avisitn atptn descending postfl descending atoxgrhn adt vsseq; run; data advs; set anl02fl; by usubjid paramcd avisitn atptn descending postfl descending atoxgrhn adt vsseq; if first.atptn and postfl='Y' and ^missing(atoxgrhn) then ANL03FL = 'Y'; drop &adslvar:; run; **Generate final dataset by updating certain attributes. Optionally merge common variables & create sequence variable as needed**; %TRTA(dsname=&DSETNAME); %adam_dataset_update( ds=&DSETNAME, libin=work, libout=output, adsllib=adb, addcomvar=Y, addseq=, dropinfmt=Y, mapspecfile=&ADAM_SPEC, maploc=&ADAM_SPEC_LOC, debug=N ); **Generate Value Level Metadata values for the ad dataset**; %* dod_vlm( type=ADAM, selmems=&DSETNAME, excmems=, specloc=&ADAM_SPEC_LOC, specname=&ADAM_SPEC, debug=N ); **Generate Enhanced Controlled Terminology for the ad dataset**; %* dod_enhcd_ct( type=ADAM, selmems=&DSETNAME, excmems=, specloc=&ADAM_SPEC_LOC, specname=&ADAM_SPEC, map_ct_nm=, map_ct_loc=, debug=N );