**************************************************************************************************** * PROGRAM OVERVIEW **************************************************************************************************** * * PROGRAM: ms_globalmacrovariables.sas * * Created (mm/dd/yyyy): 02/20/2017 * Last modified: 02/26/2018 * Version: 1.9 * *-------------------------------------------------------------------------------------------------- * PURPOSE: * These are utility macros that are used to declare, initialize and set global macro variables * * Program inputs: * * Program outputs: * * PARAMETERS: * * Programming Notes: * * * *-------------------------------------------------------------------------------------------------- * CONTACT INFO: * Mini-Sentinel Coordinating Center * info@mini-sentinel.org * *-------------------------------------------------------------------------------------------------- * CHANGE LOG: * * Version Date Initials Comment (reference external documentation when available) * ------- -------- -------- --------------------------------------------------------------- * 1.1 05/04/2017 AP 1. Added race_out, hispanic_out, agestrat cohortfile parameters * 2. Reordered assignment of &priordays_af/bf to fix QRP-375 * 1.2 06/26/2017 AP 1. Added Type 5 analysis * 2. Added covariate variables to Types 3 and 4 analysis * 3. Added EpisodeGapType to Type 2 analysis * * 1.3 09/14/2017 AP Removed Condfrom/CondTo from &inclexclvars (QRP-437) * * 1.4 09/22/2017 AP Add Condfrom/CondTo from &inclexclvars (QRP-441) * * 1.5 10/03/2017 AP Added keep_blackout parameter (QRP-319) and moved GEOG to Cohort File (QRP-434) * * 1.6 11/20/2017 AP Removed keep_blackout parameter (QRP-466) * * 1.7 12/21/2017 AP 1. Removed comorbidity window parameters (QRP-435) * 2. Added CODEDAYS parameter (QRP-455) * 3. Added censoring vars to Type1file (QRP-462) * * 1.8 02/01/2018 AP Removed variables related to post-index enrollment (QRP-496) * * 1.9 02/26/2018 RR Initialize variables related to the unexposed group (QRP-495) ***************************************************************************************************; *This macro is used to declare and initialize global macro variables; %macro ms_initmacrovariables(); *Variables related to Group(s); %global Group; %let Group=1; %global Ngroup; %let Ngroup=1; %global ITGROUP; %let ITGROUP=; *Variables related to COHORTFILE parameters; %global Type; %let Type=; %global COVERAGE; %let COVERAGE=; %global ENROLGAP; %let ENROLGAP=; %global CHARTRES; %let CHARTRES=; %global RECONTYP; %let RECONTYP=; %global DemogSex; %let DemogSex=; %global DemogRace; %let DemogRace=; %global DemogHispanic; %let DemogHispanic=; %global enrdays; %let enrdays=.; %global EnrDaysAft; %let EnrDaysAft=.; %global race_out; %let race_out=; %global hispanic_out; %let hispanic_out=; %global race_groups; %let race_groups =; %global hispanic_groups; %let hispanic_groups=; %global agestrat; %let agestrat=; %global GEOG; %let GEOG=; *Variables related to TYPEFILE parameters; %global COHORTDEF; %let COHORTDEF=; %global WASHPER; %let WASHPER=.; %global ITT; %let ITT=0; %global eventcount; %let eventcount=.; %global FUPWASHPER; %let FUPWASHPER=.; %global ITTDAYS; %let ITTDAYS=.; %global BLACKOUTPER; %let BLACKOUTPER=.; %global MINEPISDUR; %let MINEPISDUR=.; %global MAXEPISDUR; %let MAXEPISDUR=.; %global MINDAYSUPP; %let MINDAYSUPP=.; %global censor_output; %let censor_output=.; %global censor_qryend; %let censor_qryend=.; %global censor_dpend; %let censor_dpend=.; %global Censor_dth; %let Censor_dth=0; %global censor_output_cat; %let censor_output_cat = ; %global neverexposedcohort; %let neverexposedcohort =; %global ExclOnSameDay; %let ExclOnSameDay=N; %global T3CtrlFrom; %let T3CtrlFrom=.; %global T3CtrlTo; %let T3CtrlTo=.; %global T3RiskFrom; %let T3RiskFrom=.; %global T3RiskTo; %let T3RiskTo=.; %global T3SURVSTARTDATE; %let T3SURVSTARTDATE=.; %global T3ENDOFUPDATE; %let T3ENDOFUPDATE=.; %global EnrDaysFloor; %let EnrDaysFloor=.; *Variables related to COVARIATECODES parameters; %global MinCovFrom; %let MinCovFrom=.; *Variables related to HDPS; %global HDPSGROUPS; %let HDPSGROUPS=; %global MinHDPSWinfrom; %let MinHDPSWinfrom=.; %global MaxHDPSWinTo; %let MaxHDPSWinTo=.; %global L1HDPSFROM; %let L1HDPSFROM=0; *Variables related to covariates and comorbs; %global ComborbsCodes; %let ComborbsCodes=; %global CovarCodes; %let CovarCodes=; %global CovarCodes2; %let CovarCodes2=; %global NumCovars; %let NumCovars=0; %global NumComb; %let NumComb=0; *Variables related to MFU analysis; %global minMFUfrom; %let minMFUfrom=.; *Variables related to inclusion/exclusion conditions; %global INCL; %let INCL=0; %global EXCL; %let EXCL=0; %global InclExclVars; %let InclExclVars=; %if %sysfunc(exist(infolder.&INCLUSIONCODES.))=1 %then %do; %let InclExclVars=CondInclusion Cond Subcond SubCondInclusion condto condfrom codedays; %end; *Variables related to patients to exclude; %global PatIdExcl; %let PatIdExcl=No; %if %str("&PTSTOEXCLUDE.") ne %str("") %then %do; %let PatIdExcl=Yes; %end; *Variables related to stockpiling; %global SAMEDAY; %let SAMEDAY=aa; %global SUPRANGE; %let SUPRANGE=0<-HIGH; %global AMTRANGE; %let AMTRANGE=0<-HIGH; %global PERCENTDAYS; %let PERCENTDAYS=; *Variables related to CDM and output tables; %global chartvar; %global charts; %global DataLib; %let DataLib=indata.; %global agedatecohort; *Other variables; %global COMBORUN; %let COMBORUN=; %global ExpPeriodStartDt; %let ExpPeriodStartDt=.; %global ExpPeriodEndDt; %let ExpPeriodEndDt=.; %global MinExpPeriodStartDt; %let MinExpPeriodStartDt=.; %global MaxExpPeriodEndDt; %let MaxExpPeriodEndDt=.; %global dpmax_adjust; %let dpmax_adjust=.; %global startfollowup; %let startfollowup=.; %global enddate; %let enddate=.; %global numperiodid; %let numperiodid=.; %global NoFindGapDuplicate; %let NoFindGapDuplicate=Y; %global NUM_MPN; %let NUM_MPN=0; *Trigger Warnings; %global EpisodeGapWarn; %let EpisodeGapWarn = N; %mend ms_initmacrovariables; *This macro is used to set macro variables related to a particular Group during the numerators processing (ms_cidanum) based on the type of analysis being executed; %macro ms_setnumloopmacrovars(); data _null_; set infolder.&COHORTFILE.; if _n_ = &Group. then do; call symputx('ITGROUP',strip(Group)); *Determine the type of analysis; if upcase(type1)=:"Y" then call symputx('Type',1); if upcase(type2)=:"Y" then call symputx('Type',2); if upcase(type3)=:"Y" then call symputx('Type',3); if upcase(type4)=:"Y" then call symputx('Type',4); if upcase(type5)=:"Y" then call symputx('Type',5); *Enrollment parameter; call symputx("COVERAGE",strip(upcase(coverage))); *Minimum Enrollment days before exposure; call symputx("enrdays",put(enrdays,best.)); *Minimum Enrollment days after exposure; if EnrdaysAft ne . then do; call symputx("EnrDaysAft",put(EnrDaysAft,best.)); end; else do; call symputx("EnrDaysAft",0); end; *Enrollment gap; if enrolgap ne . then call symputx("ENROLGAP",enrolgap); else call symputx("ENROLGAP","0"); *Compound name for suffix of elig file; if missing(CHARTRES) then CHARTRES='N'; call symputx("CHARTRES",CHARTRES); call symputx("RECONTYP",strip(upcase(coverage))||compress(CHARTRES,"_")); *Age stratification; if missing(agestrat) then do; call symputx("agestrat","00-01 02-04 05-09 10-14 15-18 19-21 22-44 45-64 65-74 75+"); end; else do; call symputx("agestrat",agestrat); end; *Sex values applicable to demographics; if missing(Sex) then do; call symputx("DemogSex","'F' 'M' 'U' 'A'"); end; else do; call symputx('DemogSex',upcase(Sex)); end; *Race values applicable to demographics; if missing(Race) then do; call symputx("DemogRace","'0' '1' '2' '3' '4' '5'"); end; else do; call symputx("DemogRace",upcase(Race)); end; *Hispanic values applicable to demographics; if missing(Hispanic) then do; call symputx("DemogHispanic","'Y' 'N' 'U'"); end; else do; call symputx("DemogHispanic",upcase(Hispanic)); end; *Output Race and/or Hispanic information; if missing(race_out) then do; call symputx("race_out","N"); end; else do; call symputx("race_out",upcase(race_out)); end; if missing(hispanic_out) then do; call symputx("hispanic_out","N"); end; else do; call symputx("hispanic_out",upcase(hispanic_out)); end; *Geographic stratifications; call symputx("GEOG",strip(upcase(Geog))); end; run; %PUT &ITGROUP. &Type. &COVERAGE. &CHARTRES. &ENROLGAP. &RECONTYP. &enrdays. &enrdaysaft.; *HDPS variables; %ISDATA(dataset=HDPS); %IF %EVAL(&NOBS.>0) %THEN %DO; data _null_; set HDPS; where group="&ITGROUP"; if .0 then do; call symputx("ITT",1); *defensive coding; Episodegap=.; Episodegaptype = ''; expextper=.; minepisdur=.; maxepisdur=.; end; else call symputx("ITT",0); if upcase(censor_dth) eq "Y" then call symputx("censor_dth",1); else call symputx("censor_dth",0); if upcase(censor_dpend) eq "Y" then call symputx("censor_dpend",1); else call symputx("censor_dpend",0); if upcase(censor_output) eq "Y" then call symputx("censor_output",1); else call symputx("censor_output",0); if upcase(censor_qryend) eq "Y" then call symputx("censor_qryend",1); else call symputx("censor_qryend",0); call symputx("censor_output_cat", censor_output_cat); *unexposed; NEVEREXPOSEDCOHORT = strip(upcase(NEVEREXPOSEDCOHORT)); call symputx("NEVEREXPOSEDCOHORT",upcase(NEVEREXPOSEDCOHORT)); *defensive; if blackoutper = . then blackoutper = 0; call symputx("eventcount",eventcount); call symputx("COHORTDEF",T2CohortDef); call symputx("WASHPER",T2WashPer); call symputx("FUPWASHPER",T2FupWashPer); call symputx("ITTDAYS",ittdays); call symputx("BLACKOUTPER",BlackoutPer); call symputx("MINEPISDUR",MinEpisDur); call symputx("MAXEPISDUR",MaxEpisDur); call symputx("MINDAYSUPP",MinDaySupp); rename T2WashPer=WashPer; EpisodeGapType = strip(upcase(EpisodeGapType)); if ITTDAYS <=0 then do; if EpisodeGapType not in ('F', 'P') then do; EpisodeGapType = 'P'; call symputx("EpisodeGapWarn",'Y'); end; end; drop group; run; %if "&EpisodeGapWarn" = "Y" %then %do; %put WARNING: EPISODEGAPTYPE not set to F or P. Will default to P.; %end; %end; ****************************************; * Type 3 cohort definition ; ****************************************; %if %eval(&Type. = 3) %then %do; data _CohortDef; set infolder.&TYPE3FILE.; where group="&ITGROUP."; if upcase(T3censor_dth) eq "Y" then call symputx("Censor_dth",1); else call symputx("Censor_dth",0); call symputx("T3CtrlFrom",T3CtrlFrom); call symputx("T3CtrlTo",T3CtrlTo); call symputx("T3RiskFrom",T3RiskFrom); call symputx("T3RiskTo",T3RiskTo); call symputx("ExclOnSameDay",T3ExclOnSameDay); call symputx("T3SURVSTARTDATE",T3SURVSTARTDATE); if T3ENDOFUPDATE=. then T3ENDOFUPDATE=99999; call symputx("T3ENDOFUPDATE",T3ENDOFUPDATE); call symputx("ExpPeriodStartDt",T3SURVSTARTDATE);*Default when &PERIODIDSTART. = 1; rename T3WashPer=WashPer; run; %if &PERIODIDSTART. > 1 %then %do; data _null_; set infolder.&T3METADATA.; where group="&ITGROUP."; call symputx("ExpPeriodStartDt",INTNX('Month', ExpPeriodEndDt+1, 0, 'begin')); run; %put ExpPeriodStartDt: &ExpPeriodStartDt.; %end; data _null_; call symputx("MinExpPeriodStartDt",Min(&MinExpPeriodStartDt., &ExpPeriodStartDt.)); run; *Check if risk and control windows overlap; %if (&T3CtrlFrom. <= &T3RiskTo. & &T3CtrlTo. >= &T3RiskFrom.) | (&T3RiskFrom. <= &T3CtrlTo. & &T3RiskTo. >= &T3CtrlFrom.) %then %do; %put WARNING: The control window overlaps with the risk window.; %end; %end; ****************************************; * Type 4 cohort definition ; ****************************************; %if %eval(&Type. = 4) %then %do; data _CohortDef; set infolder.&TYPE4FILE.; where group="&ITGROUP."; expextper=0; * needed for POV4 creation to avoid w.a.r.n.i.n.g.s.; expextper2=0; *Primary Cohort parameters; call symputx("COHORTDEF",T4CohortDef); call symputx("WASHPER",T4WashPer); call symputx("FUPWASHPER",T4FupWashper); call symputx("ITTDAYS",ittdays); call symputx("EnrDaysFloor",put(EnrDaysFloor,best.)); rename T4WashPer=WashPer; *Secondary Cohort parameters; if ittdays2>0 then do; call symputx("ITT2",1); EpisodeGapType2 = .; Episodegap2 = .; end; else call symputx("ITT2",0); call symputx("WASHPER2",T4WashPer2); call symputx("ITTDAYS2",ittdays2); EpisodeGapType2 = upcase(EpisodeGapType2); if ITTDAYS2 <=0 then do; if EpisodeGapType2 not in ('F', 'P') then do; EpisodeGapType2 = 'P'; call symputx("EpisodeGapWarn",'Y'); end; end; rename T4WashPer2=WashPer2; run; %if "&EpisodeGapWarn" = "Y" %then %do; %put WARNING: EPISODEGAPTYPE not set to F or P. Will default to P.; %end; *Verify that enrdays is sufficient to cover at least the whole episode duration; %if %eval(&EnrDays. < &EnrDaysFloor.) %then %do; %put WARNING: The value of EnrDays is not high enough to ensure enrollment during episodes.A value of at least 294 days is required.; %end; %end; ****************************************; * Type 5 cohort definition ; ****************************************; %if %eval(&Type. = 5) %then %do; data _CohortDef; set infolder.&TYPE5FILE.; where group="&ITGROUP."; if ittdays>0 then do; call symputx("ITT",1); call symputx("ITT2",1); *defensive coding; Episodegap=.; Episodegaptype = ''; end; else do; call symputx("ITT",0); call symputx("ITT2",0); end; if upcase(censor_dth) eq "Y" then call symputx("censor_dth",1); else call symputx("censor_dth",0); if upcase(censor_dpend) eq "Y" then call symputx("censor_dpend",1); else call symputx("censor_dpend",0); if upcase(censor_qryend) eq "Y" then call symputx("censor_qryend",1); else call symputx("censor_qryend",0); call symputx("COHORTDEF",T5CohortDef); call symputx("WASHPER",T5WashPer); call symputx("ITTDAYS",ittdays); /*N/A to Type 5*/ expextper=.; minepisdur=.; maxepisdur=.; mindaysupp=.; call symputx("MINEPISDUR",MinEpisDur); call symputx("MAXEPISDUR",MaxEpisDur); call symputx("MINDAYSUPP",MinDaySupp); blackoutper = .; /*defensive*/ EpisodeGapType = upcase(EpisodeGapType); if ITTDAYS <=0 then do; if EpisodeGapType not in ('F', 'P') then do; EpisodeGapType = 'P'; call symputx("EpisodeGapWarn",'Y'); end; end; rename T5WashPer=WashPer; /*For episode creation after index*/ EpisodeGap2 = EpisodeGap; EpisodeGapType2 = EpisodeGapType; ITTdays2 = ITTDays; call symputx("ITTDAYS2",ittdays2); expextper2 = expextper; WashPer2 = 0; drop group; run; %if "&EpisodeGapWarn" = "Y" %then %do; %put WARNING: EPISODEGAPTYPE not set to F or P. Will default to P.; %end; %end; ****************************************; * All Types - for Table 1 ; ****************************************; *Get max covariatewindow from covariatecodes and MFU- even if looped at group level it will be the same since Covariate window same for both groups; %let MinCovFrom=.; %let MinMFUFrom=.; *Since input file is optional, make sure it exists; %IF %SYSFUNC(exist(infolder.&COVARIATECODES.))=1 %THEN %DO; *Select covariates codes (not combination of covariates); data _&COVARIATECODES.; set infolder.&COVARIATECODES.; where codecat not in ("CC"); run; proc sql noprint; select max(-1*CovFrom) into: MinCovFrom from _&COVARIATECODES.(where=(. < CovFrom < 0)); quit; *Add w.a.r.n.i.n.g. if there is a covariatecodes inputfile, but not PS or ADS; %if (%UPCASE("&ANALYSIS.") ne ("PS")) & (%UPCASE("&ANALYSIS.") ne ("ADS")) & (%UPCASE("&ANALYSIS.") ne ("MS")) %then %do ; %put WARNING: Table 1 not specified but &COVARIATECODES. exist. CovFrom will not be considered when evaluating enrollment criteria; %let MinCovFrom=.; %end; %END; %put &MinCovFrom.; %ISDATA(dataset=infolder.&mfufile.); %if %eval(&nobs.>0) %then %do; proc sql; select max(-1*MFUFrom) into: MinMFUFrom from infolder.&mfufile.(where=(. < MFUFROM < 0)); quit; *Add w.a.r.n.i.n.g. if there is a MFU inputfile, but not PS or ADS; %if (%UPCASE("&ANALYSIS.") ne ("PS")) & (%UPCASE("&ANALYSIS.") ne ("ADS")) & (%UPCASE("&ANALYSIS.") ne ("MS")) %then %do ; %put WARNING: MFU not specified but &MFUFILE. exist. MFUFrom will not be considered when evaluating enrollment criteria; %let MinMFUFrom=.; %end; %END; %put &MinMFUFrom.; %mend ms_setnumloopmacrovars;