Towards a First Acquisition¶
A complete acquisition workflow requires coordinating multiple hardware sub-systems in a defined sequence: selecting the correct optical path, opening the illumination shutter, snapping the image, and safely closing the shutter once the frame is captured. This example demonstrates how to orchestrate these steps programmatically using the Inscoper API.
Prerequisites¶
This example builds on the device exploration pattern introduced in Explore Devices. The device map constructed in that example is reused here to locate all relevant sub-devices by their functional type.
Overview¶
The acquisition sequence relies on six sub-device types:
| Sub-device type | Role |
|---|---|
OBJECTIVE |
Selects the active objective on the turret |
CUBE |
Selects the active filter cube on the turret |
X_AXIS / Y_AXIS |
Hold the current stage position along each axis |
MOVE_AXIS |
Triggers the physical stage movement |
| Transmission lamp intensity | Sets the illumination intensity (as a percentage) |
SHUTTER (TL) |
Opens and closes the transmitted-light illumination path |
The example executes the following steps in order:
- Select the objective slot and filter cube slot.
- Set the lamp intensity and open the transmitted-light shutter.
- Snap a single image and retrieve the pixel data.
- Display the image in a viewer.
- Close the shutter and reduce the lamp intensity to zero.
Note
This example uses a configuration named camera_and_microscope and a camera named MyCamera. Replace these values with the names defined in your own hardware configuration file.
Proto-acquisition¶
# 1. Create the Napari viewer
viewer = napari.Viewer()
objective_slot = 0
cube_slot = 0
lamp_intensity_percent = 30
# To move the stage we need to interact with the X_AXIS, Y_AXIS, and MOVE_XY sub-devices.
x_axis_sub_device_id = None
y_axis_sub_device_id = None
move_xy_sub_device_id = None
objective_turret_sub_device_id = None
cube_turret_sub_device_id = None
light_power_sub_device_id = None
shutter_tl_sub_device_id = None
for device_id, device in device_map.items():
for sub_device_tag, sub_device in device.sub_device_map.items():
if sub_device.inscoper_type == "X_AXIS":
x_axis_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif sub_device.inscoper_type == "Y_AXIS":
y_axis_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif sub_device.inscoper_type == "MOVE_AXIS":
move_xy_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif sub_device.inscoper_type == "SHUTTER" and "TL" in sub_device.name:
shutter_tl_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif sub_device.inscoper_type == "OBJECTIVE":
objective_turret_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif sub_device.inscoper_type == "CUBE":
cube_turret_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
elif ("Intensity" in sub_device.name or "Power" in sub_device.name) and "TL" in sub_device.name:
light_power_sub_device_id = inscoper_api.SubDeviceId(device.name, sub_device.name)
my_bridge.setValue(objective_turret_sub_device_id, objective_slot)
my_bridge.setValue(cube_turret_sub_device_id, cube_slot)
my_bridge.setValue(light_power_sub_device_id, lamp_intensity_percent)
my_bridge.setValue(shutter_tl_sub_device_id, 1)
my_camera = my_bridge.getCamera("MyCamera")
image = my_camera.snapImage(0)
image_data = image.getImageData()
image_width = image.getWidth()
image_height = image.getHeight()
pixel_size_bytes = image.getPixelSize()
bit_depth = image.getBitDepth()
bytes_per_value = bit_depth // 8
values_per_pixel = pixel_size_bytes // bytes_per_value
img = np.reshape(image_data, (image_height, image_width, values_per_pixel))
viewer.add_image(img[:, :, 0], name="Microscope Snap")
my_bridge.setValue(shutter_tl_sub_device_id, 0)
my_bridge.setValue(light_power_sub_device_id, 0)
napari.run()