Skip to main content
An UpSet plot is the scalable successor to Venn diagrams for showing set intersections when there are more than three or four sets. It has three visual components:
  • Intersection size bars (top): vertical bars showing how many elements belong to each intersection
  • Dot matrix (middle): a grid of circles. Filled dots indicate which sets participate in each intersection; a vertical line connects the filled dots
  • Set size bars (left, optional): horizontal bars showing the total size of each set

Constructor

new

Create an UpSet plot with default settings.
use kuva::plot::UpSetPlot;

let up = UpSetPlot::new();
Returns: UpSetPlot Defaults:
  • Sort: ByFrequency (largest count leftmost)
  • Count labels shown
  • Set-size bars shown
  • Dark gray bars and dots (#333333)
  • Light gray empty dots (#dddddd)

Data Input Methods

with_sets

Build from raw sets: an iterable of (name, elements) pairs.
pub fn with_sets<S, T, I, J>(self, sets: I) -> Self
where
    S: Into<String>,
    T: Eq + std::hash::Hash,
    I: IntoIterator<Item = (S, J)>,
    J: IntoIterator<Item = T>,
Intersection counts are computed automatically. Each element is assigned to the unique combination of sets it belongs to (bitmask semantics).
sets
impl IntoIterator<Item = (String, Vec<T>)>
Iterator of (set_name, elements) pairs where elements implement Eq + Hash
Example:
let up = UpSetPlot::new().with_sets(vec![
    ("DESeq2",   vec!["BRCA1", "TP53", "EGFR", "MYC",  "CDK4"]),
    ("edgeR",    vec!["TP53",  "EGFR", "RB1",  "PTEN", "CDK4"]),
    ("limma",    vec!["EGFR",  "MYC",  "RB1",  "CDK2"]),
]);

with_data

Build from precomputed intersection data.
pub fn with_data<S: Into<String>>(
    self,
    set_names: impl IntoIterator<Item = S>,
    set_sizes: impl IntoIterator<Item = usize>,
    intersections: impl IntoIterator<Item = (u64, usize)>,
) -> Self
Use this when intersection counts come from an external source.
set_names
impl IntoIterator<Item = String>
Set names in order (bit 0, bit 1, bit 2, …)
set_sizes
impl IntoIterator<Item = usize>
Total element count for each set (for set-size bars)
intersections
impl IntoIterator<Item = (u64, usize)>
Iterator of (mask, count) pairs where mask is a bitmask indicating set membership
Bitmask encoding: Bit i set means set_names[i] participates. For example, with three sets A, B, C:
  • mask = 0b001 (1) → elements in A only
  • mask = 0b011 (3) → elements in A ∩ B but not C
  • mask = 0b111 (7) → elements in A ∩ B ∩ C
Example:
// Three variant callers — bit 0 = GATK, bit 1 = FreeBayes, bit 2 = Strelka
let up = UpSetPlot::new().with_data(
    ["GATK", "FreeBayes", "Strelka"],
    [280usize, 263, 249],
    vec![
        (0b001, 45),   // GATK only
        (0b010, 35),   // FreeBayes only
        (0b100, 28),   // Strelka only
        (0b011, 62),   // GATK ∩ FreeBayes
        (0b101, 55),   // GATK ∩ Strelka
        (0b110, 48),   // FreeBayes ∩ Strelka
        (0b111, 118),  // all three
    ],
);

Sort Order

with_sort

Set the sort order for intersections.
pub fn with_sort(self, sort: UpSetSort) -> Self
sort
UpSetSort
Sort order (default: UpSetSort::ByFrequency)
UpSetSort variants:
  • UpSetSort::ByFrequency — largest count leftmost (default)
  • UpSetSort::ByDegree — most complex (most sets) leftmost, ties broken by count
  • UpSetSort::Natural — preserve the order supplied to with_data or the deterministic mask-sorted order from with_sets
Example:
use kuva::plot::UpSetSort;

let up = UpSetPlot::new()
    .with_sets(data)
    .with_sort(UpSetSort::ByDegree);

Filtering

with_max_visible

Show only the top max intersections after sorting.
pub fn with_max_visible(self, max: usize) -> Self
max
usize
Maximum number of intersections to display
Useful when many intersections exist but only the most prominent ones need to be displayed. The limit is applied after sorting. Example:
let up = UpSetPlot::new()
    .with_sets(data)
    .with_max_visible(10);  // show only the 10 largest intersections

Display Configuration

without_set_sizes

Hide the horizontal set-size bars on the left panel.
pub fn without_set_sizes(self) -> Self
By default a bar for each set shows its total element count. Call this to produce a more compact layout.

with_bar_color

Set the color for intersection bars and set-size bars.
pub fn with_bar_color<S: Into<String>>(self, color: S) -> Self
color
String
CSS color string (default: "#333333")

with_dot_color

Set the fill color for dots in a participating set.
pub fn with_dot_color<S: Into<String>>(self, color: S) -> Self
color
String
CSS color string for filled dots (default: "#333333")
Non-participating dots retain their color set by dot_empty_color (default light gray).

Rendering

The UpSet plot renders entirely in pixel space. It does not use the standard x/y axis system — Layout::auto_from_plots skips axis computation for UpSet plots. A title set on the Layout is still rendered.

Full Example

use kuva::plot::UpSetPlot;
use kuva::backend::svg::SvgBackend;
use kuva::render::render::render_multiple;
use kuva::render::layout::Layout;
use kuva::render::plots::Plot;

let up = UpSetPlot::new()
    .with_sets(vec![
        ("Set A", vec!["apple", "banana", "cherry", "date"]),
        ("Set B", vec!["banana", "cherry", "elderberry", "fig"]),
        ("Set C", vec!["cherry", "fig", "grape"]),
    ])
    .with_max_visible(10);

let plots = vec![Plot::UpSet(up)];
let layout = Layout::auto_from_plots(&plots)
    .with_title("Set Intersections");

let svg = SvgBackend.render_scene(&render_multiple(plots, layout));
std::fs::write("upset.svg", svg).unwrap();

Build docs developers (and LLMs) love