*
;
/*Recently there was a flurry of questions about how to put multiple graphs on
a page and add titles to graphs in a catalog. Warren Sarle has kindly
provided some macros that are helpful for such things.
Although these macros are not officially supported, I know that Warren will
try to fix bugs and make improvements as time permits, so please send bug
reports and suggestions to saswss@unx.sas.com.
*/
/********************************************************************
name: grid
title: Replay graphs in a regular grid
product: graph
system: all
procs: greplay gslide
support: saswss update: 10jul95
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.
The %GRID macro lets you easily replay graphs in a regular grid with
one or more rows and one or more columns. The %GRID macro also
supports titles and footnotes for the entire replayed graph. For
example, if you have run GPLOT four times and want to replay these
graphs in a 2-by-2 grid with the title 'Four Marvelous Graphs', you
could submit the following statements:
title 'Four Marvelous Graphs';
%grid( gplot*4, rows=2, cols=2);
The %GRID macro allows 10% of the vertical size of the graph for
titles by default. You can adjust this percentage via the TOP=
argument in %GRID. Determining the best value for TOP= requires
trial and error in most cases. To allow space for footnotes, use
the BOTTOM= argument.
The graphs to replay must be stored in a graphics catalog with
library and member names specified by the macro variables &glibrary
and &gout. By default, SAS/GRAPH stores graphs in WORK.GSEG, which
is the catalog that the %GRID macro uses by default. If your
graphs are in another catalog, you must specify &glibrary and/or
&gout using %LET statements as shown below.
Each graph that is stored in a catalog has a name. Each procedure
assigns default names such as GPLOT, GPLOT1, GPLOT2, etc. Most
SAS/GRAPH procedures let you specify the name via a NAME= option
which takes a quoted string that must be a valid SAS name. However,
if a graph by that name already exists in the catalog, SAS/GRAPH
appends a number to the name; it does not replace the previous graph
by the same name unless you specify GOPTIONS GOUTMODE=REPLACE, but
this option causes _all_ entries in the catalog to be deleted
everytime you save a new graph, so it is not very useful. If you want
to replace a single graph in a catalog, sometimes you can use the
%GDELETE macro to delete the old one and later recreate a graph with
the same name, but this does not work reliably due to a bug in
SAS/GRAPH. By default, %GDELETE deletes _everything_ in the catalog;
this does seem to work reliably.
When you use BY processing, SAS/GRAPH appends numbers to the graph
name to designate graphs for each BY group. For example, if you run
GPLOT with three BY groups and NAME='HENRY', the graphs are named
HENRY, HENRY1, and HENRY2. The %GRID macro lets you abbreviate this
list of names as HENRY*3, where the repetition factor following the
asterisk is the total number of graphs, not the number of the last
graph.
*********************************************************************/
%let glibrary=WORK;
%let gout=GSEG;
%macro grid( /* replay graphs in a rectangular grid */
list, /* list of names of graphs, separated by blanks;
a name may be followed by an asterisk and a
repetition factor with no intervening blanks;
for example, ABC*3 is expanded to: ABC ABC1 ABC2 */
rows=1, /* number of rows in the grid */
cols=1, /* number of columns in the grid */
top=10, /* percentage at top to reserve for titles */
bottom=0); /* percentage at bottom to reserve for footnotes */
%gtitle;
%greplay;
%tdef(rows=&rows,cols=&cols,top=&top,bottom=&bottom)
%trep(&list,rows=&rows,cols=&cols)
run; quit;
%mend grid;
%macro gdelete(list); /* delete list of graphs from the catalog;
default is _ALL_ */
%if %bquote(&list)= %then %let list=_ALL_;
proc greplay igout=&glibrary..&gout nofs;
delete &list;
run; quit;
%mend gdelete;
%macro gtitle; /* create graph with titles and footnotes only */
%global titlecnt;
%if %bquote(&titlecnt)= %then %let titlecnt=1;
%else %let titlecnt=%eval(&titlecnt+1);
goptions nodisplay;
proc gslide gout=&glibrary..&gout name="title&titlecnt";
run;
goptions display;
%mend gtitle;
%macro greplay( /* invoke PROC GREPLAY */
tc); /* template catalog; default is JUNK */
%if %bquote(&tc)= %then %let tc=junk;
proc greplay nofs tc=&tc;
igout &glibrary..&gout;
%mend greplay;
%macro tdef( /* define a template for a rectangular grid */
rows=1, /* number of rows in the grid */
cols=1, /* number of columns in the grid */
top=10, /* percentage at top to reserve for titles */
bottom=0); /* percentage at bottom to reserve for footnotes */
%global tdefname; /* returned: name of template */
%local height width n row col lower upper left right;
%let height=%eval((100-&top-&bottom)/&rows);
%let width =%eval(100/&cols);
%let tdefname=t&rows._&cols;
tdef &tdefname
0/ulx=0 uly=100 llx=0 lly=0 urx=100 ury=100 lrx=100 lry=0
%let n=1;
%do row=1 %to &rows;
%let lower=%eval(100-&top-&row*&height);
%let upper=%eval(&lower+&height);
%do col=1 %to &cols;
%let right=%eval(&col*&width);
%let left =%eval(&right-&width);
&n/ulx=&left uly=&upper llx=&left lly=&lower
urx=&right ury=&upper lrx=&right lry=&lower
%let n=%eval(&n+1);
%end;
%end;
;
template &tdefname;
%mend tdef;
%macro trep( /* replay graphs using template defined by %TDEF */
list, /* list of names of graphs, separated by blanks;
a name may be followed by an asterisk and a
repetition factor with no intervening blanks;
for example, ABC*3 is expanded to: ABC ABC1 ABC2 */
rows=, /* (optional) number of rows in template */
cols=); /* (optional) number of columns in template */
/* rows= and cols= default to values set with %TDEF */
%global titlecnt;
%local i l n row col name root suffix nrep;
%if %bquote(&rows)= %then %let rows=%scan(&tdefname,1,t_);
%if %bquote(&cols)= %then %let cols=%scan(&tdefname,2,t_);
treplay 0:title&titlecnt
%let nrep=0;
%let l=0;
%let n=0;
%do row=1 %to &rows;
%do col=1 %to &cols;
%let n=%eval(&n+1);
%if &nrep %then %do;
%let suffix=%eval(&suffix+1);
%if &suffix>=&nrep %then %do;
%let nrep=0;
%goto tryagain;
%end;
%let name=&root&suffix;
%goto doit;
%end;
%tryagain:
%let l=%eval(&l+1);
%let name=%qscan(&list,&l,%str( ));
%if &name= %then %goto break;
%let i=%index(&name,*);
%if &i %then %do;
%let nrep=%substr(&name,&i+1);
%if &nrep<=0 %then %goto tryagain;
%let root=%substr(&name,1,&i-1);
%let name=&root;
%let suffix=0;
%end;
%doit:
&n:&name
%end;
%end;
%break:
;
%mend trep;
/****************** Examples for the %GRID macro *******************/
/*
%inc greplay;
data trig;
do n=1 to 100;
x1=sin(n/16);
x2=sin(n/8);
y1=cos(n/16);
y2=cos(n/8);
output;
end;
run;
goptions nodisplay;
proc gplot data=trig;
title 'Y1 by X1';
plot y1*x1;
run;
title 'Y1 by X2';
plot y1*x2;
run;
title 'Y2 by X1';
plot y2*x1;
run;
title 'Y2 by X2';
plot y2*x2;
run;
title 'Four Marvelous Graphs';
%grid( gplot*4, rows=2, cols=2);
title 'Adding a Title to a Single Graph';
footnote 'And a Footnote';
%grid( gplot, top=12, bottom=5);
*/
*;