*************************************************************************************************; * * CLIENT: ModernaTX, Inc. * PROTOCOL: mRNA-1273-P301 * * PURPOSE: Create analysis dataset adeff * * INPUT FILES: SDTM domains * OUTPUT FILES: ADEFF.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 = adeff; %let adslvar=%nrstr(tr01sdt tr01edt dose2dt dos2dtm tr01sdtm tr01edtm dose1fl dose2fl eosdt dthdt randfl saffl rtpcrbl where=(randfl='Y')); **Merge supplemental data onto parent domain**; %revsupp(libin=trans,libout=work,ds=ae,supp=suppae,outds=ae_all); %revsupp(libin=trans,libout=work,ds=ce,supp=suppce,outds=ce_all); %revsupp(libin=trans,libout=work,ds=mb,supp=suppmb,outds=mb_all); proc format; value $ramcd 'COVID' = 'COVID-19' 'COVIDSD' = 'COVID-19 (Secondary Definition)' 'COVIDS' = 'COVID-19 (Considering Scheduled RT-PCR)' 'COVIDSDS' = 'COVID-19 (Secondary Definition and Considering Scheduled RT-PCR)' 'COVIDSEV' = 'Severe COVID-19' 'COVIDSVS' = 'Severe COVID-19 (Considering Scheduled RT-PCR)' 'INFECT' = 'SARS-CoV-2 Infection Regardless of Symptomatology or Severity' 'ASYMPINF' = 'Asymptomatic SARS-CoV-2 Infection' 'ASYMPINA' = 'Asymptomatic SARS-CoV-2 Infection per Adjudication' 'DEATHCVD' = 'Death Caused by COVID-19' 'COVIDA' = 'COVID-19 per Adjudication' 'COVIDSVA' = 'Severe COVID-19 per Adjudication' ; invalue avisitn 'Day 29'=3 'Day 57'=4 'Day 209'=6 'Day 394'=7 'Day 759'=8 'Participant Decision Visit / OL-D1'=10 'Open Label Day 29'=11 'Open Label Day 57'=12 ; run; %macro steps_CO(outcd=,whe=,spevit=Visit 2 Day 29); proc sql; create table step_1_1 as select distinct a.*,b.mbdtc,b.mbdtn,b.dthdt,b.rev_visit,b.rev_mbdtn,b.visit from adsymp_&outcd. a inner join (select *,mbdtn as rev_mbdtn, case when visit in ("&spevit.") then '0'||visit else '9'||visit end as rev_visit from mb_adsl &whe.) b on a.usubjid=b.usubjid and a.subjid=b.subjid and b.mbdtn-14<=a.adt<=b.mbdtn+14 and b.mbdtn>. group by a.usubjid,a.subjid,aseq having ^missing(mbdtn) and ^missing(adt) and min(adt) and ^missing(symsetn) order by usubjid,subjid,symsetn,mbdtn,paramcd,adt,rev_visit; quit; data step_1_2; set step_1_1; by usubjid subjid symsetn mbdtn paramcd adt rev_visit; if first.paramcd; run; proc sort data=step_1_2;by usubjid subjid mbdtn symsetn adt paramcd descending rev_visit;run; data step_1_3; set step_1_2; by usubjid subjid mbdtn symsetn adt paramcd descending rev_visit; retain par_n ; if first.symsetn then par_n=0; if first.paramcd then par_n=par_n+1; if (symsetn=1 and par_n=2) or (symsetn=2 and par_n=1); run; proc sort data=step_1_3;by usubjid subjid mbdtn descending adt;run; data step_1; set step_1_3; by usubjid subjid mbdtn; if last.mbdtn; run; proc sql; create table step_2 as select *,count(distinct PARAMCD) as cnt_symptom from step_1 group by usubjid,subjid,symsetn,mbdtn having adt=min(adt); create table step_3 as select distinct usubjid,subjid,adt as adt_interim,mbdtn as pcrdt format date9.,dthdt, "&outcd." as paramcd,'Yes' as avalc,rev_visit,rev_mbdtn format date9. from step_2 group by usubjid,subjid,symsetn,mbdtn having adt=min(adt); create table out_&outcd. as select *,max(adt_interim,pcrdt) as adt format date9., case when rev_mbdtn=pcrdt and substr(rev_visit,1,1)='0' then 'Y' else '' end as PCRD29FL from step_3; quit; %mend steps_CO; %macro steps(outcd=,whe=,spevit=Visit 2 Day 29); proc sql; create table step_1 as select distinct a.*,b.mbdtc,b.mbdtn,b.dthdt,b.rev_visit,b.rev_mbdtn format date9. from adsymp_&outcd. a inner join (select *,mbdtn as rev_mbdtn, case when visit in ("&spevit.") then '0'||visit else '9'||visit end as rev_visit from mb_adsl &whe.) b on a.usubjid=b.usubjid and a.subjid=b.subjid and b.mbdtn-14<=a.adt<=b.mbdtn+14 and b.mbdtn>. group by a.usubjid,a.subjid,aseq having ^missing(mbdtn) and ^missing(adt) and adt=min(adt) and ^missing(symsetn) order by usubjid,subjid,symsetn,adt; create table step_2 as select *,count(distinct PARAMCD) as cnt_symptom from step_1 group by usubjid,subjid,symsetn,mbdtn having adt=min(adt); create table step_3 as select distinct usubjid,subjid,adt as adt_interim,mbdtn as pcrdt format date9.,dthdt, "&outcd." as paramcd,'Yes' as avalc,rev_visit,rev_mbdtn from step_2 where (symsetn=1 and cnt_symptom>=2) or (symsetn=2 and cnt_symptom>=1) group by usubjid,subjid,mbdtn having adt=min(adt); create table out_&outcd. as select *,max(adt_interim,pcrdt) as adt format date9., case when rev_mbdtn=pcrdt and substr(rev_visit,1,1)='0' then 'Y' else '' end as PCRD29FL from step_3 order by usubjid,subjid,pcrdt,adt,rev_mbdtn; proc sort data=out_&outcd. nodupkey; by usubjid subjid pcrdt adt; run; quit; %mend steps; data adb_adsl; set adb.adsl; run; **INSERT CODE TO GENERATE DATASET**; /** mb, postivie PCR test **/ data mb_all; length usubjid $25 subjid $20; merge mb_all(in=a) adb_adsl(in=b keep=USUBJID subjid); by usubjid subjid; if mbtestcd='SARSCOV2' and upcase(MBORRES) in ('DETECTED' 'Y' 'YES' 'POSITIVE') then output; run; data mb_adsl; merge mb_all(in=a) adb_adsl(in=b keep=USUBJID subjid &adslvar.); by usubjid subjid; if ^missing(mbdtc) then mbdtn = input(mbdtc,yymmdd10.); if a and b and mbdtc>:put(tr01sdt,yymmdd10.) and upcase(mbstresc) in ('DETECTED' 'Y' 'YES' 'POSITIVE') then output; run; /** adsymp - PARAMCD: COVID, COVIDS **/ data adsymp_covid; set adb.adsymp(where=(avalc in ('Y' 'YES'))); if paramcd='NLSMELL' then paramcd='NLTASTE'; if paramcd='BODYACHE' then paramcd='MYALGIA'; if paramcd in ('CEPNEU' 'REPNEU') and astdt>. then adt = astdt; if paramcd in ('FEVER' 'CHILLS' 'MYALGIA' 'HEADACHE' 'STHROAT' 'NLSMELL' 'NLTASTE') then symsetn = 1; else if paramcd in ('COUGH', 'SHBREATH', 'DIBREATH' 'CEPNEU' 'REPNEU') then symsetn = 2; run; %steps_CO(outcd=COVID,whe=%nrstr(where visit not in ('Visit 2 Day 29' 'Participant Decision Visit / OL-D1'))); data adsymp_covids; set adsymp_covid; run; %steps_CO(outcd=COVIDS,whe=,spevit=Visit 2 Day 29); /** adsymp - PARAMCD: COVIDSD, COVIDSDS **/ data adsymp_covidsd; set adb.adsymp(where=(avalc in ('Y' 'YES'))); if paramcd in ('FEVER' 'CHILLS' 'COUGH' 'SHBREATH' 'DIBREATH' 'FATIGUE' 'MYALGIA' 'BODYACHE' 'HEADACHE' 'NLTASTE' 'NLSMELL' 'STHROAT' 'NASALCON' 'RUNNOSE' 'NAUSEA' 'VOMIT' 'DIARRHEA') then symsetn = 2; run; %steps(outcd=COVIDSD,whe=%nrstr(where visit not in ('Visit 2 Day 29' 'Participant Decision Visit / OL-D1'))); data adsymp_covidsds; set adsymp_covidsd; run; %steps(outcd=COVIDSDS,whe=,spevit=Visit 2 Day 29); /** adis_crit5 - PARAMCD - INFECT **/ data _adis_cirt5; set adb.adis(where=(crit5fl='Y' and ^missing(adt))); _dt=adt; run; proc sort data=_adis_cirt5; by usubjid subjid randfl _dt; run; data _mb_adsl; set mb_adsl; _dt=mbdtn; visit_rtp=visit; keep usubjid subjid mbdtn randfl _dt visit_rtp; run; proc sort data=_mb_adsl; by usubjid subjid randfl _dt; run; data out_infect; length EVIDINF $50; merge _adis_cirt5(in=is) _mb_adsl(in=rtp); by usubjid subjid randfl _dt; PARAMCD = 'INFECT'; AVALC = 'Yes'; if rtp and not is then EVIDINF='Virology'; else if is and not rtp then EVIDINF='Serology'; else if rtp and is then EVIDINF='Virology and Serology'; if rtp then do; pcrdt = mbdtn; adt = pcrdt; end; if rtp and visit_rtp='Visit 2 Day 29' then PCRD29FL = 'Y'; format pcrdt adt date9.; run; proc sort data=out_infect; by usubjid subjid adt descending pcrdt descending pcrd29fl; run; data out_infect(keep=usubjid subjid paramcd avalc pcrdt adt PCRD29FL EVIDINF); set out_infect; by usubjid subjid adt descending pcrdt descending pcrd29fl; if first.subjid and randfl='Y' then output; run; /** summarized PARAMCD - COVIDSEV, COVIDSVS **/ %macro create_sev(mcd=,indst=); data adsymp_&mcd.; set adb.adsymp(where=(avalc in ('Y' 'YES'))); if paramcd='O2SAT93' then astdt=adt; else if astdt=. and aendt=. then astdt=adt; if paramcd in ('RR30' 'HR125' 'OXYGEN93' 'O2SAT93' 'PAO2F300' 'RF' 'ARDS' 'S90D60' 'VASOPRES' 'ARDYSF' 'HEPDYSF' 'NEURDYSF' 'ICU') then do; symsetn = 2; output; end; run; proc sql; create table covid_sev as select distinct a.usubjid,a.subjid,a.aseq,b.dthdt,b.pcrdt,a.adt as sev_adt, aendt,max(a.adt) as max_sympdt format date9.,b.adt as covid_adt,a.astdt, b.rev_visit from adsymp_covidsev a left join (select * from &indst.) b on a.usubjid=b.usubjid and a.subjid=b.subjid and (/*b.pcrdt-14<=a.adt<=b.pcrdt+28 or*/ (a.astdtpcrdt+28) or a.adt=. or .pcrdt+28) or (.tr01sdt>. then input(substr(mbdtc,1,10),yymmdd10.) else . end as _pcrdt format date9.,max(input(substr(mbdtc,1,10),yymmdd10.)) as pcrdt format date9., "DEATHCVD" as paramcd,'Yes' as avalc from /*mb_adsl*/ (select * from trans.mb where mbtestcd='SARSCOV2') a inner join adb.adsl b on a.usubjid=b.usubjid and a.subjid=b.subjid group by a.usubjid,a.subjid having ^missing(adt) and input(substr(mbdtc,1,10),yymmdd10.)=pcrdt order by usubjid,subjid; quit; data out_deathcvd; length usubjid $25 subjid $20; merge _out_deathcvd(in=a) ae_all(in=b); by usubjid subjid; if a and b; pcrdt = _pcrdt; drop mbdtc _pcrdt tr01sdt; run; /**CE**/ data ce_adsl; merge ce_all(where=(CECAT='ADJUDICATION') in=a) adb_adsl(in=b keep=USUBJID &adslvar.); by usubjid; if a and b; run; /**CE: COVIDA***/ proc sort data=ce_adsl(where=(find(cereasoc,"EVENT MEETS THE CHARTER DEFINITION OF COVID-19"))) out=ce_cov; by usubjid cestdtc; run; data out_covida; set ce_cov; by usubjid cestdtc; if first.usubjid; if cestdtc~='' then adt=input(cestdtc,yymmdd10.); PARAMCD='COVIDA'; format adt date9.; drop rtpcrbl randfl; run; /**CE: COVIDSVA***/ proc sort data=ce_adsl(where=(find(cereasoc,"EVENT MEETS THE CHARTER DEFINITION OF SEVERE COVID-19"))) out=ce_covsv; by usubjid cestdtc; run; data out_covidsva; set ce_covsv; by usubjid cestdtc; if first.usubjid; if cestdtc~='' then adt=input(cestdtc,yymmdd10.); PARAMCD='COVIDSVA'; format adt date9.; run; /** summarized PARAMCD - ASYMPINF, ASYMPINA **/ %macro create_asympin(mcd=,indst1=,indst2=); proc sql; create table adis_cirt5 as select distinct usubjid,subjid,adt as adt_crit5 format date9.,visit as visit_crit5, visitnum , adt as _dt from adb.adis where crit5fl='Y' and index(upcase(VISIT),'UNSCH')=0 and index(upcase(VISIT),'ILLNESS')=0 and index(upcase(VISIT),'CONVALESCENCE')=0 order by usubjid,subjid,_dt; create table post_dose as select distinct usubjid,subjid,mbdtn format date9.,visit as visit_rtp, mbdtn as _dt from mb_adsl where visit in ('Visit 2 Day 29' 'Participant Decision Visit / OL-D1') order by usubjid,subjid,_dt; quit; data merge_crit; length visit $200 EVIDINF AVISIT $50; merge adis_cirt5(in=a) post_dose(in=b) ; by usubjid subjid _dt; if b and not a then do; EVIDINF='Virology'; visit=visit_rtp; end; else if a and not b then do; EVIDINF='Serology'; visit=visit_crit5; end; else if b and a then do; EVIDINF='Virology and Serology'; visit=visit_rtp; end; if (visitnum in (2,6,10,15,21,32) and a and not b) or visit='Visit 2 Day 29' then AVISIT=substr(VISIT,index(VISIT,'Day')); else if VISIT='Participant Decision Visit / OL-D1' then AVISIT=VISIT; else if VISIT='OL-D29' then AVISIT='Open Label Day 29'; else if VISIT='OL-D57' then AVISIT='Open Label Day 57'; AVISITN=input(AVISIT,avisitn.); if adt_crit5>=mbdtn and mbdtn>. then minadt = mbdtn; else if mbdtn>=adt_crit5 and adt_crit5>. then minadt = adt_crit5; else if adt_crit5>=mbdtn and mbdtn=. then minadt = adt_crit5; else if mbdtn>=adt_crit5 and adt_crit5=. then minadt = mbdtn; format minadt date9.; /* drop visitnum;*/ run; proc sort data=merge_crit; by usubjid minadt AVISITN; run; proc sort data=merge_crit nodupkey; by usubjid; run; data covid_and_sd; length paramcd $8; set &indst1. &indst2.; adt_covid = adt; format adt_covid pcrdt date9.; run; proc sql; create table comp_adt as select a.*,b.minadt from covid_and_sd a left join merge_crit b on a.usubjid=b.usubjid and a.adt_covid<=b.minadt having adt_covid<=minadt; quit; proc sort data=comp_adt out=comp_uni nodupkey; by usubjid; run; data out_&mcd.; merge comp_uni(in=a) adb_adsl(keep=usubjid rtpcrbl randfl) merge_crit(in=c drop=minadt subjid); by usubjid; PARAMCD = upcase("&mcd."); if adt_crit5>. then ADT = adt_crit5; else ADT = mbdtn; if adt_crit5=. or (adt_crit5=mbdtn and mbdtn>.) then do; PCRDT = ADT; if visit='Visit 2 Day 29' then PCRD29FL = 'Y'; end; if a or randfl^='Y' or not c then delete; run; %mend create_asympin; %create_asympin(mcd=ASYMPINF,indst1=out_covids,indst2=out_covidsds); %create_asympin(mcd=ASYMPINA,indst1=out_covida,indst2=out_covidsds); /**************************************/ data setall; length avalc $2000 paramcd $8 param $200 PCRD29FL $1; set out_:; PARAM = put(paramcd,$ramcd.); drop tr01sdt studyid randfl avalc subjid; run; proc sql; create table final as select a.*,b.tr01sdt,b.studyid,'Y' as AVALC length=50 from setall a left join (select usubjid,tr01sdt,studyid from adb_adsl) b on a.usubjid=b.usubjid order by usubjid,paramcd,adt,pcrdt; quit; data final; merge final(in=a) adb_adsl(keep=usubjid randfl EUAVACDT AP02SDT in=b); by usubjid; if a ; if randfl='N' then delete; run; data adeff; set final; by usubjid paramcd adt pcrdt; * Period; if . 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 );