Euler Bar Chart#

The Euler bar chart visualizes overlapping sets. Each bar represents the union of two sets, drawn as two offset, semi-transparent rectangles whose physical overlap zone exactly represents the measured intersection between the sets. Bar height equals set_a + set_b - overlap (the inclusion-exclusion union).

This is different from a standard stacked bar chart because the segments are not mutually exclusive – they intentionally overlap, and the blended zone where the two rectangles intersect shows the overlap visually.

Like the pebble bar chart, Euler bar charts are rendered as self-contained HTML files with inline CSS and JavaScript (no external dependencies).

Euler bar chart example

Quick start#

from matviz import euler_bar_chart

categories = [
    {"name": "nyc", "label": "NYC",
     "set_a": 4, "set_b": 1905, "overlap": 4},
    {"name": "bos", "label": "Boston",
     "set_a": 12, "set_b": 340, "overlap": 8},
    {"name": "cam", "label": "Cambridge",
     "set_a": 3, "set_b": 120, "overlap": 2},
]

euler_bar_chart(
    categories,
    "overlap.html",
    title="City Reports",
    subtitle="Filed vs Total reports by city",
    set_a_label="Filed",
    set_b_label="Total",
    overlap_label="Both",
)

Open overlap.html in a browser to see the chart.

How it works#

Each bar has two semi-transparent rectangles drawn with a horizontal offset:

  • Set A (left-aligned): height proportional to set_a, starting at the baseline.

  • Set B (offset right): height proportional to set_b, starting at set_a - overlap from the baseline.

Because set B starts partway up set A, the physical overlap of the two rectangles equals the measured overlap. Both rectangles use mix-blend-mode: multiply so the intersection zone blends visually.

The total bar height is the union: set_a + set_b - overlap.

Category data#

Each category dict should have:

Key

Type

Description

name

str

Internal identifier

label

str

Display label under the bar

set_a

int/float

Size of set A

set_b

int/float

Size of set B

overlap

int/float

Size of the intersection

Key parameters#

Parameter

Default

Description

set_a_label

"Set A"

Display name for set A

set_b_label

"Set B"

Display name for set B

overlap_label

"Overlap"

Display name for the overlap

color_a

"#6A9BCC"

Color for set A rectangles

color_b

"#C46686"

Color for set B rectangles

opacity_a

0.72

Opacity for set A

opacity_b

0.62

Opacity for set B

bar_width

80

Pixel width of each bar

bar_gap

40

Pixels between bars

sort_desc

True

Sort by union total, largest first

show_values

True

Show union total above each bar

show_table

True

Show data table below chart

open_browser

False

Open file in default browser

Data table#

When show_table=True (the default), a table is rendered below the chart with columns: Category, Set A, Set B, Overlap, Union. The column headers use set_a_label and set_b_label.

API reference#

matviz.euler_bar.euler_bar_chart(categories: Sequence[Dict[str, Any]], output: str | Path | None = None, *, title: str = '', subtitle: str = '', set_a_label: str = 'Set A', set_b_label: str = 'Set B', overlap_label: str = 'Overlap', color_a: str = '#6A9BCC', color_b: str = '#C46686', opacity_a: float = 0.72, opacity_b: float = 0.62, bar_width: int = 80, bar_gap: int = 40, sort_desc: bool = True, show_values: bool = True, show_table: bool = True, font_family: str = 'system-ui, -apple-system, sans-serif', extra_css: str = '', open_browser: bool = False) → str[source]#

Generate an Euler bar chart as a self-contained HTML file.

An Euler bar chart visualizes overlapping sets. Each bar represents the union of two sets, drawn as two offset, semi-transparent rectangles whose physical overlap zone matches the measured intersection. Bar height equals set_a + set_b - overlap (the inclusion-exclusion union).

Parameters:
categorieslist of dict

Each category dict should have:

  • name (str): internal identifier

  • label (str): display label shown under the bar

  • set_a (int or float): size of set A

  • set_b (int or float): size of set B

  • overlap (int or float): size of the intersection (must be <= min(set_a, set_b))

outputstr or Path or None

Path to write the HTML file. If None, the HTML string is returned without writing to disk.

titlestr

Chart title displayed as a heading.

subtitlestr

Description line below the title.

set_a_labelstr

Display name for set A in legend and table. Default "Set A".

set_b_labelstr

Display name for set B in legend and table. Default "Set B".

overlap_labelstr

Display name for the overlap in the table. Default "Overlap".

color_astr

CSS color for set A rectangles. Default "#6A9BCC" (blue).

color_bstr

CSS color for set B rectangles. Default "#C46686" (rose).

opacity_afloat

Opacity for set A rectangles (0–1). Default 0.72.

opacity_bfloat

Opacity for set B rectangles (0–1). Default 0.62.

bar_widthint

Pixel width of each bar column. Default 80.

bar_gapint

Pixel gap between adjacent bars. Default 40.

sort_descbool

Sort categories by union total, largest first. Default True.

show_valuesbool

Show the union total above each bar. Default True.

show_tablebool

Render a data table below the chart. Default True.

font_familystr

CSS font stack.

extra_cssstr

Extra CSS injected into the page.

open_browserbool

Open the file in the default browser after writing.

Returns:
str

The HTML string. Also written to output if provided.

Examples

Basic overlapping-set chart:

>>> categories = [
...     {"name": "nyc", "label": "NYC",
...      "set_a": 4, "set_b": 1905, "overlap": 4},
...     {"name": "bos", "label": "Boston",
...      "set_a": 12, "set_b": 340, "overlap": 8},
...     {"name": "cam", "label": "Cambridge",
...      "set_a": 3, "set_b": 120, "overlap": 2},
... ]
>>> html = euler_bar_chart(
...     categories, "overlap.html",
...     title="City Reports",
...     set_a_label="Filed",
...     set_b_label="Total",
...     overlap_label="Both",
... )

Without the data table:

>>> euler_bar_chart(categories, show_table=False)