I have this Venn diagram:
from matplotlib_venn import venn2, venn2_circles
venn2(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'), set_colors=('r', 'g'), alpha = 0.5);
venn2_circles(subsets = (30, 10, 5));
Is it possible to change the line style to dashed of just the circle segments where Group A and B overlap (i.e. the lines around the brown area)?
By setting the edgecolor
on each of the patches in the venn diagram (A
, B
, and C
) we can see that the paths overlap around the overlapping section.
import matplotlib.pyplot as plt
from matplotlib_venn import venn2, venn2_circles
for char in "ABC":
v = venn2(
subsets=(30, 10, 5),
set_labels=("Group A", "Group B"),
set_colors=("r", "g"),
alpha=0.5,
)
overlap = v.get_patch_by_id(char)
overlap.set_edgecolor("black")
overlap.set_alpha(1)
overlap.set_ls("dashed")
overlap.set_lw(1.5)
plt.show()
But, by using a contrasting colour we can outline the overlap. The downside to this method is that we loose the alpha
on the overlap.
# plot venn
v = venn2(
subsets=(30, 10, 5),
set_labels=("Group A", "Group B"),
set_colors=("r", "g"),
alpha=0.5,
)
# add circles
c = venn2_circles(subsets=(30, 10, 5), linewidth=2, color="black")
overlap = v.get_patch_by_id("C") # get the overlap
overlap.set_edgecolor("white") # set the edgecolor
overlap.set_alpha(1) # set the alpha to 1 otherwise
# we can't see the line
overlap.set_linestyle("dashed") # set a dashed line
overlap.set_linewidth(2) # set same linewidth as the circles
overlap.set_zorder(2) # bump overlap up a level so we can
# see the line
This method is completely untested outside of this problem As far as I can tell it should work for most 2-circle venn diagrams.
This one is a bit more involved, but it allows us to seamlessly add dashed lines around the overlap without affecting the alpha
.
It requires that we import a function from a private module in matplotlib_venn
, circle_circle_intersection
which we will use to create matplotlib.patches.Arc
s.
These arcs will replace the circles drawn by matplotlib_venn
.
import math
import matplotlib.pyplot as plt
from matplotlib.patches import Arc
from matplotlib_venn._math import circle_circle_intersection
# Create `v` and `c` as in the previous example
# Get the current ax
ax = plt.gca()
# Get the intersections of the circles
(P2x, P2y), (P3x, P3y) = circle_circle_intersection(
c[0].center, c[0].radius, c[1].center, c[1].radius
)
# Iterate through the circles matplotlib_venn added
for _c in c:
# remove the circle
_c.set_visible(False)
# get the center or the circle and the angle at the center (theta)
P1x, P1y = _c.center
theta = math.degrees(
math.atan2(P3y - P1y, P3x - P1x) - math.atan2(P2y - P1y, P2x - P1x)
)
# Add the Arcs
ax.add_patch(
Arc(
xy=_c.center,
width=_c.radius * 2,
height=_c.radius * 2,
linewidth=2,
color="black",
angle=theta / 2 if theta < 180 else theta / -2,
theta2=360 - theta if theta < 180 else theta,
)
)
ax.add_patch(
Arc(
xy=_c.center,
width=_c.radius * 2,
height=_c.radius * 2,
linewidth=2,
color="black",
linestyle="dashed",
angle=theta / 2 if theta > 180 else theta / -2,
theta2=360 - theta if theta > 180 else theta,
)
)
plt.show()
Which produces: