chord_ribbon
Trees & flows · used in the chord cookbook recipe
Minimal call
df = {"a0": [0.0, 2.0], "a1": [1.5, 3.5],
"b0": [6.0, 8.0], "b1": [7.5, 9.5]}
c = pt.chart(df, aes(x1_start="a0", x1_end="a1",
x2_start="b0", x2_end="b1"), xlabel="position")
c.add_chord_ribbon(color="#4C72B0", alpha=0.6)
c.yticks([])
Docstring
Custom artist: chord_ribbon — filled ribbons between two x-ranges.
Sibling of ``chord_links``: where ``chord_links`` draws a thin line
between two x positions (chords carry no width), ``chord_ribbon`` draws
a filled shape between two x **ranges**. That's the visual a matrix
chord diagram demands — each non-zero matrix entry M[i, j] becomes a
ribbon whose width on the i side and the j side is proportional to
M[i, j].
Inside a ``CircularCoordinate`` inner disc each ribbon edge is a
cubic Bezier whose two control points sit on the endpoint→center
radius at fraction ``tension`` (default 0.5) of the way to the
center. That recipe matches d3's chord-ribbon convention and handles
both extremes cleanly: opposite-arc chords curve through the center;
self-loops bulge inward as short petals without a center pinch. The
boundary caps between same-side corners are short polylines along the
disc boundary.
In flat (no-coord) panels the artist falls back to a linear-bow
shape: an outer half-bow arc spanning the outer pair of corners and
an inner half-bow arc spanning the inner pair, joined by short
baseline caps at each end. That's the linear unroll of the circular
ribbon and matches the linear-strip idiom used in the hg38 chord
cookbook.
API mirrors ``chord_links`` for the sector tags and color resolution:
c.add_chord_ribbon(aes(x1_start="x1a", x1_end="x1b",
x2_start="x2a", x2_end="x2b",
x1_sector="src", x2_sector="dst",
color="src"), palette={...},
alpha=0.6, edge_color="#000", edge_width=0.5)
Each row contributes one ribbon. Positions are in the **data**
coordinate system — when the panel has continuous sectors, the standard
sector remap offsets them into the global span automatically. With no
sectors, positions are global from the start.
Self-loops (where both endpoints land on the same sector) render as a
through-center curve like any other ribbon. They read OK for thin
sectors and get visually busy for thick ones; if that matters, drop
the diagonal before passing the matrix in.