Sample 49344: Create an animated SVG graph using PROC GMAP and the Annotate facility
Beginning with SAS® 9.4, you can create animated graphs in scalable vector graphics (SVG) format. New options available in the OPTIONS statement enable you to have a wide range of control over the SVG animation. Note that in order to take advantage of SVG graphics, you must use an SVG-enabled web browser to view the graphics output.
The sample code on the Full Code tab uses a combination of PROC GMAP and the Annotate facility to create an animated graph where a hurricane symbol moves across the map.
These sample files and code examples are provided by SAS Institute
Inc. "as is" without warranty of any kind, either express or implied, including
but not limited to the implied warranties of merchantability and fitness for a
particular purpose. Recipients acknowledge and agree that SAS Institute shall
not be liable for any damages whatsoever arising out of their use of this material.
In addition, SAS Institute will provide no support for the materials contained herein.
Support for animated SVG graphics output is new starting with SAS 9.4. You must be running SAS 9.4 in order to run this sample code.
%macro delcat(catname);
%if %sysfunc(cexist(&catname))
%then %do;
proc greplay nofs igout=&catname;
delete _all_;
run;
quit;
%end;
%mend delcat;
%delcat(work.gseg)
ods _all_ close;
ods listing;
%let name=fran;
filename odsout '.';
/* Use unprojected Maps.County */
data work.nc_map;
set maps.county(where=(fipstate(state) in ('NC' 'SC' 'VA')));
order=_n_;
run;
%let hurcolor=Aff3300FF;
%let landgreen=cx10CA10;
/*--- Input Hurricane Fran tracking positions and wind speeds. */
data track;
length stage $20;
format date mmddyy10.;
input date mmddyy10. time latitude longitude pressure wind stage $ &;
label latitude='Latitude' longitude='Longitude' pressure='Pressure (mb)' wind='Wind Speed (kt.)';
/*--- Assign hurricane intensity categories. */
if wind > 64 then do;
if wind < 83 then category = 1;
else if wind < 96 then category = 2;
else if wind < 114 then category = 3;
else if wind < 136 then category = 4;
else category = 5;
end;
else
category = 0;
datalines;
9/05/1996 1800 32.3 -77.8 952 100 Hurricane
9/06/1996 0000 33.7 -78 954 100 Hurricane
9/06/1996 600 35.2 -78.7 970 65 Hurricane
9/06/1996 1200 36.7 -79 985 40 Tropical Storm
9/06/1996 1800 38 -79.4 995 30 Tropical Depression
9/07/1996 0000 39.2 -79.9 1000 30 Tropical Depression
;
run;
/* Create the annotate data set for the path of the hurricane */
data track; set track;
x=atan(1)/45 * (-1*longitude);
y=atan(1)/45 * latitude;
foo=1;
run;
data labels;
length function color $ 9 position $ 1 text $ 100 style $ 12;
set track;
sizer=(wind/150)+.1;
anno_flag=3;
xsys='2';
ysys='2';
hsys='3';
position='6';
when='a';
style='"albany amt"';
function='label';
color='black';
size=2;
x=x-3*(.004*sizer);
text='Date: ' || trim(left(put(date, mmddyy10.)));
output;
position=9;
text='Time: ' || trim(left(time));
output;
run;
data work.path_anno;
length function color $ 9 position $ 1 text $ 100 style $ 12;
set track;
xsys='2';
ysys='2';
hsys='3';
when='a';
anno_flag=5;
/*--- Path for clickable links and mouse-over text on gage points. */
/*
http://lwf.ncdc.noaa.gov/img/olimages/hurricane-fran-ir-landfall.gif
*/
/* Convert the decimal degrees into degrees & minutes */
longdeg=int(longitude);
longmin=(longitude-int(longitude))*60;
latdeg=int(latitude);
latmin=(latitude-int(latitude))*60;
/* Hurricane symbol */
/* Percent size of maximum hurricane */
sizer=(wind/150)+.1;
function='pie';
size=4*sizer;
style='psolid'; color="&hurcolor";
y=y+(.004*sizer);
x=x-(.004*sizer);
angle=45;
rotate=180;
output;
style='pempty'; color='white';
output;
style='psolid'; color="&hurcolor";
y=y-2*(.004*sizer);
x=x+2*(.004*sizer);
angle=180+45;
rotate=180;
output;
style='pempty'; color='white';
output;
style='psolid'; color="&hurcolor";
y=y+(.004*sizer);
x=x-(.004*sizer);
angle=0;
rotate=360;
output;
style='pempty'; color='white';
output;
run;
/* Line/Path of the hurricane */
data work.path_anno2;
length function style color $ 8 position $ 1 text $ 20;
retain xsys ysys '2' hsys '3' when 'a';
set track;
by foo;
anno_flag=6;
if first.foo then do;
function='move';
end;
else do;
function='draw';
end;
color='cxff0000';
size=.5;
run;
/* Create an annotate data set containing the county outlines */
/* so that the county outlines appear on top of the circles. */
data work.county_outline;
length color function $ 8;
retain xsys ysys '2' color 'gray' size 1.75 when 'A' fx fy function;
set work.nc_map;
by state county segment;
anno_flag=2;
if first.segment then do;
function = 'move'; fx = x; fy = y;
end;
else if function ^= ' ' then do;
if x = . then do;
x = fx; y = fy; output; function = ' ';
end;
else function = 'draw';
end;
if function ^= ' ' then do;
output;
if last.segment then do;
x = fx; y = fy; output;
end;
end;
run;
/* Remove all internal county boundaries, keeping the state outline */
proc gremove data=work.nc_map out=work.state_outline;
by state;
id county;
run;
data work.state_outline;
length color function $ 8;
retain xsys ysys '2' color 'black' size 1.9 when 'A' fx fy function;
set work.state_outline;
by state segment;
anno_flag=4;
if first.segment then do;
function = 'move'; fx = x; fy = y;
end;
else if function ^= ' ' then do;
if x = . then do;
x = fx; y = fy; output; function = ' ';
end;
else function = 'draw';
end;
if function ^= ' ' then do;
output;
if last.segment then do;
x = fx; y = fy; output;
end;
end;
run;
/* Project the map */
data work.combined;
set work.nc_map work.path_anno work.labels work.path_anno2 work.state_outline work.county_outline;
run;
proc gproject data=work.combined out=work.combined dupok;
id state;
run;
data work.nc_map work.path_anno work.path_anno2 work.labels work.state_outline work.county_outline ;
set work.combined;
if anno_flag=2 then output work.county_outline;
else if anno_flag=3 then output work.labels;
else if anno_flag=4 then output work.state_outline;
else if anno_flag=5 then output work.path_anno;
else if anno_flag=6 then output work.path_anno2;
else output work.nc_map;
run;
data work.path_combined;
set work.path_anno2 work.path_anno work.labels;
run;
proc sort data=work.path_combined;
by date time;
run;
data work.path_combined1 work.path_combined2 work.path_combined3
work.path_combined4 work.path_combined5 work.path_combined6;
set work.path_combined;
if date='05sep96'd then output work.path_combined1;
if date='06sep96'd and time=0 then output work.path_combined2;
if date='06sep96'd and time=600 then output work.path_combined3;
if date='06sep96'd and time=1200 then output work.path_combined4;
if date='06sep96'd and time=1800 then output work.path_combined5;
if date='07sep96'd and time=0 then output work.path_combined6;
run;
data anno_slide1;
set work.county_outline work.state_outline work.path_combined1;
run;
data anno_slide2;
set work.county_outline work.state_outline work.path_combined1
work.path_combined2;
run;
data anno_slide3;
set work.county_outline work.state_outline work.path_combined1
work.path_combined2 work.path_combined3;
run;
data anno_slide4;
set work.county_outline work.state_outline work.path_combined1
work.path_combined2 work.path_combined3 work.path_combined4;
run;
data anno_slide5;
set work.county_outline work.state_outline work.path_combined1
work.path_combined2 work.path_combined3 work.path_combined4
work.path_combined5;
run;
data anno_slide6;
set work.county_outline work.state_outline work.path_combined1
work.path_combined2 work.path_combined3 work.path_combined4
work.path_combined5 work.path_combined6;
run;
/* Layer the annotate so that they are drawn in desired order,
and so that the proper pieces look "on top" */
/*
data work.all_anno;
set work.county_outline work.state_outline work.path_anno2 work.path_anno;
run;
*/
/* Set the size of the SVG graph */
options svgheight='400px' svgwidth='600px';
/* Set the DEVICE= option to SVG */
goptions reset=all device=svg border ftext="Albany AMT" htext=12pt
cback=cxDDFFFF gunit=pct htitle=6 htext=4 ftitle="albany amt"
ctitle='black' ctext='black' border;
/* Set the system options to control the SVG animation */
options printerpath=svg nodate nonumber animate=start
animduration=4 svgfadein=0 svgfadeout=0 animloop=no ;
/* Use PROC GMAP with the ODS HTML5 statement */
/* to create the final animated graph. */
ods _all_ close;
ods html5 file='svg_fran.html' options(svg_mode='inline');
title 'Path of Hurricane Fran - September 1996';
pattern1 c=&landgreen v=s r=100;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide1;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
/* Set the SVGFADEIN option to 2 seconds after the first frame is */
/* loaded to see the hurricane symbols fade into view. If the */
/* ANIMOVERLAY option is specified, the SVGFADEOUT option will */
/* have no effect because frames never fade out of view. */
options svgfadein=2;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide2;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide3;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide4;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide5;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
proc gmap map=work.nc_map data=work.nc_map anno=work.anno_slide6;
id state county;
choro state / coutline=graydd nolegend
discrete des="" ;
run;
quit;
ods _all_ close;
ods listing;
These sample files and code examples are provided by SAS Institute
Inc. "as is" without warranty of any kind, either express or implied, including
but not limited to the implied warranties of merchantability and fitness for a
particular purpose. Recipients acknowledge and agree that SAS Institute shall
not be liable for any damages whatsoever arising out of their use of this material.
In addition, SAS Institute will provide no support for the materials contained herein.
This sample illustrates how to create an animated SVG graph using the GMAP procedure and the Annotate facility.
Date Modified: | 2013-07-02 08:59:37 |
Date Created: | 2013-03-04 14:29:23 |
Operating System and Release Information
SAS System | N/A | Greenplum on Linux x64 | 9.4 TS1M0 | |
z/OS | 9.4 TS1M0 | |
Z64 | 9.4 TS1M0 | |
Microsoft® Windows® for 64-Bit Itanium-based Systems | 9.4 TS1M0 | |
Microsoft Windows Server 2003 Datacenter 64-bit Edition | 9.4 TS1M0 | |
Microsoft Windows Server 2003 Enterprise 64-bit Edition | 9.4 TS1M0 | |
Microsoft Windows XP 64-bit Edition | 9.4 TS1M0 | |
Microsoft® Windows® for x64 | 9.4 TS1M0 | |
Microsoft Windows Server 2003 Datacenter Edition | 9.4 TS1M0 | |
Microsoft Windows Server 2003 Enterprise Edition | 9.4 TS1M0 | |
Microsoft Windows Server 2003 Standard Edition | 9.4 TS1M0 | |
Microsoft Windows Server 2003 for x64 | 9.4 TS1M0 | |
Microsoft Windows Server 2008 | 9.4 TS1M0 | |
Microsoft Windows Server 2008 for x64 | 9.4 TS1M0 | |
Microsoft Windows XP Professional | 9.4 TS1M0 | |
Windows 7 Enterprise 32 bit | 9.4 TS1M0 | |
Windows 7 Enterprise x64 | 9.4 TS1M0 | |
Windows 7 Home Premium 32 bit | 9.4 TS1M0 | |
Windows 7 Home Premium x64 | 9.4 TS1M0 | |
Windows 7 Professional 32 bit | 9.4 TS1M0 | |
Windows 7 Professional x64 | 9.4 TS1M0 | |
Windows 7 Ultimate 32 bit | 9.4 TS1M0 | |
Windows 7 Ultimate x64 | 9.4 TS1M0 | |
Windows Vista | 9.4 TS1M0 | |
Windows Vista for x64 | 9.4 TS1M0 | |
64-bit Enabled AIX | 9.4 TS1M0 | |
64-bit Enabled HP-UX | 9.4 TS1M0 | |
64-bit Enabled Solaris | 9.4 TS1M0 | |
HP-UX IPF | 9.4 TS1M0 | |
Linux for x64 | 9.4 TS1M0 | |
Linux on Itanium | 9.4 TS1M0 | |
Solaris for x64 | 9.4 TS1M0 | |