Skip to content

ferrum.selection

Interactive selection declarations and conditional encoding builders.

Selection API for interactive charts (Phase 11c).

Constructors

selection_point — point selection (click on marks) selection_interval — interval selection (drag to brush) selection_single — point selection with toggle=False selection_multi — point selection with toggle="event.shiftKey"

Classes:

Name Description
Selection — immutable selection descriptor, with .when
SelectionMark — visual style for interval selection brush

SelectionMark dataclass

Visual style for the interval selection brush rectangle.

Pass an instance to selection_interval(mark=...) to override the default brush appearance.

Parameters:

Name Type Description Default
fill str

Hex colour string for the brush fill (e.g. "#4287f5"). Defaults to the renderer's built-in blue.

None
stroke str

Hex colour string for the brush border. Defaults to the renderer's built-in grey.

None
fill_opacity float

Opacity of the fill (0.0 = transparent, 1.0 = opaque).

0.3
stroke_opacity float

Opacity of the border.

1.0
stroke_width float

Border line width in pixels.

1.0
stroke_dash list of float

Dash pattern for the border (e.g. [4, 2]). Solid when omitted.

None

Examples:

>>> import ferrum as fm
>>> brush_style = fm.SelectionMark(fill="#ff9900", fill_opacity=0.2, stroke_dash=[4, 2])
>>> brush = fm.selection_interval(mark=brush_style)

to_spec_dict

to_spec_dict() -> dict

Serialize to a dict matching the Rust SelectionMarkStyle shape.

Selection dataclass

Immutable selection descriptor.

Created by selection_point(), selection_interval(), selection_single(), or selection_multi() — do not construct directly.

Attributes:

Name Type Description
name str

Stable identifier used to link this selection to conditional encodings and to the WASM renderer.

kind {'point', 'interval'}

Selection type.

params dict

Resolved parameters forwarded to the Rust SelectionSpec.

Examples:

Build a conditional encoding from a selection:

>>> import ferrum as fm
>>> sel = fm.selection_point()
>>> color_enc = sel.when(fm.Color("category")).otherwise(fm.value("#cccccc"))
>>> fm.Chart(df).mark_point().encode(
...     x=fm.X("x"), y=fm.Y("y"), color=color_enc
... ).add_selection(sel)

when

when(if_encoding: Any) -> _SelectionCondition

Start a conditional encoding: sel.when(Color("x")).otherwise(value("#ccc")).

to_spec_dict

to_spec_dict() -> dict

Serialize to a dict matching the Rust SelectionSpec shape.

ConditionalSpec dataclass

Resolved conditional encoding — produced by sel.when(...).otherwise(...).

Do not construct directly. Build one through the selection fluent API::

sel.when(<if_encoding>).otherwise(<else_encoding>)

Attributes:

Name Type Description
selection_name str

Name of the Selection that drives the condition.

if_selected encoding channel or value(...)

Encoding applied when a datum falls inside the selection.

if_not encoding channel or value(...)

Encoding applied when a datum falls outside the selection.

Examples:

>>> import ferrum as fm
>>> sel = fm.selection_point()
>>> cond = sel.when(fm.Color("category")).otherwise(fm.value("#cccccc"))
>>> type(cond).__name__
'ConditionalSpec'

to_spec_dict

to_spec_dict() -> dict

Serialize to a dict matching the Rust ConditionalEncoding shape.

selection_point

selection_point(*, fields: list[str] | None = None, encodings: list[str] | None = None, nearest: bool = False, toggle: str = 'event.shiftKey', on: str = 'click', clear: str = 'mouseout', resolve: Literal['global', 'union', 'intersect'] = 'global', name: str | None = None) -> Selection

Create a point selection activated by clicking on marks.

A point selection highlights individual marks. Shift-click adds to the selection by default (toggle="event.shiftKey"). Use selection_single to disable toggle, or selection_multi to keep the shift-click default explicitly.

Parameters:

Name Type Description Default
fields list of str

Data fields to project the selection onto. When omitted the selection binds to all fields.

None
encodings list of str

Encoding channels to project onto (e.g. ["x", "color"]).

None
nearest bool

When True, clicking between marks selects the nearest one.

False
toggle str

JavaScript event expression controlling when clicking adds to the selection instead of replacing it. Pass "false" to disable toggling (see also selection_single).

"event.shiftKey"
on str

Event that triggers the selection (e.g. "mouseover").

"click"
clear str

Event that clears the selection.

"mouseout"
resolve ('global', 'union', 'intersect')

How to resolve this selection when the chart is faceted.

"global"
name str

Stable identifier for the selection. Auto-generated when omitted.

None

Returns:

Type Description
Selection

Immutable selection descriptor. Pass to Chart.add_selection() and use sel.when(...).otherwise(...) to build conditional encodings.

Examples:

Highlight selected marks by colour:

>>> import ferrum as fm
>>> sel = fm.selection_point()
>>> fm.Chart(df).mark_point().encode(
...     x=fm.X("x"), y=fm.Y("y"),
...     color=sel.when(fm.Color("category")).otherwise(fm.value("#cccccc")),
... ).add_selection(sel)

Nearest-mark selection on mouse-over:

>>> sel = fm.selection_point(nearest=True, on="mouseover", clear="mouseout")

selection_interval

selection_interval(*, fields: list[str] | None = None, encodings: list[str] | None = None, translate: bool = True, zoom: bool = True, mark: SelectionMark | None = None, resolve: Literal['global', 'union', 'intersect'] = 'global', name: str | None = None) -> Selection

Create an interval (brush) selection activated by dragging.

An interval selection lets the user drag a rectangular brush over the chart. All marks inside the brush are considered selected. The brush supports panning (translate=True) and scroll-to-zoom (zoom=True) after it is drawn.

Parameters:

Name Type Description Default
fields list of str

Data fields to project the brush onto. When omitted the brush applies to all fields represented by the brushed encodings.

None
encodings list of str

Encoding channels to constrain the brush to (e.g. ["x"] for a 1-D horizontal brush).

None
translate bool

Allow the user to reposition the brush by dragging inside it.

True
zoom bool

Allow the user to scroll inside the brush to zoom the view.

True
mark SelectionMark

Visual style of the brush rectangle. Defaults to a semi-transparent blue fill with a solid grey border.

None
resolve ('global', 'union', 'intersect')

How to resolve this selection when the chart is faceted.

"global"
name str

Stable identifier for the selection. Auto-generated when omitted.

None

Returns:

Type Description
Selection

Immutable selection descriptor. Pass to Chart.add_selection() and use sel.when(...).otherwise(...) to build conditional encodings.

Examples:

Brush that greys out unselected points:

>>> import ferrum as fm
>>> brush = fm.selection_interval()
>>> fm.Chart(df).mark_point().encode(
...     x=fm.X("x"), y=fm.Y("y"),
...     color=brush.when(fm.Color("category")).otherwise(fm.value("#cccccc")),
... ).add_selection(brush)

Horizontal-only brush:

>>> brush = fm.selection_interval(encodings=["x"])

Custom brush style:

>>> brush = fm.selection_interval(
...     mark=fm.SelectionMark(fill="#4287f5", fill_opacity=0.2, stroke_dash=[4, 2])
... )

value

value(v: Any) -> '_LiteralValue'

Wrap a literal value for use in conditional encodings.

Returns an opaque literal wrapper that can be passed as the if_selected or if_not argument of sel.when(...).otherwise(...) when a constant (rather than a field mapping) is needed.

Parameters:

Name Type Description Default
v str, int, or float

The constant to embed. Hex colour strings (e.g. "#cccccc") are interpreted as colours. Numbers are interpreted as opacity values.

required

Returns:

Type Description
_LiteralValue

Opaque wrapper consumed by ConditionalSpec.

Examples:

Grey-out unselected marks:

>>> import ferrum as fm
>>> sel = fm.selection_point()
>>> fm.Chart(df).mark_point().encode(
...     x=fm.X("x"), y=fm.Y("y"),
...     color=sel.when(fm.Color("category")).otherwise(fm.value("#cccccc")),
... ).add_selection(sel)

Fade unselected marks with low opacity:

>>> color=sel.when(fm.Color("category")).otherwise(fm.value(0.1))