pt.CircularCoordinate
Coordinates & layout
Minimal call
df = {"cat": list("abcdefgh"), "val": [3, 5, 2, 6, 4, 7, 3, 5]}
c = pt.chart(df, aes(x="cat", y="val", fill="cat"), legend=False)
c.coordinate(pt.CircularCoordinate())
c.add_bar()
Docstring
Ring-shaped coordinate: t around the ring, r along the radius.
Maps (t, r) → pixel (x, y) on an annulus. ``t ∈ [0, 1]`` runs clockwise
from 12 o'clock; ``r ∈ [0, 1]`` is radial depth (0 = inner edge,
1 = outer edge). Non-affine, so only artists listed in the
``declare_coord_support("Circular", [...])`` block at the bottom of
this module render under it — they draw through ``ctx.warp`` so each
geometry point projects at draw time. Other artists raise
``NotImplementedError`` at render time.
Caveats:
- Glyph paths (text drawn inside data artists) project the anchor only;
the glyph shape stays Cartesian. Frame-level text (titles, x/y tick
labels via ``draw_x_frame`` / ``draw_frame``) is positioned in the
coordinate directly and renders correctly.
- ``c.sectors(axis="x")`` is supported (wedges with radial
dividers and tangential labels). ``c.sectors(axis="y")``
(concentric bands) is not yet supported and raises at render time.
Parameters
----------
data_diameter : float or None, default None
Outer diameter of the data annulus in pixels — the circular
counterpart of a Cartesian chart's ``data_width``/``data_height``.
The set diameter is exactly what renders: chrome (tick labels,
sector labels) grows the canvas outward around it, the same way
Cartesian margins grow around the data rectangle. ``None`` takes
the ``size.data_diameter`` spec default. Chart-level
``data_width``/``data_height`` play no role under this coord.
r_inner : float, default 0.30
Where the chart's ``r=0`` lands, as a fraction of the data
radius (``data_diameter / 2``). With ``r_outer=1.0`` (default)
this is the ring's inner edge; for nested rings, set ``r_inner``
/ ``r_outer`` per chart to claim a sub-band of the annulus.
r_outer : float, default 1.0
Where the chart's ``r=1`` lands, as a fraction of the data
radius. Combine with ``r_inner`` to nest multiple rings
inside one canvas (e.g. ``r_inner=0.5, r_outer=0.75`` for a
middle band).
wrap_gap_deg : float or None, default None
Angular gap (in degrees) at the 12 o'clock wrap-around boundary.
``None`` (default) auto-derives the angle from the x-sector gap so
the wrap boundary is visually indistinguishable from any other
inter-sector gap. Pass an explicit float to override. Works without
sectors too: produces an open arc instead of a closed ring. Ignored
when ``start_deg`` / ``end_deg`` are set explicitly (partial arc).
start_deg : float, default 0.0
Angle (degrees, clockwise from 12 o'clock) at which ``t=0`` lands.
Default 0 = top.
end_deg : float, default 360.0
Angle (degrees, clockwise from 12 o'clock) at which ``t=1`` lands.
Default 360 = back to top (closed ring). Pair with ``start_deg``
for a partial arc. Convention:
``0 ≤ start_deg < end_deg ≤ start_deg + 360``. For an arc that
crosses 12 o'clock (e.g. 9 → 3 o'clock through 12), pass values
like ``start_deg=270, end_deg=450``.
inner : Chart, optional
A separate ``pt.chart(...)`` rendered into the central disc
``r ∈ [0, r_inner]`` — the area no ring claims. Used to host
circular chord/link artists (e.g. ``c.chord_links``) that
share the t-axis with the rings but live in the inner disc.
The leaves passed via ``(c1 / c2 / ...).coordinate(...)`` still
tile the annulus exactly as today; this is additive. The inner
chart needs its own ``xlim`` matching the rings; sectors declared
on the layout auto-propagate to the inner chart (declare
``c.sectors(...)`` on the inner chart explicitly to opt out).