3. Tables
Tables are not part of the core OME-Zarr specification but can be used in ngio to store measurements, features, regions of interest (ROIs), and other tabular data. Ngio follows the Fractal's Table Spec.
Getting a table
We can list all available tables and load a specific table:
>>> ome_zarr_container.list_tables()
['FOV_ROI_table', 'nuclei_ROI_table', 'well_ROI_table', 'regionprops_DAPI', 'nuclei_measurements_wf3', 'nuclei_measurements_wf4', 'nuclei_lamin_measurements_wf4']
Ngio supports three types of tables: roi_table
, feature_table
, and masking_roi_table
, as well as untyped generic_table
.
ROI tables can be used to store arbitrary regions of interest (ROIs) in the image.
Here for example we will load the FOV_ROI_table
that contains the microscope field of view (FOV) ROIs:
>>> roi_table = ome_zarr_container.get_table("FOV_ROI_table") # Get a ROI table
>>> roi_table.get("FOV_1")
name='FOV_1' x_length=416.0 y_length=351.0 z_length=1.0 x=0.0 y=0.0 z=0.0 x_micrometer_original=np.float32(-1448.3) y_micrometer_original=np.float32(-1517.7)
>>> roi = roi_table.get("FOV_1")
>>> roi_data = image.get_roi(roi)
>>> roi_data.shape
(3, 1, 540, 640)
Masking ROIs are a special type of ROIs that can be used to store ROIs for masked objects in the image.
The nuclei_ROI_table
contains the masks for the nuclei
label in the image, and is indexed by the label id.
>>> masking_table = ome_zarr_container.get_table("nuclei_ROI_table") # Get a mask table
>>> masking_table.get(1)
name='100' x_length=11.375 y_length=14.625 z_length=1.0 x=33.63750076293945 y=18.850000381469727 z=0.0
>>> roi = masking_table.get(100)
>>> roi_data = image.get_roi(roi)
>>> roi_data.shape
(3, 1, 22, 18)
Features tables are used to store measurements and are indexed by the label id
>>> feature_table = ome_zarr_container.get_table("regionprops_DAPI") # Get a feature table
>>> feature_table.dataframe.head(5) # only show the first 5 rows
label | area | bbox_area | equivalent_diameter | max_intensity | mean_intensity | min_intensity | standard_deviation_intensity |
---|---|---|---|---|---|---|---|
1 | 2120 | 2655 | 15.9384 | 476 | 278.636 | 86 | 54.3438 |
2 | 327 | 456 | 8.54771 | 604 | 324.162 | 118 | 90.8471 |
3 | 1381 | 1749 | 13.8165 | 386 | 212.682 | 60 | 50.1696 |
4 | 2566 | 3588 | 16.9858 | 497 | 251.731 | 61 | 53.3072 |
5 | 4201 | 5472 | 20.0194 | 466 | 223.863 | 51 | 56.719 |
Creating a table
Tables (differently from Images and Labels) can be purely in memory objects, and don't need to be saved on disk.
>>> from ngio.tables import RoiTable
>>> from ngio import Roi
>>> roi = Roi(x=0, y=0, x_length=128, y_length=128, name="FOV_1")
>>> roi_table = RoiTable(rois=[roi])
RoiTableV1(num_rois=1)
>>> roi_table = ome_zarr_container.build_image_roi_table("whole_image")
>>> roi_table
RoiTableV1(num_rois=1)
build_image_roi_table
method will create a ROI table with a single ROI that covers the whole image.
This table is not associated with the image and is purely in memory.
If we want to save it to disk, we can use the add_table
method:
>>> ome_zarr_container.add_table("new_roi_table", roi_table, overwrite=True)
>>> roi_table = ome_zarr_container.get_table("new_roi_table")
RoiTableV1(num_rois=1)
Similarly to the ROI table, we can create a masking ROI table on-the-fly:
Let's for example create a masking ROI table for the nuclei
label:
>>> masking_table = ome_zarr_container.build_masking_roi_table("nuclei")
>>> masking_table
MaskingRoiTableV1(num_rois=3006, reference_label=nuclei)
Feature tables can be created from a pandas Dataframe
:
>>> from ngio.tables import FeatureTable
>>> import pandas as pd
>>> example_data = pd.DataFrame({"label": [1, 2, 3], "area": [100, 200, 300]})
>>> feature_table = FeatureTable(dataframe=example_data)
>>> feature_table
FeatureTableV1(num_rows=3, num_columns=1)
Sometimes you might want to create a table that doesn't fit into the ROI
, Masking ROI
, or Feature
categories.
In this case, you can use the GenericTable
class, which allows you to store any tabular data.
It can be created from a pandas Dataframe
:
>>> from ngio.tables import GenericTable
>>> import pandas as pd
>>> example_data = pd.DataFrame({"area": [100, 200, 300], "perimeter": [50, 60, 70]})
>>> generic_table = GenericTable(dataframe=example_data)
>>> generic_table
GenericTable(num_rows=3, num_columns=2, mode=dataframe)
>>> from ngio.tables import GenericTable
>>> import anndata as ad
>>> adata = ad.AnnData(X=np.random.rand(10, 5), obs=pd.DataFrame({"cell_type": ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]}))
>>> generic_table = GenericTable(anndata=adata)
>>> generic_table
GenericTable(mode=anndata)
GenericTable
class allows you to store any tabular data, and is a flexible way to work with tables in ngio.