API#
In addition to declaring a schema (which is intended to be language agnostic),
useq-schema offers a python API for working with
MDASequence and MDAEvent objects.
            MDASequence
#
    A sequence of MDA (Multi-Dimensional Acquisition) events.
This is the core object in the useq library, and is used define a sequence of
events to be run on a microscope. It object may be constructed manually, or from
file (e.g. json or yaml).
The object itself acts as an iterator for useq.MDAEvent objects:
Attributes:
| Name | Type | Description | 
|---|---|---|
metadata | 
            
                  dict
             | 
            
               A dictionary of user metadata to be stored with the sequence.  | 
          
axis_order | 
            
                  str
             | 
            
               The order of the axes in the sequence. Must be a permutation of   | 
          
stage_positions | 
            
                  tuple[Position, ...]
             | 
            
               The stage positions to visit. (each with   | 
          
grid_plan | 
            
                  GridFromEdges | GridRelative | None
             | 
            
               The grid plan to follow. One of   | 
          
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 | ZRangeAround | ZAboveBelow | ZRelativePositions | ZAbsolutePositions | 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   | 
          
keep_shutter_open_across | 
            
                  tuple[str, ...]
             | 
            
               A tuple of axes   | 
          
Examples:
Create a MDASequence
>>> from useq import MDASequence, Position, Channel, TIntervalDuration
>>> 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}]
... )
Print the sequence to visualize its structure
>>> print(seq)
... MDASequence(
...     stage_positions=(Position(x=1.0, y=1.0, z=1.0, name=None),),
...     grid_plan=GridRowsColumns(
...         fov_width=None,
...         fov_height=None,
...         overlap=(0.0, 0.0),
...         mode=<OrderMode.row_wise_snake: 'row_wise_snake'>,
...         rows=2,
...         columns=2,
...         relative_to=<RelativeTo.center: 'center'>
...     ),
...     channels=(
...         Channel(
...             config='DAPI',
...             group='Channel',
...             exposure=1.0,
...             do_stack=True,
...             z_offset=0.0,
...             acquire_every=1,
...             camera=None
...         ),
...     ),
...     time_plan=TIntervalLoops(
...         prioritize_duration=False,
...         interval=datetime.timedelta(microseconds=100000),
...         loops=2
...     ),
...     z_plan=ZRangeAround(go_up=True, range=3.0, step=1.0)
... )
Iterate over the events in the sequence
>>> print(list(seq))
... [
...     MDAEvent(
...         index=mappingproxy({'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
...     ),
...     MDAEvent(
...         index=mappingproxy({'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:00:00.100000'
   loops: 2
z_plan:
   range: 3.0
   step: 1.0
            shape: tuple[int, ...]
  
      property
  
#
    Return the shape of this sequence.
Note
This doesn't account for jagged arrays, like channels that exclude z stacks or skip timepoints.
            sizes: Mapping[str, int]
  
      property
  
#
    Mapping of axis name to size of that axis.
            uid: UUID
  
      property
  
#
    A unique identifier for this sequence.
            used_axes: str
  
      property
  
#
    Single letter string of axes used in this sequence, e.g. ztc.
            __eq__(other: Any) -> bool
#
    Return True if two MDASequences are equal (uid is excluded).
            __iter__() -> Iterator[MDAEvent]
#
    Same as iter_events. Supports for event in sequence: ... syntax.
            estimate_duration() -> TimeEstimate
#
    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: - total_duration: float Estimated total duration of the experiment, in seconds. - per_t_duration: float Estimated duration of a single timepoint, in seconds. - time_interval_exceeded: bool Whether the time interval between timepoints is shorter than the time it takes to acquire the data  | 
          
            iter_axis(axis: str) -> Iterator[Channel | float | PositionBase]
#
    Iterate over the positions or items of a given axis.
            iter_events() -> Iterator[MDAEvent]
#
    Iterate over all events in the MDA sequence.
See source of useq._mda_sequence.iter_sequence for details on how events are constructed and yielded.
Yields:
| Type | Description | 
|---|---|
                  MDAEvent
             | 
            
               Each event in the MDA sequence.  | 
          
            iter_sequence(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.
The 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.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
                sequence
             | 
            
                  MDASequence
             | 
            
               The sequence to iterate over.  | 
            required | 
Yields:
| Type | Description | 
|---|---|
                  MDAEvent
             | 
            
               Each event in the MDA sequence.  | 
          
Source code in src/useq/_iter_sequence.py
              58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102  |  |