%let name=polar_graph; filename odsout '.'; /* SAS/Graph solution for polar graphs, modeled after: http://blogs.sas.com/content/graphicallyspeaking/2016/07/02/polar-graph/ */ %let var=black_carbon_concentration; %let max_resp=30; /* maximum response value (&var) */ %let max_wind=25; /* maximum wind speed */ %let max_rad=35; /* maximum radius (40 = 40% of the screen) */ /* where to center the polar grid on the page (leaving room for title & legend */ %let centx=45; %let centy=45; /*--Generate some random data to plot--*/ data response_data; pi=constant("pi"); conv=pi/180.0; do wind_speed=0 to 25 by .5; do wind_direction=0 to 360 by 2; &var=15+10*cos((wind_direction+wind_speed*5)*conv) + 5*cos((2*wind_direction+wind_speed*5)*conv); output; end; end; run; proc sort data=response_data out=response_data; by &var; run; data anno_grid; length function color $8 style $35 text $30; xsys='3'; ysys='3'; hsys='3'; when='a'; do wind_ring = 5 to 25 by 5; /* draw the ring */ x=¢x; y=¢y; function='PIE'; style='pempty'; color='gray77'; size=(wind_ring/&max_wind)*(&max_rad); rotate=360; output; /* convert the ending position of the pie border, to a position you can annotate text on */ function='piexy'; size=1; output; function='cntl2txt'; output; /* annotate a text label on the edge of the annotated circle */ function='label'; color='black'; rotate=0; angle=0; position='1'; size=2.0; x=.; y=.; style='albany amt/bold'; text=trim(left(wind_ring)); output; end; function='label'; position='5'; size=.; style='albany amt'; color='gray33'; y=¢y+5; x=¢x+19; text='wind speed circles'; output; run; %let c01=cxff0200; %let c02=cxff0f00; %let c03=cxff2200; %let c04=cxff3200; %let c05=cxff4d00; %let c06=cxff5500; %let c07=cxff5f00; %let c08=cxff8500; %let c09=cxff9800; %let c10=cxffad00; %let c11=cxffba00; %let c12=cxffd500; %let c13=cxffe800; %let c14=cxfff300; %let c15=cxfafc00; %let c16=cxeaf400; %let c17=cxe0ef00; %let c18=cxc8e300; %let c19=cxb7db00; %let c20=cxa2d000; %let c21=cx97cb00; %let c22=cx7fbf00; %let c23=cx6fb700; %let c24=cx57ab00; %let c25=cx4ca600; %let c26=cx3f9f00; %let c27=cx2c9600; %let c28=cx219000; %let c29=cx178b00; %let c30=cx048200; data anno_response; set response_data; length html $1000; html= 'title='||quote( 'Black Carbon: '||trim(left(put(&var,comma8.1)))||'0D'x|| 'Direction: '||trim(left(wind_direction))||'b0'x||'0D'x|| 'Speed: '||trim(left(wind_speed))); length function color $8 style $35 text $30; xsys='3'; ysys='3'; hsys='3'; when='b'; radius=(wind_speed/&max_wind)*&max_rad; angle_degrees=(360-wind_direction)+90; angle_radians=( (2*3.14)/360 )*(angle_degrees); y=¢y+radius*sin(angle_radians); x=¢x+radius*cos(angle_radians); function='pie'; style='psolid'; rotate=360; /* dots in the middle smaller, towards the outside larger */ size=.25+(wind_speed/&max_wind)*0.8; if &var >=29 then color="&c01"; else if &var >=28 then color="&c02"; else if &var >=27 then color="&c03"; else if &var >=26 then color="&c04"; else if &var >=25 then color="&c05"; else if &var >=24 then color="&c06"; else if &var >=23 then color="&c07"; else if &var >=22 then color="&c08"; else if &var >=21 then color="&c09"; else if &var >=20 then color="&c10"; else if &var >=19 then color="&c11"; else if &var >=18 then color="&c12"; else if &var >=17 then color="&c13"; else if &var >=16 then color="&c14"; else if &var >=15 then color="&c15"; else if &var >=14 then color="&c16"; else if &var >=13 then color="&c17"; else if &var >=12 then color="&c18"; else if &var >=11 then color="&c19"; else if &var >=10 then color="&c20"; else if &var >= 9 then color="&c21"; else if &var >= 8 then color="&c22"; else if &var >= 7 then color="&c23"; else if &var >= 6 then color="&c24"; else if &var >= 5 then color="&c25"; else if &var >= 4 then color="&c26"; else if &var >= 3 then color="&c27"; else if &var >= 2 then color="&c28"; else if &var >= 1 then color="&c29"; else if &var >= 0 then color="&c30"; else color="graydd"; run; data anno_compass_directions; length function color $8 style $35 text $100; xsys='3'; ysys='3'; hsys='3'; when='a'; function='move'; x=¢x; y=¢y; output; function='arrow'; y=y+(&max_rad+4.2); size=.1; angle=45; line=1.2; style='filled'; output; function='label'; y=y+2; position='*'; style='albany amt/bold'; angle=0; rotate=0; size=2.0; text='N'; output; function='move'; x=¢x; y=¢y; output; function='arrow'; x=x+(&max_rad+4.2); size=.1; angle=45; line=1.2; style='filled'; output; function='label'; x=x+1.5; position='*'; style='albany amt/bold'; angle=0; rotate=0; size=2.0; text='E'; output; function='move'; x=¢x; y=¢y; output; function='arrow'; x=x-(&max_rad+4.2); size=.1; angle=45; line=1.2; style='filled'; output; function='label'; x=x-1.5; position='*'; style='albany amt/bold'; angle=0; rotate=0; size=2.0; text='W'; output; function='move'; x=¢x; y=¢y; output; function='arrow'; y=y-(&max_rad+4.2); size=.1; angle=45; line=1.2; style='filled'; output; function='label'; y=y-2; position='*'; style='albany amt/bold'; angle=0; rotate=0; size=2.0; text='S'; output; run; data anno_legend; length function color $8 style $35 text $100; xsys='3'; ysys='3'; hsys='3'; when='a'; function='label'; style='albany amt/bold'; size=.; position='5'; x=86.0; y=88.0; text="BCC"; output; position='6'; x=87.5; y=85.4; text="30"; output; y=56.5; text="0"; output; style='albany amt/unicode'; position='5'; size=3.0; text='25a0'x; x=86; y=87; space=1.0; y=y-space; color="&c01"; output; y=y-space; color="&c02"; output; y=y-space; color="&c03"; output; y=y-space; color="&c04"; output; y=y-space; color="&c05"; output; y=y-space; color="&c06"; output; y=y-space; color="&c07"; output; y=y-space; color="&c08"; output; y=y-space; color="&c09"; output; y=y-space; color="&c10"; output; y=y-space; color="&c11"; output; y=y-space; color="&c12"; output; y=y-space; color="&c13"; output; y=y-space; color="&c14"; output; y=y-space; color="&c15"; output; y=y-space; color="&c16"; output; y=y-space; color="&c17"; output; y=y-space; color="&c18"; output; y=y-space; color="&c19"; output; y=y-space; color="&c20"; output; y=y-space; color="&c21"; output; y=y-space; color="&c22"; output; y=y-space; color="&c23"; output; y=y-space; color="&c24"; output; y=y-space; color="&c25"; output; y=y-space; color="&c26"; output; y=y-space; color="&c27"; output; y=y-space; color="&c28"; output; y=y-space; color="&c29"; output; y=y-space; color="&c30"; output; run; /* Combine all the annotate data sets */ data all_anno; set anno_grid anno_response anno_compass_directions anno_legend; run; goptions device=png border; goptions xpixels=700 ypixels=700; goptions cback=white; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="circular graph") style=htmlblue; goptions gunit=pct htitle=4 htext=2 ftitle="albany amt/bold" ftext="albany amt"; goptions ctext=gray33; title1 ls=1.3 "Black Carbon Concentration (BCC)"; title2 "by wind speed and direction"; title3 a=-90 h=5 ' '; footnote ' '; symbol1 value=none interpol=none color=gray77; axis1 label=(font='albany amt/bold' angle=90 'Wind Speed') order=(0 to 25 by 5) major=none minor=none style=0; axis2 label=(font='albany amt/bold' 'Wind Direction') value=(t=1 '0/N' t=2 '90/E' t=3 '180/S' t=4 '270/W' t=5 '360/N') order=(0 to 360 by 90) major=none minor=none style=0; data anno_gplot; set anno_response; xsys='2'; ysys='2'; x=wind_direction; y=wind_speed; size=0.8; /* all dots same size for regular plot */ run; data anno_legend_gplot; set anno_legend; x=x+8; y=y-22; run; proc gplot data=response_data anno=anno_gplot; note move=(70,2) c=gray "Using random/simulated data"; plot wind_speed*wind_direction / vaxis=axis1 haxis=axis2 noframe autovref cvref=gray77 autohref chref=black anno=anno_legend_gplot des='' name="&name"; run; title3; footnote; ods html anchor='polar'; proc gslide annotate=all_anno des='' name="&name"; note move=(70,2) c=gray "Using random/simulated data"; run; quit; ODS HTML CLOSE; ODS LISTING;