*****************************************************************************************************************;
** Program Name   : adva.sas                                                                                   **;
** Date Created   : 07Mar2021                                                                                  **;
** Programmer Name: LIUB65                                                                                     **;
** Purpose        : Create adva dataset                                                                        **;
** Input data     : is suppis adsl                                                                             **;
** Output data    : adva.sas7bdat                                                                              **;
******************************************************************************************************************;
%let oprot=/Volumes/app/cdars/prod/sites/cdars4/prjC459/nda2_unblinded_esub/bla_euaext_esub_sdtm/saseng/cdisc3_0;
%let prot=/Volumes/app/cdars/prod/sites/cdars4/prjC459/nda2_unblinded_esub/bla_esub_adam/saseng/cdisc3_0;
libname dataprot "&oprot./data" access=readonly;
libname datvprot "&prot./data_vai";

proc printto print="&prot./analysis/esub/output/adva.rpt" 
        log="&prot./analysis/esub/logs/adva.log" new;
run;

******************************************************************************************;
* Clean *;
******************************************************************************************;

proc delete data=work._all_;
run;

******************************************************************************************;
* Read in source IS SDTM datasets. *;
******************************************************************************************;

/*Impute time to correct period */
data is;
    length isdtc $20;
	set dataprot.is;
    where not missing(istestcd);

    if (index(visit, "COVID") or visit in ('V101_VAX3' 'V201_SURVEIL_CONSENT')) 
        then
            isdtc=strip(isdtc)||"T23:59:59";
    else
        isdtc=strip(isdtc)||"T00:00:00";
run;

/*Select retest result for Phase 1 subjects with available retests*/
data is_;
    set is;

    if ISTSTDTL ne " ";
    keep usubjid istest istestcd visit visitnum isdtc ISTSTDTL;
run;

data is_;
    set is_;

proc sort nodupkey;
    by usubjid visit;
run;

proc sql;
    create table is2_ as select a.*, b.ISTSTDTL as _ISTSTDTL1 from is as a left 
        join is_ as b on a.usubjid=b.usubjid and a.visit=b.visit and 
        a.visitnum=b.visitnum;
quit;

data is;
    set is2_;
    ISUSE="N";

    /*have retest, retest value not missing*/
    if _ISTSTDTL1 ne " " and ISTSTDTL ne " " then
        ISUSE="Y";

    if _ISTSTDTL1=" " and ISTSTDTL=" " then
        ISUSE="Y";
run;

data _dsnin;
    set is;
run;

data _dsnin;
    set _dsnin;
    ADT=input(ISDTC, ??is8601da.);

    if ^missing(ISDTC) then
        do;
            length hr mn sc $2 newtime $8;
            yr=substr(ISDTC, 1, 4);
            hr=substr(ISDTC, 12, 2);
            mn=substr(ISDTC, 15, 2);
            sc=substr(ISDTC, 18, 2);
            ;

            if yr ne ' ' then
                do;

                    if hr eq " " then
                        do;
                            newtime="00:00:00";
                            ATM=input(newtime, ??time8.);
                            format ATM time8.;
                            ATMF='H';
                        end;
                    else
                        do;
                            tflag=' ';

                            if sc eq "  " then
                                do;
                                    sc='00';
                                    tflag='S';
                                end;

                            if mn eq "  " then
                                do;
                                    mn='00';
                                    tflag='M';
                                end;
                            newtime=(trim(left(hr))||':'||trim(left(mn))||':'||trim(left(sc)));
                            ATM=input(newtime, ??time8.);
                            format ATM time8.;
                            ATMF=tflag;
                            drop tflag;
                        end;
                end;
            drop yr hr mn sc newtime;
        end;
    ;
    ADTM=DHMS(ADT, 0, 0, ATM);
    format ADT date9. ADTM datetime20. ATM time8.;
    label ADT="Analysis Date" ADTM="Analysis Date/Time" ATM="Analysis Time" 
        ATMF="Analysis Time Imputation Flag";
run;

/* Remove NOTDONEs and create PARAM */
data _dsnin;
    set _dsnin(rename=(isstresn=aval iscat=parcat1 isdy=ady isseq=srcseq 
        domain=srcdom istestcd=paramcd)) end=eof;
    where upcase(paramcd) ne "ISALL";

    if paramcd in ("C2NGNT50" "C2NGNT90") then
        do;

            if not missing(ismethod) then
                param=trim(left(istest))||' ('||trim(left("titer"))||') - '||trim(left(ismethod));
            else
                param=trim(left(istest))||' ('||trim(left("titer"))||')';
        end;
    else if paramcd in ("C19NIG") then
        do;

            if not missing(ismethod) then
                param=trim(left(istest))||' - '||trim(left(ismethod));
            else
                param=trim(left(istest));
        end;
    else
        do;

            if not missing(ismethod) then
                param=trim(left(istest))||' ('||trim(left(isstresu))||') - '||trim(left(ismethod));
            else
                param=trim(left(istest))||' ('||trim(left(isstresu))||')';
        end;
    avalc=isstresc;

    /*     if missing(isstresu) and isorres in ("IND" "QNS" "INDETERMINATE" "NOT DONE") then delete;  *//*Check before finalization*/

    if isorres in ("NOT DONE") then
        delete;
    srcvar="ISSTRESN";

    if parcat1="SEROLOGY" then
        parcat1n=1;
run;

/* Merge with ADSL */
Data work.adsl;
    Set datvprot.adsl;

    If Missing(TR01STM) then
        _apx_TR01STM="23:59:30"t;
    Else
        _apx_TR01STM=TR01STM;

    If Missing(TR01ETM) then
        _apx_TR01ETM="23:59:29"t;
    Else
        _apx_TR01ETM=TR01ETM;

    If ^Missing(TR01SDT) then
        _apx_TR01SDTM=dhms(TR01SDT, 0, 0, _apx_TR01STM);

    If ^Missing(TR01EDT) then
        _apx_TR01EDTM=dhms(TR01EDT, 0, 0, _apx_TR01ETM);
    AP01SDT=datepart(_apx_TR01SDTM);
    AP01STM=timepart(_apx_TR01SDTM);

    If Missing(TR02STM) then
        _apx_TR02STM="23:59:30"t;
    Else
        _apx_TR02STM=TR02STM;

    If Missing(TR02ETM) then
        _apx_TR02ETM="23:59:29"t;
    Else
        _apx_TR02ETM=TR02ETM;

    If ^Missing(TR02SDT) then
        _apx_TR02SDTM=dhms(TR02SDT, 0, 0, _apx_TR02STM);

    If ^Missing(TR02EDT) then
        _apx_TR02EDTM=dhms(TR02EDT, 0, 0, _apx_TR02ETM);
    AP02SDT=datepart(_apx_TR02SDTM);
    AP02STM=timepart(_apx_TR02SDTM);

    if ^Missing(_apx_TR02SDTM-1) then
        do;
            _apx_TR01EDTM=min((_apx_TR02SDTM-1), (_apx_TR01EDTM+((365)*86400)));
        end;
    else
        _apx_TR01EDTM=_apx_TR01EDTM+((365)*86400);
    AP01EDT=datepart(_apx_TR01EDTM);
    AP01ETM=Timepart(_apx_TR01EDTM);
    AP01SDTM=dhms(AP01SDT, 0, 0, AP01STM);
    AP01EDTM=dhms(AP01EDT, 0, 0, AP01ETM);
    Attrib AP01SDT Label="Period 01 Start Date" AP01EDT Label="Period 01 End Date" 
        AP01STM Label="Period 01 Start Time" AP01ETM Label="Period 01 End Time" 
        AP01SDTM Label="Period 01 Start Datetime" AP01EDTM 
        Label="Period 01 End Datetime";
    Format AP01SDT AP01EDT date9. AP01STM AP01ETM time8. AP01SDTM AP01EDTM 
        datetime20.;
    _apx_TR02EDTM=_apx_TR02EDTM+((365)*86400);
    AP02EDT=datepart(_apx_TR02EDTM);
    AP02ETM=Timepart(_apx_TR02EDTM);
    AP02SDTM=dhms(AP02SDT, 0, 0, AP02STM);
    AP02EDTM=dhms(AP02EDT, 0, 0, AP02ETM);
    Attrib AP02SDT Label="Period 02 Start Date" AP02EDT Label="Period 02 End Date" 
        AP02STM Label="Period 02 Start Time" AP02ETM Label="Period 02 End Time" 
        AP02SDTM Label="Period 02 Start Datetime" AP02EDTM 
        Label="Period 02 End Datetime";
    Format AP02SDT AP02EDT date9. AP02STM AP02ETM time8. AP02SDTM AP02EDTM 
        datetime20.;
run;

proc sort data=_dsnin out=_ds1;
    by USUBJID;
run;

proc sort data=adsl out=_ds2;
    by USUBJID;
run;

data adsl_dsin;
    merge _ds1(in=d1) _ds2(in=d2 keep=Usubjid SUBJID SITEID AGE AGEU SEX SEXN RACE 
        RACEN RANDFL SAFFL ARM ARMCD ACTARM ACTARMCD TRTSDT TRTEDT TRTSTM TRTETM 
        TRT01A TRT01AN TRT02A TRT02AN TRT01P TRT01PN TRT02P TRT02PN TR01SDT TR01STM 
        TR01SDTM TR01EDT TR01ETM TR01EDTM TR02SDT TR02STM TR02SDTM TR02EDT TR02ETM 
        TR02EDTM COHORTN COHORT VAX101DT VAX102DT VAX10UDT VAX201DT VAX202DT SAFFL 
        AAI01FL EVAL02FL AAI02FL EVAL01FL DOSALVL DOSALVLN DOSPLVL DOSPLVLN AGEGR1 
        AGEGR1N AGEGR2 AGEGR2N AGEGR4 AGEGR4N PHASE PHASEN COVBLST HIVFL PEDIMMFL 
        EV1MD2FL AGETR01 VAX101 VAX102 VAX10U VAX201 VAX202 VAX20U VAX20UDT UNBLNDDT 
        MULENRFL RAND1FL TRTSDTM TRTEDTM AP01SDT AP01STM AP01SDTM AP01EDT AP01ETM 
        AP01EDTM AP02SDT AP02STM AP02SDTM AP02EDT AP02ETM AP02EDTM TR01SDT TR01STM 
        TR01SDTM TR01EDT TR01ETM TR01EDTM TR02SDT TR02STM TR02SDTM TR02EDT TR02ETM 
        TR02EDTM);
    by USUBJID;

    if d1;
run;

/* Create period related variables */
data adsl_dsin;
    set adsl_dsin;
    _AP01SDT=AP01SDT;
    _AP01STM=AP01STM;
    _AP01SDTM=AP01SDTM;
    _AP01EDT=AP01EDT;
    _AP01ETM=AP01ETM;
    _AP01EDTM=AP01EDTM;
    AP01SDTM=AP01SDTM;
    AP01EDTM=AP01EDTM - hms(0, 0, 0);
    AP01SDT=datepart(AP01SDTM);
    AP01STM=timepart(AP01SDTM);
    AP01EDT=datepart(AP01EDTM);
    AP01ETM=timepart(AP01EDTM);
    _AP02SDT=AP02SDT;
    _AP02STM=AP02STM;
    _AP02SDTM=AP02SDTM;
    _AP02EDT=AP02EDT;
    _AP02ETM=AP02ETM;
    _AP02EDTM=AP02EDTM;
    AP02SDTM=AP02SDTM - hms(0, 0, 0);
    AP02EDTM=AP02EDTM;
    AP02SDT=datepart(AP02SDTM);
    AP02STM=timepart(AP02SDTM);
    AP02EDT=datepart(AP02EDTM);
    AP02ETM=timepart(AP02EDTM);
run;

data _dsnin;
    attrib APERIODC length=$20. label="Period (C)" APERIOD label="Period" APHASE 
        length=$20. label="Phase" TRTP length=$100. label="Planned Treatment" TRTA 
        length=$100. label="Actual Treatment" TRTPN label="Planned Treatment (N)" 
        TRTAN label="Actual Treatment (N)" APERSTM label="Period Start Time" 
        format=time8. APERETM label="Period End Time" format=time8. APERSDTM 
        label="Period Start Datetime" format=datetime20. APEREDTM 
        label="Period End Datetime" format=datetime20. APERSDT 
        label="Period Start Date" format=date9. APEREDT label="Period End Date" 
        format=date9. APERDY label="Relative Day of Period Start";
    set adsl_dsin;
    Array APSDT[*] AP01SDT AP02SDT;
    Array APEDT[*] AP01EDT AP02EDT;
    Array APSDTM[*] AP01SDTM AP02SDTM;
    Array APEDTM[*] AP01EDTM AP02EDTM;

    if ADTM <=APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1])then
        do;
            TRTP=TRT01P;
            TRTA=TRT01A;
            TRTPN=TRT01PN;
            TRTAN=TRT01AN;
            APERIOD=1;
            APERIODC="Period 01";
        end;
    else if ADTM > APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1]) then
        do;
            TRTP=TRT02P;
            TRTA=TRT02A;
            TRTPN=TRT02PN;
            TRTAN=TRT02AN;
            APERIOD=2;
            APERIODC="Period 02";
        end;

    if ADTM <=APSDTM[1] and ^missing(ADTM) and ^missing(APSDTM[1]) then
        do;
            Aphase="PRE-TREATMENT";
        end;
    else if APSDTM[1] < ADTM <=APEDTM[1] and ^missing(ADTM) 
        and ^missing(APSDTM[1]) and ^missing(APEDTM[1]) then
            do;
            Aphase="TREATMENT "||"01";
        end;
    else if APEDTM[1] < ADTM <=APSDTM[2] and ^missing(APEDTM[1]) 
        and ^missing(ADTM) and ^missing(APSDTM[2]) then
            do;
            Aphase="OFFDRUG "||"01";
        end;
    else if APSDTM[2] < ADTM <=APEDTM[2] and ^missing(ADTM) 
        and ^missing(APSDTM[2]) and ^missing(APEDTM[2]) then
            do;
            Aphase="TREATMENT "||"02";
        end;
    else if ADTM > APEDTM[2] and ^missing(ADTM) and ^missing(APEDTM[2]) then
        do;
            Aphase="FOLLOW-UP";
        end;

    if ADTM <=APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1]) then
        do;

            if ADT < APSDT[1] then
                APERDY=ADT - APSDT[1];
            else if ADT >=APSDT[1] then
                APERDY=ADT - APSDT[1] + 1;
        end;
    else if ADTM > APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1]) then
        do;

            if ADT < APSDT[2] and ^missing(APSDT[2]) then
                APERDY=ADT - APSDT[2];
            else if ADT >=APSDT[2] and ^missing(APSDT[2]) then
                APERDY=ADT - APSDT[2] + 1;
        end;

    if ADTM <=APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1])then
        do;
            APERSDT=AP01SDT;
            APEREDT=AP01EDT;
            APERSTM=AP01STM;
            APERETM=AP01ETM;
            APERSDTM=AP01SDTM;
            APEREDTM=AP01EDTM;
        end;
    else if ADTM > APEDTM[1] and ^missing(ADTM) and ^missing(APEDTM[1]) then
        do;
            APERSDT=AP02SDT;
            APEREDT=AP02EDT;
            APERSTM=AP02STM;
            APERETM=AP02ETM;
            APERSDTM=AP02SDTM;
            APEREDTM=AP02EDTM;
        end;
run;

run;

data adsl_dsin;
    attrib AP01SDT format=date9. label="Period 01 Start Date" AP01EDT 
        format=date9. label="Period 01 End Date" AP01STM 
        format=time8. label="Period 01 Start Time" AP01ETM 
        format=time8. label="Period 01 End Time" AP01SDTM 
        format=datetime20. label="Period 01 Start Datetime" AP01EDTM 
        format=datetime20. label="Period 01 End Date/Time" AP02SDT 
        format=date9. label="Period 02 Start Date" AP02EDT 
        format=date9. label="Period 02 End Date" AP02STM 
        format=time8. label="Period 02 Start Time" AP02ETM 
        format=time8. label="Period 02 End Time" AP02SDTM 
        format=datetime20. label="Period 02 Start Datetime" AP02EDTM 
        format=datetime20. label="Period 02 End Date/Time";
    set _dsnin(drop=AP01SDT AP01STM AP01SDTM AP01EDT AP01ETM AP01EDTM AP02SDT 
        AP02STM AP02SDTM AP02EDT AP02ETM AP02EDTM rename=(_AP01SDT=AP01SDT 
        _AP01STM=AP01STM _AP01SDTM=AP01SDTM _AP01EDT=AP01EDT _AP01ETM=AP01ETM 
        _AP01EDTM=AP01EDTM _AP02SDT=AP02SDT _AP02STM=AP02STM _AP02SDTM=AP02SDTM 
        _AP02EDT=AP02EDT _AP02ETM=AP02ETM _AP02EDTM=AP02EDTM) );
run;

data Allparamdata;
    length XOCFDERV 8;
    set adsl_dsin;
    paramcd=upcase(paramcd);
    winderv=0;
    XOCFDERV=0;
    label XOCFDERV="Result imputed by XOCF method (1=Yes)";
run;

data ParQData1;
    Length WINTNAME WINTMPLT WINFNAME $40 WINMETH $10 XVISWINM $30 XOCFMETH $20 
        XOCFSUB XOCFWIN $400 VISWINM obs 8;
    set Allparamdata;
    WinTmplt="VISITS";
    WinTName="VISITS";
    WinMeth="L";
    XVisWinM="";
    VisWinM=0;
    XOCFMeth="OBS";
    XOCFSub="";
    XOCFWin="";
    WinFName="winmeta1";
    obs=_n_;
    Label WinTName="Window template name" WinMeth="Windowing selection method" 
        XOCFMeth="XOCF selection method" Wintmplt="Original Window Template" 
        XOCFSub="Criteria to select obs for Carry Forward" 
        XOCFWin="Criteria to select window for Imputation";
run;

/* visit window */
data ParQCond1;
    length avisit $ 40 baseinfo $ 8;
    set ParQData1;

    if visitnum in (60748 60765) then
        do;
            avisit="Before Vaccination 1";
            avisitn=1;
            baseinfo="PRE";
        end;
    else if visitnum in (60750) then
        do;
            avisit="1 Week after Vaccination 1";
            avisitn=2;
            baseinfo="POST";
        end;
    else if visitnum in (60751) then
        do;
            avisit="3 Weeks after Vaccination 1";
            avisitn=3;
            baseinfo="POST";
        end;
    else if visitnum in (60752 1165455) then
        do;
            avisit="1 Week after Vaccination 2";
            avisitn=4;
            baseinfo="POST";
        end;
    else if visitnum in (60753 1165456) then
        do;
            avisit="2 Weeks after Vaccination 2";
            avisitn=5;
            baseinfo="POST";
        end;
    else if visitnum in (60754 60767 1165457) then
        do;
            avisit="1 Month after Vaccination 2";
            avisitn=6;
            baseinfo="POST";
        end;
    else if visitnum in (60755 60768) then
        do;
            avisit="6 Months after Vaccination 2";
            avisitn=7;
            baseinfo="POST";
        end;
    else if visitnum in (60756 60769) then
        do;
            avisit="12 Months after Vaccination 2";
            avisitn=8;
            baseinfo="POST";
        end;
    else if visitnum in (60757 60770) then
        do;
            avisit="24 Months after Vaccination 2";
            avisitn=9;
            baseinfo="POST";
        end;

    /* Correct AVISIT/AVISITN for 100ug group */
    if cohortn=1.16 then
        do;

            if visitnum=60752 then
                do;
                    avisitn=3.1;
                    avisit="4 Weeks after Vaccination 1";
                end;
            else if visitnum=60753 then
                do;
                    avisitn=3.2;
                    avisit="5 Weeks after Vaccination 1";
                end;
            else if visitnum=60754 then
                do;
                    avisitn=3.3;
                    avisit="1 Month and 3 weeks after Vaccination 1";
                end;
            else if visitnum=1165454 then
                do;
                    avisitn=3.9;
                    avisit="Before Vaccination 2";
                end;
        end;
    label avisitn="Analysis Visit (N)" avisit="Analysis Visit";
run;

/* End visit window */
proc sort data=ParQData1 out=ParQData1;
    by paramcd usubjid VISITNUM obs;
run;

proc sort data=ParQCond1 out=ParQCond1;
    by paramcd usubjid VISITNUM obs;
run;

data ParQAll1 (drop=obs);
    merge ParQData1 ParQCond1;
    by paramcd usubjid VISITNUM obs;
run;

data AllData;
    set ParQAll1;

    if paramcd='C2NGNT50' then
        paramn=1;
    else if paramcd='C2NGNT90' then
        paramn=2;
    else if paramcd='C19S1IGG' then
        paramn=3;
    else if paramcd='C19RBDIG' then
        paramn=4;
    else if paramcd='C19NIG' then
        paramn=5;
run;

proc sort data=alldata;
    by paramcd;
run;

data bds_apply_window;
    set AllData;
run;

data _parwin _parwinmiss;
    set bds_apply_window;
    _instrec=.;

    if avisitn=. or winmeth=' ' or baseinfo="PRE" then
        do;
            WINCNFL=' ';
            output _parwinmiss;
        end;
    else
        output _parwin;
run;

data _param;
    set _parwin;
    array _num _numeric_;
    array _vis[*] winref;
    array _new[*] visvaval;

    do _i=1 to dim (_vis);
        vis_varname=lowcase(_vis[_i]);

        do _j=1 to dim(_num);
            num_varname=lowcase(vname(_num[_j]));

            if num_varname=vis_varname then
                do;
                    _new[_i]=_num[_j];
                    leave;
                end;
        end;
    end;
    drop vis_varname num_varname _i _j;
run;

data _parscale;
    length method stat $20.;
    set _param;
    _wscale=0;
    _winref=visvaval;
    _winbeg=awlo;
    _winend=awhi;
    _wintarg=awtarget;
    method=trim(upcase(scan(winmeth, 1, '_')));
    stat=trim(upcase(scan(winmeth, 2, '_')));

    if indexw(method, 'F') then
        _Wscale=_winref-_winbeg;
    else if indexw(method, 'L') then
        _Wscale=_winend-_winref;
    else if indexw(method, 'A') then
        _Wscale=1;
    else if indexw(method, 'C') then
        _Wscale=abs(_winref-_wintarg);
    else if indexw(method, 'CB') then
        _Wscale=abs(_wintarg-_winref)+max(_winref>_wintarg, 
            0)*(abs(_wintarg-_winbeg)+1);
    else if indexw(method, 'CA') then
        _Wscale=abs(_wintarg-_winref)+max(_winref<_wintarg, 
            0)*(abs(_wintarg-_winbeg)+1);
    else if indexw(method, 'CF') then
        _Wscale=abs(_wintarg-_winref)+max(_winref>_wintarg, 0)*0.5;
    else if indexw(method, 'CL') then
        _Wscale=abs(_wintarg-_winref)+max(_winref<_wintarg, 0)*0.5;
run;

proc sql;
    create table _parpick As select *, min(_wscale) as min_wscale, case when 
        _wscale=min(_wscale) then 1 else 0 end as _parpick from _parscale where aval 
        ne . or ^missing(avalc) group by usubjid, paramcd, APERIOD, avisitn outer 
        union corr select *, 0 as _parpick from _parscale where missing(avalc) group 
        by usubjid, paramcd, APERIOD, avisitn;
quit;

proc sort data=_parpick;
    by usubjid paramcd APERIOD avisitn;
run;

proc summary data=_parpick;
    where _parpick eq 1;
    by usubjid paramcd APERIOD avisitn;
    var min_wscale;
    output out=_parpickmin N(min_wscale)=count;
run;

data _parone _parmany;
    merge _parpick(in=a) _parpickmin(in=b keep=usubjid paramcd APERIOD avisitn 
        count);
    by usubjid paramcd APERIOD avisitn;

    if a;

    if count > 1 then
        output _parmany;
    else
        do;

            if _parpick=1 then
                WINCNFL='Y';
            else
                WINCNFL=' ';
            output _parone;
        end;
run;

data _parstat _parnostat;
    set _parmany;

    if stat=' ' then
        output _parnostat;
    else
        output _parstat;
run;

proc sort data=_parnostat out=_parnostat;
    by usubjid paramcd APERIOD avisitn _winref ADT ATM;
run;

data _parnostat1 _parnostat2;
    set _parnostat;
    WINCNFL=' ';

    if _parpick=1 then
        output _parnostat1;
    else
        output _parnostat2;
run;

data _parnostat1;
    set _parnostat1;
    by usubjid paramcd APERIOD avisitn _winref ADT ATM;

    if last.avisitn then
        do;
            _parpick=1;
            WINCNFL='Y';
        end;
    else
        do;
            _parpick=0;
        end;
run;

data _parnostat;
    set _parnostat1 _parnostat2;
    by usubjid paramcd APERIOD avisitn _winref ADT ATM;
run;

data bds_win_calc (drop=min_wscale visvaval count method stat);
    attrib VISWIN length=8 label='Visit number to use in analysis' XVISWIN 
        length=$40 label='Decode of VisWin' ANL01FL length=$1. 
        label="Analysis Record Flag 01:Window Record" WINCNFL length=$1. 
        label='Visit Window Contributing Record Flag' WINDERFL length=$1. 
        label='Derived Visit Window Record Flag' DTYPE length=$20. 
        label='Derivation Type';
    set _parnostat _parone _parwinmiss;

    if _parpick=1 then
        do;

            if avisitn ne . then
                do;
                    VisWin=avisitn;
                    XVisWin=avisit;
                    ANL01FL='Y';
                end;
            else
                ANL01FL=' ';
        end;

    if _instrec=1 then
        WINDERFL='Y';
    else
        WINDERFL=' ';

    if WINDERFL='Y' and index(winmeth, '_') > 0 then
        do;
            DTYPE=scan(winmeth, 2, '_');
            SRCSEQ=.;
            SRCDOM=" ";
            SRCVAR=" ";
        end;
run;

/* Create baseline */
data bds_base_dsin(drop=_timefield _dosetime);
    set bds_win_calc;
    length Basetype $100. basec $200;
    Base=.;
    BaseType=" ";
    BnrLo=.;
    BnrHi=.;
    Basec=" ";
    AnrLo=.;
    AnrHi=.;
    format _dataDateTime _trtdatetime datetime18.;
    _prdbasecat=1;

    if ^missing(Tr01Stm) then
        _dosetime=Tr01Stm;
    else
        _dosetime="24:00"t;
    _trtdatetime=dhms(Tr01Sdt, 0, 0, _dosetime);

    if ^missing(atm) then
        _timefield=atm;
    else
        _timefield="00:00"t;
    _dataDateTime=dhms(adt, 0, 0, _timefield);
    _minSelectableDateTime=_trtDateTime-(99999*24*60*60);
    BasDerFl=" ";
run;

proc sort data=bds_base_dsin;
    by usubjid PARAMCD _datadatetime;
run;

data bds_base_dsin;
    set bds_base_dsin;
    _nflag1=_n_;
run;

data pre_baseline;
    set bds_base_dsin;
    Where (^Missing(Aval) or ^Missing(Avalc)) and (avisitn=1 and avalc ne "" and 
        adt<=vax101dt and isuse="Y");
run;

proc sql;
    create table pre_basedatetime as select distinct usubjid, PARAMCD  , 
        max(_datadatetime) as _basedatetime from pre_baseline as a group by usubjid, 
        PARAMCD order by usubjid, PARAMCD;
quit;

data pre_baseline;
    set pre_baseline;
    Where (avisitn in (1) and avalc ne "");
run;

proc sql noprint;
    create table getbasetype as select distinct usubjid, PARAMCD, "Study" as 
        _basetype length=100 from pre_baseline order by usubjid, PARAMCD;
quit;

proc sort data=pre_baseline;
    by usubjid _prdbasecat PARAMCD descending _datadatetime;
run;

data pre_baseline;
    set pre_baseline;
    by usubjid _prdbasecat PARAMCD descending _datadatetime;
    retain _count_base_obs;

    if first.PARAMCD then
        _count_base_obs=1;
    else
        _count_base_obs=_count_base_obs+1;
run;

data pre_baseline;
    set pre_baseline;
    _nflag2=_nflag1;
run;

proc sort data=pre_baseline;
    by usubjid PARAMCD PARAMCD ADT;
run;

data pre_baseline_first_last;
    set pre_baseline;
    by usubjid PARAMCD;

    if LAST.PARAMCD then
        do;
            _nflag2=_nflag1;
            output pre_baseline_first_last;
        end;
run;

proc sort data=bds_base_dsin;
    by usubjid PARAMCD PARAMCD ADT;
run;

proc sort data=pre_baseline_first_last;
    by usubjid PARAMCD PARAMCD ADT;
run;

data bds_base_dsin(drop=_aval _avalc _AnrLo _AnrHi);
    merge bds_base_dsin(in=a) pre_baseline_first_last(rename=(aval=_aval 
        Avalc=_Avalc AnrLo=_AnrLo AnrHi=_AnrHi) keep=usubjid PARAMCD aval avalc 
        _nflag2 AnrLo AnrHi) getbasetype pre_basedatetime;
    by usubjid PARAMCD;

    if a;
    base=_Aval;
    basec=put(_Avalc, $200.);
    BnrLo=_AnrLo;
    BnrHi=_AnrHi;
    Basetype=_Basetype;

    if _nflag1=_nflag2 then
        do;
            efbascn=1;
            efbasflg=1;
        end;
run;

data bds_base_dsin(drop=_prdbasecat AnrLo BnrLo AnrHi BnrHi);
    set bds_base_dsin;
    attrib efbascn label='Contributes to Baseline Derivation' efbasflg 
        label='Baseline record flag(1=YES) (num)' ABLFL label='Baseline Record Flag' 
        APSBLFL Label='Post Baseline Record Flag' Base Label='Baseline Value' BaseC 
        Label='Baseline Value (C)' BaseType Label='Baseline Type' BasCnFl 
        label='Baseline Contributing Records' BasDerFl 
        Label='Baseline Derived Record';

    if (^missing(_basedatetime) and _datadatetime>_basedatetime) 
        or (missing(_basedatetime) and _datadatetime>_trtdatetime 
        and ^missing(_trtdatetime)) then
            APSBLFL="Y";

    If EfBasCn=1 then
        BasCnFl="Y";

    If Efbasflg=1 then
        do;
            ABLFL="Y";

            if BaseInfo="PRE" and ABLFL="Y" then
                do;
                    ANL01FL="Y";
                    VisWin=AvisitN;
                    XvisWin=Avisit;
                end;
        end;
run;

proc sort data=bds_base_dsin out=baseflag1 nodupkey;
    by usubjid PARAMCD _basedatetime;
    where (^missing(base) or ^missing(basec)) and apsblfl="Y";
run;

proc sort data=bds_base_dsin;
    by usubjid PARAMCD;
run;

data baseflag2(keep=usubjid PARAMCD);
    merge bds_base_dsin(in=a) baseflag1(in=b drop=_basedatetime);
    by usubjid PARAMCD;

    if a and b;

    if (^missing(aval) or ^missing(avalc)) and (_datadatetime>_basedatetime 
        and ^missing(_basedatetime));
run;

proc sort data=baseflag2 nodupkey;
    by usubjid PARAMCD;
run;

data bds_base(drop=_datadatetime _basedatetime _trtdatetime 
        _minSelectabledatetime _nflag: _basetype:);
    merge bds_base_dsin(in=a) baseflag2(in=b);
    by usubjid PARAMCD;

    if a and b then
        do;
            Ablpblfl="Y";
        end;
    else if a and not b then
        AblpblFl="N";
    attrib ABLPBLFL label='Baseline and post-baseline flag';

    if missing(base) and missing(basec) then
        do;
            AblFl=" ";
            AblpblFl=" ";
            BaseType=" ";
        end;
run;

/* Change from baseline */
data bds_chg_base;
    set bds_base;

    if BASE>. and AVAL>. then
        do;
            CHG=AVAL - BASE;
        end;
    else
        do;
            CHG=.;
        end;
run;

data bds_chg_base;
    set bds_chg_base;

    if BASE>. and AVAL>. then
        do;

            if BASE ne 0 then
                do;
                    PCHG=((AVAL - BASE)/BASE)*100;
                end;
            else
                do;
                    PCHG=.;
                end;
        end;
    else
        do;
            PCHG=.;
        end;
run;

data bds_chg_base;
    attrib CHG label="Change from Baseline" PCHG 
        label="Percent Change from Baseline";
    set bds_chg_base;

    if APSBLFL ne 'Y' then
        do;
            CHG=.;
            PCHG=.;
        end;
run;

data bds_base_lis;
    set bds_chg_base;
    where BASE ne . and PCHG=.;
    keep USUBJID PARAMCD VISIT SRCSEQ AVAL BASE CHG;
run;

proc sort data=bds_base_lis;
    by USUBJID PARAMCD VISIT SRCSEQ;
run;

data final;
    set bds_chg_base;
run;

data final;
    attrib ANL02FL length=$1. label="Analysis Record Flag 02:In TRT Period";
    set final;
    _obs=_N_;

    if APERSDT < ADT <=APEREDT then
        ANL02FL='Y';
run;

/* Create LLOQ */
data final;
    set final;

    if paramcd in ("C2NGNT50" "C2NGNT90") then
        islloq=20;
    else if paramcd in ("C19S1IGG") then
        islloq=1.2665;
    else if paramcd in ("C19RBDIG") then
        islloq=1.1505;
    else if paramcd in ("C19NIG") then
        islloq=.;

    if avalc not in ("" "IND" "QNS" "INDETERMINATE") then
        anl03fl='Y';

    if not missing(islloq) and aval >=islloq then
        anl04fl='Y';
run;

data final;
    length param $ 200 BSSEROC $ 50;
    set final;
    base4f=base;

    /* Impute BLQ values per SAP and create BSSEROC/BSSERON for param other than C19NIG */
    if paramcd not in ("C19NIG") then
        do;

            if (aval < islloq and aval ne .) or avalc in ('BLQ') then
                do;
                    aval=islloq*.5;
                    avalc=ifc(^missing(aval), strip(put(aval, best.)), "");
                end;

            if (base < islloq and base ne .) or basec in ('BLQ') then
                do;
                    base=islloq*.5;
                    base4f=islloq;
                    basec=ifc(^missing(base), strip(put(base, best.)), "");
                    BSSEROC="< LLOQ";
                    BSSERON=1;
                end;
            else
                do;
                    BSSEROC=">= LLOQ";
                    BSSERON=2;
                end;

            if avalc in ("QNS" "IND") then
                do;
                    avalc="";
                    aval=.;
                end;

            if chg ne . then
                chg=aval - base;

            if base >0 and ablfl ne 'Y' then
                r2base=(aval/base);

            if base4f >0 and ablfl ne 'Y' then
                r2base4f=(aval/base4f);
            dtype='LLOQIMP';

            if missing(base) then
                do;
                    BSSEROC="Missing";
                    BSSERON=0;
                end;

            if not missing(base) then
                basetype=trim(left(basetype))||' ('||trim(left(dtype))||')';
        end;

    /* Create aval for C19NIG */
    else
        do;

            if avalc in ("NEG" "neg") then
                aval=0;
            else if avalc in ("POS" "pos") then
                aval=1;

            if basec in ("NEG" "neg") then
                do;
                    base=0;
                    base4f=0;
                end;
            else if basec in ("POS" "pos") then
                do;
                    base=1;
                    base4f=1;
                end;
            dtype='';
        end;

    if r2base4f ge 4 then
        fold4fl="Y";
    label r2base='Ratio to Baseline' anl03fl='Analysis Flag 03:valid value' 
        anl04fl='Analysis Flag 04:ge LLoQ' BSSERON="Baseline serostatus (N)" 
        BSSEROC="Baseline serostatus" ISLLOQ="Lower Limit of Quantitation" 
        fold4fl="Achieve 4-Fold Rise Flag" base4f="Baseline Value for 4 Fold Rise" 
        r2base4f="Ratio to baseline for 4 Fold Rise";
run;

data final1;
    set final;

    if isuse ne "Y";
run;

proc sort data=final;
    where isuse="Y";
    by usubjid;
run;

proc sort data=final out=v3(keep=usubjid) nodupkey;
    where visitnum in (60754 60767) and isuse="Y";
    by usubjid;
run;

data final;
    merge final v3(in=a);
    by usubjid;
    v3=a;

    if v3=0 and (index(visit, "COVID") or visit in ('V101_VAX3' 
        'V201_SURVEIL_CONSENT')) then
            do;

            if 28<=adt-vax102dt<=42 then
                do;
                    avisitn=6;
                    avisit="1 Month after Vaccination 2";
                    ANL01FL="Y";
                end;
            else
                do;
                    avisitn=.;
                    avisit="";
                    ANL01FL="";
                end;
        end;
    else if v3=1 and (index(visit, "COVID") or visit in ('V101_VAX3' 
        'V201_SURVEIL_CONSENT')) then
            do;
            avisitn=.;
            avisit="";
            ANL01FL="";
        end;
run;

data final;
    set final;

    if avisitn>=4 and vax201dt ne . and adt>vax201dt then
        ANL01FL="";
run;

/* Generate GMR */
proc sort data=final out=gmr_pre;
    by usubjid visitnum adt;
run;

proc transpose data=gmr_pre out=gmr_pre_t;
    by usubjid visitnum adt;
    id paramcd;
    var aval;
run;

data gmr;
    set gmr_pre_t;

    if not missing(C2NGNT50) and not missing(C19S1IGG) then
        do;
            paramn=11;
            paramcd="NT50_S1";

            /*          param="SARS-CoV-2-mNG for serum antibody NT50 to COVID-19 S1 IgG"; */
            param="SARS-CoV-2 serum neutralizing titer 50 to COVID-19 S1 IgG";
            aval=round(C2NGNT50/C19S1IGG, 0.0001);
            output;
        end;

    if not missing(C2NGNT90) and not missing(C19S1IGG) then
        do;
            paramn=12;
            paramcd="NT90_S1";

            /*          param="SARS-CoV-2-mNG for serum antibody NT90 to COVID-19 S1 IgG"; */
            param="SARS-CoV-2 serum neutralizing titer 90 to COVID-19 S1 IgG";
            aval=round(C2NGNT90/C19S1IGG, 0.0001);
            output;
        end;

    if not missing(C2NGNT50) and not missing(C19RBDIG) then
        do;
            paramn=13;
            paramcd="NT50_RB";

            /*          param="SARS-CoV-2-mNG for serum antibody NT50 to COVID-19 RBD Ig"; */
            param="SARS-CoV-2 serum neutralizing titer 50 to COVID-19 RBD Ig";
            aval=round(C2NGNT50/C19RBDIG, 0.0001);
            output;
        end;

    if not missing(C2NGNT90) and not missing(C19RBDIG) then
        do;
            paramn=14;
            paramcd="NT90_RB";

            /*          param="SARS-CoV-2-mNG for serum antibody NT90 to COVID-19 RBD Ig"; */
            param="SARS-CoV-2 serum neutralizing titer 90 to COVID-19 RBD Ig";
            aval=round(C2NGNT90/C19RBDIG, 0.0001);
            output;
        end;
    keep usubjid visitnum adt paramn paramcd param aval;
run;

proc sort data=gmr;
    by usubjid visitnum adt;
run;

proc sort data=gmr_pre out=shell nodupkey;
    by usubjid visitnum adt;
run;

data gmr;
    merge shell(drop=paramn paramcd param aval) gmr(in=a);
    by usubjid visitnum adt;

    if a;
    dtype="Derived";
    avalc=strip(put(aval, best.));
    base=.;
    base4f=.;
    basec="";
    basetype="";
    r2base=.;
    r2base4f=.;
    fold4fl="";
    islloq=.;
    isstresc="";
    srcseq=.;
    anl03fl="";
    anl04fl="";
    SRCDOM="";
    SRCVAR="";
    BSSEROC="";
    BSSERON=.;
    ISTSTDTL="";
run;

/* Add BASE/R2BASE for GMR */
proc sort data=gmr;
    by subjid paramcd adt;
run;

data gmr;
    set gmr(drop=base base4f basec basetype r2base r2base4f ABLPBLFL);
    by subjid paramcd adt;
    retain base;

    if first.paramcd and ABLFL="Y" then
        base=aval;
    else if first.paramcd then
        base=.;
    else if base ne . then
        base+0;

    if not missing(base) then
        do;
            basec=strip(put(base, best.));
            basetype="Study (Derived)";
        end;

    if base >0 and ablfl ne 'Y' then
        r2base=(aval/base);
run;

data base;
    set gmr;
    where ABLFL="Y";

proc sort nodupkey;
    by subjid;
run;

data post;
    set gmr;
    where ABLFL^="Y";

proc sort nodupkey;
    by subjid;
run;

data both;
    merge base(in=a) post(in=b);
    by subjid;

    if a and b;
    ABLPBLFL="Y";
run;

data gmr;
    merge gmr(in=a) both(keep=subjid ABLPBLFL in=b);
    by subjid;

    if a;

    if not b then
        ABLPBLFL="N";
run;

data Nbind(drop=ABLPBLFL) final;
    set final gmr;

    if param="N-binding antibody - N-binding Antibody Assay" then
        output Nbind;
    else
        output final;
run;

data base;
    set Nbind;
    where ABLFL="Y";

proc sort nodupkey;
    by subjid;
run;

data post;
    set Nbind;
    where ABLFL^="Y";

proc sort nodupkey;
    by subjid;
run;

data both;
    merge base(in=a) post(in=b);
    by subjid;

    if a and b;
    ABLPBLFL="Y";
run;

data Nbind;
    merge Nbind(in=a) both(keep=subjid ABLPBLFL);
    by subjid;

    if a;

    if ABLPBLFL="" then
        ABLPBLFL="N";
run;

data final;
    set final Nbind final1;
run;

data final;
    set final;

    /* Re-create ADY per each vax date */
    if not missing(vax101dt) and adt>=vax101dt then
        ady=adt-vax101dt+1;

    if not missing(vax102dt) and adt>vax102dt then
        ady=adt-vax102dt+1;

    if missing(vax101dt) then
        ady=.;

    if cohortn=1.16 then
        do;

            if visitnum=60752 then
                do;
                    avisitn=3.1;
                    avisit="4 Weeks after Vaccination 1";
                    anl01fl="Y";
                end;
            else if visitnum=60753 then
                do;
                    avisitn=3.2;
                    avisit="5 Weeks after Vaccination 1";
                    anl01fl="Y";
                end;
            else if visitnum=60754 then
                do;
                    avisitn=3.3;
                    avisit="1 Month and 3 weeks after Vaccination 1";
                    anl01fl="Y";
                end;
            else if visitnum=1165454 then
                do;
                    avisitn=3.9;
                    avisit="Before Vaccination 2";
                    anl01fl="Y";
                end;
        end;

    /* Create all-available and evaluable flags */
    if phasen in (1) then
        do;

            if avisitn<4 then
                do;

                    if eval01fl="Y" then
                        EVIMMFL="Y";
                    else
                        EVIMMFL="N";

                    if aai01fl="Y" then
                        AAIMMFL="Y";
                    else
                        AAIMMFL="N";
                end;
            else if avisitn>=4 then
                do;

                    if eval02fl="Y" then
                        EVIMMFL="Y";
                    else
                        EVIMMFL="N";

                    if aai02fl="Y" then
                        AAIMMFL="Y";
                    else
                        AAIMMFL="N";
                end;
        end;

    if phasen in (2 3 4) then
        do;

            if eval02fl="Y" then
                EVIMMFL="Y";
            else
                EVIMMFL="N";

            if aai02fl="Y" then
                AAIMMFL="Y";
            else
                AAIMMFL="N";
        end;

    if not missing(PD1POSDT) and adt ge PD1POSDT then
        EVIMMFL="N";
    label EVIMMFL="Evaluable Immunogenicity Record Flag" 
        AAIMMFL="All-available Immunogenicity Record Flag";
run;

proc sort data=final out=base(keep=usubjid paramcd) nodupkey;
    where ablfl="Y";
    by usubjid paramcd;
run;

proc sort data=final out=post(keep=usubjid paramcd) nodupkey;
    where Apsblfl="Y";
    by usubjid paramcd;
run;

data bp(keep=usubjid paramcd);
    merge base(in=a) post(in=b);
    by usubjid paramcd;

    if a and b;
run;

proc sort data=final;
    by usubjid paramcd;
run;

data final;
    merge final(in=a) bp(in=b);
    by usubjid paramcd;

    if a;
    Ablpblfl="N";

    if b then
        Ablpblfl="Y";
run;

data final;
    set final;

    if paramn not in (13, 14);
    isdtc=strip(scan(isdtc, 1, "T"));

    if paramcd="C19NIG" then
        do;
            avisitn=.;
            avisit="";
            anl01fl=" ";
        end;

    if isuse="N" then
        do;
            avisitn=.;
            avisit="";
            anl01fl=" ";
        end;
run;

proc sort data=final;
    by usubjid param aperiod AVISITN ADT visitnum DTYPE;
run;

data final_reset;
    set final;

    if ^missing(DTYPE) and upcase(dtype) not in ('LLOQIMP', 'DERIVED') then
        do;

            if (^missing(DTYPE) and upcase(dtype) not in ('LLOQIMP', 'DERIVED') ) then
                ADT=.;
            ATM=.;
            ADTM=.;
            ATMF=" ";

            if (^missing(DTYPE) and upcase(dtype) not in ('LLOQIMP', 'DERIVED') ) then
                ADY=.;
            SRCSEQ=.;

            if (^missing(DTYPE) and upcase(dtype) not in ('LLOQIMP', 'DERIVED') ) then
                APERDY=.;
        end;
run;

/* Output ADVA */
data datvprot.adva (label="Immunogenicity Analysis Dataset");
    retain STUDYID USUBJID SUBJID SITEID TRTP TRTPN TRTA TRTAN ISDTC ADT ADY 
        AVISIT AVISITN VISIT VISITNUM PARCAT1 PARCAT1N PARAM PARAMN PARAMCD AVAL 
        AVALC BASE BASEC BASETYPE ABLFL APSBLFL ABLPBLFL DTYPE R2BASE SRCDOM SRCVAR 
        SRCSEQ ANL01FL ANL03FL ANL04FL SRCVAR SRCDOM SRCSEQ ISLLOQ ISSTRESC EVIMMFL 
        AAIMMFL BSSERON BSSEROC APERIOD APERIODC APERSDTM APEREDTM BASE4F R2BASE4F 
        FOLD4FL ISTSTDTL USUBJID SUBJID SITEID AGE AGEU SEX SEXN RACE RACEN RANDFL 
        SAFFL ARM ARMCD ACTARM ACTARMCD TRTSDT TRTEDT TRTSTM TRTETM TRT01A TRT01AN 
        TRT02A TRT02AN TRT01P TRT01PN TRT02P TRT02PN TR01SDT TR01STM TR01SDTM TR01EDT 
        TR01ETM TR01EDTM TR02SDT TR02STM TR02SDTM TR02EDT TR02ETM TR02EDTM COHORTN 
        COHORT VAX101DT VAX102DT VAX10UDT VAX201DT VAX202DT SAFFL AAI01FL EVAL02FL 
        AAI02FL EVAL01FL DOSALVL DOSALVLN DOSPLVL DOSPLVLN AGEGR1 AGEGR1N AGEGR2 
        AGEGR2N AGEGR4 AGEGR4N PHASE PHASEN COVBLST HIVFL PEDIMMFL EV1MD2FL AGETR01 
        VAX101 VAX102 VAX10U VAX201 VAX202 VAX20U VAX20UDT UNBLNDDT MULENRFL RAND1FL 
        TRTSDTM TRTEDTM;
    set final_reset;
    keep STUDYID USUBJID SUBJID SITEID TRTP TRTPN TRTA TRTAN ISDTC ADT ADY AVISIT 
        AVISITN VISIT VISITNUM PARCAT1 PARCAT1N PARAM PARAMN PARAMCD AVAL AVALC BASE 
        BASEC BASETYPE ABLFL APSBLFL ABLPBLFL DTYPE R2BASE SRCDOM SRCVAR SRCSEQ 
        ANL01FL ANL03FL ANL04FL SRCVAR SRCDOM SRCSEQ ISLLOQ ISSTRESC EVIMMFL AAIMMFL 
        BSSERON BSSEROC APERIOD APERIODC APERSDTM APEREDTM BASE4F R2BASE4F FOLD4FL 
        ISTSTDTL USUBJID SUBJID SITEID AGE AGEU SEX SEXN RACE RACEN RANDFL SAFFL ARM 
        ARMCD ACTARM ACTARMCD TRTSDT TRTEDT TRTSTM TRTETM TRT01A TRT01AN TRT02A 
        TRT02AN TRT01P TRT01PN TRT02P TRT02PN TR01SDT TR01STM TR01SDTM TR01EDT 
        TR01ETM TR01EDTM TR02SDT TR02STM TR02SDTM TR02EDT TR02ETM TR02EDTM COHORTN 
        COHORT VAX101DT VAX102DT VAX10UDT VAX201DT VAX202DT SAFFL AAI01FL EVAL02FL 
        AAI02FL EVAL01FL DOSALVL DOSALVLN DOSPLVL DOSPLVLN AGEGR1 AGEGR1N AGEGR2 
        AGEGR2N AGEGR4 AGEGR4N PHASE PHASEN COVBLST HIVFL PEDIMMFL EV1MD2FL AGETR01 
        VAX101 VAX102 VAX10U VAX201 VAX202 VAX20U VAX20UDT UNBLNDDT MULENRFL RAND1FL 
        TRTSDTM TRTEDTM;

    if ^missing(dtype) and (WINDERFL='Y' or BASDERFL='Y') then
        do;

            if ^missing(avaldec) then
                do;
                    AVAL=round(AVAL, (0.1)**AVALDEC);
                    AVALC=strip(put(AVAL, best.));
                end;
        end;
    label ADY="Analysis Relative Day" AVAL="Analysis Value" 
        AVALC="Analysis Value (C)" DTYPE="Derivation Type" PARAM="Parameter" 
        PARAMCD="Parameter Code" PARAMN="Parameter (N)" 
        PARCAT1="Parameter Category 1" PARCAT1N="Parameter Category 1 (N)" 
        SRCVAR="Source Variable" SRCDOM="Source Data" SRCSEQ="Source Sequence Number";
run;

proc printto;
run;
