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
PixelSize(x=0.65, y=0.65, z=1.0, t=1.0)
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_array() # Get the image as a numpy array
>>> data.shape, data.dtype
(3, 1, 1080, 1280) uint16
>>> dask_array = image.get_array(mode="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>
>>> dask_delayed = image.get_array(mode="delayed") # Get the image as a dask delayed object
>>> dask_delayed
Delayed('transform_numpy_array-21f175ac-358b-49e8-a04a-b921eea51860')
The get_array
can also be used to slice the image data, and query specific axes in specific orders:
>>> image_slice = image.get_array(c=0, 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_array(c=0, 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, c=0, 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
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.