I currently have a figure with 5 venn diagram subplots. All 5 diagrams are 2 circle venns and each have a different sum of elements.Refer to this figure.
I would like to know if it is possible to have these 6 subplots all to the same scale? For example, my entire first venn would be scaled to be smaller than the fifth one.
Code below. Any help most appreciated.
from matplotlib_venn import venn2
from matplotlib import pyplot as plt
import numpy as np
figure, axes = plt.subplots(2, 3, figsize=(11.69,8.27))
BSL_20=(313,10,76)
BSL_40=(384,17,150)
BSL_100=(665,8,378)
BSL_100CC=(860,23,879)
BSL_200=(585,17,758)
v1=venn2(BSL_20, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][0])
v2=venn2(BSL_40, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][1])
v3=venn2(BSL_100, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[0][2])
v4=venn2(BSL_100CC, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][0])
v5=venn2(BSL_200, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][1])
v6=venn2(BSL_200, set_labels = ('150mm at 50%', '400mm at 25%'), ax=axes[1][1])
axes[1,2].axis('off')
plt.show()
Try adding this to your code before plt.show()
:
from matplotlib.cbook import flatten
data = [BSL_20, BSL_40, BSL_100, BSL_100CC, BSL_200]
max_area = max(map(sum, data))
def set_venn_scale(ax, true_area, reference_area=max_area):
s = np.sqrt(float(reference_area)/true_area)
ax.set_xlim(-s, s)
ax.set_ylim(-s, s)
for a, d in zip(flatten(axes), data):
set_venn_scale(a, sum(d))
Explanation:
matplotlib_venn
draws are scaled so that their total area is 1. The diagram is positioned with its center near the point (0, 0) and axis limits are configured so that the diagram would fit tightly inside.xlim(-1, 1)
and ylim(-1, 1)
for all the subplots, you would get diagrams that all have the same total area (assuming all subplots are shown at the same scale).sqrt(2)
.sqrt(max_area/required_area)
.You could also cut some slack on the Y axis and pack the code and the diagram tighter as follows:
from matplotlib_venn import venn2
from matplotlib.cbook import flatten
from matplotlib import pyplot as plt
import numpy as np
figure, axes = plt.subplots(2, 3, figsize=(11.69,5.5))
BSL_20=(313,10,76)
BSL_40=(384,17,150)
BSL_100=(665,8,378)
BSL_100CC=(860,23,879)
BSL_200=(585,17,758)
data = [BSL_20, BSL_40, BSL_100, BSL_100CC, BSL_200]
max_area = max(map(sum, data))
def set_venn_scale(vd, ax, true_area, reference_area=max_area):
sx = np.sqrt(float(reference_area)/true_area)
sy = max(vd.radii)*1.3
ax.set_xlim(-sx, sx)
ax.set_ylim(-sy, sy)
for a, d in zip(flatten(axes), data):
vd = venn2(d, set_labels = ('150mm at 50%', '400mm at 25%'), ax=a)
set_venn_scale(vd, a, sum(d))
axes[1,2].axis('off')
figure.tight_layout(pad=0.1)
plt.show()
Note, though, that tight_layout
will start rescaling your subplots if it feels there is not enough space, so check the results (e.g by adding axes around your subplots via ax.set_axis_on()
and making sure all the subplots have the same width).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With