Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
Eunoia 0.4.0
Logo
Eunoia 0.4.0

Contents

  • Home
  • Quickstart
  • A gallery of Euler and Venn diagrams
  • Comparison with other Python packages
  • API reference
    • eunoia.euler
    • eunoia.venn
    • eunoia.options
    • eunoia.get_options
    • eunoia.reset_options
    • eunoia.EulerFit
    • eunoia.Circle
    • eunoia.Ellipse
    • eunoia.Point
    • eunoia.EunoiaError
Back to top
View this page

A gallery of Euler and Venn diagrams¶

This page is a gallery of Euler and Venn diagrams and a showcase of the customization options available through plot(). It is the Python counterpart to the eulerr gallery.

import matplotlib.pyplot as plt

import eunoia as eu

Euler diagrams¶

Uniform intersections¶

Here we use squares instead of the default circles.

fit = eu.euler(
    {
        "A": 10,
        "B": 10,
        "C": 10,
        "A&B": 4,
        "A&C": 4,
        "B&C": 4,
        "A&B&C": 2,
    },
    shape="square",
)
fit.plot();
_images/3a01437ff7bb6f4be327042eda205c75507291fa4e041496ae57cb09d56c4b93.png

Disjoint sets¶

Rename the sets simply by choosing the dictionary keys. A flat edges dict is applied to every outline.

fit = eu.euler({"Tom": 1, "Greg": 1, "Alberta": 1})
fit.plot(edges={"linestyle": "--"});
_images/2c540ada08ffc00fc912deb20bfa59adac2f289fd7a3a44ae316e298928e04d0.png

To style each outline independently, pass edges as a dict keyed by set name (each value a dict of PathPatch kwargs) or as a sequence of such dicts, one per set in shape order — mirroring how colors accepts a per-set dict.

fit = eu.euler({"Tom": 1, "Greg": 1, "Alberta": 1})
fit.plot(
    edges={
        "Tom": {"linestyle": "--", "linewidth": 2},
        "Greg": {"linestyle": ":"},
    },
);
_images/fd6106f8421bb9cee2a9074023c975a8ddc88835f9a38ca17d6e468b6c597b61.png

A set contained in the intersection of two sets¶

fit = eu.euler(
    {
        "A": 15,
        "B": 15,
        "C": 0,
        "A&B": 3,
        "A&C": 0,
        "B&C": 0,
        "A&B&C": 3,
    }
)
fit.plot(
    colors=["black", "cyan", "orange"],
    edges={"edgecolor": "white", "linewidth": 2},
);
_images/4eb5405bd7d5c020d7973120d1a10843f1f599f86feae713d2139f3a4ea64057.png

Two sets intersecting inside a third¶

Here we override individual region fills with per-region fills styles.

fit = eu.euler(
    {
        "A": 15,
        "B": 0,
        "C": 0,
        "A&B": 3,
        "A&C": 3,
        "B&C": 0,
        "A&B&C": 2,
    }
)
fit.plot(
    fills={
        "A&B&C": {"facecolor": "orange"},
        "A&B": {"facecolor": "lightblue"},
        "A&C": {"facecolor": "lightsalmon"},
    },
);
_images/3323f356e5709598cdd8be772e0af72330932d281e2c3e6f8be9c945f2e90192.png

Difficult set (for circles!)¶

This relationship cannot be drawn exactly with circles but works well with ellipses.

fit = eu.euler(
    {"A": 7, "B": 6, "C": 0, "A&B": 0, "A&C": 1, "B&C": 1, "A&B&C": 2},
    shape="ellipse",
)
fit.plot(quantities=True);
_images/d120cd11213cc78521a6eb89dc0bec15233581d07af4905f801ef9e97fb8f048.png

Russian doll¶

Sets intersecting inside other sets.

fit = eu.euler(
    {
        "A": 15,
        "B": 0,
        "C": 0,
        "A&B": 10,
        "A&C": 0,
        "B&C": 0,
        "A&B&C": 5,
    }
)
fit.plot();
_images/855a0b62d5b54202214b95b6355f933d7d867c28e1ddecf3de095c1f05ec4830.png

Wilkinson set relationship¶

This set relationship is taken from Wilkinson et al. It works best with ellipses. We show the fitted values rather than the requested ones.

fit = eu.euler(
    {
        "A": 4,
        "B": 6,
        "C": 3,
        "D": 2,
        "E": 7,
        "F": 3,
        "A&B": 2,
        "A&F": 2,
        "B&C": 2,
        "B&D": 1,
        "B&F": 2,
        "C&D": 1,
        "D&E": 1,
        "E&F": 1,
        "A&B&F": 1,
        "B&C&D": 1,
    },
    shape="ellipse",
)
fit.plot(quantities="fitted", edges={"linestyle": ":"});
_images/e6431c1961238364395b13ec51905ec2a6a33cc013b115a5b30836f5ab3cff91.png

Gene set¶

fit = eu.euler(
    {
        "SE": 13,
        "Treat": 28,
        "Anti-CCP": 101,
        "DAS28": 91,
        "SE&Treat": 1,
        "SE&DAS28": 14,
        "Treat&Anti-CCP": 6,
        "SE&Anti-CCP&DAS28": 1,
    }
)
fit.plot(quantities=True);
_images/4dd0be54a28748605d8d158992921efee008f0dbe69b4649cbf791097ffedb3c.png

Three sets intersecting inside a fourth¶

fit = eu.euler(
    {
        "A": 30,
        "A&B": 3,
        "A&C": 3,
        "A&D": 3,
        "A&B&C": 0.4,
        "A&B&D": 0.4,
        "A&C&D": 0.4,
        "A&B&C&D": 1,
    }
)
fit.plot();
_images/45b351f33b0b14dec3d53cd58929a810215f840d45dfb9a857adaa503344a9bc.png

eulerAPE combination¶

A combination taken from the eulerAPE article, fit with ellipses.

fit = eu.euler(
    {
        "a": 3491,
        "b": 3409,
        "c": 3503,
        "a&b": 120,
        "a&c": 114,
        "b&c": 132,
        "a&b&c": 126,
    },
    shape="ellipse",
)
fit.plot();
_images/018b1856907aad4fcc2325adecd77e964bfe46473e5133198b199e28eece4414.png

Four uniform interactions¶

This time we fit the diagram using rectangles.

fit = eu.euler(
    {
        "Frodo": 10,
        "Sam": 10,
        "Merry": 10,
        "Pippin": 10,
        "Frodo&Sam": 3,
        "Frodo&Merry": 3,
        "Frodo&Pippin": 0,
        "Sam&Merry": 0,
        "Sam&Pippin": 3,
        "Merry&Pippin": 3,
        "Frodo&Sam&Merry": 1,
        "Frodo&Sam&Pippin": 1,
        "Frodo&Merry&Pippin": 1,
        "Sam&Merry&Pippin": 1,
        "Frodo&Sam&Merry&Pippin": 1,
    },
    shape="rectangle",
)
fit.plot();
_images/09be9cda4c4346f184d23effd26cfc98be50608fe5c740dff8aa5f355613dcef.png

Two circles intersecting completely¶

fit = eu.euler({"A": 0, "B": 0, "A&B": 10})
fit.plot();
_images/0671762de6e9685023941f2057cfd318f2250b2143a76761f7873ca5b11311ca.png

Styling and the complement¶

A universe (complement) box¶

Pass complement= to euler() to reserve area outside every set; it comes back as a container that plot() draws behind everything. The complement= plot keyword styles that box.

fit = eu.euler({"A": 10, "B": 8, "A&B": 4}, complement=20)
fit.plot(complement={"facecolor": "#eeeeee"}, quantities=True);
_images/982bc46438d5dbf909fca32413f7bdbdd94a145331e27142f5a075ff1a71e7cf.png

Colors as a sequence or a mapping¶

colors accepts either a sequence (one per set, in fit order) or a mapping from set name to color.

fit = eu.euler(
    {"A": 10, "B": 7, "C": 8, "A&B": 3, "A&C": 4, "B&C": 2, "A&B&C": 1}
)
fit.plot(colors={"A": "#e41a1c", "B": "#377eb8", "C": "#4daf4a"});
_images/f2c9e34dd55aa317042e822d63b89d53c63eb679228351fd38906b1f8069c0d6.png

A legend instead of inline labels¶

When sets are small or crowded their inline labels can overlap. Passing legend=True moves the set names into a color-keyed legend and turns the inline labels off by default (pass labels=True to keep both). A dict is forwarded to matplotlib’s Axes.legend, so you can control placement and title.

fit = eu.euler(
    {"A": 10, "B": 7, "C": 8, "A&B": 3, "A&C": 4, "B&C": 2, "A&B&C": 1}
)
fit.plot(legend={"loc": "upper right", "title": "Sets"});
_images/debb320b3c53956dc5b78524fe39e1ba9368ebfd9298a385a655c0b5c68c751b.png

Custom label text and style¶

labels can be a dict for per-set control. Map a set name to a replacement string (matplotlib mathtext works, which is part of why we picked matplotlib), to an Axes.text kwargs dict (with an optional "text" key for custom text), or to None/False to hide that set’s label. A dict whose keys are not set names — e.g. {"fontsize": 14} — is a uniform style applied to every label instead.

fit = eu.euler({"alpha": 10, "beta": 7, "alpha&beta": 3})
fit.plot(
    labels={
        "alpha": {"text": r"$\alpha$", "fontsize": 22},
        "beta": {"text": r"$\beta$", "fontsize": 22, "color": "crimson"},
    },
);
_images/f9c217040c0d884d44cc54411c76791b9cdc22cfb9d40f93f70444ebf0da583c.png

Original versus fitted quantities¶

Drawing into axes we create ourselves lets us place two diagrams side by side to compare the requested values against what the layout achieved.

fit = eu.euler(
    {"A": 7, "B": 6, "A&C": 1, "B&C": 1, "A&B&C": 2, "C": 0},
    shape="ellipse",
)

fig, (left, right) = plt.subplots(1, 2, figsize=(9, 4))
fit.plot(ax=left, quantities="original")
left.set_title("original")
fit.plot(ax=right, quantities="fitted")
right.set_title("fitted")
fig;
_images/2ff812b3ea24a675b0bc6fc895fd45c3aee1fc558b4e92d06d5a8417f7a79505.png

Counts and percentages¶

quantities also chooses how to display each region. A string picks the display type—"counts" (the raw value, the default) or "percent" (the region’s share of the total)—while a dict combines a type, a value source, and text styling. Passing both types stacks the count above its percentage.

fit = eu.euler(
    {
        "SE": 13,
        "Treat": 28,
        "Anti-CCP": 101,
        "DAS28": 91,
        "SE&Treat": 1,
        "SE&DAS28": 14,
        "Treat&Anti-CCP": 6,
        "SE&Anti-CCP&DAS28": 1,
    }
)
fit.plot(quantities={"type": ["counts", "percent"], "fontsize": 8});
_images/6c42eeeb7e120ff3e73dbcd90892349b242d4aba1fd2644579c620a0846cb414.png

Venn diagrams¶

venn() draws topological (non-proportional) Venn diagrams. It accepts an integer count, a list of names, or a mapping. The default shape is the ellipse, which supports one through five sets.

{note} Circle Venn diagrams are unsupported in the pinned Eunoia core and raise an {class}`~eunoia.EunoiaError`. Use ellipses (1–5 sets) or squares/rectangles (1–3 sets).

Two and three sets¶

fig, (left, right) = plt.subplots(1, 2, figsize=(9, 4))
eu.venn(2).plot(ax=left)
eu.venn(["A", "B", "C"]).plot(ax=right)
fig;
_images/8f62921e468f669e442aeb006cc11daf37860b295240ab240820e3826b9599c5.png

Four and five sets¶

fig, (left, right) = plt.subplots(1, 2, figsize=(9, 4))
eu.venn(4).plot(ax=left)
eu.venn(5).plot(ax=right)
fig;
_images/c0b1c4bafd992fde073ae736a0363446bb6496454ecfe174613a2a667bc05544.png

Squares and rectangles¶

Square and rectangle Venn diagrams support up to three sets.

fig, (left, right) = plt.subplots(1, 2, figsize=(9, 4))
eu.venn(3, shape="square").plot(ax=left)
eu.venn(3, shape="rectangle").plot(ax=right)
fig;
_images/6f631bdccb1dbbef41ae7748e78bef56afcf2131b7c8ad7504b2734366bad887.png

With region quantities¶

venn accepts the same value mapping as euler. The layout stays topological, but the values are kept as original_values and plot() labels each region automatically (pass quantities=False to suppress them). This is the usual “Venn diagram with subset sizes” plot.

eu.venn(
    {
        "A": 12, "B": 9, "C": 7,
        "A&B": 4, "A&C": 3, "B&C": 2, "A&B&C": 1,
    }
).plot();
_images/2bd984aefa815e8644b82d2e8c7bb4c4fdd4d1f8f9edbb8b483bd603c87dffad.png

Use input="inclusive" when the values are total set sizes (overlaps included) rather than per-region counts.

From membership lists¶

venn accepts the same membership-list input as euler; it counts each element into its region, so the quantities are shown just as above.

eu.venn({"A": ["x", "y", "z"], "B": ["y", "z", "w"], "C": ["z", "w", "q"]}).plot();
_images/2226e062cc48b4328c72a0bc827d1747e5f3ae2c2327ba2645c20c7fa10f4c39.png
Next
Comparison with other Python packages
Previous
Quickstart
Copyright © 2026, Johan Larsson
Made with Sphinx and @pradyunsg's Furo
On this page
  • A gallery of Euler and Venn diagrams
    • Euler diagrams
      • Uniform intersections
      • Disjoint sets
      • A set contained in the intersection of two sets
      • Two sets intersecting inside a third
      • Difficult set (for circles!)
      • Russian doll
      • Wilkinson set relationship
      • Gene set
      • Three sets intersecting inside a fourth
      • eulerAPE combination
      • Four uniform interactions
      • Two circles intersecting completely
    • Styling and the complement
      • A universe (complement) box
      • Colors as a sequence or a mapping
      • A legend instead of inline labels
      • Custom label text and style
      • Original versus fitted quantities
      • Counts and percentages
    • Venn diagrams
      • Two and three sets
      • Four and five sets
      • Squares and rectangles
      • With region quantities
      • From membership lists