diff --git a/README.md b/README.md index 3ae9a04..c647100 100644 --- a/README.md +++ b/README.md @@ -8,33 +8,53 @@ [![docs](https://github.com/pymmcore-plus/useq-schema/actions/workflows/docs.yml/badge.svg)](https://pymmcore-plus.github.io/useq-schema/) [![codecov](https://codecov.io/gh/pymmcore-plus/useq-schema/branch/main/graph/badge.svg)](https://codecov.io/gh/pymmcore-plus/useq-schema) -*An implementation agnostic schema for describing a sequence of events during a -multi-dimensional imaging acquisition.* +*An open, implementation-agnostic schema for describing multi-dimensional +microscopy experiments.* **Documentation: ** -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. +## Rationale -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. +The `useq-schema` library defines a structured schema to represent a sequence of +microscope acquisition events. By adopting this schema, various microscopy +software tools can facilitate interoperability, allowing end users to +potentially switch between different control backends with ease. The goal is to +encourage a shared standard, making it straightforward for developers to adopt +useq-schema and enhance compatibility across tools. -Any and all feedback is welcome! Please get in touch if you have any thoughts. +**We are particularly interested in feedback from developers of microscopy-control +software**. If you are interested in supporting the useq-schema in your software, +please open an issue or pull request to discuss how we can make that easier for +you, or to request additional features that would be necessary for your use case. -## `MDAEvent` +## `useq.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]`. +execution of the event (such as an image acquisition). + +```python +from useq import MDAEvent + +event = MDAEvent( + channel="DAPI", + exposure=100, + x_pos=100.0, + y_pos=100.0, + z_pos=30.0, + min_start_time=10.0, + ... # multiple other fields +) +``` + +Downstream libraries that aim to support useq-schema should support driving +hardware based on an `Iterable[MDAEvent]`. See [`useq.MDAEvent` +documentation](https://pymmcore-plus.github.io/useq-schema/schema/event/) for +more details. + +
+ +Similar objects in existing software packages - For [micro-manager](https://github.com/micro-manager/micro-manager), this object is most similar (though not *that* similar) to the events generated by @@ -49,23 +69,25 @@ useq schema should support driving hardware based on an `Iterable[MDAEvent]`. single pycro-manager event dict) - *your object here?...* -See [`useq.MDAEvent` documentation](https://pymmcore-plus.github.io/useq-schema/schema/event/) -for more details. - -> **Note:** `useq-schema` uses [`pydantic`](https://pydantic-docs.helpmanual.io/) to -> define models, so you can retrieve the [json schema](https://json-schema.org/) -> for the `MDAEvent` object with `MDAEvent.model_json_schema()` +
-## `MDASequence` +## `useq.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 +`useq.MDASequence` is a declarative representation of an multi-dimensional +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](https://pymmcore-plus.github.io/useq-schema/schema/axes/) (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](https://pymmcore-plus.github.io/useq-schema/schema/sequence/) +for more details. + +
+ +Similar objects in existing software packages + - 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), @@ -77,10 +99,9 @@ Time Plan, a Z Plan, a list of channels and positions, etc.). A converts an `MDASequence` to a list of pycro-manager events) - *your object here?...* -See [`useq.MDASequence` documentation](https://pymmcore-plus.github.io/useq-schema/schema/sequence/) -for more details. +
-### example `MDASequence` usage +### Example usage ```python from useq import MDASequence @@ -92,39 +113,46 @@ mda_seq = MDASequence( 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 +The `MDASequence` object is iterable, yielding `MDAEvent` objects in the order +specified by the `axis_order` attribute. + +```python +>>> 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, + )] + ``` + +Both `MDAEvent` and `MDASequence` objects are pydantic models, so they can be +easily serialized to and from json or yaml. ```py print(mda_seq.yaml()) @@ -150,10 +178,22 @@ z_plan: step: 0.5 ``` +## Installation + +```bash +pip install useq-schema +``` + +or, with conda: + +```bash +conda install -c conda-forge useq-schema +``` + ## Executing useq-schema experiments with pymmcore-plus [pymmcore-plus](https://github.com/pymmcore-plus/pymmcore-plus) implements an -acquisition engine that can execute an `MDASequence` using +acquisition engine that can execute an iterable of `MDAEvents` using micro-manager in a pure python environment (no Java required). ```python @@ -169,4 +209,6 @@ events = [MDAEvent(...), MDAEvent(...), ...] core.mda.run(events) ``` -See [pymmcore-plus documentation](https://pymmcore-plus.github.io/pymmcore-plus/examples/mda/) for details +This can be considered a "reference implementation" of an engine that supports useq-schema. + +See [pymmcore-plus documentation](https://pymmcore-plus.github.io/pymmcore-plus/examples/mda/) for details.