Live updates

Live updates#

Algorithms can send intermediate outputs to the client application before they have finished running. This makes it possible for user interfaces, such as the Napari Viewer, to update in real time.

For example, you might “stream”:

  • Frames from a camera along with a segmentation overlay or detection boxes.

  • Progress notifications from a long-running task.

  • Intermediate results from an iterative algorithm.

Using yield#

When a function decorated with @sk.algorithm contains yield statements, the yielded values are interpreted as intermediate outputs. Each yielded value should be annotated as, and is matched with a data layer, just like the return values.

Here is a simple example:

import imaging_server_kit as sk
import time

@sk.algorithm
def threshold_algo(image):
    for threshold in range(0, 255, 20):  # Progressively increase the threshold value
        mask = image > threshold
        yield sk.Mask(mask), sk.String(f"Threshold: {threshold}")  # <- "Stream" the outputs
        time.sleep(0.5)

viewer = sk.to_napari(threshold_algo)

import skimage.data
viewer.add_image(skimage.data.coins())

When running this algorithm in Napari, the displayed segmentation mask progressively gets updated as the threshold value increases.

An algorithm can yield multiple intermediate outputs and still produce a final result via return.

For example:

import imaging_server_kit as sk
import time

@sk.algorithm
def mini_pipeline(image, threshold=100):
    yield sk.Notification("Starting the processing")

    time.sleep(2)

    mask = image > threshold

    yield sk.Notification("Segmented the image"), sk.Mask(mask)
    
    time.sleep(2)

    fract = mask.sum() / mask.size

    return sk.Notification(f"Fraction of True pixels: {fract}")

viewer = sk.to_napari(mini_pipeline)

import skimage.data
viewer.add_image(skimage.data.coins())

In this example, the algorithm notifies the user that processing has started, then returns a segmentation mask, and finally prints out the final measurement.

Summary#

  • Use yield to send intermediate results before an algorithm finishes running.

  • Yielded values should be annotated just like return values.

Next steps#

In the next section, you will see how to run an algorithm tile-by-tile.