Basic Usage¶
In this notebook we will show how to use the 'ngffImage' class to manage a OME-NGFF image.
For this example we will use a small example image that can be downloaded from the following link: example ome-zarr
You can download the example image (on Linux and Mac os) by running the following command:
bash setup_data.sh
from the root of the repository.
NgffImage¶
The NgffImage
provides a high-level interface to read, write and manipulate NGFF images.
A NgffImage
can be created from a storelike object (e.g. a path to a directory or a zarr store) or from a zarr.Group
object.
from ngio.core import NgffImage
ngff_image = NgffImage("../../data/20200812-CardiomyocyteDifferentiation14-Cycle1_mip.zarr/B/03/0")
The ngff_image
contains several attributes and methods to interact with the OME-NGFF
(OME-Zarr
) file on the storage.
# Explore object metadata
print("Levels: ", ngff_image.levels_paths)
print("Num Levels: ", ngff_image.num_levels)
Levels: ['0', '1', '2', '3', '4'] Num Levels: 5
Get a single level
of the image pyramid as Image
(to know more about the Image
class, please refer to the Image notebook
The Image
object is the main object to interact with the image.
It contains methods to interact with the image data and metadata.
from ngio.ngff_meta import PixelSize
# 1. Get image from highest resolution (default)
image = ngff_image.get_image()
print(f"{image.shape=}")
print(f"{image.pixel_size=}")
# 2. Get image from a specific level using the path keyword
print(f"{image.shape=}")
print(f"{image.pixel_size=}")
# 3. Get image from a specific pixel size using the pixel_size keyword
image = ngff_image.get_image(pixel_size=PixelSize(x=0.65, y=0.65, z=1))
print(f"{image.shape=}")
print(f"{image.pixel_size=}")
image.shape=(3, 1, 4320, 5120) image.pixel_size=PixelSize(x=0.1625, y=0.1625, z=1.0, unit=<SpaceUnits.micrometer: 'micrometer'>, virtual=False) image.shape=(3, 1, 4320, 5120) image.pixel_size=PixelSize(x=0.1625, y=0.1625, z=1.0, unit=<SpaceUnits.micrometer: 'micrometer'>, virtual=False) image.shape=(3, 1, 1080, 1280) image.pixel_size=PixelSize(x=0.65, y=0.65, z=1.0, unit=<SpaceUnits.micrometer: 'micrometer'>, virtual=True)
Labels¶
The NgffImage
can also be used to load labels from a OME-NGFF
file.
print("List of Labels: ", ngff_image.label.list())
label_nuclei = ngff_image.label.get_label("nuclei", path="0")
print(f"{label_nuclei.shape=}")
print(f"{label_nuclei.pixel_size=}")
List of Labels: ['nuclei', 'wf_2_labels', 'wf_3_labels', 'wf_4_labels'] label_nuclei.shape=(1, 4320, 5120) label_nuclei.pixel_size=PixelSize(x=0.1625, y=0.1625, z=1.0, unit=<SpaceUnits.micrometer: 'micrometer'>, virtual=False)
Tables¶
The NgffImage
can also be used to load tables from a OME-NGFF
file.
ngio
supports three types of tables:
features table
A simple table to store features associated with a label.roi table
A table to store regions of interest.masking roi tables
A table to store single objects bounding boxes associated with a label.
print("List of Tables: ", ngff_image.table.list())
print(" - Feature tables: ", ngff_image.table.list(table_type='feature_table'))
print(" - Roi tables: ", ngff_image.table.list(table_type='roi_table'))
print(" - Masking Roi tables: ", ngff_image.table.list(table_type='masking_roi_table'))
List of Tables: ['FOV_ROI_table', 'nuclei_ROI_table', 'well_ROI_table', 'regionprops_DAPI', 'nuclei_measurements_wf3', 'nuclei_measurements_wf4', 'nuclei_lamin_measurements_wf4'] - Feature tables: ['regionprops_DAPI', 'nuclei_measurements_wf3', 'nuclei_measurements_wf4', 'nuclei_lamin_measurements_wf4'] - Roi tables: ['FOV_ROI_table', 'well_ROI_table'] - Masking Roi tables: ['nuclei_ROI_table']
# Loading a table
feature_table = ngff_image.table.get_table("regionprops_DAPI")
feature_table.table
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/anndata/_core/aligned_df.py:68: ImplicitModificationWarning: Transforming to str index. warnings.warn("Transforming to str index.", ImplicitModificationWarning)
area | bbox_area | equivalent_diameter | max_intensity | mean_intensity | min_intensity | standard_deviation_intensity | |
---|---|---|---|---|---|---|---|
label | |||||||
1 | 2120.0 | 2655.0 | 15.938437 | 476.0 | 278.635864 | 86.0 | 54.343792 |
2 | 327.0 | 456.0 | 8.547709 | 604.0 | 324.162079 | 118.0 | 90.847092 |
3 | 1381.0 | 1749.0 | 13.816510 | 386.0 | 212.682114 | 60.0 | 50.169601 |
4 | 2566.0 | 3588.0 | 16.985800 | 497.0 | 251.731491 | 61.0 | 53.307186 |
5 | 4201.0 | 5472.0 | 20.019413 | 466.0 | 223.862885 | 51.0 | 56.719025 |
... | ... | ... | ... | ... | ... | ... | ... |
3002 | 1026.0 | 1288.0 | 12.513618 | 589.0 | 308.404480 | 132.0 | 64.681778 |
3003 | 859.0 | 1080.0 | 11.794101 | 400.0 | 270.349243 | 107.0 | 49.040470 |
3004 | 508.0 | 660.0 | 9.899693 | 314.0 | 205.043304 | 82.0 | 33.249981 |
3005 | 369.0 | 440.0 | 8.899028 | 376.0 | 217.970184 | 82.0 | 50.978519 |
3006 | 278.0 | 330.0 | 8.097459 | 339.0 | 217.996399 | 100.0 | 38.510067 |
3006 rows × 7 columns
# Loading a roi table
roi_table = ngff_image.table.get_table("FOV_ROI_table")
print(f"{roi_table.field_indexes=}")
print(f"{roi_table.get_roi('FOV_1')=}")
roi_table.table
roi_table.field_indexes=['FOV_1', 'FOV_2', 'FOV_3', 'FOV_4'] roi_table.get_roi('FOV_1')=WorldCooROI(x_length=416.0, y_length=351.0, z_length=1.0, x=0.0, y=0.0, z=0.0)
x_micrometer | y_micrometer | z_micrometer | len_x_micrometer | len_y_micrometer | len_z_micrometer | x_micrometer_original | y_micrometer_original | |
---|---|---|---|---|---|---|---|---|
FieldIndex | ||||||||
FOV_1 | 0.0 | 0.0 | 0.0 | 416.0 | 351.0 | 1.0 | -1448.300049 | -1517.699951 |
FOV_2 | 416.0 | 0.0 | 0.0 | 416.0 | 351.0 | 1.0 | -1032.300049 | -1517.699951 |
FOV_3 | 0.0 | 351.0 | 0.0 | 416.0 | 351.0 | 1.0 | -1448.300049 | -1166.699951 |
FOV_4 | 416.0 | 351.0 | 0.0 | 416.0 | 351.0 | 1.0 | -1032.300049 | -1166.699951 |
Derive a new NgffImage¶
When processing an image, it is often useful to derive a new image from the original image.
The NgffImage
class provides a method to derive a new image from the original image.
When deriving a new image, a new NgffImage
object is created with the same metadata as the original image. Optionally the
user can specify different metadata for the new image(.e.g. different channels names).
new_ngff_image = ngff_image.derive_new_image("../../data/new_ome.zarr", name="new_image")
print(f"{new_ngff_image.store=}")
print(f"{new_ngff_image.levels_paths=}")
print(f"{new_ngff_image.num_levels=}")
new_ngff_image.store='../../data/new_ome.zarr' new_ngff_image.levels_paths=['0', '1', '2', '3', '4'] new_ngff_image.num_levels=5