2

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));

enter image description here

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)?

justinian482
  • 845
  • 2
  • 10
  • 18
  • 1
    I don't know `matplotlib` well, but have found an online resource that shows an example of this. [The resource is here.](https://www.programmersought.com/article/22117010728/#%E4%B8%AA%E6%80%A7%E5%8C%96%E8%AE%BE%E7%BD%AE%E5%9B%BE%E4%B8%AD7%E9%83%A8%E5%88%86%E6%AF%8F%E4%B8%80%E9%83%A8%E5%88%86) When you have solved your problem please remember to post the solution. – LaytonGB Jul 06 '21 at 10:54
  • 1
    I've updated my answer to include another method for adding this line style, though it is quite involved. – Alex Jul 06 '21 at 17:09
  • 1
    Thank you so much for taking the time to give such a comprehensive answer – justinian482 Jul 06 '21 at 17:25

1 Answers1

3

Option 1

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()
A B C
A B C

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

overlapped section with dashed edge


Option 2

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.Arcs.

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:

Overlapping venn diagram with different edges and preserved alpha

Alex
  • 6,610
  • 3
  • 20
  • 38