%let name=vennmap; filename odsout '.'; goptions reset=global; %let text1=Scholars; %let text2=Students; %let text3=Athletes; %let label1=1 Only; %let label2=2 Only; %let label3=3 Only; %let label1_2=1&2 Intersect; %let label2_3=2&3 Intersect; %let label1_3=1&3 Intersect; %let label1_2_3=1&2&3 Intersect; %let value1=7%; %let value2=23%; %let value3=12%; %let value1_2=3%; %let value2_3=8%; %let value1_3=4%; %let value1_2_3=2%; %let color1=cx5A5AE7; %let color2=cxE75A5A; %let color3=cx5AE75A; /* Calculate the 'overlapping' colors. This isn't true color-blending, but rather taking the average of the rgb hex codes. (using this algorithm, if you mix blue & yellow you do not get green like you would in true color mixing) Maybe someone who knows color mixing algorithms can replace this code with something better... */ data _null_; /* First get the rgb hex values of the 3 defined colors */ red1= input(substr("&color1",3,2),hex2.); green1=input(substr("&color1",5,2),hex2.); blue1= input(substr("&color1",7,2),hex2.); red2= input(substr("&color2",3,2),hex2.); green2=input(substr("&color2",5,2),hex2.); blue2= input(substr("&color2",7,2),hex2.); red3= input(substr("&color3",3,2),hex2.); green3=input(substr("&color3",5,2),hex2.); blue3= input(substr("&color3",7,2),hex2.); /* A factor to 'darken' the combined area colors. values 0->1 (1=no darkening, 0=totally darkened) */ darken=.9; /* Calculate color for 1_2 intersection, and store in macro variable */ red= ((red1+red2)/2)*darken; green= ((green1+green2)/2)*darken; blue= ((blue1+blue2)/2)*darken; color1_2="cx"||put(red,hex2.)||put(green,hex2.)||put(blue,hex2.); call symput('color1_2',trim(left(color1_2))); /* Calculate color for 2_3 intersection, and store in macro variable */ red= ((red2+red3)/2)*darken; green= ((green2+green3)/2)*darken; blue= ((blue2+blue3)/2)*darken; color2_3="cx"||put(red,hex2.)||put(green,hex2.)||put(blue,hex2.); call symput('color2_3',trim(left(color2_3))); /* Calculate color for 1_3 intersection, and store in macro variable */ red= ((red1+red3)/2)*darken; green= ((green1+green3)/2)*darken; blue= ((blue1+blue3)/2)*darken; color1_3="cx"||put(red,hex2.)||put(green,hex2.)||put(blue,hex2.); call symput('color1_3',trim(left(color1_3))); /* Calculate color for 1_2_3 intersection, and store in macro variable */ red= ((red1+red2+red3)/3)*darken*darken; green= ((green1+green2+green3)/3)*darken*darken; blue= ((blue1+blue2+blue3)/3)*darken*darken; color1_2_3="cx"||put(red,hex2.)||put(green,hex2.)||put(blue,hex2.); call symput('color1_2_3',trim(left(color1_2_3))); run; /* ------------------------------------------------------------*/ /* Create the "response data" data set */ data mydata; length area_id $30 value $30; area_id="&label1"; value="&value1"; output; area_id="&label2"; value="&value2"; output; area_id="&label3"; value="&value3"; output; area_id="&label1_2"; value="&value1_2"; output; area_id="&label2_3"; value="&value2_3"; output; area_id="&label1_3"; value="&value1_3"; output; area_id="&label1_2_3"; value="&value1_2_3"; output; run; data mydata; set mydata; length htmlvar $500; htmlvar='title='||quote( 'AREA: '|| trim(left(area_id)) ||'0D'x|| 'VALUE: '|| trim(left(value)) ) ||' '|| 'href="venn.htm"'; run; /* ------------------------------------------------------------*/ /* Create the "map" geometry data set */ data mymap; length area_id $30; radius=25; /* ----- Area 1 (top-most, area 1 only) ----- */ area_id="&label1"; /* top arc of area 1 */ center_x=50; center_y=25+10+21.650635; start_angle=0; /* 3pm */ end_angle=180; direction=1; %include 'vennmap_inc.sas'; /* bottom/left arc of area 1 */ center_x=50-(50/4); center_y=25+10; start_angle=120; end_angle=60; direction=-1; %include 'vennmap_inc.sas'; /* bottom/right arc of area 1 */ center_x=50+(50/4); center_y=25+10; start_angle=120; end_angle=60; direction=-1; %include 'vennmap_inc.sas'; /* ----- Area 2 (Left-most, area 2 only) ----- */ area_id="&label2"; /* big/left arc of area 2 */ center_x=50-(50/4); center_y=25+10; start_angle=300; end_angle=120; direction=-1; %include 'vennmap_inc.sas'; /* little/right/top arc of area 2 */ center_x=50; center_y=25+10+21.650635; start_angle=180; end_angle=240; direction=1; %include 'vennmap_inc.sas'; /* little/right/bottom arc of area 2 */ center_x=50+(50/4); center_y=25+10; start_angle=180; end_angle=240; direction=1; %include 'vennmap_inc.sas'; /* ----- Area 3 (Right-most, area 3 only) ----- */ area_id="&label3"; /* big/right arc of area 3 */ center_x=50+(50/4); center_y=25+10; start_angle=60; end_angle=-120; direction=-1; %include 'vennmap_inc.sas'; /* little/left lower arc of area 3 */ center_x=50-(50/4); center_y=25+10; start_angle=-60; end_angle=0; direction=1; %include 'vennmap_inc.sas'; /* little/left/top arc of area 3 */ center_x=50; center_y=25+10+21.650635; start_angle=-60; end_angle=0; direction=1; %include 'vennmap_inc.sas'; /* ----- Area 1&2 Intersection ----- */ area_id="&label1_2"; /* lower/left arc */ center_x=50; center_y=25+10+21.650635; start_angle=180; end_angle=240; direction=1; %include 'vennmap_inc.sas'; /* lower/right arc */ center_x=50+(50/4); center_y=25+10; start_angle=180; end_angle=120; direction=-1; %include 'vennmap_inc.sas'; /* topmost arc */ center_x=50-(50/4); center_y=25+10; start_angle=60; end_angle=120; direction=1; %include 'vennmap_inc.sas'; /* ----- Area 2&3 Intersection ----- */ area_id="&label2_3"; /* lower/left arc */ center_x=50+(50/4); center_y=25+10; start_angle=180; end_angle=240; direction=1; %include 'vennmap_inc.sas'; /* lower/right arc */ center_x=50-(50/4); center_y=25+10; start_angle=-60; end_angle=0; direction=1; %include 'vennmap_inc.sas'; /* topmost arc */ center_x=50; center_y=25+10+21.650635; start_angle=300; end_angle=240; direction=-1; %include 'vennmap_inc.sas'; /* ----- Area 1&3 Intersection ----- */ area_id="&label1_3"; /* topmost arc */ center_x=50+(50/4); center_y=25+10; start_angle=60; end_angle=120; direction=1; %include 'vennmap_inc.sas'; /* lower/left arc */ center_x=50-(50/4); center_y=25+10; start_angle=60; end_angle=0; direction=-1; %include 'vennmap_inc.sas'; /* lower/right arc */ center_x=50; center_y=25+10+21.650635; start_angle=300; end_angle=360; direction=1; %include 'vennmap_inc.sas'; /* ----- Area 1&2&3 Intersection (center) ----- */ area_id="&label1_2_3"; /* upper/right arc */ center_x=50-(50/4); center_y=25+10; start_angle=0; end_angle=60; direction=1; %include 'vennmap_inc.sas'; /* upper/left arc */ center_x=50+(50/4); center_y=25+10; start_angle=120; end_angle=180; direction=1; %include 'vennmap_inc.sas'; /* lower/bottom arc */ center_x=50; center_y=25+10+21.650635; start_angle=240; end_angle=300; direction=1; %include 'vennmap_inc.sas'; run; /* Put the labels on the pieces of the circles */ proc sql; /* Get the average x/y center coordinates of each piece */ create table centroids as select unique area_id, avg(x) as x, avg(y) as y from mymap group by area_id; /* Merge the centers with the 'response' data */ create table mydata as select unique mydata.*, centroids.x, centroids.y from mydata left join centroids on mydata.area_id = centroids.area_id; quit; run; data slice_anno; set mydata; length text $20 style $12 function $12 color $12; xsys='2'; ysys='2'; hsys='3'; when='A'; function='label'; position='5'; style='"arial/bo"';size=4; color='white'; text=trim(left(value)); run; /* Put labels beside (outside) the circles */ /* Generate a version with labels instead of hatch-marks and 'legend' */ data outside_anno; length text $20 style $12 function $12 color $12; xsys='2'; ysys='2'; hsys='3'; when='A'; function='label'; style='"arial/bo"'; size=4; color='black'; text="&text1"; position='4'; x=27;y=73; output; text="&text2"; position='4'; x=13;y=25; output; text="&text3"; position='6'; x=87;y=25; output; run; GOPTIONS DEVICE=gif; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" style=minimal gtitle gfootnote ; goptions border; goptions htitle=6pct htext=4pct ftitle="arial/bo" ftext="arial"; goptions cback=white; title "Venn Diagram"; title2 "(non-proportional)"; footnote "Created using SAS/Graph 'proc gmap'"; /* Use the 'midpoints=' gmap option to guarantee the colors will be assigned in the desired order (otherwise they will be assigned alphabetically by &labeln values. */ pattern1 v=s c=&color1; pattern2 v=s c=&color2; pattern3 v=s c=&color3; pattern4 v=s c=&color1_2; pattern5 v=s c=&color2_3; pattern6 v=s c=&color1_3; pattern7 v=s c=&color1_2_3; legend1 position=(bottom) across=3 label=none shape=bar(3,1); proc gmap map=mymap data=mydata anno=outside_anno all; id area_id; choro area_id / nolegend /* legend=legend1 */ midpoints= "&label1" "&label2" "&label3" "&label1_2" "&label2_3" "&label1_3" "&label1_2_3" coutline=black woutline=2 anno=slice_anno html=htmlvar des="" name="&name"; run; quit; ODS HTML CLOSE; ODS LISTING;