ezmsg.tools.plot#

Putting ezmsg streams onto phosphor plots.

describe is the pure half – given dims, axes and attrs, work out what is being plotted – and imports neither Qt nor phosphor, so it is usable from a topic subscriber, a shared-memory mirror, or a test with neither. shmem_sweep is the Qt widget built on it, and needs the viewer or sigmon extra.

ShmemSweepWidget and layout are resolved lazily so that importing this package, or anything under it, does not pull in Qt. Eagerly importing it here would make from ezmsg.tools.plot.describe import ... fail without phosphor installed, since importing a submodule runs its parent’s __init__ first – which would put a GPU stack behind a module that deliberately has no rendering dependency at all.

class MetricSpec(axis, labels, kind)[source]#

Bases: NamedTuple

A trailing per-sample tuple: what it is called and what it holds.

Parameters:
axis: str#

Name of the trailing axis.

labels: tuple[str, ...]#

Its coordinate values, lowercased, in order.

kind: str#

The entry in METRIC_KINDS these labels matched.

class StreamShape(n_channels, srate, channel_labels, metric, unit)[source]#

Bases: NamedTuple

What a plot needs to know about an incoming stream.

Parameters:
n_channels: int#

Channels, excluding any envelope axis.

srate: float#

Samples per second of the pushed stream. For an envelope this is the bucket rate, not the rate before decimation – which is what a sweep buffer must be sized with, or its ring is longer than the data arriving to fill it.

channel_labels: list[str] | None#

One name per channel, or None if the stream does not say.

metric: MetricSpec | None#

The trailing per-sample tuple, if the stream carries one.

unit: str | None#

The signal’s amplitude unit, if it declares one.

property envelope: bool#

Whether each sample carries a (min, max) pair – phosphor’s envelope.

exception UnsupportedMetricError[source]#

Bases: NotImplementedError

A recognised metric axis that no renderer here can draw yet.

describe_axisarray(msg, *, time_axis='time', label_fields=('label',))[source]#

Describe a stream from one of its AxisArray messages.

Parameters:
Return type:

StreamShape

describe_mirror(mirror, *, time_axis='time', label_fields=('label',))[source]#

Describe a stream from a connected EZShmMirror.

Returns None until the writer has published both a valid buffer header and its metadata – the two arrive independently, and a description built from only one of them would be missing either the shape or the names.

Parameters:
Return type:

StreamShape | None

flatten_for_plot(data, shape)[source]#

Reshape a block to what a plot’s push_data expects.

(n_samples, n_channels, k) when the stream carries a k-wide metric tuple, (n_samples, n_channels) otherwise, with any other dimensions folded into channels.

The metric case is the reason this exists. Folding a (time, ch, 2) block into (time, ch * 2) – which is what a naive reshape does – renders as twice as many traces, alternating the two metrics, with every channel label off by a factor of two. It looks like data, so nothing complains.

Parameters:
Return type:

ndarray

metric_axis(dims, axes)[source]#

Describe the trailing per-sample tuple, or None if there is not one.

Recognised by labels, not by name or width. The name only narrows the search; the labels are what distinguish a (min, max) envelope from a (mean, std) dispersion pair, which is the same shape and must not be drawn the same way.

Returns a spec for any tuple in METRIC_KINDS, including ones no renderer here supports yet – describing a stream is not the same as being able to draw it, and a caller that only wants to know what arrived should not have to catch an exception. See require_sweep_renderable() for the capability check.

Parameters:
Return type:

MetricSpec | None

require_sweep_renderable(shape)[source]#

Raise if a sweep plot cannot draw this stream’s metric axis.

Raises:

UnsupportedMetricError – for a recognised metric a sweep cannot draw.

Parameters:

shape (StreamShape)

Return type:

None

Modules

describe

Reading a stream's shape well enough to plot it.

layout

Turning a structured ch coordinate axis into a per-channel grid layout.