Saved image callbacks

Saved image callbacks provide a mechanism to execute custom code immediately after an image is saved, which:

  1. Avoids speed limitations of image processors when using the Java backend (see Headless Mode)

  2. Enables custom user interface updates

  3. Allows immediate post-processing of acquired data

Basic Usage

To use saved image callbacks, supply an image_saved_fn to the Acquisition. This function takes two arguments:

  • axes: A dictionary describing the unique identifier of the image (e.g., z=0, time=2)

  • dataset: A Dataset object associated with the Acquisition

Access the newly saved image as follows:

def image_saved_fn(axes, dataset):
    pixels = dataset.read_image(**axes)
    # Process or display pixels here

Example:

from pycromanager import Acquisition, multi_d_acquisition_events

def image_saved_fn(axes, dataset):
    pixels = dataset.read_image(**axes)
    # TODO: Use pixels for post-processing or custom visualization

with Acquisition(directory=save_dir, name="tcz_acq",
                 image_saved_fn=image_saved_fn) as acq:
    events = multi_d_acquisition_events(
        num_time_points=5,
        z_start=0, z_end=6, z_step=0.4,
    )
    acq.acquire(events)

Adapting acquisition from image saved callbacks

Note

Adapting acquisition form image saved callbacks is an older feature. The newer Adaptive Acquisitions API is now the reccomended way to do this. However, the approach below still works.

The event_queue allows you to create new acquisition events in response to saved images, enabling adaptive acquisition strategies. Use a three-argument version of image_saved_fn:

def image_saved_fn(axes, dataset, event_queue):
    pixels = dataset.read_image(**axes)
    # Process pixels
    new_event = create_new_event(pixels)  # Create a new acquisition event
    event_queue.put(new_event)  # Add the new event to the queue

Custom user interface updates

The example below shows Headless Mode in combination with an saved image callback, which calls a user-defined function whenever new data is stored (on disk or in RAM depending on the arguments to Acquisition). This setup could be used to replace the pycro-manager viewer with a custom user interface (note the show_display=False in the acquisition).

from pycromanager import Acquisition, multi_d_acquisition_events, start_headless

mm_app_path = '/path/to/micromanager'
config_file = mm_app_path + "/MMConfig_demo.cfg"

# Start the Java process
start_headless(mm_app_path, config_file, timeout=5000)

save_dir = r"\path\to\data"

def image_saved_fn(axes, dataset):
    pixels = dataset.read_image(**axes)
    # TODO: use the pixels for something, like post-processing or a custom image viewer

with Acquisition(directory=save_dir, name="tcz_acq", show_display=False,
                image_saved_fn=image_saved_fn) as acq:
    events = multi_d_acquisition_events(num_time_points=5,
        z_start=0, z_end=6, z_step=0.4,)
    acq.acquire(events)

# Another way to access to the saved data
d = acq.get_dataset()