/****************************************************************/ /* S A S A U T O C A L L L I B R A R Y */ /* */ /* NAME: modstyle */ /* TITLE: Modify Template Styles for ODS Graphics */ /* PRODUCT: STAT */ /* SYSTEM: ALL */ /* KEYS: graph */ /* PROCS: MACRO */ /* SUPPORT: Bob Derr */ /* */ /* MISC: The following SAS products are required to run */ /* this macro: BASE, GRAPH. */ /* */ /* DESCRIPTION: Modifies template styles by reordering the */ /* colors, linestyles, and marker symbols in */ /* the GraphDataN style elements. */ /* */ /****************************************************************/ /*--------------------------------------------------------------------- DISCLAIMER: THIS INFORMATION IS PROVIDED BY SAS INSTITUTE INC. AS A SERVICE TO ITS USERS. IT IS PROVIDED "AS IS". THERE ARE NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE REGARDING THE ACCURACY OF THE MATERIALS OR CODE CONTAINED HEREIN. ----------------------------------------------------------------------- SYNTAX: name= The name of the style you are creating. To use this style, you specify that name as the ods destination style. For example, ODS HTML STYLE=NAME. The default name is NewStyle. parent= The style you are creating inherits most of its attributes from some "parent" style (like a cascading style sheet). Name the style you are modifying here. For example, PARENT=DEFAULT or PARENT=STATISTICAL. type= Specifies how your new style will cycle through colors, markers, and linestyles. These first three methods will work well with all the plots, because cycling linestyles and markers together ensures that scatterplot markers will be distinguishable, and seriesplot lines without markers will also be distinguishable. CLM Cycles through colors, linestyles, and markers simultaneously. So the first group uses the first color, linestyle, and marker, the second group uses the second color, linestyle, and marker, and so on. This is the method used by the ODS Graphics styles. LMbyC Fixes linestyle and marker, cycles through colors, then moves to the next linestyle and marker... This is the default. CbyLM Fixes color, cycles through linestyle and marker, then moves to the next color... Forces the number of linestyles and the number of markers to be the same, otherwise, e.g., you can have multiple instances of blue-circles in a scatterplot. The following two methods may not work well with all plots. CbyLbyM Fixes color and linestyle, cycles through markers, increments linestyle, cycles through markers...then moves to the next color... LbyMbyC Fixes linestyle and marker, cycles through colors, increments marker, cycles through colors...then moves to the next linestyle... This is closest to the SAS/GRAPH method. Other variations may be added in the future, if requested. NumberOfGroups= Creates this many combinations of your colors, markers, and linestyles as GraphData1---GraphData&NumberOfGroups. By default, 32 combinations are created, which is probably way more than you will ever need. colors= A space-delimited list of colors for markers and lines. If you do not specify this option, then the colors from the parent style will be used. You ought to be able to specify the colors using any SAS-color notation; e.g. RGB colors are CXrrggbb. See SAS/GRAPH Reference: SAS/GRAPH Concepts: SAS/GRAPH Colors and Images: Specifying Colors in SAS/GRAPH Programs for a list. COLORS=GRAYS generates 7 distinguishable (hopefully!) grayscale colors from blackest-to-whitest. The colors probably should be mixed up to provide better distinguishablity when you need fewer colors, but you can do that with your own COLORS=list. The HLS-coding is used to generate these colors by setting hue=saturation=0 and incrementing the lightness for each gray. You can also use the keywords BLUES, PURPLES, MAGENTAS, REDS, ORANGES, YELLOWS, GREENS, and CYANS to generate 7 such colors, where the hue fixs the color and the saturation=AA. COLORS=SHADES INT generates 7 colors as described above, except you specify an integer 0 <= INT < 360. See the HLS color-cone in SAS/GRAPH Reference: SAS/GRAPH Concepts: SAS/GRAPH Colors and Images: Specifying Colors in SAS/GRAPH Programs for the mapping between degrees and hues. The obvious shorthand hues are available: GRAY, GREY, BLUE=0, PURPLE=30, MAGENTA=60, RED=120, ORANGE=150, YELLOW=180, GREEN=240, and CYAN=300. fillcolors= A space-delimited list of colors for bands and fills. If you do not specify this option, then the colors from the parent style will be used. Fillcolors from the parent-style were designed to work well with the colors from the parent-style. If you specify a COLOR= list, then you may want to redefine the FILLCOLORS= list as well. You need to have at least as many FILLCOLORS as you have COLORS (any extra fillcolors are ignored). Two shortcuts are available: FILLCOLORS=COLORS simply uses the same colors for the fills. Your confidence bands should have transparency for this to be useful. FILLCOLORS=LIGHTCOLORS is only allowed with COLORS=SHADES, and modifies the hues associated with each COLOR. linestyles= A space-delimited list of linestyle numbers. If you do not specify this option, a default list is used. Linestyle numbers can range from 1 to 46. Some linestyles have names associated with them; you can also use these names in the list. The following names are supported: Number Name ========================== 1 Solid 2 ShortDash 4 MediumDash 5 LongDash 8 MediumDashShortDash 14 DashDashDot 15 DashDotDot 20 Dash 26 LongDashShortDash 34 Dot 35 ThinDot 41 ShortDashDot 42 MediumDashDotDot markers=A space-delimited list of marker symbols. If you do not specify this option, a default list is used. The available marker symbols are listed in the ODS Graphics documentation. Two shortcuts are available: markers=FILLED is an alias for the specification markers=CircleFilled TriangleFilled SquareFilled DiamondFilled StarFilled HomeDownFilled markers=EMPTY is an alias for the specification markers=Circle Triangle Square Diamond Star HomeDown display= 1=Use MPRINT to display your new template. debug= Code for debugging. 'debug=1' displays messages, 'debug=0' hides them. ----------------------------------------------------------------------- USAGE: First few series/scatter plots distinguished by color, but later by changing marker+linestyle %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC); First few series/scatter plots distinguished by linestyle+marker %modstyle(name=NewStatStyle,parent=Statistical,type=CbyLM); First few series/scatter plots distinguished by marker %modstyle(name=NewStatStyle,parent=Statistical,type=CbyLbyM); First few series/scatter plots distinguished by color, but later by changing marker %modstyle(name=NewStatStyle,parent=Statistical,type=LbyMbyC); First few series plots distinguished by linestyle, but later by changing color %modstyle(name=NewStatStyle,parent=Statistical,type=CbyLbyM,markers=circle); Grayscale filled circles %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=grays,markers=circlefilled); Grayscale with transparent confidence bands %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=grays,fillcolors=colors); Grayscale with non-transparent confidence bands %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=grays,fillcolors=lightcolors); Blue filled circles %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=shades 0,markers=circlefilled); %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=shades blue,markers=circlefilled); %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,colors=blues,markers=circlefilled); Specifying linestyles and markers %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC,linestyles=1 2 dot 4,markers=filled); ----------------------------------------------------------------------- To implement your new style, specify it in the ods destination; for example: ods html style=NewStatStyle file='test.html'; ----------------------------------------------------------------------- EXAMPLE: data one; do group=1 to 32; lower=group-0.5; upper=group+0.5; do x=0 to 10; output; end; end; run; proc template; define statgraph mytpl; begingraph; layout lattice / rows=1 columns=3 columndatarange=UNIONALL rowdatarange=UNIONALL; rowaxes; rowaxis / display=(line ticks tickvalues); endrowaxes; layout overlay / yaxisopts=(display=none) xaxisopts=(display=none); seriesplot y=group x=x / group=group display=all; endlayout; layout overlay / yaxisopts=(display=none) xaxisopts=(display=none); scatterplot y=group x=x / group=group markerattrs=(size=9); endlayout; layout overlay / yaxisopts=(display=none) xaxisopts=(display=none); bandplot limitlower=lower limitupper=upper x=x / group=group; seriesplot y=group x=x / group=group; endlayout; endlayout; endgraph; end; %modstyle(name=NewStatStyle,parent=Statistical,type=LMbyC); ods graphics on; ods html style=NewStatStyle file='test.html'; proc sgrender data=one template=mytpl; run; ods html close; ods graphics off; ---------------------------------------------------------------------*/ %macro modstyle(name=Newstyle, parent=Default, type=LMbyC, colors=%str(GraphColors("gcdata1")) %str(GraphColors("gcdata2")) %str(GraphColors("gcdata3")) %str(GraphColors("gcdata4")) %str(GraphColors("gcdata5")) %str(GraphColors("gcdata6")) %str(GraphColors("gcdata7")) %str(GraphColors("gcdata8")) %str(GraphColors("gcdata9")) %str(GraphColors("gcdata10")) %str(GraphColors("gcdata11")) %str(GraphColors("gcdata12")), fillcolors=%str(GraphColors("gdata1")) %str(GraphColors("gdata2")) %str(GraphColors("gdata3")) %str(GraphColors("gdata4")) %str(GraphColors("gdata5")) %str(GraphColors("gdata6")) %str(GraphColors("gdata7")) %str(GraphColors("gdata8")) %str(GraphColors("gdata9")) %str(GraphColors("gdata10")) %str(GraphColors("gdata11")) %str(GraphColors("gdata12")), linestyles= 1 4 8 5 14 26 15 20 41 42 2, markers= circle plus X triangle square asterisk diamond, NumberOfGroups=32, display=0, debug=0); ; %local done i j temp NumberOfLines NumberOfMarkers NumberOfColors ColorNum MarkerNum LineNum Cycle MinCycle Cycle2 NumberOfFills FillNum hue saturation okay savemprint; %let savemprint = %sysfunc(getoption(mprint)); %*------Catch obvious input errors------; %if %eval(&name=) %then %do; %put ERROR: You must specify a valid name= style name.; %return; %end; %if %eval(&parent=) %then %do; %put ERROR: You must specify a valid parent= style.; %return; %end; %if %eval(%upcase(&name)=%upcase(&parent)) %then %do; %put ERROR: You must specify a NAME= new style name different from the PARENT= style name.; %return; %end; %if %datatyp(&NumberOfGroups)=CHAR %then %do; %put ERROR: You must specify an integer NumberOfGroups > 0.; %return; %end; %if %eval(&NumberOfGroups= or &NumberOfGroups<1) %then %do; %put ERROR: You must specify an integer NumberOfGroups > 0.; %return; %end; %if %eval(&type ^= LMbyC and &type ^= CbyLM and &type ^= CbyLbyM and &type ^= LbyMbyC and &type ^= CLM) %then %do; %put ERROR: You must specify type=CLM or LMbyC or CbyLM or CbyLbyM or LbyMbyC: type=&type.; %return; %end; %if %eval(&display=) %then %let display=0; %else %if %datatyp(&display)=CHAR %then %let display=1; %else %if %eval(%upcase(&display)^=0) %then %let display=1; %else %let display=0; %if %eval(&debug=) %then %let debug=0; %else %if %datatyp(&debug)=CHAR %then %let debug=1; %else %if %eval(%upcase(&debug)^=0) %then %let debug=1; %else %let debug=0; %*------Linestyles------; %let done=0; %let i=0; %do %while (&done=0); %let temp = %scan(&linestyles,%eval(&i+1),%str( )%str(,)); %if %nrbquote(&temp)= %then %let done=1; %else %do; %let i=%eval(&i+1); %local l&i; %if %eval(%upcase(&temp)=SOLID) %then %let l&i = 1; %else %if %eval(%upcase(&temp)=SHORTDASH) %then %let l&i = 2; %else %if %eval(%upcase(&temp)=MEDIUMDASH) %then %let l&i = 4; %else %if %eval(%upcase(&temp)=LONGDASH) %then %let l&i = 5; %else %if %eval(%upcase(&temp)=MEDIUMDASHSHORTDASH) %then %let l&i = 8; %else %if %eval(%upcase(&temp)=DASHDASHDOT) %then %let l&i = 14; %else %if %eval(%upcase(&temp)=DASHDOTDOT) %then %let l&i = 15; %else %if %eval(%upcase(&temp)=DASH) %then %let l&i = 20; %else %if %eval(%upcase(&temp)=LONGDASHSHORTDASH) %then %let l&i = 26; %else %if %eval(%upcase(&temp)=DOT) %then %let l&i = 34; %else %if %eval(%upcase(&temp)=THINDOT) %then %let l&i = 35; %else %if %eval(%upcase(&temp)=SHORTDASHDOT) %then %let l&i = 41; %else %if %eval(%upcase(&temp)=MEDIUMDASHDOTDOT) %then %let l&i = 42; %else %if %eval(&temp < 1 or &temp > 46) %then %do; %put ERROR: Each specified linestyle must be an integer between 1 and 46.; %return; %end; %else %let l&i = &temp; %if (&debug) %then %put &i &&l&i; %end; %end; %let NumberOfLines=%eval(&i); %if %eval(&NumberOfLines < 1) %then %do; %put ERROR: You must specify at least one linestyle.; %return; %end; %*------Marker symbols------; %let done=0; %let i=0; %let j=0; %do %while (&done=0); %let temp = %scan(&markers,%eval(&j+1),%str( )%str(,)); %if %nrbquote(&temp)= %then %let done=1; %else %do; %if (%eval(%upcase(&temp) = FILLED)) %then %do; %let i=%eval(&i+1); %local m&i; %let m&i= circlefilled; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= trianglefilled; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= squarefilled; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= diamondfilled; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= starfilled; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= homedownfilled; %if (&debug) %then %put &i &&m&i; %end; %else %if (%eval(%upcase(&temp) = EMPTY)) %then %do; %let i=%eval(&i+1); %local m&i; %let m&i= circle; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= triangle; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= square; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= diamond; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= star; %if (&debug) %then %put &i &&m&i; %let i=%eval(&i+1); %local m&i; %let m&i= homedown; %if (&debug) %then %put &i &&m&i; %end; %else %do; %let i=%eval(&i+1); %local m&i; %let m&i = &temp; %if (&debug) %then %put &i &&m&i; %end; %let j=%eval(&j+1); %end; %end; %let NumberOfMarkers=%eval(&i); %if %eval(&NumberOfMarkers < 1) %then %do; %put ERROR: You must specify at least one marker symbol.; %return; %end; %*------Color list------; %let done=0; %let i=0; %do %while (&done=0); %let temp = %scan(&colors,%eval(&i+1),%str( )%str(,)); %if %nrbquote(&temp)= %then %let done=1; %else %do; %let i=%eval(&i+1); %local c&i; %let c&i = &temp; %if (&debug) %then %put &i &&c&i; %end; %end; %let NumberOfColors=%eval(&i); %if %eval(&NumberOfColors < 1) %then %do; %put ERROR: You must specify at least one color.; %return; %end; %let hue=; %let saturation=; %let okay=0; %if %eval(&NumberOfColors = 1) %then %do; %if (&debug) %then %put (1); %local c2; %if (%eval(%upcase(&c1) = GRAYS or %upcase(&c1) = GREYS or %upcase(&c1) = SHADES)) %then %do; %let saturation=00; %let c2=0; %let NumberOfColors=2; %let c1=SHADES; %let okay=1; %end; %else %do; %if %eval(%upcase(&c1)=BLUES) %then %do; %let c2=0; %let okay=1; %end; %else %if %eval(%upcase(&c1)=PURPLES) %then %do; %let c2=30; %let okay=1; %end; %else %if %eval(%upcase(&c1)=MAGENTAS) %then %do; %let c2=60; %let okay=1; %end; %else %if %eval(%upcase(&c1)=REDS) %then %do; %let c2=120; %let okay=1; %end; %else %if %eval(%upcase(&c1)=ORANGES) %then %do; %let c2=150; %let okay=1; %end; %else %if %eval(%upcase(&c1)=YELLOWS) %then %do; %let c2=180; %let okay=1; %end; %else %if %eval(%upcase(&c1)=GREENS) %then %do; %let c2=240; %let okay=1; %end; %else %if %eval(%upcase(&c1)=CYANS) %then %do; %let c2=300; %let okay=1; %end; %if %eval(&okay=1) %then %do; %let saturation=AA; %let c1=SHADES; %let NumberOfColors=2; %end; %end; %end; %if (&debug) %then %put saturation=&saturation %eval(&saturation~=) %eval(&saturation=) okay=&okay; %if (&debug) %then %put (2); %if %eval(&NumberOfColors = 2) %then %do; %if (&debug) %then %put (3); %if (%eval(%upcase(&c1) = SHADES)) %then %do; %if (&debug) %then %put (4); %local c3 c4 c5 c6 c7; %if %eval(&saturation=) %then %do; %if (&debug) %then %put (5); %if %eval(not(&c2 >= 0 and &c2 <= 359)) %then %do; %if (&debug) %then %put (6); %if %eval(%upcase(&c2)=GRAY) %then %do; %let saturation=00; %let c2=0; %end; %else %if %eval(%upcase(&c2)=GREY) %then %do; %let saturation=00; %let c2=0; %end; %else %if %eval(%upcase(&c2)=BLUE) %then %do; %let saturation=AA; %let c2=0; %end; %else %if %eval(%upcase(&c2)=PURPLE) %then %do; %let saturation=AA; %let c2=30; %end; %else %if %eval(%upcase(&c2)=MAGENTA) %then %do; %let saturation=AA; %let c2=60; %end; %else %if %eval(%upcase(&c2)=RED) %then %do; %let saturation=AA; %let c2=120; %end; %else %if %eval(%upcase(&c2)=ORANGE) %then %do; %let saturation=AA; %let c2=150; %end; %else %if %eval(%upcase(&c2)=YELLOW) %then %do; %let saturation=AA; %let c2=180; %end; %else %if %eval(%upcase(&c2)=GREEN) %then %do; %let saturation=AA; %let c2=240; %end; %else %if %eval(%upcase(&c2)=CYAN) %then %do; %let saturation=AA; %let c2=300; %end; %else %do; %put ERROR: Specify 'shades n' where 0 <= n < 360.; %return; %end; %end; %else %let saturation=AA; %let okay=1; %end; %if (&debug) %then %put saturation=&saturation %eval(&saturation~=) %eval(&saturation=); %if (&debug) %then %put c2=&c2; %local first second third; %let first =%eval(&c2/256); %let c3=%eval(&c2-&first*256); %let second =%eval(&c3/16); %let third =%eval(&c3-&second*16); %if %eval(&first > 9) %then %do; %if %eval(&first=10) %then %let first=A; %else %if %eval(&first=11) %then %let first=B; %else %if %eval(&first=12) %then %let first=C; %else %if %eval(&first=13) %then %let first=D; %else %if %eval(&first=14) %then %let first=E; %else %if %eval(&first=15) %then %let first=F; %end; %if %eval(&second > 9) %then %do; %if %eval(&second=10) %then %let second=A; %else %if %eval(&second=11) %then %let second=B; %else %if %eval(&second=12) %then %let second=C; %else %if %eval(&second=13) %then %let second=D; %else %if %eval(&second=14) %then %let second=E; %else %if %eval(&second=15) %then %let second=F; %end; %if %eval(&third > 9) %then %do; %if %eval(&third=10) %then %let third=A; %else %if %eval(&third=11) %then %let third=B; %else %if %eval(&third=12) %then %let third=C; %else %if %eval(&third=13) %then %let third=D; %else %if %eval(&third=14) %then %let third=E; %else %if %eval(&third=15) %then %let third=F; %end; %let hue= &first&second&third; %let c1= h&hue.33&saturation; %let c2= h&hue.61&saturation; %let c3= h&hue.88&saturation; %let c4= h&hue.aa&saturation; %let c5= h&hue.cc&saturation; %let c6= h&hue.dd&saturation; %let c7= h&hue.ee&saturation; %let NumberOfColors=7; %end; %end; %*------Fill Color list------; %let done=0; %let i=0; %do %while (&done=0); %let temp = %scan(&fillcolors,%eval(&i+1),%str( )%str(,)); %if %nrbquote(&temp)= %then %let done=1; %else %do; %let i=%eval(&i+1); %local f&i; %let f&i = &temp; %if (&debug) %then %put &i &&f&i; %end; %end; %let NumberOfFills=%eval(&i); %if %eval(&NumberOfFills < 1) %then %do; %put ERROR: You must specify at least one fillcolor.; %return; %end; %if %eval(&NumberOfFills = 1) %then %do; %if (%eval(%upcase(&f1) = COLORS)) %then %do i=1 %to &NumberOfColors; %if (&debug) %then %put (7); %local f&i; %let f&i = &&c&i; %let NumberOfFills=%eval(&NumberOfColors); %end; %else %if (%eval(%upcase(&f1) = LIGHTCOLORS)) %then %do; %if (&debug) %then %put (8); %if %eval(&hue ~=) %then %do i=1 %to &NumberOfColors; %if (&debug) %then %put (9); %let f1= h&hue.a2&saturation; %let f2= h&hue.b2&saturation; %let f3= h&hue.c2&saturation; %let f4= h&hue.d2&saturation; %let f5= h&hue.e2&saturation; %let f6= h&hue.f0&saturation; %let f7= h&hue.f8&saturation; %let NumberOfFills=7; %end; %else %do; %put ERROR: Fillcolors=lightcolors is only allowed when colors=shades.; %return; %end; %end; %end; %if %eval(&NumberOfFills < &NumberOfColors) %then %do; %put ERROR: The number of fillcolors must equal the number of colors.; %* ignore any excess fillcolors; %return; %end; %*------Colors are added to a Style list, in case the actual Style color list is used------; %macro newstyles; style ColorStyles / %do i=1 %to &NumberOfColors; "c&i" = &&c&i %end;; style FillStyles / %do i=1 %to &NumberOfFills; "f&i" = &&f&i %end;; %mend; %if (&display) %then options mprint;; proc template; define style Styles.&name; parent = Styles.&parent; %newstyles; %*------Cycle Lines, Markers, and Colors simultaneously------; %if %eval(&type = CLM) %then %do i=0 %to %eval(&NumberOfGroups-1); %let j= %eval(&i+1); %let ColorNum = %eval(&i-&NumberOfColors*(&i/&NumberOfColors)+1); %let MarkerNum= %eval(&i-&NumberOfMarkers*(&i/&NumberOfMarkers)+1); %let LineNum= %eval(&i-&NumberOfLines*(&i/&NumberOfLines)+1); replace GraphData&j / Color = FillStyles("f&ColorNum") ContrastColor = ColorStyles("c&ColorNum") linestyle = &&l&LineNum markersymbol = "&&m&MarkerNum" ; %end; %*------Cycle by Line and Marker, within by Color------; %if %eval(&type = LMbyC) %then %do i=0 %to %eval(&NumberOfGroups-1); %let j= %eval(&i+1); %let ColorNum = %eval(&i-&NumberOfColors*(&i/&NumberOfColors)+1); %let Cycle= %eval(&i/&NumberOfColors); %let MarkerNum= %eval(&Cycle-&NumberOfMarkers*(&Cycle/&NumberOfMarkers)+1); %let LineNum= %eval(&Cycle-&NumberOfLines*(&Cycle/&NumberOfLines)+1); replace GraphData&j / Color = FillStyles("f&ColorNum") ContrastColor = ColorStyles("c&ColorNum") linestyle = &&l&LineNum markersymbol = "&&m&MarkerNum" ; %end; %*------Cycle by Color, within by Line and Marker------; %else %if %eval(&type = CbyLM) %then %do i=0 %to %eval(&NumberOfGroups-1); %let j= %eval(&i+1); %if %eval(&NumberOfMarkers < &NumberOfLines) %then %let MinCycle= &NumberOfMarkers; %else %let MinCycle= &NumberOfLines; %let MarkerNum= %eval(&i-&MinCycle*(&i/&MinCycle)+1); %let LineNum= %eval(&MarkerNum); %let Cycle= %eval(&i/&MinCycle); %let ColorNum = %eval(&Cycle-&NumberOfColors*(&Cycle/&NumberOfColors)+1); replace GraphData&j / Color = FillStyles("f&ColorNum") ContrastColor = ColorStyles("c&ColorNum") linestyle = &&l&LineNum markersymbol = "&&m&MarkerNum" ; %end; %*------Cycle by Color, within by Line, and within by Marker------; %else %if %eval(&type = CbyLbyM) %then %do i=0 %to %eval(&NumberOfGroups-1); %let j= %eval(&i+1); %let MarkerNum= %eval(&i-&NumberOfMarkers*(&i/&NumberOfMarkers)+1); %let Cycle= %eval(&i/&NumberOfMarkers); %let LineNum= %eval(&Cycle-&NumberOfLines*(&Cycle/&NumberOfLines)+1); %let Cycle2= %eval(&Cycle/&NumberOfLines); %let ColorNum = %eval(&Cycle2-&NumberOfColors*(&Cycle2/&NumberOfColors)+1); replace GraphData&j / Color = FillStyles("f&ColorNum") ContrastColor = ColorStyles("c&ColorNum") linestyle = &&l&LineNum markersymbol = "&&m&MarkerNum" ; %end; %*------Cycle by Line, within by Marker, and within by Color------; %else %if %eval(&type = LbyMbyC) %then %do i=0 %to %eval(&NumberOfGroups-1); %let j= %eval(&i+1); %let ColorNum= %eval(&i-&NumberOfColors*(&i/&NumberOfColors)+1); %let Cycle= %eval(&i/&NumberOfColors); %let MarkerNum= %eval(&Cycle-&NumberOfMarkers*(&Cycle/&NumberOfMarkers)+1); %let Cycle2= %eval(&Cycle/&NumberOfMarkers); %let LineNum = %eval(&Cycle2-&NumberOfLines*(&Cycle2/&NumberOfLines)+1); replace GraphData&j / Color = FillStyles("f&ColorNum") ContrastColor = ColorStyles("c&ColorNum") linestyle = &&l&LineNum markersymbol = "&&m&MarkerNum" ; %end; end; run; %if (&display) %then options &savemprint;; %mend;