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")
Roi(t=None->None, z=0.0->1.0, y=0.0->351.0, x=0.0->416.0)
>>> 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_label(1)
Roi(t=None->None, z=0.0->1.0, y=18.850000381469727->33.47500038146973, x=33.63750076293945->45.01250076293945, label=100)
>>> roi = masking_table.get_label(100)
>>> roi_data = image.get_roi(roi)
>>> roi_data.shape
(3, 1, 23, 19)
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(table_data=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(table_data=example_data)
>>> generic_table
GenericTable
>>> 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(table_data=adata)
>>> generic_table
GenericTable
GenericTable class allows you to store any tabular data, and is a flexible way to work with tables in ngio.