Skip to content

redsun.utils

Helpers parsing bluesky descriptor and reading keys.

Key format

Keys follow the ophyd-async child naming convention:

    {name}-{property}

where:

  • name is the runtime device instance name;
  • property is the individual setting name.

parse_key

parse_key(key: str) -> tuple[str, str]

Split a key of the form {name}-{property_name} into (name, property_name).

Raises:

Type Description
ValueError

If the key does not conform to the expected format.

parse_map_key

parse_map_key(
    input: str, map_prefix: str
) -> tuple[str, str, str]

Split a descriptor or reading key of a DeviceMap into its parts.

Returns (name, map_key, key): the device name (before the first hyphen), the map key (between the first and second hyphens) and the property key (after the second hyphen).

Parameters:

Name Type Description Default
input str

The key to parse, in the form {name}-{map_prefix}-{property}.

required
map_prefix str

The prefix used in the key to identify the map (e.g. "axis").

required

Raises:

Type Description
ValueError

If input has fewer than three parts, or its second part is not map_prefix.

What a device offers to be moved and set: its axes, limits and configuration.

These read an ophyd-async device through the protocols it implements, never through attribute names, so they apply to any device.

Axis

Bases: AsyncLocatable[float], Subscribable[float], Protocol

Something set moves, locate reports and subscribe_reading follows.

set returns an ophyd-async status, which the positioner waits on and cancels to stop the move. Checking an object against this protocol at run time finds the methods only, not what set returns.

set

set(
    value: float,
) -> AsyncStatus[Any] | WatchableAsyncStatus[float]

Start a move to value, which is passed by position.

An axis may name the parameter as it likes, new_position for an ophyd-async StandardMovable.

AxisInfo dataclass

AxisInfo(
    readback: Readback,
    stoppable: bool = False,
    key: str | None = None,
    configuration: tuple[str, ...] = (),
    path: DevicePath | None = None,
)

What a view shows of an axis before its next readback arrives.

readback instance-attribute

readback: Readback

Position when the axis was described, with its units, precision and limits.

stoppable class-attribute instance-attribute

stoppable: bool = False

Whether the axis can be stopped, by itself or through its device.

key class-attribute instance-attribute

key: str | None = None

Data key of the readback in the readings the axis reports.

configuration class-attribute instance-attribute

configuration: tuple[str, ...] = ()

Keys of the axis' configuration entries.

path class-attribute instance-attribute

path: DevicePath | None = None

Where the axis sits in its tree; None when not known.

Configuration dataclass

Configuration(
    descriptors: dict[str, DataKey],
    readings: dict[str, Reading[Any]],
    writable: dict[str, SignalRW[Any]],
    owners: dict[str, str] = dict(),
    paths: dict[str, DevicePath] = dict(),
)

A device's configuration, and which of its signals can be written.

descriptors instance-attribute

descriptors: dict[str, DataKey]

Descriptors by key; a read-only entry has :readonly appended to its source.

readings instance-attribute

readings: dict[str, Reading[Any]]

Readings by key.

writable instance-attribute

writable: dict[str, SignalRW[Any]]

The writable signals among them, by key.

owners class-attribute instance-attribute

owners: dict[str, str] = field(default_factory=dict)

Name of the device each key belongs to; empty when not known.

paths class-attribute instance-attribute

paths: dict[str, DevicePath] = field(default_factory=dict)

Where the signal behind each key, and each owner, sit in their tree, by name.

Empty when not known.

DevicePath

Bases: NamedTuple

Where a device sits in its tree.

root instance-attribute

root: str

Name of the device the keys start from: the top of the tree, or the highest device below a parent that does not list it among its children.

keys instance-attribute

keys: tuple[str, ...]

Key of each device below the root, down to this one; empty for the root.

names instance-attribute

names: tuple[str, ...]

Names of the device at the top of the tree and of every device down to this one, in order.

path property

path: str

The keys joined by dots, such as xy.x; empty for the root.

parent property

parent: DevicePath | None

Where the device's parent sits; None for a root.

Light

Bases: Protocol

A light source that can be switched on and off.

enabled property

enabled: SignalRW[bool]

On when True.

DimmableLight

Bases: Light, Protocol

A light whose intensity can also be set.

intensity property

intensity: SignalRW[float]

How bright the light is, in the units its descriptor gives.

LightInfo dataclass

LightInfo(
    enabled: bool,
    intensity: Readback | None = None,
    path: DevicePath | None = None,
)

What a view shows of a light before its next readback arrives.

enabled instance-attribute

enabled: bool

Whether the light was on when described.

intensity class-attribute instance-attribute

intensity: Readback | None = None

Intensity when described, with its units, precision and limits; None for a light that has none.

path class-attribute instance-attribute

path: DevicePath | None = None

Where the light sits in its tree; None when not known.

Readback dataclass

Readback(
    value: float,
    units: str | None = None,
    precision: int | None = None,
    limits: tuple[float | None, float | None] = (
        None,
        None,
    ),
)

A number as a device reads it back, with what its descriptor says of it.

value instance-attribute

value: float

The value read.

units class-attribute instance-attribute

units: str | None = None

Engineering units, from the descriptor.

precision class-attribute instance-attribute

precision: int | None = None

Decimals the descriptor asks for.

limits class-attribute instance-attribute

limits: tuple[float | None, float | None] = (None, None)

Lowest and highest value the descriptor allows; None for no bound.

device_path

device_path(device: Device) -> DevicePath

Return where device sits in its tree.

A device whose parent does not list it among its children starts the keys, as a root does, and the names still reach the top of the tree.

held_by

held_by(device: Device, names: Set[str]) -> bool

Tell whether device or a device above it is in names.

describe_axis async

describe_axis(axis: Axis) -> AxisInfo

Return where axis stands and what its readback descriptor says.

The descriptor is the entry of the readback a StandardMovable names, otherwise of the axis' first hint, or its only entry; an axis that is not readable has none.

Raises:

Type Description
TypeError

If the position of axis is not a number.

limits

limits(
    descriptor: Mapping[str, Any],
) -> tuple[float | None, float | None]

Return the lowest and highest value descriptor allows; None for no bound.

Control limits come first, display limits otherwise. A pair whose low is not below its high counts as no limits: EPICS reports 0 and 0 for a record that has none.

read_configuration async

read_configuration(
    device: AsyncConfigurable,
) -> Configuration

Read the configuration of device, marking what cannot be written.

readback

readback(
    value: float, descriptor: Mapping[str, Any]
) -> Readback

Return value with the units, precision and limits descriptor gives.

Units that are not text, and a precision that is not a whole number of at least 0, are left out.

is_light

is_light(item: object) -> TypeGuard[Light]

Tell whether item is a light: its enabled is a boolean signal it can write.

A device whose intensity is not a numeric signal it can write counts as a light without intensity.

dimmable

dimmable(light: Light) -> TypeGuard[DimmableLight]

Tell whether light has an intensity that is a numeric signal it can write.

describe_light async

describe_light(light: Light) -> LightInfo

Return the state of light and what its intensity's descriptor says.