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
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=["DAPI", {"config": "FITC", "exposure": 50}],
    time_plan={"interval": 2, "loops": 5},
    z_plan={"range": 4, "step": 0.5},
    axis_order="tpcz",
)

mmc = CMMCorePlus.instance()  # (2)!
mmc.loadSystemConfiguration()  #  load demo configuration (3)


# connect callback using a decorator (4)
@mmc.mda.events.frameReady.connect
def new_frame(img: np.ndarray, event: MDAEvent):
    print(img.shape)


# 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)

# run the sequence in a separate thread (5)
mmc.run_mda(sequence)
  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!")