Skip to content

Commit

Permalink
minor refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzocerrone committed Nov 14, 2024
1 parent 65cb234 commit e4c2bf0
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 57 deletions.
14 changes: 7 additions & 7 deletions docs/notebooks/image.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
"metadata": {},
"outputs": [],
"source": [
"roi_table = ngff_image.table.get_table(\"FOV_ROI_table\")\n",
"roi_table = ngff_image.tables.get_table(\"FOV_ROI_table\")\n",
"roi = roi_table.get_roi(\"FOV_1\")\n",
"print(f\"{roi=}\")\n",
"\n",
Expand Down Expand Up @@ -173,7 +173,7 @@
"\n",
"\n",
"# Load the image from disk and show the edited image\n",
"nuclei = ngff_image.label.get_label(\"nuclei\")\n",
"nuclei = ngff_image.labels.get_label(\"nuclei\")\n",
"fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n",
"axs[0].imshow(image.on_disk_array[0, 0], cmap=\"gray\")\n",
"axs[1].imshow(nuclei.on_disk_array[0])\n",
Expand Down Expand Up @@ -202,7 +202,7 @@
"outputs": [],
"source": [
"# Create a a new label object and set it to a simple segmentation\n",
"new_label = ngff_image.label.derive(\"new_label\", overwrite=True)\n",
"new_label = ngff_image.labels.derive(\"new_label\", overwrite=True)\n",
"\n",
"simple_segmentation = image.on_disk_array[0] > 100\n",
"new_label.on_disk_array[...] = simple_segmentation\n",
Expand Down Expand Up @@ -234,8 +234,8 @@
"metadata": {},
"outputs": [],
"source": [
"label_0 = ngff_image.label.get_label(\"new_label\", path=\"0\")\n",
"label_2 = ngff_image.label.get_label(\"new_label\", path=\"2\")\n",
"label_0 = ngff_image.labels.get_label(\"new_label\", path=\"0\")\n",
"label_2 = ngff_image.labels.get_label(\"new_label\", path=\"2\")\n",
"\n",
"label_before_consolidation = label_2.on_disk_array[...]\n",
"\n",
Expand Down Expand Up @@ -274,10 +274,10 @@
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"print(f\"List of feature table: {ngff_image.table.list(table_type='feature_table')}\")\n",
"print(f\"List of feature table: {ngff_image.tables.list(table_type='feature_table')}\")\n",
"\n",
"\n",
"nuclei = ngff_image.label.get_label('nuclei')\n",
"nuclei = ngff_image.labels.get_label('nuclei')\n",
"\n",
"# Create a table with random features for each nuclei in each ROI\n",
"list_of_records = []\n",
Expand Down
1 change: 0 additions & 1 deletion docs/notebooks/processing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
"metadata": {},
"outputs": [],
"source": [
"\n",
"mip_ngff = ngff_image.derive_new_image(\"../../data/20200812-CardiomyocyteDifferentiation14-Cycle1.zarr/B/03/0_mip\",\n",
" name=\"MIP\",\n",
" on_disk_shape=(1, 1, 2160, 5120))"
Expand Down
3 changes: 2 additions & 1 deletion src/ngio/core/image_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def __repr__(self) -> str:
len_name = len(name)
return (
f"{name}"
f"path={self.path},\n"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}path={self.path},\n"
f"{' ':>{len_name}}{self.pixel_size},\n"
f"{' ':>{len_name}}{self.dimensions},\n"
")"
Expand Down
3 changes: 2 additions & 1 deletion src/ngio/core/label_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def __repr__(self) -> str:
len_name = len(name)
return (
f"{name}"
f"path={self.path},\n"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}path={self.path},\n"
f"{' ':>{len_name}}name={self.name},\n"
f"{' ':>{len_name}}{self.pixel_size},\n"
f"{' ':>{len_name}}{self.dimensions},\n"
Expand Down
41 changes: 31 additions & 10 deletions src/ngio/core/ngff_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import dask.array as da
import numpy as np
import zarr

from ngio.core.image_handler import Image
from ngio.core.label_handler import LabelGroup
Expand All @@ -24,17 +25,19 @@ def __init__(
"""Initialize the NGFFImage in read mode."""
self.store = store
self._mode = mode
self.group = open_group_wrapper(store=store, mode=self._mode)
self._group = open_group_wrapper(store=store, mode=self._mode)

if self.group.read_only:
if self._group.read_only:
self._mode = "r"

self._image_meta = get_ngff_image_meta_handler(
self.group, meta_mode="image", cache=cache
self._group, meta_mode="image", cache=cache
)
self._metadata_cache = cache
self.table = TableGroup(self.group, mode=self._mode)
self.label = LabelGroup(self.group, image_ref=self.get_image(), mode=self._mode)
self.tables = TableGroup(self._group, mode=self._mode)
self.labels = LabelGroup(
self._group, image_ref=self.get_image(), mode=self._mode
)

ngio_logger.info(f"Opened image located in store: {store}")
ngio_logger.info(f"- Image number of levels: {self.num_levels}")
Expand All @@ -45,13 +48,31 @@ def __repr__(self) -> str:
len_name = len(name)
return (
f"{name}"
f"store={self.store}, \n"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}paths={self.levels_paths}, \n"
f"{' ':>{len_name}}labels={self.label.list()}, \n"
f"{' ':>{len_name}}tables={self.table.list()}, \n"
f"{' ':>{len_name}}labels={self.labels.list()}, \n"
f"{' ':>{len_name}}tables={self.tables.list()}, \n"
")"
)

@property
def group(self) -> zarr.Group:
"""Get the group of the image."""
return self._group

@property
def root_path(self) -> str:
"""Get the root path of the image."""
return str(self._group.store.path)

@property
def group_path(self) -> str:
"""Get the path of the group."""
root = self.root_path
if root.endswith("/"):
root = root[:-1]
return f"{root}/{self._group.path}"

@property
def image_meta(self) -> ImageMeta:
"""Get the image metadata."""
Expand Down Expand Up @@ -92,11 +113,11 @@ def get_image(
highest_resolution = False

image = Image(
store=self.group,
store=self._group,
path=path,
pixel_size=pixel_size,
highest_resolution=highest_resolution,
label_group=LabelGroup(self.group, image_ref=None, mode=self._mode),
label_group=LabelGroup(self._group, image_ref=None, mode=self._mode),
cache=self._metadata_cache,
mode=self._mode,
)
Expand Down
24 changes: 15 additions & 9 deletions src/ngio/tables/v1/feature_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,16 @@ def __init__(

def __repr__(self) -> str:
"""Return the string representation of the class."""
region_path = self.meta.region["path"]
label_name = region_path.split("/")[-1]
name = "FeatureTableV1("
len_name = len(name)
return (
f"FeatureTable(name={self.name}, "
f"source_label={label_name}, "
f"features={self.table.columns.to_list()}, "
f"num_labels={len(self.table.index)})"
f"{name}"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}name={self.name},\n"
f"{' ':>{len_name}}features={self.table.columns.to_list()}, \n"
f"{' ':>{len_name}}source_label={self.source_label()}, \n"
f"{' ':>{len_name}}num_labels={len(self.table.index)}), \n"
")"
)

@classmethod
Expand Down Expand Up @@ -156,7 +159,7 @@ def set_table(self, table: pd.DataFrame) -> None:
"""Set the feature table."""
self._table_handler.set_table(table)

def label_image_name(self, get_full_path: bool = False) -> str:
def source_label(self, get_full_path: bool = False) -> str | None:
"""Return the name of the label image.
The name is assumed to be after the last '/' in the path.
Expand All @@ -165,10 +168,13 @@ def label_image_name(self, get_full_path: bool = False) -> str:
Args:
get_full_path (bool): If True, the full path is returned.
"""
path = self.meta.region["path"]
region = self.meta.region
if region is None:
return None
path = region["path"]

if get_full_path:
return path

return path.split("/")[-1]

def consolidate(self) -> None:
Expand Down
42 changes: 30 additions & 12 deletions src/ngio/tables/v1/masking_roi_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pydantic import BaseModel

from ngio.core.label_handler import Label
from ngio.core.roi import WorldCooROI
from ngio.core.roi import SpaceUnits, WorldCooROI
from ngio.tables._utils import validate_columns
from ngio.tables.v1._generic_table import REQUIRED_COLUMNS, BaseTable, write_table_ad

Expand Down Expand Up @@ -81,12 +81,15 @@ def __init__(

def __repr__(self) -> str:
"""Return the string representation of the class."""
region_path = self.meta.region["path"]
label_name = region_path.split("/")[-1]
name = "MaskingROITableV1("
len_name = len(name)
return (
f"MaskingROITable(name={self.name}, "
f"source_label={label_name}, "
f"num_labels={len(self.table.index)})"
f"{name}"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}name={self.name},\n"
f"{' ':>{len_name}}source_label={self.source_label()}, \n"
f"{' ':>{len_name}}num_labels={len(self.table.index)}), \n"
")"
)

@classmethod
Expand Down Expand Up @@ -167,6 +170,24 @@ def table(self, table: pd.DataFrame) -> None:
"Setting the table is not implemented. Please use the 'set_table' method."
)

def source_label(self, get_full_path: bool = False) -> str | None:
"""Return the name of the label image.
The name is assumed to be after the last '/' in the path.
Since this might fails, get_full_path is True, the full path is returned.
Args:
get_full_path (bool): If True, the full path is returned.
"""
region = self.meta.region
if region is None:
return None
path = region["path"]

if get_full_path:
return path
return path.split("/")[-1]

def set_table(self, table: pd.DataFrame) -> None:
"""Set the feature table."""
self._table_handler.set_table(table)
Expand Down Expand Up @@ -196,21 +217,18 @@ def get_roi(self, label: int) -> WorldCooROI:

table_df = self.table.loc[label]

region_path = self.meta.region["path"]
label_name = region_path.split("/")[-1]

roi = WorldCooROI(
x=table_df.loc["x_micrometer"],
y=table_df.loc["y_micrometer"],
z=table_df.loc["z_micrometer"],
x_length=table_df.loc["len_x_micrometer"],
y_length=table_df.loc["len_y_micrometer"],
z_length=table_df.loc["len_z_micrometer"],
unit="micrometer",
unit=SpaceUnits.micrometer,
infos={
"label": label,
"label_image": region_path,
"label_name": label_name,
"source_label_path": self.source_label(get_full_path=True),
"source_label": self.source_label(),
},
)
return roi
Expand Down
19 changes: 16 additions & 3 deletions src/ngio/tables/v1/roi_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import zarr
from pydantic import BaseModel

from ngio.core.roi import WorldCooROI
from ngio.core.roi import SpaceUnits, WorldCooROI
from ngio.tables._utils import validate_columns
from ngio.tables.v1._generic_table import REQUIRED_COLUMNS, BaseTable, write_table_ad

Expand Down Expand Up @@ -141,7 +141,15 @@ def _new(

def __repr__(self) -> str:
"""Return the string representation of the ROI table."""
return f"ROITable(name={self.name}, num_rois={len(self.table.index)})"
name = "ROITableV1("
len_name = len(name)
return (
f"{name}"
f"group_path={self.group_path}, \n"
f"{' ':>{len_name}}name={self.name},\n"
f"{' ':>{len_name}}num_rois={self.num_rois}, \n"
")"
)

@property
def name(self) -> str:
Expand Down Expand Up @@ -189,6 +197,11 @@ def field_indexes(self) -> list[str]:
"""Return a list of all field indexes in the table."""
return self.table.index.tolist()

@property
def num_rois(self) -> int:
"""Return the number of ROIs in the table."""
return len(self.field_indexes)

def set_rois(
self,
rois: Iterable[WorldCooROI] | WorldCooROI,
Expand Down Expand Up @@ -257,7 +270,7 @@ def get_roi(self, field_index: str) -> WorldCooROI:
x_length=table_df.loc["len_x_micrometer"],
y_length=table_df.loc["len_y_micrometer"],
z_length=table_df.loc["len_z_micrometer"],
unit="micrometer",
unit=SpaceUnits.micrometer,
infos={"FieldIndex": field_index, **self._gater_optional_columns(table_df)},
)
return roi
Expand Down
6 changes: 3 additions & 3 deletions tests/core/test_label_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ def test_label_image(self, ome_zarr_image_v04_path: Path) -> None:

ngff_image = NgffImage(ome_zarr_image_v04_path)
image_handler = ngff_image.get_image(path="0")
label_handler = ngff_image.label.derive(name="label")
label_handler = ngff_image.labels.derive(name="label")
label_handler.__repr__()

assert label_handler.array_path == f"{ome_zarr_image_v04_path}/labels/label/0"
assert ngff_image.label.list() == ["label"]
assert ngff_image.labels.list() == ["label"]
assert "c" not in label_handler.axes_names
assert label_handler.shape == image_handler.shape[1:]

Expand All @@ -26,5 +26,5 @@ def test_label_image(self, ome_zarr_image_v04_path: Path) -> None:

label_handler._consolidate()

label_handler_1 = ngff_image.label.get_label(name="label")
label_handler_1 = ngff_image.labels.get_label(name="label")
assert label_handler_1._get_array(t=0, z=0, x=0, y=0) == 1
14 changes: 7 additions & 7 deletions tests/tables/test_table_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,33 @@ def test_table_group(self, ome_zarr_image_v04_path: Path) -> None:

ngff_image = NgffImage(ome_zarr_image_v04_path)

ngff_image.table.new(
ngff_image.tables.new(
name="feat_table",
table_type="feature_table",
label_image="region",
overwrite=True,
)

ngff_image.table.new(
ngff_image.tables.new(
name="roi_table",
table_type="roi_table",
overwrite=False,
)

ngff_image.table.new(
ngff_image.tables.new(
name="masking_roi_table",
table_type="masking_roi_table",
label_image="region",
overwrite=False,
)

assert ngff_image.table.list() == [
assert ngff_image.tables.list() == [
"feat_table",
"roi_table",
"masking_roi_table",
]
assert ngff_image.table.list(table_type="roi_table") == ["roi_table"]
assert ngff_image.table.list(table_type="feature_table") == ["feat_table"]
assert ngff_image.table.list(table_type="masking_roi_table") == [
assert ngff_image.tables.list(table_type="roi_table") == ["roi_table"]
assert ngff_image.tables.list(table_type="feature_table") == ["feat_table"]
assert ngff_image.tables.list(table_type="masking_roi_table") == [
"masking_roi_table"
]
Loading

0 comments on commit e4c2bf0

Please sign in to comment.