Skip to content

Composition

HConcatChart, VConcatChart, LayerChart, hconcat, vconcat, concat.

Ferrum — a statistical visualization library with a Rust core.

ClusterMapChart

Bases: _CompositeBase

Clustered heatmap with optional row and column dendrograms.

Lays out a 2 × 2 grid: the heatmap occupies the bottom-right panel, the column dendrogram goes top-right, the row dendrogram (rotated 90°) goes bottom-left, and the top-left corner is empty. Dendrogram value axes are hidden; categorical axes align with the heatmap row/column labels.

Panel size is split by dendrogram_ratio: dendrograms receive that fraction of the total width/height, the heatmap receives the remainder.

Most users obtain a ClusterMapChart from ferrum.clustermap rather than constructing one directly.

Parameters:

Name Type Description Default
heatmap Chart

The central heatmap chart.

required
row_dendrogram Chart

Dendrogram chart for the row axis. Displayed to the left of the heatmap, rotated 90°.

None
col_dendrogram Chart

Dendrogram chart for the column axis. Displayed above the heatmap.

None
dendrogram_ratio float

Fraction of the total width/height allocated to each dendrogram panel. Must be in the open interval (0, 1).

0.2
spacing float

Pixel gap between adjacent panels.

10.0

Raises:

Type Description
ValueError

If dendrogram_ratio is not in the open interval (0, 1).

Examples:

>>> import ferrum as fm
>>> cm = fm.clustermap(df, method="ward", cmap="rdbu")
>>> cm.save("clustermap.svg")

charts property

charts: list

List of Chart : All non-None sub-charts in __init__ order (heatmap, row_dendrogram, col_dendrogram).

spec property

spec: dict

Dict : Serializable layout introspection (ferrum-spec §3.12 contract).

Embedded charts round-trip through ChartSpec.from_json. Purely an introspection/serialization surface — rendering goes through the composite spec tree (:meth:_composite_tree), not this dict.

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

to_svg

to_svg() -> str

Render the cluster map to an SVG string.

Returns:

Type Description
str

SVG markup with the 2 × 2 grid layout.

ConcatChart

Bases: _CompositeBase

General wrapping concatenation of charts in a grid.

Arranges charts left-to-right, wrapping to the next row after columns charts. When columns is None, all charts are placed in a single row.

Parameters:

Name Type Description Default
*charts Chart

Two or more charts to arrange.

()
columns int

Maximum number of columns before wrapping. Defaults to len(charts) (single row, no wrapping).

None
spacing float

Pixel gap between adjacent panels.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides — e.g. resolve={"x": "shared", "y": "shared"}. Pass a :class:Resolve to also control figure-level legend resolution for a shared color/size scale.

None

Raises:

Type Description
ValueError

If fewer than one chart is provided, if columns is not > 0, or if resolve contains invalid values.

Examples:

>>> import ferrum as fm
>>> charts = [fm.Chart(df).mark_point().encode(x=col, y="y") for col in cols]
>>> fm.ConcatChart(*charts, columns=2).save("grid.svg")

columns property

columns: Optional[int]

Number of columns in the wrapping grid, or None for single-row.

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

to_svg

to_svg() -> str

Render the concatenated charts to an SVG string.

Routes HConcat/VConcat/ConcatChart through the one-call Rust composite entry (render_composite_svg); see :func:_lower_composite.

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

HConcatChart

Bases: _CompositeBase

Horizontal concatenation of two or more charts.

Each sub-chart retains its own scales, axes, and legend by default. Pass resolve= to unify one or more channels across panels. Construct via the | operator on Chart instances or directly with a list.

Parameters:

Name Type Description Default
charts list of Chart

Sub-charts to concatenate left-to-right.

required
spacing float

Horizontal pixel gap between adjacent charts.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides, e.g. {"color": "shared"} (equivalent to Resolve(scale={"color": "shared"})). Pass a :class:Resolve to also control figure-level legend resolution, e.g. Resolve(scale={"color": "shared"}, legend={"color": "independent"}) to keep per-panel legends over a shared color scale. Accepts the same keys and values as ConcatChart(resolve=...).

None

Examples:

>>> import ferrum as fm
>>> combined = fm.Chart(df).encode(x="hp", y="mpg").mark_point() | fm.Chart(df).encode(x="hp").mark_histogram()
>>> combined.save("side_by_side.svg")

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

to_svg

to_svg() -> str

Render the concatenated charts to an SVG string.

Routes HConcat/VConcat/ConcatChart through the one-call Rust composite entry (render_composite_svg); see :func:_lower_composite.

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

JointChart

Bases: _CompositeBase

Joint distribution view: center chart plus optional top and right marginals.

Lays out a 2 × 2 grid: center chart occupies the bottom-left panel, top marginal goes top-left, right marginal goes bottom-right, and the top-right corner is empty. The x-axis is shared between the center and top charts; the y-axis is shared between the center and right charts.

The panel size ratio between the center and each marginal is controlled by ratio. A ratio of 5 gives the center 5/(5+1) of each dimension and each marginal 1/(5+1).

Most users obtain a JointChart from ferrum.jointplot rather than constructing one directly.

Parameters:

Name Type Description Default
center Chart

Primary scatter / distribution chart occupying the main panel.

required
top Chart

Marginal chart drawn above the center (e.g. a histogram of the x variable).

None
right Chart

Marginal chart drawn to the right of the center (e.g. a histogram of the y variable).

None
ratio int

Size ratio of the center panel to each marginal panel. Must be > 0.

5
spacing float

Pixel gap between adjacent panels.

10.0

Raises:

Type Description
ValueError

If ratio is not > 0.

Examples:

>>> import ferrum as fm
>>> joint = fm.jointplot(df, x="hp", y="mpg")
>>> joint.save("joint.svg")

charts property

charts: list

List of Chart : All non-None sub-charts (center, top, right).

spec property

spec: dict

Dict : Serializable layout introspection (ferrum-spec §3.12 contract).

Embedded charts round-trip through ChartSpec.from_json. Purely an introspection/serialization surface — rendering goes through the composite spec tree (:meth:_composite_tree), not this dict.

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

to_svg

to_svg() -> str

Render the joint chart to an SVG string.

Returns:

Type Description
str

SVG markup with the 2 × 2 grid layout.

LayerChart

Bases: _ChartLike

Overlay multiple charts on shared axes (same coordinate space).

All layers share x scale by default (union domain) and this cannot be turned off — the overlay only makes sense with a single shared x coordinate space; see :func:_validate_layer_resolve. y shares by default too, but resolve={"y": "independent"} renders a dual-axis chart instead: layer 0's y-axis on the left, each subsequent layer's own y-axis stacked on the right (GH #52) — see :meth:_build_merged and :meth:to_svg. The charts are merged using the same Chart + Chart layer-merge logic that the + operator provides — domain union, null-padded diagonal concat for heterogeneous data, named-transform routing for per-layer transforms.

Render routing (three routes): the _y_independent() predicate selects the static path — (1) static shared/default y → the Phase B overlay composite tree (:meth:_composite_tree); (2) static independent y → the merged flat single-panel chart (:meth:_build_mergedto_svg) — while (3) the interactive entry point ALWAYS uses the merged flat chart regardless of resolve (:meth:_render_interactive_merged) because selections/hit-testing require overlays to be ONE scene panel. Nested lowering follows the same predicate in _lower_any.

Use LayerChart when you have pre-built Chart objects and want a composition-level overlay without constructing the + chain inline. The resulting SVG is rendered as a single plot area with all layers stacked.

Parameters:

Name Type Description Default
*charts Chart

Two or more charts to overlay. At least one chart is required.

()
resolve dict or Resolve

Per-channel scale-sharing overrides — e.g. resolve={"color": "independent"}. x is always shared (the overlay contract) and marking it "independent" raises (see GH

55 dual-x-axis). y: "independent" renders a secondary axis

per non-primary layer (GH #52). Non-positional channels follow the same inheritance rules as Chart + Chart. Pass a :class:Resolve to also control figure-level legend resolution for a shared color/size scale.

None
title str

Title applied to the combined chart via .properties(title=...).

None

Raises:

Type Description
ValueError

If fewer than one chart is provided, if resolve contains invalid values, or if resolve marks x "independent" (see GH #55 dual-x-axis).

Examples:

>>> import ferrum as fm
>>> scatter = fm.Chart(df).mark_point().encode(x="x", y="y")
>>> line = fm.Chart(df).mark_line().encode(x="x", y="y")
>>> fm.LayerChart(scatter, line).save("overlay.svg")
>>> fm.LayerChart(scatter, line, resolve={"y": "independent"}).save("dual.svg")

charts property

charts: list

List of Chart : All member charts in layer order (bottom to top).

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

to_svg

to_svg() -> str

Render the layered charts to an SVG string.

Default/shared-y renders through the composite overlay tree (:meth:_composite_tree). resolve={"y": "independent"} renders a dual-axis chart instead: the overlay tree has no per-layer y-scale-slot concept, so it routes through the same merged flat single-panel path (:meth:_build_merged) the interactive output already uses (GH #52) -- one implementation serves both output kinds for independent y.

Returns:

Type Description
str

SVG markup with all layers rendered in a single plot area.

properties

properties(**kwargs)

Forward non-chrome properties(**kwargs) to every layer; store title locally.

LayerChart is a single-plot overlay: it merges its layers into one Chart at render time via :meth:_build_merged, which already applies self._title to the merged chart. Because of that, title must be stored on the LayerChart itself (not fanned to the inner charts), so that:

  • :meth:_figure_title_text (→ _title) returns the correct text for the HTML document <title>.
  • :meth:_build_merged applies the title to the merged chart's on-plot chrome exactly once — inner layers carry no stray title.

Non-chrome kwargs (width, height, ...) are fanned to every layer as usual via the base :meth:_ChartLike.properties implementation.

Parameters:

Name Type Description Default
**kwargs

Same keyword arguments accepted by Chart.properties. title is intercepted here; all other kwargs are forwarded to each layer.

{}

Returns:

Type Description
LayerChart

A new LayerChart instance with _title updated and / or per-layer properties applied.

RepeatChart

Bases: _CompositeBase

Repeat a template chart over a grid of row / column field combinations.

Use Repeat.column, Repeat.row, or Repeat.layer typed sentinels in the template's .encode(...) call to mark which encoding channel receives the per-panel field substitution. RepeatChart.expand() materializes the grid into fully-resolved (row_field, col_field, Chart) tuples.

diagonal= provides an alternate template for panels where row_field == col_field (symmetric n × n repeat). corner=True filters the expanded grid to the lower triangle including the diagonal.

Most users obtain a RepeatChart through Chart.repeat() or ferrum.pairplot.

Parameters:

Name Type Description Default
template Chart

Template chart whose Repeat.* placeholders are substituted per panel.

required
row list of str

Field names assigned to the row axis.

None
column list of str

Field names assigned to the column axis.

None
layer list of str

Field names assigned to the layer axis (for non-grid repeat layouts).

None
diagonal Chart

Alternate template used when row_field == col_field. Requires both row and column to be set.

None
corner bool

When True, only the lower-triangle panels (ri >= ci) are rendered, giving a half-matrix layout.

False
spacing float

Pixel gap between adjacent panels.

10.0
columns int

Maximum number of columns for a wrapped 1-D repeat layout (no-op for 2-D row/column repeat).

None
resolve dict or Resolve

Per-channel scale-sharing overrides — e.g. resolve={"x": "shared", "y": "independent"}. "shared" computes the union domain across all panels (and across every layer of layered panels) and injects an explicit scale on every participating chart so the axis ticks match. "independent" (the default for unlisted channels) keeps per-panel domains. Pass a :class:Resolve to also control figure-level legend resolution for a shared color/size scale, e.g. Resolve(scale={"color": "shared"}, legend={"color": "independent"}).

None

Raises:

Type Description
ValueError

If diagonal is set but row or column is not.

Examples:

>>> import ferrum as fm
>>> base = fm.Chart(df).encode(x=fm.Repeat.column, y=fm.Repeat.row).mark_point()
>>> grid = fm.RepeatChart(base, row=["mpg", "hp"], column=["mpg", "hp"])
>>> grid.save("pair_grid.svg")

charts property

charts: list

List of Chart : Template plus diagonal (when set), in init order.

spec property

spec: dict

Dict : Serializable layout introspection (ferrum-spec §3.12 contract).

Embedded charts round-trip through ChartSpec.from_json. Purely an introspection/serialization surface — rendering goes through the composite spec tree (:meth:_composite_tree), not this dict.

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

expand

expand() -> list

Materialize the template into fully-resolved chart panels.

Panel iteration shape:

  • 2-D grid (both row and column set): len(row) × len(column) panels, optionally filtered by corner; diagonal substitutes the template on row_field == col_field panels.
  • 1-D wrap (only one of row or column set): the populated field list, paired with None on the missing axis. Geometry is applied by :meth:to_svg driven by columns.
  • Layer-only (layer= set, row and column both None): a single panel containing all layers.

When layer= is set, each panel becomes a layered Chart with one layer per element in self.layer (substituted into every Repeat.layer placeholder). Diagonal panels skip layering — the diagonal template already defines that panel.

Returns:

Type Description
list of tuple

Each element is (row_field, col_field, Chart) with all Repeat.* placeholders replaced. For 1-D and layer-only layouts the unused axis is None. Panels are returned exactly as materialized — resolve= is NOT applied here. Scale sharing is a render-time concern: :meth:to_svg / :meth:_render_interactive (via :meth:_composite_tree) lower self.resolve onto the composite tree's resolve field, which the Rust resolve pass unions across cells (see :func:_composite_resolve_field). A caller that wants shared panels should render the RepeatChart directly rather than reading scale dicts off expand()'s output.

Raises:

Type Description
ValueError

If diagonal is set but row != column (asymmetric repeat), or if the template references a Repeat.* placeholder for an axis that was not populated.

share_scale

share_scale(**channels)

Share scales across this repeat's panels by merging into resolve=.

Pure sugar for :meth:_ChartLike.share_scaleRepeatChart exposes its resolve field as the public resolve attribute (see the _resolve alias property), so the base implementation's merge logic and _rebuild_with_charts(lambda c: c, resolve=merged) call work unchanged. Both paths store the identical resolve dict, which :meth:_composite_tree lowers onto the composite tree's resolve field at render time (:meth:to_svg / :meth:_render_interactive); the Rust resolve pass then unions the shared channel's domain across every panel (including each layer of layered panels). :meth:expand does NOT apply resolve= — it returns panels un-injected regardless of this setting. Passing the same channel twice with different modes takes the call's value.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent".

{}

Returns:

Type Description
RepeatChart

A new RepeatChart with the merged resolve= config.

to_svg

to_svg() -> str

Render the repeated grid to an SVG string.

Returns:

Type Description
str

SVG markup containing all materialized panel charts in a grid.

Notes

2-D grids (both row and column set) lay out as len(row) × len(column). 1-D layouts (only one axis set) wrap by columns — column-only spreads left-to-right and wraps downward; row-only spreads top-to-bottom in a single column unless columns opens additional columns. When columns is unset the 1-D layout is a single row (column-only) or column (row-only).

Resolve dataclass

Per-channel scale and legend resolution for a composition's resolve=.

Accepted everywhere a composition takes resolve= (HConcatChart, VConcatChart, ConcatChart, RepeatChart, LayerChart, and the hconcat/vconcat/concat/layer sugar) in place of a flat {channel: mode} dict — the flat-dict form remains valid and is equivalent to Resolve(scale=that_dict); both keep meaning scale resolution.

Parameters:

Name Type Description Default
scale dict

Channel name ("x", "y", "color", "size") -> "shared" | "independent". Whether panels share a unioned domain for that channel — the same axis the flat-dict form controls.

None
legend dict

Channel name ("color" or "size" only) -> "shared" | "independent". Whether a composite that shares scale for that channel renders one figure-level legend ("shared") or keeps each participating panel's own legend ("independent"). Absent from legend means "follow the scale mode" for that channel — the default, matching Vega-Lite. A "shared" legend mode requires a "shared" scale mode for the same channel; an unsatisfiable combination raises ValueError at render time rather than silently falling back to per-panel legends. This shared-legend-requires-shared-scale matrix is enforced at render (lowering), not at Resolve/composite construction time — constructing Resolve(scale={"color": "independent"}, legend={"color": "shared"}) succeeds; the mismatch only raises once something renders it.

None

Examples:

>>> import ferrum as fm
>>> fm.HConcatChart([a, b], resolve=fm.Resolve(scale={"color": "shared"}))
>>> # Force per-panel legends even though the color scale is shared:
>>> fm.HConcatChart(
...     [a, b],
...     resolve=fm.Resolve(scale={"color": "shared"}, legend={"color": "independent"}),
... )

VConcatChart

Bases: _CompositeBase

Vertical concatenation of two or more charts.

Each sub-chart retains its own scales, axes, and legend by default. Pass resolve= to unify one or more channels across panels. Construct via the & operator on Chart instances or directly with a list.

Parameters:

Name Type Description Default
charts list of Chart

Sub-charts to stack top-to-bottom.

required
spacing float

Vertical pixel gap between adjacent charts.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides, e.g. {"color": "shared"} (equivalent to Resolve(scale={"color": "shared"})). Pass a :class:Resolve to also control figure-level legend resolution, e.g. Resolve(scale={"color": "shared"}, legend={"color": "independent"}) to keep per-panel legends over a shared color scale. Accepts the same keys and values as ConcatChart(resolve=...).

None

Examples:

>>> import ferrum as fm
>>> stacked = fm.Chart(df).encode(x="hp", y="mpg").mark_point() & fm.Chart(df).encode(x="hp").mark_histogram()
>>> stacked.save("stacked.svg")

configure_axis

configure_axis(*, x: bool = True, y: bool = True, label_angle: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_format: 'str | None' = None, label_format_raw: 'str | None' = None, label_overlap: 'str | None' = None, tick_count: 'int | None' = None, tick_size: 'float | None' = None, tick_values: 'list | None' = None, title_font_size: 'float | None' = None, title_color: 'str | None' = None, title_padding: 'float | None' = None, label_padding: 'float | None' = None, domain: 'bool | None' = None, domain_color: 'str | None' = None, domain_width: 'float | None' = None, grid: 'bool | None' = None, grid_color: 'str | None' = None, grid_dash: 'list[float] | None' = None, grid_width: 'float | None' = None, grid_opacity: 'float | None' = None, domain_min: 'float | None' = None, domain_max: 'float | None' = None, nice: 'bool | None' = None, zero: 'bool | None' = None, translate: 'float | None' = None, min_band: 'float | None' = None, max_band: 'float | None' = None, tick_extra: 'bool | None' = None, tick_min_step: 'float | None' = None, title_orient: 'str | None' = None, zindex: 'int | None' = None, min_extent: object = _MISSING, max_extent: object = _MISSING)

Apply axis configuration.

Parameters:

Name Type Description Default
x bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
y bool

Deprecated and has no effect. Use Chart.axis(x=False) / Chart.axis(y=False) to show or hide an axis.

True
label_angle float

Tick label rotation in degrees.

None
label_font_size float

Tick label font size in pixels.

None
label_color str

Tick label color.

None
label_format str

Named format preset (e.g. "currency", "percent").

None
label_format_raw str

Raw d3-format string (e.g. ".2f", "~s"); overrides label_format when both are given.

None
label_overlap str

Overlap-handling strategy for crowded tick labels (e.g. "parity", "greedy").

None
tick_count int

Target number of ticks on the axis.

None
tick_size float

Tick mark length in pixels.

None
tick_values list

Explicit tick positions, overriding automatic tick selection.

None
title_font_size float

Axis title font size in pixels.

None
title_color str

Axis title color.

None
title_padding float

Gap between the axis title and its labels in pixels.

None
label_padding float

Gap between tick labels and the axis line in pixels.

None
domain bool

Whether to draw the axis domain (baseline) line.

None
domain_color str

Domain line color.

None
domain_width float

Domain line width in pixels.

None
grid bool

Whether to draw grid lines for this axis.

None
grid_color str

Grid line color.

None
grid_dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
grid_width float

Grid line width in pixels.

None
grid_opacity float

Grid line opacity (0--1).

None
domain_min float

Explicit scale domain bounds.

None
domain_max float

Explicit scale domain bounds.

None
nice bool

Extend the domain to nice round numbers.

None
zero bool

Include zero in the scale domain.

None
translate float

Pixel translation of the axis group perpendicular to its line.

None
min_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
max_band float

Lower / upper bounds for the reserved axis margin band, in pixels.

.. deprecated:: 0.17.0 min_extent= and max_extent= are accepted as aliases but are deprecated; use min_band= / max_band= instead.

None
tick_extra bool

Append an extra tick at each domain boundary.

None
tick_min_step float

Minimum step between ticks in data space.

None
title_orient str

Side/orientation of the axis title.

None
zindex int

Coarse draw order of the axis relative to marks.

None

Returns:

Type Description
Self
Notes

orient (the axis side) is intentionally absent here: configure_axis applies to both the x and y axes, so a single side value can be valid for at most one of them. Set it per-axis instead, via configure(axis_x=AxisConfig(orient="top")) / configure(axis_y=AxisConfig(orient="right")) or per-channel fm.X("f", axis=fm.Axis(orient="top")).

configure_legend

configure_legend(*, orient: 'str | None' = None, direction: 'str | None' = None, columns: 'int | None' = None, title_font_size: 'float | None' = None, label_font_size: 'float | None' = None, label_color: 'str | None' = None, label_limit: 'float | None' = None, symbol_size: 'float | None' = None, symbol_stroke_width: 'float | None' = None, symbol_type: 'str | None' = None, gradient_length: 'float | None' = None, gradient_thickness: 'float | None' = None, title_padding: 'float | None' = None, row_padding: 'float | None' = None, column_padding: 'float | None' = None, clip_height: 'float | None' = None, tick_min_step: 'float | None' = None, offset: 'float | None' = None, padding: 'float | None' = None, zindex: 'int | None' = None)

Apply legend configuration.

Parameters:

Name Type Description Default
orient str

Legend position: "right", "left", "top", "bottom", "none".

None
direction str

Layout direction: "vertical" or "horizontal".

None
columns int

Number of columns for multi-column layout.

None
title_font_size float

Legend title font size in pixels.

None
label_font_size float

Legend entry label font size in pixels.

None
label_color str

Legend label color.

None
label_limit float

Maximum legend-label width in pixels; wider labels are truncated with an ellipsis.

None
symbol_size float

Legend symbol size in pixels.

None
symbol_stroke_width float

Stroke width of legend symbol swatches in pixels.

None
symbol_type str

Legend symbol shape (e.g. "circle", "square").

None
gradient_length float

Length of the continuous-legend gradient bar in pixels.

None
gradient_thickness float

Thickness of the continuous-legend gradient bar in pixels.

None
title_padding float

Padding between the legend title and its entries in pixels.

None
row_padding float

Vertical entry spacing in pixels (vertical-direction legends).

None
column_padding float

Horizontal entry spacing in pixels (horizontal-direction legends).

None
clip_height float

Cap on the legend group height in pixels; overflow is hard-clipped.

None
tick_min_step float

Minimum step between colorbar ticks in data units.

None
offset float

Legend offset from the plot edge in pixels.

None
padding float

Padding inside the legend box in pixels.

None
zindex int

Coarse draw order of the legend relative to marks.

None

Returns:

Type Description
Self

configure_title

configure_title(*, font_size: 'float | None' = None, font_weight: 'str | None' = None, anchor: 'str | None' = None, color: 'str | None' = None, offset: 'float | None' = None, subtitle_font_size: 'float | None' = None, subtitle_color: 'str | None' = None)

Apply title configuration.

Parameters:

Name Type Description Default
font_size float

Title font size in pixels.

None
font_weight str

Title font weight (e.g. "normal", "bold").

None
anchor str

Title alignment: "start", "middle", or "end".

None
color str

Title text color.

None
offset float

Title offset from the plot in pixels.

None
subtitle_font_size float

Subtitle font size in pixels.

None
subtitle_color str

Subtitle text color.

None

Returns:

Type Description
Self

configure_grid

configure_grid(*, x: 'bool | None' = None, y: 'bool | None' = None, color: 'str | None' = None, width: 'float | None' = None, dash: 'list[float] | None' = None, opacity: 'float | None' = None, band_colors: 'list[str] | None' = None)

Apply grid configuration.

Parameters:

Name Type Description Default
x bool

Enable/disable grid on each axis.

None
y bool

Enable/disable grid on each axis.

None
color str

Grid line color.

None
width float

Grid line width in pixels.

None
dash list[float]

Grid line dash pattern (on/off pixel lengths).

None
opacity float

Grid line opacity (0--1).

None
band_colors list[str]

Alternating band fill colors (None to disable).

None

Returns:

Type Description
Self

configure_padding

configure_padding(*, top: 'float | None' = None, right: 'float | None' = None, bottom: 'float | None' = None, left: 'float | None' = None, auto: bool = True)

Apply padding configuration.

Parameters:

Name Type Description Default
top float

Minimum padding in pixels per side.

None
right float

Minimum padding in pixels per side.

None
bottom float

Minimum padding in pixels per side.

None
left float

Minimum padding in pixels per side.

None
auto bool

Auto-expand margins to fit labels.

True

Returns:

Type Description
Self

configure_color

configure_color(*, scheme: 'str | None' = None, sequential_scheme: 'str | None' = None, diverging_scheme: 'str | None' = None, domain: 'list | None' = None, range: 'list[str] | None' = None)

Apply color scale configuration.

Parameters:

Name Type Description Default
scheme str

Categorical color scheme name.

None
sequential_scheme str

Sequential color scheme name.

None
diverging_scheme str

Diverging color scheme name.

None
domain list

Explicit color-scale domain values.

None
range list[str]

Explicit color range, overriding the scheme.

None

Returns:

Type Description
Self

configure

configure(*, axis: 'AxisConfig | None' = None, axis_x: 'AxisConfig | None' = None, axis_y: 'AxisConfig | None' = None, axis_y2: 'AxisConfig | None' = None, legend: 'LegendConfig | None' = None, title: 'TitleConfig | None' = None, grid: 'GridConfig | None' = None, padding: 'PaddingConfig | None' = None, color: 'ColorConfig | None' = None)

Append a :class:~ferrum.configure.Configure layer.

Accepts typed config objects for each domain. All parameters are keyword-only and default to None (no change for that domain).

Parameters:

Name Type Description Default
axis AxisConfig

Applies to all axes.

None
axis_x AxisConfig

Applies only to the x axis.

None
axis_y AxisConfig

Applies only to the y axis.

None
axis_y2 AxisConfig

Applies only to the secondary y axis.

None
legend LegendConfig

Legend appearance.

None
title TitleConfig

Chart title appearance.

None
grid GridConfig

Grid line appearance.

None
padding PaddingConfig

Plot-area padding.

None
color ColorConfig

Default color scale settings.

None

Returns:

Type Description
Self

New instance with the configure layer appended.

Examples:

>>> from ferrum.configure import AxisConfig, LegendConfig
>>> chart.configure(
...     axis=AxisConfig(label_angle=-45),
...     legend=LegendConfig(orient="bottom"),
... )

to_svg

to_svg() -> str

Render the concatenated charts to an SVG string.

Routes HConcat/VConcat/ConcatChart through the one-call Rust composite entry (render_composite_svg); see :func:_lower_composite.

interactive

interactive(*, toolbar: bool = True)

Return an interactive rendering of this composition.

Parameters:

Name Type Description Default
toolbar bool

Whether to show the interactive toolbar (zoom/pan controls, export button). Set to False to render without the toolbar.

True

Returns:

Type Description
InteractiveChart

An interactive widget/container backed by the WASM renderer.

show

show() -> None

Print the SVG markup to stdout.

to_png

to_png(*, scale: float = 2.0) -> bytes

Return the composition rendered as PNG bytes.

This returns the PNG-encoded image data; it does not display the composition. Rasterises the SVG produced by :meth:to_svg through the Rust resvg pipeline — the same rasteriser Chart.to_png() uses.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions. 2.0 (the default) produces a retina-quality image. 1.0 renders at 1:1 resolution.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes suitable for IPython.display.Image or writing directly to disk.

to_html

to_html(*, embed_wasm: bool = True, toolbar: bool = True, csp_nonce: str | None = None) -> str

Return the composition as a self-contained interactive HTML document.

This returns the HTML markup; it does not display the composition or write it to disk. The returned string is byte-identical to what save(path) writes for an .html destination — it embeds the WASM-backed interactive renderer rather than a static SVG snapshot. Because it bundles that renderer, the document is substantially larger than a static export; for a lightweight static image use :meth:to_svg / :meth:to_png.

Routes through the shared :func:ferrum.display.html_string helper, so the HTML assembly and tab-title resolution are identical to a plain Chart. It does not construct a live InteractiveChart widget, so headless HTML export works without anywidget installed.

Parameters:

Name Type Description Default
embed_wasm bool

When True, the WASM binary is base64-inlined for single-file distribution. When False, the document references an adjacent ferrum_wasm_bg.wasm sidecar that must be served alongside it.

True
toolbar bool

When False, the interactive toolbar (zoom / pan controls, export button) is hidden in the rendered HTML.

True
csp_nonce str

When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Returns:

Type Description
str

A complete, self-contained interactive HTML document.

show_svg

show_svg() -> str

Render the composition to an SVG string.

.. deprecated:: 0.16.0 Use :meth:to_svg instead. show_svg will be removed in a future release. It now forwards to :meth:to_svg.

Returns:

Type Description
str

SVG markup for the composition.

show_png

show_png(*, scale: float = 2.0) -> bytes

Render the composition to PNG bytes.

.. deprecated:: 0.16.0 Use :meth:to_png instead. show_png will be removed in a future release. It now forwards to :meth:to_png.

Parameters:

Name Type Description Default
scale float

Pixel-density multiplier applied to the SVG's intrinsic dimensions.

2.0

Returns:

Type Description
bytes

PNG image as raw bytes.

save

save(path: str, *, format=None, scale: float = 2.0, toolbar: bool = True, embed_wasm: bool = True, csp_nonce: str | None = None) -> None

Save the composition to a file.

Routes through :func:ferrum.display.save_chart — the single save-format router shared with Chart.save — so the supported format table (svg / png / html / json / pdf) and the HTML / title resolution are identical across chart and composite.

Parameters:

Name Type Description Default
path str

Destination file path. The extension determines the format when format is omitted.

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

Explicit format override. Other formats raise ValueError.

"svg"
scale float

Pixel-density multiplier for PNG and PDF output. Has no effect on SVG, HTML, or JSON exports.

2.0
toolbar bool

Whether to include the interactive toolbar (zoom/pan controls, export button) when saving as HTML. Has no effect on SVG, PNG, JSON, or PDF exports.

True
embed_wasm bool

For "html" format only. When True, the WASM binary is base64-inlined for single-file distribution. When False, an adjacent ferrum_wasm_bg.wasm sidecar is written alongside.

True
csp_nonce str

For "html" format only. When provided, both the <style> and <script type="module"> tags receive a nonce="..." attribute so they pass strict Content-Security-Policy headers.

None

Raises:

Type Description
ValueError

If format (or the path extension) is not a recognised export format.

share_scale

share_scale(**channels)

Merge channels into this composition's resolve= scale field.

Pure sugar for constructing the same composition with the merged scale-mode dict — resolution happens at render time through the composite tree, the same Rust resolve pass (:func:_composite_resolve_field) that resolve= at construction already uses. No scale= domain dict is computed or injected here, and a "shared" union runs over transform-aware chart extents (e.g. a box mark's whisker reach, a KDE's density support), not raw column min/max — see :func:compute_union_domain for the one remaining raw-column injection seam (:meth:LayerChart._build_merged, the interactive one-panel path; GH #52). **channels only ever touches scale resolution; when the existing resolve= is a :class:Resolve with a legend field set, that legend field carries through unchanged onto the rebuilt composition. The merged result is always stored as a :class:Resolve (never the flat-dict form), even when no legend override is present -- a stable _resolve type after every share_scale call. This has no effect on rendering: the flat-dict form and Resolve(scale=that_dict) lower to identical wire output (byte-identical SVG).

A child whose channel carries an explicit scale= (e.g. fm.Y("y", scale={"domain": [0, 200]})) is EXCLUDED from the shared union and keeps its pinned domain -- an explicit per-chart scale always wins over composition-level sharing (spec §6). The remaining children still share among themselves; with only one unpinned child left, its "union" is simply its own domain.

Parameters:

Name Type Description Default
**channels str

Channel name → "shared" | "independent". Common channels: x, y, color, size.

{}

Returns:

Type Description
_ChartLike

A new composition of the same type with the merged resolve= field. No-op (returns self) when no channel is given.

Raises:

Type Description
ValueError

If any value is not "shared" or "independent", or if this composition has no resolve= field to merge into (JointChart/ClusterMapChart: their marginal/dendrogram alignment is fixed layout geometry, not a resolve= channel).

Examples:

>>> import ferrum as fm
>>> combined = (chart_a | chart_b).share_scale(x="shared")
>>> grid = fm.HConcatChart([chart_a, chart_b], resolve={"x": "shared"})
>>> combined.to_svg() == grid.to_svg()
True

theme

theme(t)

Apply a theme to every sub-chart and return a new composition.

Parameters:

Name Type Description Default
t Theme

Theme value to apply.

required

Returns:

Type Description
_ChartLike

A new instance of the same composition class with t applied to each sub-chart.

properties

properties(**kwargs)

Set figure-level or per-child chart properties.

The keyword arguments title, subtitle, and caption are intercepted and stored at the figure level — they render once around the whole composed figure and are never fanned to individual child panels. All other keyword arguments (e.g. width, height) are forwarded to each child via Chart.properties.

Parameters:

Name Type Description Default
title str

Figure-level title rendered above all panels.

required
subtitle str

Figure-level subtitle rendered below the title, above all panels.

required
caption str

Figure-level caption rendered below all panels.

required
**kwargs

Additional keyword arguments forwarded to Chart.properties for every child chart (e.g. width, height).

{}

Returns:

Type Description
_CompositeBase

A new instance of the same composition class with the figure chrome stored and / or child properties updated.

concat

concat(*charts, columns=None, spacing=10.0, resolve=None)

Wrapping concatenation of charts in a grid.

Parameters:

Name Type Description Default
*charts Chart or _ChartLike

Charts to arrange in a wrapping grid.

()
columns int

Maximum number of columns before wrapping. Defaults to len(charts) (single row).

None
spacing float

Pixel gap between adjacent cells.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides. Pass a :class:Resolve to also control figure-level legend resolution for a shared channel.

None

Returns:

Type Description
ConcatChart

Examples:

>>> import ferrum as fm
>>> charts = [fm.Chart(df).mark_point().encode(x=c, y="y") for c in cols]
>>> fm.concat(*charts, columns=2)

hconcat

hconcat(*charts, spacing=10.0, resolve=None)

Horizontal concatenation of charts.

Parameters:

Name Type Description Default
*charts Chart or _ChartLike

Two or more charts to place side-by-side.

()
spacing float

Pixel gap between adjacent charts.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides, e.g. {"color": "shared"}. Pass a :class:Resolve to also control figure-level legend resolution for a shared channel.

None

Returns:

Type Description
HConcatChart

Examples:

>>> import ferrum as fm
>>> left = fm.Chart(df).mark_point().encode(x="x", y="y")
>>> right = fm.Chart(df).mark_bar().encode(x="category", y="count")
>>> fm.hconcat(left, right)

vconcat

vconcat(*charts, spacing=10.0, resolve=None)

Vertical concatenation of charts.

Parameters:

Name Type Description Default
*charts Chart or _ChartLike

Two or more charts to stack top-to-bottom.

()
spacing float

Pixel gap between adjacent charts.

10.0
resolve dict or Resolve

Per-channel scale-sharing overrides, e.g. {"color": "shared"}. Pass a :class:Resolve to also control figure-level legend resolution for a shared channel.

None

Returns:

Type Description
VConcatChart

Examples:

>>> import ferrum as fm
>>> top = fm.Chart(df).mark_point().encode(x="x", y="y")
>>> bottom = fm.Chart(df).mark_line().encode(x="time", y="value")
>>> fm.vconcat(top, bottom)