Skip to content

Writing Custom Scripts

This module runs Python functions during acquisition. Scripts must follow the templates in the inscoper-scripts repository.

Image Provider Function

The image provider function is your script's entry point. The acquisition engine calls it after every image capture. It has two responsibilities:

  1. Gating: Decide whether the processing function should run (e.g., wait until a Z-stack is complete).
  2. Image selection: Decide which images to fetch from memory and pass to the processing function (e.g., the full Z-stack, or only the last 2D frame).

Signature

Arguments

  • new_image (images): The first argument, typed images. It receives the last image acquired by the hardware, together with the metadata that identifies the multidimensional state of the microscope (time, position, channel, and Z-slice indices).
  • Optional arguments: Define additional parameters (such as channel_index or focus_option) that the user configures in the interface.

Return Value

The image provider function must return a List[Dict[str, int]].

  • Empty list [] or None: Skips the processing function for the current iteration.
  • Non-empty list of dictionaries: Runs the processing function. Each dictionary specifies one image to fetch from memory.

    • Empty Dictionary {}: Fetches the current image (indices are inferred from the new_image object).
    • Specific Indices (e.g., {'focusIndex': 3}): Fetches an image from a specific coordinate (e.g., Z-slice 3). Any dimension index not explicitly declared (e.g., timeIndex, positionIndex) is copied from the current new_image.
    Dimension Index key Size key
    Time (t) timeIndex timeSize
    Position (XY) positionIndex positionSize
    Channel (λ) channelIndex channelSize
    Focus (Z) focusIndex focusSize
    Lifetime (FLIM) flimIndex flimSize

Code Example: Fetching an Entire Z-stack

This example checks whether the current image is the last slice of a Z-stack. If so, it collects all prior slices so that the Imaging Software can dispatch this list of images to the processing function; if not the final slice, it does nothing and awaits the next capture. Note that the positionIndex and timeIndex are inferred from the new_image object.

from inscoper_scripts.utils import extract_metadata
import numpy as np
from typing import List, Dict

def fetch_zstack(new_image: "images", channel_index: int = 0) -> List[Dict[str, int]]:
    """
    Collect the full Z-stack for the current position in the target channel.
    """
    # 1. Read the metadata dictionary of the current image
    meta = extract_metadata(new_image)

    current_z = meta.get('focusIndex', 0)
    total_z = meta.get('focusSize', 1)

    # 2. Run only on the last Z slice
    if current_z != (total_z - 1):
        return [] # An empty list skips the processing function

    # 3. Select every slice, 0 to total_z-1
    # Only 'focusIndex' and 'channelIndex' are given;
    # 'timeIndex' and 'positionIndex' are inferred from the current image.
    image_selection = []
    for z in range(total_z):
        image_selection.append({
            'focusIndex': z,
            'channelIndex': channel_index
        })

    return image_selection

Code Example: Fetching the Current Image

This is the simplest case. A list containing one empty dictionary sends only the current image to the processing function.

def fetch_current_image(new_image: "images") -> List[Dict[str, int]]:
    return [{}]

Code Example: Fetching the Last Two Timepoints

This pattern retrieves the images from the previous (t-1) and current (t) timepoints. Use it for tracking algorithms.

def fetch_last_two_timepoints(new_image: "images") -> List[Dict[str, int]]:
    meta = extract_metadata(new_image)
    current_t = meta.get('timeIndex', 0)

    # At least two timepoints are required (index 0 and index 1)
    if current_t < 1:
        return []

    return [
        {'timeIndex': current_t - 1}, # Previous timepoint
        {'timeIndex': current_t}      # Current timepoint
    ]

Processing Function

In the data processing function, the first argument must be typed images. It receives the list of image arrays returned by the image provider.

Supported Argument Types and UI Automation

Python type Generated widget Description
str A string parameter, rendered as a text input field.
int An integer value, rendered as a spin box with an increment of 1.
float A floating-point value, rendered as a spin box with an increment of 0.001.
bool A boolean value, rendered as a toggle switch.
Path or str with / or \\ A directory path, rendered as a directory chooser.
Literal["val1", "val2", "val3"] A value constrained to an enumeration, rendered as a single-selection dropdown list.
List[Literal["val1", "val2", "val3"]] Several values constrained to an enumeration, rendered as a multi-selection dropdown list.
images Represents one or more image arrays provided by the Imaging Software (the last acquired image for the image provider function, or a curated list of images for the processing function).
SubDeviceId A sub-device name (used as a key to read its value in the metadata), rendered as a dropdown list of all available sub-devices.
channel A channel name, rendered as a dropdown list of all available channels.
IIS_CONTEXT A context object, allowing the script to interact with the software environment (variable transfer, method execution).

Set default values in the function signature, using standard Python syntax: e.g., var1: float = 0.5 or List[Literal["val1", "val2", "val3"]] = ["val2"].

Interacting with Inscoper I.S.

The IIS_CONTEXT exposes methods allowing your script to interact with the software environment.

getCameras()

Retrieves a list of active cameras.

  • Returns: List[str] - The camera names.

Example:

cameras = IIS_CONTEXT.getCameras()
# Returns, for example: ["Camera1", "Camera2"]

getProjectPath()

Retrieves the path of the currently active project directory.

  • Returns: str - The active project path.

Example:

path = IIS_CONTEXT.getProjectPath()
# Returns, for example: "D:/Data/Project_001"

displayImage(id, img)

Sends an image array to a data processor in the visualization dashboard.

  • Parameters:
    • id (str): An identifier matching the target data processor.
    • img (NDArray): The image data to display.

setVariable(id, value)

Stores a variable in the application. Use it to pass values between calls during the acquisition loop.

  • Parameters:
    • id (str): The key identifying the stored variable.
    • value (Object): The value to store.

Example:

IIS_CONTEXT.setVariable("tracking_counter", 1)

getVariable(id)

Retrieves a variable previously stored with setVariable.

  • Parameters:
    • id (str): The key of the variable.
  • Returns: object - The stored value.

Example:

count = IIS_CONTEXT.getVariable("tracking_counter")

fireOnDemand(cameraName, roi, channelName, powerMap, repetition)

Triggers a FRAP photo-activation sequence on the given region of interest (ROI), using the specified channel and power settings.

  • Parameters:
    • cameraName (str): The name of the camera to be used for the photo-activation sequence (this string must exactly match one of the returned values from the getCameras() execution).
    • roi (Object): The region of interest. Pass an ROI instance (e.g., RectangleROI) from the inscoper_scripts.utils.rois module, or a list of such instances. Given a list, the system photoactivates each ROI in turn.
    • channelName (str): The name of the channel to use.
    • powerMap (Object): The illumination power settings, as a Python dictionary (e.g., {"MyLaserSubDevice": 100}).
    • repetition (Object): The number of repetitions (e.g., 10 runs 10 consecutive cycles).

Example:

from inscoper_scripts.utils.rois import RectangleROI

# Define the parameters
cam = "Camera1"
my_roi = RectangleROI(0, 0, 512, 512, fill=False)
channel = "GFP_Activation"
power = {"488nm_Laser": 50.0}
reps = 1

# Trigger the sequence
IIS_CONTEXT.fireOnDemand(cam, my_roi, channel, power, reps)