ezmsg.tools.plot.layout#
Turning a structured ch coordinate axis into a per-channel grid layout.
The geometry counterpart to ezmsg.tools.chmeta, which does the same job
for names. An AxisArray’s ch axis may carry electrode coordinates; a grid
plot wants positions, sizes and labels. Which fields those live in is a
property of the acquisition system, so the decoding belongs here rather than in
phosphor, whose grids take plain arrays and have no opinion about where they
came from.
Everything degrades: a source with no ch axis at all, or one carrying names
but no coordinates, still gets a layout – a square-ish tiling – because a plot
that draws nothing is less useful than one that draws the right number of cells
in the wrong places.
Functions
- channel_layout(ch_axis_data, n_ch, *, position_fields=('x', 'y'), size_field='size', group_field='headstage', label_fields=('label',))[source]#
Per-channel
(positions, sizes, labels)for a grid plot.- Parameters:
ch_axis_data (ndarray | None) – The
chaxis’ structured data, orNonewhen the stream carries no channel metadata.n_ch (int) – Channels in the data, used when the axis cannot say.
position_fields (Tuple[str, str]) – Fields holding each channel’s coordinates. Both must be present, or the layout falls back to a tiling.
size_field (str) – Field holding each channel’s extent. Absent gives
None, which lets the renderer size cells by the inferred pitch.group_field (str | None) – Field identifying which device a channel belongs to. Devices commonly number their electrodes from a shared origin, so without this two of them draw on top of each other.
Noneskips the check.label_fields (Sequence[str]) – Passed to
channel_names().
- Returns:
positionsas(n, 2)float32,sizesas(n,)float32 orNone, and one label per channel.- Return type:
Classes
- class ChannelLayoutCache[source]#
Bases:
objectchannel_layout(), recomputed only when the axis actually changes.A grid that derives its layout per message pays for it per message, while the answer changes about once a session. Fingerprinting the axis costs around 1 us against the 75 us the derivation takes, so this is worth having wherever messages arrive faster than the geometry does.
Deliberately a cache rather than a shared instance: two widgets watching one stream each keep their own, so neither has to know the other exists, and the derivation stays where any application can call it.
- class ChannelLayoutCache[source]#
Bases:
objectchannel_layout(), recomputed only when the axis actually changes.A grid that derives its layout per message pays for it per message, while the answer changes about once a session. Fingerprinting the axis costs around 1 us against the 75 us the derivation takes, so this is worth having wherever messages arrive faster than the geometry does.
Deliberately a cache rather than a shared instance: two widgets watching one stream each keep their own, so neither has to know the other exists, and the derivation stays where any application can call it.
- channel_layout(ch_axis_data, n_ch, *, position_fields=('x', 'y'), size_field='size', group_field='headstage', label_fields=('label',))[source]#
Per-channel
(positions, sizes, labels)for a grid plot.- Parameters:
ch_axis_data (ndarray | None) – The
chaxis’ structured data, orNonewhen the stream carries no channel metadata.n_ch (int) – Channels in the data, used when the axis cannot say.
position_fields (Tuple[str, str]) – Fields holding each channel’s coordinates. Both must be present, or the layout falls back to a tiling.
size_field (str) – Field holding each channel’s extent. Absent gives
None, which lets the renderer size cells by the inferred pitch.group_field (str | None) – Field identifying which device a channel belongs to. Devices commonly number their electrodes from a shared origin, so without this two of them draw on top of each other.
Noneskips the check.label_fields (Sequence[str]) – Passed to
channel_names().
- Returns:
positionsas(n, 2)float32,sizesas(n,)float32 orNone, and one label per channel.- Return type: