Sequence¶
An MDASequence describes a whole experiment: a plan for each
axis (time, stage positions, grid, channels and z), and the order in which to
iterate them. See Building Sequences for examples.
useq.MDASequence
¶
Bases: UseqModel
A sequence of MDA (Multi-Dimensional Acquisition) events.
This is the core object in the useq library, and is used to define a sequence of
events to be run on a microscope. The object may be constructed manually, or
loaded from a file (JSON or YAML) with MDASequence.from_file.
Iterating over the sequence yields useq.MDAEvent objects (see Examples).
Attributes:
| Name | Type | Description |
|---|---|---|
metadata |
dict[str, Any]
|
A dictionary of user metadata to be stored with the sequence. |
axis_order |
tuple[str, ...]
|
The order in which the axes are iterated, slowest first. May be given as a
string (e.g. |
stage_positions |
WellPlatePlan | tuple[AbsolutePosition, ...]
|
The stage positions to visit (each with |
grid_plan |
GridFromEdges | GridFromPolygon | GridRowsColumns | GridWidthHeight | RandomPoints | RelativePosition | None
|
The grid plan to follow at each position, or |
channels |
tuple[Channel, ...]
|
The channels to acquire. See |
time_plan |
MultiPhaseTimePlan | TIntervalDuration | TIntervalLoops | TDurationLoops | None
|
The time plan to follow. One of |
z_plan |
ZTopBottom | ZAboveBelow | ZRangeAround | ZAbsolutePositions | ZRelativePositions | None
|
The z plan to follow. One of |
uid |
UUID
|
A read-only unique identifier (uuid version 4) for the sequence. This will be generated, do not set. |
autofocus_plan |
AxesBasedAF | None
|
The hardware autofocus plan to follow. One of |
setup |
MDAEvent | None
|
An optional setup event for the sequence. This event is not yielded
during iteration; it is intended to be handled separately by the engine.
It can be used to set hardware state (e.g. device properties, ROI)
before the main acquisition events. By default, |
keep_shutter_open_across |
tuple[str, ...]
|
A tuple of axes |
Examples:
Create a MDASequence
>>> from useq import MDASequence
>>> seq = MDASequence(
... axis_order="tpgcz",
... time_plan={"interval": 0.1, "loops": 2},
... stage_positions=[(1, 1, 1)],
... grid_plan={"rows": 2, "columns": 2},
... z_plan={"range": 3, "step": 1},
... channels=[{"config": "DAPI", "exposure": 1}],
... )
Look at the sequence to visualize its structure (only fields that were set are shown, and long outputs here are wrapped for readability)
>>> seq
MDASequence(
stage_positions=(AbsolutePosition(x=1.0, y=1.0, z=1.0),),
grid_plan=GridRowsColumns(rows=2, columns=2),
channels=(Channel(config='DAPI', exposure=1.0),),
time_plan=TIntervalLoops(
interval=datetime.timedelta(microseconds=100000), loops=2
),
z_plan=ZRangeAround(range=3.0, step=1.0),
)
Iterate over the events in the sequence
>>> events = list(seq)
>>> len(events)
32
>>> events[:2]
[
MDAEvent(
index={'t': 0, 'p': 0, 'g': 0, 'c': 0, 'z': 0},
channel=Channel(config='DAPI'),
exposure=1.0,
min_start_time=0.0,
x_pos=0.5,
y_pos=1.5,
z_pos=-0.5,
reset_event_timer=True,
),
MDAEvent(
index={'t': 0, 'p': 0, 'g': 0, 'c': 0, 'z': 1},
channel=Channel(config='DAPI'),
exposure=1.0,
min_start_time=0.0,
x_pos=0.5,
y_pos=1.5,
z_pos=0.5,
),
]
Print the sequence as yaml
>>> print(seq.yaml())
axis_order:
- t
- p
- g
- c
- z
channels:
- config: DAPI
exposure: 1.0
grid_plan:
columns: 2
rows: 2
stage_positions:
- x: 1.0
y: 1.0
z: 1.0
time_plan:
interval: 0.1
loops: 2
z_plan:
range: 3.0
step: 1.0
Create a sequence with a setup event
>>> from useq import MDASequence, MDAEvent
>>> seq = MDASequence(
... setup=MDAEvent(
... properties=[("Camera", "Binning", "2")],
... roi=(0, 0, 512, 512),
... ),
... channels=["GFP"],
... time_plan={"interval": 1, "loops": 5},
... )
The setup event is accessible via seq.setup but is not yielded
during iteration (it should be handled separately by implementing engines):
>>> seq.setup.action.name
'setup'
>>> seq.setup.roi
CameraROI(offset_x=0, offset_y=0, width=512, height=512)
Print setup sequence as yaml
>>> print(seq.yaml())
channels:
- config: GFP
setup:
action:
name: setup
properties:
- - Camera
- Binning
- '2'
roi:
height: 512
offset_x: 0
offset_y: 0
width: 512
time_plan:
interval: 1.0
loops: 5
-
API Reference
-
pymmcore-plus
pymmcore_plus -
pymmcore-widgets
pymmcore_widgets - useq-schema
-
pymmcore-plus
- Getting Started
-
User Guide
- Controlling Hardware Using Your Own Microscope Groups, channels and pixel sizes
- Running Acquisitions
- Widget Gallery
- useq-schema
stage_positions
¶
stage_positions: WellPlatePlan | tuple[Position, ...] = Field(
default_factory=tuple, union_mode="left_to_right"
)
shape
property
¶
Return the shape of this sequence.
Note
This doesn't account for jagged arrays, like channels that exclude z stacks or skip timepoints.
iter_axis
¶
Iterate over the positions or items of a given axis.
iter_events
¶
Iterate over all events in the MDA sequence.
See source of iter_sequence for
details on how events are constructed and yielded.
Yields:
| Type | Description |
|---|---|
MDAEvent
|
Each event in the MDA sequence. |
estimate_duration
¶
Estimate duration and other timing issues of an MDASequence.
Notable mis-estimations may include:
- when the time interval is shorter than the time it takes to acquire the data
and any of the channels have
acquire_every> 1 - when channel exposure times are omitted. In this case, we assume 1ms exposure.
Returns:
| Type | Description |
|---|---|
TimeEstimate
|
A named 3-tuple with the following fields:
|
How sequences are iterated¶
Iterating an MDASequence yields MDAEvent objects. The
logic lives in iter_sequence, an implementation detail (it isn't part of the
schema itself) that is shown here for reference:
iter_sequence
¶
Iterate over all events in the MDA sequence.
Note
This method will usually be used via useq.MDASequence.iter_events, or by
simply iterating over the sequence.
This does the job of iterating over all the frames in the MDA sequence, handling the logic of merging all z plans in channels and stage positions defined in the plans for each axis.
This is the most "logic heavy" part of useq-schema (the rest of which is
almost entirely declarative). This iterator is useful for consuming MDASequence
objects in a python runtime, but it isn't considered a "core" part of the schema.
The sequence.setup event is not yielded during iteration. It is intended
to be handled separately by an engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sequence
|
MDASequence
|
The sequence to iterate over. |
required |
Yields:
| Type | Description |
|---|---|
MDAEvent
|
Each event in the MDA sequence. |
-
API Reference
useq-schema
Sequence
MDASequenceiter_events