%macro Euler_Macro (n1=, n2=, ni=, skin=none); %if &n1 < &n2 %then %do; %put The parameter N1 must be greater than N2 - Macro Terminated.; %goto finished; %end; /*--Special case S1 where N2=0--*/ %if &n2 = 0 %then %do; data euler; format Error 5.3; pi=constant("PI"); /*--Number of obs in each set--*/ ns1=&n1; /*--Set 1 only--*/ ns2=&n2; /*--Set 2 only--*/ nsi=∋ /*--Set 1 & 2--*/ nc1=ns1+nsi; /*--Number of obs in circle 1--*/ nc2=ns2+nsi; /*--Number of obs in circle 2--*/ r1=10; /*--Assumed Radius of circle 1--*/ r2=r1*sqrt(nc2/nc1); /*--Proportional radius of circle 2--*/ xo1=0; yo1=0; xo2=xo1+r1-r2; yo2=0; /*--Location of the text labels--*/ xt1=((xo1-r1)+(xo2-r2))/2; xt2=.; xti=xo2; output; run; /*--Define template--*/ proc template; define statgraph euler_bubble_S1; begingraph; entrytitle 'Proportional Euler Diagram'; entryfootnote halign=left "N1=&n1 N2=&n2 Ni=&ni Error = 0"; layout overlayequated / cycleattrs=true walldisplay=none xaxisopts=(display=none) yaxisopts=(display=none); bubbleplot x=xo1 y=yo1 size=r1 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; bubbleplot x=xo2 y=yo2 size=r2 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; textplot x=xt1 y=yo1 text=ns1 / textattrs=(size=16) strip=true; textplot x=xt2 y=yo1 text=ns2 / textattrs=(size=16) strip=true; textplot x=xti y=yo1 text=nsi / textattrs=(size=16) strip=true; discretelegend 'a'; endlayout; endgraph; end; run; /*--Render the graph--*/ proc sgrender data=euler template=euler_bubble_S1; run; %end; /*--Special case S1 where NI=0--*/ %else %if &ni = 0 %then %do; data euler; format Error 5.3; /*--Number of obs in each set--*/ ns1=&n1; /*--Set 1 only--*/ ns2=&n2; /*--Set 2 only--*/ nsi=∋ /*--Set 1 & 2--*/ nc1=ns1+nsi; /*--Number of obs in circle 1--*/ nc2=ns2+nsi; /*--Number of obs in circle 2--*/ r1=10; /*--Assumed Radius of circle 1--*/ r2=r1*sqrt(nc2/nc1); /*--Proportional radius of circle 2--*/ xo1=0; yo1=0; xo2=xo1+r1+r2; yo2=0; /*--Location of the text labels--*/ xt1=xo1; xt2=xo2; xti=.; output; run; /*--Define template--*/ proc template; define statgraph euler_bubble_S1; begingraph; entrytitle 'Proportional Euler Diagram'; entryfootnote halign=left "N1=&n1 N2=&n2 Ni=&ni Error = 0"; layout overlayequated / cycleattrs=true walldisplay=none xaxisopts=(display=none) yaxisopts=(display=none); bubbleplot x=xo1 y=yo1 size=r1 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; bubbleplot x=xo2 y=yo2 size=r2 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; textplot x=xt1 y=yo1 text=ns1 / textattrs=(size=16) strip=true; textplot x=xt2 y=yo1 text=ns2 / textattrs=(size=16) strip=true; textplot x=xti y=yo1 text=nsi / textattrs=(size=16) strip=true; discretelegend 'a'; endlayout; endgraph; end; run; /*--Render the graph--*/ proc sgrender data=euler template=euler_bubble_S1; run; %end; %else %do; /*--Define a two set proportional Euler Diagram--*/ data euler; format Error 5.3; pi=constant("PI"); /*--Number of obs in each set--*/ ns1=&n1; /*--Set 1 only--*/ ns2=&n2; /*--Set 2 only--*/ nsi=∋ /*--Set 1 & 2--*/ nc1=ns1+nsi; /*--Number of obs in circle 1--*/ nc2=ns2+nsi; /*--Number of obs in circle 2--*/ r1=10; /*--Assumed Radius of circle 1--*/ r2=r1*sqrt(nc2/nc1); /*--Proportional radius of circle 2--*/ A1=pi*r1*r1; A2=pi*r2*r2; v=1; /*--Half the vertical leg on intersection line--*/ err=1; count=0; done=0; do while (done = 0); th1=arsin(v/r1); th2=arsin(v/r2); d1=r1*cos(th1); d2=r2*cos(th2); /*--Area of sector for angle 2*th--*/ s1=r1*r1*th1; s2=r2*r2*th2; /*--Area of triangle for angle 2*th--*/ t1=d1*v; t2=d2*v; /*--Area of intersection and for each set--*/ Asi=s1+s2-t1-t2; As1=A1-Asi; As2=A2-Asi; na1=ns1/As1; na2=ns2/As2; nai=nsi/Asi; /*--Center of the circles--*/ xo1=0; yo1=0; xo2=d1+d2; yo2=0; /*--Location of the text labels--*/ xt1=((xo2-r2)+(xo1-r1))/2; xt2=((xo1+r1)+(xo2+r2))/2; xti=xo1+d1; err=sqrt(nai/na1); output; if count=0 then v=v+1; else do; v=min(r2*.999999,(2*v+v*err)/3); end; count+1; error=abs(err-1); if error < 0.001 or count > 10 then done=1; end; /*--Intersection if beyond center of 2nd circle--*/ if error >= 0.001 then do; %put Second section; v=0.99*r2; /*--Half the vertical leg on intersection line--*/ err=1; count=0; done=0; do while (done = 0); th1=arsin(v/r1); th2=arsin(v/r2); d1=r1*cos(th1); d2=r2*cos(th2); /*--Area of sector and triangle for angle 2*th1--*/ s1=r1*r1*th1; t1=d1*v; /*--Area of sector for angle 2*th2--*/ s2=r2*r2*th2; /*--Area of intersection and for each set--*/ Asi=s1-t1+A2-s2; As1=A1-Asi; As2=A2-Asi; na1=ns1/As1; na2=ns2/As2; nai=nsi/Asi; /*--Center of the circles--*/ xo1=0; yo1=0; xo2=d1-d2; yo2=0; /*--Location of the text labels--*/ xt1=((xo1-r1)+(xo2-r2))/2; xt2=((xo1+r1)+(xo2+r2))/2; xti=((xo1+r1)+(xo2-r2))/2; err=sqrt(na1/nai); output; if count=0 then v=v-1; else do; v=min(r2*.999999,(2*v+v*err)/3); end; count+1; error=abs(err-1); if error < 0.001 or count > 10 then done=1; end; end; call symput("Error", put(Error, 5.3)); run; /*--Keep only last obs--*/ data euler1; set euler end=last; if last then output; run; /*--Define template--*/ proc template; define statgraph euler_bubble; dynamic _err; begingraph; entrytitle 'Proportional Euler Diagram'; entryfootnote halign=left "N1=&n1 N2=&n2 Ni=&ni Error = " _err; layout overlayequated / cycleattrs=true walldisplay=none xaxisopts=(display=none) yaxisopts=(display=none); bubbleplot x=xo1 y=yo1 size=r1 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; bubbleplot x=xo2 y=yo2 size=r2 / display=(fill outline) relativescale=false datatransparency=0.5 dataskin=&skin; textplot x=xt1 y=yo1 text=ns1 / textattrs=(size=16) strip=true; textplot x=xt2 y=yo1 text=ns2 / textattrs=(size=16) strip=true; textplot x=xti y=yo1 text=nsi / textattrs=(size=16) strip=true; discretelegend 'a'; endlayout; endgraph; end; run; /*--Render the graph--*/ proc sgrender data=euler1 template=euler_bubble; dynamic _err=&Error; run; %end; %finished: %mend Euler_Macro; %let gpath='C:\'; %let dpi=200; ods html close; ods listing gpath=&gpath image_dpi=&dpi;; options mautosource mprint mlogic; /*ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_25_15_10_Both_Pressed';*/ /*%Euler_Macro (n1=25, n2=15, ni=10, skin=pressed);*/ /**/ /*ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_25_2_5_Both_Sheen';*/ /*%Euler_Macro (n1=25, n2=5, ni=2, skin=sheen);*/ /**/ /*ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_25_40_10_Both_None';*/ /*%Euler_Macro (n1=25, n2=40, ni=10, skin=none);*/ /*ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_20_20_20_Both_None';*/ /*%Euler_Macro (n1=20, n2=10, ni=20, skin=none);*/ ods listing style=analysis; ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_20_10_None'; %Euler_Macro (n1=30, n2=20, ni=10, skin=None); ods listing style=analysis; ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_20_10_Sheen'; %Euler_Macro (n1=30, n2=20, ni=10, skin=sheen); ods listing style=analysis; ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_20_10_gloss'; %Euler_Macro (n1=30, n2=20, ni=10, skin=gloss); ods listing style=analysis; ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_10_30_gloss'; %Euler_Macro (n1=30, n2=10, ni=30, skin=gloss); /*--Special case N2=0--*/ ods listing style=listing; ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_0_20_sheen'; %Euler_Macro (n1=30, n2=0, ni=20, skin=sheen); /*--Special case NI=0--*/ ods graphics / reset attrpriority=color width=5in height=3in imagename='Euler_30_20_0_Sheen'; %Euler_Macro (n1=30, n2=20, ni=0, skin=sheen);