****************************************************************************************************
*                                           PROGRAM OVERVIEW
****************************************************************************************************
*
* PROGRAM: create_tableofcontents.sas  
* Created (mm/dd/yyyy): 02/09/2021
*
*--------------------------------------------------------------------------------------------------
* PURPOSE: This macro createas a dataset with 1 row per table and figure that is used as the 
*          report table of contents
*                                        
*  Program inputs:                                                                                   
*
*  Program outputs:          
*   -tableofcontents: dataset containing table of contents 
* 
*  PARAMETERS:                                                                       
*            
*  Programming Notes:                                                                                
*                                                                           
*
*--------------------------------------------------------------------------------------------------
* CONTACT INFO: 
*  Sentinel Coordinating Center
*  info@sentinelsystem.org
*
***************************************************************************************************;

%macro create_tableofcontents();

    %put =====> MACRO CALLED: create_tableofcontents;

    /*********************************************************************************************/
    /* Utility macro to add row to tableofcontents file                                          */
    /*********************************************************************************************/
    %macro addtotoc(tabnum=, caption=, appendixtype=);
    data tableofcontents;
        set tableofcontents end=eof;
        output;
        if eof then do;
            tabnum = "&tabnum.";
            caption = "&caption.";
			appendixtype = "&appendixtype.";
            output;
        end;
    run;
    %mend;

    /*********************************************************************************************/
    /* Initialize empty table and table number                                                   */
    /*********************************************************************************************/
    data tableofcontents;
        length tabnum $25 caption $500 appendixtype $30;
        call missing(tabnum, caption, appendixtype);
    run;

    %let number = 1;
    %let tablenum = 1;

    /*********************************************************************************************/
    /* Build table of contents                                                                   */
    /*********************************************************************************************/

    /*********************************************************************************************/
    /* Glossary rows */
    /*********************************************************************************************/
    %addtotoc(tabnum=Glossary (CIDA), caption=List of Terms to Define the Cohort Identification and Descriptive Analysis (CIDA) Found in this Report);
	%if %str("&reporttype") = %str("T2L2") | %str("&reporttype") = %str("T4L2") %then %do;
	  %addtotoc(tabnum=Glossary (PSA), caption=List of Terms to Define the Propensity Score Analysis (PSA) Found in this Report);				 
    %end;


    /*********************************************************************************************/
    /* Baseline Table                                                                            */
    /*********************************************************************************************/

    %if %eval(&numbaselinetablegrp.>0) %then %do;

        /*counter for determining table letter*/
        %let tablecount = 1;

        /* counter for determining table number */
        %let tablenum = 2;

        /*loop through each baseline table*/
        %do b = 1 %to &numbaselinetablegrp.;
            %let analysisgrp = ;
            %let analysisgrp2 = ;
            %let baselinegroupnum = ;
            %let pregnancylabel = ;
            %let pregnancylabel2 = ;
            %let includenonpregnant = N;

            /*for L2 tables - need to reference PS/CS specific files to pull additional parameters*/
            %let ratio = F;
            %let psfile = ;
            %let weightlabel = ;
            %let weightscheme = ;
            %let pstrim = ;
            %let percentiles=;
            %let ratiolabel = ;
            %let caliperlabel = ;
            %let truncationlabel = ;
            %let psestimategrp = ;
            %let unadjusted = ;

            data _null_;
                set baselinefile(where=(order=&b.));
                if _n_ = 1 then do;
                    call symputx('analysisgrp', analysisgrp);
                    call symputx('runid', runid);
                    call symputx('cohort', cohort);
                    call symputx('unique_psestimate',unique_psestimate);
					call symputx('unique_psestimate_orig',unique_psestimate);
                    %if %sysfunc(prxmatch(m/T4L1/i,&reporttype.)) > 0 %then %do;
                    if cohort in ('preg', 'nopreg') then do;
                     call symputx('pregnancylabel',preg_outcome_label);
                    end;
                    call symputx('includenonpregnant', upcase(includenonpregnant));
                    %end;
                    if missing(baselinegroupnum)=0 then call symputx('baselinegroupnum', baselinegroupnum);
                end;
                /*if baselinegroupnum is specified, a 2nd row will exist in the file*/
                if _n_ = 2 then do;
                    if missing(baselinegroupnum)=0 then do;
                        call symputx('analysisgrp2',analysisgrp);
                        %if %index(&reporttype,T4L1) %then %do;
                        call symputx('pregnancylabel2', preg_outcome_label);
                        %end;
                    end;
                end;
            run;         
            %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) > 0 %then %do;
            data _null_;
                set pscs_masterinputs(where=(analysisgrp = "&analysisgrp." and missing(subgroup)));
                call symputx('psfile', strip(file));
                call symputx('psestimategrp', psestimategrp);
                call symput('unadjusted', 'Unadjusted '); /*for unadjusted table label*/

                if file = 'psmatchfile' then do;
                    call symputx('ratio',upcase(ratio));
                    if upcase(ratio)='F' then call symputx("ratiolabel",'Fixed Ratio 1:'||strip(put(ceiling, 8.)));
                    if upcase(ratio)='V' then call symputx("ratiolabel",'Variable Ratio 1:'||strip(put(ceiling, 8.)));
                    call symputx("caliperlabel", cat(', Caliper: ', caliper));
                end;
                if file = 'stratificationfile' then do;
                    call symputx('pstrim', pstrim);
                    call symputx('percentiles', percentiles);
                    if missing(strataweight) =0 then call symputx('weightscheme', strataweight);
        	        if upcase(strataweight)= 'ATE' or missing(strataweight) then call symputx("weightlabel","Average Treatment Effect (ATE)");
                    else if upcase(strataweight)= 'ATT' then call symputx("weightlabel","Average Treatment Effect in the Treated (ATT)");
                end;
                if file = 'iptwfile' then do;
                    if upcase(ipweight)= 'ATE' then call symputx("weightlabel","Average Treatment Effect (ATE)");
                    else if upcase(ipweight)= 'ATES' then call symputx("weightlabel","Average Treatment Effect, Stabilized (ATES)");
                    else if upcase(ipweight)= 'ATT' then call symputx("weightlabel","Average Treatment Effect in the Treated (ATT)");
                    call symputx('truncationlabel',strip(put(truncweight, best.)));
                end;
            run;
            %end;

            /*For L1 tables, determine if only 1 baseline table and set &tablecount to 0. Will occur if all the following are true:
            - 1 monitoring period
            - DP stratification = N
            - max(order) in baselinefile = 1
             For L2 tables, tablecount assigned in macro baselinetoc*/
            %if %eval(&b.=1) & %eval(&look_start.) = %eval(&look_end.) & &stratifybydp. = N & %eval(&numbaselinetablegrp.=1) %then %do;
                %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) = 0 %then %do;
                    %let tablecount = 0;
                %end;                
            %end;

            /*Assign labels*/
            %let baselinelabel = ;
            %let grouplabel = &analysisgrp.;
            %let psestimatelabel = &psestimategrp.;
            %if %length(&baselinegroupnum.)>0 %then %do;
            %let grouplabel2 = &analysisgrp2.;
            %end;

            %isdata(dataset=labelfile);
            %if %eval(&nobs.>0) %then %do;
                data _null_;
                    set labelfile(in=a where=(group="&analysisgrp" and runid = "&runid"))
                        %if %length(&baselinegroupnum.)>0 %then %do;
                        labelfile(in=b where=(group="&analysisgrp2" and runid = "&runid"))
                        %end; 
                        %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) > 0 %then %do;
                        labelfile(in=c where=(group="&psestimategrp" and runid = "&runid"))
                        %end; ;
                    if a then do;
                        if labeltype = 'grouplabel' then call symputx('grouplabel',label);
                        if labeltype = 'baselinelabel' then call symputx('baselinelabel',cat(', ',strip(label), ','));
                    end;
                    %if %length(&baselinegroupnum.)>0 %then %do;
                    if b then do;
                        if labeltype = 'grouplabel' then call symputx('grouplabel2',label);
                    end;
                    %end;
                    %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) > 0 & &psfile. ne covstratfile %then %do;
                    if c then do;
                        if labeltype = 'grouplabel' then call symputx('psestimatelabel',label);
                    end;
                    %end;
                run;
            %end;

            /*1 block of code for both aggregate and DP tables*/
            %macro baselinetoc(aggregated=, dpinparenthesis=, dpcomma=);

				* Process L2 subgroups;
				%let numsubgroups=0;
				%let subgroup=;
				%let subgroupcat=;
				%let subgrouptitle=;

				%if &reporttype = T2L2 or &reporttype = T4L2 %then %do;
					proc sort nodupkey data=Pscs_masterinputs(where=(analysisgrp="&analysisgrp." and runid="&runid." and not missing(subgroup))) 
									   out=_subgroups(keep=subgroup subgroupcat subgrouporder subgroupcatorder combinedlabel);
					by subgrouporder subgroupcatorder;
					run;

					proc sql noprint;
					select count(*) into :numsubgroups from _subgroups;
					quit;
				%end;

				%do sub=0 %to &numsubgroups.;

					%if &sub. > 0 %then %do;
						data _null_;
						set _subgroups;
						if _N_=&sub.;		
						call symputx("subgrouptitle",combinedlabel);
						run;
						
						%let captionlabel = %bquote(&grouplabel.&pregnancylabel&baselinelabel.);
						%let unique_psestimate = 1;
					%end;	
					%else %do;
						%let captionlabel = %bquote(&grouplabel.&pregnancylabel&baselinelabel.);
			            %if %length(&baselinegroupnum.)>0 %then %do;
                            %if %index(&reporttype,T4L1) %then %let pregnancylabel = &pregnancylabel2;
			            %let captionlabel = %bquote(&grouplabel.&pregnancylabel and &grouplabel2.&pregnancylabel&baselinelabel.);
			            %end;
			            %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) >0 & &psfile. ne covstratfile %then %do;
			            %let captionlabel = %bquote(&psestimatelabel.);
			            %end;  

						%let unique_psestimate = &unique_psestimate_orig;
					%end;

                    /*For L2 queries, set &tablecount to 0 if covariate stratification AND no subgroups*/
					%if &psfile. = covstratfile and &numsubgroups. = 0 and %eval(&look_start.) = %eval(&look_end.) and 
						&stratifybydp. = N and %eval(&numbaselinetablegrp.=1) %then %let tablecount = 0;

	                %if %eval(&unique_psestimate.) = 1 %then %do;
	                 %tableletter(); 
	                 %addtotoc(tabnum=Table 1&tableletter., 
	                 caption=%quote(&aggregated.&unadjusted.Characteristics of &captionlabel. &dpinparenthesis.in the &database. from &startdateformatted. to &&enddate&periodid.formatted.&subgrouptitle.));
	                %end;

	                /*For L2 tables - up to 2 additional adjusted tables*/
	                %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) > 0 %then %do;
	                    /*PS Match Adjusted*/
	                    %if &psfile. = psmatchfile %then %do;
	                    %tableletter(); 
	                    %addtotoc(tabnum=Table 1&tableletter., 
	                    caption=%quote(&aggregated.Adjusted Characteristics of &grouplabel. (Propensity Score Matched&dpcomma., &ratiolabel.&caliperlabel.), in the &database. from &startdateformatted. to &&enddate&periodid.formatted.&subgrouptitle.));
	                    %end;

	                    /*Unweighted - IPTW and PS Stratum*/
	                    %if (&psfile. = iptwfile & %eval(&unique_psestimate.) = 1) | (&psfile. = stratificationfile & ("&weightscheme." = "ATE" | "&weightscheme." = "ATT") & %eval(&pstrim.>=0)) %then %do;
	                    %tableletter(); 
	                    %addtotoc(tabnum=Table 1&tableletter., 
	                     caption=%quote(&aggregated.Unweighted Characteristics of &grouplabel. (Unweighted, Trimmed&dpcomma.) in the &database. from &startdateformatted. to &&enddate&periodid.formatted.&subgrouptitle.));
	                    %end;

	                    /*Weighted - IPTW, PS Stratum, PS Stratification*/
	                    %if &psfile. = iptwfile | &psfile. = stratificationfile %then %do;
	                        %if &psfile. = iptwfile %then %let stratumtitle = Inverse Probability of Treatment Weighted, Trimmed&dpcomma., Weight: &weightlabel., Truncation: &truncationlabel.%nrbquote(%);
	                        %else %if "&weightscheme." = "ATE" | "&weightscheme." = "ATT" %then 
	                         %let stratumtitle = Propensity Score Stratum Weighted, Trimmed&dpcomma., Percentiles: &percentiles., Weight: &weightlabel.;
	                        %else %let stratumtitle =Propensity Score Stratified&dpcomma., Percentiles: &percentiles.;
	                        %tableletter(); 
	                        %addtotoc(tabnum=Table 1&tableletter., 
	                        caption=%quote(&aggregated.Weighted Characteristics of &grouplabel. (&stratumtitle.), in the &database. from &startdateformatted. to &&enddate&periodid.formatted.&subgrouptitle.));
	                    %end;
	                %end; /*Additional L2 tables*/
				%end; /*Subgroups looping*/
            %mend;

            /*loop through each periodid*/
            %do periodid = %eval(&look_start.) %to %eval(&look_end.);
                /*Aggregated*/
                %baselinetoc(%if %eval(&num_dp.)=1 %then %do;
                            aggregated=,
                            %end;
                            %else %do;
                            aggregated=%str(Aggregated ),
                            %end;
                            dpinparenthesis=, dpcomma=);
       
                /*Output separate table for each Data Partner - loop through each DP*/
                %if &stratifybydp. = Y %then %do;    
                    %do dps = 1 %to %eval(&num_dp.);
        		        %let maskedID = %scan(&masked_dplist,&dps); 
                        %baselinetoc(aggregated = , dpinparenthesis=%str((&maskedid.) ), dpcomma=%str(, &maskedid.));
                    %end;
                %end; /*DP stratification*/
            %end; /*loop through each periodid*/
        %end; /*loop through each row in baselinefile*/
    %end; /*include baseline tables in toc*/

    /*********************************************************************************************/
    /* Covariate Profile Table                                                                   */
    /*********************************************************************************************/
    %if &numprofilecovarstoinclude > 0 %then %do;

    /* reset counter to reset table letter */
    %let tablecount = 1;

    %do periodid = %eval(&look_start.) %to %eval(&look_end.);

    proc sql noprint ;
        select 'order='||strip(put(order,8.))||' and runid='||quote(strip(runid))||' and group='||quote(strip(group))||' and cohort='||quote(strip(cohort))
        into :whereexpr separated by '@'
        from (select order, runid, group, case when(cohort is missing) then 'all' else cohort end as cohort
              from baselinefile
              where not missing(profilecovarstoinclude))
        order by order;
    quit;

    %do wherenum = 1 %to %sysfunc(countw(&whereexpr, @));
        %let where = %scan(&whereexpr,&wherenum, @);

            data _temp_agg_order_profile;
                set aggregate_profile(where=(periodid=&periodid and &where));
                grouplabel='';
                if cohort = 'mi' then group2=scan(group,1,'_');
                else group2=group;

                if cohort = 'switch' then switchlabel = ' ';
                call symputx('runid',runid);
            run;

            %let profileswitches = 0;
            %if &reporttype = T6 %then %do;
            proc sql noprint;
            select max(switchstep) into :profileswitches
            from _temp_agg_order_profile;
            quit;
            %end;

            %isdata(dataset=_temp_agg_order_profile);
            %if &nobs > 0 %then %do;

            %do s = 0 %to &profileswitches;

            %if &reporttype = T6 %then %do;
            data _temp_agg_profile;
                set _temp_agg_order_profile (where=(switchstep = &s));
            run;

            /* Join treatment file onto profile table to obtain product group */
            proc sql noprint undo_policy=none;
                create table _temp_agg_profile as
                select a.*, b.group as productswitchgroup
                from _temp_agg_profile a 
                inner join infolder.&&&runid._treatmentpathways b
                on a.group = b.analysisgrp and a.switchstep = b.switchevalstep;
            quit;
            %end;
            %else %do;
            proc datasets lib=work nolist;
                change _temp_agg_order_profile = _temp_agg_profile;
            run;
            %end;

            /* Check for existence of label file and join to profile dataset. Set grouplabel to missing if no labelfile */
            %isdata(dataset=labelfile);
            %if &nobs > 0 %then %do;
            proc sql noprint undo_policy=none;
                create table _temp_agg_profile as
                select a.group, a.runid, a.order, a.periodid, b.label as grouplabel
                %if %index(&where,%str(cohort="mi")) %then %do;
                ,c.label as grouplabel2, a.group2
                %end;
                %if %index(&where,%str(cohort="switch")) %then %do;
                ,d.label as switchlabel, a.productswitchgroup
                %end;
                from _temp_agg_profile(drop=grouplabel %if &reporttype = T6 %then %do; switchlabel %end;) a 
                left join labelfile(where=(lowcase(labeltype)='grouplabel')) b
                on a.group = b.group and a.runid = b.runid
                %if %index(&where,%str(cohort="mi")) %then %do;
                left join labelfile(where=(lowcase(labeltype)='grouplabel')) c
                on a.group2 = c.group and a.runid = c.runid
                %end;
                %if %index(&where,%str(cohort="switch")) %then %do;
                left join labelfile(where=(lowcase(labeltype)='grouplabel')) d
                on a.productswitchgroup = d.group and a.runid = d.runid
                %end;
                ;
            quit;
            %end;
            %else %do;
            data  _temp_agg_profile;
            set _temp_agg_profile;
            grouplabel2='';
            switchlabel='';
            run;
            %end;
                
            data _null_;
                set _temp_agg_profile(keep=group grouplabel order
                                       %if %index(&where,%str(cohort="mi")) %then %do;
                                       group2 grouplabel2
                                       %end;
                                       %if %index(&where,%str(cohort="switch")) %then %do;
                                       productswitchgroup switchlabel
                                       %end;
                                        );
                if _n_ = 1;
                if not missing(grouplabel) then call symputx('grouplabel',grouplabel);
                else call symputx('grouplabel',group);

                %if %index(&where,%str(cohort="nopreg")) %then %do;
                if not missing(grouplabel) then call symputx('grouplabel',catx(' ',grouplabel,'Non-Pregnancy'));
                else call symputx('grouplabel',catx(' ',group,'Non-Pregnancy'));
                %end;

                %else %if %index(&where,%str(cohort="preg")) %then %do;
                if not missing(grouplabel) then call symputx('grouplabel',catx(' ',grouplabel,'Pregnancy'));
                else call symputx('grouplabel',catx(' ',group,'Pregnancy'));
                %end;

                %else %if %index(&where,%str(cohort="mi")) %then %do;
                if not missing(grouplabel) then do;
                if not missing(grouplabel2) then call symputx('grouplabel',grouplabel2);
                else call symputx('grouplabel',group2);
                end;
                else do;
                call symputx('grouplabel',group);
                end;
                %end;

                %else %if &reporttype = T6 %then %do;

                %if &s = 0 %then %do;
                if not missing(grouplabel) then do;
                call symputx('grouplabel',grouplabel);
                end;
                else do;
                call symputx('grouplabel',group);
                end;
                %end;

                %else %if &s = 1 %then %do;
                if not missing(grouplabel) then do;
                call symputx('grouplabel',grouplabel);
                end;
                else do;
                call symputx('grouplabel',group);
                end;
                %end;

                %else %if &s = 2 %then %do;
                if not missing(grouplabel) then do;
                call symputx('grouplabel',grouplabel);
                end;
                else do;
                call symputx('grouplabel',group);
                end;
                %end;

                %end;
            run;

             %tableletter();
             %if &numprofilecovarstoinclude = 1 and &reporttype ^= T6 %then %let tableletter =;
             %else %if &numprofilecovarstoinclude = 1 and &profileswitches = 0 and &reporttype = T6 %then %let tableletter =;
             %addtotoc(tabnum=Table &tablenum.&tableletter.,
             caption=%quote(Characteristic Profile of &grouplabel in the &database. from &startdateformatted. to &&enddate&periodid.formatted.));

             %end; /* _temp_agg_order_profile */
        %end; /* switch loop */

        proc datasets library=work nowarn noprint;
        delete _temp_agg_profile _temp_agg_order_profile;
        quit;

    %end; /* where loop */

    %end; /* periodid loop */
	
    %let tablenum = %eval(&tablenum + 1);
    %end; /* &numprofilecovarstoinclude > 0 */

    /*********************************************************************************************/
    /* Effect estimate table                                                                     */
    /*********************************************************************************************/

    %if &numl2comparisons > 0 and %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do; 

        /*loop through each comparison*/
        %do c = 1 %to &numl2comparisons;

        /* reset counter to reset table letter */
        %let tablecount = 1;

            data _null_;
                set l2comparisonfile(where=(order=&c.));
                call symputx('analysisgrp', analysisgrp);
                call symputx('runid', runid);
            run;

            /* Merge in group labels if they exist */
            %let grouplabel = &analysisgrp;
            %isdata(dataset=labelfile);
            %if %eval(&nobs>0) %then %do;
            data _null_;
                set labelfile(in=a where=(group="&analysisgrp" and runid = "&runid")) ;
                if labeltype = 'grouplabel' then call symputx('grouplabel',label);
            run;
            %end;

            /* Store subgroup to determine subgroup labels */
			proc sort nodupkey data=l2_effectestimates_&look_end.(where=(analysisgrp="&analysisgrp."))
							   out=_subgroups(keep= subgroup subgrouporder);
			by subgrouporder;
			run;

            proc sql noprint;
                select distinct subgroup, subgrouporder
                into :subgrouplist, :dummyvar
                separated by ' '
                from _subgroups
				order by subgrouporder;				
            quit;

            %if %str(&subgrouplist.) = %str() %then %do;
				%let tablecount = 0;
				%let numsubgroups=0;
			%end;
			%else %let numsubgroups=%sysfunc(countw(&subgrouplist));

            /* loop subgroup and assign subgroup label */
            %do subgroupcount = 0 %to &numsubgroups.;
                %if &subgroupcount. = 0 %then %let subgroup=;
        		%else %let subgroup= %scan(&subgrouplist,&subgroupcount);
				%let subgrouplabel=;

				proc sql noprint;
					select distinct strip(tabletitle) into: subgrouplabel trimmed
            		from Pscs_masterinputs
            		where subgroup = "&subgroup.";
				quit;

                %if %str(&subgroup.) = %str() %then %do;
                %let titleend = %str();
                %end;

                %else %if %substr(%upcase(&subgroup.),1,2) eq DP %then %do;
                %let titleend = %str(and Data Partner);
                %end;

                %else %do;                
                %let titleend = %str(and &subgrouplabel);
                %end;

                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                caption=%quote(Effect Estimates for &grouplabel. in the &database. from &startdateformatted. to &&enddate&look_end.formatted., by Analysis Type &titleend.));
            %end; /* covarcount */
            %let tablenum = %eval(&tablenum + 1);
         %end; /* numl2comparison do loop */
    %end; /* numl2comparison */

    /*********************************************************************************************/
    /* Type 1 and 2 summary tables                                                               */
    /*********************************************************************************************/

        %if %sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&tdatasetlist.)) %then %do;
           %do td = 1 %to &tdatasetlistnum.; 
            %let reporttable = %scan(&tdatasetlist, &td.);
            %if ^%sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&reporttable.)) %then %goto leavet1t2conc;

                proc sql noprint;
                    %let tableobs = 0;
                    select max(stratificationorder)
                    into :tableobs trimmed 
                    from tablefile
                    where dataset="&reporttable";
                quit;

                %do z = 1 %to %eval(&tableobs.);

                data _null_;
                    set tablefile(where=(dataset="&reporttable" and stratificationorder=&z));
                    call symputx('tabletitle', tabletitle);
                run;

                %if &stratifybydp = Y %then %let tablecount=1;
                %else %let tablecount=0;

                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                    caption=%bquote(Summary of &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));

                %if &stratifybydp. = Y %then %do;    
                    %do dps = 1 %to %eval(&num_dp.);
                        %let maskedID = %scan(&masked_dplist,&dps); 
                        %tableletter();
                        %addtotoc(tabnum=Table &tablenum.&tableletter.,
                            caption=%bquote(Summary of &reporttitle. in the &database. for &maskedID. from &startdateformatted. to &enddateformatted.&tabletitle.));    
                    %end;
                %end; 

                %let tablenum = %eval(&tablenum + 1);

                %end; /* z */
          %leavet1t2conc:
          %end; /* td */
        %end; /* %sysfunc(prxmatch(m/t1cida|t2cida|t2conc/i,&tdatasetlist.)) */

        /*****************************************************************************************/
        /* Type 1 and 2 censor tables                                                            */
        /*****************************************************************************************/
        %if %sysfunc(prxmatch(m/t1censor|t2censor|t2followuptime/i,&tdatasetlist.)) > 0 %then %do;

            %macro t1t2censortoc(tablename=, title=);

                %let tableidlist=;
                proc sql noprint;
                    select distinct table into: tableidlist separated by ' '
                    from tablefile(where=(dataset in ("&tablename.")));
                quit;

                %if %str("&tableidlist") ne %str("") %then %do;

                %isdata(dataset=&tablename.);
                %if %eval(&nobs.>0) %then %do;

                %do t = 1 %to %sysfunc(countw(&tableidlist.));
                    %let tableid = %scan(&tableidlist., &t.);
                    %let stratificationorder = 0;
                    proc sql noprint;
                        select max(stratificationorder) into: stratificationorder
                        from tablefile(where=(dataset in ("&tablename.") and table = "&tableid"));
                    quit;

                   /*counter for determining table letter*/
                   %if %eval(&stratificationorder. = 1) & &stratifybydp. ne Y %then %let tablecount = 0;
                   %else %let tablecount = 1;

                    %do st = 1 %to &stratificationorder.;
                        data _null_;
                            set tablefile(where=(dataset in ("&tablename.") and table = "&tableid" and stratificationorder = &st.));
                            call symputx('tabletitle', tabletitle);
                        run;
                     
                        %tableletter();
                        %if &tableid. = T1 %then %do;
                            %addtotoc(tabnum=Table &tablenum.&tableletter.,
                            caption=%quote(Summary of Time to End of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));

                        %if &stratifybydp. = Y & %eval(&st.=1) %then %do;
                            %tableletter();
                            %addtotoc(tabnum=Table &tablenum.&tableletter.,
                            caption=%quote(Summary of Time to End of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner));
                            %end;
                        %end;
                        %else %if &tableid. = T2 %then %do;
                            %addtotoc(tabnum=Table &tablenum.&tableletter.,
                            caption=%quote(Summary of Reasons for End of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));

                        %if &stratifybydp. = Y & %eval(&st.=1) %then %do;
                            %tableletter();
                            %addtotoc(tabnum=Table &tablenum.&tableletter.,
                            caption=%quote(Summary of Reasons for End of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner));
                            %end;
                        %end;
                        %else %if &tableid. = T3 & %eval(&st.=1) %then %do;

                            /*loop through each reason for censoring and within that - loop through stratificationorder*/
                            %do c = 1 %to %sysfunc(countw(&defaultcensororder., ' '));
                                %let reason = %scan(&defaultcensororder., &c.);
                                /*check if rows exist in table (censorreason parameter has already been applied in %censortables_createdata*/
                                data chktable;
                                    set &tablename.(where=(table_name="&reason."));
                                run;
                                %isdata(dataset=chktable);
                                %if %eval(&nobs.>0) %then %do;

                                /*set table letter counter - need to check # of stratifications requested for censor reason*/
                                proc sql noprint;
                                    select count(distinct stratificationorder) into: reasonstratificationorder
                                    from tablefile
                                    where dataset in ("&tablename.") and table = "&tableid" and findw(censorreason, "&reason.")>0;
                                quit;

                                %if %eval(&reasonstratificationorder. = 1) %then %let tablecount = 0;
                                %else %let tablecount = 1;

                                /*loop through each stratification*/
                                %do t3st = 1 %to &stratificationorder.;
                                    %let censorreasontable = N;
                                    data _null_;
                                        set tablefile(where=(dataset in ("&tablename.") and table = "T3" and stratificationorder = &t3st.));
                                        call symputx('tabletitle', tabletitle);
                                        /*check if censoring reason requested*/ 
                                        if findw(censorreason, "&reason.")>0 then call symputx('censorreasontable', 'Y');
                                    run;

                                    %if &censorreasontable. = Y %then %do;
                                    %tableletter();
                                    %addtotoc(tabnum=Table &tablenum.&tableletter.,
                                    caption=%quote(Summary of Time to End of &title. due to %bquote(&&&reason._label) for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));
                                    %end; /*censor reason requested*/
                                %end; /*loop through stratification*/

                                proc datasets nowarn noprint lib=work;
                                    delete chktable;
                                quit;

                                /*after each censor reason upnumber table*/
                                %let tablenum = %eval(&tablenum + 1);
                                %end; /*dataset exists*/
                             %end; /*censor reason loop*/
                        %end; /*T3*/
                    %end; /*loop through stratifications*/

                    /*if table = T1 or T2 - upnumber table*/
                    %if %sysfunc(prxmatch(m/T1|T2/i,&tableid.)) > 0 %then %do;
                    %let tablenum = %eval(&tablenum + 1);
                    %end;
                %end; /*underlying data exists*/
                %end; /*loop through each table*/
                %end; /*table requested*/
            %mend;
     
            %t1t2censortoc(tablename=t2followuptime, title=At-Risk Period);
            %t1t2censortoc(tablename=t&typenum.censor, title=Observable Data);
        %end; /*t1censor and t2censor tables*/
 

    /*********************************************************************************************/
    /* Type 4 summary tables                                                                     */
    /*********************************************************************************************/
	%if %str("&reporttype") = %str("T4L1") & %str("&tablelist") ne %str("") %then %do;
     
        %do tb = 1 %to %sysfunc(countw(&tablelist.));
            %let table = %scan(&tablelist., &tb);

            /*determine if table includes non-pregnant section*/;
            %let nonpreg = %str( );
            %let s=;
            data _null_;
                set tablefile(where=(table="&table"));
                if tablesubstrat in ("t4nopreg", "t4nopreggestwk") then do;
                    call symput('nonpreg', " and Matched Non-Pregnant Episodes ");
                    call symputx('s', "s");
                end;
            run;

            %if &stratifybydp = Y %then %let tablecount=1;
            %else %let tablecount=0;

            /*Overall*/
            %tableletter();
            %addtotoc(tabnum=Table &tablenum.&tableletter.,
                    %if &table. = T1 %then %do;
                    caption=%quote(Pregnant Episodes&nonpreg.with &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.));
                    %end;
                    %if &table. = T2 %then %do;
                    caption=%quote(&reporttitle. Episodes Among Pregnant&nonpreg.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted.));
                    %end;
                    %if &table. = T3 %then %do;
                    caption=%quote(&reporttitle. Codes Among Pregnant&nonpreg.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., without Adjusting for Same-Day Dispensings));
                    %end;
                    %if &table. = T4 %then %do;
                    caption=%quote(&reporttitle. Codes Among Pregnant&nonpreg.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., Adjusting for Same-Day Dispensings));
                    %end;
                    %if &table. = T5 %then %do;
                    caption=%quote(Pregnant Episodes&nonpreg.with &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Gestational Week));
                    %end;
                    %if &table. = T6 %then %do;
                    caption=%quote(&reporttitle. Episodes Among Pregnant&nonpreg.Cohort&s. in the &database. from &startdateformatted. to &enddateformatted., by Gestational Week));
                    %end;

            /*By DP*/
            %if &stratifybydp. = Y %then %do;    
                %do dps = 1 %to %eval(&num_dp.);
                    %let maskedID = %scan(&masked_dplist,&dps); 
                    %tableletter();
                    %addtotoc(tabnum=Table &tablenum.&tableletter.,
                        %if &table. = T1 %then %do;
                        caption=%quote(Pregnant Episodes&nonpreg.with &reporttitle. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted.));
                        %end;
                        %if &table. = T2 %then %do;
                        caption=%quote(&reporttitle. Episodes Among Pregnant&nonpreg.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted.));
                        %end;
                        %if &table. = T3 %then %do;
                        caption=%quote(&reporttitle. Codes Among Pregnant&nonpreg.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., without Adjusting for Same-Day Dispensings));
                        %end;
                        %if &table. = T4 %then %do;
                        caption=%quote(&reporttitle. Codes Among Pregnant&nonpreg.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., Adjusting for Same-Day Dispensings));
                        %end;             
                        %if &table. = T5 %then %do;
                        caption=%quote(Pregnant Episodes&nonpreg.with &reporttitle. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., by Gestational Week));
                        %end;
                        %if &table. = T6 %then %do;
                        caption=%quote(&reporttitle. Episodes Among Pregnant&nonpreg.Cohort&s. in the &database. for &maskedid. from &startdateformatted. to &enddateformatted., by Gestational Week));
                        %end;
                 %end;
            %end;
            %let tablenum = %eval(&tablenum + 1);
        %end; /*loop through each table*/
    %end; /*type 4 summary tables*/

    /*********************************************************************************************/
    /* Type 5 summary tables                                                                     */
    /*********************************************************************************************/
	%if %str("&reporttype") = %str("T5") %then %do;

        /*****************************************************************************************/
        /* Type 5 Tables T1-T13, T18-T22                                                         */
        /*****************************************************************************************/

        /*Example order of tables:
          2a: Categorical - overall
          2b: Continuous - all
          2c: Categorical - by age group
          2d: Continuous - by age group */
 
        %macro t5toc(cattableid=, disttableid=, cattitle=, disttitle=);

            /*if both categorical and continuous tables specified, then need to ascertain master order between both tables*/
            %if %str("&cattableid.") ne %str("") & %str("&disttableid.") ne %str("") %then %do;
                /*Because a user can select different stratifications for each table need to ascertain a master order from tablefile regardless of whether includeinreport = Y*/
                /*if user excludes includeinreport = N from file, order may not match SOC standard order of operations */
                proc sort data=input.&tablefile.(keep=table tablesub where=(table in ("&cattableid","&disttableid"))) out=_temptablefile;
                    by table;
                run;
				
                data _temptablefile;
                    set _temptablefile;
                    by table;
                    length order 3;
                    if first.table then order = 1;
                    else order = order+1;
                    retain order;
                run;

                proc sort data=_temptablefile nodupkey;
                    by tablesub;
                run;
				
                proc sort data=tablefile(keep=table tablesub stratificationorder tabletitle) out=_temptablefile1;
                    by tablesub; 
                run;

                *create dataset that maps categorical and continuous tables;
                data _tempmap;
                    merge _temptablefile
                          _temptablefile1(rename=table=cattable rename=stratificationorder=catstratificationorder where=(cattable="&cattableid"))
                          _temptablefile1(rename=table=disttable rename=stratificationorder=diststratificationorder where=(disttable="&disttableid"));
                    by tablesub;
                    if missing(catstratificationorder) &  missing(diststratificationorder) then delete;
                run;

                proc sort data=_tempmap;
                    by order ;
                run;
            %end;
            %else %do;
                data _tempmap;
                    set tablefile(keep=table tablesub stratificationorder tabletitle 
                                  where=(table in (%if %str("&cattableid.") ne %str("") %then %do; "&cattableid" %end;
                                                   %if %str("&disttableid.") ne %str("") %then %do; "&disttableid" %end;)));
                run;
            %end;

            /*Loop through each tablesub, determine whether to output categorical and/or continuous table*/
            %isdata(dataset=_tempmap);
            %let t5tableobs = &nobs.;
            %let tablecount=1;
            %do i = 1 %to %eval(&t5tableobs.);

                %let cattablestratorder = 0;
                %let disttablestratorder = 0;

                data _null_;
                    set _tempmap;
                    if _n_ = &i. then do;
                        if tablesub = 'overall' and "&stratifybydp." = "Y" then call symputx('tabletitle', ', by Data Partner');
                        else call symputx('tabletitle', tabletitle);
                        /*Both requested - determine whether to print both tables*/
                        %if %str("&cattableid.") ne %str("") & %str("&disttableid.") ne %str("") %then %do;
                            if missing(cattable) | missing(disttable) then call symputx('numtables', 1);
                            else call symputx('numtables', 2);

                            if missing(cattable)=0 then call symputx('cattablestratorder', catstratificationorder);
                            if missing(disttable)=0 then call symputx('disttablestratorder', diststratificationorder);
                        %end;
                        %else %do;
                            call symputx('numtables', 1);
                            /*determine which table*/
                            if table = "&cattableid" then call symputx('cattablestratorder', stratificationorder);
                            if table = "&disttableid" then call symputx('disttablestratorder', stratificationorder);
                        %end;
                    end;
                run;

                /*reset table letter counter if only 1 table*/
                %if %eval(&t5tableobs.=1) & %eval(&numtables.=1) %then %let tablecount=0;

                %if %eval(&cattablestratorder.>0) %then %do;
                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                caption=%bquote(&cattitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));
                %end;
                %if %eval(&disttablestratorder.>0) %then %do;
                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                caption=%bquote(&disttitle. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));
                %end;
            %end;

            /*Save the table of contents datasets for use during the Type 5 report output process*/
			%isdata(dataset=t5_tempmap);
			%if %eval(&nobs.>0) %then %do;
				data t5_tempmap;
				 set t5_tempmap _tempmap (in=a);
				  %if %varexist(_tempmap,stratificationorder) = 1 %then %do;
					  if a and stratificationorder ne . then do;
						 %if %str("&cattableid.") ne %str("") %then %do;
							 cattable="&cattableid";
							 catstratificationorder = stratificationorder;
						 %end;
						 %else %if %str("&disttableid.") ne %str("") %then %do;
							 disttable="&disttableid";
							 diststratificationorder = stratificationorder;
						 %end;
					  end;
				  %end;
				run; 
			%end;
			%else %do;
				/*dummy t5_tempmap file*/
				data t5_tempmap;
				 set _tempmap;
				  %if %varexist(_tempmap,stratificationorder) = 1 %then %do;
					  if stratificationorder ne . then do;
						 %if %str("&cattableid.") ne %str("") %then %do;
							 length cattable $3;
							 cattable="&cattableid";
							 catstratificationorder = stratificationorder;
						 %end;
						 %else %if %str("&disttableid.") ne %str("") %then %do;
							 length disttable $3;
							 disttable="&disttableid";
							 diststratificationorder = stratificationorder;
						 %end;
					  end;
				  %end;
				run; 
			%end;
			
            proc datasets nowarn noprint lib=work;
                delete _temp:;
            quit;

            %let tablenum = %eval(&tablenum+1);
        %mend;

        /*T1/T2 - Days Supplied per Dispensing*/
	    %if %sysfunc(prxmatch(m/T1\b|T2\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=%if %sysfunc(prxmatch(m/T1\b/i,&tablelist.)) > 0 %then %do; T1 %end;,
               disttableid=%if %sysfunc(prxmatch(m/T2\b/i,&tablelist.)) > 0 %then %do; T2 %end;,
               cattitle=Categorical Summary of Days Supplied per Dispensing,
               disttitle=Continuous Summary of Days Supplied per Dispensing); 
        %end;

        /*T3/T4 - Cumulative episode duration*/
    	%if %sysfunc(prxmatch(m/T3\b|T4\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=%if %sysfunc(prxmatch(m/T3\b/i,&tablelist.)) > 0 %then %do; T3 %end;,
               disttableid=%if %sysfunc(prxmatch(m/T4\b/i,&tablelist.)) > 0 %then %do; T4 %end;,
               cattitle=Categorical Summary of Patients%str(%') Cumulative Treatment Episode Durations,
               disttitle=Continuous Summary of Patients%str(%') Cumulative Treatment Episode Durations); 
    	%end;

    	/*T5/T6 - Episode duration - all episodes*/
        %if %sysfunc(prxmatch(m/T5\b|T6\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=%if %sysfunc(prxmatch(m/T5\b/i,&tablelist.)) > 0 %then %do; T5 %end;,
               disttableid=%if %sysfunc(prxmatch(m/T6\b/i,&tablelist.)) > 0 %then %do; T6 %end;,
               cattitle=Categorical Summary of All Treatment Episodes,
               disttitle=Continuous Summary of All Treatment Episodes); 
    	%end; 

    	/*T7/T8 - Episode duration - first episode*/
    	%if %sysfunc(prxmatch(m/T7\b|T8\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=%if %sysfunc(prxmatch(m/T7\b/i,&tablelist.)) > 0 %then %do; T7 %end;,
               disttableid=%if %sysfunc(prxmatch(m/T8\b/i,&tablelist.)) > 0 %then %do; T8 %end;,
               cattitle=Categorical Summary of First Treatment Episodes,
               disttitle=Continuous Summary of First Treatment Episodes); 
    	%end;

    	/*T9/T10 - Episode duration - second and subsequent episodes*/
    	%if %sysfunc(prxmatch(m/T9\b|T10\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=%if %sysfunc(prxmatch(m/T9\b/i,&tablelist.)) > 0 %then %do; T9 %end;,
               disttableid=%if %sysfunc(prxmatch(m/T10\b/i,&tablelist.)) > 0 %then %do; T10 %end;,
               cattitle=Categorical Summary of Second and Subsequent Treatment Episodes,
               disttitle=Continuous Summary of Second and Subsequent Treatment Episodes); 
    	%end;

    	/*T11 - All episode gaps*/
        %if %sysfunc(prxmatch(m/T11\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=,
               disttableid=T11,
               cattitle=,
               disttitle=Continuous Summary of All Treatment Episode Gaps); 
    	%end;
    	/*T12 - First episode gap*/
        %if %sysfunc(prxmatch(m/T12\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=,
               disttableid=T12,
               cattitle=,
               disttitle=Continuous Summary of First Treatment Episode Gaps); 
    	%end;
    	/*T13 - Second and subequent episode gaps*/
        %if %sysfunc(prxmatch(m/T13\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=,
               disttableid=T13,
               cattitle=,
               disttitle=Continuous Summary of Second and Subsequent Treatment Episode Gaps); 
    	%end;
    	/*T18 - Filled daily dose in each dispensing*/
        %if %sysfunc(prxmatch(m/T18\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=T18,
               disttableid=,
               cattitle=Summary of Filled Daily Dose in Each Dispensing,
               disttitle=); 
    	%end;
    	/*T19 - Average filled daily dose in each episode*/
        %if %sysfunc(prxmatch(m/T19\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=T19,
               disttableid=,
               cattitle=Summary of Average Filled Daily Dose in Each Treatment Episode,
               disttitle=); 
    	%end;
    	/*T20 - Average filled daily dose in first episode*/
        %if %sysfunc(prxmatch(m/T20\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=T20,
               disttableid=,
               cattitle=Summary of Average Filled Daily Dose in Each Patient%str(%')s First Valid Episode,
               disttitle=); 
    	%end;
    	/*T21 - Cumulative filled dose in each episode*/
        %if %sysfunc(prxmatch(m/T21\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=T21,
               disttableid=,
               cattitle=Summary of Cumulative Filled Dose in All Treatment Episodes,
               disttitle=); 
    	%end;
    	/*T22 - Cumulative filled dose in first episode*/
        %if %sysfunc(prxmatch(m/T22\b/i,&tablelist.)) > 0 %then %do;
        %t5toc(cattableid=T22,
               disttableid=,
               cattitle=Summary of Cumulative Filled Dose in Each Patient%str(%')s First Treatment Episode,
               disttitle=); 
    	%end;
	
        /*Additional variables for ordering Type 5 table report output*/		
        %isdata(dataset=t5_tempmap);
        %if %eval(&nobs.>0) %then %do;
    		data t5_tempmap;
    		 set t5_tempmap;
    		 length t5order 3;
    		 t5order=_n_;
    		run; 
    			
    		proc sort data = t5_tempmap;
    		by table t5order;
    		run;
    		
    		data t5_tempmap;
    		 set t5_tempmap;
    		 by table;
    		 length numtables tableorder 3;
    		 if first.table and last.table
    			%if %varexist(t5_tempmap,cattable) = 1 & %varexist(t5_tempmap,disttable) = 1 %then %do; and (cattable = '' or disttable = '') %end;
    		  then numtables=1;
    		 else numtables=2;
    		 retain tableorder;
    		 if first.table then tableorder=0;
    		 tableorder+1;
    		run; 
    			
    		proc sort data = t5_tempmap;
    		by t5order table;
    		run;
        %end;

        /*****************************************************************************************/
        /* Type 5 censor tables (T14-T17)                                                        */
        /*****************************************************************************************/
        %macro t5censortoc(tableid=, first=, dataset=);
            %if %sysfunc(prxmatch(m/T14\b|T16\b/i,&tableid.)) > 0 %then %do;
                /*counter for determining table letter*/
                %if &stratifybydp. = Y %then %let tablecount = 1;
                %else %let tablecount = 0;
                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                          caption=%quote(Summary of Reasons &first.Treatment Episodes Ended for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.));
                %if &stratifybydp. = Y %then %do;
                %tableletter();
                %addtotoc(tabnum=Table &tablenum.&tableletter.,
                          caption=%quote(Summary of Reasons &first.Treatment Episodes Ended for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner));
                %end;
                %let tablenum = %eval(&tablenum + 1);
            %end;

            %if %sysfunc(prxmatch(m/T15\b|T17\b/i,&tableid.)) > 0 %then %do;
                /*loop through each reason for censoring*/
                %do c = 1 %to %sysfunc(countw(&defaultcensororder., ' '));
                    %let reason = %scan(&defaultcensororder., &c.);
                    %let censorreasontable = N;

                    data _null_;
                        set tablefile(where=(dataset in ("t5censor") and table = "&tableid."));
                        /*check if censoring reason requested*/ 
                        if findw(censorreason, "&reason.")>0 then call symputx('censorreasontable', 'Y');
                    run;

                    %if &censorreasontable. = Y %then %do;
                    /*check if rows exist in table (censorreason parameter has already been applied in %censortables_createdata*/
                    data chktable;
                        set &dataset.(where=(table_name="&reason."));
                    run;
                    %isdata(dataset=chktable);
                    %if %eval(&nobs.>0) %then %do;
                        /*note - table is not stratified by DP*/
                        %addtotoc(tabnum=Table &tablenum.,
                                  caption=%quote(Summary of Episode Duration for &first.Treatment Episodes Ended due to %bquote(&&&reason._label) for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.));
                        %let tablenum = %eval(&tablenum + 1);
                    %end;
                    proc datasets nowarn noprint lib=work;
                        delete chktable;
                    quit;
                    %end;
                %end;
            %end;
        %mend;

        %if %sysfunc(prxmatch(m/T14\b/i,&tablelist.)) > 0 %then %do;
            %t5censortoc(tableid=T14, first=%str(First ), dataset=);
        %end;
        %if %sysfunc(prxmatch(m/T15\b/i,&tablelist.)) > 0 %then %do;
            %t5censortoc(tableid=T15, first=%str(First ), dataset=t5censor_first);
        %end;
        %if %sysfunc(prxmatch(m/T16\b/i,&tablelist.)) > 0 %then %do;
            %t5censortoc(tableid=T16, first=, dataset=);
        %end;
        %if %sysfunc(prxmatch(m/T17\b/i,&tablelist.)) > 0 %then %do;
            %t5censortoc(tableid=T17, first=, dataset=t5censor);
        %end;
     
    %end; /*type 5 tables*/

	/*********************************************************************************************/
    /* Type 6 tables                                                                      		 */
    /*********************************************************************************************/	
	%if %sysfunc(prxmatch(m/t6censor|t6plota|t6plotb/i,&tdatasetlist.)) > 0 %then %do;

        %macro t6toc(tableid=, title=);            
            %isdata(dataset=table&tableid.);
            %if %eval(&nobs.>0) %then %do;                        
                %let stratificationorder = 0;
                proc sql noprint;
                    select max(stratificationorder) into: stratificationorder
                    from tablefile(where=(table = "&tableid"));
                quit;

               	/*counter for determining table letter*/
               	%if %eval(&stratificationorder. = 1) & &stratifybydp. ne Y %then %let tablecount = 0;
               	%else %let tablecount = 1;

            	%do st = 1 %to &stratificationorder.;
                    data _null_;
                        set tablefile(where=(table = "&tableid" and stratificationorder = &st.));
                        call symputx('tabletitle', tabletitle);
                    run;
                 
                    %tableletter();                    
                    %addtotoc(tabnum=Table &tablenum.&tableletter.,

					%if &tableid. eq T8 or &tableid. eq T9 or &tableid. eq T10 %then %do;
                    	caption=%quote(Summary of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted.&tabletitle.));
					%end;
                    %if &stratifybydp. = Y & %eval(&st.=1) %then %do;
                        %tableletter();
                        %addtotoc(tabnum=Table &tablenum.&tableletter.,

						%if &tableid. eq T8 or &tableid. eq T9 or &tableid. eq T10 %then %do;
                        	caption=%quote(Summary of &title. for &reporttitle. in the &database. from &startdateformatted. to &enddateformatted., by Data Partner));
						%end;
                    %end;                    			
                %end; /*loop through stratifications*/
                
                %let tablenum = %eval(&tablenum + 1);                
            %end; /*underlying data exists*/
           
        %mend t6toc;
 
        %t6toc(tableid=T8, title=Episode Duration by Reason Episodes Ended);
        %t6toc(tableid=T9, title=Time to First Switch or Episode End);
		%t6toc(tableid=T10, title=Time to Second Switch or Episode End);
    %end; /*type 6 tables*/
     
    /*********************************************************************************************/
    /*   Code Distribution Tables                                                                */
    /*********************************************************************************************/ 
    %if &output_code_distribution. eq Y %then %do;

    /* This macros output a specific distribution type (EXP or HOI) entries in the table of content */
	%macro codedistribution_type_toc(distindextype=);
        /* Compute group label to display in title */
		%let grouplabel=;
		%isdata(dataset=labelfile);
    	%if %eval(&nobs>0) %then %do;
			proc sql noprint;
			select label into :grouplabel trimmed from labelfile
			where lower(group)="&group." and runid = "&runid" and
			%if &distindextype. eq exp %then %do;
				lower(labeltype)="grouplabel";
			%end;
			%else %do;
				lower(labeltype)="outcomelabel";
			%end;
			quit;
		%end;

		%if %str("&grouplabel.") eq %str("") %then %let grouplabel = %trim(&group.);

		/* Full Code Distribution Table */
		%tableletter();
		%addtotoc(tabnum=Table &tablenum.&tableletter.,
                  caption=%quote(Full Code Distribution of &grouplabel. in the &database. from &startdateformatted. to &enddateformatted.));

		/* Total Code Counts Table */
		%tableletter();
		%addtotoc(tabnum=Table &tablenum.&tableletter.,
                  caption=%quote(Total Code Counts of &grouplabel. in the &database. from &startdateformatted. to &enddateformatted.));
	%mend codedistribution_type_toc; 

	/* reset counter to reset table letter */
	%let tablecount=1;
    
	proc sql noprint;
	select count(*) into :numgroupscodedist trimmed 
	from GroupsDist;
	quit;
	
    %do loopcount = 1 %to &numgroupscodedist.; 

		%let codedistexp = N;
		%let codedisthoi = N;

        data _null_;
            set GroupsDist;
			if &loopcount. = _N_;
            call symputx('runid', runid);
            call symputx('group', group);			
            if index(upcase(codedist), "EXP") > 0 then call symputx('codedistexp', 'Y');
			if index(upcase(codedist), "HOI") > 0 then call symputx('codedisthoi', 'Y');
        run;

		%if &codedistexp. eq Y %then %do;
			* Defensive: make sure the requested data is available;
			%let obscount=0;

			proc sql noprint;
			select count(*) into :obscount from codedistdata
			where lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "exp";
			quit;

			%if %eval(&obscount. > 0) %then %codedistribution_type_toc(distindextype=exp);
		%end;
		%if &codedisthoi. eq Y %then %do;
			* Defensive: make sure the requested data is available;
			%let obscount=0;

			proc sql noprint;
			select count(*) into :obscount from codedistdata
			where lower(group) = "&group." and runid = "&runid" and lower(distindextype) = "hoi";
			quit;

			%if %eval(&obscount. > 0) %then %codedistribution_type_toc(distindextype=hoi);
		%end;
				
	%end; *numgroupscodedist;
	%let tablenum = %eval(&tablenum + 1);
    %end;

    /*********************************************************************************************/
    /* Attrition table                                                                           */
    /*********************************************************************************************/
	
    /* reset counter to reset table letter */
    %let tablecount=1;

    %do j = %eval(&look_start.) %to %eval(&look_end.);

        %if %index(&reporttype,L2) %then %let attrperiodid = _&j;
        %isdata(dataset=agg_patient_attrition&attrperiodid);
        %let attrition_patient = &nobs;
        %isdata(dataset=agg_episode_attrition&attrperiodid);
        %let attrition_episode = &nobs;
	
        %if &attrition_patient > 0 or &attrition_episode > 0 %then %do;

    		%if (&attrition_patient > 0 and &attrition_episode = 0) or (&attrition_patient = 0 and &attrition_episode > 0) %then %do;
    			%let tablecount = 0;
    		%end;

    		%if &attrition_episode > 0 %then %do;
    			%tableletter();
    			%addtotoc(tabnum=Table &tablenum.&tableletter.,
    					  caption=%quote(Summary of Episode Level Cohort Attrition in the &database. from &startdateformatted. to &&enddate&j.formatted.));			 
    		%end; 

    		%if &attrition_patient > 0 %then %do;
    			%tableletter();	
    			%addtotoc(tabnum=Table &tablenum.&tableletter.,
    					  caption=%quote(Summary of Patient Level Cohort Attrition in the &database. from &startdateformatted. to &&enddate&j.formatted.));
    		%end;
    	
            %let tablenum = %eval(&tablenum + 1);

        %end;/* attrition_groups file */

    %end;/*periodid */ 


    /*** END TABLES **/

    /*********************************************************************************************/
    /*   Figures                                                                                 */
    /*********************************************************************************************/  

    %isdata(dataset=figurefile);
    %if %eval(&nobs.>0) %then %do; 

        %let figurenum = 1; /* Add +1 for additional figure types that are requested */
        %let tablecount = 1;

        /***************************************************************************************/
        /* L1 Figures                                                                          */
        /***************************************************************************************/
        %if %sysfunc(prxmatch(m/T1|T2L1|T5|T6/i,&reporttype.)) > 0 %then %do;

            /*utility macro to loop through groups*/
            %macro figuretoc(figure=, title =, dataset_name =);
			  
                %isdata(dataset=&dataset_name.);
                %if %eval(&nobs.>0) %then %do;

                /*number of distinct groups in figure to loop through determine whether to add letter to figure #*/
                proc sql noprint;
                    select distinct order
                    into :fgrouporderlist separated by ' '
                    from &dataset_name.
                    order by order;

                    select max(stratificationorder)
                    into :fstrataorder 
                    from figurefile
                    where figure="&figure";
                quit;

                %if %sysfunc(countw(&fgrouporderlist.)) = 1 and &fstrataorder = 1 %then %let tablecount = 0;
                %else %let tablecount = 1;

                %do g = 1 %to %sysfunc(countw(&fgrouporderlist.));
                    %let order = %scan(&fgrouporderlist., &g.);
                    %let grouplabel = ;

                    %do f = 1 %to &fstrataorder;

					%let figuretitle = "";
		            data _null_;
                      set figurefile(where=(figure = "&figure" and stratificationorder = &f));
                      call symputx('figuretitle', figuretitle);
                    run;

                    data _null_;
                        set &dataset_name.(where=(order = &order.));
                        if _n_ = 1 then do;
                        call symputx('grouplabel', grouplabel);
                        /* Assign competing risk label */
                        %if &reporttype = T6 and %sysfunc(prxmatch(m/F8|F9/i,&figure)) %then %do;
                        call symputx('competingrisklabel',vlabel(competingrisk));
                        %end;
                        end;
                    run;

                    /* Unmask title for T6 F8 and F9 figures to resolve competing risk macro variable */
                    %if &reporttype = T6 and %sysfunc(prxmatch(m/F8|F9/i,&figure)) %then %let title = %unquote(&title);

                    %tableletter();	
            		%addtotoc(tabnum=Figure &figurenum.&tableletter.,
            				  caption=%quote(&title. &grouplabel. in the &database. from &startdateformatted. to &enddateformatted.&figuretitle.));
                    %end;
                %end; /*loop through each figure*/
                %let figurenum = %eval(&figurenum.+1); 
                %end; /*figure dataset exists*/
            %mend;

            /**********************************************************************************************
             T1: 1 figure: 
                1) F1: t1censor = Reasons for End of Observable Data by Group (1-CDF) - 1 figure per group
            /**********************************************************************************************/
            %if &reporttype. = T1 %then %do;
                %figuretoc(figure=F1, title =Reasons for End of Observable Data Among, dataset_name = figureF1);
            %end; /*T1*/

            /**********************************************************************************************
             T2L1: 3 figures:
                1) F1: t2followuptime = Kaplan-Meier Estimate of Event of Interest Not Occurring
                2) F2: t2followuptime = Reasons for End of Follow-Up by Group (1-CDF)
                3) F3: t2censor = Reasons for End of Observable Data by Group (1-CDF)
            /**********************************************************************************************/
            %if &reporttype. = T2L1 %then %do;

                /*F1: 1 figure per report*/
                %isdata(dataset=figuref1);
                %if %eval(&nobs.>0) %then %do;
                	%addtotoc(tabnum=Figure &figurenum.,
                			  caption=%quote(Kaplan-Meier Estimate of Event of Interest Not Occurring in the &database. from &startdateformatted. to &enddateformatted.));
                    %let figurenum = %eval(&figurenum.+1); 
                %end;

                /*F2: 1 figure per group*/
                %if %sysfunc(prxmatch(m/F2/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F2, title =Reasons for End of Follow-Up Among, dataset_name = figureF2);
                %end; /*figuref2*/

                /*F3: 1 figure per group*/
                %if %sysfunc(prxmatch(m/F3/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F3, title =Reasons for End of Observable Data Among, dataset_name = figureF3);
                %end; /*figuref3*/
            %end; /*T2L1*/

            /**********************************************************************************************
             T5: 5 figures:
                1) F1: Patient Entry into Study by Month
                2) F2: Number of Prescription Dispensings in Patients First Episodes by Month
                3) F3: Total Days Supply in Patients' First Episodes by Month
                4) F4: t5censor = Reasons for End of First Treatment Episode by Group
                5) F5: t5censor = End of First Treatment Episode due to [Censoring Reason] by Group 
            /**********************************************************************************************/
			
            %if &reporttype. = T5 %then %do;
			  /* F1 */
			  %if %sysfunc(prxmatch(m/\bF1\b/i,&figurelist.)) > 0 %then %do;
			    %figuretoc(figure=F1, title =Patient Entry into Study by Month for, dataset_name = figure123);
			  %end;

			  /* F2 */
		      %if %sysfunc(prxmatch(m/F2/i,&figurelist.)) > 0 %then %do;
			    %figuretoc(figure=F2, title =Number of Prescription Dispensings in Patients%str(%') First Episodes by Month Patient Entered into Study for,
                           dataset_name = figure123);
		      %end;

			  /* F3 */
		      %if %sysfunc(prxmatch(m/F3/i,&figurelist.)) > 0 %then %do;
			    %figuretoc(figure=F3, title =Total Days Supply in Patients%str(%') First Episodes by Month Patient Entered into Study for,
                           dataset_name = figure123);
		      %end;

              /*F4: 1 figure per group*/
              %if %sysfunc(prxmatch(m/F4/i,&figurelist.)) > 0 %then %do;
                %figuretoc(figure=F4, title =Reasons for End of First Treatment Episode Among, dataset_name = figureF4);
              %end; /*figuref4*/

                /*F5: 1 figure per report*/
                    /*Censor reason*/
			  %if %sysfunc(prxmatch(m/F5/i,&figurelist.)) > 0 %then %do;
			   %isdata(dataset= figuref5);
			   %if %eval(&nobs.>0) %then %do;
                data _null_;
                  set figurefile(where=(figure="F5"));
                  call symputx('censordisplay', censordisplay);
                run;
                %addtotoc(tabnum=Figure &figurenum, 
                          caption =%quote(End of First Treatment Episode due to &&&censordisplay._label in the &database. from &startdateformatted. to &enddateformatted.));
                %let figurenum = %eval(&figurenum.+1);
			  %end;
             %end;  	
             
            %end; /*T5*/

            /**********************************************************************************************
             T6: 9 figures:
                1) F1 (not yet implemented)
                2) F2 (not yet implemented)
                3) F3 (not yet implemented)
                4) F4: t6plota = Kaplan-Meier Estimate of First Switch Not Occurring
                5) F5: t6plotb = Kaplan-Meier Estimate of Second Switch Not Occurring
                6) F6: t6plota = Reasons for Censoring at First Switch Evaluation by Analysisgrp
                7) F7: t6plotb = Reasons for Censoring at Second Switch Evaluation by Analysisgrp
                8) F8: t6plota = Cumulative Incidence of First Switch Against Competing Risk by Analysisgrp
                9) F9: t6plotb = Cumulative Incidence of Second Switch Against Competing Risk by Analysisgrp
            /***********************************************************************************************/
            %if &reporttype. = T6 %then %do;
                /*F4 - F7: 1 figure per group*/
                %if %sysfunc(prxmatch(m/F4/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F4, title =Kaplan-Meier Estimate of First Switch Not Occurring Among, dataset_name = figureF4);
                %end; /*figuref4*/
                %if %sysfunc(prxmatch(m/F5/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F5, title =Kaplan-Meier Estimate of Second Switch Not Occurring Among, dataset_name = figureF5);
                %end; /*figuref5*/
                %if %sysfunc(prxmatch(m/F6/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F6, title =Reasons for Censoring at First Switch Evaluation Among, dataset_name = figureF6);
                %end; /*figuref6*/
                %if %sysfunc(prxmatch(m/F7/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F7, title =Reasons for Censoring at Second Switch Evaluation Among, dataset_name = figureF7);
                %end; /*figuref7*/
                %if %sysfunc(prxmatch(m/F8/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F8, title =%nrstr(Cumulative Incidence of First Switch Accounting for &competingrisklabel. as a Competing Risk Among), dataset_name = figureF8);
                %end; /*figuref8*/
                %if %sysfunc(prxmatch(m/F9/i,&figurelist.)) > 0 %then %do;
                    %figuretoc(figure=F9, title =%nrstr(Cumulative Incidence of Second Switch Accounting for &competingrisklabel. as a Competing Risk Among), dataset_name = figureF9);
                %end; /*figuref9*/
            %end; /*T6*/

        %end; /*L1 figures*/

        /***************************************************************************************/
        /* L2 Figures                                                                          */
        /***************************************************************************************/
        %if %sysfunc(prxmatch(m/T2L2|T4L2/i,&reporttype.)) > 0 %then %do;

	        /*F1: PS distribution histograms*/
	        %if %sysfunc(prxmatch(m/F1/i,&figurelist.)) > 0 %then %do;				

				%do j = %eval(&look_start) %to %eval(&look_end);
					%do loopcount = 1 %to &numl2comparisons.; 

						data _NULL_;
			            set l2comparisonfile(where=(order=&loopcount.));
			            call symputx('runid', runid);
			            call symputx('analysisgrp', analysisgrp);
			            call symputx('OutputPSDistribution', OutputPSDistribution);
			       		run;

					  %if &OutputPSDistribution. = Y %then %do;

						%isdata(dataset=labelfile);
						%let grouplabel=&analysisgrp.;

					    %if %eval(&nobs>0) %then %do;
						  data _NULL_;
						  set labelfile(where=(lowcase(labeltype)='grouplabel'));
						  if group="&analysisgrp." and runid = "&runid";
			              call symputx('grouplabel', Label);
						  run;
						  %put &grouplabel.;
						%end;

						%let andafter=;

						proc sql noprint;
			            select strip(file) into: psfile
			            from pscs_masterinputs
			            where analysisgrp = "&analysisgrp." and missing(subgroup);
				        quit;

	                    %if &psfile. = psmatchfile | &psfile. = stratificationfile | &psfile. = iptwfile %then %do;
					      data _null_; 
		                  set pscs_masterinputs (where=(lowcase(analysisgrp)="&analysisgrp." and missing(subgroup)));
		                    call symputx("psestimategrp", lowcase(psestimategrp));
		                        %if &psfile. = psmatchfile  %then %do;
		                            if upcase(ratio) = "F" then do;
									    call symput("andafter", " and After");
		                            end;
		                        %end;
		                        %if &psfile = iptwfile %then %do;
								   call symput("andafter", " and After");
		                        %end;
								%else %if &psfile = stratificationfile %then %do;
								   if upcase(strataweight) in ("ATE", "ATT") then do;
								     call symput("andafter", " and After");
								   end;
		                        %end;
		                  run; 

			            
						%let numsubgroups=0;
						%let subgroup=;
						%let subgroupcat=;
						%let subgrouptitle=;

						proc sort nodupkey data=Pscs_masterinputs(where=(analysisgrp="&analysisgrp." and runid="&runid." and not missing(subgroup))) 
											   out=_subgroups(keep=subgroup subgroupcat subgrouporder subgroupcatorder combinedlabel);
						by subgrouporder subgroupcatorder;
						run;

						proc sql noprint;
						select count(*) into :numsubgroups from _subgroups;
						quit;

						%do sub=0 %to &numsubgroups.;

							%let max_eoi=0;
							%let max_ref=0;
							
							%if &sub. > 0 %then %do;
								data _null_;
								set _subgroups;
								if _N_=&sub.;		
								call symputx("SubGroup",lowcase(strip(subgroup)));
						    	call symputx("SubgroupCat",upcase(strip(subgroupcat)));	
								call symputx("subgrouptitle",combinedlabel);
								run;			

								proc sql noprint;
								select max(_eoi), max(_ref) into :max_eoi, :max_ref
								from histogram_&j. (where=(runid="&runid." and order="&loopcount." and subgroup="&subgroup." and subgroupcat="&subgroupcat."));
							quit;	
							%end;
							%else %do;
								proc sql noprint;
									select max(_eoi), max(_ref) into :max_eoi, :max_ref
									from histogram_&j. (where=(runid="&runid." and order="&loopcount." and subgroup="" and subgroupcat=""));
								quit;
							%end;
							
							%if &max_eoi. > 0 and &max_ref. > 0 %then %do;
								%if &numsubgroups.=0 %then %let tablecount = 0;								
				                %tableletter();
				                %addtotoc(tabnum=Figure &figurenum.&tableletter.,
				                caption=%quote(Histograms Depicting Propensity Score Distributions Before&andafter Adjustment for &grouplabel. in the &database. from &startdateformatted. to &&enddate&j.formatted.&subgrouptitle.))
							%end;
							%else %do;
								 %put WARNING: (Sentinel) Insufficient data to produce histogram for analysisgrp=&analysisgrp., subgroup=&SubGroup., subgroupcat=&SubgroupCat.. Histogram will not be produced.; 
							%end;
			            %end; /* loop subgroups */

						%let figurenum = %eval(&figurenum.+1); 
						%let tablecount = 1;
						%let tableletter =a;

					 %end; /*psfile*/
				    %end; /* OutputPSDistribution */					
				   %end; /* loop comparisons */
				%end; /* loop periods */			 
	        %end; /*Histograms*/

	        /*F2: Forest Plots*/
	        %if %sysfunc(prxmatch(m/F2/i,&figurelist.)) > 0 and %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do;
	            %if %sysfunc(prxmatch(m/T2L2/i,&reporttype.)) > 0 %then %let ForestRatioTitle = Hazard Ratios (HR);
	            %else %let ForestRatioTitle = Risk Ratios (RR);

				%let tableletter=a;
				%let tablecount = 1;

	            %do j = %eval(&look_start) %to %eval(&look_end);
	                %do plot = 1 %to 7;
	                    %let forest_title = ;
	                    data _null_;
	                    set forest_&j(where=(plotorder=&plot));
	                      call symputx("forest_title",forest_title);
	                    run;

	                    %if %length(&forest_title) > 0 %then %do;
	                    %tableletter();
	                    %addtotoc(tabnum=Figure &figurenum.&tableletter.,
	                    caption=%quote(Forest Plot of &ForestRatioTitle and 95% Confidence Intervals (CI) for &forest_title in the &database. from &startdateformatted. to &&enddate&j.formatted.))
	                    %end; /* Forest title exists */
	                %end; /* loop plots */
	            %end; /* loop periods */

                %let figurenum = %eval(&figurenum.+1); 
	        %end; /*Forest plots */

            /*F3-F5: KM Plots - Type 2 only*/
            %if &reporttype. = T2L2 & %sysfunc(prxmatch(m/F3|F4|F5/i,&figurelist.)) > 0 and %sysfunc(exist(input.&treeaggfile.)) eq 0 %then %do;

                *reset tablecount; 
				%let tablecount = 1;

				%let F3nobs = 0;
				%let F4nobs = 0;
				%let F5nobs = 0;
				
				%macro survivalcurvestoc(aggregated=, dpinparenthesis=, dpwhere=);		                	                    
	                        /*assign labels*/
	                        data _null_; 
	                            set pscs_masterinputs(where=(analysisgrp="&analysisgrp." and missing(subgroup)));
	                            call symputx("psestimategrp", lowcase(psestimategrp));
	                        run;
	                        data _null_; 
	                            set infolder.&&&runid._psestimationfile(where=(lowcase(psestimategrp)="&psestimategrp."));
	                            call symputx('GRP1', eoi);
	                            call symputx('GRP0', ref); 
	                        run;

	                        %let outcomelabel = Event of Interest;
	                        %let eoilabel = &grp1.;
	                        %let reflabel = &grp0.;
							%let AnalysisGroupLabel = &analysisgrp.;
							%let PSEstimateGroupLabel = &psestimategrp.;

	                        %isdata(dataset=labelfile);
	                        %if %eval(&nobs.>0) %then %do;
	                            data _null_;
	                                set labelfile(in=a where=(group="&analysisgrp" and runid = "&runid" and labeltype = "outcomelabel"))
	                                    labelfile(in=b where=(group="&grp1." and runid = "&runid." and labeltype = "grouplabel"))
	                                    labelfile(in=c where=(group="&grp0." and runid = "&runid." and labeltype = "grouplabel"))
										labelfile(in=d where=(group="&analysisgrp" and runid = "&runid" and labeltype = "grouplabel"))
										labelfile(in=e where=(group="&psestimategrp" and runid = "&runid" and labeltype = "grouplabel"))
									;
	                                if a then call symputx('outcomelabel', label);
	                                if b then call symputx('eoilabel', label);
	                                if c then call symputx('reflabel', label);
									if d then call symputx('AnalysisGroupLabel', label);
									if e then call symputx('PSEstimateGroupLabel', label);
	                            run;
	                        %end;         

							%let numsubgroups=0;
							%let subgroup=;
							%let subgroupcat=;
							%let subgrouptitle=;

							proc sort nodupkey data=Pscs_masterinputs(where=(analysisgrp="&analysisgrp." and runid="&runid." and not missing(subgroup))) 
												   out=_subgroups(keep=subgroup subgroupcat subgrouporder subgroupcatorder combinedlabel);
							by subgrouporder subgroupcatorder;
							run;

							proc sql noprint;
							select count(*) into :numsubgroups from _subgroups;
							quit;

							%do sub=0 %to &numsubgroups.;
								
								%if &sub. > 0 %then %do;
									data _null_;
									set _subgroups;
									if _N_=&sub.;					
									call symputx("SubGroup",lowcase(strip(subgroup)));	
									call symputx("SubgroupCat",upcase(strip(subgroupcat)));										
									call symputx("subgrouptitle",combinedlabel);
									run;

								%end;			 

		                        /*F3*/								
		                        %isdata(dataset=figureF3_analysis&loopcount._&j.);
								%let F3nobs = &nobs.;
		                        %if %eval(&nobs.>0) %then %do;
									%let max_day=0;
									
									proc sql noprint;
										select max(day) into :max_day
										from figureF3_analysis&loopcount._&j. 
										where subgroup="&subgroup." and subgroupcat="&subgroupcat." and dpidsiteid="&dpwhere";
									quit;

									%if &max_day. > 0 %then %do;
				                        %tableletter();	
				                    	%addtotoc(tabnum=Figure &figurenum.&tableletter.,
				                    			  caption=%quote(&aggregated.Unadjusted Kaplan-Meier Estimate and 95% Confidence Interval of &outcomelabel. Not Occurring Among &AnalysisGroupLabel.&dpinparenthesis. from the Whole Population in the &database. from &startdateformatted. to &&enddate&j.formatted.&subgrouptitle.));
									%end;
									%else %do;
										 %put WARNING: (Sentinel) Insufficient data to produce unadjusted Kaplan-Meier estimate for analysisgrp=&analysisgrp., subgroup=&SubGroup., subgroupcat=&SubgroupCat.. KM curves will not be produced.; 
									%end;
		                        %end;
		                        /*F4*/
		                        %isdata(dataset=figureF4_analysis&loopcount._&j.);
								%let F4nobs = &nobs.;
		                        %if %eval(&nobs.>0) %then %do;
									%let max_day=0;
									
									proc sql noprint;
										select max(day) into :max_day
										from figureF4_analysis&loopcount._&j. 
										where subgroup="&subgroup." and subgroupcat="&subgroupcat." and dpidsiteid="&dpwhere";
									quit;

									%if &pscsfile. = psmatchfile %then %let pop=Conditional Matched Population after;
									%else %if &pscsfile. = stratificationfile | &pscsfile. = iptwfile %then %let pop=Weighted Population after;

									%if &max_day. > 0 %then %do;
										%if &kmrefpop. = unweighted %then %let cititle=%str( and 95% Confidence Interval);
										%else %let cititle=; 

				                        %tableletter();	
				                    	%addtotoc(tabnum=Figure &figurenum.&tableletter.,
				                    			  caption=%quote(&aggregated.Adjusted Kaplan-Meier Estimate&cititle. of &outcomelabel. Not Occurring Among &AnalysisGroupLabel.&dpinparenthesis. from the &pop. &PSEstimateGroupLabel. in the &database. from &startdateformatted. to &&enddate&j.formatted.&subgrouptitle.));
									%end;
									%else %do;
										 %put WARNING: (Sentinel) Insufficient data to produce conditional Kaplan-Meier estimate for analysisgrp=&analysisgrp., subgroup=&SubGroup., subgroupcat=&SubgroupCat.. KM curves will not be produced.; 
									%end;
		                        %end;
		                        /*F5*/
		                        %isdata(dataset=figureF5_analysis&loopcount._&j.);
								%let F5nobs = &nobs.;
		                        %if %eval(&nobs.>0) %then %do;
									%let max_day=0;
									
									proc sql noprint;
										select max(day) into :max_day
										from figureF5_analysis&loopcount._&j. 
										where subgroup="&subgroup." and subgroupcat="&subgroupcat." and dpidsiteid="&dpwhere";
									quit;

									%let pop=Unconditional Matched Population after;

									%if &max_day. > 0 %then %do;
				                        %tableletter();	
				                    	%addtotoc(tabnum=Figure &figurenum.&tableletter.,
				                    			  caption=%quote(&aggregated.Adjusted Kaplan-Meier Estimate and 95% Confidence Interval of &outcomelabel. Not Occurring Among &AnalysisGroupLabel.&dpinparenthesis. from the &pop. &PSEstimateGroupLabel. in the &database. from &startdateformatted. to &&enddate&j.formatted.&subgrouptitle.));
									%end;
									%else %do;
										 %put WARNING: (Sentinel) Insufficient data to produce unconditional Kaplan-Meier estimate for analysisgrp=&analysisgrp., subgroup=&SubGroup., subgroupcat=&SubgroupCat.. KM curves will not be produced.; 
									%end;
		                        %end;

							%end; /*loop through numsubgroups */     																		
				%mend survivalcurvestoc;

				/*loop through each analysisgrp - dataset only exists if curve computed*/
				%do loopcount = 1 %to &numl2comparisons.; 
 
					data _null_;
                        set l2comparisonfile(where=(order=&loopcount.));
		                call symputx('runid', runid);
		                call symputx('analysisgrp', analysisgrp);
						call symputx('kmrefpop',kmrefpop);
                    run;

                    proc sql noprint;
                        select distinct strip(file) into: pscsfile trimmed
                        from pscs_masterinputs
                        where analysisgrp = "&analysisgrp." and runid = "&runid" and missing(subgroup);
                    quit;

                    %if &pscsfile. = psmatchfile | &pscsfile. = stratificationfile | &pscsfile. = iptwfile %then %do;

						/*loop through periodid*/
		                %do j = %eval(&look_start) %to %eval(&look_end);
							%survivalcurvestoc( %if %eval(&num_dp.)=1 %then %do;
					                            aggregated=,
					                            %end;
					                            %else %do;
					                            aggregated=%str(Aggregated ),
					                            %end;
												dpinparenthesis=, dpwhere=ALL);

							* Save number of observations for the aggregated curves for figurenum increment below;
							%let F3nobsALL=&F3nobs.;
							%let F4nobsALL=&F3nobs.;
							%let F5nobsALL=&F3nobs.;

							*Output separate table for each Data Partner - loop through each DP;
		                	%if &stratifybydp. = Y %then %do;    
			                    %do dps = 1 %to %eval(&num_dp.);
			        		        %let maskedID = %scan(&masked_dplist,&dps); 
			                        %survivalcurvestoc(aggregated=, dpinparenthesis=%str( (&maskedid.)), dpwhere=&maskedid.);
			                    %end;
		                	%end; /*DP stratification*/
		                %end; /*loop through periodid*/  

						/* if there is only 1 figure, rewrite figure # - this method is used instead of determining apriori b/c of 
                  	   	   the numerous permutations of situations that can lead to 1 figure */
						%let countkm = 0;
						proc sql noprint;
		                    select count(caption) into: countkm
		                    from tableofcontents
		                    where index(tabnum, "Figure &figurenum.")>0;
		                quit;

		                %if %eval(&countkm.)=1 %then %do;
		                    data tableofcontents;
		                        set tableofcontents;
		                        if index(tabnum, "Figure &figurenum.")>0 then do;
		                        tabnum = "Figure &figurenum.";
		                        end;
		                    run;
		                %end;   

						%if %eval(&F3nobsALL.>0) | %eval(&F4nobsALL.>0) | %eval(&F5nobsALL.>0) %then %do;
							%let figurenum = %eval(&figurenum.+1); 
							%let tablecount = 1;
							%let tableletter =a; 
						%end;

                    %end; /*PSmatch, stratification or IPTW*/
 				%end; /*loop through numl2comparisons */
            %end; /*KM plots*/
        %end; /*L2 figures*/
    %end; /* Figure file */


    /*****************/
    /* Appendices    */
    /*****************/

    /*Appendix A*/
	%if &produceappendixfileonly. = N %then %do;
    	%addtotoc(tabnum=Appendix A, caption=Dates of Available Data for Each Data Partner (DP) as of Request Distribution Date &datedistributed.);
	%end;

	/* The remaining appendices are created in appendix_driver.sas */
	
    /*********************/
    /* Remove empty rows */
    /*********************/
    data tableofcontents;
       set tableofcontents;
       if missing(tabnum)=0;
    run;

    %put =====> END MACRO: create_tableofcontents ;

%mend create_tableofcontents;