ngio 0.5.0__py3-none-any.whl → 0.5.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 (54) hide show
  1. ngio/__init__.py +2 -5
  2. ngio/common/__init__.py +6 -11
  3. ngio/common/_masking_roi.py +54 -34
  4. ngio/common/_pyramid.py +87 -321
  5. ngio/common/_roi.py +330 -258
  6. ngio/experimental/iterators/_feature.py +3 -3
  7. ngio/experimental/iterators/_rois_utils.py +11 -10
  8. ngio/hcs/_plate.py +136 -192
  9. ngio/images/_abstract_image.py +35 -539
  10. ngio/images/_create.py +283 -0
  11. ngio/images/_create_synt_container.py +43 -40
  12. ngio/images/_image.py +251 -517
  13. ngio/images/_label.py +172 -249
  14. ngio/images/_masked_image.py +2 -2
  15. ngio/images/_ome_zarr_container.py +241 -644
  16. ngio/io_pipes/_io_pipes.py +9 -9
  17. ngio/io_pipes/_io_pipes_masked.py +7 -7
  18. ngio/io_pipes/_io_pipes_roi.py +6 -6
  19. ngio/io_pipes/_io_pipes_types.py +3 -3
  20. ngio/io_pipes/_match_shape.py +8 -6
  21. ngio/io_pipes/_ops_slices_utils.py +5 -8
  22. ngio/ome_zarr_meta/__init__.py +18 -29
  23. ngio/ome_zarr_meta/_meta_handlers.py +708 -392
  24. ngio/ome_zarr_meta/ngio_specs/__init__.py +0 -4
  25. ngio/ome_zarr_meta/ngio_specs/_axes.py +51 -152
  26. ngio/ome_zarr_meta/ngio_specs/_dataset.py +22 -13
  27. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +91 -129
  28. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +68 -57
  29. ngio/ome_zarr_meta/v04/__init__.py +1 -5
  30. ngio/ome_zarr_meta/v04/{_v04_spec.py → _v04_spec_utils.py} +85 -54
  31. ngio/ome_zarr_meta/v05/__init__.py +1 -5
  32. ngio/ome_zarr_meta/v05/{_v05_spec.py → _v05_spec_utils.py} +87 -64
  33. ngio/resources/__init__.py +1 -1
  34. ngio/resources/resource_model.py +1 -1
  35. ngio/tables/_tables_container.py +27 -85
  36. ngio/tables/backends/_anndata.py +8 -58
  37. ngio/tables/backends/_anndata_utils.py +6 -1
  38. ngio/tables/backends/_csv.py +19 -3
  39. ngio/tables/backends/_json.py +13 -10
  40. ngio/tables/backends/_non_zarr_backends.py +196 -0
  41. ngio/tables/backends/_parquet.py +31 -3
  42. ngio/tables/v1/_roi_table.py +27 -44
  43. ngio/utils/__init__.py +12 -8
  44. ngio/utils/_datasets.py +0 -6
  45. ngio/utils/_logger.py +50 -0
  46. ngio/utils/_zarr_utils.py +250 -292
  47. {ngio-0.5.0.dist-info → ngio-0.5.0a1.dist-info}/METADATA +6 -13
  48. ngio-0.5.0a1.dist-info/RECORD +88 -0
  49. {ngio-0.5.0.dist-info → ngio-0.5.0a1.dist-info}/WHEEL +1 -1
  50. ngio/images/_create_utils.py +0 -406
  51. ngio/tables/backends/_py_arrow_backends.py +0 -222
  52. ngio/utils/_cache.py +0 -48
  53. ngio-0.5.0.dist-info/RECORD +0 -88
  54. {ngio-0.5.0.dist-info → ngio-0.5.0a1.dist-info}/licenses/LICENSE +0 -0
@@ -1,38 +1,33 @@
1
1
  """Base class for handling OME-NGFF metadata in Zarr groups."""
2
2
 
3
- from collections.abc import Callable
4
- from typing import TypeVar
3
+ from typing import Generic, Protocol, TypeVar
4
+
5
+ from pydantic import ValidationError
5
6
 
6
7
  from ngio.ome_zarr_meta.ngio_specs import (
7
8
  AxesSetup,
8
9
  NgioImageMeta,
9
10
  NgioLabelMeta,
10
- NgioLabelsGroupMeta,
11
11
  NgioPlateMeta,
12
12
  NgioWellMeta,
13
13
  )
14
- from ngio.ome_zarr_meta.ngio_specs._ngio_image import NgffVersions
15
14
  from ngio.ome_zarr_meta.v04 import (
16
15
  ngio_to_v04_image_meta,
17
16
  ngio_to_v04_label_meta,
18
- ngio_to_v04_labels_group_meta,
19
17
  ngio_to_v04_plate_meta,
20
18
  ngio_to_v04_well_meta,
21
19
  v04_to_ngio_image_meta,
22
20
  v04_to_ngio_label_meta,
23
- v04_to_ngio_labels_group_meta,
24
21
  v04_to_ngio_plate_meta,
25
22
  v04_to_ngio_well_meta,
26
23
  )
27
24
  from ngio.ome_zarr_meta.v05 import (
28
25
  ngio_to_v05_image_meta,
29
26
  ngio_to_v05_label_meta,
30
- ngio_to_v05_labels_group_meta,
31
27
  ngio_to_v05_plate_meta,
32
28
  ngio_to_v05_well_meta,
33
29
  v05_to_ngio_image_meta,
34
30
  v05_to_ngio_label_meta,
35
- v05_to_ngio_labels_group_meta,
36
31
  v05_to_ngio_plate_meta,
37
32
  v05_to_ngio_well_meta,
38
33
  )
@@ -42,471 +37,792 @@ from ngio.utils import (
42
37
  ZarrGroupHandler,
43
38
  )
44
39
 
45
- # This could be replaced with a more dynamic registry if needed in the future
46
- _image_encoder_registry = {"0.4": ngio_to_v04_image_meta, "0.5": ngio_to_v05_image_meta}
47
- _image_decoder_registry = {"0.4": v04_to_ngio_image_meta, "0.5": v05_to_ngio_image_meta}
48
- _label_encoder_registry = {"0.4": ngio_to_v04_label_meta, "0.5": ngio_to_v05_label_meta}
49
- _label_decoder_registry = {"0.4": v04_to_ngio_label_meta, "0.5": v05_to_ngio_label_meta}
50
- _plate_encoder_registry = {"0.4": ngio_to_v04_plate_meta, "0.5": ngio_to_v05_plate_meta}
51
- _plate_decoder_registry = {"0.4": v04_to_ngio_plate_meta, "0.5": v05_to_ngio_plate_meta}
52
- _well_encoder_registry = {"0.4": ngio_to_v04_well_meta, "0.5": ngio_to_v05_well_meta}
53
- _well_decoder_registry = {"0.4": v04_to_ngio_well_meta, "0.5": v05_to_ngio_well_meta}
54
- _labels_group_encoder_registry = {
55
- "0.4": ngio_to_v04_labels_group_meta,
56
- "0.5": ngio_to_v05_labels_group_meta,
57
- }
58
- _labels_group_decoder_registry = {
59
- "0.4": v04_to_ngio_labels_group_meta,
60
- "0.5": v05_to_ngio_labels_group_meta,
61
- }
62
-
63
- _meta_type = TypeVar(
64
- "_meta_type",
65
- NgioImageMeta,
66
- NgioLabelMeta,
67
- NgioLabelsGroupMeta,
68
- NgioPlateMeta,
69
- NgioWellMeta,
70
- )
40
+ ConverterError = ValidationError | Exception | None
71
41
 
42
+ ###########################################################################
43
+ #
44
+ # The code below implements a generic class for handling OME-Zarr metadata
45
+ # in Zarr groups.
46
+ #
47
+ ###########################################################################
72
48
 
73
- def _find_encoder_registry(
74
- ngio_meta: _meta_type,
75
- ) -> dict[str, Callable]:
76
- if isinstance(ngio_meta, NgioImageMeta):
77
- return _image_encoder_registry
78
- elif isinstance(ngio_meta, NgioLabelMeta):
79
- return _label_encoder_registry
80
- elif isinstance(ngio_meta, NgioPlateMeta):
81
- return _plate_encoder_registry
82
- elif isinstance(ngio_meta, NgioWellMeta):
83
- return _well_encoder_registry
84
- elif isinstance(ngio_meta, NgioLabelsGroupMeta):
85
- return _labels_group_encoder_registry
86
- else:
87
- raise NgioValueError(f"Unsupported NGIO metadata type: {type(ngio_meta)}")
88
-
89
-
90
- def update_ngio_meta(
91
- group_handler: ZarrGroupHandler,
92
- ngio_meta: _meta_type,
93
- ) -> None:
94
- """Update the metadata in the Zarr group.
95
-
96
- Args:
97
- group_handler (ZarrGroupHandler): The Zarr group handler.
98
- ngio_meta (_meta_type): The new NGIO metadata.
99
-
100
- """
101
- registry = _find_encoder_registry(ngio_meta)
102
- exporter = registry.get(ngio_meta.version)
103
- if exporter is None:
104
- raise NgioValueError(f"Unsupported NGFF version: {ngio_meta.version}")
105
-
106
- zarr_meta = exporter(ngio_meta)
107
- group_handler.write_attrs(zarr_meta)
108
-
109
-
110
- def _find_decoder_registry(
111
- meta_type: type[_meta_type],
112
- ) -> dict[str, Callable]:
113
- if meta_type is NgioImageMeta:
114
- return _image_decoder_registry
115
- elif meta_type is NgioLabelMeta:
116
- return _label_decoder_registry
117
- elif meta_type is NgioPlateMeta:
118
- return _plate_decoder_registry
119
- elif meta_type is NgioWellMeta:
120
- return _well_decoder_registry
121
- elif meta_type is NgioLabelsGroupMeta:
122
- return _labels_group_decoder_registry
123
- else:
124
- raise NgioValueError(f"Unsupported NGIO metadata type: {meta_type}")
125
-
126
-
127
- def get_ngio_meta(
128
- group_handler: ZarrGroupHandler,
129
- meta_type: type[_meta_type],
130
- version: str | None = None,
131
- **kwargs,
132
- ) -> _meta_type:
133
- """Retrieve the NGIO metadata from the Zarr group.
134
-
135
- Args:
136
- group_handler (ZarrGroupHandler): The Zarr group handler.
137
- meta_type (type[_meta_type]): The type of NGIO metadata to retrieve.
138
- version (str | None): Optional NGFF version to use for decoding.
139
- **kwargs: Additional arguments to pass to the decoder.
140
-
141
- Returns:
142
- _meta_type: The NGIO metadata.
143
- """
144
- registry = _find_decoder_registry(meta_type)
145
- if version is not None:
146
- decoder = registry.get(version)
147
- if decoder is None:
148
- raise NgioValueError(f"Unsupported NGFF version: {version}")
149
- versions_to_try = {version: decoder}
150
- else:
151
- versions_to_try = registry
152
-
153
- attrs = group_handler.load_attrs()
154
- all_errors = []
155
- for version, decoder in versions_to_try.items():
156
- try:
157
- ngio_meta = decoder(attrs, **kwargs)
158
- return ngio_meta
159
- except Exception as e:
160
- all_errors.append(f"Version {version}: {e}")
161
- error_message = (
162
- f"Failed to decode NGIO {meta_type.__name__} metadata:\n"
163
- + "\n".join(all_errors)
164
- )
165
- raise NgioValidationError(error_message)
166
49
 
50
+ class ImageMetaImporter(Protocol):
51
+ @staticmethod
52
+ def __call__(
53
+ metadata: dict,
54
+ axes_setup: AxesSetup | None = None,
55
+ allow_non_canonical_axes: bool = False,
56
+ strict_canonical_order: bool = True,
57
+ ) -> tuple[bool, NgioImageMeta | ConverterError]:
58
+ """Convert the metadata to a NgioImageMeta object.
167
59
 
168
- ##################################################
169
- #
170
- # Concrete implementations for NGIO metadata types
171
- #
172
- ##################################################
60
+ Args:
61
+ metadata (dict): The metadata (typically from a Zarr group .attrs).
62
+ axes_setup (AxesSetup, optional): The axes setup.
63
+ This is used to map axes with non-canonical names.
64
+ allow_non_canonical_axes (bool, optional): Whether to allow non-canonical
65
+ axes.
66
+ strict_canonical_order (bool, optional): Whether to enforce a strict
67
+ canonical order.
173
68
 
69
+ Returns:
70
+ tuple[bool, NgioImageMeta | ConverterError]: A tuple with a boolean
71
+ indicating whether the conversion was successful and the
72
+ NgioImageMeta object or an error.
174
73
 
175
- def get_ngio_image_meta(
176
- group_handler: ZarrGroupHandler,
177
- version: str | None = None,
178
- axes_setup: AxesSetup | None = None,
179
- ) -> NgioImageMeta:
180
- """Retrieve the NGIO image metadata from the Zarr group.
181
-
182
- Args:
183
- group_handler (ZarrGroupHandler): The Zarr group handler.
184
- version (str | None): Optional NGFF version to use for decoding.
185
- axes_setup (AxesSetup | None): Optional axes setup for validation.
186
-
187
- Returns:
188
- NgioImageMeta: The NGIO image metadata.
189
- """
190
- # axes_setup = axes_setup or AxesSetup(x="XX")
191
- return get_ngio_meta(
192
- group_handler=group_handler,
193
- meta_type=NgioImageMeta,
194
- version=version,
195
- axes_setup=axes_setup,
196
- )
74
+ """
75
+ ...
197
76
 
198
77
 
199
- def update_ngio_image_meta(
200
- group_handler: ZarrGroupHandler,
201
- ngio_meta: NgioImageMeta,
202
- ) -> None:
203
- """Update the NGIO image metadata in the Zarr group.
78
+ class ImageMetaExporter(Protocol):
79
+ def __call__(self, metadata: NgioImageMeta) -> dict: ...
204
80
 
205
- Args:
206
- group_handler (ZarrGroupHandler): The Zarr group handler.
207
- ngio_meta (NgioImageMeta): The new NGIO image metadata.
208
81
 
209
- """
210
- update_ngio_meta(
211
- group_handler=group_handler,
212
- ngio_meta=ngio_meta,
213
- )
82
+ class LabelMetaImporter(Protocol):
83
+ @staticmethod
84
+ def __call__(
85
+ metadata: dict,
86
+ axes_setup: AxesSetup | None = None,
87
+ allow_non_canonical_axes: bool = False,
88
+ strict_canonical_order: bool = True,
89
+ ) -> tuple[bool, NgioLabelMeta | ConverterError]:
90
+ """Convert the metadata to a NgioLabelMeta object.
91
+
92
+ Args:
93
+ metadata (dict): The metadata (typically from a Zarr group .attrs).
94
+ axes_setup (AxesSetup, optional): The axes setup.
95
+ This is used to map axes with non-canonical names.
96
+ allow_non_canonical_axes (bool, optional): Whether to allow non-canonical
97
+ axes.
98
+ strict_canonical_order (bool, optional): Whether to enforce a strict
99
+ canonical order.
100
+
101
+ Returns:
102
+ tuple[bool, NgioLabelMeta | ConverterError]: A tuple with a boolean
103
+ indicating whether the conversion was successful and the
104
+ NgioLabelMeta object or an error.
105
+
106
+ """
107
+ ...
214
108
 
215
109
 
216
- class ImageMetaHandler:
110
+ class LabelMetaExporter(Protocol):
111
+ def __call__(self, metadata: NgioLabelMeta) -> dict: ...
112
+
113
+
114
+ class WellMetaImporter(Protocol):
115
+ def __call__(
116
+ self, metadata: dict
117
+ ) -> tuple[bool, NgioWellMeta | ConverterError]: ...
118
+
119
+
120
+ class WellMetaExporter(Protocol):
121
+ def __call__(self, metadata: NgioWellMeta) -> dict: ...
122
+
123
+
124
+ class PlateMetaImporter(Protocol):
125
+ def __call__(
126
+ self, metadata: dict
127
+ ) -> tuple[bool, NgioPlateMeta | ConverterError]: ...
128
+
129
+
130
+ class PlateMetaExporter(Protocol):
131
+ def __call__(self, metadata: NgioPlateMeta) -> dict: ...
132
+
133
+
134
+ ###########################################################################
135
+ #
136
+ # Image and label metadata handlers
137
+ #
138
+ ###########################################################################
139
+
140
+ _image_meta = TypeVar("_image_meta", NgioImageMeta, NgioLabelMeta)
141
+ _image_meta_importer = TypeVar(
142
+ "_image_meta_importer", ImageMetaImporter, LabelMetaImporter
143
+ )
144
+ _image_meta_exporter = TypeVar(
145
+ "_image_meta_exporter", ImageMetaExporter, LabelMetaExporter
146
+ )
147
+
148
+
149
+ class GenericMetaHandler(
150
+ Generic[_image_meta, _image_meta_importer, _image_meta_exporter]
151
+ ):
152
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
153
+
217
154
  def __init__(
218
155
  self,
156
+ meta_importer: _image_meta_importer,
157
+ meta_exporter: _image_meta_exporter,
219
158
  group_handler: ZarrGroupHandler,
220
- version: str | None = None,
221
159
  axes_setup: AxesSetup | None = None,
160
+ allow_non_canonical_axes: bool = False,
161
+ strict_canonical_order: bool = True,
222
162
  ):
163
+ """Initialize the handler.
164
+
165
+ Args:
166
+ meta_importer (MetaImporter): The metadata importer.
167
+ meta_exporter (MetaExporter): The metadata exporter.
168
+ group_handler (ZarrGroupHandler): The Zarr group handler.
169
+ axes_setup (AxesSetup, optional): The axes setup.
170
+ This is used to map axes with non-canonical names.
171
+ allow_non_canonical_axes (bool, optional): Whether to allow non-canonical
172
+ axes.
173
+ strict_canonical_order (bool, optional): Whether to enforce a strict
174
+ canonical order.
175
+ """
223
176
  self._group_handler = group_handler
224
- self._version = version
177
+ self._meta_importer = meta_importer
178
+ self._meta_exporter = meta_exporter
225
179
  self._axes_setup = axes_setup
226
- # Validate metadata
227
- meta = self.get_meta()
228
- # Store the resolved version
229
- self._version = meta.version
230
-
231
- def get_meta(self) -> NgioImageMeta:
232
- """Retrieve the NGIO image metadata."""
233
- return get_ngio_image_meta(
234
- group_handler=self._group_handler,
235
- version=self._version,
180
+ self._allow_non_canonical_axes = allow_non_canonical_axes
181
+ self._strict_canonical_order = strict_canonical_order
182
+
183
+ def _load_meta(self, return_error: bool = False):
184
+ """Load the metadata from the store."""
185
+ attrs = self._group_handler.load_attrs()
186
+ is_valid, meta_or_error = self._meta_importer(
187
+ metadata=attrs,
236
188
  axes_setup=self._axes_setup,
189
+ allow_non_canonical_axes=self._allow_non_canonical_axes,
190
+ strict_canonical_order=self._strict_canonical_order,
237
191
  )
192
+ if is_valid:
193
+ return meta_or_error
238
194
 
239
- def update_meta(self, ngio_meta: NgioImageMeta) -> None:
240
- """Update the NGIO image metadata."""
241
- update_ngio_meta(
242
- group_handler=self._group_handler,
243
- ngio_meta=ngio_meta,
244
- )
195
+ if return_error:
196
+ return meta_or_error
245
197
 
198
+ raise NgioValueError(f"Could not load metadata: {meta_or_error}")
246
199
 
247
- def get_ngio_label_meta(
248
- group_handler: ZarrGroupHandler,
249
- version: str | None = None,
250
- axes_setup: AxesSetup | None = None,
251
- ) -> NgioLabelMeta:
252
- """Retrieve the NGIO label metadata from the Zarr group.
253
-
254
- Args:
255
- group_handler (ZarrGroupHandler): The Zarr group handler.
256
- version (str | None): Optional NGFF version to use for decoding.
257
- axes_setup (AxesSetup | None): Optional axes setup for validation.
258
-
259
- Returns:
260
- NgioLabelMeta: The NGIO label metadata.
261
- """
262
- return get_ngio_meta(
263
- group_handler=group_handler,
264
- meta_type=NgioLabelMeta,
265
- version=version,
266
- axes_setup=axes_setup,
267
- )
200
+ def _write_meta(self, meta) -> None:
201
+ """Write the metadata to the store."""
202
+ _meta = self._meta_exporter(metadata=meta)
203
+ self._group_handler.write_attrs(_meta)
268
204
 
205
+ def write_meta(self, meta: _image_meta) -> None:
206
+ self._write_meta(meta)
269
207
 
270
- def update_ngio_label_meta(
271
- group_handler: ZarrGroupHandler,
272
- ngio_meta: NgioLabelMeta,
273
- ) -> None:
274
- """Update the NGIO label metadata in the Zarr group.
208
+ @property
209
+ def meta(self) -> _image_meta:
210
+ """Return the metadata."""
211
+ raise NotImplementedError("This method should be implemented in a subclass.")
275
212
 
276
- Args:
277
- group_handler (ZarrGroupHandler): The Zarr group handler.
278
- ngio_meta (NgioLabelMeta): The new NGIO label metadata.
279
213
 
280
- """
281
- update_ngio_meta(
282
- group_handler=group_handler,
283
- ngio_meta=ngio_meta,
284
- )
214
+ class ImageMetaHandler(
215
+ GenericMetaHandler[NgioImageMeta, ImageMetaImporter, ImageMetaExporter]
216
+ ):
217
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
218
+
219
+ @property
220
+ def meta(self) -> NgioImageMeta:
221
+ meta = self._load_meta()
222
+ if isinstance(meta, NgioImageMeta):
223
+ return meta
224
+ raise NgioValueError(f"Could not load metadata: {meta}")
225
+
226
+ def safe_load_meta(self) -> NgioImageMeta | ConverterError:
227
+ """Load the metadata from the store."""
228
+ return self._load_meta(return_error=True)
229
+
230
+
231
+ class LabelMetaHandler(
232
+ GenericMetaHandler[NgioLabelMeta, LabelMetaImporter, LabelMetaExporter]
233
+ ):
234
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
235
+
236
+ @property
237
+ def meta(self) -> NgioLabelMeta:
238
+ meta = self._load_meta()
239
+ if isinstance(meta, NgioLabelMeta):
240
+ return meta
241
+ raise NgioValueError(f"Could not load metadata: {meta}")
242
+
243
+ def safe_load_meta(self) -> NgioLabelMeta | ConverterError:
244
+ """Load the metadata from the store."""
245
+ return self._load_meta(return_error=True)
246
+
247
+
248
+ ###########################################################################
249
+ #
250
+ # Well and plate metadata handlers
251
+ #
252
+ ###########################################################################
253
+
254
+ _hcs_meta = TypeVar("_hcs_meta", NgioWellMeta, NgioPlateMeta)
255
+ _hcs_meta_importer = TypeVar("_hcs_meta_importer", WellMetaImporter, PlateMetaImporter)
256
+ _hcs_meta_exporter = TypeVar("_hcs_meta_exporter", WellMetaExporter, PlateMetaExporter)
257
+
285
258
 
259
+ class GenericHCSMetaHandler(Generic[_hcs_meta, _hcs_meta_importer, _hcs_meta_exporter]):
260
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
286
261
 
287
- class LabelMetaHandler:
288
262
  def __init__(
289
263
  self,
264
+ meta_importer: _hcs_meta_importer,
265
+ meta_exporter: _hcs_meta_exporter,
290
266
  group_handler: ZarrGroupHandler,
291
- axes_setup: AxesSetup | None = None,
292
- version: str | None = None,
293
267
  ):
294
268
  self._group_handler = group_handler
295
- self._version = version
296
- self._axes_setup = axes_setup
269
+ self._meta_importer = meta_importer
270
+ self._meta_exporter = meta_exporter
297
271
 
298
- # Validate metadata
299
- meta = self.get_meta()
300
- # Store the resolved version
301
- self._version = meta.version
272
+ def _load_meta(self, return_error: bool = False):
273
+ """Load the metadata from the store."""
274
+ attrs = self._group_handler.load_attrs()
275
+ is_valid, meta_or_error = self._meta_importer(metadata=attrs)
276
+ if is_valid:
277
+ return meta_or_error
302
278
 
303
- def get_meta(self) -> NgioLabelMeta:
304
- """Retrieve the NGIO label metadata."""
305
- return get_ngio_label_meta(
306
- group_handler=self._group_handler,
307
- version=self._version,
308
- axes_setup=self._axes_setup,
309
- )
279
+ if return_error:
280
+ return meta_or_error
310
281
 
311
- def update_meta(self, ngio_meta: NgioLabelMeta) -> None:
312
- """Update the NGIO label metadata."""
313
- update_ngio_meta(
314
- group_handler=self._group_handler,
315
- ngio_meta=ngio_meta,
316
- )
282
+ raise NgioValueError(f"Could not load metadata: {meta_or_error}")
317
283
 
284
+ def _write_meta(self, meta) -> None:
285
+ _meta = self._meta_exporter(metadata=meta)
286
+ self._group_handler.write_attrs(_meta)
318
287
 
319
- def get_ngio_plate_meta(
320
- group_handler: ZarrGroupHandler,
321
- version: str | None = None,
322
- ) -> NgioPlateMeta:
323
- """Retrieve the NGIO plate metadata from the Zarr group.
324
-
325
- Args:
326
- group_handler (ZarrGroupHandler): The Zarr group handler.
327
- version (str | None): Optional NGFF version to use for decoding.
328
-
329
- Returns:
330
- NgioPlateMeta: The NGIO plate metadata.
331
- """
332
- return get_ngio_meta(
333
- group_handler=group_handler,
334
- meta_type=NgioPlateMeta,
335
- version=version,
336
- )
288
+ def write_meta(self, meta: _hcs_meta) -> None:
289
+ self._write_meta(meta)
337
290
 
291
+ @property
292
+ def meta(self) -> _hcs_meta:
293
+ raise NotImplementedError("This method should be implemented in a subclass.")
338
294
 
339
- def update_ngio_plate_meta(
340
- group_handler: ZarrGroupHandler,
341
- ngio_meta: NgioPlateMeta,
342
- ) -> None:
343
- """Update the NGIO plate metadata in the Zarr group.
344
295
 
345
- Args:
346
- group_handler (ZarrGroupHandler): The Zarr group handler.
347
- ngio_meta (NgioPlateMeta): The new NGIO plate metadata.
296
+ class WellMetaHandler(
297
+ GenericHCSMetaHandler[NgioWellMeta, WellMetaImporter, WellMetaExporter]
298
+ ):
299
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
348
300
 
349
- """
350
- update_ngio_meta(
351
- group_handler=group_handler,
352
- ngio_meta=ngio_meta,
353
- )
301
+ @property
302
+ def meta(self) -> NgioWellMeta:
303
+ meta = self._load_meta()
304
+ if isinstance(meta, NgioWellMeta):
305
+ return meta
306
+ raise NgioValueError(f"Could not load metadata: {meta}")
307
+
308
+ def safe_load_meta(self) -> NgioWellMeta | ConverterError:
309
+ """Load the metadata from the store."""
310
+ return self._load_meta(return_error=True)
354
311
 
355
312
 
356
- class PlateMetaHandler:
313
+ class PlateMetaHandler(
314
+ GenericHCSMetaHandler[NgioPlateMeta, PlateMetaImporter, PlateMetaExporter]
315
+ ):
316
+ """Generic class for handling OME-Zarr metadata in Zarr groups."""
317
+
318
+ @property
319
+ def meta(self) -> NgioPlateMeta:
320
+ meta = self._load_meta()
321
+ if isinstance(meta, NgioPlateMeta):
322
+ return meta
323
+ raise NgioValueError(f"Could not load metadata: {meta}")
324
+
325
+ def safe_load_meta(self) -> NgioPlateMeta | ConverterError:
326
+ """Load the metadata from the store."""
327
+ return self._load_meta(return_error=True)
328
+
329
+
330
+ ###########################################################################
331
+ #
332
+ # Metadata importer/exporter registration & builder classes
333
+ #
334
+ ###########################################################################
335
+
336
+
337
+ _meta_exporter = TypeVar(
338
+ "_meta_exporter",
339
+ ImageMetaExporter,
340
+ LabelMetaExporter,
341
+ WellMetaExporter,
342
+ PlateMetaExporter,
343
+ )
344
+ _meta_importer = TypeVar(
345
+ "_meta_importer",
346
+ ImageMetaImporter,
347
+ LabelMetaImporter,
348
+ WellMetaImporter,
349
+ PlateMetaImporter,
350
+ )
351
+
352
+
353
+ class _ImporterExporter(Generic[_meta_importer, _meta_exporter]):
357
354
  def __init__(
358
355
  self,
359
- group_handler: ZarrGroupHandler,
360
- version: str | None = None,
356
+ version: str,
357
+ importer: _meta_importer,
358
+ exporter: _meta_exporter,
361
359
  ):
362
- self._group_handler = group_handler
363
- self._version = version
364
-
365
- # Validate metadata
366
- _ = self.get_meta()
367
- # Store the resolved version
368
- # self._version = meta.version
369
-
370
- def get_meta(self) -> NgioPlateMeta:
371
- """Retrieve the NGIO plate metadata."""
372
- return get_ngio_plate_meta(
373
- group_handler=self._group_handler,
374
- version=self._version,
360
+ self.importer = importer
361
+ self.exporter = exporter
362
+ self.version = version
363
+
364
+
365
+ ImageImporterExporter = _ImporterExporter[ImageMetaImporter, ImageMetaExporter]
366
+ LabelImporterExporter = _ImporterExporter[LabelMetaImporter, LabelMetaExporter]
367
+ WellImporterExporter = _ImporterExporter[WellMetaImporter, WellMetaExporter]
368
+ PlateImporterExporter = _ImporterExporter[PlateMetaImporter, PlateMetaExporter]
369
+
370
+ _importer_exporter = TypeVar(
371
+ "_importer_exporter",
372
+ ImageImporterExporter,
373
+ LabelImporterExporter,
374
+ WellImporterExporter,
375
+ PlateImporterExporter,
376
+ )
377
+ _image_handler = TypeVar("_image_handler", ImageMetaHandler, LabelMetaHandler)
378
+ _hcs_handler = TypeVar("_hcs_handler", WellMetaHandler, PlateMetaHandler)
379
+
380
+
381
+ class ImplementedMetaImporterExporter:
382
+ _instance = None
383
+ _image_ie: dict[str, ImageImporterExporter]
384
+ _label_ie: dict[str, LabelImporterExporter]
385
+ _well_ie: dict[str, WellImporterExporter]
386
+ _plate_ie: dict[str, PlateImporterExporter]
387
+
388
+ def __new__(cls):
389
+ """Create a new instance of the class if it does not exist."""
390
+ if cls._instance is None:
391
+ cls._instance = super().__new__(cls)
392
+ cls._image_ie = {}
393
+ cls._label_ie = {}
394
+ cls._well_ie = {}
395
+ cls._plate_ie = {}
396
+ return cls._instance
397
+
398
+ def _find_image_handler(
399
+ self,
400
+ group_handler: ZarrGroupHandler,
401
+ axes_setup: AxesSetup | None = None,
402
+ allow_non_canonical_axes: bool = False,
403
+ strict_canonical_order: bool = True,
404
+ _ie_name: str = "_image_ie",
405
+ _handler: type[_image_handler] = ImageMetaHandler,
406
+ ) -> _image_handler:
407
+ """Get an image metadata handler."""
408
+ _errors = {}
409
+
410
+ dict_ie = self.__getattribute__(_ie_name)
411
+
412
+ for ie in reversed(dict_ie.values()):
413
+ handler = _handler(
414
+ meta_importer=ie.importer,
415
+ meta_exporter=ie.exporter,
416
+ group_handler=group_handler,
417
+ axes_setup=axes_setup,
418
+ allow_non_canonical_axes=allow_non_canonical_axes,
419
+ strict_canonical_order=strict_canonical_order,
420
+ )
421
+ meta = handler.safe_load_meta()
422
+ if isinstance(meta, ValidationError):
423
+ _errors[ie.version] = meta
424
+ continue
425
+ return handler
426
+
427
+ raise NgioValidationError(
428
+ f"Could not load metadata from any known version. Errors: {_errors}"
375
429
  )
376
430
 
377
- def update_meta(self, ngio_meta: NgioPlateMeta) -> None:
378
- """Update the NGIO plate metadata."""
379
- update_ngio_meta(
380
- group_handler=self._group_handler,
381
- ngio_meta=ngio_meta,
431
+ def find_image_handler(
432
+ self,
433
+ group_handler: ZarrGroupHandler,
434
+ axes_setup: AxesSetup | None = None,
435
+ allow_non_canonical_axes: bool = False,
436
+ strict_canonical_order: bool = True,
437
+ ) -> ImageMetaHandler:
438
+ """Get an image metadata handler."""
439
+ return self._find_image_handler(
440
+ group_handler=group_handler,
441
+ axes_setup=axes_setup,
442
+ allow_non_canonical_axes=allow_non_canonical_axes,
443
+ strict_canonical_order=strict_canonical_order,
444
+ _ie_name="_image_ie",
445
+ _handler=ImageMetaHandler,
382
446
  )
383
447
 
448
+ def get_image_meta_handler(
449
+ self,
450
+ group_handler: ZarrGroupHandler,
451
+ version: str,
452
+ axes_setup: AxesSetup | None = None,
453
+ allow_non_canonical_axes: bool = False,
454
+ strict_canonical_order: bool = True,
455
+ ) -> ImageMetaHandler:
456
+ """Get an image metadata handler."""
457
+ if version not in self._image_ie:
458
+ raise NgioValueError(f"Image handler for version {version} does not exist.")
459
+
460
+ image_ie = self._image_ie[version]
461
+ return ImageMetaHandler(
462
+ meta_importer=image_ie.importer,
463
+ meta_exporter=image_ie.exporter,
464
+ group_handler=group_handler,
465
+ axes_setup=axes_setup,
466
+ allow_non_canonical_axes=allow_non_canonical_axes,
467
+ strict_canonical_order=strict_canonical_order,
468
+ )
384
469
 
385
- def get_ngio_well_meta(
386
- group_handler: ZarrGroupHandler,
387
- version: str | None = None,
388
- ) -> NgioWellMeta:
389
- """Retrieve the NGIO well metadata from the Zarr group.
390
-
391
- Args:
392
- group_handler (ZarrGroupHandler): The Zarr group handler.
393
- version (str | None): Optional NGFF version to use for decoding.
394
-
395
- Returns:
396
- NgioWellMeta: The NGIO well metadata.
397
- """
398
- return get_ngio_meta(
399
- group_handler=group_handler,
400
- meta_type=NgioWellMeta,
401
- version=version,
402
- )
470
+ def _register(
471
+ self,
472
+ version: str,
473
+ importer: _importer_exporter,
474
+ overwrite: bool = False,
475
+ _ie_name: str = "_image_ie",
476
+ ):
477
+ """Register an importer/exporter."""
478
+ ie_dict = self.__getattribute__(_ie_name)
479
+ if version in ie_dict and not overwrite:
480
+ raise NgioValueError(
481
+ f"Importer/exporter for version {version} already exists. "
482
+ "Use 'overwrite=True' to overwrite."
483
+ )
484
+ ie_dict[version] = importer
485
+
486
+ def register_image_ie(
487
+ self,
488
+ version: str,
489
+ importer: ImageMetaImporter,
490
+ exporter: ImageMetaExporter,
491
+ overwrite: bool = False,
492
+ ):
493
+ """Register an importer/exporter."""
494
+ importer_exporter = ImageImporterExporter(
495
+ version=version, importer=importer, exporter=exporter
496
+ )
497
+ self._register(
498
+ version=version,
499
+ importer=importer_exporter,
500
+ overwrite=overwrite,
501
+ _ie_name="_image_ie",
502
+ )
403
503
 
504
+ def find_label_handler(
505
+ self,
506
+ group_handler: ZarrGroupHandler,
507
+ axes_setup: AxesSetup | None = None,
508
+ allow_non_canonical_axes: bool = False,
509
+ strict_canonical_order: bool = True,
510
+ ) -> LabelMetaHandler:
511
+ """Get a label metadata handler."""
512
+ return self._find_image_handler(
513
+ group_handler=group_handler,
514
+ axes_setup=axes_setup,
515
+ allow_non_canonical_axes=allow_non_canonical_axes,
516
+ strict_canonical_order=strict_canonical_order,
517
+ _ie_name="_label_ie",
518
+ _handler=LabelMetaHandler,
519
+ )
404
520
 
405
- def update_ngio_well_meta(
406
- group_handler: ZarrGroupHandler,
407
- ngio_meta: NgioWellMeta,
408
- ) -> None:
409
- """Update the NGIO well metadata in the Zarr group.
521
+ def get_label_meta_handler(
522
+ self,
523
+ group_handler: ZarrGroupHandler,
524
+ version: str,
525
+ axes_setup: AxesSetup | None = None,
526
+ allow_non_canonical_axes: bool = False,
527
+ strict_canonical_order: bool = True,
528
+ ) -> LabelMetaHandler:
529
+ """Get a label metadata handler."""
530
+ if version not in self._label_ie:
531
+ raise NgioValueError(f"Label handler for version {version} does not exist.")
532
+
533
+ label_ie = self._label_ie[version]
534
+ return LabelMetaHandler(
535
+ meta_importer=label_ie.importer,
536
+ meta_exporter=label_ie.exporter,
537
+ group_handler=group_handler,
538
+ axes_setup=axes_setup,
539
+ allow_non_canonical_axes=allow_non_canonical_axes,
540
+ strict_canonical_order=strict_canonical_order,
541
+ )
410
542
 
411
- Args:
412
- group_handler (ZarrGroupHandler): The Zarr group handler.
413
- ngio_meta (NgioWellMeta): The new NGIO well metadata.
543
+ def register_label_ie(
544
+ self,
545
+ version: str,
546
+ importer: LabelMetaImporter,
547
+ exporter: LabelMetaExporter,
548
+ overwrite: bool = False,
549
+ ):
550
+ """Register an importer/exporter."""
551
+ importer_exporter = LabelImporterExporter(
552
+ version=version, importer=importer, exporter=exporter
553
+ )
554
+ self._register(
555
+ version=version,
556
+ importer=importer_exporter,
557
+ overwrite=overwrite,
558
+ _ie_name="_label_ie",
559
+ )
414
560
 
415
- """
416
- update_ngio_meta(
417
- group_handler=group_handler,
418
- ngio_meta=ngio_meta,
419
- )
561
+ def _find_hcs_handler(
562
+ self,
563
+ group_handler: ZarrGroupHandler,
564
+ _ie_name: str = "_well_ie",
565
+ _handler: type[_hcs_handler] = WellMetaHandler,
566
+ ) -> _hcs_handler:
567
+ """Get a handler for a HCS metadata."""
568
+ _errors = {}
569
+
570
+ dict_ie = self.__getattribute__(_ie_name)
571
+
572
+ for ie in reversed(dict_ie.values()):
573
+ handler = _handler(
574
+ meta_importer=ie.importer,
575
+ meta_exporter=ie.exporter,
576
+ group_handler=group_handler,
577
+ )
578
+ meta = handler.safe_load_meta()
579
+ if isinstance(meta, ValidationError):
580
+ _errors[ie.version] = meta
581
+ continue
582
+ return handler
583
+
584
+ raise NgioValidationError(
585
+ f"Could not load metadata from any known version. Errors: {_errors}"
586
+ )
420
587
 
588
+ def find_well_handler(
589
+ self,
590
+ group_handler: ZarrGroupHandler,
591
+ ) -> WellMetaHandler:
592
+ """Get a well metadata handler."""
593
+ return self._find_hcs_handler(
594
+ group_handler=group_handler,
595
+ _ie_name="_well_ie",
596
+ _handler=WellMetaHandler,
597
+ )
421
598
 
422
- class WellMetaHandler:
423
- def __init__(
599
+ def get_well_meta_handler(
424
600
  self,
425
601
  group_handler: ZarrGroupHandler,
426
- version: str | None = None,
602
+ version: str,
603
+ ) -> WellMetaHandler:
604
+ """Get a well metadata handler."""
605
+ if version not in self._well_ie:
606
+ raise NgioValueError(f"Well handler for version {version} does not exist.")
607
+
608
+ well_ie = self._well_ie[version]
609
+ return WellMetaHandler(
610
+ meta_importer=well_ie.importer,
611
+ meta_exporter=well_ie.exporter,
612
+ group_handler=group_handler,
613
+ )
614
+
615
+ def register_well_ie(
616
+ self,
617
+ version: str,
618
+ importer: WellMetaImporter,
619
+ exporter: WellMetaExporter,
620
+ overwrite: bool = False,
427
621
  ):
428
- self._group_handler = group_handler
429
- self._version = version
430
-
431
- # Validate metadata
432
- _ = self.get_meta()
433
- # Store the resolved version
434
- # self._version = meta.version
435
-
436
- def get_meta(self) -> NgioWellMeta:
437
- """Retrieve the NGIO well metadata."""
438
- return get_ngio_well_meta(
439
- group_handler=self._group_handler,
440
- version=self._version,
622
+ """Register an importer/exporter."""
623
+ importer_exporter = WellImporterExporter(
624
+ version=version, importer=importer, exporter=exporter
625
+ )
626
+ self._register(
627
+ version=version,
628
+ importer=importer_exporter,
629
+ overwrite=overwrite,
630
+ _ie_name="_well_ie",
631
+ )
632
+
633
+ def find_plate_handler(
634
+ self,
635
+ group_handler: ZarrGroupHandler,
636
+ ) -> PlateMetaHandler:
637
+ """Get a plate metadata handler."""
638
+ return self._find_hcs_handler(
639
+ group_handler=group_handler,
640
+ _ie_name="_plate_ie",
641
+ _handler=PlateMetaHandler,
441
642
  )
442
643
 
443
- def update_meta(self, ngio_meta: NgioWellMeta) -> None:
444
- """Update the NGIO well metadata."""
445
- update_ngio_meta(
446
- group_handler=self._group_handler,
447
- ngio_meta=ngio_meta,
644
+ def get_plate_meta_handler(
645
+ self,
646
+ group_handler: ZarrGroupHandler,
647
+ version: str,
648
+ ) -> PlateMetaHandler:
649
+ """Get a plate metadata handler."""
650
+ if version not in self._plate_ie:
651
+ raise NgioValueError(f"Plate handler for version {version} does not exist.")
652
+
653
+ plate_ie = self._plate_ie[version]
654
+ return PlateMetaHandler(
655
+ meta_importer=plate_ie.importer,
656
+ meta_exporter=plate_ie.exporter,
657
+ group_handler=group_handler,
658
+ )
659
+
660
+ def register_plate_ie(
661
+ self,
662
+ version: str,
663
+ importer: PlateMetaImporter,
664
+ exporter: PlateMetaExporter,
665
+ overwrite: bool = False,
666
+ ):
667
+ """Register an importer/exporter."""
668
+ importer_exporter = PlateImporterExporter(
669
+ version=version, importer=importer, exporter=exporter
670
+ )
671
+ self._register(
672
+ version=version,
673
+ importer=importer_exporter,
674
+ overwrite=overwrite,
675
+ _ie_name="_plate_ie",
448
676
  )
449
677
 
450
678
 
451
- def get_ngio_labels_group_meta(
679
+ ###########################################################################
680
+ #
681
+ # Register metadata importers/exporters
682
+ #
683
+ ###########################################################################
684
+
685
+
686
+ ImplementedMetaImporterExporter().register_image_ie(
687
+ version="0.4",
688
+ importer=v04_to_ngio_image_meta,
689
+ exporter=ngio_to_v04_image_meta,
690
+ )
691
+
692
+ ImplementedMetaImporterExporter().register_label_ie(
693
+ version="0.5",
694
+ importer=v05_to_ngio_label_meta,
695
+ exporter=ngio_to_v05_label_meta,
696
+ )
697
+
698
+ ImplementedMetaImporterExporter().register_label_ie(
699
+ version="0.4",
700
+ importer=v04_to_ngio_label_meta,
701
+ exporter=ngio_to_v04_label_meta,
702
+ )
703
+ ImplementedMetaImporterExporter().register_image_ie(
704
+ version="0.5",
705
+ importer=v05_to_ngio_image_meta,
706
+ exporter=ngio_to_v05_image_meta,
707
+ )
708
+
709
+ ImplementedMetaImporterExporter().register_well_ie(
710
+ version="0.4", importer=v04_to_ngio_well_meta, exporter=ngio_to_v04_well_meta
711
+ )
712
+ ImplementedMetaImporterExporter().register_well_ie(
713
+ version="0.5", importer=v05_to_ngio_well_meta, exporter=ngio_to_v05_well_meta
714
+ )
715
+ ImplementedMetaImporterExporter().register_plate_ie(
716
+ version="0.4", importer=v04_to_ngio_plate_meta, exporter=ngio_to_v04_plate_meta
717
+ )
718
+ ImplementedMetaImporterExporter().register_plate_ie(
719
+ version="0.5", importer=v05_to_ngio_plate_meta, exporter=ngio_to_v05_plate_meta
720
+ )
721
+
722
+
723
+ ###########################################################################
724
+ #
725
+ # Public functions to avoid direct access to the importer/exporter
726
+ # registration methods
727
+ #
728
+ ###########################################################################
729
+
730
+
731
+ def find_image_meta_handler(
452
732
  group_handler: ZarrGroupHandler,
453
- version: str | None = None,
454
- ) -> NgioLabelsGroupMeta:
455
- """Retrieve the NGIO labels group metadata from the Zarr group.
456
-
457
- Args:
458
- group_handler (ZarrGroupHandler): The Zarr group handler.
459
- version (str | None): Optional NGFF version to use for decoding.
460
-
461
- Returns:
462
- NgioLabelsGroupMeta: The NGIO labels group metadata.
463
- """
464
- return get_ngio_meta(
733
+ axes_setup: AxesSetup | None = None,
734
+ allow_non_canonical_axes: bool = False,
735
+ strict_canonical_order: bool = True,
736
+ ) -> ImageMetaHandler:
737
+ """Open an image metadata handler."""
738
+ return ImplementedMetaImporterExporter().find_image_handler(
739
+ group_handler=group_handler,
740
+ axes_setup=axes_setup,
741
+ allow_non_canonical_axes=allow_non_canonical_axes,
742
+ strict_canonical_order=strict_canonical_order,
743
+ )
744
+
745
+
746
+ def get_image_meta_handler(
747
+ group_handler: ZarrGroupHandler,
748
+ version: str,
749
+ axes_setup: AxesSetup | None = None,
750
+ allow_non_canonical_axes: bool = False,
751
+ strict_canonical_order: bool = True,
752
+ ) -> ImageMetaHandler:
753
+ """Open an image metadata handler."""
754
+ return ImplementedMetaImporterExporter().get_image_meta_handler(
465
755
  group_handler=group_handler,
466
- meta_type=NgioLabelsGroupMeta,
467
756
  version=version,
757
+ axes_setup=axes_setup,
758
+ allow_non_canonical_axes=allow_non_canonical_axes,
759
+ strict_canonical_order=strict_canonical_order,
468
760
  )
469
761
 
470
762
 
471
- def update_ngio_labels_group_meta(
763
+ def find_label_meta_handler(
472
764
  group_handler: ZarrGroupHandler,
473
- ngio_meta: NgioLabelsGroupMeta,
474
- ) -> None:
475
- """Update the NGIO labels group metadata in the Zarr group.
765
+ axes_setup: AxesSetup | None = None,
766
+ allow_non_canonical_axes: bool = False,
767
+ strict_canonical_order: bool = True,
768
+ ) -> LabelMetaHandler:
769
+ """Open a label metadata handler."""
770
+ return ImplementedMetaImporterExporter().find_label_handler(
771
+ group_handler=group_handler,
772
+ axes_setup=axes_setup,
773
+ allow_non_canonical_axes=allow_non_canonical_axes,
774
+ strict_canonical_order=strict_canonical_order,
775
+ )
476
776
 
477
- Args:
478
- group_handler (ZarrGroupHandler): The Zarr group handler.
479
- ngio_meta (NgioLabelsGroupMeta): The new NGIO labels group metadata.
480
777
 
481
- """
482
- update_ngio_meta(
778
+ def get_label_meta_handler(
779
+ group_handler: ZarrGroupHandler,
780
+ version: str,
781
+ axes_setup: AxesSetup | None = None,
782
+ allow_non_canonical_axes: bool = False,
783
+ strict_canonical_order: bool = True,
784
+ ) -> LabelMetaHandler:
785
+ """Open a label metadata handler."""
786
+ return ImplementedMetaImporterExporter().get_label_meta_handler(
483
787
  group_handler=group_handler,
484
- ngio_meta=ngio_meta,
788
+ version=version,
789
+ axes_setup=axes_setup,
790
+ allow_non_canonical_axes=allow_non_canonical_axes,
791
+ strict_canonical_order=strict_canonical_order,
485
792
  )
486
793
 
487
794
 
488
- class LabelsGroupMetaHandler:
489
- def __init__(
490
- self,
491
- group_handler: ZarrGroupHandler,
492
- version: NgffVersions | None = None,
493
- ):
494
- self._group_handler = group_handler
495
- self._version = version
795
+ def find_well_meta_handler(group_handler: ZarrGroupHandler) -> WellMetaHandler:
796
+ """Open a well metadata handler."""
797
+ return ImplementedMetaImporterExporter().find_well_handler(
798
+ group_handler=group_handler,
799
+ )
496
800
 
497
- meta = self.get_meta()
498
- self._version = meta.version
499
801
 
500
- def get_meta(self) -> NgioLabelsGroupMeta:
501
- """Retrieve the NGIO labels group metadata."""
502
- return get_ngio_labels_group_meta(
503
- group_handler=self._group_handler,
504
- version=self._version,
505
- )
802
+ def get_well_meta_handler(
803
+ group_handler: ZarrGroupHandler,
804
+ version: str,
805
+ ) -> WellMetaHandler:
806
+ """Open a well metadata handler."""
807
+ return ImplementedMetaImporterExporter().get_well_meta_handler(
808
+ group_handler=group_handler,
809
+ version=version,
810
+ )
506
811
 
507
- def update_meta(self, ngio_meta: NgioLabelsGroupMeta) -> None:
508
- """Update the NGIO labels group metadata."""
509
- update_ngio_labels_group_meta(
510
- group_handler=self._group_handler,
511
- ngio_meta=ngio_meta,
512
- )
812
+
813
+ def find_plate_meta_handler(group_handler: ZarrGroupHandler) -> PlateMetaHandler:
814
+ """Open a plate metadata handler."""
815
+ return ImplementedMetaImporterExporter().find_plate_handler(
816
+ group_handler=group_handler
817
+ )
818
+
819
+
820
+ def get_plate_meta_handler(
821
+ group_handler: ZarrGroupHandler,
822
+ version: str,
823
+ ) -> PlateMetaHandler:
824
+ """Open a plate metadata handler."""
825
+ return ImplementedMetaImporterExporter().get_plate_meta_handler(
826
+ group_handler=group_handler,
827
+ version=version,
828
+ )