Skip to content

Commit d5f0654

Browse files
authoredOct 6, 2024
Merge pull request opencobra#2339 from farid-zare/patch-4
Update venn4.m
2 parents 586780c + 68fad68 commit d5f0654

File tree

1 file changed

+119
-106
lines changed
  • external/visualization/venn4

1 file changed

+119
-106
lines changed
 

‎external/visualization/venn4/venn4.m

+119-106
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
function vennfig = venn4(n,varargin)
2-
% Draw venn diagram with two to four sets with optional text labels.
2+
%% Draw venn diagram with two to four sets with optional text labels.
33
% User can specify the number of sets to draw (maximum four) and label each
44
% set and the intersectional regions between sets.
5-
%
6-
% USAGE:
7-
% vennfig = venn4(n,varargin)
5+
% Man Ho Wong (2022).
86
%
9-
% INPUTS: n [positive integer]
7+
% Input : n [positive integer]
108
% Number of sets to draw
119
% sets [string | char | cellstr | numeric]
1210
% An array of set names in left-to-right order
1311
% labels [string | char | cellstr | numeric]
1412
% An array of label names for labeling each section;
15-
% Elements in the array must follow the following order:
13+
% Elements in the array must follow the following order:
1614
% For diagram with Set A and B, labels for 3 sections are
1715
% A, B and A&B.
1816
% For diagram with Set A, B and C, labels for 7 sections are
19-
% A, B, C, D, A&B, A&C, B&C and A&B&C.
17+
% A, B, C, A&B, A&C, B&C and A&B&C.
2018
% For diagram with Set A, B, C and D, labels for 15 sections
21-
% are A, B, C, D, A&B, A&C, A&D, B&C, B&D, C&D, A&B&C, A&B&D
19+
% are A, B, C, D, A&B, A&C, A&D, B&C, B&D, C&D, A&B&C, A&B&D
2220
% , A&C&D, B&C&D, A&B&C&D.
2321
% Any extra labels will be ignored.
2422
% colors [rows of RGB triplet]
@@ -27,28 +25,20 @@
2725
% If number of colors is less than n, colors will be
2826
% repeated.
2927
% alpha [0 to 1]
30-
% Fill color transparency; 0 = fully transparent.
28+
% Fill color alpha; 0 = fully transparent.
3129
% edgeC [RGB triplet]
3230
% Edge color (only effective when 'edgeW' is > 0).
3331
% edgeW [positive number]
3432
% Edge width (By default, there is no edge)
3533
% labelC [RGB triplet]
3634
% Color of section labels.
35+
% fontSize [positive number]
36+
% Font size for the text (default is adjusted based on number of sets).
3737
%
38-
% OUTPUT : A Veenn diagram will be drawn on a new figure.
38+
% Output : A Veenn diagram will be drawn on a new figure.
3939
% vennfig (optional): A handle to the figure.
4040
%
41-
% EXAMPLES: see README.md
42-
%
43-
% Reference:
44-
% cff-version: 1.2.0
45-
% ..Authors:
46-
% - family-names: Wong
47-
% given-names: Man Ho
48-
% orcid: https://orcid.org/0000-0002-3738-1914
49-
% version: 1.0.0
50-
% doi: 10.5281/zenodo.7297812
51-
% date-released: 2022-11-07
41+
% Examples: see README.md
5242

5343
% default set names
5444
s = repmat(" ",4,1); % white space as spaceholder
@@ -72,6 +62,7 @@
7262
addParameter(p,'edgeC', 'w', validColor);
7363
addParameter(p,'edgeW', [], validPosNum);
7464
addParameter(p,'labelC', 'k', validColor);
65+
addParameter(p,'fontSize', [], validPosNum); % Optional fontSize input
7566

7667
% Parse input
7768
parse(p,varargin{:});
@@ -82,6 +73,28 @@
8273
edgeC = p.Results.edgeC;
8374
edgeW = p.Results.edgeW;
8475
labelC = p.Results.labelC;
76+
fontSize = p.Results.fontSize;
77+
78+
% Default font sizes based on the number of sets
79+
if isempty(fontSize)
80+
switch n
81+
case 2
82+
fontSizeSets = 28;
83+
fontSizeIntersections = 24;
84+
case 3
85+
fontSizeSets = 26;
86+
fontSizeIntersections = 22;
87+
case 4
88+
fontSizeSets = 24;
89+
fontSizeIntersections = 20;
90+
otherwise
91+
error('n must be an integer between 2 and 4.');
92+
end
93+
else
94+
% If user provides a fontSize, use it for both sets and intersections, scaled appropriately
95+
fontSizeSets = fontSize + 2; % Slightly larger for set labels
96+
fontSizeIntersections = fontSize;
97+
end
8598

8699
% repeat colors if number of colors given is less than n
87100
if height(colors) < n
@@ -120,19 +133,19 @@
120133
B = v(2);
121134
C = v(3);
122135
D = v(4);
123-
136+
124137
AB = v(5);
125138
AC = v(6);
126139
AD = v(7);
127140
BC = v(8);
128141
BD = v(9);
129142
CD = v(10);
130-
143+
131144
ABC = v(11);
132145
ABD = v(12);
133146
ACD = v(13);
134147
BCD = v(14);
135-
148+
136149
ABCD = v(15);
137150
end
138151

@@ -154,97 +167,94 @@
154167
circle(X,Y,r,colors(1,:),alpha);
155168
circle(X+r,Y,r,colors(2,:),alpha);
156169
% draw circle A edge again (so it's not covered by circle B)
157-
circle(X,Y,r,[0 0 0],0);
170+
circle(X,Y,r,[0 0 0],0);
158171

159-
text(1,2.2,s(1),'HorizontalAlignment','right');
160-
text(2,2.2,s(2),'HorizontalAlignment','left');
172+
text(1,2.2,s(1),'HorizontalAlignment','right', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
173+
text(2,2.2,s(2),'HorizontalAlignment','left', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
161174

162-
text(0.5,1,A,'HorizontalAlignment','center')
163-
text(2.5,1,B,'HorizontalAlignment','center')
164-
text(1.5,1,AB,'HorizontalAlignment','center')
175+
text(0.5,1,A,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
176+
text(2.5,1,B,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
177+
text(1.5,1,AB,'HorizontalAlignment','center', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
165178

166179
case 3
167180
xlim([-0.5 4])
168181
circle(X,Y,r,colors(1,:),alpha);
169182
circle(X+r,Y,r,colors(2,:),alpha);
170183
circle(X+r/2,Y+r,r,colors(3,:),alpha);
171-
% draw circle A and B edge again (so they are not covered by circle C)
172-
circle(X,Y,r,[0 0 0],0);
173-
circle(X+r,Y,r,[0 0 0],0);
174184

175-
text(1.5,3.2,s(1),'HorizontalAlignment','center')
176-
text(-0.1,1,s(2),'HorizontalAlignment','right')
177-
text(3.1,1,s(3),'HorizontalAlignment','left')
185+
text(1.5,3.2,s(1),'HorizontalAlignment','center', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
186+
text(-0.1,1,s(2),'HorizontalAlignment','right', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
187+
text(3.1,1,s(3),'HorizontalAlignment','left', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
178188

179-
text(1.5,2.4,A,'HorizontalAlignment','center')
180-
text(0.5,1,B,'HorizontalAlignment','center')
181-
text(2.5,1,C,'HorizontalAlignment','center')
189+
text(1.5,2.4,A,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
190+
text(0.5,1,B,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
191+
text(2.5,1,C,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
182192

183-
text(1,1.75,AB,'HorizontalAlignment','center')
184-
text(1.5,0.75,BC,'HorizontalAlignment','center')
185-
text(2,1.75,AC,'HorizontalAlignment','center')
186-
187-
text(1.5,1.4,ABC,'HorizontalAlignment','center')
193+
text(1,1.75,AB,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
194+
text(1.5,0.75,BC,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
195+
text(2,1.75,AC,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold');
196+
197+
text(1.5,1.4,ABC,'HorizontalAlignment','center', 'FontSize', fontSizeSets, 'FontWeight', 'bold');
198+
199+
case 4
188200

189-
case 4
190201
xlim([-3.5 4])
191202

192-
% ellipse A and B
203+
% Draw ellipses for the sets
204+
% Ellipse A and B
193205
[X,Y] = getEllipse(0.8,1.6,[-1.1 1]);
194-
patch(X,Y,colors(1,:),'FaceAlpha',alpha,'LineStyle','none');
195-
patch(X+1,Y+0.5,colors(2,:),'FaceAlpha',alpha,'LineStyle','none');
206+
patch(X,Y,colors(1,:),'FaceAlpha',alpha,'LineStyle','none'); % Set A
207+
patch(X+1,Y+0.5,colors(2,:),'FaceAlpha',alpha,'LineStyle','none'); % Set B
196208

197-
% ellipse C and D
209+
% Ellipse C and D
198210
[X,Y] = getEllipse(1.6,0.8,[1.1 1]);
199-
patch(X-1,Y+0.5,colors(3,:),'FaceAlpha',alpha,'LineStyle','none');
200-
patch(X,Y,colors(4,:),'FaceAlpha',alpha,'LineStyle','none');
201-
202-
% draw ellipse edges separately (so they are not covered by others)
203-
patch(X-1,Y+0.5,'w','FaceAlpha',0,'LineStyle','none'); % ellipse C
204-
patch(X,Y,'w','FaceAlpha',0,'LineStyle','none'); % ellipse D
211+
patch(X-1,Y+0.5,colors(3,:),'FaceAlpha',alpha,'LineStyle','none'); % Set C
212+
patch(X,Y,colors(4,:),'FaceAlpha',alpha,'LineStyle','none'); % Set D
213+
214+
% Draw ellipse edges separately to ensure they're not covered by others
215+
patch(X-1,Y+0.5,'w','FaceAlpha',0,'LineStyle','none'); % Set C edge
216+
patch(X,Y,'w','FaceAlpha',0,'LineStyle','none'); % Set D edge
205217
[X,Y] = getEllipse(0.8,1.6,[-1.1 1]);
206-
patch(X,Y,'w','FaceAlpha',0,'LineStyle','none'); % ellipse A
207-
patch(X+1,Y+0.5,'w','FaceAlpha',0,'LineStyle','none'); % ellipse B
208-
209-
text(-3,3,s(1),'HorizontalAlignment','right')
210-
text(-2,3.5,s(2),'HorizontalAlignment','right')
211-
text(2,3.5,s(3),'HorizontalAlignment','left')
212-
text(3,3,s(4),'HorizontalAlignment','left')
213-
214-
text(-2,1.5,A,'HorizontalAlignment','center')
215-
text(2,1.5,D,'HorizontalAlignment','center')
216-
text(-1,2.75,B,'HorizontalAlignment','center')
217-
text(1,2.75,C,'HorizontalAlignment','center')
218-
219-
220-
text(-1.4,2.25,AB,'HorizontalAlignment','center')
221-
text(1.4,2.25,CD,'HorizontalAlignment','center')
222-
text(0,2.25,BC,'HorizontalAlignment','center')
223-
text(-1.25,0.5,AC,'HorizontalAlignment','center')
224-
text(1.25,0.5,BD,'HorizontalAlignment','center')
225-
text(0,-0.4,AD,'HorizontalAlignment','center')
226-
227-
text(-0.75,1.5,ABC,'HorizontalAlignment','center')
228-
text(0.75,1.5,BCD,'HorizontalAlignment','center')
229-
text(-0.4,0.05,ACD,'HorizontalAlignment','center')
230-
text(0.4,0.05,ABD,'HorizontalAlignment','center')
231-
232-
text(0,0.5,ABCD,'HorizontalAlignment','center')
233-
218+
patch(X,Y,'w','FaceAlpha',0,'LineStyle','none'); % Set A edge
219+
patch(X+1,Y+0.5,'w','FaceAlpha',0,'LineStyle','none'); % Set B edge
220+
221+
% Set Labels (A, B, C, D)
222+
text(-3,3,s(1),'HorizontalAlignment','right', 'FontSize', fontSizeSets, 'FontWeight', 'bold'); % Set A
223+
text(-2,3.5,s(2),'HorizontalAlignment','right', 'FontSize', fontSizeSets, 'FontWeight', 'bold'); % Set B
224+
text(2,3.5,s(3),'HorizontalAlignment','left', 'FontSize', fontSizeSets, 'FontWeight', 'bold'); % Set C
225+
text(3,3,s(4),'HorizontalAlignment','left', 'FontSize', fontSizeSets, 'FontWeight', 'bold'); % Set D
226+
227+
% Intersection Labels
228+
text(-2,1.5,A,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A only
229+
text(2,1.5,D,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % D only
230+
text(-1,2.75,B,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % B only
231+
text(1,2.75,C,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % C only
232+
233+
% Pairwise Intersections
234+
text(-1.4,2.25,AB,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&B
235+
text(1.4,2.25,CD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % C&D
236+
text(0,2.25,BC,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % B&C
237+
text(-1.25,0.5,AC,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&C
238+
text(1.25,0.5,BD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % B&D
239+
text(0,-0.4,AD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&D
240+
241+
% Triple Intersections
242+
text(-0.75,1.5,ABC,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&B&C
243+
text(0.75,1.5,BCD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % B&C&D
244+
text(-0.4,0.05,ACD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&C&D
245+
text(0.4,0.05,ABD,'HorizontalAlignment','center', 'FontSize', fontSizeIntersections, 'FontWeight', 'bold'); % A&B&D
246+
247+
% Quadruple Intersection (A&B&C&D)
248+
text(0,0.5,ABCD,'HorizontalAlignment','center', 'FontSize', fontSizeSets, 'FontWeight', 'bold'); % A&B&C&D
249+
234250
otherwise
235251
disp('n must be an integer between 2 and 4.')
236252
end
237253

238-
% Get all text objects
239-
h=vennfig.findobj('Type','text');
240-
241-
% Configure texts
242-
set(h,'fontsize',11,'FontWeight','bold');
254+
% Set label color
255+
h=vennfig.findobj('Type','text'); % Get all text objects
243256
for i = 1:length(h)
244-
if ismember(h(i).String,sets)
245-
h(i).FontSize = 14;
246-
h(i).FontWeight = 'bold';
247-
else
257+
if ~ ismember(h(i).String,sets)
248258
h(i).Color = labelC;
249259
end
250260
end
@@ -263,21 +273,24 @@
263273
end
264274

265275
%%
266-
function [x,y] = getEllipse(r1,r2,C)
267-
beta = linspace(0,2*pi,100);
268-
x = r1*cos(beta) - r2*sin(beta);
269-
y = r1*cos(beta) + r2*sin(beta);
270-
x = x + C(1,1);
271-
y = y + C(1,2);
272-
end
276+
function [x,y] = getEllipse(r1,r2,C)
277+
beta = linspace(0,2*pi,100);
278+
x = r1*cos(beta) - r2*sin(beta);
279+
y = r1*cos(beta) + r2*sin(beta);
280+
x = x + C(1,1);
281+
y = y + C(1,2);
282+
end
273283

274284
%%
275-
function circle(cX,cY,r,faceC,alpha)
276-
x = cX-r;
277-
y = cY-r;
278-
d = 2*r;
279-
fC = [faceC alpha];
280-
rectangle('Position',[x y d d],'Curvature',1,'FaceColor',fC,'LineStyle','none');
281-
end
285+
function circle(cX,cY,r,faceC,alpha)
286+
x = cX-r;
287+
y = cY-r;
288+
d = 2*r;
289+
h = rectangle('Position', [x y d d], 'Curvature', [1, 1], 'FaceColor', faceC, 'EdgeColor', faceC);
290+
% Adjust the alpha using the alpha function
291+
h.FaceAlpha = alpha;
292+
% Ensure the axes are set to equal scaling for proper aspect ratio
293+
axis equal;
294+
end
282295

283296
end

0 commit comments

Comments
 (0)
Please sign in to comment.