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