VENN Plot 2 or 3 circle areaproportional Venn diagram
VENN offers the following advantages over the VennX function available on the FEX:
1) It's much faster
2) Draws venn diagram as patch objects, allowing much greater flexibility in presentation (edge/face colors, transparency, etc.)
3) Returns a structure with required plotting data, allowing the user to make additional modifications (translation, scaling, rotation, etc.)
4) Supports multiple methods for optimizing the position of threecircle venn diagrams.
venn(A, I)
venn(Z)
venn(..., 'ErrMinMode', MODE)
H = venn(...)
[H, S] = venn(...)
[H, S] = venn(..., 'Plot', 'off')
S = venn(..., 'Plot', 'off')
[...] = venn(..., P1, V1, P2, V2, ...)
venn(A, I) by itself plots circles with total areas A, and intersection area(s) I. For twocircle venn diagrams, A is a two element vector of circle areas [c1 c2] and I is a scalar specifying the area of intersection between them. For threecircle venn diagrams, A is a three element vector [c1 c2 c3], and I is a four element vector [i12 i13 i23 i123], specifiying the twocircle intersection areas i12, i13, i23, and the threecircle intersection i123.
venn(..., 'ErrMinMode', MODE)
Used for 3circle venn diagrams only. MODE can be 'TotalError' (default), 'None', or 'ChowRodgers'. When ErrMinMode is 'None', the positions and sizes of the three circles are fixed by their pairwiseintersections, which means there may be a large amount of error in the area of the threecircle intersection. Specifying ErrMinMode as 'TotalError' attempts to minimize the total error in all four intersection zones. The areas of the three circles are kept constant in proportion to their populations. The 'ChowRodgers' mode uses the the method proposed by Chow and Rodgers [Ref. 1] to draw 'nice' threecircle venn diagrams which appear more visually representative of the desired areas, although the actual areas of the circles are allowed to deviate from requested values.
H = venn(...) returns a two or three element vector of handles to the patches representing the circles.
[H, S] = venn(...) returns a structure containing descriptive valuescomputed for the requested venn diagram.
[...] = venn(..., P1, V1, P2, V2, ...) Specifies additional patch settings in standard Matlab parameter/value pair syntax. Parameters can be any valid patch parameter. Values for patch parameters can either be single values, or a cell array of length LENGTH(A), in which case each value in the cell array is applied to the corresponding circle in A.
See venn.m for additional options, descriptions, references, and examples.
Darik (2020). venn (https://www.mathworks.com/matlabcentral/fileexchange/22282venn), MATLAB Central File Exchange. Retrieved .
1.7.0.0  Bugfix: ChowRodgers mode failed when initial guess had zero three circle intersection 

1.6.0.0  Fixed a typo in the help comments 

1.4.0.0  Fixed a bug found by Eran Mukamel where zone centroids in the returned structure were miscalculated in some cases. 

1.3.0.0  Fixed a bug found by Or Zuk (bug report via email) where zone centroids weren't properly calculated for twoset diagrams. 
Inspired by: Proportional Venn Diagrams
Create scripts with code, output, and formatted text in a single executable document.
Florian Schwaiger (view profile)
Fixed the bug "Triangle inequality not satisfied". Replace the block raising the error by the following code. Reason is, if one circle is within the other, all three circles are on one line and due to minimization inaccuracy, d1+d2<d3 is possible, violating the triangle equation.
%Check triangle inequality
srtD = sort(d);
if srtD(end) < (srtD(1) + srtD(2))
%Guess the initial position of the third circle using the law of cosines
alpha = acos( (d(1)^2 + d(2)^2  d(3)^2) / (2 * d(1) * d(2)) );
x(3) = d(2)*cos(alpha);
y(3) = d(2)*sin(alpha);
else
% Guess the initial position of the third circle using mean
% distance
IM = max(I0);
if (I0(2) == IM && A0(1) > A0(3))  (I0(3) == IM && A0(2) > A0(3))
% #1 is the inner most circle
x(3) = (d(1) + d(2)  d(3)) / 2;
elseif (I0(1) == IM && A0(2) > A0(1))  (I0(2) == IM && A0(3) > A0(1))
% #2 is the inner most circle
x(3) = (d(1)  d(2)  d(3)) / 2;
elseif (I0(1) == IM && A0(1) > A0(2))  (I0(3) == IM && A0(3) > A0(2))
% #3 is the inner most circle
x(3) = (d(1) + d(2) + d(3)) / 2;
end
end
cmo (view profile)
Matthew (view profile)
Tong Sheng (view profile)
With regards to "When I put text onto the graph (suppose for simplicity I want to put the amount % of each zone in each zone centroid), when I set a transparency (alpha <1), the text becomes faded as if the circles were covering it."
Just to update, this is no longer an issue when I export the figure as jpg, etc.; the text appears opaque and not covered by the patches.
Tong Sheng (view profile)
Thank you, Darik. I will give that a try.
Another comment/question: when I put text onto the graph (suppose for simplicity I want to put the amount % of each zone in each zone centroid), when I set a transparency (alpha <1), the text becomes faded as if the circles were covering it. Ideally I would like the text to be bold and clear on top of the semitransparent circles. Anyone else have this same problem, or know of a workaround? Thanks.
Darik (view profile)
@Tong: I suppose you could tweak the position of the circles manually via the returned handles:
%Build the venn plot and return the handles
h = venn(...)
%Shift the first circle by (dx, dy)
set(h(1), 'XData', dx + get(h(1), 'XData'))
set(h(1), 'YData', dy + get(h(1), 'YData'))
Tong Sheng (view profile)
I have a 3circle diagram in which one of my zones is empty (for [z1 z2 z3 z12 z13 z23 z123], z1 = 0), but an area/patch is still drawn. I think if the centroid for circle1 is shifted so that it fits completely inside the other two circles, that would be ok. How can I do this?
Fabiano Baroni (view profile)
great work, thanks.
I noticed that sometimes this error is returned: "Triangle inequality not satisfied", for example if A=[15 14 3]; I=[13 1 0 0].
It seems to be related to the constrain that circle centres shall not be further apart than rA+rB:
D = fminbnd(@areadiff, 0, rA+rB, opts);
Can you please suggest a solution or a workaround for this issue? Many thanks.
Hiren (view profile)
Eugene Gallagher (view profile)
Thanks Darik. You were right. My 2013a had a faulty Matlab path statement and wasn't finding my optimization toolbox. I changed back to the default path, rebuilt my path for my directories, and Venn.m worked beautifully. Thanks.
Darik (view profile)
Eugene: optimset is a function in the optimization toolbox. I suspect you have that toolbox installed in your Matlab 2012, but not 2013.
Eugene Gallagher (view profile)
While the function works great in Matlab Release 2012a, it produces errors in Release 2013a:
>> figure, axis equal, axis off;A=[100 100];I=25;venn(A,I,'FaceColor',{'r','y'},'FaceAlpha',{1,0.6},'EdgeColor','black')
Undefined function 'optimset' for input arguments of type 'char'.
Error in venn>parseArgsIn (line 860)
fminOpts = [optimset('fminbnd'), optimset('fminsearch')];
Error in venn (line 166)
[A0, I0, Z0, nCirc, fminOpts, vennOpts, patchOpts] = parseArgsIn (varargin);
Darik (view profile)
@RyanG sure, just set the intersection between those two circles equal to the area of the smaller (enclosed) circle. But depending on the area of the third circle and its intesections, a solution may not be possible.
Ryan G (view profile)
Is it possible to create a 3circle venn diagram such that 1 circle is entirely inside another?
Darik (view profile)
the cyclist: that would be a pretty embarrassing bug on my part. what about circles drawn by other functions, like:
cla, rectangle('Curvature', [1 1], 'Position', [0 0 1 1]); axis equal
?
the cyclist (view profile)
Great function. Seems to work just as advertised (in my limited trial). However, the areas don't look quite circular to me, whether or not I apply "axis square" after running venn.
Is that expected? I am using R2012b.
Rob Campbell (view profile)
Matt (view profile)
moggces (view profile)
[h, s] = venn([49, 58, 108], [33, 1, 17, 0], 'ErrMinMode', 'ChowRodgers');
This will prompt errors and can't generate h and s variables.
Jeremy (view profile)
Nevermind my last comment. As long as you center the text labels vertically and horizontally, the zone centroids work quite well. Nice work!
Jeremy (view profile)
Great job on the function. My only beef is that the zone centroids don't seem to be quite accurate.
Darik (view profile)
Hi Yuri,
You can try the ChowRodgers mode, which adjusts area ratios instead of absolute areas, and seems to give more satisfying results when actual solutions are impossible. Unfortunately when I tried your dataset I found a small bug in the code  I just submitted a fix, but it will take a day or two to show up on FEX. If you want you can just fix it yourself: line 563 says:
x = NaN; y = NaN;
It should be edited to include:
x = NaN; y = NaN; sinTp = NaN; cosTp = NaN;
Then you can plot the approximate venn diagram with
venn([477 487 370 3 54 5 2], 'ErrMinMode', 'ChowRodgers')
Yuri K (view profile)
Trying to build venn diagram with the vector v=[477 487 370 3 54 5 2];
Without any additional parameters I've got an error:
Exiting: Maximum number of function evaluations has been exceeded
 increase MaxFunEvals option.
Current function value: Inf
Worked only with
venn(v,'ErrMinMode','None');
but didn't get any 123 intersection. No problem with vennX, but I really like the idea of vector graphics.
I don't need exact proportions, something close would be good enough.
Omar (view profile)
Eran Mukamel (view profile)
Thanks for the bug fix!
Darik (view profile)
Hey Eran, can you paste the error you get? Also what version of Matlab are you using?
Eran Mukamel (view profile)
Functionality of syntax: [H, S] = venn(...) does not work for me.
Or Zuk (view profile)
Darik (view profile)
Hi Or,
You can do this with the returned structure:
[H, S] = venn(...)
for i = 1:length(S.ZoneCentroid)
text(S.ZoneCentroid(i,1), S.ZoneCentroid(i,2), num2str(S.ZonePop(i)));
end
Or Zuk (view profile)
Works great.
The only thing missing (which appears in VennX) is a display
the sizes of each set on the venn diagram itself. Is it easy to add this?