Skip to content

An implementation agnostic schema for describing a sequence of events during a multi-dimensional imaging acquisition.

License

Notifications You must be signed in to change notification settings

pymmcore-plus/useq-schema

Repository files navigation

useq-schema

License PyPI - Python Version PyPI Conda tests docs codecov

An implementation agnostic schema for describing a sequence of events during a multi-dimensional imaging acquisition.

Documentation: https://pymmcore-plus.github.io/useq-schema/

The goal of this repo is to provide a specification (and some python utilities) for generating event objects that can be consumed by microscope acquisition engines. The hope is that this will encourage interoperability between various efforts to drive automated image acquisition.

The schema tries to remain agnostic to the specific acquisition engine, though it was designed around the needs of Micro-Manager. One hope is to solicit feedback from interested parties regarding limitations and/or potential extensions to the schema. Similarly, while the "ideal" schema will support arbitrary dimensions (i.e. more than the conventional position, time, channel, z, ...), it also hard to avoid hard-coding some assumptions about dimensionality in certain places.

Any and all feedback is welcome! Please get in touch if you have any thoughts.

MDAEvent

The primary "event" object is useq.MDAEvent. This represents a single event that a microscope should perform, including preparation of the hardware, and execution of the event (such as an image acquisition). This is the simpler, but more important of the two objects. Downstream libraries that aim to support useq schema should support driving hardware based on an Iterable[MDAEvent].

See useq.MDAEvent documentation for more details.

Note: useq-schema uses pydantic to define models, so you can retrieve the json schema for the MDAEvent object with MDAEvent.model_json_schema()

MDASequence

useq.MDASequence is a declarative representation of an entire experiment. It represents a sequence of events (as might be generated by the multidimensional acquisition GUI in most microscope software). It is composed of "plans" for each axis in the experiment (such as a Time Plan, a Z Plan, a list of channels and positions, etc.). A useq.MDASequence object is itself iterable, and yields MDAEvent objects.

See useq.MDASequence documentation for more details.

example MDASequence usage

from useq import MDASequence

mda_seq = MDASequence(
    stage_positions=[(100, 100, 30), (200, 150, 35)],
    channels=["DAPI", "FITC"],
    time_plan={'interval': 1, 'loops': 20},
    z_plan={"range": 4, "step": 0.5},
    axis_order='tpcz',
)
events = list(mda_seq)

print(len(events))  # 720

print(events[:3])

# [MDAEvent(
#     channel=Channel(config='DAPI'),
#     index=mappingproxy({'t': 0, 'p': 0, 'c': 0, 'z': 0}),
#     min_start_time=0.0,
#     x_pos=100.0,
#     y_pos=100.0,
#     z_pos=28.0,
#  ),
#  MDAEvent(
#     channel=Channel(config='DAPI'),
#     index=mappingproxy({'t': 0, 'p': 0, 'c': 0, 'z': 1}),
#     min_start_time=0.0,
#     x_pos=100.0,
#     y_pos=100.0,
#     z_pos=28.5,
#  ),
#  MDAEvent(
#     channel=Channel(config='DAPI'),
#     index=mappingproxy({'t': 0, 'p': 0, 'c': 0, 'z': 2}),
#     min_start_time=0.0,
#     x_pos=100.0,
#     y_pos=100.0,
#     z_pos=29.0,
#  )]

serialize to yaml or json

print(mda_seq.yaml())
axis_order: tpcz
channels:
- config: DAPI
- config: FITC
stage_positions:
- x: 100.0
  y: 100.0
  z: 30.0
- x: 200.0
  y: 150.0
  z: 35.0
time_plan:
  interval: 0:00:01
  loops: 20
z_plan:
  range: 4.0
  step: 0.5

Executing useq-schema experiments with pymmcore-plus

pymmcore-plus implements an acquisition engine that can execute an MDASequence using micro-manager in a pure python environment (no Java required).

from pymmcore_plus import CMMCorePlus

core = CMMCorePlus()
core.loadSystemConfiguration()  # loads demo by default

core.mda.run(mda_seq)  # run the experiment

# or, construct a sequence of MDAEvents anyway you like
events = [MDAEvent(...), MDAEvent(...), ...]
core.mda.run(events)

See pymmcore-plus documentation for details