Resources

Documentation Example 3 for Template Modification

/****************************************************************/
/*          S A S   S A M P L E   L I B R A R Y                 */
/*                                                              */
/*    NAME: TEMPLT                                              */
/*   TITLE: Documentation Example 3 for Template Modification   */
/* PRODUCT: STAT                                                */
/*  SYSTEM: ALL                                                 */
/*    KEYS: graphics, ods                                       */
/*   PROCS:                                                     */
/*    DATA:                                                     */
/*                                                              */
/* SUPPORT: saswfk                UPDATE: July 25, 2011         */
/*     REF: ods graphics                                        */
/*    MISC:                                                     */
/*   NOTES: This sample provides the DATA step and PROC code    */
/*   from the chapter "ODS Graphics Template Modification."  It */
/*   does not provide most of the ODS statements and style      */
/*   changes that are in the chapter.  Rather, this sample      */
/*   provides code that can be run in one large batch to make   */
/*   all of the graphs in the chapter.  If destinations were    */
/*   repeatedly opened and closed, as in the chapter, then      */
/*   output would be lost and rewritten.  Note that you should  */
/*   not specify destination style changes without first        */
/*   closing a destination.  Changing the style of the output   */
/*   without first closing the destination will not work        */
/*   as you might expect.  Do not do the following:             */
/*                                                              */
/*      ODS HTML STYLE=STATISTICAL;                             */
/*      . . . code . . .                                        */
/*      ODS HTML STYLE=DEFAULT;                                 */
/*      . . . code . . .                                        */
/*      ODS HTML STYLE=ANALYSIS;                                */
/*      . . . code . . .                                        */
/*                                                              */
/*   Instead, do the following:                                 */
/*                                                              */
/*      ODS HTML STYLE=STATISTICAL;                             */
/*      . . . code . . .                                        */
/*      ODS HTML CLOSE;                                         */
/*      ODS HTML STYLE=DEFAULT;                                 */
/*      . . . code . . .                                        */
/*      ODS HTML CLOSE;                                         */
/*      ODS HTML STYLE=ANALYSIS;                                */
/*      . . . code . . .                                        */
/*      ODS HTML CLOSE;                                         */
/*                                                              */
/*   Note that several steps are commented out in this sample,  */
/*   because they create large volumes of output.  To run those */
/*   steps, remove the comments.                                */
/****************************************************************/
ods graphics on;
ods trace on;

proc lifetest data=sashelp.BMT plots=survival(cb=hw test);
   time T * Status(0);
   strata Group;
run;

ods trace off;
proc template;
   source Stat.Lifetest.Graphics.ProductLimitSurvival;
run;

proc template;
   define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
      dynamic NStrata xName plotAtRisk plotCensored plotCL plotHW plotEP labelCL
         labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
         classAtRisk plotBand plotTest GroupName yMin Transparency SecondTitle
         TestName pValue;
      BeginGraph;
         if (NSTRATA=1)
            if (EXISTS(STRATUMID))
               entrytitle "Kaplan-Meier Plot for " STRATUMID;
            else
               entrytitle "Kaplan-Meier Plot";
            endif;
            if (PLOTATRISK=1)
               entrytitle "with Number of Subjects at Risk" / textattrs=
                  GRAPHVALUETEXT;
            endif;
            layout overlay / xaxisopts=(shortlabel=XNAME offsetmin=.05
               linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
               tickvaluefitpolicy=XTICKVALFITPOL))
               yaxisopts=(label="Survival Probability" shortlabel ="Survival"
               linearopts=(viewmin=0 viewmax=1
                           tickvaluelist=(0 .2 .4 .6 .8 1.0)));
               if (PLOTHW=1 AND PLOTEP=0)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHCONFIDENCE name="HW"
                     legendlabel=LABELHW;
               endif;
               if (PLOTHW=0 AND PLOTEP=1)
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHCONFIDENCE
                     name="EP" legendlabel=LABELEP;
               endif;
               if (PLOTHW=1 AND PLOTEP=1)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHDATA1
                     datatransparency=.55 name="HW" legendlabel=LABELHW;
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHDATA2
                  datatransparency=.55 name="EP" legendlabel=LABELEP;
               endif;
               if (PLOTCL=1)
                  if (PLOTHW=1 OR PLOTEP=1)
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        modelname="Survival" display=(outline) outlineattrs=
                        GRAPHPREDICTIONLIMITS name="CL" legendlabel=LABELCL;
                  else
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        modelname="Survival" fillattrs=GRAPHCONFIDENCE
                        name="CL" legendlabel=LABELCL;
                  endif;
               endif;
                stepplot y=SURVIVAL x=TIME / name="Survival"
                  rolename=(_tip1=ATRISK _tip2=EVENT)
                  tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                  tip=(y x _tip1 _tip2) legendlabel="Survival";
               if (PLOTCENSORED=1)
                  scatterplot y=CENSORED x=TIME / markerattrs=(symbol=plus)
                     tiplabel=(y="Survival Probability")
                     name="Censored" legendlabel="Censored";
               endif;
               if (PLOTCL=1 OR PLOTHW=1 OR PLOTEP=1)
                  discretelegend "Censored" "CL" "HW" "EP" / location=outside
                     halign=center;
               else
                  if (PLOTCENSORED=1)
                     discretelegend "Censored" / location=inside autoalign=(
                        topright bottomleft);
                  endif;
               endif;
               if (PLOTATRISK=1)
                  innermargin / align=bottom;
                     blockplot x=TATRISK block=ATRISK / repeatedvalues=true
                        display=(label values) valuehalign=start
                        valuefitpolicy=truncate
                        labelposition=left labelattrs=GRAPHVALUETEXT valueattrs=
                        GRAPHDATATEXT (size=7pt) includemissingclass=false;
                  endinnermargin;
               endif;
            endlayout;
         else
               entrytitle "Kaplan-Meier Plot";
            if (EXISTS(SECONDTITLE))
               entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
            endif;
            layout overlay /
               xaxisopts=(shortlabel=XNAME offsetmin=.05
                          linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
                                      tickvaluefitpolicy= XTICKVALFITPOL))
               yaxisopts=(label="Survival Probability" shortlabel="Survival"
                          linearopts=(viewmin=0 viewmax=1
                                      tickvaluelist=(0 .2 .4 .6 .8 1.0)));
               if (PLOTHW)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME / group=
                     STRATUM index=STRATUMNUM modelname="Survival"
                     datatransparency=Transparency;
               endif;
               if (PLOTEP)
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME / group=
                     STRATUM index=STRATUMNUM modelname="Survival"
                     datatransparency=Transparency;
               endif;
               if (PLOTCL)
                  if (PLOTBAND)
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        group=STRATUM index=STRATUMNUM modelname="Survival"
                        display=(outline);
                  else
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        group=STRATUM index=STRATUMNUM modelname="Survival"
                        datatransparency=Transparency;
                  endif;
               endif;
               stepplot y=SURVIVAL x=TIME / group=STRATUM index=STRATUMNUM name=
                  "Survival" rolename=(_tip1=ATRISK _tip2=EVENT)
                  tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                  tip=(y x _tip1 _tip2);
               if (PLOTCENSORED)
                  scatterplot y=CENSORED x=TIME / group=STRATUM index=STRATUMNUM
                     tiplabel=(y="Survival Probability")
                     markerattrs=(symbol=plus);
               endif;
               if (PLOTATRISK=1)
                  innermargin / align=bottom;
                     blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
                        repeatedvalues=true display=(label values) valuehalign=
                        start valuefitpolicy=truncate labelposition=left
                        labelattrs=GRAPHVALUETEXT valueattrs=GRAPHDATATEXT(size=
                        7pt) includemissingclass=false;
                  endinnermargin;
               endif;
               DiscreteLegend "Survival" / title=GROUPNAME location=outside;
               if (PLOTCENSORED)
                  if (PLOTTEST)
                     layout gridded / rows=2 autoalign=(TOPRIGHT BOTTOMLEFT TOP
                        BOTTOM) border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        entry "+ Censored";
                        if (PVALUE < .0001)
                           entry TESTNAME " p " eval (PUT(PVALUE, PVALUE6.4));
                        else
                           entry TESTNAME " p=" eval (PUT(PVALUE, PVALUE6.4));
                        endif;
                     endlayout;
                  else
                     layout gridded / rows=1 autoalign=(TOPRIGHT BOTTOMLEFT TOP
                        BOTTOM) border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        entry "+ Censored";
                     endlayout;
                  endif;
               else
                  if (PLOTTEST)
                     layout gridded / rows=1 autoalign=(TOPRIGHT BOTTOMLEFT TOP
                        BOTTOM) border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        if (PVALUE < .0001)
                           entry TESTNAME " p " eval (PUT(PVALUE, PVALUE6.4));
                        else
                           entry TESTNAME " p=" eval (PUT(PVALUE, PVALUE6.4));
                        endif;
                     endlayout;
                  endif;
               endif;
            endlayout;
         endif;
      EndGraph;
   end;
run;

proc lifetest data=sashelp.BMT plots=survival(cb=hw test);
   time T * Status(0);
   strata Group;
run;

%let TitleText0 = METHOD " Survival Estimate";
%let TitleText1 = &titletext0 " for " STRATUMID;
%let TitleText2 = &titletext0 "s";
%let yOptions   = label="Survival Probability"
                  shortlabel="Survival"
                  linearopts=(viewmin=0 viewmax=1
                              tickvaluelist=(0 .2 .4 .6 .8 1.0));
%let xOptions   = shortlabel=XNAME
                  offsetmin=.05
                  linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
                              tickvaluefitpolicy=XTICKVALFITPOL);

proc template;
   define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
      dynamic NStrata xName plotAtRisk plotCensored plotCL plotHW plotEP labelCL
         labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
         classAtRisk plotBand plotTest GroupName yMin Transparency SecondTitle
         TestName pValue;
      BeginGraph;
         if (NSTRATA=1)
            if (EXISTS(STRATUMID))
               entrytitle &titletext1;
            else
               entrytitle &titletext0;
            endif;
            if (PLOTATRISK=1)
               entrytitle "with Number of Subjects at Risk" / textattrs=
                  GRAPHVALUETEXT;
            endif;
            layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
               if (PLOTHW=1 AND PLOTEP=0)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHCONFIDENCE name="HW"
                     legendlabel=LABELHW;
               endif;
               if (PLOTHW=0 AND PLOTEP=1)
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHCONFIDENCE name="EP"
                     legendlabel=LABELEP;
               endif;
               if (PLOTHW=1 AND PLOTEP=1)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHDATA1
                     datatransparency=.55 name="HW" legendlabel=LABELHW;
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
                     modelname="Survival" fillattrs=GRAPHDATA2
                     datatransparency=.55 name="EP" legendlabel=LABELEP;
               endif;
               if (PLOTCL=1)
                  if (PLOTHW=1 OR PLOTEP=1)
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        modelname="Survival" display=(outline) outlineattrs=
                        GRAPHPREDICTIONLIMITS name="CL" legendlabel=LABELCL;
                  else
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        modelname="Survival" fillattrs=GRAPHCONFIDENCE
                        name="CL" legendlabel=LABELCL;
                  endif;
               endif;
               stepplot y=SURVIVAL x=TIME / name="Survival"
                  rolename=(_tip1=ATRISK _tip2=EVENT)
                  tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                  tip=(x y _tip1 _tip2)
                  legendlabel="Survival";
               if (PLOTCENSORED=1)
                  scatterplot y=CENSORED x=TIME / markerattrs=(symbol=plus)
                     tiplabel=(y="Survival Probability")
                     name="Censored" legendlabel="Censored";
               endif;
               if (PLOTCL=1 OR PLOTHW=1 OR PLOTEP=1)
                  discretelegend "Censored" "CL" "HW" "EP" / location=outside
                     halign=center;
               else
                  if (PLOTCENSORED=1)
                     discretelegend "Censored" / location=inside autoalign=(
                        topright bottomleft);
                  endif;
               endif;
               if (PLOTATRISK=1)
                  innermargin / align=bottom;
                     blockplot x=TATRISK block=ATRISK / repeatedvalues=true
                        display=(label values) valuehalign=start
                        valuefitpolicy=truncate
                        labelposition=left labelattrs=GRAPHVALUETEXT
                        valueattrs= GRAPHDATATEXT (size=7pt)
                        includemissingclass=false;
                  endinnermargin;
               endif;
            endlayout;
         else
            entrytitle &titletext2;
            if (EXISTS(SECONDTITLE))
               entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
            endif;
            layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
               if (PLOTHW)
                  bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
                     group=STRATUM index=STRATUMNUM modelname="Survival"
                     datatransparency=Transparency;
               endif;
               if (PLOTEP)
                  bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
                     group=STRATUM index=STRATUMNUM modelname="Survival"
                     datatransparency=Transparency;
               endif;
               if (PLOTCL)
                  if (PLOTBAND)
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        group=STRATUM index=STRATUMNUM modelname="Survival"
                        display=(outline);
                  else
                     bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
                        group=STRATUM index=STRATUMNUM modelname="Survival"
                        datatransparency=Transparency;
                  endif;
               endif;
               stepplot y=SURVIVAL x=TIME / group=STRATUM index=STRATUMNUM
                  name="Survival" rolename=(_tip1=ATRISK _tip2=EVENT)
                  tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                  tip=(y x _tip1 _tip2);
               if (PLOTCENSORED)
                  scatterplot y=CENSORED x=TIME / group=STRATUM
                     index=STRATUMNUM tiplabel=(y="Survival Probability")
                     markerattrs=(symbol=plus);
               endif;
               if (PLOTATRISK=1)
                  innermargin / align=bottom;
                     blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
                        repeatedvalues=true display=(label values)
                        valuehalign=start valuefitpolicy=truncate
                        labelposition=left labelattrs=GRAPHVALUETEXT
                        valueattrs=GRAPHDATATEXT (size= 7pt)
                        includemissingclass=false;
                  endinnermargin;
               endif;
               DiscreteLegend "Survival" / title=GROUPNAME location=outside;
               if (PLOTCENSORED)
                  if (PLOTTEST)
                     layout gridded / rows=2 autoalign=(TOPRIGHT BOTTOMLEFT
                                                        TOP BOTTOM)
                        border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        entry "+ Censored";
                        if (PVALUE < .0001)
                           entry TESTNAME " p " eval(PUT(PVALUE, PVALUE6.4));
                        else
                           entry TESTNAME " p=" eval(PUT(PVALUE, PVALUE6.4));
                        endif;
                     endlayout;
                  else
                     layout gridded / rows=1 autoalign=(TOPRIGHT BOTTOMLEFT
                        TOP BOTTOM) border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        entry "+ Censored";
                     endlayout;
                  endif;
               else
                  if (PLOTTEST)
                     layout gridded / rows=1 autoalign=(TOPRIGHT BOTTOMLEFT TOP
                        BOTTOM) border=true BackgroundColor=GraphWalls:Color
                        Opaque=true;
                        if (PVALUE < .0001)
                           entry TESTNAME " p " eval (PUT(PVALUE, PVALUE6.4));
                        else
                           entry TESTNAME " p=" eval (PUT(PVALUE, PVALUE6.4));
                        endif;
                     endlayout;
                  endif;
               endif;
            endlayout;
         endif;
      EndGraph;
   end;
run;

%macro SurvivalTemplateRestore;

   %global TitleText0 TitleText1 TitleText2 yOptions xOptions tips
           tipl groups bandopts gridopts blockopts censored censorstr;

   %let TitleText0 = METHOD " Survival Estimate";
   %let TitleText1 = &titletext0 " for " STRATUMID;
   %let TitleText2 = &titletext0 "s";         /* plural: Survival Estimates */

   %let yOptions   = label="Survival Probability"
                     shortlabel="Survival"
                     linearopts=(viewmin=0 viewmax=1
                                 tickvaluelist=(0 .2 .4 .6 .8 1.0));

   %let xOptions   = shortlabel=XNAME
                     offsetmin=.05
                     linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
                                 tickvaluefitpolicy=XTICKVALFITPOL);

   %let tips       = rolename=(_tip1= ATRISK _tip2=EVENT)
                     tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                     tip=(x y _tip1 _tip2);
   %let tipl       = tiplabel=(y="Survival Probability");

   %let groups     = group=STRATUM index=STRATUMNUM;

   %let bandopts   = &groups modelname="Survival";

   %let gridopts   = autoalign=(TOPRIGHT BOTTOMLEFT TOP BOTTOM)
                     border=true BackgroundColor=GraphWalls:Color Opaque=true;

   %let blockopts  = repeatedvalues=true valuehalign=start
                     valuefitpolicy=truncate labelposition=left
                     labelattrs=GRAPHVALUETEXT includemissingclass=false
                     valueattrs=GRAPHDATATEXT(size=7pt);

   %let censored   = markerattrs=(symbol=plus);
   %let censorstr  = "+ Censored";
   %macro SurvivalTemplate;
      proc template;
         define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
         dynamic NStrata xName plotAtRisk plotCL plotHW plotEP labelCL
            %if %nrbquote(&censored) ne %then plotCensored;
            labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
            classAtRisk plotBand plotTest GroupName yMin Transparency
            SecondTitle TestName pValue;
            BeginGraph;

               if (NSTRATA=1)
                  if (EXISTS(STRATUMID))
                     entrytitle &titletext1;
                  else
                     entrytitle &titletext0;
                  endif;
                  if (PLOTATRISK=1)
                     entrytitle "with Number of Subjects at Risk" / textattrs=
                        GRAPHVALUETEXT;
                  endif;

                  layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                     %singlestratum
                  endlayout;

               else
                  entrytitle &titletext2;
                  if (EXISTS(SECONDTITLE))
                     entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
                  endif;

                  layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                     %multiplestrata
                  endlayout;

               endif;

            EndGraph;
         end;
      run;
   %mend;

   %macro entry_p;
      if (PVALUE < .0001)
         entry TESTNAME " p " eval (PUT(PVALUE, PVALUE6.4));
      else
         entry TESTNAME " p=" eval (PUT(PVALUE, PVALUE6.4));
      endif;
   %mend;

   %macro SingleStratum;
      if (PLOTHW=1 AND PLOTEP=0)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHCONFIDENCE
            name="HW" legendlabel=LABELHW;
      endif;
      if (PLOTHW=0 AND PLOTEP=1)
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHCONFIDENCE
            name="EP" legendlabel=LABELEP;
      endif;
      if (PLOTHW=1 AND PLOTEP=1)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHDATA1 datatransparency=.55
            name="HW" legendlabel=LABELHW;
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHDATA2
            datatransparency=.55 name="EP" legendlabel=LABELEP;
      endif;
      if (PLOTCL=1)
         if (PLOTHW=1 OR PLOTEP=1)
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
               modelname="Survival" display=(outline)
               outlineattrs=GRAPHPREDICTIONLIMITS name="CL" legendlabel=LABELCL;
         else
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
               modelname="Survival" fillattrs=GRAPHCONFIDENCE name="CL"
               legendlabel=LABELCL;
         endif;
      endif;

      stepplot y=SURVIVAL x=TIME / name="Survival" &tips legendlabel="Survival";

      if (PLOTCENSORED=1)
         scatterplot y=CENSORED x=TIME / &censored &tipl
            name="Censored" legendlabel="Censored";
      endif;

      if (PLOTCL=1 OR PLOTHW=1 OR PLOTEP=1)
         discretelegend "Censored" "CL" "HW" "EP" / location=outside
            halign=center;
      else
         if (PLOTCENSORED=1)
            discretelegend "Censored" / location=inside
                                        autoalign=(topright bottomleft);
         endif;
      endif;
      if (PLOTATRISK=1)
         innermargin / align=bottom;
            blockplot x=TATRISK block=ATRISK / display=(label values)
                                               &blockopts;
         endinnermargin;
      endif;
   %mend;

   %macro MultipleStrata;
     if (PLOTHW)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
      if (PLOTEP)
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
      if (PLOTCL)
         if (PLOTBAND)
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                     display=(outline);
         else
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                     datatransparency=Transparency;
         endif;
      endif;

      stepplot y=SURVIVAL x=TIME / &groups name="Survival" &tips;

      if (PLOTCENSORED)
         scatterplot y=CENSORED x=TIME / &groups &censored &tipl;
      endif;

      if (PLOTATRISK=1)
         innermargin / align=bottom;
            blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
               display=(label values) &blockopts;
         endinnermargin;
      endif;

      DiscreteLegend "Survival" / title=GROUPNAME location=outside;

      if (PLOTCENSORED)
         if (PLOTTEST)
            layout gridded / rows=2 &gridopts;
               entry &censorstr;
               %entry_p
            endlayout;
         else
            layout gridded / rows=1 &gridopts;
               entry &censorstr;
            endlayout;
         endif;
      else
         if (PLOTTEST)
            layout gridded / rows=1 &gridopts;
               %entry_p
            endlayout;
         endif;
      endif;
   %mend;

%SurvivalTemplate
%mend;

%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;
                                          /* Make the macros and macro      */
%SurvivalTemplateRestore                  /* variables available            */

%let TitleText0 = "Kaplan-Meier Plot";    /* Change the title.              */
%let TitleText1 = &titletext0 " for " STRATUMID;
%let TitleText2 = &titletext0;

%SurvivalTemplate                         /* Compile the template with      */
                                          /* the new title.                 */

proc lifetest data=sashelp.BMT            /* Perform the analysis and make  */
              plots=survival(cb=hw test); /* the graph.                     */
   time T * Status(0);
   strata Group;
run;

%SurvivalTemplateRestore                  /* Restore the default macros     */
                                          /* and macro variables.           */

proc template;                            /* Restore the default template.  */
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

%SurvivalTemplateRestore

%let TitleText0 = "Kaplan-Meier Plot";
%let TitleText1 = &titletext0 " for " STRATUMID;
%let TitleText2 = &titletext0;

%SurvivalTemplate
proc lifetest data=sashelp.BMT plots=survival(cb=hw test);
   time T * Status(0);
   strata Group;
run;
%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

%SurvivalTemplateRestore

%let TitleText0 = "Kaplan-Meier Plot";
%let TitleText1 = &titletext0 " for " STRATUMID;
%let TitleText2 = &titletext0;

%let gridopts = autoalign=(BottomRight TOPRIGHT BOTTOMLEFT TOP BOTTOM)
                border=true BackgroundColor=GraphWalls:Color Opaque=true;

%macro multiplestrata;
  if (PLOTHW)
      bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME / &bandopts
               datatransparency=Transparency;
   endif;
   if (PLOTEP)
      bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME / &bandopts
               datatransparency=Transparency;
   endif;
   if (PLOTCL)
      if (PLOTBAND)
         bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                  display=(outline);
      else
         bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
   endif;

   stepplot y=SURVIVAL x=TIME / &groups name="Survival" &tips;

   if (PLOTCENSORED)
      scatterplot y=CENSORED x=TIME / &groups &censored &tipl;
   endif;

   if (PLOTATRISK=1)
      innermargin / align=bottom;
         blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
            display=(label values) &blockopts;
      endinnermargin;
   endif;

   DiscreteLegend "Survival" / title=GROUPNAME across=1 location=inside
      autoalign=(TopRight BottomLeft Top Bottom);

   if (PLOTCENSORED)
      if (PLOTTEST)
         layout gridded / rows=2 &gridopts;
            entry &censorstr;
            %entry_p
         endlayout;
      else
         layout gridded / rows=1 &gridopts;
            entry &censorstr;
         endlayout;
      endif;
   else
      if (PLOTTEST)
         layout gridded / rows=1 &gridopts;
            %entry_p
         endlayout;
      endif;
   endif;
%mend;

%SurvivalTemplate
proc lifetest data=sashelp.BMT plots=survival(cb=hw test);
   time T * Status(0);
   strata Group;
run;
%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

proc lifetest data=sashelp.BMT plots=survival(atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

proc lifetest data=sashelp.BMT
   plots=survival(atrisk(maxlen=13 outside(0.15)));
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%SurvivalTemplateRestore
%let TitleText2 = "Kaplan-Meier Plot";

%macro SurvivalTemplate;
   proc template;
      define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
         dynamic NStrata xName plotAtRisk plotCL plotHW plotEP labelCL
            %if %nrbquote(&censored) ne %then plotCensored;
            labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
            classAtRisk plotBand plotTest GroupName yMin Transparency
            SecondTitle TestName pValue;
         BeginGraph;

            entrytitle &titletext2;
            if (EXISTS(SECONDTITLE))
               entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
            endif;

            layout lattice /  rows=2 columns=1 columndatarange=unionall
                              rowweights=(.85 .15);
               layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                  %multiplestrata
               endlayout;

               layout overlay / xaxisopts=(display=none);
                  blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
                  display=(label values) &blockopts;
               endlayout;
            endlayout;

         EndGraph;
      end;
   run;
%mend;

%macro multiplestrata;
  if (PLOTHW)
      bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME / &bandopts
               datatransparency=Transparency;
   endif;
   if (PLOTEP)
      bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME / &bandopts
               datatransparency=Transparency;
   endif;
   if (PLOTCL)
      if (PLOTBAND)
         bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                  display=(outline);
      else
         bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
   endif;

   stepplot y=SURVIVAL x=TIME / &groups name="Survival" &tips;

   if (PLOTCENSORED)
      scatterplot y=CENSORED x=TIME / &groups &censored &tipl;
   endif;

   DiscreteLegend "Survival" / title=GROUPNAME location=outside;

   if (PLOTCENSORED)
      if (PLOTTEST)
         layout gridded / rows=2 &gridopts;
            entry &censorstr;
            %entry_p
         endlayout;
      else
         layout gridded / rows=1 &gridopts;
            entry &censorstr;
         endlayout;
      endif;
   else
      if (PLOTTEST)
         layout gridded / rows=1 &gridopts;
            %entry_p
         endlayout;
      endif;
   endif;

   dynamic NObs1 NObs2 NObs3 NEvent1 NEvent2 NEvent3;
   layout gridded / columns=3 border=TRUE autoalign=(TopRight);
      entry "";      entry "Event";   entry "Total";
      entry "1";     entry NEvent1;   entry NObs1;
      entry "2";     entry NEvent2;   entry NObs2;
      entry "3";     entry NEvent3;   entry Nobs3;
   endlayout;
%mend;

%SurvivalTemplate
%let TitleText2 = "Kaplan-Meier Plot";

%macro SurvivalTemplate;
   proc template;
      define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
         dynamic NStrata xName plotAtRisk plotCL plotHW plotEP labelCL
            %if %nrbquote(&censored) ne %then plotCensored;
            labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
            classAtRisk plotBand plotTest GroupName yMin Transparency
            SecondTitle TestName pValue;
         BeginGraph;

            entrytitle &titletext2;
            if (EXISTS(SECONDTITLE))
               entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
            endif;

            layout lattice /  rows=2 columns=1 columndatarange=unionall
                              rowweights=(.85 .15);
               layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                  %multiplestrata
               endlayout;

               layout overlay / xaxisopts=(display=none);
                  blockplot x=TATRISK block=ATRISK / class=CLASSATRISK
                  display=(label values) &blockopts;
               endlayout;
            endlayout;

         EndGraph;
      end;
   run;
%mend;

%macro MultipleStrata;

   stepplot y=SURVIVAL x=TIME / &groups name="Survival" &tips;

   if (PLOTCENSORED)
      scatterplot y=CENSORED x=TIME / &groups &censored &tipl;
   endif;

   DiscreteLegend "Survival" / title="+ Censored"
      titleattrs=GraphValueText location=inside autoalign=(Bottom);

   dynamic NObs1 NObs2 NObs3 NEvent1 NEvent2 NEvent3;
   layout gridded / columns=3 border=TRUE autoalign=(TopRight);
      entry "";      entry "Event";   entry "Total";
      entry "1";     entry NEvent1;   entry NObs1;
      entry "2";     entry NEvent2;   entry NObs2;
      entry "3";     entry NEvent3;   entry Nobs3;
   endlayout;
%mend;

%SurvivalTemplate
proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;
%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

%modstyle(name=StatColor, parent=statistical)

*
ods listing style=StatColor;

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%modstyle(name=StatColor, parent=HTMLBlue, colors=purple orange silver)

proc template;
   define style Styles.StatColor;
      parent = Styles.HTMLBlue;
      style GraphData1 / contrastcolor = purple;
      style GraphData2 / contrastcolor = orange;
      style GraphData3 / contrastcolor = silver;
   end;
run;

proc template;
   define style Styles.StatColor;
      parent = Styles.HTMLBlue;
      style GraphData1 from GraphData1 / contrastcolor = purple;
      style GraphData2 from GraphData2 / contrastcolor = orange;
      style GraphData3 from GraphData3 / contrastcolor = silver;
   end;
run;

*
ods listing style=StatColor;

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

proc template;
   delete Styles.StatColor / store=sasuser.templat;
run;

%SurvivalTemplateRestore

%let yOptions   = label="Survival Probability"
                  shortlabel="Survival"
                  labelattrs=(size=12pt weight=bold)
                  tickvalueattrs=(size=8pt weight=bold)
                  linearopts=(viewmin=0 viewmax=1
                              tickvaluelist=(0 .2 .4 .6 .8 1.0));

%let xOptions   = shortlabel=XNAME
                  offsetmin=.05
                  labelattrs=(size=12pt weight=bold)
                  tickvalueattrs=(size=8pt weight=bold)
                  linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
                              tickvaluefitpolicy=XTICKVALFITPOL);
%SurvivalTemplate

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

filename temp1 'temp1.tpl' lrecl=100;
filename temp2 'temp2.tpl' lrecl=100;
filename temp  ('temp1.tpl' 'temp2.tpl') lrecl=100;

proc template;
   source styles.htmlblue    / file=temp1;
   source styles.statistical / file=temp2;
run;

data _null_;
   infile temp pad;
   input line $ 1-100;
   file print;
   if index(lowcase(line), 'font') then put line;
run;

filename temp1 'temp1.tpl' lrecl=100;
filename temp2 'temp2.tpl' lrecl=100;
filename temp3 'temp3.tpl' lrecl=100;
filename temp  ('temp1.tpl' 'temp2.tpl' 'temp3.tpl') lrecl=100;

proc template;
   source styles.htmlblue    / file=temp1;
   source styles.statistical / file=temp2;
   source styles.default     / file=temp3;
run;

data _null_;
   infile temp pad;
   input line $ 1-100;
   file print;
   if index(lowcase(line), 'font') then put line;
run;

proc template;
   define style Styles.StatBigFont;
      parent = Styles.HTMLBlue;
      style graphfonts from graphfonts /
         'GraphLabelFont' = (", ",12pt,bold)
         'GraphValueFont' = (", ",8pt,bold);
   end;
run;

*
ods listing style=StatBigFont;

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

proc template;
   delete Styles.StatBigFont / store=sasuser.templat;
run;

%SurvivalTemplateRestore

%let censored  = markerattrs=(symbol=circlefilled size=3px);
%let censorstr = "(*ESC*){Unicode '25cf'x} Censored"
                 / textattrs=GraphValueText(family=GraphUnicodeText:FontFamily);

%SurvivalTemplate

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

proc lifetest data=sashelp.BMT
   plots=survival(nocensor maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%let censored = ;

%SurvivalTemplate;

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;

%SurvivalTemplateRestore

%let fmt = bestd6.;

%macro header;
   entry halign=right "Subjects";
   entry halign=right "Event";
   entry halign=right "Censored";
   entry halign=right "Median Survival";
   entry halign=right PctMedianConfid;
   entry halign=left  "CL";
%mend;

%macro table1;
   columnheaders;
      layout overlay / pad=(top=5);
         layout gridded / columns=6 border=TRUE;
            dynamic PctMedianConfid NObs NEvent Median
                    MedianLower MedianUpper;
            %header
            entry halign=right NObs;
            entry halign=right NEvent;
            entry halign=right eval(NObs-NEvent);
            entry halign=right eval(put(Median,&fmt));
            entry halign=right eval(put(MedianLower,&fmt));
            entry halign=right eval(put(MedianUpper,&fmt));
         endlayout;
      endlayout;
   endcolumnheaders;
%mend;

%macro table2;
   columnheaders;
      layout overlay / pad=(top=5);
         layout gridded / columns=7 border=TRUE;
            dynamic PctMedianConfid;
            entry " ";
            %header
            %do i = 1 %to 6;
               dynamic StrVal&i NObs&i NEvent&i Median&i
                       LowerMedian&i UpperMedian&i;
               if (&i <= nstrata)
                  entry halign=left StrVal&i;
                  entry halign=right NObs&i;
                  entry halign=right NEvent&i;
                  entry halign=right eval(NObs&i-NEvent&i);
                  entry halign=right eval(put(Median&i,&fmt));
                  entry halign=right eval(put(LowerMedian&i,&fmt));
                  entry halign=right eval(put(UpperMedian&i,&fmt));
               endif;
            %end;
         endlayout;
      endlayout;
   endcolumnheaders;
%mend;

%macro SurvivalTemplate;
   proc template;
      define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival;
         dynamic NStrata xName plotAtRisk plotCL plotHW plotEP labelCL
            %if %nrbquote(&censored) ne %then plotCensored;
            labelHW labelEP maxTime xtickVals xtickValFitPol method StratumID
            classAtRisk plotBand plotTest GroupName yMin Transparency
            SecondTitle TestName pValue;
         BeginGraph / designheight=defaultdesignwidth;

            if (NSTRATA=1)
               if (EXISTS(STRATUMID))
                  entrytitle &titletext1;
               else
                  entrytitle &titletext0;
               endif;
               if (PLOTATRISK=1)
                  entrytitle "with Number of Subjects at Risk" / textattrs=
                     GRAPHVALUETEXT;
               endif;

               layout lattice / rows=1 columns=1;
                  layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                     %singlestratum
                  endlayout;
                  %table1
               endlayout;

            else
               entrytitle &titletext2;
               if (EXISTS(SECONDTITLE))
                  entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
               endif;

               layout lattice / rows=1 columns=1;
                  layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                     %multiplestrata
                  endlayout;
                  %table2
               endlayout;
            endif;
         EndGraph;
      end;
   run;
%mend;

%SurvivalTemplate

proc lifetest data=sashelp.BMT
   plots=survival(maxlen=13 atrisk=0 to 2500 by 500);
   ods select SurvivalPlot;
   time T * Status(0);
   strata Group;
run;

%SurvivalTemplateRestore

proc template;
   delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat;
run;