ngio 0.3.0a0__py3-none-any.whl → 0.3.1__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 (36) hide show
  1. ngio/common/_array_pipe.py +50 -27
  2. ngio/common/_table_ops.py +1 -1
  3. ngio/hcs/__init__.py +1 -1
  4. ngio/hcs/{plate.py → _plate.py} +27 -12
  5. ngio/images/__init__.py +3 -3
  6. ngio/images/{image.py → _image.py} +26 -21
  7. ngio/images/{label.py → _label.py} +6 -4
  8. ngio/images/{masked_image.py → _masked_image.py} +2 -2
  9. ngio/images/{ome_zarr_container.py → _ome_zarr_container.py} +59 -24
  10. ngio/ome_zarr_meta/_meta_handlers.py +16 -8
  11. ngio/ome_zarr_meta/ngio_specs/_axes.py +4 -7
  12. ngio/ome_zarr_meta/ngio_specs/_channels.py +41 -29
  13. ngio/tables/__init__.py +7 -2
  14. ngio/tables/{abstract_table.py → _abstract_table.py} +5 -4
  15. ngio/tables/{tables_container.py → _tables_container.py} +42 -29
  16. ngio/tables/backends/__init__.py +6 -4
  17. ngio/tables/backends/_abstract_backend.py +1 -1
  18. ngio/tables/backends/{_anndata_v1.py → _anndata.py} +1 -1
  19. ngio/tables/backends/{_csv_v1.py → _csv.py} +2 -2
  20. ngio/tables/backends/{_json_v1.py → _json.py} +1 -1
  21. ngio/tables/backends/{_parquet_v1.py → _parquet.py} +2 -2
  22. ngio/tables/backends/_table_backends.py +41 -17
  23. ngio/tables/v1/__init__.py +12 -3
  24. ngio/tables/v1/_condition_table.py +8 -4
  25. ngio/tables/v1/_feature_table.py +11 -13
  26. ngio/tables/v1/_generic_table.py +14 -3
  27. ngio/tables/v1/_roi_table.py +11 -7
  28. ngio/utils/_fractal_fsspec_store.py +1 -1
  29. {ngio-0.3.0a0.dist-info → ngio-0.3.1.dist-info}/METADATA +69 -35
  30. ngio-0.3.1.dist-info/RECORD +61 -0
  31. ngio-0.3.0a0.dist-info/RECORD +0 -61
  32. /ngio/images/{abstract_image.py → _abstract_image.py} +0 -0
  33. /ngio/images/{create.py → _create.py} +0 -0
  34. /ngio/tables/backends/{_non_zarr_backends_v1.py → _non_zarr_backends.py} +0 -0
  35. {ngio-0.3.0a0.dist-info → ngio-0.3.1.dist-info}/WHEEL +0 -0
  36. {ngio-0.3.0a0.dist-info → ngio-0.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -2,15 +2,12 @@
2
2
 
3
3
  from collections.abc import Collection
4
4
  from enum import Enum
5
- from logging import Logger
6
5
  from typing import Literal, TypeVar
7
6
 
8
7
  import numpy as np
9
8
  from pydantic import BaseModel, ConfigDict, Field
10
9
 
11
- from ngio.utils import NgioValidationError, NgioValueError
12
-
13
- logger = Logger(__name__)
10
+ from ngio.utils import NgioValidationError, NgioValueError, ngio_logger
14
11
 
15
12
  T = TypeVar("T")
16
13
 
@@ -102,20 +99,20 @@ class Axis(BaseModel):
102
99
  def implicit_type_cast(self, cast_type: AxisType) -> "Axis":
103
100
  unit = self.unit
104
101
  if self.axis_type != cast_type:
105
- logger.warning(
102
+ ngio_logger.warning(
106
103
  f"Axis {self.on_disk_name} has type {self.axis_type}. "
107
104
  f"Casting to {cast_type}."
108
105
  )
109
106
 
110
107
  if cast_type == AxisType.time and unit is None:
111
- logger.warning(
108
+ ngio_logger.warning(
112
109
  f"Time axis {self.on_disk_name} has unit {self.unit}. "
113
110
  f"Casting to {DefaultSpaceUnit}."
114
111
  )
115
112
  unit = DefaultTimeUnit
116
113
 
117
114
  if cast_type == AxisType.space and unit is None:
118
- logger.warning(
115
+ ngio_logger.warning(
119
116
  f"Space axis {self.on_disk_name} has unit {unit}. "
120
117
  f"Casting to {DefaultSpaceUnit}."
121
118
  )
@@ -329,33 +329,35 @@ class ChannelsMeta(BaseModel):
329
329
  @classmethod
330
330
  def default_init(
331
331
  cls,
332
- labels: Collection[str] | int,
333
- wavelength_id: Collection[str] | None = None,
334
- colors: Collection[str | NgioColors] | None = None,
335
- start: Collection[int | float] | int | float | None = None,
336
- end: Collection[int | float] | int | float | None = None,
337
- active: Collection[bool] | None = None,
332
+ labels: Collection[str | None] | int,
333
+ wavelength_id: Collection[str | None] | None = None,
334
+ colors: Collection[str | NgioColors | None] | None = None,
335
+ start: Collection[int | float | None] | int | float | None = None,
336
+ end: Collection[int | float | None] | int | float | None = None,
337
+ active: Collection[bool | None] | None = None,
338
338
  data_type: Any = np.uint16,
339
339
  **omero_kwargs: dict,
340
340
  ) -> "ChannelsMeta":
341
341
  """Create a ChannelsMeta object with the default unit.
342
342
 
343
343
  Args:
344
- labels(Collection[str] | int): The list of channels names in the image.
345
- If an integer is provided, the channels will be named "channel_i".
346
- wavelength_id(Collection[str] | None): The wavelength ID of the channel.
347
- If None, the wavelength ID will be the same as the channel name.
348
- colors(Collection[str, NgioColors] | None): The list of colors for the
349
- channels. If None, the colors will be random.
350
- start(Collection[int | float] | int | float | None): The start value of the
351
- channel. If None, the start value will be the minimum value of the
352
- data type.
353
- end(Collection[int | float] | int | float | None): The end value of the
354
- channel. If None, the end value will be the maximum value of the
355
- data type.
344
+ labels(Collection[str | None] | int): The list of channels names
345
+ in the image. If an integer is provided, the channels will be
346
+ named "channel_i".
347
+ wavelength_id(Collection[str | None] | None): The wavelength ID of the
348
+ channel. If None, the wavelength ID will be the same as the
349
+ channel name.
350
+ colors(Collection[str | NgioColors | None] | None): The list of
351
+ colors for the channels. If None, the colors will be random.
352
+ start(Collection[int | float | None] | int | float | None): The start
353
+ value of the channel. If None, the start value will be the
354
+ minimum value of the data type.
355
+ end(Collection[int | float | None] | int | float | None): The end
356
+ value of the channel. If None, the end value will be the
357
+ maximum value of the data type.
356
358
  data_type(Any): The data type of the channel. Will be used to set the
357
359
  min and max values of the channel.
358
- active (Collection[bool] | None):active(bool): Whether the channel should
360
+ active (Collection[bool | None] | None): Whether the channel should
359
361
  be shown by default.
360
362
  omero_kwargs(dict): Extra fields to store in the omero attributes.
361
363
  """
@@ -366,25 +368,35 @@ class ChannelsMeta(BaseModel):
366
368
  labels = _check_unique(labels)
367
369
 
368
370
  _wavelength_id: Collection[str | None] = [None] * len(labels)
369
- if isinstance(wavelength_id, Collection):
371
+ if wavelength_id is None:
372
+ _wavelength_id: Collection[str | None] = [None] * len(labels)
373
+ else:
370
374
  _wavelength_id = _check_elements(wavelength_id, str)
371
375
  _wavelength_id = _check_unique(wavelength_id)
372
376
 
373
- _colors: Collection[str | NgioColors | None] = [None] * len(labels)
374
- if isinstance(colors, Collection):
377
+ if colors is None:
378
+ _colors = [NgioColors.semi_random_pick(label) for label in labels]
379
+ else:
375
380
  _colors = _check_elements(colors, str | NgioColors)
376
381
 
377
- _start: Collection[int | float | None] = [None] * len(labels)
378
- if isinstance(start, Collection):
382
+ if start is None:
383
+ _start = [None] * len(labels)
384
+ elif isinstance(start, int | float):
385
+ _start = [start] * len(labels)
386
+ else:
379
387
  _start = _check_elements(start, (int, float))
380
388
 
381
- _end: Collection[int | float | None] = [None] * len(labels)
382
- if isinstance(end, Collection):
389
+ if end is None:
390
+ _end = [None] * len(labels)
391
+ elif isinstance(end, int | float):
392
+ _end = [end] * len(labels)
393
+ else:
383
394
  _end = _check_elements(end, (int, float))
384
395
 
385
- _active: Collection[bool] = [True] * len(labels)
386
- if isinstance(active, Collection):
387
- _active = _check_elements(active, bool)
396
+ if active is None:
397
+ _active = [True] * len(labels)
398
+ else:
399
+ _active = _check_elements(active, (bool,))
388
400
 
389
401
  all_lengths = [
390
402
  len(labels),
ngio/tables/__init__.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """Ngio Tables implementations."""
2
2
 
3
- from ngio.tables.backends import ImplementedTableBackends, TableBackendProtocol
4
- from ngio.tables.tables_container import (
3
+ from ngio.tables._tables_container import (
5
4
  ConditionTable,
6
5
  FeatureTable,
7
6
  GenericRoiTable,
@@ -15,6 +14,11 @@ from ngio.tables.tables_container import (
15
14
  open_table_as,
16
15
  open_tables_container,
17
16
  )
17
+ from ngio.tables.backends import (
18
+ ImplementedTableBackends,
19
+ TableBackend,
20
+ TableBackendProtocol,
21
+ )
18
22
  from ngio.tables.v1._generic_table import GenericTable
19
23
 
20
24
  __all__ = [
@@ -26,6 +30,7 @@ __all__ = [
26
30
  "MaskingRoiTable",
27
31
  "RoiTable",
28
32
  "Table",
33
+ "TableBackend",
29
34
  "TableBackendProtocol",
30
35
  "TableType",
31
36
  "TablesContainer",
@@ -11,6 +11,7 @@ from anndata import AnnData
11
11
  from ngio.tables.backends import (
12
12
  BackendMeta,
13
13
  ImplementedTableBackends,
14
+ TableBackend,
14
15
  TableBackendProtocol,
15
16
  TabularData,
16
17
  convert_to_anndata,
@@ -146,7 +147,7 @@ class AbstractBaseTable(ABC):
146
147
  def _load_backend(
147
148
  meta: BackendMeta,
148
149
  handler: ZarrGroupHandler,
149
- backend: str | TableBackendProtocol,
150
+ backend: TableBackend,
150
151
  ) -> TableBackendProtocol:
151
152
  """Create a new ROI table from a Zarr group handler."""
152
153
  if isinstance(backend, str):
@@ -202,7 +203,7 @@ class AbstractBaseTable(ABC):
202
203
  def set_backend(
203
204
  self,
204
205
  handler: ZarrGroupHandler | None = None,
205
- backend: str | TableBackendProtocol = "anndata_v1",
206
+ backend: TableBackend = "anndata",
206
207
  ) -> None:
207
208
  """Set the backend of the table."""
208
209
  if handler is None:
@@ -226,7 +227,7 @@ class AbstractBaseTable(ABC):
226
227
  cls,
227
228
  handler: ZarrGroupHandler,
228
229
  meta_model: builtins.type[BackendMeta],
229
- backend: str | TableBackendProtocol | None = None,
230
+ backend: TableBackend | None = None,
230
231
  ) -> Self:
231
232
  """Create a new ROI table from a Zarr group handler."""
232
233
  meta = meta_model(**handler.load_attrs())
@@ -241,7 +242,7 @@ class AbstractBaseTable(ABC):
241
242
  def from_handler(
242
243
  cls,
243
244
  handler: ZarrGroupHandler,
244
- backend: str | TableBackendProtocol | None = None,
245
+ backend: TableBackend | None = None,
245
246
  ) -> Self:
246
247
  """Create a new ROI table from a Zarr group handler."""
247
248
  pass
@@ -8,7 +8,7 @@ import polars as pl
8
8
 
9
9
  from ngio.tables.backends import (
10
10
  BackendMeta,
11
- TableBackendProtocol,
11
+ TableBackend,
12
12
  TabularData,
13
13
  )
14
14
  from ngio.tables.v1 import (
@@ -90,7 +90,7 @@ class Table(Protocol):
90
90
  def set_backend(
91
91
  self,
92
92
  handler: ZarrGroupHandler | None = None,
93
- backend: str | TableBackendProtocol = "anndata_v1",
93
+ backend: TableBackend = "anndata",
94
94
  ) -> None:
95
95
  """Set the backend store and path for the table.
96
96
 
@@ -105,7 +105,7 @@ class Table(Protocol):
105
105
  def from_handler(
106
106
  cls,
107
107
  handler: ZarrGroupHandler,
108
- backend: str | TableBackendProtocol | None = None,
108
+ backend: TableBackend | None = None,
109
109
  ) -> "Table":
110
110
  """Create a new table from a Zarr group handler."""
111
111
  ...
@@ -126,25 +126,30 @@ class Table(Protocol):
126
126
 
127
127
 
128
128
  TypedTable = Literal[
129
+ "generic_table",
129
130
  "roi_table",
130
131
  "masking_roi_table",
131
132
  "feature_table",
132
- "generic_roi_table",
133
133
  "condition_table",
134
134
  ]
135
135
 
136
+ TypedRoiTable = Literal[
137
+ "roi_table",
138
+ "masking_roi_table",
139
+ ]
140
+
136
141
  TableType = TypeVar("TableType", bound=Table)
137
142
 
138
143
 
139
144
  class TableMeta(BackendMeta):
140
145
  """Base class for table metadata."""
141
146
 
142
- fractal_table_version: str = "1"
147
+ table_version: str = "1"
143
148
  type: str = "generic_table"
144
149
 
145
150
  def unique_name(self) -> str:
146
151
  """Return the unique name for the table."""
147
- return f"{self.type}_v{self.fractal_table_version}"
152
+ return f"{self.type}_v{self.table_version}"
148
153
 
149
154
 
150
155
  def _get_meta(handler: ZarrGroupHandler) -> TableMeta:
@@ -175,7 +180,7 @@ class ImplementedTables:
175
180
  self,
176
181
  meta: TableMeta,
177
182
  handler: ZarrGroupHandler,
178
- backend: str | TableBackendProtocol | None = None,
183
+ backend: TableBackend | None = None,
179
184
  strict: bool = True,
180
185
  ) -> Table:
181
186
  """Try to get a handler for the given store based on the metadata version."""
@@ -192,19 +197,34 @@ class ImplementedTables:
192
197
  table = table_cls.from_handler(handler=handler, backend=backend)
193
198
  return table
194
199
 
195
- def add_implementation(self, handler: type[Table], overwrite: bool = False):
200
+ def _add_implementation(
201
+ self, handler: type[Table], name: str, overwrite: bool = False
202
+ ) -> None:
203
+ """Register a new table handler."""
204
+ if name in self._implemented_tables and not overwrite:
205
+ raise NgioValueError(
206
+ f"Table handler for {name} already implemented. "
207
+ "Use overwrite=True to replace it."
208
+ )
209
+ self._implemented_tables[name] = handler
210
+
211
+ def add_implementation(
212
+ self,
213
+ handler: type[Table],
214
+ overwrite: bool = False,
215
+ aliases: list[str] | None = None,
216
+ ) -> None:
196
217
  """Register a new table handler."""
197
218
  meta = TableMeta(
198
219
  type=handler.table_type(),
199
- fractal_table_version=handler.version(),
220
+ table_version=handler.version(),
200
221
  )
201
222
 
202
- if meta.unique_name() in self._implemented_tables and not overwrite:
203
- raise NgioValueError(
204
- f"Table handler for {meta.unique_name()} already implemented. "
205
- "Use overwrite=True to replace it."
206
- )
207
- self._implemented_tables[meta.unique_name()] = handler
223
+ self._add_implementation(handler, meta.unique_name(), overwrite)
224
+
225
+ if aliases is not None:
226
+ for alias in aliases:
227
+ self._add_implementation(handler, alias, overwrite)
208
228
 
209
229
 
210
230
  class TablesContainer:
@@ -240,14 +260,7 @@ class TablesContainer:
240
260
  handler = self._group_handler.derive_handler(path=name)
241
261
  return handler
242
262
 
243
- def list_roi_tables(self) -> list[str]:
244
- """List all ROI tables in the group."""
245
- _tables = []
246
- for _type in ["roi_table", "masking_roi_table"]:
247
- _tables.extend(self.list(_type))
248
- return _tables
249
-
250
- def list(self, filter_types: str | None = None) -> list[str]:
263
+ def list(self, filter_types: TypedTable | str | None = None) -> list[str]:
251
264
  """List all labels in the group."""
252
265
  tables = self._get_tables_list()
253
266
  if filter_types is None:
@@ -264,7 +277,7 @@ class TablesContainer:
264
277
  def get(
265
278
  self,
266
279
  name: str,
267
- backend: str | TableBackendProtocol | None = None,
280
+ backend: TableBackend | None = None,
268
281
  strict: bool = True,
269
282
  ) -> Table:
270
283
  """Get a label from the group."""
@@ -285,7 +298,7 @@ class TablesContainer:
285
298
  self,
286
299
  name: str,
287
300
  table_cls: type[TableType],
288
- backend: str | TableBackendProtocol | None = None,
301
+ backend: TableBackend | None = None,
289
302
  ) -> TableType:
290
303
  """Get a table from the group as a specific type."""
291
304
  if name not in self.list():
@@ -301,7 +314,7 @@ class TablesContainer:
301
314
  self,
302
315
  name: str,
303
316
  table: Table,
304
- backend: str | TableBackendProtocol = "anndata_v1",
317
+ backend: TableBackend = "anndata",
305
318
  overwrite: bool = False,
306
319
  ) -> None:
307
320
  """Add a table to the group."""
@@ -357,7 +370,7 @@ def open_tables_container(
357
370
 
358
371
  def open_table(
359
372
  store: StoreOrGroup,
360
- backend: str | TableBackendProtocol | None = None,
373
+ backend: TableBackend | None = None,
361
374
  cache: bool = False,
362
375
  mode: AccessModeLiteral = "a",
363
376
  parallel_safe: bool = False,
@@ -375,7 +388,7 @@ def open_table(
375
388
  def open_table_as(
376
389
  store: StoreOrGroup,
377
390
  table_cls: type[TableType],
378
- backend: str | TableBackendProtocol = "anndata_v1",
391
+ backend: TableBackend | None = None,
379
392
  cache: bool = False,
380
393
  mode: AccessModeLiteral = "a",
381
394
  parallel_safe: bool = False,
@@ -393,7 +406,7 @@ def open_table_as(
393
406
  def write_table(
394
407
  store: StoreOrGroup,
395
408
  table: Table,
396
- backend: str | TableBackendProtocol = "anndata_v1",
409
+ backend: TableBackend = "anndata",
397
410
  cache: bool = False,
398
411
  mode: AccessModeLiteral = "a",
399
412
  parallel_safe: bool = False,
@@ -1,12 +1,13 @@
1
1
  """Ngio Tables backend implementations."""
2
2
 
3
3
  from ngio.tables.backends._abstract_backend import AbstractTableBackend, BackendMeta
4
- from ngio.tables.backends._anndata_v1 import AnnDataBackend
5
- from ngio.tables.backends._csv_v1 import CsvTableBackend
6
- from ngio.tables.backends._json_v1 import JsonTableBackend
7
- from ngio.tables.backends._parquet_v1 import ParquetTableBackend
4
+ from ngio.tables.backends._anndata import AnnDataBackend
5
+ from ngio.tables.backends._csv import CsvTableBackend
6
+ from ngio.tables.backends._json import JsonTableBackend
7
+ from ngio.tables.backends._parquet import ParquetTableBackend
8
8
  from ngio.tables.backends._table_backends import (
9
9
  ImplementedTableBackends,
10
+ TableBackend,
10
11
  TableBackendProtocol,
11
12
  )
12
13
  from ngio.tables.backends._utils import (
@@ -34,6 +35,7 @@ __all__ = [
34
35
  "ImplementedTableBackends",
35
36
  "JsonTableBackend",
36
37
  "ParquetTableBackend",
38
+ "TableBackend",
37
39
  "TableBackendProtocol",
38
40
  "TabularData",
39
41
  "convert_anndata_to_pandas",
@@ -19,7 +19,7 @@ from ngio.utils import NgioValueError, ZarrGroupHandler
19
19
  class BackendMeta(BaseModel):
20
20
  """Metadata for the backend."""
21
21
 
22
- backend: str = "anndata_v1"
22
+ backend: str = "anndata"
23
23
  index_key: str | None = None
24
24
  index_type: Literal["int", "str"] | None = None
25
25
 
@@ -21,7 +21,7 @@ class AnnDataBackend(AbstractTableBackend):
21
21
  @staticmethod
22
22
  def backend_name() -> str:
23
23
  """Return the name of the backend."""
24
- return "anndata_v1"
24
+ return "anndata"
25
25
 
26
26
  @staticmethod
27
27
  def implements_anndata() -> bool:
@@ -1,7 +1,7 @@
1
1
  import pandas as pd
2
2
  import polars as pl
3
3
 
4
- from ngio.tables.backends._non_zarr_backends_v1 import NonZarrBaseBackend
4
+ from ngio.tables.backends._non_zarr_backends import NonZarrBaseBackend
5
5
 
6
6
 
7
7
  def write_lf_to_csv(path: str, table: pl.DataFrame) -> None:
@@ -32,4 +32,4 @@ class CsvTableBackend(NonZarrBaseBackend):
32
32
  @staticmethod
33
33
  def backend_name() -> str:
34
34
  """Return the name of the backend."""
35
- return "experimental_csv_v1"
35
+ return "csv"
@@ -17,7 +17,7 @@ class JsonTableBackend(AbstractTableBackend):
17
17
  @staticmethod
18
18
  def backend_name() -> str:
19
19
  """Return the name of the backend."""
20
- return "experimental_json_v1"
20
+ return "json"
21
21
 
22
22
  @staticmethod
23
23
  def implements_anndata() -> bool:
@@ -1,7 +1,7 @@
1
1
  import pandas as pd
2
2
  import polars as pl
3
3
 
4
- from ngio.tables.backends._non_zarr_backends_v1 import NonZarrBaseBackend
4
+ from ngio.tables.backends._non_zarr_backends import NonZarrBaseBackend
5
5
 
6
6
 
7
7
  def write_lf_to_parquet(path: str, table: pl.DataFrame) -> None:
@@ -44,4 +44,4 @@ class ParquetTableBackend(NonZarrBaseBackend):
44
44
  @staticmethod
45
45
  def backend_name() -> str:
46
46
  """Return the name of the backend."""
47
- return "experimental_parquet_v1"
47
+ return "parquet"
@@ -7,10 +7,10 @@ from pandas import DataFrame
7
7
  from polars import DataFrame as PolarsDataFrame
8
8
  from polars import LazyFrame
9
9
 
10
- from ngio.tables.backends._anndata_v1 import AnnDataBackend
11
- from ngio.tables.backends._csv_v1 import CsvTableBackend
12
- from ngio.tables.backends._json_v1 import JsonTableBackend
13
- from ngio.tables.backends._parquet_v1 import ParquetTableBackend
10
+ from ngio.tables.backends._anndata import AnnDataBackend
11
+ from ngio.tables.backends._csv import CsvTableBackend
12
+ from ngio.tables.backends._json import JsonTableBackend
13
+ from ngio.tables.backends._parquet import ParquetTableBackend
14
14
  from ngio.tables.backends._utils import TabularData
15
15
  from ngio.utils import NgioValueError, ZarrGroupHandler
16
16
 
@@ -167,7 +167,7 @@ class ImplementedTableBackends:
167
167
  self,
168
168
  *,
169
169
  group_handler: ZarrGroupHandler,
170
- backend_name: str = "anndata_v1",
170
+ backend_name: str = "anndata",
171
171
  index_key: str | None = None,
172
172
  index_type: Literal["int", "str"] | None = None,
173
173
  ) -> TableBackendProtocol:
@@ -180,22 +180,46 @@ class ImplementedTableBackends:
180
180
  )
181
181
  return backend
182
182
 
183
- def add_backend(
183
+ def _add_backend(
184
184
  self,
185
- table_beckend: type[TableBackendProtocol],
185
+ table_backend: type[TableBackendProtocol],
186
+ name: str,
186
187
  overwrite: bool = False,
187
- ):
188
+ ) -> None:
188
189
  """Register a new handler."""
189
- backend_name = table_beckend.backend_name()
190
- if backend_name in self._implemented_backends and not overwrite:
190
+ if name in self._implemented_backends and not overwrite:
191
191
  raise NgioValueError(
192
- f"Table backend {backend_name} already implemented. "
192
+ f"Table backend {name} already implemented. "
193
193
  "Use the `overwrite=True` parameter to overwrite it."
194
194
  )
195
- self._implemented_backends[backend_name] = table_beckend
196
-
195
+ self._implemented_backends[name] = table_backend
197
196
 
198
- ImplementedTableBackends().add_backend(AnnDataBackend)
199
- ImplementedTableBackends().add_backend(JsonTableBackend)
200
- ImplementedTableBackends().add_backend(CsvTableBackend)
201
- ImplementedTableBackends().add_backend(ParquetTableBackend)
197
+ def add_backend(
198
+ self,
199
+ table_backend: type[TableBackendProtocol],
200
+ overwrite: bool = False,
201
+ aliases: list[str] | None = None,
202
+ ) -> None:
203
+ """Register a new handler."""
204
+ self._add_backend(
205
+ table_backend=table_backend,
206
+ name=table_backend.backend_name(),
207
+ overwrite=overwrite,
208
+ )
209
+ if aliases is not None:
210
+ for alias in aliases:
211
+ self._add_backend(
212
+ table_backend=table_backend, name=alias, overwrite=overwrite
213
+ )
214
+
215
+
216
+ ImplementedTableBackends().add_backend(AnnDataBackend, aliases=["anndata_v1"])
217
+ ImplementedTableBackends().add_backend(
218
+ JsonTableBackend, aliases=["experimental_json_v1"]
219
+ )
220
+ ImplementedTableBackends().add_backend(CsvTableBackend, aliases=["experimental_csv_v1"])
221
+ ImplementedTableBackends().add_backend(
222
+ ParquetTableBackend, aliases=["experimental_parquet_v1"]
223
+ )
224
+
225
+ TableBackend = Literal["anndata", "json", "csv", "parquet"] | str | TableBackendProtocol
@@ -1,14 +1,23 @@
1
1
  """Tables implementations for fractal_tables v1."""
2
2
 
3
- from ngio.tables.v1._condition_table import ConditionTableV1
4
- from ngio.tables.v1._feature_table import FeatureTableV1
3
+ from ngio.tables.v1._condition_table import ConditionTableMeta, ConditionTableV1
4
+ from ngio.tables.v1._feature_table import FeatureTableMeta, FeatureTableV1
5
5
  from ngio.tables.v1._generic_table import GenericTable
6
- from ngio.tables.v1._roi_table import MaskingRoiTableV1, RoiTableV1
6
+ from ngio.tables.v1._roi_table import (
7
+ MaskingRoiTableV1,
8
+ MaskingRoiTableV1Meta,
9
+ RoiTableV1,
10
+ RoiTableV1Meta,
11
+ )
7
12
 
8
13
  __all__ = [
14
+ "ConditionTableMeta",
9
15
  "ConditionTableV1",
16
+ "FeatureTableMeta",
10
17
  "FeatureTableV1",
11
18
  "GenericTable",
12
19
  "MaskingRoiTableV1",
20
+ "MaskingRoiTableV1Meta",
13
21
  "RoiTableV1",
22
+ "RoiTableV1Meta",
14
23
  ]
@@ -1,14 +1,18 @@
1
1
  """Implementation of a generic table class."""
2
2
 
3
- from ngio.tables.abstract_table import AbstractBaseTable
4
- from ngio.tables.backends import BackendMeta, TableBackendProtocol, TabularData
3
+ from ngio.tables._abstract_table import AbstractBaseTable
4
+ from ngio.tables.backends import (
5
+ BackendMeta,
6
+ TableBackend,
7
+ TabularData,
8
+ )
5
9
  from ngio.utils import ZarrGroupHandler
6
10
 
7
11
 
8
12
  class ConditionTableMeta(BackendMeta):
9
13
  """Metadata for the condition table."""
10
14
 
11
- fractal_table_version: str | None = "1"
15
+ table_version: str | None = "1"
12
16
  type: str | None = "condition_table"
13
17
 
14
18
 
@@ -58,7 +62,7 @@ class ConditionTableV1(AbstractBaseTable):
58
62
  def from_handler(
59
63
  cls,
60
64
  handler: ZarrGroupHandler,
61
- backend: str | TableBackendProtocol | None = None,
65
+ backend: TableBackend | None = None,
62
66
  ) -> "ConditionTableV1":
63
67
  return cls._from_handler(
64
68
  handler=handler,