*************************************************************************************************** * PROGRAM OVERVIEW **************************************************************************************************** * * PROGRAM: ms_cidanum.sas * * Created (mm/dd/yyyy): 12/19/2014 * Last modified: 02/27/2018 * Version: 2.7 * *-------------------------------------------------------------------------------------------------- * PURPOSE: * This macro will compute the numerators and call many other macros creating the denominators * and the output tables. * * Program inputs: * -infolder.&COHORTFILE. * -infolder.&TYPE1FILE. * -infolder.&TYPE2FILE. * -infolder.&TYPE3FILE. * -infolder.&TYPE4FILE. * -infolder.&TYPE5FILE. * -infolder.&comorbfile. * -infolder.&T3METADATA. * -infolder.&STOCKPILINGFILE. * -infolder.&MFUFILE. * -infolder.&INCLUSIONCODES. * -infolder.&PREGCODES. * -infolder.&COVARIATECODES. * * Program outputs: * -DPLocal.&RUNID._mstr * * PARAMETERS: * -RUNID = Run identifier to denote each execution of the program * -MSPROJID = MSOC-defined value * -MSWPTYPE = MSOC-defined value * -MSWPID = MSOC-defined value * -MSDPID = MSOC-defined value * -MSVERID = MSOC-defined value * -PERIODIDSTART = Starting PERIODID from the MONITORINGFILE * -PERIODIDEND = Ending PERIODID from the MONITORINGFILE * -ANALYSIS = Type of Analysis to perform in ms_cidacov * -MONITORNGFILE = Name of the SAS dataset that defines the relevant query periods for execution * -COHORTFILE = Name of the SAS dataset that defines how the cohort should be created (gaps, coverage,...) * -TYPE1FILE = Name of the SAS dataset that defines type 1 cohort parameters (washouts, cohortdef, ...) * -TYPE2FILE = Name of the SAS dataset that defines type 2 cohort parameters (washouts, cohortdef, ...) * -TYPE3FILE = Name of the SAS dataset that defines type 3 cohort parameters (washouts, cohortdef, ...) * -TYPE4FILE = Name of the SAS dataset that defines type 4 cohort parameters (washouts, cohortdef, ...) * -TYPE5FILE = Name of the SAS dataset that defines type 5 cohort parameters (washouts, cohortdef, ...) * -T3METADATA = Name of the SAS dataset that defines the metadata generated for each time period request * -COHORTCODES = Name of the SAS dataset that includes the codes defining the cohort * -INCLUSIONCODES = Name of the SAS dataset that includes the codes defining inclusions/exclusions * -COVARIATECODES = Name of the SAS dataset that includes the codes associated with covariates used to determine the propensity score * -PROFILE = Indicates if a covariate profile file should be produced * -MFUFILE = Name of the SAS dataset that defines how MFU analysis should be performed * -STOCKPILINGFILE= Name of the SAS dataset that defines how the stockpiling algorithm should be performed * -UTILFILE = Name of the SAS dataset that defines how ms_util should be performed * -COMBOFILE = Name of the SAS dataset that will be used to create combination items. When this parameter is specified, "CODES" and "STOCK" input files are also required. * -COMORBFILE = Name of the SAS dataset that defines how ms_cci_elix should be performed * -DRUGCLASSFILE = Name of the SAS dataset that lists NDCs by generic and class names and allows the program to count the number of distinct generic names and class names for input into the PS match model * -FREEZEDATA = Indicates if MSDD patient data shoul be copied to DPLocal * -LABSCODEMAP = Name of the SAS dataset that contains laboratory matching information * -SURVEILLANCEMODE = Indicates if the module should be executed in suveilance mode and wich type * -PREGCODES = Name of the SAS dataset that contains pre/post term delivery codes for type 4 analysis * -ZIPFILE = Name of the SAS dataset that contains list of valid Zip/Zip State values * -RUN_ENVELOPE = Indicates if the envelope macro should include Adate or be turned off entirely * Programming Notes: * * * *-------------------------------------------------------------------------------------------------- * CONTACT INFO: * Mini-Sentinel Coordinating Center * info@mini-sentinel.org * *-------------------------------------------------------------------------------------------------- * CHANGE LOG: * * Version Date Initials Comment (reference external documentation when available) * ------- -------- -------- --------------------------------------------------------------- * 1.4 01/22/14 DM Minor bug fix. Added de-duped sort to _agegroups dataset * * 1.5 02/06/15 SL(EM) Removed MSREQID definition line * * 1.6 02/23/15 DM Removed Enr_Start and Enr_end when shaving ITDrugsComb to * avoid a w.a.r.n.i.n.g. in the log and incorrect results in outputs * Modified how the required follow-up time after exposure is * calculated * * 1.7 03/11_15 DM Renamed Episodes_analysis to Pt_Analysis_Episode_Num * Renamed Episodes_exposure to Pt_Exposure_Episode_Num * Process _ITDrugs, _ITMeds and _ITLabs with ms_shaveoutside * even when they are empty * * 1.8 03/26/15 DM Changed the method to verify MSDD file existence before calling * the FREEZEDATA macro * * 1.9 04/13/15 DM Changed the stockpiling input file parameters processing * * 1.10 06/26/15 DM Verify that patients have at least one day at risk in the look * of their index date (analysis = PS or ADS). * Removed Surveillance Analysis related code. * * 1.11 09/14/15 DM Added code for Type 4 analysis. * * 1.12 03/10/16 VC Enhance Inclusions and Covariates to allow more complex criteria. * * 1.13 04/21/16 DM Carried forward changes made in 2.2.1 version (incidence at day 0) * * 1.14 05/26/16 VC JIRA 173 * * 1.15 06/14/16 DM Fix for RxAmt and RxAmt in Type 1 plus hybrid AT/ITT * * 1.16 07/05/16 DM Added time to censor data plus fix for JIRA #DEVI-14 * * 1.17 08/10/16 AP Modified to remove true duplicates in SDD (QCI-195) * DM Fixed same day claims issue in type 1 analysis (QCI-208) * * 1.18 08/15/16 DM Added Surveillance Analysis related code removed in 1.10. * * 1.19 10/17/16 DM Fixed an issue regarding Eventcount (QCI-219) and replaced an * append statement with a set one (QCI-210) * * 1.20 11/14/16 AP Added ability to stratify T1/T2 output by geographic location * Added ability to turn off envelope macro * * 1.21 11/30/16 AP Added ability to truncate TTE at Query period end date and also to * enumerate reasons for censoring * * 1.22 02/09/16 AP Fixed bug (QRP-301) in TTE calculation when censor_dth = N * * 2.0 03/30/17 DM Reorganization of the code to modularize the POVs creation * * 2.1 05/05/17 AP 1. Extracted hispanic info * 2. Removed AgeStrat as a run-level parameter and converted to * group level parameter * 3. Moved ms_cidatables, ms_cidatablest3, ms_cidatablest4 into group loop * * 2.2 07/12/17 RR Removed (drop = expireDt) from DoITTCheck * * 2.3 06/26/17 AP 1. Added Type 5 Analysis * 2. Integrated MP7 and added new index date definitions * * 2.4 09/14/17 AP Bug fix (QRP-437) * * 2.5 10/03/17 AP -Changed PRECODES to PREGDUR (QRP-388) * -Recoded sex values A/U (QRP-453) * * 2.6 12/28/17 AP Moved censor table to ms_createcensortable (QRP-462) * * 2.7 02/27/18 RR Changes related to the never exposed group (QRP-495) ***************************************************************************************************; %macro ms_cidanum(RUNID, MSPROJID, MSWPTYPE, MSWPID, MSDPID, MSVERID, PERIODIDSTART, PERIODIDEND, ANALYSIS, MONITORINGFILE, COHORTFILE, TYPE1FILE, TYPE2FILE, TYPE3FILE, TYPE4FILE, TYPE5FILE, T3METADATA, COHORTCODES, INCLUSIONCODES, COVARIATECODES, PROFILE, MFUFILE, STOCKPILINGFILE, UTILFILE, COMBOFILE, COMORBFILE, DRUGCLASSFILE, FREEZEDATA, LABSCODEMAP, SURVEILLANCEMODE, PREGDUR, ZIPFILE, RUN_ENVELOPE ); %PUT "ms_cidanum"; %put =====> MACRO CALLED: ms_cidanum v2.7; %ms_starttimer(START=MAINSTART); /*---------------------------------------------------*/ /* 01 -- Set up variables needed for the run */ /*---------------------------------------------------*/ %LET MSPROJID=%LOWCASE(&MSPROJID.); %LET MSWPTYPE=%LOWCASE(&MSWPTYPE.); %LET MSWPID=%LOWCASE(&MSWPID.); %LET MSDPID=%LOWCASE(&MSDPID.); %LET MSVERID=%LOWCASE(&MSVERID.); %LET PERIODIDSTART=%LOWCASE(&PERIODIDSTART.); %LET PERIODIDEND=%LOWCASE(&PERIODIDEND.); %LET ANALYSIS=%LOWCASE(&ANALYSIS.); %LET SURVEILLANCEMODE=%LOWCASE(&SURVEILLANCEMODE.); %let PROFILE=%LOWCASE(&PROFILE.); %LET MONITORINGFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&MONITORINGFILE.), .sas7bdat, %STR()))); %LET COHORTFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&COHORTFILE.), .sas7bdat, %STR()))); %LET TYPE1FILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&TYPE1FILE.), .sas7bdat, %STR()))); %LET TYPE2FILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&TYPE2FILE.), .sas7bdat, %STR()))); %LET TYPE3FILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&TYPE3FILE.), .sas7bdat, %STR()))); %LET TYPE4FILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&TYPE4FILE.), .sas7bdat, %STR()))); %LET TYPE5FILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&TYPE5FILE.), .sas7bdat, %STR()))); %LET COHORTCODES=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&COHORTCODES.), .sas7bdat, %STR()))); %LET INCLUSIONCODES=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&INCLUSIONCODES.), .sas7bdat, %STR()))); %LET COVARIATECODES=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&COVARIATECODES.), .sas7bdat, %STR()))); %LET MFUFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&MFUFILE.), .sas7bdat, %STR()))); %LET STOCKPILINGFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&STOCKPILINGFILE.), .sas7bdat, %STR()))); %LET UTILFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&UTILFILE.), .sas7bdat, %STR()))); %LET COMORBFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&COMORBFILE.), .sas7bdat, %STR()))); %LET DRUGCLASSFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&DRUGCLASSFILE.), .sas7bdat, %STR()))); %LET COMBOFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&COMBOFILE.), .sas7bdat, %STR()))); %LET FREEZEDATA=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&FREEZEDATA.), .sas7bdat, %STR()))); %LET PREGDUR=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&PREGDUR.), .sas7bdat, %STR()))); %LET ZIPFILE=%TRIM(%SYSFUNC(TranWrd(%LOWCASE(&ZIPFILE.), .sas7bdat, %STR()))); /*---------------------------------------------------*/ /* 02 -- Import input files in SAS format */ /*---------------------------------------------------*/ %IMPORTFILES(var=&MONITORINGFILE.); %IMPORTFILES(var=&COHORTFILE.); %IMPORTFILES(var=&TYPE1FILE.); %IMPORTFILES(var=&TYPE2FILE.); %IMPORTFILES(var=&TYPE3FILE.); %IMPORTFILES(var=&TYPE4FILE.); %IMPORTFILES(var=&TYPE5FILE.); %IMPORTFILES(var=&COHORTCODES.); %IMPORTFILES(var=&INCLUSIONCODES.); %IMPORTFILES(var=&COVARIATECODES.); %IMPORTFILES(var=&MFUFILE.); %IMPORTFILES(var=&STOCKPILINGFILE.); %IMPORTFILES(var=&UTILFILE.); %IMPORTFILES(var=&COMORBFILE.); %IMPORTFILES(var=&DRUGCLASSFILE.); %IMPORTFILES(var=&COMBOFILE.); %IMPORTFILES(var=&DRUGCLASSFILE.); %IMPORTFILES(var=&LABSCODEMAP.); %IMPORTFILES(var=&PTSTOEXCLUDE.); %IMPORTFILES(var=&PREGDUR.); %IMPORTFILES(var=&ZIPFILE.); /*---------------------------------------------------*/ /* 03 -- Initialize macro variables and */ /* Process input file parameters */ /*---------------------------------------------------*/ *Initialize macro variables; %ms_initmacrovariables(); *Process input files; %MS_ProcessInputFiles(); /*---------------------------------------------------*/ /* 04 -- Process Ranges "-" and Wilcards "*" */ /* in lookup codes */ /*---------------------------------------------------*/ %ISDATA(dataset=_diag); %IF %EVAL(&NOBS.>=1) %THEN %DO; %MS_ProcessWildcards(InFile=_diag, CodeVar=code, OutFile=_diag); %END; /*---------------------------------------------------*/ /* 05 -- Extract Raw Data and run envelope or */ /* Create combo records (if applicable) */ /*---------------------------------------------------*/ %if %str(&COMBOFILE.) = %str() or %length(&COMBOFILE.) = 0. %then %do; *Programming note: We are not using caresettingprincipal in the pre-extraction phase because typical sensitivity analysis around caresettingprincipal could lead to massive claim duplication; %ms_extractmeds(datafile=indata.&proctable., datacode=PX , datacodetype=PX_codetype , lookfile=_proc, outfile=_procextract(drop=EncounterID Provider)); proc sort data=_procextract nodupkey; by _all_; run; *Delete data from patients in DPs &PTSTOEXCLUDE. files; %ms_delpatients(datafile=_procextract, ptsfile=&PTSTOEXCLUDE., Outfile=_procextract); %ms_extractmeds(datafile=indata.&diatable., datacode=DX, datacodetype=DX_codetype, lookfile=_diag, outfile=_diagextract(drop=EncounterID Provider)); proc sort data=_diagextract nodupkey; by _all_; run; *Delete data from patients in DPs &PTSTOEXCLUDE. files; %ms_delpatients(datafile=_diagextract, ptsfile=&PTSTOEXCLUDE., Outfile=_diagextract); *Codes must be unique to avoid claim duplication.; proc sort nodupkey data=_ndc; by code; run; %ms_extractdrugs(datafile=indata.&distable., datavar=NDC , lookfile=_ndc(drop=codecat CodeType), lookvar=code , outfile=Drugs); proc sort data=Drugs nodupkey; by _all_; run; *Delete data from patients in DPs &PTSTOEXCLUDE. files; %ms_delpatients(datafile=Drugs, ptsfile=&PTSTOEXCLUDE., Outfile=Drugs); %ms_extractlabs(datafile=indata.&labtable., lookfile=_lab, outfile=labextract); proc sort data=labextract nodupkey; by _all_; run; *Delete data for patients in DPs &PTSTOEXCLUDE. files; %ms_delpatients(datafile=labextract, ptsfile=&PTSTOEXCLUDE., Outfile=labextract); %end; %else %do; *Combo is called using a macro wrapper to preserve the scoping of macro call combo variables (specifically STOCKPILINGFILE); %MACRO RUNCOMBO; %let COMBORUN=1; %if %EVAL(&RUN_ENVELOPE. = 2) %then %do; %let DXENVEL = 0; %let PXENVEL = 0; %end; %else %do; %let DXENVEL = 1; %let PXENVEL = 1; %end; %combo(COMBFILE=&COMBOFILE., CODESFILE=&COMBOFILE.Codes, DXENVEL=1&DXENVEL., PXENVEL=1&PXENVEL., OUTNAME=&RUNID._Combo, STOCKPILING=1, STOCKPILINGFILE=&COMBOFILE.Stock, ENROLGAP=0, LABSCODEMAP=&LABSCODEMAP., SAVETODPLOCAL=N, PTSTOEXCLUDE=&PTSTOEXCLUDE.); *Combo creates _Drugs, but we need Drugs to continue; proc datasets library=work nowarn nolist; change _drugs=drugs; quit; %MEND RUNCOMBO; %RUNCOMBO; %end; * Deaths are not processed by combo tool. Therefore they must be extracted no matter if combo is run; %ms_extractdeaths(deathfile=indata.&DEATHTABLE., encounterfile=indata.&enctable., outfile=deathextract); * Delete data for patients in DPs &PTSTOEXCLUDE. files; %ms_delpatients(datafile=deathextract, ptsfile=&PTSTOEXCLUDE., Outfile=deathextract); *Combine _diags and _procs for envelope later; proc sql noprint; create table meds as select proc.PatId, proc.Adate, compress(proc.PX,' .')as Code, " " as Pdx, proc.EncType, PX_Codetype as Codetype, "PX" as CodeCat, 1 as RxSup, 1 as RxAmt from _procextract as proc union corr all select diag.PatId, diag.Adate, compress(diag.DX,' .') as Code, diag.EncType, diag.Pdx, diag.DX_Codetype as Codetype, "DX" as CodeCat, 1 as RxSup, 1 as RxAmt from _diagextract as diag; quit; *To avoid w.a.r.n.i.n.g.s. down the line; data meds; set meds; length Adate 4.; run; *If meds records not out of combo, run envellope; %ISDATA(dataset=meds); %if (%str(&COMBOFILE.) = %str() or %length(&COMBOFILE.) = 0.) & %EVAL(&NOBS.>=1) & %EVAL(&RUN_ENVELOPE. ne 2) %then %do; %MS_ENVELOPE(INFILE=meds, /*Name of SAS dataset with diagnosis and/or procedure claims data*/ ENCOUNTERINFILE=indata.&ENCTABLE., /*Name of SAS dataset with encounter data*/ OUTFILE=meds); /*Name of output file with reclassified claims*/ %end; *Separate raw un-stockpiled RX claims from combo claims set to behave like Rx; data Drugs DrugsComb; set Drugs; if RxSup>0 and RxAMt>0; if comb then output DrugsComb; else output Drugs; run; proc datasets library=work nowarn nolist; delete _:; quit; /*---------------------------------------------------*/ /* 06 -- Loop through Group(s) */ /*---------------------------------------------------*/ %macro forloop; %do Group=1 %to &Ngroup.; /*---------------------------------------------------*/ /* 06.a -- Loop pre-processing */ /*---------------------------------------------------*/ *Set current Group macro parameters; %ms_setnumloopmacrovars(); %PUT INFO: NOW LOOPING ON &ITGROUP.; *Get specific codes for this loop and separate diags from others to process wildcards; data _diag _others; set &COHORTCODES.; where group="&ITGROUP."; if CodeCat in("DX") then output _diag ; else output _others; run; %ISDATA(dataset=_diag); %IF %EVAL(&NOBS.>=1) %THEN %DO; %MS_ProcessWildcards(InFile=_diag, CodeVar=code, OutFile=_diag); %END; *Create Loop-specific parameter files; data _ITGroupParamNDC _ITGroupParamMeds _ITGroupParamLabs(rename=Group=RawGroup rename=CareSettingprincipal=RawCaresetting) _ITGroupParamDate; set _diag _others; if Condinclusion=. then Condinclusion=1; if SubCondinclusion=. then SubCondinclusion=1; if Cond=. then Cond=-1; if SubCond=. then SubCond=-1; if codedays = . then codedays = 1; if CodeCat="RX" then output _ITGroupParamNDC; if CodeCat in("DX","PX") then output _ITGroupParamMeds; if CodeCat in("LB") then output _ITGroupParamLabs; if CodeCat in("AN","DT") then output _ITGroupParamDate; run; *Indicator if group Index determined by Age Anniversary or Calendar Date; %let agedatecohort = N; %isdata(dataset=_ITGroupParamDate); %if %eval(&nobs.) > 0 %then %do; %let agedatecohort = Y; %end; *Break out CaresettingPrincipal into Caresetting and Principal; %ms_caresettingprincipal(InFile=_ITGroupParamMeds, Var=CareSettingPrincipal, OutFile=_ITGroupParamMeds); /*---------------------------------------------------*/ /* 06.b -- Extract loop-specific records */ /*---------------------------------------------------*/ *Extract Records necessary for creating this group only (record duplic OK + add loop parameters back to records); %ms_loopmeds(datafile=meds, lookfile=_ITGroupParamMeds, outfile=_ITMeds); %ms_extractdrugs(datafile=Drugs, datavar=NDC , lookfile=_ITGroupParamNDC, lookvar=code , outfile=_ITDrugs); *Need to define Supply End Date to make sure days of supply are constrained within enrollment; data _ITDrugs; set _ITDrugs; format RxSupEndDt date9.; RxSupEndDt=Rxdate+RxSup-1; run; %ms_extractdrugs(datafile=DrugsComb, datavar=NDC , lookfile=_ITGroupParamNDC, lookvar=code , outfile=_ITDrugsComb); *Need to define Supply End Date to make sure days of supply are constrained within enrollment; data _ITDrugsComb; set _ITDrugsComb; format RxSupEndDt date9.; RxSupEndDt=Rxdate+RxSup-1; run; %ms_extractlabs(datafile=labextract, lookfile=_ITGroupParamLabs, outfile=_ITlabs); /*---------------------------------------------------*/ /* 06.c -- Create enrollment dataset for required */ /* coverage/charts (if not already created) */ /*---------------------------------------------------*/ %MS_EPISODEREC2(INFILE=indata.&ENRTABLE., /*SAS dataset containing the raw enrollment data*/ OUTFILE=ENR_&RECONTYP.&ENROLGAP., /*SAS output dataset containing the conciliated enrollment periods*/ COVERAGE=&COVERAGE., /*Drug/Medical coverage indicator*/ CHARTRES=&CHARTRES., /*Chart availability indicator*/ ENRSTART=Enr_Start, /*Name of enrollment episode start date variable in INFILE*/ ENREND=Enr_End, /*Name of enrollment episode end date variable in INFILE*/ ENROLGAP=&ENROLGAP., /*Maximum allowable enrollment episode gap*/ REMOVEDUP=Yes); /*Indicates the removal of duplicates from the output file*/ *Restrict to desired population according to demographic criteria in COHORTFILE; proc sql noprint undo_policy=none; create table ENR_&RECONTYP.&ENROLGAP. as select Enr.*, Dem.BIRTH_DATE, Dem.Sex, Dem.Race, Dem.Hispanic, Dem.zip, Dem.zip_date from ENR_&RECONTYP.&ENROLGAP. as Enr, indata.&DEMTABLE. as Dem where Enr.patid=Dem.patid and upcase(Dem.sex) in (&DemogSex.) and upcase(Dem.Race) in (&DemogRace.) and upcase(Dem.Hispanic) in (&DemogHispanic.) order by PatID, Enr_Start, Enr_End; quit; * Delete data for patients in DPs &PTSTOEXCLUDE. file; %ms_delpatients(datafile=ENR_&RECONTYP.&ENROLGAP., ptsfile=&PTSTOEXCLUDE., Outfile=ENR_&RECONTYP.&ENROLGAP.); data ENR_&GROUP.; merge ENR_&RECONTYP.&ENROLGAP.(in=a) DeathExtract(in=b); *Already sorted by PatID; by PatId; if a; enr_end_equal_death = 0; if &censor_dth.=1 then do; if b and DeathDt <= Enr_End then do; EnrEpisodeCensoredAtDeath=1; if enr_end = deathdt then enr_end_equal_death = 1; /*For censoring table*/ if Enr_end < Enr_Start then delete; end; end; %if %eval(&type. = 3) %then %do; if EnrEpisodeCensoredAtDeath=1 then Enr_End=DeathDt; /*Adjust for Type 3, keep for Type 2 and adjust later*/ if &T3ENDOFUPDATE. < Enr_End then Enr_End=&T3ENDOFUPDATE.; if Enr_end < Enr_Start then delete; %end; *recode A/U sex values; if sex in ('A', 'U') then sex = 'O'; run; *Make sure all claims overlap enrollment span and only keep eligible exposures (overlaping Enr_Start Enr_End); %ms_shaveoutside(reffile=ENR_&GROUP., refstart=Enr_Start, refend=Enr_End, KeepPartBf=N, ToShaveFile=_ITDrugs, ToShaveStart=RxDate, ToShaveEnd=RxSupEndDt, outfile=_ITDrugs); %ISDATA(dataset=_ITDrugsComb); %IF %EVAL(&NOBS.>=1) %THEN %DO; %ms_shaveoutside(reffile=ENR_&GROUP., refstart=Enr_Start, refend=Enr_End, KeepPartBf=N, ToShaveFile=_ITDrugsComb, ToShaveStart=RxDate, ToShaveEnd=RxSupEndDt, outfile=_ITDrugsComb(drop=Enr_Start Enr_end)); %END; %ms_shaveoutside(reffile=ENR_&GROUP., refstart=Enr_Start, refend=Enr_End, KeepPartBf=N, ToShaveFile=_ITMeds, ToShaveStart=ADate, ToShaveEnd=ADate, outfile=_ITMeds); %ms_shaveoutside(reffile=ENR_&GROUP., refstart=Enr_Start, refend=Enr_End, KeepPartBf=N, ToShaveFile=_ITLabs, ToShaveStart=ADate, ToShaveEnd=ADate, outfile=_ITLabs); %if %str(&ExclOnSameDay.)=%str(Y) %then %do; *Identify SameDayDispensings for different NDCs but from the same group; proc sort nodupkey data=_ITDrugs out=_SameDayNDCs(keep=Patid rxdate ndc); by Patid rxdate ndc; WHERE T&type._INDEX="DEF"; run; proc means data=_SameDayNDCs nway noprint; class Patid rxdate; output out=_SameDayNDCs(where=(_freq_>1)); run; %end; /*--------------------------------------------------------------*/ /* 06.d -- Create claims dataset based on age or calendar date */ /*--------------------------------------------------------------*/ %ms_extractanniversarydate(datafile = enr_&group., lookfile = _ITGroupParamDate, lookvar = code, outfile = _itdates); /*---------------------------------------------------*/ /* 06.e -- Apply StockPiling */ /*---------------------------------------------------*/ %ISDATA(dataset=infolder.&STOCKPILINGFILE.); %IF %EVAL(&NOBS.>0) %THEN %DO; data &STOCKPILINGFILE.; set infolder.&STOCKPILINGFILE.; where group="&ITGROUP."; call symputx("SAMEDAY",strip(SameDay)); call symputx("SUPRANGE",strip(SupRange)); call symputx("AMTRANGE",strip(AmtRange)); call symputx("PERCENTDAYS",put(PercentDays,best.)); run; %end; %MS_STOCKPILING(INFILE=_ITDrugs, CLMDATE=RxDate, CLMSUP=RxSup, CLMAMT=RxAmt, PROCFLAG=, PERCENTDAYS=&PERCENTDAYS., GROUPING=Group StockGroup T1_INDEX T2_INDEX T2_FUP T3_INDEX T3_FUP T4_INDEX T4_FUP T5_INDEX &InclExclVars., SAMEDAY=&SAMEDAY., SUPRANGE=&SUPRANGE., AMTRANGE=&AMTRANGE., ID=CODECAT, OUTFILE=_ITDrugs, OUTFILEEXCL=_ITDrugsExcl ); data _ITDrugs; set _ITDrugs _ITDrugsComb(in=a); *ExpireDt does not exist in _ITDrugsComb; if a then ExpireDt=Rxdate+RxSup-1; run; *Need to reshave because Stockpiling may have pushed claims outside enrollment period; %ISDATA(dataset=_ITDrugs); %IF %EVAL(&NOBS.>=1) %THEN %DO; %ms_shaveoutside(reffile=ENR_&GROUP., refstart=Enr_Start, refend=Enr_End, KeepPartBf=N, ToShaveFile=_ITDrugs, ToShaveStart=RxDate, ToShaveEnd=ExpireDt, outfile=_ITDrugs); %END; proc datasets library=work nowarn nolist; delete _ITGroupParam: _diag _others; quit; *Process same day diag, proc and labs for TYPE1 analysis; %if %eval(&type. eq 1) %then %do; %macro ProcessT1SameDayClaims(infile=); proc means data=_IT&infile. nway noprint; class PatId ADate T1_Index Cond SubCond; output out=_IT&infile.Freq(rename=_freq_=NumDispensing drop=_Type_) N=; run; proc sort data=_IT&infile.; by PatId ADate T1_Index Cond SubCond; run; data _IT&infile.; merge _IT&infile.(drop=RxSup RxAmt) _IT&infile.Freq(keep=PatId ADate T1_Index Cond SubCond NumDispensing); by PatId ADate T1_Index Cond SubCond; RxSup=1; RxAmt=1; Expiredt=Adate; run; proc sort nodupkey data=_IT&infile.; by PatId ADate T1_Index Cond SubCond; run; %mend ProcessT1SameDayClaims; %ISDATA(dataset=_ITMeds); %IF %EVAL(&NOBS.>=1) %THEN %DO; %ProcessT1SameDayClaims(infile=Meds); %END; %ISDATA(dataset=_ITLabs); %IF %EVAL(&NOBS.>=1) %THEN %DO; %ProcessT1SameDayClaims(infile=Labs); %END; %end; * TYPE1 same day claims; /*---------------------------------------------------*/ /* 06.f -- Create raw POVs datasets */ /*---------------------------------------------------*/ data _GroupIndex(keep=PatId Adate ExpireDt RXsup RXAmt NumDispensing Enr_Start Enr_end) /* POV1: Primary cohort Group Index Date (GroupIndex) */ %if %eval(&type. eq 4) %then %do; %do n=1 %to &NUM_MPN.; _GroupIndex&n.(keep=PatId Adate ExpireDt RXsup RXAmt Enr_Start Enr_end CodeSupply) /* POV1: Primary cohort Group Index Date (GroupIndex) */ _GroupWash&n.(keep=PatId Adate ExpireDt Enr_Start) /* POV2: Primary Cohort Group Washout (GroupWash) */ %end; _GroupPreg(keep=PatId Adate ExpireDt Enr_Start CodeCat Codetype Code PriorityGroup1 PriorityGroup2 Priority Duration) %end; _GroupWash(keep=PatId Adate ExpireDt Enr_Start) /* POV2: Primary Cohort Group Washout (GroupWash) */ _GroupWashForTrunk(keep=PatId Adate Enr_Start) _InclExcl /* POV3: Inclusion/Exclusion (InclExcl) */ _FUPEvent(keep=PatId Adate ExpireDt Enr_Start codecat codetype code) /* POV5: Risk Follow-Up Event (FUPEvent) */ _FUPWash(keep=PatId Adate ExpireDt Enr_Start); /* POV6: Risk Follow-Up Washout (FUPWash) */ set _ITDrugs(in=a rename=RxDate=ADate) _ITMeds(in=b) _ITLabs(in=c) _itdates(in=d); %if %eval(&type. ne 1) %then %do; if b or c then do; Expiredt=Adate; RXsup=1; RXAmt=1; NumDispensing = 1; end; %end; if d then do; Expiredt=Adate; RXsup=1; RXAmt=1; end; if &type.=1 then do; /*POV1*/ if T1_INDEX in('DEF') then output _GroupIndex; /*POV2*/ if T1_INDEX in('IOC') then output _GroupWash; /*POV3*/ if T1_INDEX in('INC','EXC') then output _InclExcl; end; if &type.=2 then do; /*POV1*/ if T2_INDEX in('DEF') then output _GroupIndex; /*POV2*/ if T2_INDEX in('IOT','IOD') then output _GroupWash; *for the IO* part; if T2_INDEX in('IOT','FUT') then output _GroupWashForTrunk; *for the **T part; /*POV3*/ if T2_INDEX in('INC','EXC') then output _InclExcl; /*POV5*/ if T2_FUP in('DEF') then output _FUPEvent; /*POV6*/ if T2_FUP in('IOC') then output _FUPWash; end; if &type.=3 then do; /*POV1*/ if T3_INDEX in('DEF') then output _GroupIndex; /*POV2*/ if T3_INDEX in('IOC') then output _GroupWash; *for the IO* part; /*POV3*/ if T3_INDEX in('INC','EXC') then output _InclExcl; /*POV5*/ if T3_FUP in('DEF') then output _FUPEvent; /*POV6*/ if T3_FUP in('IOC') then output _FUPWash; end; %if %eval(&type. eq 4) %then %do; if not a and not missing(CodeSupply) then do; RxSup=CodeSupply; Expiredt=ADate+RxSup-1; end; /*POV1*/ if T4_INDEX in('DEF') then output _GroupIndex; %do n=1 %to &NUM_MPN.; if T4_INDEX in("MP&n.") then output _GroupIndex&n.; %end; /*POV2*/ if T4_INDEX in('IOC') then output _GroupWash; *for the IO* part; %do n=1 %to &NUM_MPN.; if T4_INDEX in("IC&n.") then output _GroupWash&n.; %end; /*POV3*/ if T4_INDEX in('INC','EXC') then output _InclExcl; /*Preg*/ if T4_INDEX in('PCY') then output _GroupPreg; /*POV5*/ if T4_FUP in('DEF') then output _FUPEvent; /*POV6*/ if T4_FUP in('IOC') then output _FUPWash; %end; if &type.=5 then do; /*POV1*/ if T5_INDEX in('DEF') then output _GroupIndex; /*POV2*/ if T5_INDEX in('IOT','IOD') then output _GroupWash; *for the IO* part; if T5_INDEX in('IOT','FUT') then output _GroupWashForTrunk; *for the **T part; /*POV3*/ if T5_INDEX in('INC','EXC') then output _InclExcl; end; run; proc datasets library= work nowarn nolist; delete _ITDrugs _ITMeds _ITLabs; quit; /*---------------------------------------------------*/ /* 06.g -- POV1: Find All potential index dates */ /*---------------------------------------------------*/ *Leave CohortId blank for primary cohort; %ms_createpov1(CohortId=); %IF %EVAL(&type. = 4) %THEN %DO; %ms_createpov1t4(CohortId=); %do n=1 %to &NUM_MPN.; %ms_createpov1(CohortId=&n.); %end; %END; /*---------------------------------------------------*/ /* 06.h -- POV2: identify all index dates that are */ /* free of POV2 records in washper */ /*---------------------------------------------------*/ *Leave CohortId blank for primary cohort; %ms_createpov2(CohortId=); %IF %EVAL(&type.=4) %THEN %DO; %do n=1 %to &NUM_MPN.; %ms_createpov2(CohortId=&n.); %end; %END; /*---------------------------------------------------*/ /* 06.i -- POV3: identify all index dates meeting */ /* inclusion Exclusion */ /*---------------------------------------------------*/ %ms_createpov3(); /*---------------------------------------------------*/ /* 06.j -- POV4: Create At-Risk Episodes */ /*---------------------------------------------------*/ *Before we build episodes, we must make sure potential index dates are separated by at least ITT days if ITT episodes are required; %macro DoITTCheck(CohortId=); %let paramsuffix=; %if %str("&CohortId.") ne %str("") %then %do; %let paramsuffix=2; %end; %if %eval(&&itt¶msuffix. ne 0) %then %do; *When ITT days is greater than exposure plus washper we must make sure that two consecutive claims are separated by at least ITT days for the second one to be a valid index date; data _POV1&CohortId.; set _POV1&CohortId.; ExpireDt=ADate; run; %ms_findgap(InFile=_POV1&CohortId., OutFile=_POV1&CohortId., sort=PatId Adate descending ExpireDt, NoDup=Y, gapby=PatId, gap=ittdays¶msuffix., dupby=patid adate); *Reset ExpireDt to first claim ADate plus supply; data _POV1&CohortId.; set _POV1&CohortId.; ExpireDt=ADate+RxSup-1; run; *Clean potential index date dataset for later use; data _GroupIndex&CohortId.; merge _POV1&CohortId. (in=a) _GroupIndex&CohortId.; by PatId Adate; if a; run; %end; %mend DoITTCheck; %DoITTCheck(CohortId=); *Leave CohortId blank for primary cohort; %IF %EVAL(&type. ne 4) %THEN %DO; %ms_createpov4(CohortId=); %END; %ELSE %DO; %ms_createpov4t4(CohortId=); %do n=1 %to &NUM_MPN.; %DoITTCheck(CohortId=&n.); %ms_createpov4(CohortId=&n.); %end; %END; /*---------------------------------------------------*/ /* 06.k -- Create Final Record wrt index date */ /*---------------------------------------------------*/ %ms_createptsmasterlist(); /**********/ /* EVENTS */ /**********/ %ms_createpov56(); /********************************************************************/ /* For Type 5 - select index episode and create subsequent episodes */ /********************************************************************/ %if %eval(&type=5) %then %do; %ms_createt5episodes(); %end; /*---------------------------------------------------*/ /* 06.l -- Finalize Episode List */ /*---------------------------------------------------*/ %ms_finalizeptsmasterlist(); %if %eval(&type=4) %then %do; * Create the control group (match treated patients); %ms_CreateControlGroup(); data _ControlGroup; set _ControlGroup; format group $40.; Group="&ITGROUP."; DelNum=_N_; * To make sure patients used more than once in the matching process are considered distinct deliveries; feventdt = .; run; * Keep only the secondary cohort episodes of members who are in the primary cohort (to avoid unnecessary big file); proc sql noprint; create table _UniquePtsList as select distinct(PatId) from _PtsMasterList union select distinct(PatId) from _ControlGroup; quit; data _PtsMasterList2; merge _UniquePtsList(in=a) _PtsMasterList2 (in=b); by Patid; if a and b; run; proc sort nodupkey data=_PtsMasterList2; by _ALL_; run; %end; %if %eval(&type < 3) %then %do; *Compute Denominators; %ms_cidadenom(); %end; %if %eval(&type = 2) %then %do; *Compute Unexposed Cohort; %ms_nvrexposed(); %end; *Run surveillance if required and applicable; %if ("&SURVEILLANCEMODE."="f" or "&SURVEILLANCEMODE."="p") and %eval(&type. = 2) %then %do; %if ("&SURVEILLANCEMODE."="f") %then %do; data _PtsMasterList; set _PtsMasterList; format EndFollowUpType $20.; if LastLookFollowed=0 then do; *apply only to eligible patients; if min(Feventdt,EpisodeEndDt) < &enddate. then do; LastLookFollowedDt = &enddate.; LastLookFollowed = &PERIODIDSTART.; EndFollowUpType="EpisodeEndBFEnddate"; end; else if Feventdt = &enddate. then do; LastLookFollowedDt = &enddate.; LastLookFollowed = &PERIODIDSTART.; EndFollowUpType="EventOnEnddate"; end; end; run; %end; * Prior data existence for Surveillance; %ISDATA(dataset=DPLPRIOR.&RUNID._mstr); %IF %EVAL(&NOBS.>0) and %EVAL(&PERIODIDSTART. > 1) %THEN %DO; %ms_surveillance(); %END; %end; *Store patient episodes to DPLocal; %IF %EVAL(&group.=1) %THEN %DO; data DPLocal.&RUNID._mstr; set _PtsMasterList; run; %if %eval(&type eq 3) %then %do; data DPLocal.&RUNID._mstr_Censor; set _PtsMasterList_Censor; run; %end; %if %eval(&type eq 4) %then %do; data DPLocal.&RUNID._sec; set _PtsMasterList2; run; data DPLocal.&RUNID._ctrl; set _ControlGroup; run; data DPLocal.&RUNID._prePostCodes; set _prePostCodes; run; data DPLocal.&RUNID._allDeliveries; set _Deliveries; run; %end; %if %eval(&type eq 5) %then %do; data DPLocal.&RUNID._dispensings; set _dispensings; run; %end; %END; %ELSE %DO; *Because of surveillance mode and the carried forward variables from look <&PERIODIDSTART. that have not been calculated yet for the (&PERIODIDSTART.<=look<=&PERIODIDEND.)) - we will use a set method rather than append; data DPLocal.&RUNID._mstr; set DPLocal.&RUNID._mstr _PtsMasterList; run; %if %eval(&type eq 3) %then %do; proc append base=DPLocal.&RUNID._mstr_Censor data=_PtsMasterList_Censor force; run; %end; %if %eval(&type eq 4) %then %do; proc append base=DPLocal.&RUNID._sec data=_PtsMasterList2 force; run; proc append base=DPLocal.&RUNID._ctrl data=_ControlGroup force; run; proc append base=DPLocal.&RUNID._prePostCodes data=_prePostCodes force; run; proc append base=DPLocal.&RUNID._allDeliveries data=_Deliveries force; run; %end; %if %eval(&type eq 5) %then %do; proc append base=DPLocal.&RUNID._dispensings data=_dispensings force; run; %end; %END; %if %eval(&type ne 4) %then %do; %if &censor_dth.=1 %then %do; *If censoring is used, truncate enrollment at death date (for denominators/attrition); data ENR_&GROUP.; set ENR_&GROUP.; if EnrEpisodeCensoredAtDeath = 1 and DeathDt <= Enr_End then do; Enr_End=DeathDt; end; if Enr_end < Enr_Start then delete; run; data _groupindex; set _groupindex; if EnrEpisodeCensoredAtDeath = 1 and . < DeathDt < adate then delete; run; %end; *Compute Attrition for this group; %ms_attrition(); %end; /************************/ /* Produce outputs */ /************************/ %if %eval(&type. = 1) | %eval(&type. = 2) %then %do; %ms_cidatables(); %end; %if %eval(&type. eq 3) %then %do; %ms_cidatablest3(); %end; %if %eval(&type. eq 4) %then %do; %ms_cidatablest4(); %end; %if %eval(&type. eq 5) %then %do; %ms_cidatablest5(); %end; proc datasets library=work nowarn nolist; delete _:; quit; * Reset loop macro variables; %let EXCL=; %let INCL=; %let CHARTRES=; %put LAST GROUP RAN WAS &ITGROUP. &group.; %end; /*group loop*/ %mend forloop; %forloop; proc sort data=DPLocal.&RUNID._mstr; by Group PatId IndexDt; run; %if %eval(&type.=4) %then %do; proc sort data=DPLocal.&RUNID._ctrl; by Group PatId IndexDt; run; %end; /************************/ /* Freeze Patients Data */ /************************/ %macro wrapper; %IF %UPCASE(%str("&FREEZEDATA."))=%str("Y") | %UPCASE(%str("&FREEZEDATA."))=%str("A") %THEN %DO; %if %eval(&type. ne 4) %then %do; proc sort nodupkey data=DPLocal.&RUNID._mstr /*excludes never-exposed cohorts if "Y" */ %IF %UPCASE(%str("&FREEZEDATA."))=%str("Y") %THEN (WHERE = (INDEX(UPCASE(GROUP), "_NVREXP") = 0)) ; out=_PtsList(keep=Patid); by Patid; run; %end; %else %do; data _PtsList; set DPLocal.&RUNID._allDeliveries (keep=Patid) DPLocal.&RUNID._ctrl (keep=Patid); run; proc sort nodupkey data=_PtsList; by Patid; run; %end; %isdata(dataset=_PtsList); %if %eval(&nobs.>0) %then %do; %IF %STR(&ENRTABLE.) ne %STR() or %LENGTH(&ENRTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&ENRTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&ENRTABLE.);%END; %IF %STR(&DEMTABLE.) ne %STR() or %LENGTH(&DEMTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&DEMTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&DEMTABLE.);%END; %IF %STR(&DISTABLE.) ne %STR() or %LENGTH(&DISTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&DISTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&DISTABLE.);%END; %IF %STR(&DIATABLE.) ne %STR() or %LENGTH(&DIATABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&DIATABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&DIATABLE.);%END; %IF %STR(&PROCTABLE.) ne %STR() or %LENGTH(&PROCTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&PROCTABLE,PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&PROCTABLE.);%END; %IF %STR(&ENCTABLE.) ne %STR() or %LENGTH(&ENCTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&ENCTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&ENCTABLE.);%END; %IF %STR(&LABTABLE.) ne %STR() or %LENGTH(&LABTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&LABTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&LABTABLE.);%END; %IF %STR(&VITTABLE.) ne %STR() or %LENGTH(&VITTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&VITTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&VITTABLE.);%END; %IF %STR(&DEATHTABLE.) ne %STR() or %LENGTH(&DEATHTABLE.) > 0. %THEN %DO;%MS_FREEZEDATA(INFILE=indata.&DEATHTABLE, PATLISTINFILE=_PtsList,OUTFILE=DPLocal.&RUNID._&DEATHTABLE.);%END; *This datalib will point to the subset of PatId data gererated by Freeze data; %let DataLib=DPlocal.&RUNID._; %end; %END; %mend wrapper; %wrapper; /*** Extract Covariates and Produce Baseline table ***/ %ms_CIDAcov(data=mstr, outcohort=); %if %eval(&type.=4) %then %do; %ms_CIDAcov(data=ctrl, outcohort=_ctrl); %end; *delete undocumented vars from MSTR; data dplocal.&RUNID._mstr(drop=EndFollowUpType blackoutper); set dplocal.&RUNID._mstr; if _n_ = 1 then do; dsid = open("dplocal.&RUNID._mstr"); if varnum(dsid,"EndFollowUpType") = 0 then EndFollowUpType =''; if varnum(dsid,"blackoutper") = 0 then blackoutper =.; rc= close(dsid); end; drop rc dsid; %if %eval(&type.=5) %then %do; drop FEventDt; rename tte=EpisodeLength; %end; run; *output censoring table; %if &censor_output. = 1 %then %do; %ms_createcensortable(); %end; proc datasets library=work nowarn nolist; delete &COHORTCODES. DRUGS Drugscomb ENR_MD30 LABEXTRACT DeathExtract MEDS &MONITORINGFILE. &Inclusioncodes. Enr_: PreMeds ElixMeds covmeds PreDrugs Monitoringfileflm Premeds Ptslist Studynames _:; quit; %ms_stoptimer(START=&MAINSTART.); * Reset global macro variables; %let COMBORUN=; *Create the number of groups to create cohorts (into NOBS); %ISDATA(dataset=infolder.&COHORTFILE.); *Signature file; data signature; DPID="&DPID."; SITEID="&SITEID."; MSReqID="&MSREQID."; MSProjID="&MSPROJID."; MSWPType="&MSWPTYPE."; MSWPID="&MSWPID."; MSDPID="&MSDPID."; MSVerID="&MSVERID."; RunID="&RUNID."; MPNum="QRP"; MPVer="&Ver."; format StartTime StopTime datetime21.2; StartTime=input("&MAINSTART.",best.); StopTime=input("&STOP.",best.); format Seconds $20.; Seconds=put(int(&stop.-&MAINSTART.),best.)||" s"; ExecutionTime="&hours. h &minutes. m &seconds. s"; ScenarioCnt=strip("&NOBS."); PERIODIDSTART="&PERIODIDSTART."; PERIODIDEND="&PERIODIDEND."; ANALYSIS="&ANALYSIS."; MONITORINGFILE="&MONITORINGFILE."; T3METADATA="&T3METADATA."; COHORTFILE="&COHORTFILE."; TYPE1FILE="&TYPE1FILE."; TYPE2FILE="&TYPE2FILE."; TYPE3FILE="&TYPE3FILE."; TYPE4FILE="&TYPE4FILE."; TYPE5FILE="&TYPE5FILE."; COHORTCODES="&COHORTCODES."; INCLUSIONCODES="&INCLUSIONCODES."; COVARIATECODES="&COVARIATECODES."; MFUFILE="&MFUFILE."; PROFILE = "&PROFILE."; STOCKPILINGFILE="&STOCKPILINGFILE."; UTILFILE="&UTILFILE."; COMBOFILE="&COMBOFILE."; COMORBFILE="&COMORBFILE."; DRUGCLASSFILE="&DRUGCLASSFILE."; FREEZEDATA="&FREEZEDATA."; LABSCODEMAP="&LABSCODEMAP."; PREGDUR="&PREGDUR."; ZIPFILE="&ZIPFILE."; RUN_ENVELOPE = "&RUN_ENVELOPE."; SURVEILLANCEMODE = "&SURVEILLANCEMODE"; PATIDEXCL="&PATIDEXCL."; ETLNUMBER="&ETL."; format DPMINDATE DPMAXDATE date9.; DPMINDATE=&DP_MinDate.; DPMAXDATE=&DP_MaxDate.; output; run; proc transpose data=signature out=msoc.&RUNID._signature(rename=_NAME_=Var rename=COL1=VALUE); var _ALL_; run; %put NOTE: ********END OF MACRO: ms_cidanum v2.7********; %mend ms_cidanum;