Quickstart

A two-set fit

The simplest case: two sets with one overlap.

import eunoia as eu

fit = eu.euler({"A": 10, "B": 5, "A&B": 3})
print(fit)
EulerFit (2 circles, diag_error=2.776e-17, stress=5.887e-33, loss=5.887e-33)
         original      fitted    residual regionError
  A            10          10           0           0
  B             5           5           0           0
  A&B           3           3   8.882e-16   2.776e-17
fit.plot();

Inclusive input

By default, values are interpreted as exclusive per-region areas. If your numbers are total set sizes that include overlaps, pass input="inclusive" and the eunoia core converts internally:

fit = eu.euler({"A": 13, "B": 8, "A&B": 3}, input="inclusive")
fit.original_values, fit.fitted_values
({'A': 13.0, 'B': 8.0, 'A&B': 3.0},
 {'A': 13.0, 'B': 7.999999999999999, 'A&B': 2.999999999999999})

Three sets with ellipses

Ellipses are more flexible than circles and can fit many three-set arrangements exactly:

fit = eu.euler(
    {"A": 2, "B": 2, "C": 2, "A&B": 1, "A&C": 1, "B&C": 1},
    shape="ellipse",
)
print(f"diag_error = {fit.diag_error:.3g}")
fit.plot(quantities="fitted");
diag_error = 2.04e-14

Custom styling

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=["#e41a1c", "#377eb8", "#4daf4a"],
    quantities=True,
    edges={"linewidth": 1.5},
);

Reproducibility

Pass a seed to fix the optimizer’s RNG:

fit_a = eu.euler({"A": 10, "B": 5, "A&B": 3}, seed=42)
fit_b = eu.euler({"A": 10, "B": 5, "A&B": 3}, seed=42)
fit_a.diag_error == fit_b.diag_error
True