Skip to content

ferrum.chart

The core chart value class.

Chart — the user-facing top-level value class.

Immutability rule: every fluent method returns a new Chart. The internal spec is deep-copied on each call so chains compose without aliasing surprises.

Chart

Bases: _RenderMixin

Top-level chart value class.

Every method returns a new Chart — the object is effectively immutable and safe to reuse across branches of a pipeline. The fluent API follows the pattern::

fm.Chart(df).mark_point().encode(x="sepal_length", y="sepal_width")

Parameters:

Name Type Description Default
data DataFrame - like or None

Input data. Accepts Polars DataFrame, pandas DataFrame, PyArrow Table / RecordBatch, dict-of-arrays, list-of-records, or a 2-D NumPy array. Passed through ferrum._coerce.to_arrow_table at render time. None is allowed when composing layered charts that share a parent's data.

None
width int or 'container'

Chart width in pixels, or "container" to fill the parent element. Default is 600.

None
height int or 'container'

Chart height in pixels. Default is 400.

None
title str

Title rendered above the plot area.

None
description str

Accessible description attached to the SVG root (<title> element).

None

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> chart = fm.Chart(df).mark_point().encode(x="x", y="y")
>>> svg = chart.show_svg()

layer_names property

layer_names: list[str]

Named sub-layers after composite-mark desugar resolution.

Returns [] for single-mark charts with no layers. Accessing this property forces resolution of any pending _PendingMark.

mark_point

mark_point(**kwargs) -> 'Chart'

Render data as points (scatter plot).

Parameters:

Name Type Description Default
size float

Point area in square pixels. Default is 36.

required
fill str

Fill colour override (CSS colour string or hex). Normally driven by the color encoding.

required
stroke str

Stroke colour for the point outline.

required
opacity float

Overall opacity in [0, 1].

required
filled bool

Whether points are filled. Default is True.

required
shape str

Point shape: "circle", "square", "cross", "diamond", "triangle-up", "triangle-down".

required
stroke_width float

Stroke width in pixels.

required
position Position

Position adjustment — fm.Jitter(), fm.Dodge(), etc.

required

Returns:

Type Description
Chart

New Chart with mark set to "point".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> fm.Chart(df).mark_point(size=60, opacity=0.7).encode(x="x", y="y")
Chart(mark='point', encoding=['x', 'y'])

mark_line

mark_line(**kwargs) -> 'Chart'

Render data as a connected line.

Parameters:

Name Type Description Default
stroke str

Stroke colour override.

required
stroke_width float

Line width in pixels. Default is 2.

required
opacity float

Overall opacity in [0, 1].

required
interpolate str

Line interpolation: "linear", "monotone", "step", "step-before", "step-after", "basis", "cardinal".

required
stroke_cap str

Line cap: "butt", "round", "square".

required
stroke_join str

Line join: "miter", "round", "bevel".

required
position Position

Position adjustment.

required

Returns:

Type Description
Chart

New Chart with mark set to "line".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> fm.Chart(df).mark_line(stroke_width=3, interpolate="monotone").encode(x="x", y="y")
Chart(mark='line', encoding=['x', 'y'])

mark_bar

mark_bar(**kwargs) -> 'Chart'

Render data as bars.

Parameters:

Name Type Description Default
fill str

Bar fill colour override.

required
stroke str

Bar stroke colour.

required
stroke_width float

Bar stroke width in pixels.

required
opacity float

Overall opacity in [0, 1].

required
corner_radius float

Rounded corner radius in pixels.

required
orient str

"vertical" (default) or "horizontal".

required
position Position

Position adjustment — fm.Stack(), fm.Dodge(), etc.

required

Returns:

Type Description
Chart

New Chart with mark set to "bar".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"cat": ["a", "b", "c"], "val": [10, 20, 15]})
>>> fm.Chart(df).mark_bar(corner_radius=4).encode(x="cat", y="val")
Chart(mark='bar', encoding=['x', 'y'])

mark_area

mark_area(**kwargs) -> 'Chart'

Render data as a filled area between the line and a baseline.

Parameters:

Name Type Description Default
fill str

Fill colour override.

required
stroke str

Border stroke colour.

required
stroke_width float

Border stroke width in pixels.

required
opacity float

Overall opacity in [0, 1].

required
interpolate str

Area boundary interpolation: "linear", "monotone", "step", "basis", "cardinal".

required
line bool

Whether to draw the top boundary as a line. Default is False.

required
position Position

Position adjustment — e.g. fm.Stack().

required

Returns:

Type Description
Chart

New Chart with mark set to "area".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> fm.Chart(df).mark_area(opacity=0.5, line=True).encode(x="x", y="y")
Chart(mark='area', encoding=['x', 'y'])

mark_rule

mark_rule(**kwargs) -> 'Chart'

Render a horizontal or vertical reference rule spanning the plot area.

A rule spans the full width (when y is encoded) or full height (when x is encoded). Encoding both x/x2 or y/y2 draws finite line segments instead.

Parameters:

Name Type Description Default
stroke str

Rule colour override.

required
stroke_width float

Rule width in pixels. Default is 1.

required
stroke_dash str or list

Dash pattern, e.g. "4,2".

required
opacity float

Overall opacity in [0, 1].

required
position Position

Position adjustment.

required

Returns:

Type Description
Chart

New Chart with mark set to "rule".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"y": [0.0]})
>>> fm.Chart(df).mark_rule(stroke="red", stroke_width=2).encode(y="y")
Chart(mark='rule', encoding=['y'])

mark_text

mark_text(**kwargs) -> 'Chart'

Render data values as text labels.

Requires a text encoding channel pointing at the column to display.

Parameters:

Name Type Description Default
fill str

Text colour override.

required
font_size float

Font size in points. Default is 11.

required
font_weight str or int

CSS font-weight, e.g. "bold", 400, 700.

required
align str

Horizontal alignment: "left", "center", "right".

required
baseline str

Vertical alignment: "top", "middle", "bottom", "alphabetic".

required
dx float

Horizontal pixel offset from the anchor point.

required
dy float

Vertical pixel offset from the anchor point.

required
angle float

Rotation in degrees.

required
limit float

Maximum rendered width in pixels; clips overflow.

required
position Position

Position adjustment.

required

Returns:

Type Description
Chart

New Chart with mark set to "text".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4], "label": ["A", "B"]})
>>> fm.Chart(df).mark_text(dy=-8).encode(x="x", y="y", text="label")
Chart(mark='text', encoding=['x', 'y', 'text'])

mark_tick

mark_tick(**kwargs) -> 'Chart'

Render data as short tick marks (rug / strip plot).

Parameters:

Name Type Description Default
stroke str

Tick colour override.

required
stroke_width float

Tick stroke width in pixels.

required
opacity float

Overall opacity in [0, 1].

required
band_size float

Tick length in pixels.

required
orient str

"vertical" (default ticks perpendicular to x) or "horizontal".

required
position Position

Position adjustment.

required

Returns:

Type Description
Chart

New Chart with mark set to "tick".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1.1, 2.3, 3.5, 2.2, 1.8]})
>>> fm.Chart(df).mark_tick().encode(x="x")
Chart(mark='tick', encoding=['x'])

mark_rect

mark_rect(**kwargs) -> 'Chart'

Render data as rectangles (heatmap cells, Gantt bars).

Requires x/x2 or y/y2 encoding pairs (or ordinal x/y for a heatmap cell grid).

Parameters:

Name Type Description Default
fill str

Rectangle fill colour override.

required
stroke str

Rectangle border stroke colour.

required
stroke_width float

Border stroke width in pixels.

required
opacity float

Overall opacity in [0, 1].

required
corner_radius float

Rounded corner radius in pixels.

required
position Position

Position adjustment.

required

Returns:

Type Description
Chart

New Chart with mark set to "rect".

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"row": ["A", "B"], "col": ["X", "Y"], "val": [1.0, 0.5]})
>>> fm.Chart(df).mark_rect().encode(x="col", y="row", color="val")
Chart(mark='rect', encoding=['x', 'y', 'color'])

mark_segment

mark_segment(*, position=None, **kwargs) -> 'Chart'

Render data as line segments from (x, y) to (x2, y2).

Distinct from mark_rule (axis-aligned only); segments may take any direction. Requires x, y, x2, y2 on the encoding.

Parameters:

Name Type Description Default
stroke str

Segment stroke colour override.

required
stroke_width float

Segment stroke width in pixels.

required
stroke_dash list of float

Dash pattern (alternating on/off pixel lengths).

required
opacity float

Stroke opacity in [0, 1].

required
position Position

Position adjustment.

None
**kwargs

Additional mark-style overrides forwarded to the segment layer.

{}

Returns:

Type Description
Chart

New Chart configured for segment rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [0, 1], "y": [0, 1], "x2": [1, 2], "y2": [1, 0]})
>>> fm.Chart(df).mark_segment().encode(x="x", y="y", x2="x2", y2="y2")
Chart(mark='segment', encoding=['x', 'y', 'x2', 'y2'])

mark_density

mark_density(*, position=None, **kwargs) -> 'Chart'

Render a kernel-density estimate (KDE) curve or filled contour.

When only x is encoded, draws a 1-D KDE area curve. When both x and y are encoded, renders a bivariate filled-contour density (routes through desugar_contour(fill=True)). Can be called before or after .encode().

Parameters:

Name Type Description Default
bandwidth float or 'scott' or 'silverman'

KDE bandwidth. "scott" and "silverman" use the corresponding rule-of-thumb estimates. Default is "scott".

required
kernel str

Kernel type: "gaussian", "tophat", "epanechnikov", "exponential", "linear", "cosine". Default is "gaussian".

required
extent list of float or None

[min, max] evaluation range. Defaults to data extent.

required
cumulative bool

Produce a CDF instead of a PDF. Default is False.

required
n int

Number of evaluation points. Default is 200.

required
multiple str

How to handle multiple densities when a color encoding is present: "layer" (default), "stack", "fill".

required
position Position

Position adjustment.

None

Returns:

Type Description
Chart

New Chart configured for density rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"val": [1.0, 2.1, 1.8, 3.0, 2.5]})
>>> fm.Chart(df).mark_density().encode(x="val")
Chart(mark='area', encoding=['x'])

mark_histogram

mark_histogram(*, position=None, **kwargs) -> 'Chart'

Render data as a histogram.

Bins the x-encoded column and encodes bin extents as x/x2 with counts (or densities) on y. Can be called before or after .encode(x=...).

Parameters:

Name Type Description Default
bin_count int

Target number of bins. Ignored when bin_width is set. Default is chosen automatically from Sturges' rule.

required
bin_width float

Exact bin width in data units. Overrides bin_count.

required
density bool

Normalise counts to a probability density. Default is False.

required
right bool

Whether bins are closed on the right. Default is True.

required
cumulative bool

Render a cumulative histogram. Default is False.

required
multiple str

How to handle grouped histograms when a color encoding is present: "layer" (default), "stack", "dodge".

required
position Position

Position adjustment.

None

Returns:

Type Description
Chart

New Chart configured for histogram rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"val": [1.0, 1.2, 2.3, 3.1, 2.8, 1.5]})
>>> fm.Chart(df).mark_histogram(bin_count=5).encode(x="val")
Chart(mark='bar', encoding=['x', 'x2', 'y'])

mark_smooth

mark_smooth(*, position=None, **kwargs) -> 'Chart'

Render a smoothed regression line with optional confidence interval band.

Fits a smooth curve through (x, y) data using the method specified by method. When ci is set, emits a layered ribbon (CI band) + line chart. Can be called before or after .encode(x=..., y=...).

Parameters:

Name Type Description Default
method str

Smoothing method: "loess" (default), "linear", "quadratic", "cubic", "log", "sqrt".

required
degree int

Polynomial degree for "linear"/"quadratic"/"cubic".

required
bandwidth float

LOESS bandwidth fraction in (0, 1]. Default is 0.75.

required
n int

Number of evaluation points along the x range. Default is 200.

required
ci float or None

Confidence level for the interval band, e.g. 0.95. When set, produces a layered ribbon + line chart. Default is None.

required
groupby str

Group-key column (Utf8). When set, the smooth is computed independently per group and the group column is preserved in the output so downstream color= encoding maps to it.

required
position Position

Position adjustment.

None

Returns:

Type Description
Chart

New Chart configured for smooth rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1.0, 2.0, 3.0, 4.0], "y": [1.1, 1.9, 3.1, 4.0]})
>>> fm.Chart(df).mark_smooth(method="linear", ci=0.95).encode(x="x", y="y")
Chart(mark='line', encoding=['x', 'y'])

mark_boxplot

mark_boxplot(*, extent=1.5, size=None, width=None, outliers=True, color_field=None, horizontal=False, position=None, **mark_kwargs) -> 'Chart'

Render a Tukey boxplot via composite mark desugaring.

Desugars to a multi-layer chart: box (IQR rect), upper and lower whisker rules, median rule, and (optionally) outlier points. Requires a categorical x encoding and a continuous y (or the reverse when horizontal=True).

Parameters:

Name Type Description Default
extent float

Whisker reach as a multiple of IQR. Default is 1.5.

1.5
size float or None

Box band-width as a fraction of the category band (default 0.6). Alias: width.

None
width float or None

Alias for size. Controls box band-width as a fraction of the category band. When both size and width are provided, size takes precedence.

None
outliers bool

Whether to draw outlier points beyond the whiskers. Default is True.

True
color_field str or None

Column name to drive per-group fill colour on the box layer.

None
horizontal bool

Swap x and y axes so boxes run horizontally. Default is False.

False
position Position

Position adjustment — e.g. fm.Dodge() for side-by-side boxes.

None
**mark_kwargs

Additional mark-style overrides forwarded to each constituent layer.

{}

Returns:

Type Description
Chart

New layered Chart representing the boxplot.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"species": ["a"]*5 + ["b"]*5, "val": [1,2,3,2,1,4,5,4,5,6]})
>>> fm.Chart(df).mark_boxplot().encode(x="species", y="val")
Chart(mark='point', encoding=[])

mark_boxen

mark_boxen(*, k_depth: str = 'tukey', k_proportion: float = 0.007, outlier_threshold: float = 1.5, palette=None, horizontal: bool = False, color_field=None, position=None, **mark_kwargs) -> 'Chart'

Render a letter-value (boxen) plot via composite mark desugaring.

Produces nested rectangular bands for each letter-value depth, a median rule, and an outlier-point layer via the LetterValue transform. Requires a categorical x encoding and a continuous y (or the reverse when horizontal=True).

Parameters:

Name Type Description Default
k_depth ('proportion', 'trustworthy', 'full')

Rule for choosing the number of letter-value levels.

"proportion"
k_proportion float

Proportion parameter used when k_depth="proportion". Default is 0.007.

0.007
outlier_threshold float

IQR multiple beyond which points are considered outliers. Default is 1.5.

1.5
palette list of str or None

Colour palette applied to successive depth bands. None uses the active theme's categorical palette.

None
horizontal bool

Swap axes so bands run horizontally. Default is False.

False
color_field str or None

Column name to drive per-group colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Additional mark-style overrides forwarded to constituent layers.

{}

Returns:

Type Description
Chart

New layered Chart representing the boxen plot.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"group": ["a"]*20 + ["b"]*20,
...                    "val": list(range(20)) + list(range(10, 30))})
>>> fm.Chart(df).mark_boxen().encode(x="group", y="val")
Chart(mark='point', encoding=[])

mark_errorbar

mark_errorbar(*, extent='ci', ticks=True, position=None, **mark_kwargs) -> 'Chart'

Render error bars via the ErrorExtent transform.

Computes extent values (CI, SD, SEM, or IQR) per group defined by the x encoding, then draws a vertical rule spanning the extent with optional tick caps.

Parameters:

Name Type Description Default
extent ('ci', 'stderr', 'stdev', 'iqr')

Extent measure: confidence interval ("ci"), standard error ("stderr"), standard deviation ("stdev"), or interquartile range ("iqr").

"ci"
ticks bool

Whether to draw horizontal tick caps at the extent endpoints. Default is True.

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to constituent rule/tick layers.

{}

Returns:

Type Description
Chart

New layered Chart representing the error bars.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"group": ["a"]*10 + ["b"]*10,
...                    "val": list(range(10)) + list(range(5, 15))})
>>> fm.Chart(df).mark_errorbar(extent="stdev").encode(x="group", y="val")
Chart(mark='point', encoding=[])

mark_errorband

mark_errorband(*, extent='ci', borders=False, position=None, **mark_kwargs) -> 'Chart'

Render an error band (ribbon) via the ErrorExtent transform.

Similar to mark_errorbar but renders the extent as a filled ribbon rather than whisker rules. Optionally draws border lines at the upper and lower extent edges.

Parameters:

Name Type Description Default
extent ('ci', 'stderr', 'stdev', 'iqr')

Extent measure: confidence interval ("ci"), standard error ("stderr"), standard deviation ("stdev"), or interquartile range ("iqr").

"ci"
borders bool

Whether to draw line borders at the band edges. Default is False.

False
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides (e.g. opacity) forwarded to the ribbon layer.

{}

Returns:

Type Description
Chart

New layered Chart representing the error band.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": list(range(10)), "y": [float(i) for i in range(10)]})
>>> fm.Chart(df).mark_errorband(extent="ci", borders=True).encode(x="x", y="y")
Chart(mark='point', encoding=[])

mark_ribbon

mark_ribbon(*, opacity=0.3, interpolate='linear', position=None, **mark_kwargs) -> 'Chart'

Render a ribbon (filled area between y and y2 along x).

Requires both y and y2 encoding channels. Typically used to visualise confidence intervals alongside a mark_line in the same layered chart.

Parameters:

Name Type Description Default
opacity float

Fill opacity of the ribbon. Default is 0.3.

0.3
interpolate str

Boundary interpolation: "linear", "monotone", "step", "basis", "cardinal". Default is "linear".

'linear'
position Position

Position adjustment.

None
**mark_kwargs

Additional mark-style overrides (e.g. fill, stroke).

{}

Returns:

Type Description
Chart

New Chart configured for ribbon rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y_lo": [0.5, 1.5, 2.5], "y_hi": [1.5, 2.5, 3.5]})
>>> fm.Chart(df).mark_ribbon().encode(x="x", y="y_lo", y2="y_hi")
Chart(mark='ribbon', encoding=['x', 'y', 'y2'])

mark_contour

mark_contour(*, bandwidth='scott', thresholds=6, smooth=True, fill=False, cmap=None, position=None, **mark_kwargs) -> 'Chart'

Render a bivariate contour plot via Kde2D + Contour transforms.

Estimates a 2-D kernel density and draws iso-contour lines (or filled contour regions when fill=True). Requires both x and y encodings.

Parameters:

Name Type Description Default
bandwidth float or 'scott' or 'silverman'

Bandwidth for the 2-D KDE. Default is "scott".

'scott'
thresholds int or list of float

Number of evenly-spaced contour levels, or an explicit list of density thresholds. Default is 6.

6
smooth bool

Whether to smooth contour paths via Gaussian filtering before contouring. Default is True.

True
fill bool

Render filled contour regions instead of contour lines. Default is False.

False
cmap str or None

Colour map name applied to contour levels. None (default) defers to the theme's sequential scheme.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the polygon/path layers.

{}

Returns:

Type Description
Chart

New layered Chart configured for contour rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1.0, 2.0, 3.0, 2.0, 1.5], "y": [4.0, 5.0, 4.5, 3.0, 4.0]})
>>> fm.Chart(df).mark_contour(thresholds=4, fill=True).encode(x="x", y="y")
Chart(mark='polygon', encoding=['x', 'y'])

mark_violin

mark_violin(*, bandwidth='scott', inner='box', position=None, **mark_kwargs) -> 'Chart'

Render violin plots via the Violin transform.

Estimates a mirrored KDE per group and overlays an optional inner summary (box, quartile lines, or individual points). Requires a categorical x and continuous y encoding (or swapped when horizontal is set).

Parameters:

Name Type Description Default
bandwidth float or 'scott' or 'silverman'

KDE bandwidth. Default is "scott".

'scott'
inner ('box', 'quartile', 'point', 'none')

Inner mark drawn on top of each violin: "box" — IQR box + median rule, "quartile" — three horizontal quartile rules, "point" — individual data points (strip), "none" — no inner mark.

"box"
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the violin polygon layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for violin rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"group": ["a"]*10 + ["b"]*10,
...                    "val": list(range(10)) + list(range(5, 15))})
>>> fm.Chart(df).mark_violin(inner="quartile").encode(x="group", y="val")
Chart(mark='polygon', encoding=['x', 'y'])

mark_qq

mark_qq(*, distribution='normal', dequantize=False, line=True, position=None, **mark_kwargs) -> 'Chart'

Render a quantile-quantile plot.

Computes theoretical vs. sample quantiles via the QQ transform. Reads the sample column from the x encoding; y is ignored.

Parameters:

Name Type Description Default
distribution ('normal', 'uniform', 'exponential', 'lognormal')

Theoretical distribution to compare the sample against.

"normal"
dequantize bool

Whether to apply rank-based dequantization before comparison. Default is False.

False
line bool

Whether to overlay a 45-degree reference line. Default is True.

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the scatter layer.

{}

Returns:

Type Description
Chart

New Chart configured for QQ rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"val": [1.2, 0.8, 1.5, -0.5, 0.3, 2.1, -1.0, 0.6]})
>>> fm.Chart(df).mark_qq(distribution="normal").encode(x="val")
Chart(mark='point', encoding=['x'])

mark_raster

mark_raster(*, aggregate='count', field=None, cmap=None, resolution='screen', blend='alpha', min_count=None, log_scale=False, position=None, **mark_kwargs) -> 'Chart'

Render a 2-D raster (pixel heatmap) via the Raster transform.

Bins data into a pixel grid and colours each pixel by an aggregate statistic. Most useful for very large datasets where a scatter plot would overplot. Requires x and y encodings.

Parameters:

Name Type Description Default
aggregate str

Aggregate function applied to each pixel bin: "count" (default), "sum", "mean", "min", "max". When aggregate is not "count", field must be provided.

'count'
field str or None

Column name to aggregate. Required unless aggregate="count".

None
cmap str or None

Colour map name. None (default) defers to the theme's sequential scheme.

None
resolution 'screen' or int

Pixel grid resolution. "screen" (default) matches the rendered chart dimensions; pass an integer to set an explicit grid width.

'screen'
blend str

Alpha-compositing blend mode. Default is "alpha".

'alpha'
min_count int or None

Minimum count threshold; pixels below this are rendered transparent. None (default) shows all pixels.

None
log_scale bool

Apply a log transform to pixel values before colour mapping. Default is False.

False
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the image layer.

{}

Returns:

Type Description
Chart

New Chart configured for raster rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1.0, 2.0, 3.0, 2.5], "y": [4.0, 5.0, 4.5, 4.0]})
>>> fm.Chart(df).mark_raster(cmap="plasma").encode(x="x", y="y")
Chart(mark='image', encoding=['x', 'y'])

mark_hex

mark_hex(*, bin_size=None, aggregate='count', field=None, cmap=None, stroke=None, stroke_width=0, position=None, **mark_kwargs) -> 'Chart'

Render a hexagonal bin plot via the Hex transform.

Bins data into a regular hexagonal grid and colours each cell by an aggregate statistic. Requires x and y encodings.

Parameters:

Name Type Description Default
bin_size float or None

Hexagon radius in data units. None (default) chooses a size automatically from the data range and chart dimensions.

None
aggregate str

Aggregate function: "count" (default), "sum", "mean", "min", "max".

'count'
field str or None

Column to aggregate. Required unless aggregate="count".

None
cmap str or None

Colour map name. None (default) defers to the theme's sequential scheme.

None
stroke str or None

Hex border colour. None (default) means no border.

None
stroke_width float

Hex border width in pixels. Default is 0.

0
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the polygon layer.

{}

Returns:

Type Description
Chart

New Chart configured for hexagonal binning.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1.0, 2.0, 1.5, 3.0, 2.5], "y": [4.0, 5.0, 4.5, 3.0, 4.0]})
>>> fm.Chart(df).mark_hex(bin_size=0.5).encode(x="x", y="y")
Chart(mark='polygon', encoding=['x', 'y'])

mark_swarm

mark_swarm(*, size=4, orient='vertical', spacing=1.0, side='both', dodge=None, position=None, **mark_kwargs) -> 'Chart'

Render a beeswarm (strip swarm) plot via the Swarm transform.

Computes non-overlapping point positions along the categorical axis using a deterministic placement algorithm seeded for reproducibility. Requires a continuous y (or x) and an optional categorical grouping axis.

Parameters:

Name Type Description Default
size float

Point diameter in pixels. Default is 4.

4
orient ('vertical', 'horizontal')

Orientation of the swarm axis. "vertical" spreads points along x; "horizontal" spreads along y.

"vertical"
spacing float

Minimum spacing between point centres as a fraction of size. Default is 1.0.

1.0
side ('both', 'left', 'right')

Side of the axis on which points can be placed.

"both"
dodge str or None

Column name to use as a secondary grouping variable for dodging. None (default) means no dodging.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the point layer.

{}

Returns:

Type Description
Chart

New Chart configured for beeswarm rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"group": ["a"]*8 + ["b"]*8, "val": list(range(16))})
>>> fm.Chart(df).mark_swarm(size=6).encode(x="group", y="val")
Chart(mark='point', encoding=['x', 'y'])

mark_function

mark_function(fn, *, domain=None, n=200, clip=True, position=None, **mark_kwargs) -> 'Chart'

Render a mathematical function as a line.

Evaluates fn(xs) on n evenly-spaced x values in the specified domain and renders the result as a line. The input data on the chart is replaced with the synthetic dataset; use + composition to overlay a function on a scatter chart.

Parameters:

Name Type Description Default
fn callable

A function accepting a 1-D NumPy array of x values and returning a 1-D array of y values.

required
domain list of float or None

[x_min, x_max] evaluation range. None (default) infers the range from the parent chart's x column if available, otherwise raises ValueError.

None
n int

Number of evaluation points. Default is 200.

200
clip bool

Whether to clip rendered line to the plot viewport. Default is True.

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to the line layer (e.g. stroke, stroke_width).

{}

Returns:

Type Description
Chart

New Chart whose data is the synthetic (x, y) table.

Raises:

Type Description
ValueError

When domain is not provided and no parent x data can be inferred.

Examples:

>>> import ferrum as fm
>>> import numpy as np
>>> import polars as pl
>>> fm.Chart(None).mark_function(np.sin, domain=[0, 6.28], n=100)
Chart(mark='line', encoding=['x', 'y'])

mark_residuals

mark_residuals(*, kind: str = 'studentized', reference_line: bool = True, cook_threshold: float | str | None = None, color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a residuals diagnostic plot.

Plots fitted values (y_pred) on x against residuals (raw or studentized) on y. Data must carry the schema emitted by ModelSource.predictions(): y_true, y_pred, residual, studentized_residual, and cooks_distance.

When reference_line=True a sentinel _ref_zero column is injected so the downstream mark_rule draws a single horizontal line at y=0.

When cook_threshold is set, high-leverage points (Cook's D above the threshold) are highlighted as a second mark_point layer drawn in red with a black outline.

Parameters:

Name Type Description Default
kind ('studentized', 'raw')

Residual type to plot on the y axis. "studentized" uses studentized_residual; "raw" uses residual.

"studentized"
reference_line bool

Whether to draw a horizontal reference line at y=0. Default is True.

True
cook_threshold float, "auto", or None

Cook's Distance threshold for outlier highlighting. "auto" uses the conventional 4 / n rule. None (default) disables outlier highlighting.

None
color_field str or None

Column name to drive per-group colour on the scatter layer.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the scatter layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for residuals rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.predictions()).mark_residuals(cook_threshold="auto")
Chart(mark='point', encoding=[])

mark_prediction_error

mark_prediction_error(*, reference_line: bool = True, ci: float | None = None, reference_band: bool = False, color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render an actual-vs-predicted plot.

Plots y_true on x against y_pred on y as scatter points. When reference_line=True the data is pre-sorted ascending by y_true so the downstream mark_line renders a monotonic y=x diagonal. Data must carry y_true and y_pred columns (schema from ModelSource.predictions()).

Parameters:

Name Type Description Default
reference_line bool

Whether to overlay a y=x identity reference line. Default is True.

True
ci float or None

Confidence level for a prediction-interval band (e.g. 0.95). None (default) omits the band.

None
reference_band bool

Whether to draw a shaded reference band around the identity line. Default is False.

False
color_field str or None

Column name to drive per-group colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the scatter layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for prediction-error rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.predictions()).mark_prediction_error(ci=0.95)
Chart(mark='point', encoding=[])

mark_roc

mark_roc(*, average: str | None = None, reference_line: bool = True, annotate_auc: bool = False, color_field: str | None = 'class', position=None, **mark_kwargs) -> 'Chart'

Render a Receiver Operating Characteristic (ROC) curve.

Plots false-positive rate (fpr) on x against true-positive rate (tpr) on y as a line per class. Data must carry the schema emitted by ModelSource.roc_curve(): fpr, tpr, threshold, class, auc. When reference_line=True the data is pre-sorted ascending by fpr before rendering.

Parameters:

Name Type Description Default
average str or None

When the data contains a macro/micro average row with class=average, pass "macro" or "micro" to keep only that average line. None (default) renders all classes.

None
reference_line bool

Whether to overlay a diagonal chance-level reference line (TPR=FPR). Default is True.

True
annotate_auc bool

Whether to annotate each curve with its AUC value. Default is False.

False
color_field str or None

Column name to drive per-class colour. Default is "class".

'class'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for ROC rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.roc_curve()).mark_roc(annotate_auc=True)
Chart(mark='point', encoding=[])

mark_pr

mark_pr(*, average: str | None = None, annotate_ap: bool = False, iso_lines: bool = False, color_field: str | None = 'class', position=None, **mark_kwargs) -> 'Chart'

Render a Precision-Recall (PR) curve.

Plots recall on x against precision on y as a line per class. Data must carry the schema emitted by ModelSource.pr_curve(): precision, recall, threshold, class, ap.

Parameters:

Name Type Description Default
average str or None

Filter to a specific average type row (e.g. "macro"). None (default) renders all classes.

None
annotate_ap bool

Whether to annotate each curve with its average-precision (AP) value. Default is False.

False
iso_lines bool

Whether to draw iso-F1 reference lines in the background. Default is False.

False
color_field str or None

Column name to drive per-class colour. Default is "class".

'class'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for PR-curve rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.pr_curve()).mark_pr(annotate_ap=True)
Chart(mark='point', encoding=[])

mark_calibration

mark_calibration(*, n_bins: int = 10, strategy: str = 'uniform', reference_line: bool = True, color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a calibration (reliability) curve.

Plots mean predicted probability on x against fraction of positive outcomes (empirical probability) on y. A perfectly calibrated model lies on the diagonal. Data must carry the schema emitted by ModelSource.calibration_curve(): mean_predicted, fraction_positive, count.

When reference_line=True the data is pre-sorted ascending by mean_predicted before rendering.

Parameters:

Name Type Description Default
n_bins int

Number of calibration bins. Default is 10.

10
strategy ('uniform', 'quantile')

Binning strategy. "uniform" uses equally-spaced bins; "quantile" uses equal-frequency bins.

"uniform"
reference_line bool

Whether to overlay a perfect-calibration diagonal reference line. Default is True.

True
color_field str or None

Column name to drive per-group colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for calibration rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.calibration_curve()).mark_calibration(n_bins=15)
Chart(mark='point', encoding=[])

mark_gain

mark_gain(*, reference_line: bool = True, color_field: str | None = 'class', position=None, **mark_kwargs) -> 'Chart'

Render a cumulative gain chart.

Plots percent of population contacted on x against the cumulative gain (fraction of positive cases captured) on y. Data must carry the schema emitted by ModelSource.cumulative_gain(): percent_population, gain, class. The no-skill diagonal baseline is encoded as rows with class='baseline'.

Parameters:

Name Type Description Default
reference_line bool

Whether to draw the no-skill baseline diagonal. Default is True.

True
color_field str or None

Column name to drive per-class colour. Default is "class".

'class'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for cumulative-gain rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.cumulative_gain()).mark_gain()
Chart(mark='point', encoding=[])

mark_lift

mark_lift(*, reference_line: bool = True, color_field: str | None = 'class', position=None, **mark_kwargs) -> 'Chart'

Render a lift curve chart.

Plots percent of population targeted on x against lift (ratio of positive-case density to baseline) on y. Data must carry the schema emitted by ModelSource.lift_curve(): percent_population, lift, class. The no-skill lift=1 baseline is encoded as rows with class='baseline'.

Parameters:

Name Type Description Default
reference_line bool

Whether to draw the lift=1 baseline rule. Default is True.

True
color_field str or None

Column name to drive per-class colour. Default is "class".

'class'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for lift-curve rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.lift_curve()).mark_lift()
Chart(mark='point', encoding=[])

mark_discrimination_threshold

mark_discrimination_threshold(*, metrics: tuple[str, ...] = ('precision', 'recall', 'f1', 'queue_rate'), n_thresholds: int = 50, threshold_line: bool = False, optimum_label: bool = True, position=None, **mark_kwargs) -> 'Chart'

Render a discrimination-threshold sweep plot.

Sweeps the decision threshold from 0 to 1 and plots multiple metrics (precision, recall, F1, queue rate) as lines against the threshold value. Data must be in long form with columns threshold, metric, value — the figure builder handles unpivoting from ModelSource.discrimination_threshold() output.

Parameters:

Name Type Description Default
metrics tuple of str

Metric names to include. Default is ("precision", "recall", "f1", "queue_rate").

('precision', 'recall', 'f1', 'queue_rate')
n_thresholds int

Number of evenly-spaced threshold steps to evaluate. Default is 50.

50
threshold_line bool

Whether to draw a vertical rule at the optimal threshold. Default is False.

False
optimum_label bool

Whether to overlay a text annotation at the F1-optimum point showing "max F1 = {f1:.3f} @ t={threshold:.2f}". Default True (Schwabish C7 audit-rework, 2026-05-12). The mark's data_transform injects _optimum_x / _optimum_y / _optimum_text sentinel columns from the long-form data; the desugar emits a mark_text layer.

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for discrimination-threshold rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.discrimination_threshold()).mark_discrimination_threshold()
Chart(mark='point', encoding=[])

mark_confusion

mark_confusion(*, normalize: str | None = None, annotate: bool = True, color_field: str = 'value', cmap: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a confusion matrix as an annotated heatmap.

Renders an ordinal heatmap with actual class on one axis and predicted class on the other. Data must carry the long-form schema emitted by ModelSource.confusion_matrix(): actual, predicted, value, value_fmt. When annotate=True, a second mark_text layer reads value_fmt for per-cell text labels.

Parameters:

Name Type Description Default
normalize ('true', 'pred', 'all')

Normalise cell counts. None (default) shows raw counts.

"true"
annotate bool

Whether to overlay per-cell count / percentage text. Default is True.

True
color_field str

Column name driving the heatmap colour scale. Default is "value".

'value'
cmap str or None

Sequential colormap name for the heat cells. None (default) defers to the theme's sequential scheme.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the rect layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for confusion-matrix rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.confusion_matrix()).mark_confusion(normalize="true")
Chart(mark='point', encoding=[])

mark_class_prediction_error

mark_class_prediction_error(*, normalize: bool = False, color_field: str = 'predicted', show_counts: bool = True, position=None, **mark_kwargs) -> 'Chart'

Render a class prediction error bar chart.

Renders one stacked bar per actual class (x-axis), with segments coloured by predicted class. This orientation surfaces which classes are confused with which — for each actual class you can see how the model's predictions distribute across the predicted classes. Data must carry long-form columns (actual, predicted, value) — same shape as ModelSource.confusion_matrix(normalize=None).

Parameters:

Name Type Description Default
normalize bool

Whether to normalise each bar to 100%. Default is False.

False
color_field str

Column driving the segment colour. Default is "predicted".

'predicted'
show_counts bool

Whether to overlay per-segment count text at the segment centre. Default is True (Schwabish SB-followup 2026-05-12). Empty segments are skipped.

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for class-prediction-error rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.confusion_matrix()).mark_class_prediction_error(normalize=True)
Chart(mark='point', encoding=[])

mark_importance

mark_importance(*, orient: str = 'horizontal', error_bars: bool = True, top_k: int | None = None, color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a feature-importance bar chart.

Renders one bar per feature, sorted descending by importance. When error_bars=True and the data carries imp_lower/imp_upper columns a second errorbar layer is added. Data must carry the schema emitted by ModelSource.importances(): feature, importance, std. The chart builder computes the bound columns and truncates to top_k rows before calling this method.

Parameters:

Name Type Description Default
orient ('horizontal', 'vertical')

Bar orientation. "horizontal" places features on the y axis with importance on x (default); "vertical" swaps axes.

"horizontal"
error_bars bool

Whether to draw error bars from imp_lower/imp_upper. Default is True.

True
top_k int or None

Limit results to the top-k features by importance. Truncation is applied by the figure-level chart builder (importance_chart); when mark_importance is called directly this parameter is forwarded to the desugar function but the desugar layer treats it as informational — actual filtering must be done on the DataFrame before passing it to Chart.

None
color_field str or None

Column name to drive per-feature colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for feature-importance rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.importances()).mark_importance(top_k=10)
Chart(mark='point', encoding=[])

mark_shap_beeswarm

mark_shap_beeswarm(*, max_display: int = 20, color_bar: bool = True, order: str = 'abs_mean', zero_line: bool = True, position=None, **mark_kwargs) -> 'Chart'

Render a SHAP beeswarm summary plot.

Visualises the distribution of SHAP values across samples for each feature as a swarm of points, coloured by the feature's original value. Data must carry the long-form schema from ModelSource.shap_values() pre-filtered to the top max_display features by the chart builder.

When zero_line=True (default) a sentinel _ref_zero column is injected and the downstream desugar appends a dashed mark_rule layer at x=0.

Parameters:

Name Type Description Default
max_display int

Maximum number of top features to show. Default is 20.

20
color_bar bool

Whether to render a colour bar for the feature-value scale. Default is True.

True
order ('abs_mean', 'mean', 'none')

Feature ordering: by mean absolute SHAP ("abs_mean"), signed mean SHAP ("mean"), or original order ("none").

"abs_mean"
zero_line bool

Whether to overlay a dashed vertical reference rule at shap_value = 0. Default is True (Schwabish SB-followup 2026-05-12).

True
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the point layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for SHAP beeswarm rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.shap_values()).mark_shap_beeswarm(max_display=15)
Chart(mark='point', encoding=[])

mark_shap_bar

mark_shap_bar(*, max_display: int = 20, position=None, **mark_kwargs) -> 'Chart'

Render a SHAP aggregated-bar feature importance chart.

Shows mean absolute SHAP values per feature as a horizontal bar chart. Data must carry the long-form schema from ModelSource.shap_values() pre-filtered to the top max_display features by the chart builder.

Parameters:

Name Type Description Default
max_display int

Maximum number of top features to show. Default is 20.

20
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New Chart configured for SHAP bar rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.shap_values()).mark_shap_bar(max_display=10)
Chart(mark='point', encoding=[])

mark_pdp

mark_pdp(*, kind: str = 'average', ice_alpha: float = 0.2, center: bool = False, color_field: str | None = 'feature', position=None, **mark_kwargs) -> 'Chart'

Render partial-dependence plots (PDP / ICE).

Visualises how the model's output varies as a function of one feature while marginalising over all others. Data must carry the long-form schema from ModelSource.partial_dependence(): feature, feature_value, pd_value. The chart builder pre-sorts ascending by feature_value.

Parameters:

Name Type Description Default
kind ('average', 'individual', 'both')

What to render. "average" draws the mean PD line; "individual" draws ICE lines (one per sample); "both" overlays average on top of ICE lines.

"average"
ice_alpha float

Opacity of individual ICE lines when kind is "individual" or "both". Default is 0.2.

0.2
center bool

Whether to centre ICE lines at their first value (centred ICE). Default is False.

False
color_field str or None

Column name driving per-feature colour. Default is "feature".

'feature'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for PDP / ICE rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.partial_dependence()).mark_pdp(kind="both", center=True)
Chart(mark='point', encoding=[])

mark_shap_waterfall

mark_shap_waterfall(*, sample_idx: int = -1, max_display: int = 20, position=None, **mark_kwargs) -> 'Chart'

Render a SHAP waterfall chart for one sample.

Shows how each feature pushes the model output from the base value toward the final prediction for a single observation. Data must carry the long-form schema from ModelSource.shap_values() for the chosen sample_idx.

Parameters:

Name Type Description Default
sample_idx int

Row index of the sample to explain. Must be provided explicitly; the default -1 is a guard sentinel that raises ValueError immediately so callers get a clear error at call time rather than at render time.

-1
max_display int

Maximum number of features to show (smallest-magnitude features are collapsed into an "other" row). Default is 20.

20
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New Chart configured for SHAP waterfall rendering.

Raises:

Type Description
ValueError

If sample_idx is not provided (left at its default of -1).

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.shap_values()).mark_shap_waterfall(sample_idx=0)
Chart(mark='point', encoding=[])

mark_learning_curve

mark_learning_curve(*, ci_style: str = 'band', color_field: str | None = 'split', position=None, **mark_kwargs) -> 'Chart'

Render a learning curve (train size vs. CV score).

Plots training set size on x against CV score on y, with separate lines for training and validation splits. Data must carry the schema emitted by ModelSource.learning_curve(), pre-deduped per (train_size, split) by the chart builder.

Parameters:

Name Type Description Default
ci_style ('band', 'bars', 'none')

How to display cross-validation variance. "band" draws a shaded ribbon; "bars" draws error bars; "none" omits CI.

"band"
color_field str or None

Column name to drive per-split line colour. Default is "split".

'split'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for learning-curve rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_train, y_train)
>>> fm.Chart(src.learning_curve()).mark_learning_curve(ci_style="band")
Chart(mark='point', encoding=[])

mark_validation_curve

mark_validation_curve(*, log_scale: bool = False, ci_style: str = 'band', color_field: str | None = 'split', param_label: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a validation curve (hyperparameter vs. CV score).

Plots a swept hyperparameter value on x against CV score on y, with separate lines for training and validation splits. Data must carry the schema emitted by ModelSource.validation_curve(), pre-deduped per (param_value, split) by the chart builder.

Parameters:

Name Type Description Default
log_scale bool

Whether to use a log scale on the x axis. Useful for parameters like regularisation strength that span orders of magnitude. Default is False.

False
ci_style ('band', 'bars', 'none')

How to display cross-validation variance.

"band"
color_field str or None

Column name to drive per-split line colour. Default is "split".

'split'
param_label str or None

Human-readable x-axis title for the hyperparameter being swept. The chart builder forwards the user's param argument here.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for validation-curve rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_train, y_train)
>>> fm.Chart(src.validation_curve(param="C")).mark_validation_curve(
...     log_scale=True, param_label="C"
... )
Chart(mark='point', encoding=[])

mark_cv_scores

mark_cv_scores(*, kind: str = 'box', split: str = 'both', position=None, **mark_kwargs) -> 'Chart'

Render a per-fold cross-validation score summary.

Shows the distribution of CV scores across folds as a box plot, strip plot, or bar chart. Data must carry the schema emitted by ModelSource.cv_scores(). The chart builder pre-aggregates per split when kind="bar" and passes raw per-fold rows for "box" or "strip".

Parameters:

Name Type Description Default
kind ('box', 'strip', 'bar')

Summary plot type.

"box"
split ('train', 'test', 'both')

Which CV split(s) to display.

"train"
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to constituent layers.

{}

Returns:

Type Description
Chart

New layered Chart configured for CV-score rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_train, y_train)
>>> fm.Chart(src.cv_scores()).mark_cv_scores(kind="strip", split="test")
Chart(mark='point', encoding=[])

mark_alpha_selection

mark_alpha_selection(*, log_scale: bool = True, highlight_best: bool = True, ci_style: str = 'band', position=None, **mark_kwargs) -> 'Chart'

Render a regularisation-strength (alpha) selection curve.

Sweeps the regularisation parameter alpha and plots CV score as a function of alpha, with variance bands. When highlight_best=True a vertical rule is drawn at the alpha that maximises mean_score. Data must carry the schema emitted by ModelSource.alpha_selection(): alpha, mean_score, score_lo, score_hi, split.

Parameters:

Name Type Description Default
log_scale bool

Whether to use a log scale on the x axis. Default is True (regularisation parameters typically span orders of magnitude).

True
highlight_best bool

Whether to draw a vertical reference rule at the optimal alpha. Default is True.

True
ci_style ('band', 'bars', 'none')

How to display CV variance.

"band"
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides forwarded to constituent layers.

{}

Returns:

Type Description
Chart

New layered Chart configured for alpha-selection rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(lasso, X_train, y_train)
>>> fm.Chart(src.alpha_selection()).mark_alpha_selection(log_scale=True)
Chart(mark='point', encoding=[])

mark_silhouette

mark_silhouette(*, zero_line: bool = True, color_field: str | None = 'cluster', position=None, **mark_kwargs) -> 'Chart'

Render a Rousseeuw silhouette plot.

Displays one horizontal bar per sample whose width encodes its silhouette coefficient, coloured by cluster assignment. Samples within each cluster are stacked vertically in descending coefficient order. Data must carry the schema emitted by ModelSource.silhouette(): sample_id, y_position, cluster, silhouette_value.

When zero_line=True a sentinel _ref_zero column is injected so the downstream mark_rule renders a single vertical rule at x=0.

The method pre-computes _silhouette_x_lo, _silhouette_x_hi, _silhouette_y_lo, and _silhouette_y_hi columns from the raw data so the renderer can draw rect marks directly.

Parameters:

Name Type Description Default
zero_line bool

Whether to draw a vertical reference rule at silhouette = 0. Default is True.

True
color_field str or None

Column name driving per-cluster colour. Default is "cluster".

'cluster'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the rect layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for silhouette rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(kmeans, X)
>>> fm.Chart(src.silhouette()).mark_silhouette()
Chart(mark='rect', encoding=[])

mark_pca_scree

mark_pca_scree(*, cumulative_line: bool = True, threshold_line: float | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a PCA scree plot.

Displays explained variance ratio per component as bars and optionally overlays the cumulative variance ratio as a line. Data must carry the schema emitted by ModelSource.pca_variance(): component, explained_variance_ratio, cumulative_variance_ratio.

When threshold_line is non-None a sentinel _threshold_line column is injected so the downstream mark_rule draws a single horizontal reference line at the threshold value.

Parameters:

Name Type Description Default
cumulative_line bool

Whether to overlay a cumulative explained variance line. Default is True.

True
threshold_line float or None

Y-position of an optional horizontal threshold reference line (e.g. 0.95 for 95% explained variance). None (default) omits the line.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for PCA scree rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(pca_model, X)
>>> fm.Chart(src.pca_variance()).mark_pca_scree(threshold_line=0.95)
Chart(mark='rect', encoding=[])

mark_intercluster_distance

mark_intercluster_distance(*, label_clusters: bool = True, color_field: str | None = 'cluster', position=None, **mark_kwargs) -> 'Chart'

Render a 2-D intercluster distance (MDS) plot.

Embeds cluster centres into 2-D using MDS and visualises each centre as a point whose area encodes cluster size. With label_clusters=True a mark_text overlay labels each point by its cluster id. Data must carry the schema emitted by ModelSource.intercluster_distance(): cluster, x, y, size.

Parameters:

Name Type Description Default
label_clusters bool

Whether to overlay cluster-id text labels. Default is True.

True
color_field str or None

Column name driving per-cluster colour. Default is "cluster".

'cluster'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the point layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for intercluster-distance rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(kmeans, X)
>>> fm.Chart(src.intercluster_distance()).mark_intercluster_distance()
Chart(mark='point', encoding=[])

mark_decision_boundary

mark_decision_boundary(*, proba: bool = False, color_field: str = 'z', position=None, **mark_kwargs) -> 'Chart'

Render a decision-boundary heatmap.

Colours a pixel grid by the model's predicted class (proba=False) or class probability (proba=True) at each grid point. Data must carry pre-computed cell bound columns x, x2, y, y2 and a prediction column z. The chart builder helper _decision_boundary_chart_from_source produces these columns from a ModelSource.

Parameters:

Name Type Description Default
proba bool

Whether to colour by predicted probability rather than class index. Default is False.

False
color_field str

Column name for the colour encoding. Default is "z".

'z'
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the rect layer.

{}

Returns:

Type Description
Chart

New Chart configured for decision-boundary rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(clf, X_test, y_test)
>>> fm.Chart(src.decision_boundary()).mark_decision_boundary(proba=True)
Chart(mark='rect', encoding=[])

mark_rank1d

mark_rank1d(*, orient: str = 'horizontal', color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a univariate feature-ranking bar chart.

Ranks features by a univariate score (e.g. mutual information, ANOVA F-statistic) and displays them as a bar chart sorted by rank. Data must carry the schema emitted by ModelSource.rank1d(): feature, score, rank.

Parameters:

Name Type Description Default
orient ('horizontal', 'vertical')

Bar orientation. "horizontal" places features on the y axis with score on x; "vertical" places features on x.

"horizontal"
color_field str or None

Column name driving per-feature colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the bar layer.

{}

Returns:

Type Description
Chart

New Chart configured for rank-1D rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.rank1d()).mark_rank1d()
Chart(mark='bar', encoding=[])

mark_rank2d

mark_rank2d(*, annot: bool = True, color_field: str = 'correlation', text_field: str = 'correlation_fmt', cmap: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a pairwise feature-ranking correlation heatmap.

Displays pairwise feature correlation scores as a colour-coded matrix. When annot=True a text overlay renders each cell's value to 2 dp. Data must carry the schema emitted by ModelSource.rank2d(): feature_x, feature_y, correlation. The chart builder appends a correlation_fmt (Utf8) column when annot=True.

Parameters:

Name Type Description Default
annot bool

Whether to overlay per-cell correlation value text. Default is True.

True
color_field str

Column driving the heatmap colour scale. Default is "correlation".

'correlation'
text_field str

Column read by the text layer. Default is "correlation_fmt".

'correlation_fmt'
cmap str or None

Diverging colormap name for correlation cells. None (default) defers to the theme's diverging scheme.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the rect layer.

{}

Returns:

Type Description
Chart

New layered Chart configured for rank-2D rendering.

Examples:

>>> import ferrum as fm
>>> src = fm.ModelSource(model, X_test, y_test)
>>> fm.Chart(src.rank2d()).mark_rank2d(annot=True)
Chart(mark='rect', encoding=[])

mark_parallel_coordinates

mark_parallel_coordinates(*, alpha: float = 0.5, color_field: str | None = None, position=None, **mark_kwargs) -> 'Chart'

Render a parallel coordinates plot.

Draws one polyline per sample across normalised feature axes. Data must carry the long-form schema produced by _parallel_coords_chart_from_dataframe: feature (Utf8), value (Float64), sample_id (Utf8), and (optionally) a hue column passed via color_field. The line layer uses mark_style.detail = "sample_id" so each sample renders as its own polyline.

Parameters:

Name Type Description Default
alpha float

Line opacity. Default is 0.5.

0.5
color_field str or None

Column name driving per-sample (or per-class) line colour.

None
position Position

Position adjustment.

None
**mark_kwargs

Mark-style overrides for the line layer.

{}

Returns:

Type Description
Chart

New Chart configured for parallel-coordinates rendering.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"feature": ["a","a","b","b"],
...                    "value": [0.5, 0.3, 0.8, 0.2],
...                    "sample_id": ["s0", "s1", "s0", "s1"]})
>>> fm.Chart(df).mark_parallel_coordinates(color_field="sample_id")
Chart(mark='line', encoding=[])

mark_arc

mark_arc(**kwargs) -> 'Chart'

Render data as arcs (pie or donut slices).

Requires Chart.coord(fm.CoordPolar(theta="x")) to be set. The theta-mapped encoding channel (x by default) determines each slice's angular sweep proportional to its value.

Parameters:

Name Type Description Default
**kwargs

Mark style overrides: color, opacity, stroke_width, etc.

{}

Examples:

>>> fm.Chart(df).mark_arc().encode(x="value", color="category").coord(
...     fm.CoordPolar(theta="x")
... )

mark_image

mark_image(**kwargs) -> 'Chart'

Render data as raster images.

Each row in the dataset becomes one image tile. Supply a base64-encoded PNG/JPEG via the url encoding channel. Requires Cartesian coordinates; returns an empty scene for Polar or Geo coord systems.

Parameters:

Name Type Description Default
**kwargs

Mark style overrides: width, height, opacity, etc.

{}

Examples:

>>> fm.Chart(df).mark_image().encode(x="x", y="y", url="data_url")

mark_geoshape

mark_geoshape(**kwargs) -> 'Chart'

Render geographic shapes from a GeoJSON FeatureCollection.

Pass a GeoJSON FeatureCollection dict to Chart(data) — ferrum auto-detects the format and splits properties into encoding channels and geometry into a __geometry__ column. Set the projection via Chart.coord(fm.CoordGeo(projection="mercator")).

Parameters:

Name Type Description Default
**kwargs

Mark style overrides: color, opacity, stroke_width, etc.

{}

Examples:

>>> fm.Chart(geojson_data).mark_geoshape().coord(
...     fm.CoordGeo(projection="equal_earth")
... )

mark_label

mark_label(**kwargs) -> 'Chart'

Render positioned text labels near data points with collision avoidance.

Each row in the dataset becomes one text label. By default the renderer uses a greedy collision-avoidance algorithm: for each label in row order it tries a ranked list of candidate offsets (above, below, right, left, diagonals) and picks the first placement whose estimated bounding box overlaps no previously-placed label. When every candidate overlaps something, the least-bad placement is chosen.

When both dx and dy are supplied explicitly, collision avoidance is bypassed and those fixed offsets are applied to every label (manual positioning path).

Parameters:

Name Type Description Default
dx float

Fixed horizontal offset in pixels. Must be combined with dy to bypass collision avoidance.

required
dy float

Fixed vertical offset in pixels. Must be combined with dx to bypass collision avoidance. Default when auto-placing is to prefer dy = -8 (above the point).

required
font_size float

Label font size in points (default 11).

required
leader_line bool

When True, a thin line is drawn from each data point to its placed label position. Useful when labels are placed far from their source points. Default False.

required
**kwargs

Additional mark style overrides (fill, opacity, font_weight, etc.).

{}

Examples:

>>> fm.Chart(df).mark_label().encode(x="x:Q", y="y:Q", text="label")
>>> fm.Chart(df).mark_label(dx=5, dy=-12).encode(x="x:Q", y="y:Q", text="label")
>>> fm.Chart(df).mark_label(leader_line=True).encode(x="x:Q", y="y:Q", text="label")

encode

encode(**channels: Any) -> 'Chart'

Set or update encoding channels on this chart.

Each keyword argument maps a channel name to a field shorthand string (e.g. "species:N") or an explicit channel object (e.g. fm.X("sepal_length", type="Q")).

Parameters:

Name Type Description Default
x str or X

Field mapped to the x position. Shorthand format: "field" (type inferred), "field:Q" (quantitative), "field:N" (nominal), "field:O" (ordinal), "field:T" (temporal), or "agg(field):Q" (aggregation).

required
y str or Y

Field mapped to the y position.

required
x2 str or X2

Secondary x position (band / segment end).

required
y2 str or Y2

Secondary y position.

required
color str or Color

Field or value driving mark colour.

required
fill str or Fill

Field or value driving mark fill colour.

required
stroke str or Stroke

Field or value driving mark stroke colour.

required
size str or Size

Field or value driving mark size.

required
shape str or Shape

Field or value driving mark shape.

required
opacity str or Opacity

Field or value driving mark opacity.

required
text str or Text

Field rendered as text labels (used with mark_text).

required
detail str or Detail

Additional grouping field that does not map to any visual property.

required
tooltip str or Tooltip

Field shown on hover.

required
**channels Any

Any other valid channel names (x_error, y_error, theta, radius, etc.).

{}

Returns:

Type Description
Chart

New Chart with updated encoding channels.

Raises:

Type Description
ValueError

If an unknown channel name is passed.

TypeError

If a value is not a string, channel instance, or Repeat placeholder.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6], "c": ["a", "b", "a"]})
>>> fm.Chart(df).mark_point().encode(x="x:Q", y="y:Q", color="c:N")
Chart(mark='point', encoding=['x', 'y', 'color'])

layer

layer(*layers) -> 'Chart'

Add one or more layer objects to this chart.

Accepts both public Layer instances (user-facing API) and internal _Layer instances (used by ferrum internals).

When a Layer(data=df, ...) has its own data attribute, that data is merged with the chart's existing data via diagonal concatenation (same strategy as the + operator). Each layer's encoding references only its own columns; null-padded rows in the merged batch are invisible to mark renderers that skip null values.

Parameters:

Name Type Description Default
*layers Layer or _Layer

Layer objects to append. Public Layer instances may carry an independent data= DataFrame.

()

Returns:

Type Description
Chart

This chart with the new layers appended.

transform

transform(*transforms) -> 'Chart'

Append one or more data transforms to the chart's pipeline.

Transforms are executed in order by the Rust engine before rendering. Multiple calls to transform() accumulate — each appends to the existing pipeline.

Parameters:

Name Type Description Default
*transforms

One or more transform objects (e.g. fm.Filter(...), fm.Aggregate(...), fm.Sort(...), fm.Window(...)). Accepts any object that serialises to a valid TransformSpec JSON shape.

()

Returns:

Type Description
Chart

New Chart with the additional transforms appended.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> fm.Chart(df).mark_point().encode(x="x", y="y").transform(
...     fm.Filter("datum.x > 1")
... )
Chart(mark='point', encoding=['x', 'y'])

facet

facet(field: Optional[str] = None, *, row: Optional[str] = None, col: Optional[str] = None, ncols: Optional[int] = None, nrows: Optional[int] = None) -> 'Chart'

Facet this chart into small multiples by a field.

Two modes are supported:

  • Wrap — a single field is wrapped across columns (rows auto). Pass field= or equivalently col= alone.
  • Grid — two fields define row × column layout. Pass both row= and col=.

Parameters:

Name Type Description Default
field str

Column name used for wrap-mode faceting. Mutually exclusive with using both row and col together.

None
row str

Column name for the row dimension (grid mode). When used alone, behaves as wrap mode on the row axis.

None
col str

Column name for the column dimension (wrap or grid mode).

None
ncols int or None

Maximum number of columns in wrap mode. None lets the renderer choose.

None
nrows int or None

Maximum number of rows. None lets the renderer choose.

None

Returns:

Type Description
Chart

New Chart with faceting configured.

Raises:

Type Description
ValueError

If neither field, row, nor col is provided.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1,2,3]*3, "y": [4,5,6]*3,
...                    "g": ["a","a","b","b","c","c","a","b","c"]})
>>> fm.Chart(df).mark_point().encode(x="x", y="y").facet(col="g", ncols=2)
Chart(mark='point', encoding=['x', 'y'])

theme

theme(theme: Any) -> 'Chart'

Attach a Theme to this chart, overriding the process-level default.

Per-chart theme always wins over ferrum.set_default_theme(). Theme objects are immutable value classes — modifying the original Theme after calling .theme() has no effect on the chart.

Parameters:

Name Type Description Default
theme Theme

A ferrum.Theme instance (e.g. fm.themes.dark(), fm.Theme(background="white", font="serif")).

required

Returns:

Type Description
Chart

New Chart with the specified theme attached.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> dark = fm.themes.dark()
>>> fm.Chart(df).mark_point().encode(x="x", y="y").theme(dark)
Chart(mark='point', encoding=['x', 'y'])

axis

axis(*, x: Optional[bool] = None, y: Optional[bool] = None, show: Optional[bool] = None) -> 'Chart'

Suppress (or restore) the chart's x/y axis decorations.

Spec-level axis suppression — when x=False (or y=False), the corresponding axis line, ticks, tick labels, and axis title are omitted at layout time. The plot area's pixel rect is unchanged (gutters reserved for axis decorations are preserved), so this method is intended for sub-charts whose axes are shared with a neighbouring chart in a compound view: clustermap dendrograms, JointChart marginals, RepeatChart off-diagonal panels.

Parameters:

Name Type Description Default
x bool

False hides the x axis; True shows it; None leaves the current setting (default visible).

None
y bool

False hides the y axis; True shows it; None leaves the current setting (default visible).

None
show bool

Shorthand for axis(x=show, y=show). Mutually exclusive with per-axis x/y arguments.

None

Returns:

Type Description
Chart

New Chart with the requested axis-visibility settings.

Raises:

Type Description
ValueError

If show is combined with x or y.

Examples:

Hide both axes (e.g. for a dendrogram panel):

>>> chart.axis(show=False)

Hide just the x axis (top marginal of a JointChart):

>>> chart.axis(x=False)

coord

coord(coord: Any) -> 'Chart'

Set the coordinate system for this chart.

Currently only CoordFlip is supported (swaps x and y axes).

Parameters:

Name Type Description Default
coord CoordFlip

A coordinate-system object. Pass fm.CoordFlip() to swap the horizontal and vertical axes.

required

Returns:

Type Description
Chart

New Chart with the coordinate system set.

Raises:

Type Description
TypeError

If coord is not a supported coordinate-system type.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"cat": ["a", "b", "c"], "val": [10, 20, 15]})
>>> fm.Chart(df).mark_bar().encode(x="cat", y="val").coord(fm.CoordFlip())
Chart(mark='bar', encoding=['x', 'y'])

properties

properties(*, width=None, height=None, title=None, description=None, render_config=None) -> 'Chart'

Set chart-level display properties.

Only the keyword arguments that are explicitly provided are updated; unset properties inherit from the existing chart.

Parameters:

Name Type Description Default
width int or 'container' or None

Chart width in pixels, or "container" to fill the parent.

None
height int or 'container' or None

Chart height in pixels.

None
title str or None

Chart title rendered above the plot area.

None
description str or None

Accessible description attached to the SVG root.

None
render_config RenderConfig or None

Rendering policy configuration. Controls auto-raster threshold and behavior. For one-off overrides prefer the raster= keyword on .show() / .save() / .show_svg() instead.

None

Returns:

Type Description
Chart

New Chart with the specified properties updated.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4]})
>>> fm.Chart(df).mark_point().encode(x="x", y="y").properties(
...     width=400, height=300, title="My Chart"
... )
Chart(mark='point', encoding=['x', 'y'])

to_spec

to_spec()

Build the Rust ChartSpec for this chart.

Resolves any pending statistical-mark desugar, converts Python encoding channel objects to EncodingSpec instances, and constructs the ChartSpec PyO3 object that the Rust renderer consumes.

Returns:

Type Description
ChartSpec

The fully-resolved ferrum._core.ChartSpec for this chart.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4]})
>>> spec = fm.Chart(df).mark_point().encode(x="x", y="y").to_spec()
>>> spec.mark
'point'

to_json

to_json(*, indent=None) -> str

Serialise the chart specification to a JSON string.

Calls to_spec() to build the ChartSpec and then serialises it via the Rust serde_json encoder. When indent is given the compact JSON is reformatted via json.loads / json.dumps on the Python side (the Rust encoder always produces compact output).

Parameters:

Name Type Description Default
indent int or None

Number of spaces to use for pretty-printing. None (default) returns compact single-line JSON.

None

Returns:

Type Description
str

JSON representation of the chart specification.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1], "y": [2]})
>>> spec_json = fm.Chart(df).mark_point().encode(x="x", y="y").to_json()
>>> '"mark"' in spec_json
True

add_selection

add_selection(*selections) -> 'Chart'

Attach interactive selection(s) to this chart.

Per ferrum-spec.md §3.10 (L736), the SVG/PNG renderer silently ignores selections — they are intended for the WASM renderer (Phase 11). This method accepts any number of selection objects and returns a new Chart unchanged so that user code building selection-aware charts remains forward-compatible without raising under SVG/PNG rendering.

Parameters:

Name Type Description Default
*selections

Any number of selection objects (currently ignored).

()

Returns:

Type Description
Chart

New Chart (clone), with the selections recorded but not rendered.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4]})
>>> chart = fm.Chart(df).mark_point().encode(x="x", y="y").add_selection()

interactive

interactive() -> 'Chart'

Mark this chart as interactive.

Per ferrum-spec.md §3.10 (L736), interactive features (selections, pan/zoom, conditional encodings) are silently ignored under SVG/PNG. Returns a new Chart so chained construction patterns work today and will gain real interactivity once the Phase 11 WASM renderer ships.

Returns:

Type Description
Chart

New Chart (clone).

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4]})
>>> chart = fm.Chart(df).mark_point().encode(x="x", y="y").interactive()

conditional

conditional(spec: Any) -> 'Chart'

Apply a conditional encoding to this chart.

Convenience sugar: chart.conditional(sel.when(Color("x")).otherwise(value("#ccc"))) is equivalent to::

chart.add_selection(sel).encode(color=sel.when(Color("x")).otherwise(value("#ccc")))

Parameters:

Name Type Description Default
spec ConditionalSpec

A ConditionalSpec produced by sel.when(...).otherwise(...).

required

Returns:

Type Description
Chart

New Chart with the conditional recorded.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> from ferrum.selection import selection_point, value
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4], "z": ["a", "b"]})
>>> sel = selection_point(fields=["z"])
>>> chart = (
...     fm.Chart(df)
...     .mark_point()
...     .encode(x="x", y="y")
...     .conditional(sel.when(fm.Color("z")).otherwise(value("#ccc")))
... )

show_svg

show_svg(*, raster: bool | None = None) -> str

Render the chart to an SVG string.

Parameters:

Name Type Description Default
raster bool or None

Override the auto-raster policy for this render only. False forces per-element SVG regardless of mark count. True forces raster aggregation. None uses the chart's RenderConfig policy.

None

Returns:

Type Description
str

SVG markup for the chart.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> svg = fm.Chart(df).mark_point().encode(x="x", y="y").show_svg()
>>> svg.startswith("<svg")
True

show_png

show_png(*, raster: bool | None = None) -> bytes

Render the chart to PNG bytes.

Parameters:

Name Type Description Default
raster bool or None

Override the auto-raster policy for this render only. False forces per-element rendering. True forces raster. None uses the chart's RenderConfig policy.

None

Returns:

Type Description
bytes

PNG-encoded image data.

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> png = fm.Chart(df).mark_point().encode(x="x", y="y").show_png()
>>> png[:4] == b'\x89PNG'
True

save

save(path, *, format=None, embed_wasm=True, raster: bool | None = None) -> None

Save the chart to a file on disk.

Parameters:

Name Type Description Default
path str or Path

Destination file path. Extension determines the default format: .svg -> SVG, .png -> PNG, .html -> HTML, .json -> JSON.

required
format ('svg', 'png', 'html', 'json')

Explicit format override. None (default) infers from path.

"svg"
embed_wasm bool

For "html" format only. When True (default), the WASM binary is base64-inlined for single-file distribution.

True
raster bool or None

Override the auto-raster policy for this save only. False forces per-element output. True forces raster. None uses the chart's RenderConfig policy.

None

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
>>> fm.Chart(df).mark_point().encode(x="x", y="y").save("/tmp/chart.svg")

show

show(*, raster: bool | None = None) -> None

Display the chart inline or in a browser.

Parameters:

Name Type Description Default
raster bool or None

Override the auto-raster policy for this render only. False forces per-element SVG regardless of mark count. True forces raster aggregation. None uses the chart's RenderConfig policy.

None

Examples:

>>> import ferrum as fm
>>> import polars as pl
>>> df = pl.DataFrame({"x": [1, 2], "y": [3, 4]})
>>> fm.Chart(df).mark_point().encode(x="x", y="y").show()