Skip to content

Chart

Mojo struct 🡭

Chart

@memory_only
struct Chart[M: MarkType]

One chart of mark type M: the mark’s own columns in mark, and everything every mark shares beside it. Built through Plot.

Parameters

  • M (MarkType)

Fields

  • mark (M)
  • settings (_ChartSettings)
  • style (_MarkStyle)
  • annotations (_AnnotationData)
  • width (Int)
  • height (Int)

Implemented traits

AnyType, ChartLike, Copyable, Deinitable, Movable

Methods

__init__

fn def __init__(out self, var mark: M, var settings: _ChartSettings, var style: _MarkStyle)

Args:

  • mark (M)
  • settings (_ChartSettings)
  • style (_MarkStyle)
  • self (Self)

Returns:

Self

id

fn def id(self) -> Mark

Args:

  • self (Self)

Returns:

Mark

canvas_width

fn def canvas_width(self) -> Int

Args:

  • self (Self)

Returns:

Int

canvas_height

fn def canvas_height(self) -> Int

Args:

  • self (Self)

Returns:

Int

chart_settings

fn def chart_settings(self) -> _ChartSettings

Args:

  • self (Self)

Returns:

_ChartSettings

mark_style

fn def mark_style(self) -> _MarkStyle

Args:

  • self (Self)

Returns:

_MarkStyle

chart_annotations

fn def chart_annotations(self) -> _AnnotationData

Args:

  • self (Self)

Returns:

_AnnotationData

x_data

fn def x_data(self) -> List[Float64]

Args:

  • self (Self)

Returns:

List[Float64]

y_data

fn def y_data(self) -> List[Float64]

Args:

  • self (Self)

Returns:

List[Float64]

render_mark

fn def render_mark[T: DrawTarget](self, mut target: T, ox0: Int, oy0: Int, ox1: Int, oy1: Int, has_shared_y_domain: Bool, shared_y_min: Float64, shared_y_max: Float64, shared_y_is_log: Bool, *, mut cache: FontCache, vector_target: Bool) -> _RenderResult

Parameters:

  • T (DrawTarget)

Args:

  • self (Self)
  • target (T)
  • ox0 (Int)
  • oy0 (Int)
  • ox1 (Int)
  • oy1 (Int)
  • has_shared_y_domain (Bool)
  • shared_y_min (Float64)
  • shared_y_max (Float64)
  • shared_y_is_log (Bool)
  • cache (FontCache)
  • vector_target (Bool)

Returns:

_RenderResult

Raises:

scaled_by

fn def scaled_by(self, factor: Float64) -> Self

Args:

  • self (Self)
  • factor (Float64)

Returns:

Self

erased

fn def erased(self) -> AnyChart

This chart with its mark type erased, for a List[AnyChart].

Args:

  • self (Self)

Returns:

AnyChart

erased_with

fn def erased_with[canvas: Bool = False, svg: Bool = False, pdf: Bool = False, bounds: Bool = False, display_list: Bool = False](self) -> AnyChart

Parameters:

  • canvas (Bool)
  • svg (Bool)
  • pdf (Bool)
  • bounds (Bool)
  • display_list (Bool)

Args:

  • self (Self)

Returns:

AnyChart

capabilities

fn def capabilities(self) -> _Capabilities

Args:

  • self (Self)

Returns:

_Capabilities

size

fn def size(var self, width: Int, height: Int) -> Self

Set the dimensions render()/render_svg()/save() construct their target at. Defaults to 640x420.

The unit is a point, 1/72 inch, which is what makes a figure size mean something physical (#372). On the raster backends one point is one pixel at the default resolution, so nothing about the old reading changes; save(..., dpi=300) keeps the physical size and multiplies the pixels. In a PDF it is a point on the page. size_inches()/size_mm() say the same thing in the units a page is usually specified in.

Args:

  • self (Self)
  • width (Int): Figure width in points.
  • height (Int): Figure height in points.

Returns:

Self: Self, for further chaining.

size_inches

fn def size_inches(var self, width: Float64, height: Float64) -> Self

size() in inches: 72 points to the inch, rounded to whole points (#372).

A figure for a journal column or a slide is specified physically, and size(468, 312) does not read as “6.5 by 4.3 inches” to anyone.

Args:

  • self (Self)
  • width (Float64): Figure width in inches.
  • height (Float64): Figure height in inches.

Returns:

Self: Self, for further chaining.

size_mm

fn def size_mm(var self, width: Float64, height: Float64) -> Self

size() in millimeters: 25.4 mm to the inch and 72 points to the inch, rounded to whole points (#372).

Args:

  • self (Self)
  • width (Float64): Figure width in millimeters.
  • height (Float64): Figure height in millimeters.

Returns:

Self: Self, for further chaining.

theme

fn def theme(var self, t: Theme) -> Self

Attach a full Theme to this plot, replacing the default one. Every styling knob lives on Theme.

Args:

  • self (Self)
  • t (Theme): The Theme to attach, replacing whatever was set before (the default Theme() if this is the first call).

Returns:

Self: Self, for further chaining.

tooltips

fn def tooltips(var self, policy: Tooltips) -> Self

Set whether this chart’s data get SVG hover tooltips, overriding Theme.tooltips for this plot only. Tooltips.ON titles every datum, Tooltips.OFF none, and Tooltips.AUTO titles them when there are at most Theme.auto_tooltip_limit (tooltips.mojo). Precedence is this call, then the theme.

Tooltips.ON on a mark without tooltips raises when the chart renders; which marks have them is MarkType.supports_tooltips.

Args:

  • self (Self)
  • policy (Tooltips): Tooltips.ON, Tooltips.OFF or Tooltips.AUTO.

Returns:

Self: Self, for further chaining.

labels

fn def labels(var self, title: String = "", subtitle: String = "", x_title: String = "", y_title: String = "", description: String = "") -> Self

Set the chart title/subtitle and/or axis titles. Named x_title/ y_title rather than x/y so a call next to .encode(x=..., y=...) never reads as setting data.

Each is independent and defaults to "" (not set); layout space is reserved only for the non-empty visible ones (title/subtitle/ x_title/y_title – description draws nothing). subtitle draws directly beneath title, smaller and in Theme.subtitle_color; with no title it draws at the top position title would have used.

x_title/y_title caption whatever is drawn along the bottom/left edge, whichever axis that is for the mark’s orientation. Mark.ARC has no axes, so x_title/y_title raise at render() time there; only title/subtitle/description apply.

description is an SVG <desc> – longer, screen-reader-only context subtitle alone can’t carry since it’s drawn on the chart itself. save()/save_layers()/save_facets() write it (falling back to subtitle when empty) automatically whenever title is set; see accessible_svg_string()’s own docstring for the full markup.

Any of the four drawn labels may hold mathematics between $ signs: "$\sigma^2$", "Rate $\frac{\Delta y}{\Delta x}$". Inside the dollars, Latin letters and lowercase Greek are italic variables and everything else upright; ^ and _ attach scripts, \frac{}{} stacks a fraction, \sqrt{} draws a radical, \mathrm{} forces upright text, and \alpha…\Omega and operators such as \times, \leq and \sum name symbols – the full list is in dataviz/core/mathtext.mojo. A lone $ is a price and stays plain; write \$ for a literal one beside math. The space an expression needs above and below the line is measured and reserved. A label that does not parse raises at render time, naming the label and the character, rather than drawing a guess.

Args:

  • self (Self)
  • title (String): The chart’s title. Left empty (the default), reserves no layout space for it.
  • subtitle (String): A secondary line shown under the title, independent of whether title is also set.
  • x_title (String): Caption for whatever’s drawn along the bottom edge; raises at render() time on Mark.ARC.
  • y_title (String): Caption for whatever’s drawn along the left edge; raises at render() time on Mark.ARC.
  • description (String): Optional longer SVG <desc> text, drawn nowhere on the chart itself; falls back to subtitle when left empty.

Returns:

Self: Self, for further chaining.

series_name

fn def series_name(var self, name: String) -> Self

Name this layer for render_layers()’s/render_layers_svg()’s per-layer legend: a swatch (this layer’s own Theme.mark_color) plus name, one row per named layer, drawn before any per-point color/color_categories legend a Mark. POINT layer has of its own. A Plot.secondary_axis() layer’s row gets " (right axis)" appended, so the reader knows which axis it reads against.

render_layers()/render_layers_svg() and _render_bar_combo_layers (the Mark.BAR-combo path) only; render()/render_svg() ignore it, since a standalone plot has only one series, nothing for a legend entry to distinguish. Layers with no name draw no row.

See the Cookbook’s own “Layer Legend” recipe (docs/src/ cookbook_recipes/layer_legend.mojo) for a full worked example.

Args:

  • self (Self)
  • name (String): This layer’s label in the per-layer legend. Left empty (the default, via not calling this), the layer draws no legend row.

Returns:

Self: Self, for further chaining.

annotate_line

fn def annotate_line(var self, value: Float64, label: String = "") -> Self where M.supports_annotations_y

Add a horizontal reference line at value on the y-axis (ECharts’ markLine with a fixed value; no auto-computed average/max/min modes). Each call adds a line. label, when non-empty, draws to the right of the line in Theme.annotation_color; the line spans the full plot width, solid (canvas has no dashed-stroke primitive). A value outside the mark’s padded y-domain draws nothing.

Only meaningful on a mark whose y-axis is a continuous LinearScale, checked at render() time via _RenderResult.has_y_scale: Mark.POINT/LINE/AREA/ EFFECT_SCATTER and every mark sharing _CategoricalFrame (BAR/ LOLLIPOP/WATERFALL/BOX/CANDLESTICK/BULLET/GROUPED_BAR/ STACKED_BAR/STREAMGRAPH). Other marks raise. Also wired into render_facets() (per cell) and render_layers() (per layer, against that layer’s own primary or secondary y-scale).

See the Cookbook’s own “Reference Line” recipe (docs/src/ cookbook_recipes/annotate_line.mojo) for a full worked example.

Args:

  • self (Self)
  • value (Float64): The y-value to draw the line at. Outside the mark’s (padded) y-domain, draws nothing.
  • label (String): Drawn to the right of the line when non-empty; left empty (the default), the line draws with no label.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no genuine continuous y-axis.

annotate_area

fn def annotate_area(var self, y0: Float64, y1: Float64, label: String = "") -> Self where M.supports_annotations_y

Add a shaded horizontal band from y0 to y1 on the y-axis (ECharts’ markArea with a fixed pair). Each call adds a band. label, when non-empty, draws inside the band near its top edge in Theme.annotation_color. y0/y1 may be given in either order.

A band partially overlapping the mark’s padded y-domain clips to the visible portion; one with no overlap draws nothing. Drawn on top of the mark at Theme.annotation_area_color’s partial opacity, so the mark’s ink shows through.

Same mark support and facets/layers wiring as annotate_line().

See the Cookbook’s own “Reference Band” recipe (docs/src/ cookbook_recipes/annotate_area.mojo) for a full worked example.

Args:

  • self (Self)
  • y0 (Float64): One edge of the band; need not be the lower one.
  • y1 (Float64): The other edge of the band; whichever of y0/y1 is smaller becomes the band’s bottom edge.
  • label (String): Drawn inside the band near its top edge when non-empty; left empty (the default), the band draws with no label.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no genuine continuous y-axis.

annotate_vline

fn def annotate_vline(var self, value: Float64, label: String = "") -> Self where M.supports_annotations_x

Add a vertical reference line at value on the x-axis: annotate_line()’s mirror image, with the same fixed-value scope, additive behavior, styling, and out-of-domain skip.

Narrower mark support: only Mark.POINT/LINE/AREA/ EFFECT_SCATTER, the marks with a continuous x-axis; a categorical x-axis has no numeric value to place a line against (see _RenderResult). Raises on an unsupported mark. Also wired into render_facets() (per cell) and render_layers() (per layer, against the one shared continuous x-scale every layer uses – raises on a Mark.BAR combo chart’s categorical x-axis instead, same as a standalone unsupported mark).

See the Cookbook’s own “Vertical Reference Line” recipe (docs/ docs/cookbook_recipes/annotate_vline.mojo) for a full worked example.

Args:

  • self (Self)
  • value (Float64): The x-value to draw the line at. Outside the mark’s (padded) x-domain, draws nothing.
  • label (String): Drawn near the line when non-empty; left empty (the default), the line draws with no label.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no genuine continuous x-axis.

annotate_point

fn def annotate_point(var self, x: Float64, y: Float64, label: String = "") -> Self where M.supports_annotations_xy

Add a single labeled point at (x, y) (ECharts’ markPoint with a fixed coordinate): a small filled marker in Theme.annotation_color, with label just above it when non-empty. Each call adds a point.

Needs a continuous coordinate on both axes, so only Mark.POINT/ LINE/AREA/EFFECT_SCATTER support it; raises otherwise. A point outside the padded domain on either axis draws nothing. Also wired into render_facets() (per cell) and render_layers() (per layer, against that layer’s own primary or secondary y-scale and the one shared x-scale).

See the Cookbook’s own “Point Marker” recipe (docs/src/ cookbook_recipes/annotate_point.mojo) for a full worked example.

Args:

  • self (Self)
  • x (Float64): The point’s x-coordinate. Outside the mark’s (padded) x-domain, draws nothing.
  • y (Float64): The point’s y-coordinate. Outside the mark’s (padded) y-domain, draws nothing.
  • label (String): Drawn just above the point when non-empty; left empty (the default), the point draws with no label.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no genuine continuous x/y-axis.

annotate_arrow

fn def annotate_arrow(var self, x: Float64, y: Float64, text: String, text_x: Float64, text_y: Float64) -> Self where M.supports_annotations_xy

Point at (x, y) with an arrow, labeled text placed at (text_x, text_y). Each call adds an arrow.

This is the only annotation that can be placed in empty space, which is what makes it usable on a crowded chart where every other overlay lands on data – annotate_point()’s label sits a fixed gap above its marker and cannot be moved. An arrow is often the whole point of a chart going into a document: it is what turns a plot into an argument.

Both ends are in data coordinates. Everything else in this API is in data space, and a second convention would need explaining every time it appeared. The cost is that a label position has to be chosen against the data’s own range; the benefit is that it stays put when the chart is resized.

Straight arrows only. Curved connectors, head styles and shrink factors are refinements on top of a feature that did not exist; the straight case carries most of the value.

Needs a continuous coordinate on both axes, so only Mark.POINT/ LINE/AREA/EFFECT_SCATTER support it; raises otherwise. An arrow with either end outside the padded domain is skipped whole rather than clipped – half an arrow points at nothing.

Args:

  • self (Self)
  • x (Float64): The target’s x-coordinate, where the head lands.
  • y (Float64): The target’s y-coordinate.
  • text (String): The label, drawn centered at (text_x, text_y). Empty draws the arrow alone.
  • text_x (Float64): The label’s x-coordinate, in data space.
  • text_y (Float64): The label’s y-coordinate, in data space.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no genuine continuous x/y-axis.

annotate_band

fn def annotate_band(var self, x: List[Float64], y_lower: List[Float64], y_upper: List[Float64], label: String = "") -> Self where M.supports_annotations_xy

Shade the region between two curves that vary with x: a confidence band around a trend line, or a min/max envelope. annotate_area()’s band is a constant (y0, y1) pair; this takes two parallel lists keyed by x. Each call adds a band.

x/y_lower/y_upper must be the same length and every y_upper[i] >= y_lower[i], both checked at render() time. x need not be sorted; the top edge traces (x[i], y_upper[i]) in order and the bottom edge walks back in reverse.

Filled in Theme.annotation_area_color with straight edges (no Theme.line_smoothing). label, when non-empty, centers above the band’s middle x-index on its upper edge.

Only Mark.POINT/LINE/AREA/EFFECT_SCATTER, as for annotate_point(). A band is clipped to the overlapping range on both axes; one with no overlap draws nothing. Same facets/layers wiring as annotate_point().

See the Cookbook’s own “Confidence Band” recipe (docs/src/ cookbook_recipes/annotate_band.mojo) for a full worked example.

Args:

  • self (Self)
  • x (List[Float64]): The band’s x column, one entry per (y_lower, y_upper) pair, in the order the edges should trace.
  • y_lower (List[Float64]): The band’s bottom edge, one entry per x.
  • y_upper (List[Float64]): The band’s top edge, one entry per x; every value must be >= y_lower’s value at that same index.
  • label (String): Drawn centered above the band’s middle point when non-empty; left empty (the default), the band draws with no label.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the lengths mismatch, an upper/lower value is inverted, or the mark has no genuine continuous x/y-axis.

annotate_best_fit

fn def annotate_best_fit(var self, show_equation: Bool = False, show_r_squared: Bool = False, label: String = "", ci: Float64 = 0.94999999999999996) -> Self where M.supports_annotations_xy

Overlay an ordinary-least-squares best-fit line computed from this plot’s own _continuous.x/_continuous.y at render() time, so it works whether called before or after .encode(). Not additive: the last call wins, since the fit is determined by the data.

Drawn as a solid line in Theme.annotation_color across the mark’s full padded x-domain. show_equation/show_r_squared each add one line of text right-aligned near the plot’s top-right corner; label, when non-empty, draws as a heading above them. R-squared is 1 - SS_res/SS_tot, defined as 1.0 when SS_tot is 0.0.

Only Mark.POINT/LINE/AREA/EFFECT_SCATTER. Raises at render() time with fewer than 2 points or when every x value is identical. Also wired into render_facets() (per cell, fit to that cell’s own data) and render_layers() (per layer, fit to that layer’s own data against its primary or secondary y-scale and the shared x-scale).

See the Cookbook’s own “Best-Fit Trend Line” recipe (docs/src/ cookbook_recipes/best_fit_line.mojo) for a full worked example.

Args:

  • self (Self)
  • show_equation (Bool): Draw the fitted line’s own y = mx + b text when True; False (the default) draws only the line itself.
  • show_r_squared (Bool): Draw the fit’s R-squared text when True; False (the default) omits it.
  • label (String): An optional heading drawn above the equation/ R-squared text; left empty (the default), no heading draws (independent of show_equation/show_r_ squared – a label with both left False still draws only the line, no text at all).
  • ci (Float64): Two-sided confidence level for a band around the fitted line. 0.95 (the default) shades the 95% confidence interval of the fitted mean at each x; pass 0.0 for the bare line. The band is narrowest at the mean of x and flares toward the ends, which is the point of drawing it: a line without one invites the reader to trust the slope more than the data supports (#352). Levels carried: 0.90, 0.95, 0.99. A band needs three points – with two, the line passes through both and there is no residual error to size it from – so with fewer the line draws alone. Drawn in Theme.annotation_area_color, under the line.

Returns:

Self

annotate_smooth

fn def annotate_smooth(var self, method: SmoothMethod = SmoothMethod.LOESS, span: Float64 = 0.75, degree: Int = Int(2)) -> Self where M.supports_annotations_xy

Overlay a curved trend line fitted to this plot’s own x/y data (#147) – annotate_best_fit()’s straight line, for data a straight line does not describe.

  • SmoothMethod.LOESS (the default): locally weighted regression. At each x, a polynomial of degree (1 or 2) is fitted to the nearest span share of the points, weighted by the tricube of their distance, and evaluated there. span sets how smooth: smaller follows the data more closely. The defaults, span=0.75 and degree=2, are the conventional ones for local regression.
  • SmoothMethod.POLYNOMIAL: one least-squares polynomial of degree over every point; span is unused.

Drawn across the data’s own x range, in annotate_best_fit()’s color and line style, clipped to the plot area. Unlike annotate_best_fit() there is no confidence band, equation or R-squared: those are defined for the straight-line fit.

Args:

  • self (Self)
  • method (SmoothMethod): SmoothMethod.LOESS or SmoothMethod.POLYNOMIAL.
  • span (Float64): LOESS’s window as a share of the points, in (0, 1].
  • degree (Int): LOESS’s local degree (1 or 2), or the polynomial’s.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark has no continuous x/y axes, or the data cannot support the fit (too few points or distinct x values for the degree, or a span outside (0, 1]).

scale_y_log

fn def scale_y_log(var self) -> Self where M.supports_log_y

Scale the y-axis logarithmically (base 10). Every y value, and every y-axis annotation value, must be strictly positive; render()/ render_svg() raise otherwise (see _log_data_extent()).

Mark.POINT/LINE/EFFECT_SCATTER only, and standalone render()/ render_svg() only: a categorical mark has no continuous y-domain, Mark.AREA’s y-domain is forced through zero (which has no logarithm), and render_layers() combines layers into one linear scale. Every tick/gridline/point/annotation still goes through LinearScale.to_pixel() with real-unit values; see that method.

See the Cookbook’s own “Log Scale (Y-Axis)” recipe (docs/src/ cookbook_recipes/log_scale_y.mojo) for a full worked example.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining.

scale_x_log

fn def scale_x_log(var self) -> Self where M.supports_log_x

scale_y_log()’s x-axis mirror. Mark.POINT/LINE/AREA/ EFFECT_SCATTER (x is never forced through zero, so AREA is allowed here), standalone render()/render_svg() only.

See the Cookbook’s own “Log Scale (X-Axis)” recipe (docs/src/ cookbook_recipes/log_scale_x.mojo) for a full worked example.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining.

scale_y_symlog

fn def scale_y_symlog(var self, linthresh: Float64 = 1) -> Self where M.supports_log_y

Scale the y-axis symmetrically logarithmically: linear within [-linthresh, linthresh], logarithmic beyond it, continuous where they meet (#368).

What scale_y_log() cannot do. A log axis needs strictly positive values, so a series that crosses zero – a temperature anomaly, a profit and loss, a residual – cannot go on one at all; and a linear axis collapses every small value against the largest. Symlog keeps zero, keeps the sign, and still resolves several orders of magnitude on each side.

linthresh is the half-width of the linear region in data units, and must be positive. It sets what counts as “near zero”: values inside it are laid out linearly, so the noise floor of the measurement is usually the right choice. The linear region takes exactly as much axis as one decade of the logarithmic region, which is the only ratio that makes the two halves comparable without a second knob.

Mark.POINT/LINE/AREA/EFFECT_SCATTER, standalone render()/render_svg() only, the same scope scale_y_log() has. Mutually exclusive with scale_y_log(); setting both raises at render time rather than silently preferring one.

Args:

  • self (Self)
  • linthresh (Float64): Half-width of the linear region around zero, in data units. Must be positive.

Returns:

Self: Self, for further chaining.

scale_x_symlog

fn def scale_x_symlog(var self, linthresh: Float64 = 1) -> Self where M.supports_log_x

scale_y_symlog()’s x-axis mirror, with the same scope and the same linthresh meaning (#368).

Args:

  • self (Self)
  • linthresh (Float64): Half-width of the linear region around zero, in data units. Must be positive.

Returns:

Self: Self, for further chaining.

scale_x_domain

fn def scale_x_domain(var self, min: Float64, max: Float64) -> Self

Pin the x-axis domain to the given minimum and maximum, replacing _data_extent()’s 5%-padded domain (or _log_data_extent()’s when scale_x_log() is also set). For comparable charts across runs, a fixed reference range, or a zoomed-in view, without padding the data with fake points.

Mark.POINT/LINE/AREA/EFFECT_SCATTER only (the same marks _render_generic’s continuous path draws), standalone render()/ render_svg() and render_facets() only – render_layers() raises if any layer sets this, since a shared axis across several layers needs one shared answer, not one per layer; the categorical marks (Mark.BAR, LOLLIPOP, …) raise too, left for a supported. render_facets() applies this per cell, so every cell sharing the same override reads as one shared domain – the facets counterpart to shared_y_scale=True for the x-axis (which has no shared_y_scale equivalent otherwise).

A point outside the domain still computes a real (off-plot) pixel position via LinearScale.to_pixel(), same as it would if it merely fell outside a padded auto-computed domain; the SVG viewBox’s own default overflow: hidden clips it at the canvas edge, and the raster Canvas’s own pixel buffer bounds-checks every draw call, so nothing paints outside the plot in either backend.

Args:

  • self (Self)
  • min (Float64): The domain’s lower bound. For a log x-axis (scale_x_log()), must be > 0.
  • max (Float64): The domain’s upper bound; must be > min.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if min >= max, the mark doesn’t support this, or (with scale_x_log()) min <= 0.

scale_y_domain

fn def scale_y_domain(var self, min: Float64, max: Float64) -> Self

scale_x_domain()’s y-axis mirror – see that method’s own docstring for the shared rules. Overrides _zero_baseline_y_ extent()’s forced-zero domain on Mark.AREA too: an explicit The explicit domain is used exactly, zero baseline or not.

Args:

  • self (Self)
  • min (Float64): The domain’s lower bound. For a log y-axis (scale_y_log()), must be > 0.
  • max (Float64): The domain’s upper bound; must be > min.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if min >= max, the mark doesn’t support this, or (with scale_y_log()) min <= 0.

scale_x_ticks

fn def scale_x_ticks(var self, values: List[Float64], labels: List[String] = List()) -> Self

Put the x-axis major ticks exactly at values, instead of at the 1-2-5 positions the axis would choose (#368).

For an axis whose meaningful positions are not round numbers: a threshold, a target, the two dates a study ran between. The gridline, the tick mark and the label all move together, because they are one tick.

labels replaces the formatted numbers when given, one per position, which is how an axis reads Q1 Q2 Q3 Q4 over values that are really 1 2 3 4. Left empty, the positions are formatted the way computed ticks are, at one decimal count for the whole set.

A position outside the axis domain is dropped rather than drawn: its pixel would fall outside the plot rect and its label would print in the margin beside nothing. scale_x_domain() is what moves the domain; this only says where the ticks go inside it.

Minor ticks are not derived from an explicit set, since the caller said where the ticks belong and a subdivision of an irregular set has no meaning.

Args:

  • self (Self)
  • values (List[Float64]): Tick positions, in the axis’s own units.
  • labels (List[String]): One label per position, or empty to format the positions.

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the list is empty, a label count does not match, a position is not finite, a position is not positive on a log axis, or the mark does not support this.

scale_y_ticks

fn def scale_y_ticks(var self, values: List[Float64], labels: List[String] = List()) -> Self

scale_x_ticks()’s y-axis mirror – see that method’s docstring for the shared rules.

The y labels are what the left margin is measured from, so an explicit set widens or narrows the plot rect to fit itself, exactly as computed labels do.

Args:

  • self (Self)
  • values (List[Float64]): Tick positions, in the axis’s own units.
  • labels (List[String]): One label per position, or empty to format the positions.

Returns:

Self: Self, for further chaining – see scale_x_ticks().

scale_x_reverse

fn def scale_x_reverse(var self) -> Self

Run the x-axis right to left: the domain’s low end lands on the plot rect’s right edge (#368).

For a quantity that reads better descending – a rank where 1 is best, a countdown, a depth below a surface. Only the two pixel positions swap. The domain stays ascending, so the ticks are the same ticks in the same order and every mark keeps handing the scale the same values; what changes is where they land.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining – render()/render_svg() raise later if the mark does not support this.

scale_y_reverse

fn def scale_y_reverse(var self) -> Self

Run the y-axis top to bottom: the domain’s low end lands on the plot rect’s top edge (#368).

scale_x_reverse()’s mirror. On Mark.IMSHOW, whose y-axis already counts downward so that row 0 is at the top, this composes rather than competes: it puts row 0 back at the bottom.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining – see scale_x_reverse().

equal_aspect

fn def equal_aspect(var self) -> Self

Give one data unit the same pixel length on both axes (#368).

For anything whose two axes are the same kind of quantity, where the shape of what is drawn is part of what it says: a map, a circle that has to look round, a residual plot read against the 45-degree line.

The plot rect shrinks; the domains do not grow. With equal aspect something has to give, and the two choices are showing a wider range than the caller asked for or leaving part of the figure empty. This leaves space: the rect keeps the aspect the data implies and centers itself in the room it had. Nothing is drawn outside the data’s own range, and the axis labels, ticks and margins are the ones measured for the domains as given.

Not available on a log or time axis, where a “data unit” is not a constant length: raises at render() time rather than claiming a guarantee it cannot keep.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining – render()/render_svg() raise later on a log or time axis, or if the mark does not support this.

scale_color_domain

fn def scale_color_domain(var self, min: Float64, max: Float64) -> Self

Pin the continuous color domain to the given minimum and maximum, replacing the [min, max] this mark would otherwise take from its own colored values. scale_x_domain()’s color counterpart, and the thing that makes two color-encoded charts comparable.

Without it every continuous-color mark derives its own limits, so two panels of the same quantity are drawn against two different scales and look identical while meaning different things – the reader has no way to see the difference, because the only place it shows is in two legends whose numbers nobody cross-checks. shared_color_domain() computes one domain across several charts’ data to pass here; it is the counterpart to shared_bin_edges().

Applies to every mark that colors by a continuous value: Mark.HEATMAP, CALENDAR_HEATMAP, CORRPLOT, IMSHOW, PCOLORMESH, HIST2D, HEXBIN, CONTOUR, CONTOURF, TRICONTOUR, TRICONTOURF, TRIPCOLOR, QUIVER, STREAMPLOT, and Plot.encode(color=...)’s continuous channel on Mark.POINT/SINGLE_AXIS/EFFECT_SCATTER. Anything else raises rather than accepting a setting it would ignore. Mark.BOXENPLOT is not on the list even though it builds a ColorScale: its ramp runs over the depth of the letter-value nest, not over a data value, so an explicit data domain has nothing to say about it.

Values outside the domain are not dropped; they clamp to the ramp’s end color, because GradientStops.color_at() clamps t outside [0, 1]. A separate under/over color would say more, and is left for its own change (see the module note on _color_scale_for).

The color legend follows automatically: every mark hands the legend the same ColorScale it colored with, so the labels read the overridden domain, not the data’s.

Args:

  • self (Self)
  • min (Float64): The value the ramp’s low end means.
  • max (Float64): The value the ramp’s high end means; must be > min.

Returns:

Self: Self, for further chaining – the render raises later if min >= max or the mark has no continuous color channel.

scale_color_thresholds

fn def scale_color_thresholds(var self, boundaries: List[Float64]) -> Self

Color in discrete bands instead of a continuous ramp (#370).

n boundaries make n - 1 bands, and every value in a band gets one flat color. That is what a reader needs when the question is “which category is this” rather than “how much”: soil pH bands, risk tiers, a legend with named ranges.

Intervals are lower-inclusive, [b[i], b[i+1]), with the last closed at the top so the domain maximum has somewhere to go. A value exactly on an interior boundary belongs to the band above it. That is the one place this is easy to get wrong, so it is stated here and tested.

Values below the first boundary take the lowest band and values above the last take the highest, rather than raising. Clipping rather than rejecting keeps a shared threshold list usable across facets whose data ranges differ.

Boundaries must be strictly increasing, checked at render time along with the rest of the color domain.

Not combinable with scale_color_log() or scale_color_center(): thresholds already say where every band starts, so there is nothing left for either to place.

Args:

  • self (Self)
  • boundaries (List[Float64]): The band edges, at least two, strictly increasing.

Returns:

Self: Self, for further chaining.

Raises:

scale_color_under

fn def scale_color_under(var self, color: Color) -> Self

Color values below the color domain with color instead of the ramp’s low end (#370).

Without it an out-of-range value clamps: a reading of -40 on a domain starting at 0 is painted the same as a reading of 0, and the chart says the two are alike. A distinct color says “this is off the scale”, which is a different statement and usually the one that matters – a sensor out of range, a region with no data of its own, a value the domain was deliberately narrowed to exclude.

Applies to every mark scale_color_domain() applies to, and to every form of the ramp: continuous, logarithmic and banded. With scale_color_thresholds() the band edges are the range, so “below” means below the first boundary.

The color legend shows it, as a block at the low end of the bar inside the bar’s own footprint, so the legend costs exactly the room it did before and its end labels stay attached to the ends of the ramp, where those numbers are true.

Args:

  • self (Self)
  • color (Color): The color for a value below the domain.

Returns:

Self: Self, for further chaining.

scale_color_over

fn def scale_color_over(var self, color: Color) -> Self

Color values above the color domain with color instead of the ramp’s high end – scale_color_under()’s mirror, and see that method’s docstring for the shared rules (#370).

Values exactly at the domain maximum belong to the ramp, not to the over color: the top end is part of the range, which is the rule the last threshold band already follows.

Args:

  • self (Self)
  • color (Color): The color for a value above the domain.

Returns:

Self: Self, for further chaining.

scale_color_log

fn def scale_color_log(var self) -> Self

Normalize color by log10 instead of linearly (#370).

A linear ramp cannot resolve values spread over several orders of magnitude: on a 1-to-10,000 domain everything below 1,000 lands in the first tenth of the ramp and reads as one color. With this, equal ratios get equal color distance, so 1 to 10 spans as much of the ramp as 1,000 to 10,000.

The domain must be strictly positive, whether it came from the data or from scale_color_domain(). That is checked at render time, because until then the mark’s own limits are not known.

Not combinable with scale_color_center(): centering places the neutral color by linear distance from each end, which a log domain does not preserve.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining.

Raises:

scale_color_center

fn def scale_color_center(var self, center: Float64) -> Self

Pin the middle of the color ramp to center, so a diverging ramp’s neutral color lands on a value that means something – zero, a baseline, a target – instead of on the numeric midpoint of whatever the data happened to span.

A diverging ramp’s whole claim is that its middle is neutral and its two ends are opposite. Placed at the data’s midpoint that claim is simply false: over values from -2 to +10 the neutral color sits at +4, so half the positive range is painted in the color that is supposed to mean “negative”. Centering fixes the mapping rather than the data, and the two arms are then free to be different sizes – which is the honest picture when the data is not symmetric.

Separate from scale_color_domain() on purpose. Centering is about where the ramp’s middle goes, not about what its ends mean, and the two are wanted independently: a center on its own re-places the middle inside the data’s own limits, which is the common case, while a domain on its own leaves the ramp symmetric. Folding both into one call would have forced every caller who wants a centered ramp to also state limits they had no opinion about.

center must lie strictly inside the resolved color domain. It is not quietly widened to fit: widening would move the ramp’s ends, so a chart asking only “center this at zero” would get different end colors than the one beside it, which is the silent disagreement the whole feature exists to remove. The render raises and names the domain instead, so the fix is an explicit scale_color_domain().

This is reached by moving the ramp’s stops instead of bending the value projection; see ColorScale.from_theme_centered() for why that route is the one that keeps the legend honest.

Defined for any ramp, not only a three-stop diverging one – it means “the color at offset 0.5 lands on center” whatever the stops are. On a sequential ramp like colormaps.viridis() that is legal but rarely useful.

Args:

  • self (Self)
  • center (Float64): The value the ramp’s middle color sits on. Must be strictly between the color domain’s min and max.

Returns:

Self: Self, for further chaining – the render raises later if center is not strictly inside the domain, or the mark has no continuous color channel.

secondary_axis

fn def secondary_axis(var self) -> Self

Draw this layer’s y values against a second, independent y-domain on the plot’s right edge instead of render_layers()’s shared left-axis domain (ECharts’ yAxisIndex: 1, as a boolean since only two y-axes are ever drawn). For a combo chart whose series have different units; see _render_layers_generic.

render_layers()/render_layers_svg() only; render()/ render_svg() raise if a plot with this set reaches them. At least one layer must stay on the primary axis. The secondary axis gets an axis line, ticks, and tick labels on the right edge but no gridlines. This layer’s Plot.labels() y_title captions the secondary axis (see _secondary_axis_y_title).

See the Cookbook’s own “Dual Y-Axis” recipe (docs/src/ cookbook_recipes/dual_axis.mojo) for a full worked example.

Args:

  • self (Self)

Returns:

Self: Self, for further chaining.

encode_dendrogram

fn def encode_dendrogram(var self, tree: Dendrogram, labels: List[String], horizontal: Bool = False) -> Self

Give Mark.DENDROGRAM a merge tree from dataviz.core.cluster.linkage() and one label per leaf (#355).

labels is in the tree’s leaf order, not the caller’s original row order, because that reordering is the whole point of clustering: tree.leaf_order says which original row each position holds.

The tree is flattened here into three parallel lists, which is what the render walks. Ids are positions along the leaf axis for the leaves and len(labels) + k for merge k, and because linkage() returns its merges sorted so a node’s children come first, one forward pass places every node.

Args:

  • self (Self)
  • tree (Dendrogram): The merge tree.
  • labels (List[String]): One name per leaf, in leaf order.
  • horizontal (Bool): Leaves down the y-axis rather than across the x.

Returns:

Self: Self, for further chaining – render() raises later if the tree and the labels disagree.

encode

fn def encode(var self, x: List[Float64], y: List[Float64], color: List[Float64] = List(), color_categories: List[String] = List(), size: List[Float64] = List(), y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List(), color_map: Dict[String, Color] = Dict(), shape_map: Dict[String, PointShape] = Dict(), labels: List[String] = List(), x_err: List[Float64] = List(), x_err_lower: List[Float64] = List(), x_err_upper: List[Float64] = List()) -> Self

Map data columns onto channels. x/y are required; the optional channels must match their length, checked at render() time (a builder method can’t raise mid-chain).

color (continuous, through a ColorScale over the column’s its minimum and maximum) and color_categories (discrete, through categorical_palette_for(theme) by first-seen order of the unique values) are mutually exclusive. size is continuous only. color_map pins specific color_categories values to colors ({category_name: Color}); unlisted categories keep their palette color, and it raises without color_categories.

y_err draws a capped vertical whisker of +/- y_err[i] around each point (Theme.error_bar_cap_width); y_err_lower/y_err_upper, given together, draw an asymmetric one. The two forms are mutually exclusive and every value must be >= 0. x_err, or x_err_lower/x_err_upper together, draw the horizontal counterpart under the same rules, independently of the y bars, so a point with both reads as a cross; the x domain widens to span them as the y domain does for y_err. Error bars use the point’s own resolved color. labels draws each row’s text above its point; "" skips a row.

Mark support: color/color_categories/size/color_map on POINT/SINGLE_AXIS/EFFECT_SCATTER; labels on POINT/ EFFECT_SCATTER; y_err, y_err_lower/y_err_upper, x_err and x_err_lower/x_err_upper on POINT/LINE/ EFFECT_SCATTER. For a categorical x-axis use encode_categorical().

See the Cookbook’s own “Error Bars” recipe (docs/src/ cookbook_recipes/error_bars.mojo) for a full worked example.

Args:

  • self (Self)
  • x (List[Float64]): The continuous x column, one entry per point.
  • y (List[Float64]): The continuous y column, one entry per point.
  • color (List[Float64]): Optional continuous color channel, mapped through a ColorScale spanning the column’s minimum and maximum; mutually exclusive with color_categories. Mark. POINT/SINGLE_AXIS/EFFECT_SCATTER only.
  • color_categories (List[String]): Optional discrete color channel, palette-colored by each value’s first-seen order among its unique values; mutually exclusive with color. Mark.POINT/SINGLE_AXIS/EFFECT_SCATTER only.
  • size (List[Float64]): Optional point-size channel, continuous only. Mark.POINT/SINGLE_AXIS/EFFECT_SCATTER only.
  • y_err (List[Float64]): Optional symmetric error-bar half-width per point, continuous only, every value >= 0; mutually exclusive with y_err_lower/y_err_upper. Mark.POINT/LINE/ EFFECT_SCATTER only (not SINGLE_AXIS).
  • y_err_lower (List[Float64]): Optional asymmetric error-bar downward extent per point; must be given together with y_err_upper, every value >= 0. Mark.POINT/LINE/EFFECT_SCATTER only.
  • y_err_upper (List[Float64]): Optional asymmetric error-bar upward extent per point; must be given together with y_err_lower, every value >= 0. Mark.POINT/LINE/EFFECT_SCATTER only.
  • color_map (Dict[String, Color]): Optional explicit category-to-color overrides, keyed by the category’s own name; only meaningful alongside color_categories. Mark.POINT/SINGLE_ AXIS/EFFECT_SCATTER only (whatever mark color_ categories is used on).
  • shape_map (Dict[String, PointShape]): Optional explicit category-to-shape overrides, used only under Theme.shape_by_category. A category absent here takes the shape for its index. shared_shape_map() builds one covering a whole figure so a category missing from one panel does not shift the shapes of the others (#365).
  • labels (List[String]): Optional per-point text, drawn above each point; an entry of "" skips that one point’s label. Mark.POINT/EFFECT_SCATTER only.
  • x_err (List[Float64]): Optional symmetric horizontal error-bar half-width per point, every value >= 0; mutually exclusive with x_err_lower/x_err_upper. Mark.POINT/LINE/ EFFECT_SCATTER only.
  • x_err_lower (List[Float64]): Optional asymmetric horizontal error-bar leftward extent per point; must be given together with x_err_upper, every value >= 0.
  • x_err_upper (List[Float64]): Optional asymmetric horizontal error-bar rightward extent per point; must be given together with x_err_lower, every value >= 0.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode[TX: Float64Sequence, TY: Float64Sequence](var self, x: TX, y: TY, color: List[Float64] = List(), color_categories: List[String] = List(), size: List[Float64] = List(), y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List(), color_map: Dict[String, Color] = Dict(), shape_map: Dict[String, PointShape] = Dict(), labels: List[String] = List(), x_err: List[Float64] = List(), x_err_lower: List[Float64] = List(), x_err_upper: List[Float64] = List()) -> Self

encode()’s x/y generalized to anything conforming to Float64Sequence (array_like.mojo), for data in a custom buffer wrapper or a dataframe column type. A type’s author has to declare the conformance; List itself and numpy arrays can’t be retrofitted, which is why the concrete overload above still exists. x and y each take their own type parameter, so they need not be the same container type (#699). Materializes both via _materialize_floats and delegates to the concrete encode().

Parameters:

  • TX (Float64Sequence)
  • TY (Float64Sequence)

Args:

  • self (Self)
  • x (TX): The continuous x column, one entry per point – anything conforming to Float64Sequence.
  • y (TY): The continuous y column, one entry per point – anything conforming to Float64Sequence, not necessarily x’s type.
  • color (List[Float64]): See encode()’s own docstring – unchanged here, still a concrete List[Float64].
  • color_categories (List[String]): See encode()’s own docstring.
  • size (List[Float64]): See encode()’s own docstring.
  • y_err (List[Float64]): See encode()’s own docstring.
  • y_err_lower (List[Float64]): See encode()’s own docstring.
  • y_err_upper (List[Float64]): See encode()’s own docstring.
  • color_map (Dict[String, Color]): See encode()’s own docstring.
  • shape_map (Dict[String, PointShape]): See encode()’s own docstring.
  • labels (List[String]): See encode()’s own docstring.
  • x_err (List[Float64]): See encode()’s own docstring.
  • x_err_lower (List[Float64]): See encode()’s own docstring.
  • x_err_upper (List[Float64]): See encode()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode[x_dtype: DType, y_dtype: DType](var self, x: List[Scalar[x_dtype]], y: List[Scalar[y_dtype]], color: List[Float64] = List(), color_categories: List[String] = List(), size: List[Float64] = List(), y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List(), color_map: Dict[String, Color] = Dict(), shape_map: Dict[String, PointShape] = Dict(), labels: List[String] = List(), x_err: List[Float64] = List(), x_err_lower: List[Float64] = List(), x_err_upper: List[Float64] = List()) -> Self

encode()’s x/y generalized over numeric element type (List[Int], List[Float32], any List[Scalar[dtype]]), a different axis from the Float64Sequence overload (element type rather than container type; see array_like.mojo for why this uses DType genericity rather than a trait). x and y each take their own element type, so List[Int] x against List[Float64] y works (#699). Materializes both via _materialize_scalar_list and delegates to the concrete encode(), which Mojo still picks directly when both are List[Float64].

Parameters:

  • x_dtype (DType)
  • y_dtype (DType)

Args:

  • self (Self)
  • x (List[Scalar[x_dtype]]): The continuous x column, one entry per point – any numeric List[Scalar[dtype]].
  • y (List[Scalar[y_dtype]]): The continuous y column, one entry per point – any numeric List[Scalar[dtype]], not necessarily x’s.
  • color (List[Float64]): See encode()’s own docstring – unchanged here, still a concrete List[Float64].
  • color_categories (List[String]): See encode()’s own docstring.
  • size (List[Float64]): See encode()’s own docstring.
  • y_err (List[Float64]): See encode()’s own docstring.
  • y_err_lower (List[Float64]): See encode()’s own docstring.
  • y_err_upper (List[Float64]): See encode()’s own docstring.
  • color_map (Dict[String, Color]): See encode()’s own docstring.
  • shape_map (Dict[String, PointShape]): See encode()’s own docstring.
  • labels (List[String]): See encode()’s own docstring.
  • x_err (List[Float64]): See encode()’s own docstring.
  • x_err_lower (List[Float64]): See encode()’s own docstring.
  • x_err_upper (List[Float64]): See encode()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode(var self, x: PythonObject, y: PythonObject, color: List[Float64] = List(), color_categories: List[String] = List(), size: List[Float64] = List(), y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List(), color_map: Dict[String, Color] = Dict(), shape_map: Dict[String, PointShape] = Dict(), labels: List[String] = List(), x_err: List[Float64] = List(), x_err_lower: List[Float64] = List(), x_err_upper: List[Float64] = List()) -> Self

encode()’s x/y generalized to a numpy ndarray, a pandas Series, a MAX Tensor/Buffer, or a plain Python list of numbers (see numpy_interop.mojo). Requires numpy in the caller’s environment; raises numpy’s own error if it’s missing or x/y can’t become a 1-D numeric array. x/y need not share a dtype. Materializes both via _materialize_python_floats and delegates to the concrete encode().

Args:

  • self (Self)
  • x (PythonObject): The continuous x column, one entry per point – a numpy ndarray, a pandas Series, a MAX Tensor/Buffer, or a plain Python list of numbers.
  • y (PythonObject): The continuous y column, one entry per point – same shape as x.
  • color (List[Float64]): See encode()’s own docstring – unchanged here, still a concrete List[Float64].
  • color_categories (List[String]): See encode()’s own docstring.
  • size (List[Float64]): See encode()’s own docstring.
  • y_err (List[Float64]): See encode()’s own docstring.
  • y_err_lower (List[Float64]): See encode()’s own docstring.
  • y_err_upper (List[Float64]): See encode()’s own docstring.
  • color_map (Dict[String, Color]): See encode()’s own docstring.
  • shape_map (Dict[String, PointShape]): See encode()’s own docstring.
  • labels (List[String]): See encode()’s own docstring.
  • x_err (List[Float64]): See encode()’s own docstring.
  • x_err_lower (List[Float64]): See encode()’s own docstring.
  • x_err_upper (List[Float64]): See encode()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

encode_vectors3d

fn def encode_vectors3d(var self, x: List[Float64], y: List[Float64], z: List[Float64], u: List[Float64], v: List[Float64], w: List[Float64]) -> Self

Give Mark.QUIVER3D its arrow tails and components (#345).

The components are in the data’s own units on each axis, so an arrow’s length is read against the axes rather than against a separate legend.

Length agreement is checked at render time, like every other encode method here.

Args:

  • self (Self)
  • x (List[Float64]): The x coordinate of each arrow’s tail.
  • y (List[Float64]): The y coordinate of each tail, the same length.
  • z (List[Float64]): The z coordinate of each tail, the same length.
  • u (List[Float64]): The x component of each arrow, the same length.
  • v (List[Float64]): The y component, the same length.
  • w (List[Float64]): The z component, the same length.

Returns:

Self: Self, for further chaining.

Raises:

encode_ribbon3d

fn def encode_ribbon3d(var self, x1: List[Float64], y1: List[Float64], z1: List[Float64], x2: List[Float64], y2: List[Float64], z2: List[Float64]) -> Self

Give Mark.FILL_BETWEEN3D the two curves it fills between (#345).

Args:

  • self (Self)
  • x1 (List[Float64]): The first curve’s x column.
  • y1 (List[Float64]): The first curve’s y column, the same length.
  • z1 (List[Float64]): The first curve’s z column, the same length.
  • x2 (List[Float64]): The second curve’s x column, the same length.
  • y2 (List[Float64]): The second curve’s y column, the same length.
  • z2 (List[Float64]): The second curve’s z column, the same length.

Returns:

Self: Self, for further chaining.

Raises:

encode_bars3d

fn def encode_bars3d(var self, x: List[Float64], y: List[Float64], z: List[Float64]) -> Self

Give Mark.BAR3D its bar centers and heights (#345).

x and y are each bar’s center on the base plane, not a corner: a bar is read as a column over a position, and centers are what a lattice of positions gives you.

Length agreement is checked at render time, like every other encode method here.

Args:

  • self (Self)
  • x (List[Float64]): Each bar’s center along x.
  • y (List[Float64]): Each bar’s center along y, the same length.
  • z (List[Float64]): Each bar’s height from the base plane, the same length.

Returns:

Self: Self, for further chaining.

Raises:

encode_voxels

fn def encode_voxels(var self, filled: List[List[List[Bool]]]) -> Self

Give Mark.VOXELS its occupancy grid (#345).

Args:

  • self (Self)
  • filled (List[List[List[Bool]]]): filled[layer][row][col], True where the cell is solid. Layers run up z, rows along y and columns along x – encode_surface()’s order with a third index in front.

Returns:

Self: Self, for further chaining.

Raises:

encode_surface

fn def encode_surface(var self, z: List[List[Float64]], x: List[Float64] = List(), y: List[Float64] = List()) -> Self

Give a surface mark its height grid (#345).

The grid is row-major (z[row][col]), rows along y and columns along x – the same shape and the same optional coordinate columns as encode_contour(), so a field can be drawn either way without reshaping it.

Shape is checked at render time, like every other encode method here.

Args:

  • self (Self)
  • z (List[List[Float64]]): The grid, rectangular and at least 2x2.
  • x (List[Float64]): One x coordinate per column. Empty leaves the axis in grid-index units.
  • y (List[Float64]): One y coordinate per row. Empty leaves the axis in grid-index units.

Returns:

Self: Self, for further chaining.

Raises:

encode_xyz

fn def encode_xyz(var self, x: List[Float64], y: List[Float64], z: List[Float64]) -> Self

Give a 3D mark its three equal-length columns (#345).

Each axis is normalised to the viewing cube independently, so one axis spanning nanometres and another kilometres come out the same size. A 3D box is a viewing volume rather than a shared unit, and scaling them together would collapse every axis but the largest.

Length agreement is checked at render time, like every other encode method here.

Args:

  • self (Self)
  • x (List[Float64]): The x column.
  • y (List[Float64]): The y column, the same length.
  • z (List[Float64]): The z column, the same length.

Returns:

Self: Self, for further chaining.

Raises:

fill_colors

fn def fill_colors(var self, colors: Dict[String, Color]) -> Self

Pin named categories or series to fill colors (#848), for the marks that fill one shape per name: pie and donut, stacked and grouped bars, funnel, streamgraph, treemap and sunburst branches, marimekko, nightingale, polar bar and population pyramid sides.

A name absent from colors takes the palette color for its position, as before. A name in colors that the chart does not have is ignored, so one map can cover every panel of a figure, the way encode()’s color_map does for points. The legend shows the pinned colors. A mark that does not fill by name cannot call it: that is a compile-time error.

Args:

  • self (Self)
  • colors (Dict[String, Color]): Category or series name to color. Replaces any map given before.

Returns:

Self: Self, for further chaining.

fill_patterns

fn def fill_patterns(var self, patterns: Dict[String, HatchStyle]) -> Self

Pin named categories or series to HatchStyle patterns (#848), on the same marks as fill_colors().

A pinned pattern is drawn whether or not Theme.fill_pattern_by_category is on. With the flag on, a name absent here takes the pattern for its position; with it off, it takes none. So a caller can pattern one highlighted slice and leave the rest solid. Unknown names are ignored, as in fill_colors(), and the legend shows the patterns.

Args:

  • self (Self)
  • patterns (Dict[String, HatchStyle]): Category or series name to pattern. Replaces any map given before.

Returns:

Self: Self, for further chaining.

sort_categories

fn def sort_categories(var self, order: CategoryOrder) -> Self

Reorder a categorical chart’s categories by value or by label (#843): bar(regions, sales).sort_categories(CategoryOrder. VALUE_DESCENDING) is the ranked bar chart.

Every per-category column moves together, so each category keeps its value and its error bars. The sort is stable, and a missing value sorts last. It reorders the data the chart holds now, so it comes after encode_categorical(); before it there is nothing to sort and it raises. A mark without categories cannot call it at all: that is a compile-time error.

Args:

  • self (Self)
  • order (CategoryOrder): One of CategoryOrder’s constants.

Returns:

Self: Self, for further chaining.

Raises:

Error: The chart has no categories yet, or its categories and values differ in length.

fn def sort_categories(var self, order: List[String]) -> Self

Put a categorical chart’s categories in the order order names them (#843), for an order the data cannot imply: months, survey scales, a region list a report always uses.

order must name every category exactly once. A missing name would drop a bar and a repeated or unknown one is a typo, so all three raise with the name at fault.

Args:

  • self (Self)
  • order (List[String]): Every category’s name, in the order to draw them.

Returns:

Self: Self, for further chaining.

Raises:

Error: The chart has no categories yet, or order misses, repeats or invents a category.

encode_categorical

fn def encode_categorical(var self, x: List[String], y: List[Float64], y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List()) -> Self

Map a categorical x column and a continuous y column onto the x/y channels, for Mark.BAR and the other category-plus-value marks. x is treated as the axis’s category order as given, not deduplicated or re-sorted; repeated categories raise with their first and second positions. Use encode_grouped_bar() for category-by-series values.

y_err/y_err_lower/y_err_upper work exactly as they do on encode() – see that method’s own docstring for the shared rules (mutually exclusive forms, every value >= 0) – except Mark.BAR is the only mark among encode_categorical()’s that draws them today; every other mark this method feeds (LOLLIPOP, WATERFALL, NIGHTINGALE, FUNNEL, POLAR_BAR, RADIALBAR, …) raises if given one.

Args:

  • self (Self)
  • x (List[String]): One category per entry, in the given order – treated as already being the axis’s category order; duplicates are rejected.
  • y (List[Float64]): Each category’s value.
  • y_err (List[Float64]): Optional symmetric error-bar half-width per bar, continuous only, every value >= 0; mutually exclusive with y_err_lower/y_err_upper. Mark.BAR only.
  • y_err_lower (List[Float64]): Optional asymmetric error-bar downward extent per bar; must be given together with y_err_upper, every value >= 0. Mark.BAR only.
  • y_err_upper (List[Float64]): Optional asymmetric error-bar upward extent per bar; must be given together with y_err_lower, every value >= 0. Mark.BAR only.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_categorical[Tx: StringSequence](var self, x: Tx, y: List[Float64], y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List()) -> Self

encode_categorical()’s x generalized to anything conforming to StringSequence (array_like.mojo), as encode()’s Float64Sequence overload does for its x/y. y stays a concrete List[Float64]; each encode_categorical() overload generalizes one parameter at a time. Materializes x via _materialize_strings and delegates to the concrete overload.

Parameters:

  • Tx (StringSequence)

Args:

  • self (Self)
  • x (Tx): One category per entry, in the given order – anything conforming to StringSequence.
  • y (List[Float64]): Each category’s value – a concrete List[Float64].
  • y_err (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_lower (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_upper (List[Float64]): See encode_categorical()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_categorical[dtype: DType](var self, x: List[String], y: List[Scalar[dtype]], y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List()) -> Self

encode_categorical()’s y generalized over numeric element type (List[Int], List[Float32], …), as encode()’s DType overload is. x stays a concrete List[String]. Materializes y via _materialize_scalar_list and delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • x (List[String]): One category per entry, in the given order.
  • y (List[Scalar[dtype]]): Each category’s value – any numeric List[Scalar[ dtype]].
  • y_err (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_lower (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_upper (List[Float64]): See encode_categorical()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_categorical(var self, x: List[String], y: PythonObject, y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List()) -> Self

encode_categorical()’s y generalized to a numpy ndarray/pandas Series/MAX Tensor or Buffer/plain Python number list, as encode()’s PythonObject overload is (see numpy_interop.mojo). x stays a concrete List[String]. Materializes y via _materialize_python_floats and delegates to the concrete overload.

Args:

  • self (Self)
  • x (List[String]): One category per entry, in the given order.
  • y (PythonObject): Each category’s value – a numpy ndarray, a pandas Series, a MAX Tensor/Buffer, or a plain Python list of numbers.
  • y_err (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_lower (List[Float64]): See encode_categorical()’s own docstring.
  • y_err_upper (List[Float64]): See encode_categorical()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

encode_time_bars

fn def encode_time_bars(var self, dates: List[Morrow], values: List[Float64], y_err: List[Float64] = List(), y_err_lower: List[Float64] = List(), y_err_upper: List[Float64] = List()) -> Self

Map bars to real timestamps on a continuous time x-axis.

Each bar is centered on its timestamp and spans one observed interval. Dates must be distinct; the interval is inferred from their spacing at render time. The three error channels follow encode_categorical()’s rules. Only vertical bars have a time x-axis.

Args:

  • self (Self)
  • dates (List[Morrow])
  • values (List[Float64])
  • y_err (List[Float64])
  • y_err_lower (List[Float64])
  • y_err_upper (List[Float64])

Returns:

Self

Raises:

encode_binned_categories

fn def encode_binned_categories(var self, data: List[Float64], bins: Int = Int(10)) -> Self

Bin raw observations into bins equal-width intervals for a categorical Mark.BAR chart: one bar per interval, labeled with its range, its height the count that landed in it. Named apart from encode_histogram() because it is a different chart – the intervals become category labels, evenly spaced whatever their numeric width – so mark_histogram() is what to reach for when the x-axis should be numeric (#698).

Args:

  • self (Self)
  • data (List[Float64]): Raw observations to bin.
  • bins (Int): Number of equal-width intervals.

Returns:

Self: Self, for further chaining.

Raises:

Error: The mark is not Mark.BAR, data is empty, bins is not positive, or a value is not finite.

fn def encode_binned_categories(var self, data: List[Float64], rule: BinRule) -> Self

encode_binned_categories with the bin count chosen by rule rather than named – BinRule.AUTO for numpy’s bins="auto".

Args:

  • self (Self)
  • data (List[Float64]): Raw observations to bin.
  • rule (BinRule): Which BinRule picks the bin count.

Returns:

Self: Self, for further chaining.

Raises:

Error: The mark is not Mark.BAR, data is empty, or a value is not finite.

encode_waterfall

fn def encode_waterfall(var self, categories: List[String], deltas: List[Float64], is_total: List[Bool] = List()) -> Self

Map a category column and a signed delta column onto Mark.WATERFALL’s floating-bar shape: deltas[i] is how much the running total changes at category i. Each bar runs from the running total before it (y0) to the running total after it (y1), computed here via _waterfall_running_totals() (waterfall.mojo) as a cumulative sum from 0.0.

is_total (default empty) marks specific rows as running-total checkpoints; see _waterfall_running_totals() for how such a row draws and waterfall()’s Example: for the conventional start-then-deltas-then-end shape.

Length matching (categories/deltas, and is_total when non-empty) is checked at render() time. deltas is kept as _continuous.y so _render_waterfall can color each delta bar by sign.

Args:

  • self (Self)
  • categories (List[String]): One floating bar per entry, in the given order.
  • deltas (List[Float64]): How much the running total changes at each category – not the bar’s absolute height; the cumulative sum starts from 0.0.
  • is_total (List[Bool]): Marks specific rows as running-total checkpoints instead of a plain rising/falling delta. Left empty (the default), every row is a plain delta.

Returns:

Self: Self, for further chaining.

Raises:

encode_boxenplot

fn def encode_boxenplot(var self, categories: List[String], values: List[List[Float64]]) -> Self

Map a category column and, per category, a list of raw values onto Mark.BOXENPLOT’s nested boxes: the letter values are computed here, immediately, via _letter_values() (boxen.mojo) – median, then quantile pairs at the quartiles, eighths, sixteenths and on, as many levels as the sample size supports, with every observation beyond the deepest pair as an outlier.

Args:

  • self (Self)
  • categories (List[String]): One label per group.
  • values (List[List[Float64]]): values[i] is every raw observation in categories[i]; each must be non-empty.

Returns:

Self: Self, for further chaining.

Raises:

Error: categories and values differ in length, or a group is empty.

fn def encode_boxenplot[dtype: DType](var self, categories: List[String], values: List[List[Scalar[dtype]]]) -> Self

encode_boxenplot()’s values generalized over numeric element type; see encode_boxplot()’s DType overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • categories (List[String])
  • values (List[List[Scalar[dtype]]])

Returns:

Self

Raises:

encode_boxplot

fn def encode_boxplot(var self, categories: List[String], values: List[List[Float64]]) -> Self

Map a category column and, per category, a list of raw values onto Mark.BOX’s box-and-whiskers shape. Each category’s distribution is summarized immediately into a five-number summary (quartiles via linear interpolation, numpy.percentile’s default) plus every outlier beyond the 1.5*IQR fence, via _box_stats() (box.mojo).

Raises immediately on a categories/values length mismatch or an empty value list, since quartiles are undefined for zero points.

Args:

  • self (Self)
  • categories (List[String]): One box per entry, in the given order.
  • values (List[List[Float64]]): Each category’s raw values (values[i]) – must be non-empty; quartiles/whiskers/outliers are computed from these immediately, not deferred to render() time.

Returns:

Self: Self, for further chaining.

Raises:

If categories/values lengths don’t match, categories is empty, or any category’s value list is empty.

fn def encode_boxplot[dtype: DType](var self, categories: List[String], values: List[List[Scalar[dtype]]]) -> Self

encode_boxplot()’s values generalized over numeric element type (List[List[Int]], List[List[Float32]], …) via _materialize_nested_scalar_list (array_like.mojo). categories stays concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • categories (List[String]): One box per entry, in the given order.
  • values (List[List[Scalar[dtype]]]): Each category’s raw values – any numeric List[List[Scalar[dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

If categories/values lengths don’t match, or any category’s value list is empty.

encode_candlestick

fn def encode_candlestick(var self, categories: List[String], open: List[Float64], high: List[Float64], low: List[Float64], close: List[Float64]) -> Self

Map a category column and four value columns (open/high/low/close) onto Mark.CANDLESTICK’s wick-plus-body shape. Nothing is computed up front, so length checking is deferred to render() time, as for encode_categorical().

Args:

  • self (Self)
  • categories (List[String]): One bar per entry, in the given order.
  • open (List[Float64]): Each category’s opening value.
  • high (List[Float64]): Each category’s highest value.
  • low (List[Float64]): Each category’s lowest value.
  • close (List[Float64]): Each category’s closing value.

Returns:

Self: Self, for further chaining.

Raises:

encode_candlestick_time

fn def encode_candlestick_time(var self, dates: List[Morrow], open: List[Float64], high: List[Float64], low: List[Float64], close: List[Float64]) -> Self

Map OHLC prices onto real timestamps for Mark.CANDLESTICK.

Dates occupy their actual positions on a linear time axis, so weekends and other gaps are visible. The first date’s zone sets the time tick labels, as with encode_time(). Length and spacing checks happen when the chart is rendered.

Args:

  • self (Self)
  • dates (List[Morrow])
  • open (List[Float64])
  • high (List[Float64])
  • low (List[Float64])
  • close (List[Float64])

Returns:

Self

Raises:

encode_bullet

fn def encode_bullet(var self, categories: List[String], measures: List[Float64], targets: List[Float64], ranges: List[List[Float64]]) -> Self

Map a category column plus measures (drawn as a narrower bar), targets (drawn as a tick mark), and ranges (per category, an ascending list of qualitative-range thresholds, e.g. [50.0, 75.0, 100.0], drawn as shaded bands from 0 up to each threshold) onto Mark.BULLET’s shape. Length checking, and each ranges entry being non-empty and non-decreasing, is deferred to render() time.

Args:

  • self (Self)
  • categories (List[String]): One row per entry, in the given order.
  • measures (List[Float64]): Each category’s actual value, drawn as the narrower measure bar.
  • targets (List[Float64]): Each category’s goal value, drawn as a tick mark.
  • ranges (List[List[Float64]]): Each category’s own ascending, non-empty list of qualitative-range thresholds, drawn as shaded background bands.

Returns:

Self: Self, for further chaining.

Raises:

encode_gantt

fn def encode_gantt(var self, categories: List[String], start: List[Float64], end: List[Float64]) -> Self

Map a category column and two value columns (start/end) onto Mark.GANTT/SPAN_CHART’s span shape. This overload takes plain Float64; use encode_gantt_time() for Morrow dates on a dated Gantt axis. Numeric spans also serve generic span charts. Length checking is deferred to render() time. start[i] > end[i] is allowed: bars draw from min to max.

Args:

  • self (Self)
  • categories (List[String]): One horizontal bar per entry, top to bottom.
  • start (List[Float64]): Each bar’s starting value.
  • end (List[Float64]): Each bar’s ending value; not required to be greater than start – drawn from min(start[i], end[i]) to max(...).

Returns:

Self: Self, for further chaining.

Raises:

encode_gantt_time

fn def encode_gantt_time(var self, categories: List[String], start: List[Morrow], end: List[Morrow]) -> Self

Map Gantt task spans to a date-aware continuous x-axis.

The first start’s time zone sets tick labels. Mixed zones still place bars at their absolute instants. Length checks remain at render time, as with encode_gantt().

Args:

  • self (Self)
  • categories (List[String])
  • start (List[Morrow])
  • end (List[Morrow])

Returns:

Self

Raises:

encode_grouped_bar

fn def encode_grouped_bar(var self, categories: List[String], series_names: List[String], values: List[List[Float64]], errors: List[List[Float64]] = List()) -> Self

Map a category column plus several value series onto Mark.GROUPED_BAR’s shape (also used by STACKED_BAR/BUMP/ STREAMGRAPH): values[j][i] is series series_names[j]’s value for categories[i]. Length checking (series_names/values, and every values[j] against categories) is deferred to render() time.

errors, left empty by default, is values’ per-(series, category) symmetric error-bar half-width shape: errors[j][i] is series series_names[j]’s error bar for categories[i]. Every value must be >= 0; Mark.GROUPED_BAR only among the marks this method feeds – STACKED_BAR/BUMP/STREAMGRAPH raise if given one, the same restriction encode_categorical()’s y_err has against its own wider mark family.

Args:

  • self (Self)
  • categories (List[String]): One group of side-by-side bars per entry, in the given order.
  • series_names (List[String]): One sub-bar per name.
  • values (List[List[Float64]]): values[j] is series_names[j]’s value per category.
  • errors (List[List[Float64]]): Optional per-(series, category) symmetric error-bar half-width, shaped like values, every value >= 0. Mark.GROUPED_BAR only.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_grouped_bar[Tx: StringSequence](var self, categories: Tx, series_names: List[String], values: List[List[Float64]], errors: List[List[Float64]] = List()) -> Self

encode_grouped_bar()’s categories generalized to anything conforming to StringSequence (array_like.mojo), as encode_categorical()’s StringSequence overload is. series_names/values stay concrete. Materializes categories via _materialize_strings and delegates to the concrete overload.

Parameters:

  • Tx (StringSequence)

Args:

  • self (Self)
  • categories (Tx): One group of side-by-side bars per entry, in the given order – anything conforming to StringSequence.
  • series_names (List[String]): One sub-bar per name.
  • values (List[List[Float64]]): values[j] is series_names[j]’s value per category.
  • errors (List[List[Float64]]): See encode_grouped_bar()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_grouped_bar[dtype: DType](var self, categories: List[String], series_names: List[String], values: List[List[Scalar[dtype]]], errors: List[List[Float64]] = List()) -> Self

encode_grouped_bar()’s values generalized over numeric element type (List[List[Int]], List[List[Float32]], …) via _materialize_nested_scalar_list (array_like.mojo). categories/ series_names stay concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • categories (List[String]): One group of side-by-side bars per entry, in the given order.
  • series_names (List[String]): One sub-bar per name.
  • values (List[List[Scalar[dtype]]]): values[j] is series_names[j]’s value per category – any numeric List[List[Scalar[dtype]]].
  • errors (List[List[Float64]]): See encode_grouped_bar()’s own docstring.

Returns:

Self: Self, for further chaining.

Raises:

encode_population_pyramid

fn def encode_population_pyramid(var self, categories: List[String], left_values: List[Float64], right_values: List[Float64], left_name: String = "", right_name: String = "") -> Self

Map a category column plus two magnitude columns onto Mark.POPULATION_PYRAMID’s mirrored-bars shape: left_values[i]/ right_values[i] each grow outward from a shared, centered zero baseline. Both are read as magnitudes regardless of sign (max(v, -v)), so a caller with signed data should decide which side each value belongs on. left_name/right_name label the two-entry legend, falling back to “Left”/“Right” when empty. Length checking is deferred to render() time.

Args:

  • self (Self)
  • categories (List[String]): One row per entry, in the given order.
  • left_values (List[Float64]): Each row’s left-side magnitude, read non-negative regardless of sign.
  • right_values (List[Float64]): Each row’s right-side magnitude, read non-negative regardless of sign.
  • left_name (String): Legend label for the left side; left empty (the default), falls back to “Left” at render time.
  • right_name (String): Legend label for the right side; left empty (the default), falls back to “Right” at render time.

Returns:

Self: Self, for further chaining.

Raises:

encode_heatmap

fn def encode_heatmap(var self, x: List[String], y: List[String], value: List[Float64]) -> Self

Map two category columns plus a value column onto Mark.HEATMAP’s grid-cell shape: one row per cell (x[i], y[i], value[i]). Each axis’s domain is derived from x/y’s distinct values in first-seen order (_categorical_indices, at render() time). A missing (x, y) combination is simply not drawn. Length checking is deferred to render() time.

Args:

  • self (Self)
  • x (List[String]): Each cell’s column category, one entry per row of data.
  • y (List[String]): Each cell’s row category, one entry per row of data.
  • value (List[Float64]): Each cell’s value, mapped through a continuous color gradient.

Returns:

Self: Self, for further chaining.

Raises:

encode_calendar

fn def encode_calendar(var self, dates: List[String], values: List[Float64]) -> Self

Map a date column and a value column onto Mark.CALENDAR_HEATMAP’s shape: one row per day, dates[i] a "YYYY-MM-DD" string (parsed only for grid placement; see calendar_heatmap.mojo’s _parse_date/ _days_from_civil) and values[i] colored through the same gradient encode_heatmap() uses. Every date must fall in the same calendar year (inferred from the first), checked at render() time along with the length match.

Args:

  • self (Self)
  • dates (List[String]): Plain "YYYY-MM-DD" strings, one per entry, all in the same calendar year (inferred from dates[0]).
  • values (List[Float64]): Each date’s value, mapped through a continuous color gradient.

Returns:

Self: Self, for further chaining.

Raises:

encode_corrplot

fn def encode_corrplot(var self, variables: List[String], matrix: List[List[Float64]]) -> Self

Map a variable-name list and a square correlation matrix onto Mark.CORRPLOT’s shape: matrix[row][col] is the correlation between variables[row] and variables[col]. Squareness and every value being in [-1.0, 1.0] are checked at render() time.

Args:

  • self (Self)
  • variables (List[String]): One row and one column per entry – matrix must be this length square.
  • matrix (List[List[Float64]]): The square pairwise-correlation matrix, each value in [-1.0, 1.0].

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_corrplot[dtype: DType](var self, variables: List[String], matrix: List[List[Scalar[dtype]]]) -> Self

encode_corrplot()’s matrix generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). variables stays concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • variables (List[String]): One row and one column per entry – matrix must be this length square.
  • matrix (List[List[Scalar[dtype]]]): The square pairwise-correlation matrix – any numeric List[List[Scalar[dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

encode_punchcard

fn def encode_punchcard(var self, x: List[String], y: List[String], sizes: List[Float64]) -> Self

Map two category columns plus a size column onto Mark.PUNCHCARD’s shape, with the same x/y domain derivation as encode_heatmap() and sizes in place of value. A repeated (x, y) pair is not merged; each row draws its own bubble. Length checking and sizes being non-negative are deferred to render() time.

Args:

  • self (Self)
  • x (List[String]): Each bubble’s column category, one entry per row of data.
  • y (List[String]): Each bubble’s row category, one entry per row of data.
  • sizes (List[Float64]): Each bubble’s raw size value, non-negative.

Returns:

Self: Self, for further chaining.

Raises:

encode_barbs

fn def encode_barbs(var self, x: List[Float64], y: List[Float64], u: List[Float64], v: List[Float64]) -> Self

Map Mark.BARBS’s four channels: continuous x/y positions plus the u/v components of the vector at each. Speed is hypot(u, v) in whatever unit the caller supplies – knots by convention, since the glyph’s 50/10/5 increments are the knot ones – and v is positive pointing up the page. Length checking is deferred to render() time.

Args:

  • self (Self)
  • x (List[Float64]): The continuous x position of each barb.
  • y (List[Float64]): The continuous y position of each barb.
  • u (List[Float64]): Each barb’s x-component, in the same unit as v.
  • v (List[Float64]): Each barb’s y-component, positive pointing up the page.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_barbs[dtype: DType](var self, x: List[Scalar[dtype]], y: List[Scalar[dtype]], u: List[Scalar[dtype]], v: List[Scalar[dtype]]) -> Self

encode_barbs() generalized over numeric element type via _materialize_scalar_list (array_like.mojo). Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • x (List[Scalar[dtype]]): The continuous x position of each barb.
  • y (List[Scalar[dtype]]): The continuous y position of each barb.
  • u (List[Scalar[dtype]]): Each barb’s x-component – any numeric List[Scalar[dtype]].
  • v (List[Scalar[dtype]]): Each barb’s y-component – any numeric List[Scalar[dtype]].

Returns:

Self: Self, for further chaining.

Raises:

encode_contour

fn def encode_contour(var self, z: List[List[Float64]], levels: List[Float64] = List(), x: List[Float64] = List(), y: List[Float64] = List()) -> Self

Map a rectangular grid of values onto Mark.CONTOUR’s shape.

z is row-major (z[row][col]): rows are the y axis and columns the x axis, with row 0 at the bottom.

Without x/y the axes are in grid-index units, so a 10x20 grid spans x from 0 to 19 and y from 0 to 9, unpadded, and the grid meets the plot rect’s edges. With them the axes are in the caller’s own units and get the same 5% padding every other continuous mark has, so a contour can share a frame with a scatter and mean the same thing by its x (#423). They are one value per column and per row, strictly increasing, and need not be evenly spaced.

Shape checking (rectangular, at least 2x2) and the coordinate checks are deferred to render() time, like every other encode method here.

Args:

  • self (Self)
  • z (List[List[Float64]]): The grid, row-major and rectangular, at least 2x2.
  • levels (List[Float64]): The values to trace. Left empty (the default), the count from mark_contour(levels=n) decides how many are placed inside the data’s range.
  • x (List[Float64]): One x coordinate per column of z, strictly increasing. Empty (the default) keeps grid-index units.
  • y (List[Float64]): One y coordinate per row of z, strictly increasing. Empty (the default) keeps grid-index units.

Returns:

Self: Self, for further chaining.

Raises:

encode_pcolormesh

fn def encode_pcolormesh(var self, x_edges: List[Float64], y_edges: List[Float64], z: List[List[Float64]]) -> Self

Map a 2D array plus its cell boundaries onto Mark.PCOLORMESH’s shape.

z is row-major as in encode_imshow(). x_edges/y_edges bound the cells rather than sit at their centers, so there is one more of each than the array has columns and rows. Both must be strictly increasing.

Length and ordering checks are deferred to render() time, like every other encode method here.

Args:

  • self (Self)
  • x_edges (List[Float64]): Column boundaries, cols + 1 of them, strictly increasing.
  • y_edges (List[Float64]): Row boundaries, rows + 1 of them, strictly increasing.
  • z (List[List[Float64]]): The array, row-major and rectangular, non-empty.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_pcolormesh(var self, x_corners: List[List[Float64]], y_corners: List[List[Float64]], z: List[List[Float64]]) -> Self

Map a 2D array onto a curvilinear mesh: one coordinate per grid vertex rather than one boundary per row and column (#424).

x_corners/y_corners are both (rows + 1) x (cols + 1), so cell (r, c) is the quadrilateral through vertices (r, c), (r, c + 1), (r + 1, c + 1) and (r + 1, c). That is what a rotated, sheared, polar or model-output grid needs: the 1D overload can only describe axis-aligned rectangles, because it sets column widths and row heights independently.

Nothing is required of the shape beyond the vertex count. Cells may be non-convex or self-overlapping; they are drawn in row order and a later cell paints over an earlier one.

Cell boundaries are antialiased rather than snapped to whole pixels, which the 1D form does. A quad has no rectangular outline to snap to, and neighbouring cells share an edge rather than a rectangle, so the run-merging the rectilinear path uses does not apply either. The visible effect is slightly softer cell edges; cell interiors are identical between the two forms for a mesh that could be described either way.

Length checks are deferred to render() time, like every other encode method here.

Args:

  • self (Self)
  • x_corners (List[List[Float64]]): Vertex x coordinates, (rows + 1) x (cols + 1).
  • y_corners (List[List[Float64]]): Vertex y coordinates, the same shape.
  • z (List[List[Float64]]): The array, row-major and rectangular, non-empty.

Returns:

Self: Self, for further chaining.

Raises:

encode_time

fn def encode_time(var self, x: List[Morrow], y: List[Float64]) -> Self

Map a time series: x as dates or timestamps, y as the continuous value at each.

The axis is a LinearScale over POSIX seconds, so every continuous mark draws against it unchanged – a time axis is a labeling problem, not a projection one. What changes is the ticks: they land on local midnights, month starts or year starts rather than on multiples of 50 days, and they read as dates (#195). See _time_ticks in scale.mojo.

The zone is taken from the first value, and every tick is placed and labeled in it. Supplying a mix of zones is allowed – the positions are absolute instants either way – but the axis will read in the first one’s.

Args:

  • self (Self)
  • x (List[Morrow]): The timestamps, one per point.
  • y (List[Float64]): The value at each, one per x.

Returns:

Self: Self, for further chaining.

Raises:

Error: morrow could not convert a value to a timestamp.

encode_histogram_bins

fn def encode_histogram_bins(var self, bins: HistogramBins) -> Self

Map already-binned data onto Mark.HISTOGRAM’s shape: the bin edges and one value per bin, drawn as a rectangle each.

The bins also go into _continuous.x/_continuous.y as the step_x()/ step_y() staircase Mark.AREA would draw (swapped when the mark is horizontal, so call mark_histogram() first), so every rule that reads those columns – the x/y domains, render_layers()’s combined domain, a facet grid’s shared baseline – works unchanged; only the drawing reads the edges and values.

Args:

  • self (Self)
  • bins (HistogramBins): The binned sample, from histogram_bins() or built directly from edges and values.

Returns:

Self: Self, for further chaining.

Raises:

encode_hist2d

fn def encode_hist2d(var self, x: List[Float64], y: List[Float64], x_edges: List[Float64], y_edges: List[Float64]) -> Self

Count (x, y) points into the grid x_edges by y_edges bound and map the counts onto Mark.HIST2D’s shape: encode_pcolormesh()’s cells, with empty ones left undrawn.

The edges are yours, so the two axes can be binned differently or unevenly; hist2d() derives equal-width edges from the data for the common case. Binning is _hist2d_counts’s: a point on a shared boundary goes to the upper bin, the sample maximum to the last.

Args:

  • self (Self)
  • x (List[Float64]): The horizontal coordinates.
  • y (List[Float64]): The vertical coordinates, one per x.
  • x_edges (List[Float64]): Column boundaries, strictly increasing, at least 2.
  • y_edges (List[Float64]): Row boundaries, strictly increasing, at least 2.

Returns:

Self: Self, for further chaining.

Raises:

Error: x and y differ in length, or an edge list is shorter than 2.

encode_streamplot

fn def encode_streamplot(var self, x: List[Float64], y: List[Float64], u: List[List[Float64]], v: List[List[Float64]]) -> Self

Map a gridded vector field onto Mark.STREAMPLOT’s shape: len(x) column coordinates, len(y) row coordinates, and the two components at each node as u[j][i]/v[j][i].

The grid shape rather than encode_barbs()’s four flat columns, for the reason _StreamData’s docstring gives: a glyph reads the field only where it was sampled, an integrator reads it everywhere between. Checking is deferred to render time, like every other encoder here.

Args:

  • self (Self)
  • x (List[Float64]): Column coordinates, ascending and evenly spaced.
  • y (List[Float64]): Row coordinates, ascending and evenly spaced.
  • u (List[List[Float64]]): The x-component at each node.
  • v (List[List[Float64]]): The y-component at each node, positive up the page.

Returns:

Self: Self, for further chaining.

Raises:

encode_hexbin

fn def encode_hexbin(var self, x: List[Float64], y: List[Float64], gridsize: Int = Int(30)) -> Self

Map (x, y) points onto Mark.HEXBIN’s shape: the points themselves and the lattice width in cells. Binning happens at render time (_hexbin_bins), over the data’s own bounding box.

Args:

  • self (Self)
  • x (List[Float64]): The horizontal coordinates.
  • y (List[Float64]): The vertical coordinates, one per x.
  • gridsize (Int): Hexagons across the x range, at least 1.

Returns:

Self: Self, for further chaining.

Raises:

encode_tricontour

fn def encode_tricontour(var self, x: List[Float64], y: List[Float64], z: List[Float64], levels: List[Float64] = List()) -> Self

Map scattered (x, y, z) samples onto Mark.TRICONTOUR’s shape.

The points need not lie on any lattice and need no ordering: the Delaunay triangulation built at render time supplies the connectivity that a grid would otherwise provide. Length checking is deferred to render() time, like every other encode method here.

Args:

  • self (Self)
  • x (List[Float64]): Each sample’s x position.
  • y (List[Float64]): Each sample’s y position, one per x entry.
  • z (List[Float64]): Each sample’s value, one per x entry.
  • levels (List[Float64]): The values to trace. Left empty (the default), the count from mark_tricontour(levels=n) decides how many are placed inside the data’s range.

Returns:

Self: Self, for further chaining.

Raises:

encode_triplot

fn def encode_triplot(var self, x: List[Float64], y: List[Float64], z: List[Float64] = List(), triangulation: Triangulation = Triangulation(), facecolors: List[Float64] = List(), gouraud: Bool = False) -> Self

Map scattered (x, y) positions – and, for Mark.TRIPCOLOR, a value at each – onto the triangulation marks’ shape.

encode_tricontour()’s columns without the level list. z is optional because Mark.TRIPLOT draws connectivity and nothing else, so requiring a value column there would mean inventing one; Mark.TRIPCOLOR needs it and says so at render time, like every other length check in this package.

Args:

  • self (Self)
  • x (List[Float64]): Each sample’s x position.
  • y (List[Float64]): Each sample’s y position, one per x entry.
  • z (List[Float64]): The value at each sample, one per x entry. Left empty (the default) for Mark.TRIPLOT.
  • triangulation (Triangulation): A Triangulation to draw instead of computing one from x/y. Empty (the default) triangulates internally, as before.
  • facecolors (List[Float64]): One value per triangle. Empty (the default) colors each triangle by the mean of its vertices’ z.
  • gouraud (Bool): Interpolate each face’s color across it from its three vertices instead of filling it flat (#398). Mark.TRIPCOLOR only.

Returns:

Self: Self, for further chaining.

Raises:

Error: facecolors without a triangulation, or gouraud together with facecolors.

encode_marimekko

fn def encode_marimekko(var self, categories: List[String], subcategories: List[String], values: List[List[Float64]]) -> Self

Map Mark.MARIMEKKO’s three channels: categories (one column each), subcategories (one stacked segment each), and values, where values[i][j] is subcategories[i]’s value for categories[j] (rows are subcategories, columns are categories, matching ECharts.jl’s marimekko() and the opposite of encode_grouped_bar()’s values[series][category]). Length checking and non-negativity are deferred to render() time.

Args:

  • self (Self)
  • categories (List[String]): One column per entry.
  • subcategories (List[String]): One stacked segment per entry.
  • values (List[List[Float64]]): values[i][j] is subcategories[i]’s value for categories[j] (rows are subcategories, columns are categories).

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_marimekko[dtype: DType](var self, categories: List[String], subcategories: List[String], values: List[List[Scalar[dtype]]]) -> Self

encode_marimekko()’s values generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). categories/subcategories stay concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • categories (List[String]): One column per entry.
  • subcategories (List[String]): One stacked segment per entry.
  • values (List[List[Scalar[dtype]]]): values[i][j] is subcategories[i]’s value for categories[j] – any numeric List[List[Scalar[ dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

encode_hierarchy

fn def encode_hierarchy(var self, ids: List[String], parent_ids: List[String], values: List[Float64]) -> Self

Map a flattened hierarchy onto Mark.SUNBURST/TREE/TREEMAP’s shared shape: one row per node, ids[i] its name, parent_ids[i] its parent’s id ("" for the single root, as in d3.stratify()), values[i] its magnitude if it’s a leaf. An internal node’s displayed value is always its descendant leaves’ sum, computed at render() time (_build_hierarchy_index, hierarchy.mojo). Length checking, the single-root/duplicate-id/unresolved-parent validation, and the non-negative check are all deferred to render() time.

Args:

  • self (Self)
  • ids (List[String]): Every node’s unique id, flattened (not nested), one entry per node.
  • parent_ids (List[String]): Each node’s parent id (a value present in ids, or "" for the single root); paired with ids[i].
  • values (List[Float64]): Each leaf node’s magnitude; an internal node’s displayed value is always its descendant leaves’ sum instead, computed at render() time.

Returns:

Self: Self, for further chaining.

Raises:

encode_chord

fn def encode_chord(var self, from_categories: List[String], to_categories: List[String], values: List[Float64]) -> Self

Map an edge list onto Mark.CHORD’s shape (also used by ARC_DIAGRAM/GRAPH/SANKEY): one row per flow from from_categories[i] to to_categories[i] with magnitude values[i]. Every distinct name across both columns becomes a node (_edge_node_index, first-seen order with from_categories first, at render() time). values must be non-negative, checked at render() time along with the length match.

Args:

  • self (Self)
  • from_categories (List[String]): Each flow’s source node, one entry per row.
  • to_categories (List[String]): Each flow’s destination node, one entry per row (paired with from_categories[i]).
  • values (List[Float64]): Each flow’s magnitude; must be non-negative.

Returns:

Self: Self, for further chaining.

Raises:

encode_polar

fn def encode_polar(var self, angle: List[Float64], radius: List[Float64]) -> Self

Map an angle column (radians) and a radius column onto Mark.POLAR’s two channels: one point per row, connected in row order (not sorted by angle, so a spiral past 2*pi draws correctly). A single unnamed series with no legend; see encode_polar_series() for several. Length matching and radius being non-negative are checked at render() time.

Args:

  • self (Self)
  • angle (List[Float64]): Radians, used exactly as given and unwrapped.
  • radius (List[Float64]): Must be non-negative (checked at render() time).

Returns:

Self: Self, for further chaining.

Raises:

encode_polar_series

fn def encode_polar_series(var self, angle: List[Float64], series_names: List[String], series_values: List[List[Float64]]) -> Self

Map a shared angle column (radians) plus one or more named series onto Mark.POLAR’s two channels, the multi-series form of encode_polar(). Every series shares the angle domain and one radius scale (max(radius) across every series), unlike Mark.RADAR’s per-indicator max. Each series_values[i] must match angle’s length and every value must be non-negative, checked at render() time.

Args:

  • self (Self)
  • angle (List[Float64]): Radians, used exactly as given and unwrapped; shared by every series.
  • series_names (List[String]): One trace per name.
  • series_values (List[List[Float64]]): series_values[j] is series_names[j]’s radius per angle; same length as angle, non-negative.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_polar_series[dtype: DType](var self, angle: List[Float64], series_names: List[String], series_values: List[List[Scalar[dtype]]]) -> Self

encode_polar_series()’s series_values generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). angle/series_names stay concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • angle (List[Float64]): Radians, used exactly as given and unwrapped; shared by every series.
  • series_names (List[String]): One trace per name.
  • series_values (List[List[Scalar[dtype]]]): series_values[j] is series_names[j]’s radius per angle – any numeric List[List[Scalar[ dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

encode_radar

fn def encode_radar(var self, indicators: List[String], max_values: List[Float64], series_names: List[String], series_values: List[List[Float64]]) -> Self

Map Mark.RADAR’s four channels: one named axis per indicators entry with its own max_values[i], and one named series per series_names entry with one value per indicator in series_values. Raises immediately on any length mismatch (indicators/max_values, series_names/series_values, or a series whose value count doesn’t match indicators).

Args:

  • self (Self)
  • indicators (List[String]): One spoke per entry, in the given order.
  • max_values (List[Float64]): Each spoke’s own independent maximum, paired with indicators[i].
  • series_names (List[String]): One polygon per name.
  • series_values (List[List[Float64]]): series_values[j] is series_names[j]’s value per indicator.

Returns:

Self: Self, for further chaining.

Raises:

If indicators/max_values lengths don’t match, series_names/series_values lengths don’t match, or any series’ value count doesn’t match indicators’s count.

fn def encode_radar[dtype: DType](var self, indicators: List[String], max_values: List[Float64], series_names: List[String], series_values: List[List[Scalar[dtype]]]) -> Self

encode_radar()’s series_values generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). The other parameters stay concrete; the overload below covers max_values. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • indicators (List[String]): One named axis per entry, each with its own max_values[i].
  • max_values (List[Float64]): Each indicator’s own maximum, same length as indicators.
  • series_names (List[String]): One polygon per name.
  • series_values (List[List[Scalar[dtype]]]): series_values[j] is series_names[j]’s value per indicator – any numeric List[List[Scalar[ dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

If indicators/max_values lengths don’t match, series_names/series_values lengths don’t match, or any series’ value count doesn’t match indicators’s count.

fn def encode_radar[dtype: DType](var self, indicators: List[String], max_values: List[Scalar[dtype]], series_names: List[String], series_values: List[List[Float64]]) -> Self

encode_radar()’s max_values generalized over numeric element type via _materialize_scalar_list (array_like.mojo). The other parameters stay concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • indicators (List[String]): One named axis per entry, each with its own max_values[i].
  • max_values (List[Scalar[dtype]]): Each indicator’s own maximum, same length as indicators – any numeric List[Scalar[dtype]].
  • series_names (List[String]): One polygon per name.
  • series_values (List[List[Float64]]): series_values[j] is series_names[j]’s value per indicator.

Returns:

Self: Self, for further chaining.

Raises:

If indicators/max_values lengths don’t match, series_names/series_values lengths don’t match, or any series’ value count doesn’t match indicators’s count.

encode_gauge

fn def encode_gauge(var self, value: Float64, min_value: Float64 = 0, max_value: Float64 = 100, breakpoints: List[Float64] = List(), band_colors: List[Color] = List()) -> Self

Map a single reading onto Mark.GAUGE’s dial: value against the configured range (default 0 to 100), clamped at render() time rather than rejected. min_value < max_value is checked at render() time.

breakpoints/band_colors together replace the dial’s colored bands: breakpoints an ascending list of fractions of the full span (e.g. [0.5, 1.0]), band_colors one color per band. Left empty, both reproduce ECharts’ 20%/80%/100% green/blue/red default (_gauge_breakpoints()/_gauge_band_colors(), gauge.mojo). Length matching and ascending order are checked at render() time.

Args:

  • self (Self)
  • value (Float64): The reading to show, clamped (not rejected) to the configured minimum and maximum.
  • min_value (Float64): The dial’s low end; defaults to 0.0.
  • max_value (Float64): The dial’s high end; defaults to 100.0.
  • breakpoints (List[Float64]): Ascending fractions of the [min_value, max_value] span; left empty (the default), reproduces ECharts’ fixed 20%/80%/100% bands.
  • band_colors (List[Color]): One color per breakpoints band, same length; left empty (the default), reproduces ECharts' fixed green/blue/red bands.

Returns:

Self: Self, for further chaining.

Raises:

encode_parallel

fn def encode_parallel(var self, dims: List[String], row_names: List[String], data: List[List[Float64]]) -> Self

Map Mark.PARALLEL’s three channels: dims (one vertical axis per name, each scaled to its column’s minimum and maximum), row_names (one polyline per name), and data (one list per row, one value per dimension). Raises immediately on a row_names/data length mismatch or a row whose value count doesn’t match dims.

Args:

  • self (Self)
  • dims (List[String]): One vertical axis per entry, each independently scaled to its own column’s minimum and maximum across data.
  • row_names (List[String]): One polyline per entry.
  • data (List[List[Float64]]): data[row] is row_names[row]’s polyline, one value per dims entry.

Returns:

Self: Self, for further chaining.

Raises:

If row_names/data lengths don’t match, or any row’s value count doesn’t match dims’s count.

fn def encode_parallel[dtype: DType](var self, dims: List[String], row_names: List[String], data: List[List[Scalar[dtype]]]) -> Self

encode_parallel()’s data generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). dims/ row_names stay concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • dims (List[String]): One vertical axis per entry, each independently scaled to its own column’s minimum and maximum across data.
  • row_names (List[String]): One polyline per entry.
  • data (List[List[Scalar[dtype]]]): data[row] is row_names[row]’s polyline, one value per dims entry – any numeric List[List[ Scalar[dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

If row_names/data lengths don’t match, or any row’s value count doesn’t match dims’s count.

encode_kde

fn def encode_kde(var self, values: List[Float64]) -> Self

Map one flat column of raw observations onto Mark.KDE/ Mark.RUG.

A single ungrouped column, unlike encode_distribution()’s list-per-category: these marks draw one distribution on a continuous axis, and several are compared by layering rather than by sharing a categorical axis.

Args:

  • self (Self)
  • values (List[Float64]): The observations.

Returns:

Self: Self, for further chaining.

Raises:

Error: values is empty.

encode_eventplot

fn def encode_eventplot(var self, labels: List[String], positions: List[List[Float64]]) -> Self

Map one row label per series and, per row, that row’s event positions onto Mark.EVENTPLOT.

The same outer-list-per-category shape encode_distribution() takes, into the same storage – but with one rule deliberately relaxed, which is why it is its own method rather than a call to that one. An individual row may be empty. encode_distribution() refuses an empty category, and rightly: there is no distribution to estimate from no values. “This sensor recorded nothing over the window” is a result, though, and a row that vanished for having none would silently renumber every row below it.

What is still refused is every row being empty: the x-axis is built from the pooled positions, so with no event anywhere there is no timeline to draw and nothing to draw on it. That check is here rather than at render time so the message names this method.

labels comes first, matching encode_distribution(), encode_boxplot() and every other category-plus-values encoder in this package – sketched it the other way round, but a single encoder disagreeing about argument order is a worse trap than the sketch is a promise.

Args:

  • self (Self)
  • labels (List[String]): One row label per series, in the order they should be drawn top to bottom.
  • positions (List[List[Float64]]): Each row’s event positions (positions[i]), in the shared x-axis’ units. Individual rows may be empty.

Returns:

Self: Self, for further chaining.

Raises:

Error: labels is empty, labels/positions lengths don’t match, or every row is empty.

fn def encode_eventplot[dtype: DType](var self, labels: List[String], positions: List[List[Scalar[dtype]]]) -> Self

encode_eventplot()’s positions generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo), exactly as encode_distribution() is. labels stays concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • labels (List[String]): One row label per series, top to bottom.
  • positions (List[List[Scalar[dtype]]]): Each row’s event positions – any numeric List[List[Scalar[dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

Error: labels is empty, lengths don’t match, or every row is empty.

encode_distribution

fn def encode_distribution(var self, categories: List[String], values: List[List[Float64]]) -> Self

Map a category column and, per category, a list of raw values onto the shape Mark.BEESWARM/VIOLIN/RIDGELINE share: the same outer-list-per-category shape as encode_boxplot(), but kept as raw values rather than reduced to a five-number summary, since a swarm draws every point and a density estimate needs the raw values. Raises immediately on a categories/values length mismatch or an empty value list.

Args:

  • self (Self)
  • categories (List[String]): One row per entry, in the given order.
  • values (List[List[Float64]]): Each category’s raw values (values[i]) – must be non-empty.

Returns:

Self: Self, for further chaining.

Raises:

If categories/values lengths don’t match, categories is empty, or any category’s value list is empty.

fn def encode_distribution[dtype: DType](var self, categories: List[String], values: List[List[Scalar[dtype]]]) -> Self

encode_distribution()’s values generalized over numeric element type via _materialize_nested_scalar_list (array_like.mojo). categories stays concrete. Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • categories (List[String]): One distribution per entry, in the given order.
  • values (List[List[Scalar[dtype]]]): Each category’s raw values – any numeric List[List[Scalar[dtype]]].

Returns:

Self: Self, for further chaining.

Raises:

If categories/values lengths don’t match, or any category’s value list is empty.

encode_single_axis

fn def encode_single_axis(var self, x: List[Float64], color: List[Float64] = List(), color_categories: List[String] = List(), size: List[Float64] = List()) -> Self

Map one continuous column plus the optional color/ color_categories/size channels onto Mark.SINGLE_AXIS’s one-axis shape: encode() without a y. _continuous.y is filled with one placeholder 0.0 per row (never read as a value; see _render_single_axis) so _validate_continuous_encoding’s length check and Mark.POINT’s _draw_point_layer work unchanged.

Args:

  • self (Self)
  • x (List[Float64]): The continuous column, one entry per point.
  • color (List[Float64]): Optional continuous color channel; mutually exclusive with color_categories. Left empty (the default), every point uses Theme.mark_color.
  • color_categories (List[String]): Optional discrete color channel; mutually exclusive with color. Left empty (the default), every point uses Theme.mark_color.
  • size (List[Float64]): Optional point-size channel. Left empty (the default), every point uses Theme.point_radius.

Returns:

Self: Self, for further chaining.

Raises:

encode_imshow

fn def encode_imshow(var self, z: List[List[Float64]]) -> Self

Forwarded to the mark; refused at compile time on a mark without it.

Args:

  • self (Self)
  • z (List[List[Float64]])

Returns:

Self

Raises:

encode_histogram

fn def encode_histogram(var self, data: List[Float64], bins: Int = Int(10), weights: List[Float64] = List(), stat: HistStat = HistStat.COUNT, cumulative: Bool = False) -> Self where Bool(identical(M, Histogram))

Bin raw observations into bins equal-width intervals for Mark.HISTOGRAM: exactly what histogram() draws for the same data, bins, weights, stat and cumulative – bin_edges(), then histogram_bins(), then encode_histogram_bins(), with the bin range pinned on the axis that carries the bins (#698). encode_histogram_bins() is the path for bins already computed; encode_binned_categories() is the categorical bar chart of labeled intervals.

Args:

  • self (Self)
  • data (List[Float64]): Raw observations to bin.
  • bins (Int): Number of equal-width intervals.
  • weights (List[Float64]): One nonnegative weight per observation, or empty.
  • stat (HistStat): What a bin’s height is; see HistStat.
  • cumulative (Bool): Draw running totals instead of per-bin values.

Returns:

Self: Self, for further chaining.

Raises:

Error: The mark is not Mark.HISTOGRAM, data is empty, bins is not positive, or a value is not finite.

fn def encode_histogram(var self, data: List[Float64], rule: BinRule, weights: List[Float64] = List(), stat: HistStat = HistStat.COUNT, cumulative: Bool = False) -> Self where Bool(identical(M, Histogram))

encode_histogram with the bin count chosen by rule rather than named – BinRule.AUTO for numpy’s bins="auto", the overload histogram() and bin_edges() also have (#456).

Args:

  • self (Self)
  • data (List[Float64]): Raw observations to bin.
  • rule (BinRule): Which BinRule picks the bin count.
  • weights (List[Float64]): One nonnegative weight per observation, or empty.
  • stat (HistStat): What a bin’s height is; see HistStat.
  • cumulative (Bool): Draw running totals instead of per-bin values.

Returns:

Self: Self, for further chaining.

Raises:

Error: The mark is not Mark.HISTOGRAM, data is empty, or a value is not finite.

encode_quiver

fn def encode_quiver(var self, x: List[Float64], y: List[Float64], u: List[Float64], v: List[Float64]) -> Self

Map Mark.QUIVER’s four channels: continuous x/y positions plus the u/v components of the vector at each, v positive up the page. The same shape as encode_barbs(), stored in the same place, since the two marks draw one field two ways.

Args:

  • self (Self)
  • x (List[Float64]): The continuous x position of each arrow’s tail.
  • y (List[Float64]): The continuous y position of each arrow’s tail.
  • u (List[Float64]): Each vector’s x-component, in the same unit as v.
  • v (List[Float64]): Each vector’s y-component, positive pointing up the page.

Returns:

Self: Self, for further chaining.

Raises:

fn def encode_quiver[dtype: DType](var self, x: List[Scalar[dtype]], y: List[Scalar[dtype]], u: List[Scalar[dtype]], v: List[Scalar[dtype]]) -> Self

encode_quiver() generalized over numeric element type via _materialize_scalar_list (array_like.mojo). Delegates to the concrete overload.

Parameters:

  • dtype (DType)

Args:

  • self (Self)
  • x (List[Scalar[dtype]]): The continuous x position of each arrow’s tail.
  • y (List[Scalar[dtype]]): The continuous y position of each arrow’s tail.
  • u (List[Scalar[dtype]]): Each vector’s x-component – any numeric List[Scalar[dtype]].
  • v (List[Scalar[dtype]]): Each vector’s y-component – any numeric List[Scalar[dtype]].

Returns:

Self: Self, for further chaining.

Raises:

encode_ecdf

fn def encode_ecdf(var self, values: List[Float64]) -> Self

Map one flat column of raw observations onto Mark.ECDF.

The same single ungrouped column encode_kde() takes, into the same slot, so the two are interchangeable at the storage level. It exists under its own name because the call site is where a reader learns what the chart is: .mark_ecdf().encode_kde(...) reads as a mistake even though it works.

Args:

  • self (Self)
  • values (List[Float64]): The observations, in any order.

Returns:

Self: Self, for further chaining.

Raises:

Error: values is empty.

encode_frame

fn def encode_frame(var self, df: DataFrame, x: String, y: String, color: String = "", size: String = "", labels: String = "") -> Self

Encode from a DataFrame by column name: x and y, plus the optional color, size and labels columns. Continuous marks take a numeric x; categorical marks a string one. Refused at compile time on a mark that reads no frame.

Args:

  • self (Self)
  • df (DataFrame)
  • x (String)
  • y (String)
  • color (String)
  • size (String)
  • labels (String)

Returns:

Self

Raises: