ngio 0.1.6__py3-none-any.whl → 0.2.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. ngio/__init__.py +31 -5
  2. ngio/common/__init__.py +44 -0
  3. ngio/common/_array_pipe.py +160 -0
  4. ngio/common/_axes_transforms.py +63 -0
  5. ngio/common/_common_types.py +5 -0
  6. ngio/common/_dimensions.py +113 -0
  7. ngio/common/_pyramid.py +222 -0
  8. ngio/{core/roi.py → common/_roi.py} +22 -23
  9. ngio/common/_slicer.py +97 -0
  10. ngio/{pipes/_zoom_utils.py → common/_zoom.py} +2 -78
  11. ngio/hcs/__init__.py +60 -0
  12. ngio/images/__init__.py +23 -0
  13. ngio/images/abstract_image.py +240 -0
  14. ngio/images/create.py +251 -0
  15. ngio/images/image.py +383 -0
  16. ngio/images/label.py +96 -0
  17. ngio/images/omezarr_container.py +512 -0
  18. ngio/ome_zarr_meta/__init__.py +35 -0
  19. ngio/ome_zarr_meta/_generic_handlers.py +320 -0
  20. ngio/ome_zarr_meta/_meta_handlers.py +142 -0
  21. ngio/ome_zarr_meta/ngio_specs/__init__.py +63 -0
  22. ngio/ome_zarr_meta/ngio_specs/_axes.py +481 -0
  23. ngio/ome_zarr_meta/ngio_specs/_channels.py +378 -0
  24. ngio/ome_zarr_meta/ngio_specs/_dataset.py +134 -0
  25. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +5 -0
  26. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +434 -0
  27. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +84 -0
  28. ngio/ome_zarr_meta/v04/__init__.py +11 -0
  29. ngio/ome_zarr_meta/v04/_meta_handlers.py +54 -0
  30. ngio/ome_zarr_meta/v04/_v04_spec_utils.py +412 -0
  31. ngio/tables/__init__.py +21 -5
  32. ngio/tables/_validators.py +192 -0
  33. ngio/tables/backends/__init__.py +8 -0
  34. ngio/tables/backends/_abstract_backend.py +71 -0
  35. ngio/tables/backends/_anndata_utils.py +194 -0
  36. ngio/tables/backends/_anndata_v1.py +75 -0
  37. ngio/tables/backends/_json_v1.py +56 -0
  38. ngio/tables/backends/_table_backends.py +102 -0
  39. ngio/tables/tables_container.py +300 -0
  40. ngio/tables/v1/__init__.py +6 -5
  41. ngio/tables/v1/_feature_table.py +161 -0
  42. ngio/tables/v1/_generic_table.py +99 -182
  43. ngio/tables/v1/_masking_roi_table.py +175 -0
  44. ngio/tables/v1/_roi_table.py +226 -0
  45. ngio/utils/__init__.py +23 -10
  46. ngio/utils/_datasets.py +51 -0
  47. ngio/utils/_errors.py +10 -4
  48. ngio/utils/_zarr_utils.py +378 -0
  49. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/METADATA +18 -39
  50. ngio-0.2.0a1.dist-info/RECORD +53 -0
  51. ngio/core/__init__.py +0 -7
  52. ngio/core/dimensions.py +0 -122
  53. ngio/core/image_handler.py +0 -228
  54. ngio/core/image_like_handler.py +0 -549
  55. ngio/core/label_handler.py +0 -410
  56. ngio/core/ngff_image.py +0 -387
  57. ngio/core/utils.py +0 -287
  58. ngio/io/__init__.py +0 -19
  59. ngio/io/_zarr.py +0 -88
  60. ngio/io/_zarr_array_utils.py +0 -0
  61. ngio/io/_zarr_group_utils.py +0 -60
  62. ngio/iterators/__init__.py +0 -1
  63. ngio/ngff_meta/__init__.py +0 -27
  64. ngio/ngff_meta/fractal_image_meta.py +0 -1267
  65. ngio/ngff_meta/meta_handler.py +0 -92
  66. ngio/ngff_meta/utils.py +0 -235
  67. ngio/ngff_meta/v04/__init__.py +0 -6
  68. ngio/ngff_meta/v04/specs.py +0 -158
  69. ngio/ngff_meta/v04/zarr_utils.py +0 -376
  70. ngio/pipes/__init__.py +0 -7
  71. ngio/pipes/_slicer_transforms.py +0 -176
  72. ngio/pipes/_transforms.py +0 -33
  73. ngio/pipes/data_pipe.py +0 -52
  74. ngio/tables/_ad_reader.py +0 -80
  75. ngio/tables/_utils.py +0 -301
  76. ngio/tables/tables_group.py +0 -252
  77. ngio/tables/v1/feature_tables.py +0 -182
  78. ngio/tables/v1/masking_roi_tables.py +0 -243
  79. ngio/tables/v1/roi_tables.py +0 -285
  80. ngio/utils/_common_types.py +0 -5
  81. ngio/utils/_pydantic_utils.py +0 -52
  82. ngio-0.1.6.dist-info/RECORD +0 -44
  83. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/WHEEL +0 -0
  84. {ngio-0.1.6.dist-info → ngio-0.2.0a1.dist-info}/licenses/LICENSE +0 -0
ngio/tables/_ad_reader.py DELETED
@@ -1,80 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Any
4
-
5
- import zarr
6
- from anndata import AnnData
7
- from anndata._io.specs import read_elem
8
- from anndata._io.utils import _read_legacy_raw
9
- from anndata._io.zarr import read_dataframe
10
- from anndata.compat import _clean_uns
11
- from anndata.experimental import read_dispatched
12
-
13
- from ngio.io import open_group_wrapper
14
-
15
- if TYPE_CHECKING:
16
- from collections.abc import Callable
17
-
18
- from ngio.io import StoreOrGroup
19
-
20
-
21
- def custom_read_zarr(store: StoreOrGroup) -> AnnData:
22
- """Read from a hierarchical Zarr array store.
23
-
24
- # Implementation originally from https://github.com/scverse/anndata/blob/main/src/anndata/_io/zarr.py
25
- # Original implementation would not work with remote storages so we had to copy it
26
- # here and slightly modified it to work with remote storages.
27
-
28
- Args:
29
- store (StoreOrGroup): A store or group to read the AnnData from.
30
- """
31
- group = open_group_wrapper(store=store, mode="r")
32
-
33
- # Read with handling for backwards compat
34
- def callback(func: Callable, elem_name: str, elem: Any, iospec: Any) -> Any:
35
- if iospec.encoding_type == "anndata" or elem_name.endswith("/"):
36
- ad_kwargs = {}
37
- # Some of these elem fail on https
38
- # So we only include the ones that are strictly necessary
39
- # for fractal tables
40
- base_elem = [
41
- "X",
42
- # "layers",
43
- "obs",
44
- # "obsm",
45
- # "obsp",
46
- # "uns",
47
- "var",
48
- # "varm",
49
- # "varp",
50
- ]
51
- # This fails on some https
52
- # base_elem += list(elem.keys())
53
- for k in set(base_elem):
54
- v = elem.get(k)
55
- if v is not None and not k.startswith("raw."):
56
- ad_kwargs[k] = read_dispatched(v, callback)
57
- return AnnData(**ad_kwargs)
58
-
59
- elif elem_name.startswith("/raw."):
60
- return None
61
- elif elem_name in {"/obs", "/var"}:
62
- return read_dataframe(elem)
63
- elif elem_name == "/raw":
64
- # Backwards compat
65
- return _read_legacy_raw(group, func(elem), read_dataframe, func)
66
- return func(elem)
67
-
68
- adata = read_dispatched(group, callback=callback)
69
-
70
- # Backwards compat (should figure out which version)
71
- if "raw.X" in group:
72
- raw = AnnData(**_read_legacy_raw(group, adata.raw, read_dataframe, read_elem))
73
- raw.obs_names = adata.obs_names
74
- adata.raw = raw
75
-
76
- # Backwards compat for <0.7
77
- if isinstance(group["obs"], zarr.Array):
78
- _clean_uns(adata)
79
-
80
- return adata
ngio/tables/_utils.py DELETED
@@ -1,301 +0,0 @@
1
- from collections.abc import Callable
2
- from typing import Literal
3
-
4
- import anndata as ad
5
- import numpy as np
6
- import pandas as pd
7
- import pandas.api.types as ptypes
8
-
9
- from ngio.utils import NgioTableValidationError
10
-
11
- Validator = Callable[[pd.DataFrame], pd.DataFrame]
12
-
13
-
14
- def _check_for_mixed_types(series: pd.Series) -> None:
15
- """Check if the column has mixed types."""
16
- if series.apply(type).nunique() > 1:
17
- raise NgioTableValidationError(
18
- f"Column {series.name} has mixed types: "
19
- f"{series.apply(type).unique()}. "
20
- "Type of all elements must be the same."
21
- )
22
-
23
-
24
- def _check_for_supported_types(series: pd.Series) -> Literal["str", "int", "numeric"]:
25
- """Check if the column has supported types."""
26
- if ptypes.is_string_dtype(series):
27
- return "str"
28
- if ptypes.is_integer_dtype(series):
29
- return "int"
30
- if ptypes.is_numeric_dtype(series):
31
- return "numeric"
32
- raise NgioTableValidationError(
33
- f"Column {series.name} has unsupported type: {series.dtype}."
34
- " Supported types are string and numerics."
35
- )
36
-
37
-
38
- def _check_index_key(
39
- table_df: pd.DataFrame, index_key: str, index_type: Literal["str", "int"]
40
- ) -> pd.DataFrame:
41
- """Check if the index_key correctness.
42
-
43
- - Check if the index_key is present in the data frame.
44
- (If the index_key is a column in the DataFrame, it is set as the index)
45
- - Check if the index_key is of the correct type.
46
-
47
- Args:
48
- table_df (pd.DataFrame): The DataFrame to validate.
49
- index_key (str): The column name to use as the index of the DataFrame.
50
- index_type (str): The type of the index column in the DataFrame.
51
- Either 'str' or 'int'. Default is 'int'.
52
-
53
- Returns:
54
- pd.DataFrame: The validated DataFrame.
55
- """
56
- columns = table_df.columns
57
- if index_key in columns:
58
- table_df = table_df.set_index(index_key)
59
-
60
- if table_df.index.name != index_key:
61
- raise NgioTableValidationError(
62
- f"index_key: {index_key} not found in data frame"
63
- )
64
-
65
- if index_type == "str":
66
- if ptypes.is_integer_dtype(table_df.index):
67
- # Convert the int index to string is generally safe
68
- table_df.index = table_df.index.astype(str)
69
-
70
- if not ptypes.is_string_dtype(table_df.index):
71
- raise NgioTableValidationError(
72
- f"index_key {index_key} must be of string type"
73
- )
74
-
75
- elif index_type == "int":
76
- if ptypes.is_string_dtype(table_df.index):
77
- # Try to convert the string index to int
78
- try:
79
- table_df.index = table_df.index.astype(int)
80
- except ValueError as e:
81
- if "invalid literal for int() with base 10" in str(e):
82
- raise NgioTableValidationError(
83
- f"index_key {index_key} must be of "
84
- "integer type, but found string. We "
85
- "tried implicit conversion failed."
86
- ) from None
87
- else:
88
- raise e from e
89
-
90
- if not ptypes.is_integer_dtype(table_df.index):
91
- raise NgioTableValidationError(
92
- f"index_key {index_key} must be of integer type"
93
- )
94
-
95
- else:
96
- raise NgioTableValidationError(f"index_type {index_type} not recognized")
97
-
98
- return table_df
99
-
100
-
101
- def validate_table(
102
- table_df: pd.DataFrame,
103
- index_key: str,
104
- index_type: Literal["str", "int"],
105
- validators: list[Validator] | None,
106
- ) -> pd.DataFrame:
107
- """Validate the table DataFrame.
108
-
109
- - Check if the index_key is present in the data frame.
110
- (If the index_key is a column in the DataFrame, it is set as the index)
111
- - Check if the index_key is of the correct type.
112
- - Apply all provided optional validators.
113
-
114
- Args:
115
- table_df (pd.DataFrame): The DataFrame to validate.
116
- index_key (str): The column name to use as the index of the DataFrame.
117
- index_type (str): The type of the index column in the DataFrame.
118
- validators (list[Validator]): A list of functions to further validate table.
119
-
120
- Returns:
121
- pd.DataFrame: The validated DataFrame.
122
- """
123
- table_df = _check_index_key(table_df, index_key, index_type)
124
-
125
- if validators is None:
126
- return table_df
127
-
128
- # Apply all provided validators
129
- for validator in validators:
130
- table_df = validator(table_df)
131
-
132
- return table_df
133
-
134
-
135
- def table_df_to_ad(
136
- table_df: pd.DataFrame,
137
- index_key: str,
138
- index_type: Literal["str", "int"] = "int",
139
- validators: list[Validator] | None = None,
140
- ) -> ad.AnnData:
141
- """Convert a table DataFrame to an AnnData object.
142
-
143
- Args:
144
- table_df (pd.DataFrame): A pandas DataFrame representing a fractal table.
145
- index_key (str): The column name to use as the index of the DataFrame.
146
- index_type (str): The type of the index column in the DataFrame.
147
- Either 'str' or 'int'. Default is 'int'.
148
- validators (list[Validator]): A list of functions to further validate the table.
149
- """
150
- # Check if the index_key is present in the data frame + optional validations
151
- table_df = validate_table(
152
- table_df=table_df,
153
- index_key=index_key,
154
- index_type=index_type,
155
- validators=validators,
156
- )
157
-
158
- # DO NOT SKIP
159
- # Convert the index to string ALWAYS to avoid casting issues in AnnData
160
- table_df.index = table_df.index.astype(str)
161
-
162
- str_columns, int_columns, num_columns = [], [], []
163
- for c_name in table_df.columns:
164
- column_df = table_df[c_name]
165
- _check_for_mixed_types(column_df) # Mixed types are not allowed in the table
166
- c_type = _check_for_supported_types(
167
- column_df
168
- ) # Only string and numeric types are allowed
169
-
170
- if c_type == "str":
171
- str_columns.append(c_name)
172
-
173
- elif c_type == "int":
174
- int_columns.append(c_name)
175
-
176
- elif c_type == "numeric":
177
- num_columns.append(c_name)
178
-
179
- # Converting all observations to string
180
- obs_df = table_df[str_columns + int_columns]
181
- obs_df.index = table_df.index
182
-
183
- x_df = table_df[num_columns]
184
-
185
- if x_df.dtypes.nunique() > 1:
186
- x_df = x_df.astype("float64")
187
-
188
- if x_df.empty:
189
- # If there are no numeric columns, create an empty array
190
- # to avoid AnnData failing to create the object
191
- x_df = np.zeros((0, 0), dtype="float64")
192
-
193
- return ad.AnnData(X=x_df, obs=obs_df)
194
-
195
-
196
- def table_ad_to_df(
197
- table_ad: ad.AnnData,
198
- index_key: str = "label",
199
- index_type: Literal["str", "int"] = "int",
200
- validators: list[Validator] | None = None,
201
- validate_index_name: bool = False,
202
- ) -> pd.DataFrame:
203
- """Convert a AnnData object representing a fractal table to a pandas DataFrame.
204
-
205
- Args:
206
- table_ad (ad.AnnData): An AnnData object representing a fractal table.
207
- index_key (str): The column name to use as the index of the DataFrame.
208
- Default is 'label'.
209
- index_type (str): The type of the index column in the DataFrame.
210
- Either 'str' or 'int'. Default is 'int'.
211
- validators (list[Validator]): A list of functions to further validate the table.
212
- validate_index_name (bool): If True, the index name is validated.
213
- """
214
- table_df = table_ad.to_df()
215
- table_df[table_ad.obs_keys()] = table_ad.obs
216
-
217
- # Set the index of the DataFrame
218
- if index_key in table_df.columns:
219
- table_df = table_df.set_index(index_key)
220
- elif table_ad.obs.index.name is not None:
221
- if validate_index_name:
222
- if table_ad.obs.index.name != index_key:
223
- raise NgioTableValidationError(
224
- f"Index key {index_key} not found in AnnData object."
225
- )
226
- table_df.index = table_ad.obs.index
227
- elif table_ad.obs.index.name is None:
228
- table_df.index = table_ad.obs.index
229
- table_df.index.name = index_key
230
- else:
231
- raise NgioTableValidationError(
232
- f"Index key {index_key} not found in AnnData object."
233
- )
234
-
235
- table_df = validate_table(
236
- table_df=table_df,
237
- index_key=index_key,
238
- index_type=index_type,
239
- validators=validators,
240
- )
241
- return table_df
242
-
243
-
244
- ####################################################################################################
245
- #
246
- # Common table validators
247
- #
248
- ####################################################################################################
249
-
250
-
251
- def validate_columns(
252
- table_df: pd.DataFrame,
253
- required_columns: list[str],
254
- optional_columns: list[str] | None = None,
255
- ) -> pd.DataFrame:
256
- """Validate the columns headers of the table.
257
-
258
- If a required column is missing, a TableValidationError is raised.
259
- If a list of optional columns is provided, only required and optional columns are
260
- allowed in the table.
261
-
262
- Args:
263
- table_df (pd.DataFrame): The DataFrame to validate.
264
- required_columns (list[str]): A list of required columns.
265
- optional_columns (list[str] | None): A list of optional columns.
266
- Default is None.
267
-
268
- Returns:
269
- pd.DataFrame: The validated DataFrame.
270
- """
271
- table_header = table_df.columns
272
- for column in required_columns:
273
- if column not in table_header:
274
- raise NgioTableValidationError(
275
- f"Could not find required column: {column} in the table"
276
- )
277
-
278
- if optional_columns is None:
279
- return table_df
280
-
281
- possible_columns = [*required_columns, *optional_columns]
282
- for column in table_header:
283
- if column not in possible_columns:
284
- raise NgioTableValidationError(
285
- f"Could not find column: {column} in the list of possible columns. ",
286
- f"Possible columns are: {possible_columns}",
287
- )
288
-
289
- return table_df
290
-
291
-
292
- def validate_unique_index(table_df: pd.DataFrame) -> pd.DataFrame:
293
- """Validate that the index of the table is unique."""
294
- if table_df.index.is_unique:
295
- return table_df
296
-
297
- # Find the duplicates
298
- duplicates = table_df.index[table_df.index.duplicated()].tolist()
299
- raise NgioTableValidationError(
300
- f"Index of the table contains duplicates values. Duplicate: {duplicates}"
301
- )
@@ -1,252 +0,0 @@
1
- """Module for handling the /tables group in an OME-NGFF file."""
2
-
3
- from typing import Literal
4
- from warnings import warn
5
-
6
- import zarr
7
- from pydantic import ValidationError
8
-
9
- from ngio.core.utils import State
10
- from ngio.io import AccessModeLiteral, StoreLike
11
- from ngio.tables.v1 import FeatureTableV1, MaskingROITableV1, ROITableV1
12
- from ngio.utils import ngio_logger
13
- from ngio.utils._pydantic_utils import BaseWithExtraFields
14
-
15
- ROITable = ROITableV1
16
- IMPLEMENTED_ROI_TABLES = {"1": ROITableV1}
17
-
18
- FeatureTable = FeatureTableV1
19
- IMPLEMENTED_FEATURE_TABLES = {"1": FeatureTableV1}
20
-
21
- MaskingROITable = MaskingROITableV1
22
- IMPLEMENTED_MASKING_ROI_TABLES = {"1": MaskingROITableV1}
23
-
24
- Table = ROITable | FeatureTable | MaskingROITable
25
-
26
- TableType = Literal["roi_table", "feature_table", "masking_roi_table"]
27
-
28
-
29
- class CommonMeta(BaseWithExtraFields):
30
- """Common metadata for all tables."""
31
-
32
- type: TableType
33
- fractal_table_version: str = "1"
34
-
35
-
36
- def _find_table_impl(
37
- table_type: TableType,
38
- version: str,
39
- ) -> Table:
40
- """Find the type of table in the group."""
41
- if table_type == "roi_table":
42
- if version not in IMPLEMENTED_ROI_TABLES:
43
- raise ValueError(f"ROI Table version {version} not implemented.")
44
- return IMPLEMENTED_ROI_TABLES[version]
45
-
46
- elif table_type == "feature_table":
47
- if version not in IMPLEMENTED_FEATURE_TABLES:
48
- raise ValueError(f"Feature Table version {version} not implemented.")
49
- return IMPLEMENTED_FEATURE_TABLES[version]
50
-
51
- elif table_type == "masking_roi_table":
52
- if version not in IMPLEMENTED_MASKING_ROI_TABLES:
53
- raise ValueError(f"Masking ROI Table version {version} not implemented.")
54
- return IMPLEMENTED_MASKING_ROI_TABLES[version]
55
-
56
- else:
57
- raise ValueError(f"Table type {table_type} not recognized.")
58
-
59
-
60
- def _get_table_impl(
61
- group: zarr.Group,
62
- name: str,
63
- validate_metadata: bool = True,
64
- table_type: TableType | None = None,
65
- validate_table: bool = True,
66
- index_key: str | None = None,
67
- ) -> Table:
68
- if validate_metadata:
69
- common_meta = CommonMeta(**group.attrs)
70
- table_type = common_meta.type
71
- else:
72
- common_meta = CommonMeta.model_construct(**group.attrs)
73
- if table_type is None:
74
- raise ValueError(
75
- "Table type must be provided if metadata is not validated."
76
- )
77
-
78
- version = common_meta.fractal_table_version
79
- return _find_table_impl(table_type=table_type, version=version)(
80
- group=group,
81
- name=name,
82
- validate_metadata=validate_metadata,
83
- validate_table=validate_table,
84
- index_key=index_key,
85
- )
86
-
87
-
88
- class TableGroup:
89
- """A class to handle the /labels group in an OME-NGFF file."""
90
-
91
- def __init__(
92
- self, group: StoreLike | zarr.Group, mode: AccessModeLiteral = "r+"
93
- ) -> None:
94
- """Initialize the LabelGroupHandler."""
95
- self._mode = mode
96
- if not isinstance(group, zarr.Group):
97
- group = zarr.open_group(group, mode=self._mode)
98
-
99
- table_group = group.get("tables", None)
100
-
101
- if table_group is None and not group.read_only:
102
- table_group = group.create_group("tables")
103
- table_group.attrs["tables"] = []
104
-
105
- assert isinstance(table_group, zarr.Group) or table_group is None
106
- self._table_group = table_group
107
-
108
- if table_group is None or table_group.read_only:
109
- self._state = State.MEMORY
110
- else:
111
- self._state = State.CONSOLIDATED
112
-
113
- self._virtual_tables: list[Table] = []
114
-
115
- def _validate_list_of_tables(self, list_of_tables: list[str]) -> None:
116
- """Validate the list of tables.
117
-
118
- Args:
119
- list_of_tables (list[str]): The list of tables to validate.
120
- """
121
- if self._table_group is None:
122
- return None
123
-
124
- for table_name in list_of_tables:
125
- table = self._table_group.get(table_name, None)
126
- if table is None:
127
- ngio_logger.warning(
128
- f"Table {table_name} not found in the group. "
129
- "Consider removing it from the list of tables."
130
- )
131
-
132
- def _get_list_of_tables(self) -> list[str]:
133
- """Return the list of tables."""
134
- if self._table_group is None:
135
- return []
136
-
137
- list_of_tables = self._table_group.attrs.get("tables", [])
138
- self._validate_list_of_tables(list_of_tables)
139
- assert isinstance(list_of_tables, list)
140
- assert all(isinstance(table_name, str) for table_name in list_of_tables)
141
- return list_of_tables
142
-
143
- def list(
144
- self,
145
- table_type: TableType | None = None,
146
- ) -> list[str]:
147
- """List all labels in the group.
148
-
149
- Args:
150
- table_type (str): The type of table to list.
151
- If None, all tables are listed.
152
- Allowed values are: 'roi_table', 'feature_table', 'masking_roi_table'.
153
- """
154
- if self._table_group is None:
155
- return []
156
-
157
- list_of_tables = self._get_list_of_tables()
158
- self._validate_list_of_tables(list_of_tables=list_of_tables)
159
-
160
- all_table_types = ["roi_table", "feature_table", "masking_roi_table"]
161
-
162
- if table_type is None:
163
- return list_of_tables
164
-
165
- else:
166
- if table_type not in all_table_types:
167
- raise ValueError(
168
- f"Table type {table_type} not recognized. "
169
- f" Allowed values are: {all_table_types}"
170
- )
171
- list_of_typed_tables = []
172
- for table_name in list_of_tables:
173
- table = self._table_group[table_name]
174
- try:
175
- common_meta = CommonMeta(**table.attrs)
176
- if common_meta.type == table_type:
177
- list_of_typed_tables.append(table_name)
178
- except ValidationError:
179
- warn(
180
- f"Table {table_name} metadata is not correctly formatted.",
181
- stacklevel=1,
182
- )
183
- return list_of_typed_tables
184
-
185
- def get_table(
186
- self,
187
- name: str,
188
- table_type: TableType | None = None,
189
- validate_metadata: bool = True,
190
- validate_table: bool = True,
191
- index_key: str | None = None,
192
- ) -> Table:
193
- """Get a label from the group.
194
-
195
- Args:
196
- name (str): The name of the table to get.
197
- table_type (str): The type of table to get.
198
- If None, all the table type will be inferred from the metadata.
199
- Allowed values are: 'roi_table', 'feature_table', 'masking_roi_table'.
200
- validate_metadata (bool): Whether to validate the metadata of the table.
201
- validate_table (bool): Whether to validate the table.
202
- index_key (str): The column name to use as the index of the DataFrame.
203
- This is usually defined in the metadata of the table, if given here,
204
- it will overwrite the metadata.
205
- """
206
- if self._table_group is None:
207
- raise ValueError("No tables group found in the group.")
208
-
209
- list_of_tables = self._get_list_of_tables()
210
- if name not in list_of_tables:
211
- raise ValueError(f"Table {name} not found in the group.")
212
-
213
- return _get_table_impl(
214
- group=self._table_group[name],
215
- name=name,
216
- validate_metadata=validate_metadata,
217
- table_type=table_type,
218
- validate_table=validate_table,
219
- index_key=index_key,
220
- )
221
-
222
- def new(
223
- self,
224
- name: str,
225
- table_type: TableType = "roi_table",
226
- overwrite: bool = False,
227
- version: str = "1",
228
- **type_specific_kwargs: dict,
229
- ) -> Table:
230
- """Add a new table to the group."""
231
- if self._table_group is None:
232
- raise ValueError("No tables group found in the group.")
233
-
234
- list_of_tables = self._get_list_of_tables()
235
- if not overwrite and name in list_of_tables:
236
- raise ValueError(f"Table {name} already exists in the group.")
237
-
238
- if overwrite and name in list_of_tables:
239
- list_of_tables.remove(name)
240
-
241
- table_impl = _find_table_impl(table_type=table_type, version=version)
242
- new_table = table_impl._new(
243
- parent_group=self._table_group,
244
- name=name,
245
- overwrite=overwrite,
246
- **type_specific_kwargs,
247
- )
248
-
249
- self._table_group.attrs["tables"] = [*list_of_tables, name]
250
-
251
- assert isinstance(new_table, ROITable | FeatureTable | MaskingROITable)
252
- return new_table