magscope.datatypes#
Shared-memory buffers used across MagScope.
This module introduces two circular buffers that let different processes share camera frames and other numeric data without copying large arrays:
VideoBufferStores stacks of images in one shared-memory region together with capture timestamps. The class is designed for a producer process that records frames and one or more consumer processes that read them.
MatrixBufferStores general two-dimensional numeric data such as bead positions or motor telemetry. Like
VideoBuffer, it uses shared memory.
Both buffers rely on external multiprocessing.synchronize.Lock
objects to coordinate access between processes. See the class docstrings
below for usage details.
Attributes#
Exceptions#
Raised when attempting to read from a buffer that contains no data. |
|
Raised when attempting to write to a buffer that has no free slots. |
|
Raised when a shared-memory dataset exists but is not attachable yet. |
Classes#
Shared memory ring buffer for video data |
|
Shared-memory ring buffer for 2D numeric data. |
|
Shared-memory store for bead ROI metadata. |
|
Shared buffer that stores the latest radial profile for live display. |
|
Temporary shared-memory dataset used for Z-LUT sweep capture. |
Functions#
|
Return the unsigned integer NumPy dtype matching |
Module Contents#
- class magscope.datatypes.VideoBuffer(*, create: bool, locks: dict[str, multiprocessing.synchronize.Lock], n_stacks: int | None = None, width: int | None = None, height: int | None = None, n_images: int | None = None, bits: int | None = None)[source]#
Shared memory ring buffer for video data
- Parameters:
create (bool) –
Trueto allocate the shared-memory regions;Falseto attach to an existing buffer.locks (dict[str, Lock]) – Mapping of buffer names to
multiprocessing.Lockinstances. The dictionary must contain an entry forVideoBuffer.n_stacks (int, optional) – Number of temporal stacks stored in the buffer. Required when
createisTrue.width (int, optional) – Frame width in pixels. Required when
createisTrue.height (int, optional) – Frame height in pixels. Required when
createisTrue.n_images (int, optional) – Number of frames per stack. Required when
createisTrue.bits (int, optional) – Bit depth of each pixel. Required when
createisTrue.
Notes
The buffer should first be created by a process with
create=True. When creating,n_stacks,width,height,n_imagesandbitsmust be provided. After the shared memory exists, other processes can access the buffer withcreate=False.- get_level()[source]#
Return the fraction of the buffer that currently holds data.
- Returns:
Ratio between unread frames and total buffer capacity.
- Return type:
float
- check_read_stack()[source]#
Return
Truewhen at least one full stack can be read.- Returns:
Trueifn_imagesframes are available to read;Falseotherwise.- Return type:
bool
- peak_image()[source]#
Return the newest image and its index without acquiring the lock.
This helper supports lightweight live previews. Because the method does not acquire the lock, it may occasionally return a partially written frame or an older image.
- Returns:
Tuple containing the newest image index and a memory view of the image bytes. Convert the memory view to a 2D array with
dtypeandimage_shape.- Return type:
tuple of (int, memoryview)
- peak_stack()[source]#
Return the next unread stack without advancing the read index.
- Returns:
(stack, timestamps)wherestackhas shape(width, height, n_images)andtimestampsis afloat64array aligned with the returned frames.- Return type:
tuple of numpy.ndarray
- read_stack_no_return()[source]#
Advance the read index by one stack without returning data.
- Returns:
This method updates the internal indices but produces no data.
- Return type:
None
- read_image()[source]#
Return the next unread image and its timestamp.
- Returns:
Tuple consisting of the next unread frame as a 2D array with shape
(width, height)and the corresponding timestamp in seconds.- Return type:
tuple of (numpy.ndarray, float)
- class magscope.datatypes.MatrixBuffer(*, create: bool, locks: dict[str, multiprocessing.synchronize.Lock], name: str, shape: tuple[int, int] = None)[source]#
Shared-memory ring buffer for 2D numeric data.
- Parameters:
create (bool) –
Trueto allocate the shared-memory regions;Falseto attach to an existing buffer.locks (dict[str, Lock]) – Mapping of buffer names to
multiprocessing.Lockinstances. The dictionary must contain an entry forname.name (str) – Identifier used for the shared-memory segments.
shape (tuple[int, int], optional) – Buffer shape expressed as
(rows, columns). Required whencreateisTrue.
Notes
The buffer stores time-series style data where each row is a timestamp and each column is a measurement. Reads consume unread bytes, while
peakhelpers provide views without advancing indices.- get_count_index()[source]#
Return the number of unread bytes currently stored in the buffer.
- Returns:
Byte count representing unread data between the read and write indices.
- Return type:
int
- get_read_index()[source]#
Return the index of the next byte that will be read.
- Returns:
Position within the shared buffer corresponding to the next read operation.
- Return type:
int
- get_write_index()[source]#
Return the index of the next byte that will be written.
- Returns:
Position within the shared buffer corresponding to the next write operation.
- Return type:
int
- write(np_array)[source]#
Write
np_arrayinto the buffer, advancing the write index.- Parameters:
np_array (numpy.ndarray) – Array with
shape[1]columns. Rows may wrap around to the start of the buffer if the write reaches the end of the allocated space.
- read()[source]#
Return unread rows as a NumPy array and reset the read counter.
- Returns:
Copy of the unread rows ordered chronologically.
- Return type:
numpy.ndarray
- class magscope.datatypes.BeadRoiBuffer(*, create: bool, locks: dict[str, multiprocessing.synchronize.Lock], capacity: int | None = None, name: str = 'BeadRoiBuffer')[source]#
Shared-memory store for bead ROI metadata.
The buffer uses a fixed row per bead id so readers can attach once and take compact snapshots of active ROIs without exchanging Python dictionaries over IPC.
- class magscope.datatypes.LiveProfileBuffer(*, create: bool, locks: dict[str, multiprocessing.synchronize.Lock], profile_capacity: int | None = None, name: str = 'LiveProfileBuffer')[source]#
Shared buffer that stores the latest radial profile for live display.
The buffer keeps a single row containing
timestamp,bead_id,profile_lengthand the profile samples. It wraps aMatrixBufferfor shared-memory transport but hides the padding logic from callers so profiles can be written at their native length.- write_profile(timestamp: float, bead_id: int, profile: numpy.ndarray) None[source]#
Store the latest profile for a bead.
- Parameters:
timestamp (float) – Timestamp associated with the profile.
bead_id (int) – Bead identifier for the profile.
profile (numpy.ndarray) – One-dimensional array of profile samples. Length must not exceed
profile_capacity.
- class magscope.datatypes.ZLUTSweepDataset(*, create: bool, locks: dict[str, multiprocessing.synchronize.Lock], capacity: int | None = None, profile_length: int | None = None, n_steps: int | None = None, n_beads: int | None = None, profiles_per_bead: int | None = None, name: str = NAME)[source]#
Temporary shared-memory dataset used for Z-LUT sweep capture.
The dataset stores one row per captured profile with aligned metadata arrays for bead id, step index, timestamp, motor Z, validity, and the full radial profile. Unlike
VideoBufferandMatrixBuffer, this object never wraps and never overwrites old entries. It is intended to be created and destroyed at runtime by the workflow owner, while peer processes attach to the fixed shared-memory names on demand.- _SHM_ATTRS = ('_shm_profiles', '_shm_valid', '_shm_motor_z', '_shm_timestamps', '_shm_step_indices',...[source]#
- classmethod create(*, locks: dict[str, multiprocessing.synchronize.Lock], capacity: int, profile_length: int, n_steps: int, n_beads: int, profiles_per_bead: int, name: str = NAME) ZLUTSweepDataset[source]#
- classmethod attach(*, locks: dict[str, multiprocessing.synchronize.Lock], name: str = NAME) ZLUTSweepDataset[source]#
- write(*, bead_ids: numpy.ndarray, step_indices: numpy.ndarray, timestamps: numpy.ndarray, motor_z_values: numpy.ndarray, valid_flags: numpy.ndarray, profiles: numpy.ndarray) None[source]#
- classmethod _validate_create_parameters(*, capacity: int | None, profile_length: int | None, n_steps: int | None, n_beads: int | None, profiles_per_bead: int | None) dict[str, int][source]#
- exception magscope.datatypes.BufferUnderflow[source]#
Bases:
ExceptionRaised when attempting to read from a buffer that contains no data.
- exception magscope.datatypes.BufferOverflow[source]#
Bases:
ExceptionRaised when attempting to write to a buffer that has no free slots.
- exception magscope.datatypes.DatasetNotReadyError[source]#
Bases:
ExceptionRaised when a shared-memory dataset exists but is not attachable yet.
- magscope.datatypes.int_to_uint_dtype(bits: int)[source]#
Return the unsigned integer NumPy dtype matching
bits.- Parameters:
bits (int) – Width of the target integer in bits. Supported values are
8,16,32and64.- Returns:
Unsigned integer dtype corresponding to
bits.- Return type:
numpy.dtype
- Raises:
ValueError – If
bitsis not one of the supported widths.