# Overview

!!! info ""

    <div style="font-size: 1rem; padding: 10px;">
    <code>useq-schema</code> is an implementation agnostic schema for describing a
    sequence of events during a multi-dimensional imaging acquisition.
    </div>

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. A *hope* is that this will encourage inter-operability between
various efforts to drive automated image acquisition.

The schema *tries* to remain agnostic to the specific acquisition engine (though
it was designed based on the capabilities
[Micro-Manager](https://micro-manager.org)). We welcome 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 (even minor stuff, such as parameter naming, etc...) is welcome!
Please [open an issue](https://github.com/pymmcore-plus/useq-schema/issues/new).

## Core Schema

### `MDAEvent`

The primary "event" object is [`useq.MDAEvent`][].  This describes a single event
that a microscope should perform, including preparation of the hardware, and
execution of the event (such as an image acquisition).

- For [micro-manager](https://github.com/micro-manager/micro-manager), this
  object is most similar (though not identical) to the events generated by
  [`generate-acq-sequence`](https://github.com/micro-manager/micro-manager/blob/2b0f51a2f916112d39c6135ad35a112065f8d58d/acqEngine/src/main/clj/org/micromanager/sequence_generator.clj#L410)
  in the clojure acquisition engine that drives Micro-Managers multi-dimensional
  acquisitions.
- For [Pycro-manager](https://github.com/micro-manager/pycro-manager), this
  object is similar to an individual [acquisition event
  `dict`](https://pycro-manager.readthedocs.io/en/latest/apis.html#acquisition-event-specification)
  generated by
  [`multi_d_acquisition_events`](https://github.com/micro-manager/pycro-manager/blob/63cf209a8907fd23932ee9f8016cb6a2b61b45aa/pycromanager/acquire.py#L605),
  (and, `useq.pycromanager` provides a `to_pycromanager` method
  that returns a dict following the pycro-manager event spec)
- *your object here?...*

### `MDASequence`

[`useq.MDASequence`][] represents a **sequence** of events – as might be
generated by the multidimensional acquisition GUI in most microscope software.
The Python `MDASequence` object is itself
[iterable][useq._mda_sequence.MDASequence.__iter__], and yields
[`useq.MDAEvent`][] objects.

- For [micro-manager](https://github.com/micro-manager/micro-manager), this
  object is most similar to
  [`org.micromanager.acquisition.SequenceSettings`](https://github.com/micro-manager/micro-manager/blob/2b0f51a2f916112d39c6135ad35a112065f8d58d/mmstudio/src/main/java/org/micromanager/acquisition/SequenceSettings.java#L39),
  (generated by clicking the `Acquire!` button in the [Multi-D Acquisition
  GUI](https://micro-manager.org/Version_2.0_Users_Guide#multi-dimensional-acquisition))
- For [Pycro-manager](https://github.com/micro-manager/pycro-manager), this
  object is similar to the
  [`multi_d_acquisition_events`](https://github.com/micro-manager/pycro-manager/blob/63cf209a8907fd23932ee9f8016cb6a2b61b45aa/pycromanager/acquire.py#L605)
  convenience function, (and `useq.pycromanager` provides a
  `to_pycromanager` method that returns a list of pycro-manager event dicts)
- *your object here?...*

## Executing an MDASequence

This library is just a schema, and does not provide any built-in functionality
for executing an `MDASequence`.  However,
[`pymmcore-plus`](https://github.com/pymmcore-plus/pymmcore-plus) implements an
acquisition engine that can execute an `MDASequence` object with
[micro-manager](https://micro-manager.org) (via the
[`pymmcore`](https://github.com/micro-manager/pymmcore) python wrapper around
the C++ MMCore).  See the [pymmcore-plus documentation for
details](https://pymmcore-plus.github.io/pymmcore-plus/examples/mda/).
`napari-micromanager` also creates a `useq.MDASequence` object from user input
and passes it to `pymmcore-plus` for execution.

!!! tip "hi! :wave:"

    Have you implemented an acquisition engine that can execute a `useq.MDASequence`?
    Let us know so we can add it here!

## Serialization and Deserialization

`MDASequence` and `MDAEvent` objects are designed to be serialized and deserialized,
allowing you to define an entire multi-dimensional acquisition in human-readable
YAML (or JSON) file, and then load that file into your acquisition engine.

For example, the following file defines an experiment with:

- 3 channels (`DAPI`, `FITC`, and `Cy5`), specifying exposure times in ms for each channel
- a two-phase time-lapse: 3 frames in the first phase, followed by a frame every 10 seconds
for 40 minutes
- a Z-stack at each timepoint, with a range of 4 microns and a step size of 0.5 micron
- two stage positions, specifying a unique Z-stack for the second position

!!! example

    === "YAML"

        ```YAML title="my_experiment.yaml"
        axis_order: tpcz
        channels:
          - config: Cy5
            exposure: 50.0
          - config: FITC
            exposure: 100.0
          - config: DAPI
            acquire_every: 3
            do_stack: false
        time_plan:
          phases:
            - interval: 0:00:03
              loops: 3
            - duration: 0:40:00
              interval: 0:00:10
        z_plan:
          range: 4.0
          step: 0.5
        stage_positions:
          - x: 10.0
            y: 20.0
          - name: Cell 1
            x: 10.0
            y: 20.0
            z: 50.0
            z_plan:
              above: 10.0
              below: 0.0
              step: 1.0
        metadata:
          some info: about my experiment
        ```

    === "JSON"

        ```JSON title='my_experiment.json'
        {
          "axis_order": "tpcz",
          "channels": [
            {
              "config": "Cy5",
              "exposure": 50.0
            },
            {
              "config": "FITC",
              "exposure": 100.0
            },
            {
              "config": "DAPI",
              "acquire_every": 3,
              "do_stack": false
            }
          ],
          "time_plan": {
            "phases": [
              {
                "interval": "0:00:03",
                "loops": 3
              },
              {
                "duration": "0:40:00",
                "interval": "0:00:10"
              }
            ]
          },
          "z_plan": {
            "range": 4.0,
            "step": 0.5
          },
          "stage_positions": [
            {
              "x": 10.0,
              "y": 20.0
            },
            {
              "name": "Cell 1",
              "x": 10.0,
              "y": 20.0,
              "z": 50.0,
              "z_plan": {
                "above": 10.0,
                "below": 0.0,
                "step": 1.0
              }
            }
          ],
          "metadata": {
            "some info": "about my experiment"
          }
        }
        ```
