Skip to content

Multidimensional Acquisition#

Note

There is much more extensive documentation on the MDA acquisition engine in the Acquisition Engine guide

pymmcore-plus includes a basic Multi-dimensional Acquisition (mda) engine CMMCorePlus.run_mda that accepts experimental sequences defined using useq-schema.

run_mda.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import itertools
import sys

import numpy as np
from useq import MDAEvent, MDASequence

from pymmcore_plus import CMMCorePlus

# see https://pymmcore-plus.github.io/useq-schema/api/ (1)
sequence = MDASequence(
    channels=[{"config": "DAPI", "exposure": 10}, {"config": "FITC", "exposure": 50}],
    time_plan={"interval": 1, "loops": 5},
    z_plan={"range": 4, "step": 0.5},
    axis_order="tpcz",
)

mmc = CMMCorePlus.instance()  # (2)!
mmc.loadSystemConfiguration()  #  load demo configuration (3)
counter = itertools.count(1)


# connect callback using a decorator (4)
@mmc.mda.events.frameReady.connect
def new_frame(img: np.ndarray, event: MDAEvent):
    print(f"Frame {next(counter):>3}, shape", img.shape, event.index)


# or connect callback using a function
def on_start(sequence: MDASequence):
    print(f"now starting sequence {sequence.uid}!")


mmc.mda.events.sequenceStarted.connect(on_start)

# parse command line arguments to determine output format, default is no output.
output = None
if "--tiff" in sys.argv:
    output = "example_mda.ome.tiff"
elif "--zarr" in sys.argv:
    output = "example_mda.ome.zarr"

# run the sequence (5)
mmc.mda.run(sequence, output=output, overwrite=True)
  1. pymmcore-plus uses useq-schema to define experimental sequences. You can either construct a useq.MDASequence object manually, or from a YAML/JSON file.
  2. Access global singleton: CMMCorePlus.instance
  3. See CMMCorePlus.loadSystemConfiguration
  4. For info on all of the signals available to connect to, see the MDA Events API
  5. To avoid blocking further execution, run_mda runs on a new thread. (run_mda returns a reference to the thread in case you want to do something with it, such as wait for it to finish with threading.Thread.join)

Cancelling or Pausing#

You can pause or cancel the mda with the CMMCorePlus.mda.toggle_pause or CMMCorePlus.mda.cancel methods.

Registering a new MDA Engine#

By default the built-in MDAEngine will be used to run the MDA. However, you can create a custom acquisition engine and register it use CMMCorePlus.register_mda_engine.

Your engine must conform to the engine protocol defined by pymmcore_plus.mda.PMDAEngine. To ensure that your engine conforms you can inherit from the protocol.

You can be alerted to the the registering of a new engine with the core.events.mdaEngineRegistered signal.

@mmc.events.mdaEngineRegistered
def new_engine(new_engine, old_engine):
    print('new engine registered!")