2. Images and Labels¶
Images¶
In order to start working with the image data, we need to instantiate an Image object.
ngio provides a high-level API to access the image data at different resolution levels and pixel sizes.
Getting an image¶
By default, the get_image method returns the highest resolution image:
>>> ome_zarr_container.get_image() # Get the highest resolution image
Image(path=0, Dimensions(c: 3, z: 1, y: 4320, x: 5120))
To get a specific pyramid level, you can use the path parameter:
>>> ome_zarr_container.get_image(path="1") # Get a specific pyramid level
Image(path=1, Dimensions(c: 3, z: 1, y: 2160, x: 2560))
If you want to get an image with a specific pixel size, you can use the pixel_size parameter:
>>> from ngio import PixelSize
>>> pixel_size = PixelSize(x=0.65, y=0.65, z=1.0)
>>> ome_zarr_container.get_image(pixel_size=pixel_size)
Image(path=2, Dimensions(c: 3, z: 1, y: 1080, x: 1280))
By default the pixels must match exactly the requested pixel size. If you want to get the nearest resolution, you can use the strict parameter:
>>> from ngio import PixelSize
>>> pixel_size = PixelSize(x=0.60, y=0.60, z=1.0)
>>> ome_zarr_container.get_image(pixel_size=pixel_size, strict=False)
Image(path=2, Dimensions(c: 3, z: 1, y: 1080, x: 1280))
Similarly to the OME-Zarr Container, the Image object provides a high-level API to access the image metadata.
>>> image.dimensions
Dimensions(c: 3, z: 1, y: 1080, x: 1280)
dimensions attribute returns a object with the image dimensions for each axis.
>>> image.pixel_size
x=0.65 y=0.65 z=1.0 t=1.0 space_unit='micrometer' time_unit=None
pixel_size attribute returns the pixel size for each axis.
>>> image.shape, image.dtype, image.chunks
(3, 1, 1080, 1280) uint16 (1, 1, 1080, 1280)
axes attribute returns the order of the axes in the image.
Working with image data¶
Once you have the Image object, you can access the image data as a:
>>> data = image.get_as_numpy() # Get the image as a numpy array
>>> data.shape, data.dtype
(3, 1, 1080, 1280) uint16
>>> dask_array = image.get_as_dask() # Get the image as a dask array
>>> dask_array
dask.array<from-zarr, shape=(3, 1, 1080, 1280), dtype=uint16, chunksize=(1, 1, 1080, 1280), chunktype=numpy.ndarray>
A generic get_array method is still available for backwards compatibility.
>>> data = image.get_array(mode="numpy") # Get the image as a numpy or dask or delayed object
>>> data.shape, data.dtype
(3, 1, 1080, 1280) uint16
The get_as_* can also be used to slice the image data, and query specific axes in specific orders:
>>> image_slice = image.get_as_numpy(channel_selection="DAPI", x=slice(0, 128), axes_order=["t", "z", "y", "x", "c"]) # Get a specific channel and axes order
>>> image_slice.shape
(1, 1, 1080, 128, 1)
If you want to edit the image data, you can use the set_array method:
>>> image.set_array(data) # Set the image data
The set_array method can be used to set the image data from a numpy array, dask array, or dask delayed object.
A minimal example of how to use the get_array and set_array methods:
# Get the image data as a numpy array
data = image.get_as_numpy(channel_selection="DAPI", x=slice(0, 128), y=slice(0, 128), axes_order=["z", "y", "x", "c"])
# Modify the image data
data = some_function(data)
# Set the modified image data
image.set_array(data, channel_selection="DAPI", x=slice(0, 128), y=slice(0, 128), axes_order=["z", "y", "x", "c"])
image.consolidate() # Consolidate the changes to all resolution levels, see below for more details
Important
The set_array method will overwrite the image data at single resolution level. After you have finished editing the image data, you need to consolidate the changes to the OME-Zarr file at all resolution levels:
>>> image.consolidate() # Consolidate the changes
World coordinates slicing¶
To read or write a specific region of the image defined in world coordinates, you can use the Roi object.
>>> from ngio import Roi
>>> roi = Roi(x=34.1, y=10, x_length=321.6, y_length=330) # Define a ROI in world coordinates
>>> image.get_roi_as_numpy(roi) # Get the image data in the ROI as a numpy array
(3, 1, 509, 496)
Labels¶
Labels represent segmentation masks that identify objects in the image. In ngio Labels are similar to Images and can
be accessed and manipulated in the same way.
Getting a label¶
Now let's see what labels are available in our image:
>>> ome_zarr_container.list_labels() # Available labels
['nuclei', 'wf_2_labels', 'wf_3_labels', 'wf_4_labels']
We have 4 labels available in our image. Let's see how to access them:
By default, the get_label method returns the highest resolution label:
>>> ome_zarr_container.get_label("nuclei") # Get the highest resolution label
Label(path=0, Dimensions(z: 1, y: 4320, x: 5120))
To get a specific pyramid level, you can use the path parameter:
>>> ome_zarr_container.get_label("nuclei", path="1") # Get a specific pyramid level
Label(path=1, Dimensions(z: 1, y: 2160, x: 2560))
If you want to get a label with a specific pixel size, you can use the pixel_size parameter:
>>> from ngio import PixelSize
>>> pixel_size = PixelSize(x=0.65, y=0.65, z=1.0)
>>> ome_zarr_container.get_label("nuclei", pixel_size=pixel_size)
Label(path=2, Dimensions(z: 1, y: 1080, x: 1280))
By default the pixels must match exactly the requested pixel size. If you want to get the nearest resolution, you can use the strict parameter:
>>> from ngio import PixelSize
>>> pixel_size = PixelSize(x=0.60, y=0.60, z=1.0)
>>> ome_zarr_container.get_label("nuclei", pixel_size=pixel_size, strict=False)
Label(path=2, Dimensions(z: 1, y: 1080, x: 1280))
Working with label data¶
Data access and manipulation for Labels is similar to Images. You can use the get_array and set_array methods to access and modify the label data.
Deriving a label¶
Often, you might want to create a new label based on an existing image. You can do this using the derive_label method:
>>> new_label = ome_zarr_container.derive_label("new_label", overwrite=True) # Derive a new label
Label(path=0, Dimensions(z: 1, y: 4320, x: 5120))
This will create a new label with the same dimensions as the original image (without channels) and compatible metadata. If you want to create a new label with slightly different metadata see API Reference.