ngio 0.5.0b6__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 (88) hide show
  1. ngio/__init__.py +69 -0
  2. ngio/common/__init__.py +28 -0
  3. ngio/common/_dimensions.py +335 -0
  4. ngio/common/_masking_roi.py +153 -0
  5. ngio/common/_pyramid.py +408 -0
  6. ngio/common/_roi.py +315 -0
  7. ngio/common/_synt_images_utils.py +101 -0
  8. ngio/common/_zoom.py +188 -0
  9. ngio/experimental/__init__.py +5 -0
  10. ngio/experimental/iterators/__init__.py +15 -0
  11. ngio/experimental/iterators/_abstract_iterator.py +390 -0
  12. ngio/experimental/iterators/_feature.py +189 -0
  13. ngio/experimental/iterators/_image_processing.py +130 -0
  14. ngio/experimental/iterators/_mappers.py +48 -0
  15. ngio/experimental/iterators/_rois_utils.py +126 -0
  16. ngio/experimental/iterators/_segmentation.py +235 -0
  17. ngio/hcs/__init__.py +19 -0
  18. ngio/hcs/_plate.py +1354 -0
  19. ngio/images/__init__.py +44 -0
  20. ngio/images/_abstract_image.py +967 -0
  21. ngio/images/_create_synt_container.py +132 -0
  22. ngio/images/_create_utils.py +423 -0
  23. ngio/images/_image.py +926 -0
  24. ngio/images/_label.py +411 -0
  25. ngio/images/_masked_image.py +531 -0
  26. ngio/images/_ome_zarr_container.py +1237 -0
  27. ngio/images/_table_ops.py +471 -0
  28. ngio/io_pipes/__init__.py +75 -0
  29. ngio/io_pipes/_io_pipes.py +361 -0
  30. ngio/io_pipes/_io_pipes_masked.py +488 -0
  31. ngio/io_pipes/_io_pipes_roi.py +146 -0
  32. ngio/io_pipes/_io_pipes_types.py +56 -0
  33. ngio/io_pipes/_match_shape.py +377 -0
  34. ngio/io_pipes/_ops_axes.py +344 -0
  35. ngio/io_pipes/_ops_slices.py +411 -0
  36. ngio/io_pipes/_ops_slices_utils.py +199 -0
  37. ngio/io_pipes/_ops_transforms.py +104 -0
  38. ngio/io_pipes/_zoom_transform.py +180 -0
  39. ngio/ome_zarr_meta/__init__.py +65 -0
  40. ngio/ome_zarr_meta/_meta_handlers.py +536 -0
  41. ngio/ome_zarr_meta/ngio_specs/__init__.py +77 -0
  42. ngio/ome_zarr_meta/ngio_specs/_axes.py +515 -0
  43. ngio/ome_zarr_meta/ngio_specs/_channels.py +462 -0
  44. ngio/ome_zarr_meta/ngio_specs/_dataset.py +89 -0
  45. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +539 -0
  46. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +438 -0
  47. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +122 -0
  48. ngio/ome_zarr_meta/v04/__init__.py +27 -0
  49. ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  50. ngio/ome_zarr_meta/v04/_v04_spec.py +473 -0
  51. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  52. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  53. ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
  54. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  55. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  56. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  57. ngio/resources/__init__.py +55 -0
  58. ngio/resources/resource_model.py +36 -0
  59. ngio/tables/__init__.py +43 -0
  60. ngio/tables/_abstract_table.py +270 -0
  61. ngio/tables/_tables_container.py +449 -0
  62. ngio/tables/backends/__init__.py +57 -0
  63. ngio/tables/backends/_abstract_backend.py +240 -0
  64. ngio/tables/backends/_anndata.py +139 -0
  65. ngio/tables/backends/_anndata_utils.py +90 -0
  66. ngio/tables/backends/_csv.py +19 -0
  67. ngio/tables/backends/_json.py +92 -0
  68. ngio/tables/backends/_parquet.py +19 -0
  69. ngio/tables/backends/_py_arrow_backends.py +222 -0
  70. ngio/tables/backends/_table_backends.py +226 -0
  71. ngio/tables/backends/_utils.py +608 -0
  72. ngio/tables/v1/__init__.py +23 -0
  73. ngio/tables/v1/_condition_table.py +71 -0
  74. ngio/tables/v1/_feature_table.py +125 -0
  75. ngio/tables/v1/_generic_table.py +49 -0
  76. ngio/tables/v1/_roi_table.py +575 -0
  77. ngio/transforms/__init__.py +5 -0
  78. ngio/transforms/_zoom.py +19 -0
  79. ngio/utils/__init__.py +45 -0
  80. ngio/utils/_cache.py +48 -0
  81. ngio/utils/_datasets.py +165 -0
  82. ngio/utils/_errors.py +37 -0
  83. ngio/utils/_fractal_fsspec_store.py +42 -0
  84. ngio/utils/_zarr_utils.py +534 -0
  85. ngio-0.5.0b6.dist-info/METADATA +148 -0
  86. ngio-0.5.0b6.dist-info/RECORD +88 -0
  87. ngio-0.5.0b6.dist-info/WHEEL +4 -0
  88. ngio-0.5.0b6.dist-info/licenses/LICENSE +28 -0
@@ -0,0 +1,511 @@
1
+ """Utilities for OME-Zarr v05 specs.
2
+
3
+ This module provides a set of classes to internally handle the metadata
4
+ of the OME-Zarr v05 specification.
5
+
6
+ For Images and Labels implements the following functionalities:
7
+ - A function to find if a dict view of the metadata is a valid OME-Zarr v05 metadata.
8
+ - A function to convert a v05 image metadata to a ngio image metadata.
9
+ - A function to convert a ngio image metadata to a v05 image metadata.
10
+ """
11
+
12
+ from ome_zarr_models.common.omero import Channel as ChannelV05
13
+ from ome_zarr_models.common.omero import Omero as OmeroV05
14
+ from ome_zarr_models.common.omero import Window as WindowV05
15
+ from ome_zarr_models.v05.axes import Axis as AxisV05
16
+ from ome_zarr_models.v05.coordinate_transformations import VectorScale as VectorScaleV05
17
+ from ome_zarr_models.v05.coordinate_transformations import (
18
+ VectorTranslation as VectorTranslationV05,
19
+ )
20
+ from ome_zarr_models.v05.hcs import HCSAttrs as HCSAttrsV05
21
+ from ome_zarr_models.v05.image import ImageAttrs as ImageAttrsV05
22
+ from ome_zarr_models.v05.image_label import ImageLabelAttrs as ImageLabelAttrsV05
23
+ from ome_zarr_models.v05.labels import Labels as Labels
24
+ from ome_zarr_models.v05.labels import LabelsAttrs as LabelsAttrsV05
25
+ from ome_zarr_models.v05.multiscales import Dataset as DatasetV05
26
+ from ome_zarr_models.v05.multiscales import Multiscale as MultiscaleV05
27
+ from ome_zarr_models.v05.multiscales import ValidTransform as ValidTransformV05
28
+ from pydantic import BaseModel
29
+
30
+ from ngio.ome_zarr_meta.ngio_specs import (
31
+ AxesHandler,
32
+ AxesSetup,
33
+ Axis,
34
+ AxisType,
35
+ Channel,
36
+ ChannelsMeta,
37
+ ChannelVisualisation,
38
+ Dataset,
39
+ ImageLabelSource,
40
+ NgioImageMeta,
41
+ NgioLabelMeta,
42
+ NgioLabelsGroupMeta,
43
+ NgioPlateMeta,
44
+ NgioWellMeta,
45
+ default_channel_name,
46
+ )
47
+ from ngio.ome_zarr_meta.v05._custom_models import CustomWellAttrs as WellAttrsV05
48
+
49
+
50
+ class ImageV05AttrsWithOmero(ImageAttrsV05):
51
+ omero: OmeroV05 | None = None
52
+
53
+
54
+ class ImageV05WithOmero(BaseModel):
55
+ ome: ImageV05AttrsWithOmero
56
+
57
+
58
+ class ImageLabelV05(BaseModel):
59
+ ome: ImageLabelAttrsV05
60
+
61
+
62
+ def _v05_omero_to_channels(v05_omero: OmeroV05 | None) -> ChannelsMeta | None:
63
+ if v05_omero is None:
64
+ return None
65
+
66
+ ngio_channels = []
67
+ for idx, v05_channel in enumerate(v05_omero.channels):
68
+ channel_extra = v05_channel.model_extra
69
+
70
+ if channel_extra is None:
71
+ channel_extra = {}
72
+
73
+ if "label" in channel_extra:
74
+ label = channel_extra.pop("label")
75
+ else:
76
+ label = default_channel_name(idx)
77
+
78
+ if "wavelength_id" in channel_extra:
79
+ wavelength_id = channel_extra.pop("wavelength_id")
80
+ else:
81
+ wavelength_id = label
82
+
83
+ if "active" in channel_extra:
84
+ active = channel_extra.pop("active")
85
+ else:
86
+ active = True
87
+
88
+ channel_visualisation = ChannelVisualisation(
89
+ color=v05_channel.color,
90
+ start=v05_channel.window.start,
91
+ end=v05_channel.window.end,
92
+ min=v05_channel.window.min,
93
+ max=v05_channel.window.max,
94
+ active=active,
95
+ **channel_extra,
96
+ )
97
+
98
+ ngio_channels.append(
99
+ Channel(
100
+ label=label,
101
+ wavelength_id=wavelength_id,
102
+ channel_visualisation=channel_visualisation,
103
+ )
104
+ )
105
+
106
+ v05_omero_extra = v05_omero.model_extra if v05_omero.model_extra is not None else {}
107
+ return ChannelsMeta(channels=ngio_channels, **v05_omero_extra)
108
+
109
+
110
+ def _compute_scale_translation(
111
+ v05_transforms: ValidTransformV05,
112
+ scale: list[float],
113
+ translation: list[float],
114
+ ) -> tuple[list[float], list[float]]:
115
+ for v05_transform in v05_transforms:
116
+ if isinstance(v05_transform, VectorScaleV05):
117
+ scale = [t1 * t2 for t1, t2 in zip(scale, v05_transform.scale, strict=True)]
118
+
119
+ elif isinstance(v05_transform, VectorTranslationV05):
120
+ translation = [
121
+ t1 + t2
122
+ for t1, t2 in zip(translation, v05_transform.translation, strict=True)
123
+ ]
124
+ else:
125
+ raise NotImplementedError(
126
+ f"Coordinate transformation {v05_transform} is not supported."
127
+ )
128
+ return scale, translation
129
+
130
+
131
+ def _v05_to_ngio_datasets(
132
+ v05_multiscale: MultiscaleV05,
133
+ axes_setup: AxesSetup,
134
+ allow_non_canonical_axes: bool = False,
135
+ strict_canonical_order: bool = True,
136
+ ) -> list[Dataset]:
137
+ """Convert a v05 multiscale to a list of ngio datasets."""
138
+ datasets = []
139
+
140
+ global_scale = [1.0] * len(v05_multiscale.axes)
141
+ global_translation = [0.0] * len(v05_multiscale.axes)
142
+
143
+ if v05_multiscale.coordinateTransformations is not None:
144
+ global_scale, global_translation = _compute_scale_translation(
145
+ v05_multiscale.coordinateTransformations, global_scale, global_translation
146
+ )
147
+
148
+ # Prepare axes handler
149
+ axes = []
150
+ for v05_axis in v05_multiscale.axes:
151
+ unit = v05_axis.unit
152
+ if unit is not None and not isinstance(unit, str):
153
+ unit = str(unit)
154
+ axes.append(
155
+ Axis(
156
+ name=str(v05_axis.name),
157
+ axis_type=AxisType(v05_axis.type),
158
+ # (for some reason the type is a generic JsonValue,
159
+ # but it should be a string or None)
160
+ unit=v05_axis.unit, # type: ignore
161
+ )
162
+ )
163
+ axes_handler = AxesHandler(
164
+ axes=axes,
165
+ axes_setup=axes_setup,
166
+ allow_non_canonical_axes=allow_non_canonical_axes,
167
+ strict_canonical_order=strict_canonical_order,
168
+ )
169
+
170
+ for v05_dataset in v05_multiscale.datasets:
171
+ _scale, _translation = _compute_scale_translation(
172
+ v05_dataset.coordinateTransformations, global_scale, global_translation
173
+ )
174
+ datasets.append(
175
+ Dataset(
176
+ path=v05_dataset.path,
177
+ axes_handler=axes_handler,
178
+ scale=_scale,
179
+ translation=_translation,
180
+ )
181
+ )
182
+ return datasets
183
+
184
+
185
+ def v05_to_ngio_image_meta(
186
+ metadata: dict,
187
+ axes_setup: AxesSetup | None = None,
188
+ allow_non_canonical_axes: bool = False,
189
+ strict_canonical_order: bool = True,
190
+ ) -> NgioImageMeta:
191
+ """Convert a v05 image metadata to a ngio image metadata.
192
+
193
+ Args:
194
+ metadata (dict): The v05 image metadata.
195
+ axes_setup (AxesSetup, optional): The axes setup. This is
196
+ required to convert image with non-canonical axes names.
197
+ allow_non_canonical_axes (bool, optional): Allow non-canonical axes.
198
+ strict_canonical_order (bool, optional): Strict canonical order.
199
+
200
+ Returns:
201
+ NgioImageMeta: The ngio image metadata.
202
+ """
203
+ v05_image = ImageV05WithOmero(**metadata)
204
+ v05_image = v05_image.ome
205
+ if len(v05_image.multiscales) > 1:
206
+ raise NotImplementedError(
207
+ "Multiple multiscales in a single image are not supported in ngio."
208
+ )
209
+
210
+ v05_multiscale = v05_image.multiscales[0]
211
+
212
+ channels_meta = _v05_omero_to_channels(v05_image.omero)
213
+ axes_setup = axes_setup if axes_setup is not None else AxesSetup()
214
+ datasets = _v05_to_ngio_datasets(
215
+ v05_multiscale,
216
+ axes_setup=axes_setup,
217
+ allow_non_canonical_axes=allow_non_canonical_axes,
218
+ strict_canonical_order=strict_canonical_order,
219
+ )
220
+
221
+ name = v05_multiscale.name
222
+ if name is not None and not isinstance(name, str):
223
+ name = str(name)
224
+ return NgioImageMeta(
225
+ version="0.5",
226
+ name=name,
227
+ datasets=datasets,
228
+ channels=channels_meta,
229
+ )
230
+
231
+
232
+ def v05_to_ngio_label_meta(
233
+ metadata: dict,
234
+ axes_setup: AxesSetup | None = None,
235
+ allow_non_canonical_axes: bool = False,
236
+ strict_canonical_order: bool = True,
237
+ ) -> NgioLabelMeta:
238
+ """Convert a v05 image metadata to a ngio image metadata.
239
+
240
+ Args:
241
+ metadata (dict): The v05 image metadata.
242
+ axes_setup (AxesSetup, optional): The axes setup. This is
243
+ required to convert image with non-canonical axes names.
244
+ allow_non_canonical_axes (bool, optional): Allow non-canonical axes.
245
+ strict_canonical_order (bool, optional): Strict canonical order.
246
+
247
+ Returns:
248
+ NgioLabelMeta: The ngio label metadata.
249
+ """
250
+ v05_label = ImageLabelV05(**metadata)
251
+ v05_label = v05_label.ome
252
+
253
+ if len(v05_label.multiscales) > 1:
254
+ raise NotImplementedError(
255
+ "Multiple multiscales in a single image are not supported in ngio."
256
+ )
257
+
258
+ v05_multiscale = v05_label.multiscales[0]
259
+
260
+ axes_setup = axes_setup if axes_setup is not None else AxesSetup()
261
+ datasets = _v05_to_ngio_datasets(
262
+ v05_multiscale,
263
+ axes_setup=axes_setup,
264
+ allow_non_canonical_axes=allow_non_canonical_axes,
265
+ strict_canonical_order=strict_canonical_order,
266
+ )
267
+
268
+ if v05_label.image_label is not None:
269
+ source = v05_label.image_label.source
270
+ if source is None:
271
+ image_label_source = None
272
+ else:
273
+ source = v05_label.image_label.source
274
+ if source is None:
275
+ image_label_source = None
276
+ else:
277
+ image_label_source = source.image
278
+ image_label_source = ImageLabelSource(
279
+ version="0.5",
280
+ source={"image": image_label_source},
281
+ )
282
+ else:
283
+ image_label_source = None
284
+ name = v05_multiscale.name
285
+ if name is not None and not isinstance(name, str):
286
+ name = str(name)
287
+
288
+ return NgioLabelMeta(
289
+ version="0.5",
290
+ name=name,
291
+ datasets=datasets,
292
+ image_label=image_label_source,
293
+ )
294
+
295
+
296
+ def _ngio_to_v05_multiscale(name: str | None, datasets: list[Dataset]) -> MultiscaleV05:
297
+ """Convert a ngio multiscale to a v05 multiscale.
298
+
299
+ Args:
300
+ name (str | None): The name of the multiscale.
301
+ datasets (list[Dataset]): The ngio datasets.
302
+
303
+ Returns:
304
+ MultiscaleV05: The v05 multiscale.
305
+ """
306
+ ax_mapper = datasets[0].axes_handler
307
+ v05_axes = []
308
+ for axis in ax_mapper.axes:
309
+ v05_axes.append(
310
+ AxisV05(
311
+ name=axis.name,
312
+ type=axis.axis_type.value if axis.axis_type is not None else None,
313
+ unit=axis.unit if axis.unit is not None else None,
314
+ )
315
+ )
316
+
317
+ v05_datasets = []
318
+ for dataset in datasets:
319
+ transform = [VectorScaleV05(type="scale", scale=list(dataset._scale))]
320
+ if sum(dataset._translation) > 0:
321
+ transform = (
322
+ VectorScaleV05(type="scale", scale=list(dataset._scale)),
323
+ VectorTranslationV05(
324
+ type="translation", translation=list(dataset._translation)
325
+ ),
326
+ )
327
+ else:
328
+ transform = (VectorScaleV05(type="scale", scale=list(dataset._scale)),)
329
+
330
+ v05_datasets.append(
331
+ DatasetV05(path=dataset.path, coordinateTransformations=transform)
332
+ )
333
+ return MultiscaleV05(axes=v05_axes, datasets=tuple(v05_datasets), name=name)
334
+
335
+
336
+ def _ngio_to_v05_omero(channels: ChannelsMeta | None) -> OmeroV05 | None:
337
+ """Convert a ngio channels to a v05 omero."""
338
+ if channels is None:
339
+ return None
340
+
341
+ v05_channels = []
342
+ for channel in channels.channels:
343
+ _model_extra = {
344
+ "label": channel.label,
345
+ "wavelength_id": channel.wavelength_id,
346
+ "active": channel.channel_visualisation.active,
347
+ }
348
+ if channel.channel_visualisation.model_extra is not None:
349
+ _model_extra.update(channel.channel_visualisation.model_extra)
350
+
351
+ v05_channels.append(
352
+ ChannelV05(
353
+ color=channel.channel_visualisation.valid_color,
354
+ window=WindowV05(
355
+ start=channel.channel_visualisation.start,
356
+ end=channel.channel_visualisation.end,
357
+ min=channel.channel_visualisation.min,
358
+ max=channel.channel_visualisation.max,
359
+ ),
360
+ **_model_extra,
361
+ )
362
+ )
363
+
364
+ _model_extra = channels.model_extra if channels.model_extra is not None else {}
365
+ return OmeroV05(channels=v05_channels, **_model_extra)
366
+
367
+
368
+ def ngio_to_v05_image_meta(metadata: NgioImageMeta) -> dict:
369
+ """Convert a ngio image metadata to a v05 image metadata.
370
+
371
+ Args:
372
+ metadata (NgioImageMeta): The ngio image metadata.
373
+
374
+ Returns:
375
+ dict: The v05 image metadata.
376
+ """
377
+ v05_muliscale = _ngio_to_v05_multiscale(
378
+ name=metadata.name, datasets=metadata.datasets
379
+ )
380
+ v05_omero = _ngio_to_v05_omero(metadata._channels_meta)
381
+
382
+ v05_image_attrs = ImageV05AttrsWithOmero(
383
+ multiscales=[v05_muliscale], omero=v05_omero, version="0.5"
384
+ )
385
+ v05_image = ImageV05WithOmero(
386
+ ome=v05_image_attrs,
387
+ )
388
+ return v05_image.model_dump(exclude_none=True, by_alias=True)
389
+
390
+
391
+ def ngio_to_v05_label_meta(metadata: NgioLabelMeta) -> dict:
392
+ """Convert a ngio image metadata to a v05 image metadata.
393
+
394
+ Args:
395
+ metadata (NgioImageMeta): The ngio image metadata.
396
+
397
+ Returns:
398
+ dict: The v05 image metadata.
399
+ """
400
+ v05_muliscale = _ngio_to_v05_multiscale(
401
+ name=metadata.name, datasets=metadata.datasets
402
+ )
403
+ labels_meta = {
404
+ "multiscales": [v05_muliscale],
405
+ "image-label": metadata.image_label.model_dump(),
406
+ }
407
+ v05_label = ImageLabelAttrsV05(**labels_meta, version="0.5")
408
+ v05_label = ImageLabelV05(
409
+ ome=v05_label,
410
+ )
411
+ return v05_label.model_dump(exclude_none=True, by_alias=True)
412
+
413
+
414
+ class WellV05(BaseModel):
415
+ ome: WellAttrsV05
416
+
417
+
418
+ class HCSV05(BaseModel):
419
+ ome: HCSAttrsV05
420
+
421
+
422
+ def v05_to_ngio_well_meta(
423
+ metadata: dict,
424
+ ) -> NgioWellMeta:
425
+ """Convert a v05 well metadata to a ngio well metadata.
426
+
427
+ Args:
428
+ metadata (dict): The v05 well metadata.
429
+
430
+ Returns:
431
+ NgioWellMeta: The ngio well metadata.
432
+ """
433
+ v05_well = WellV05(**metadata).ome.well.model_dump()
434
+ images = v05_well.get("images", [])
435
+ return NgioWellMeta(images=images, version="0.5")
436
+
437
+
438
+ def v05_to_ngio_plate_meta(
439
+ metadata: dict,
440
+ ) -> NgioPlateMeta:
441
+ """Convert a v05 plate metadata to a ngio plate metadata.
442
+
443
+ Args:
444
+ metadata (dict): The v05 plate metadata.
445
+
446
+ Returns:
447
+ NgioPlateMeta: The ngio plate metadata.
448
+ """
449
+ v05_plate = HCSV05(**metadata).ome.plate.model_dump()
450
+ return NgioPlateMeta(plate=v05_plate, version="0.5") # type: ignore
451
+
452
+
453
+ def ngio_to_v05_well_meta(metadata: NgioWellMeta) -> dict:
454
+ """Convert a ngio well metadata to a v05 well metadata.
455
+
456
+ Args:
457
+ metadata (NgioWellMeta): The ngio well metadata.
458
+
459
+ Returns:
460
+ dict: The v05 well metadata.
461
+ """
462
+ v05_well = WellAttrsV05(well=metadata.model_dump()) # type: ignore
463
+ v05_well = WellV05(ome=v05_well)
464
+ return v05_well.model_dump(exclude_none=True, by_alias=True)
465
+
466
+
467
+ def ngio_to_v05_plate_meta(metadata: NgioPlateMeta) -> dict:
468
+ """Convert a ngio plate metadata to a v05 plate metadata.
469
+
470
+ Args:
471
+ metadata (NgioPlateMeta): The ngio plate metadata.
472
+
473
+ Returns:
474
+ dict: The v05 plate metadata.
475
+ """
476
+ v05_plate = HCSAttrsV05(**metadata.model_dump())
477
+ v05_plate = HCSV05(ome=v05_plate)
478
+ return v05_plate.model_dump(exclude_none=True, by_alias=True)
479
+
480
+
481
+ class LabelsV05(BaseModel):
482
+ ome: LabelsAttrsV05
483
+
484
+
485
+ def v05_to_ngio_labels_group_meta(
486
+ metadata: dict,
487
+ ) -> NgioLabelsGroupMeta:
488
+ """Convert a v04 label group metadata to a ngio label group metadata.
489
+
490
+ Args:
491
+ metadata (dict): The v04 label group metadata.
492
+
493
+ Returns:
494
+ NgioLabelGroupMeta: The ngio label group metadata.
495
+ """
496
+ v05_label_group = LabelsV05(**metadata)
497
+ return NgioLabelsGroupMeta(labels=v05_label_group.ome.labels, version="0.5")
498
+
499
+
500
+ def ngio_to_v05_labels_group_meta(metadata: NgioLabelsGroupMeta) -> dict:
501
+ """Convert a ngio label group metadata to a v05 label group metadata.
502
+
503
+ Args:
504
+ metadata (NgioLabelsGroupMeta): The ngio label group metadata.
505
+
506
+ Returns:
507
+ dict: The v05 label group metadata.
508
+ """
509
+ v05_labels_attrs = LabelsAttrsV05(labels=metadata.labels, version="0.5")
510
+ v05_labels_group = LabelsV05(ome=v05_labels_attrs)
511
+ return v05_labels_group.model_dump(exclude_none=True, by_alias=True)
@@ -0,0 +1,55 @@
1
+ """Predefined resources for testing and demonstration purposes."""
2
+
3
+ from pathlib import Path
4
+ from typing import Literal
5
+
6
+ from ngio.resources.resource_model import LabelsInfo, SampleInfo
7
+
8
+ resources = Path(__file__).parent.resolve()
9
+
10
+ _resources = {
11
+ "Cardiomyocyte": SampleInfo(
12
+ img_path=resources
13
+ / "20200812-CardiomyocyteDifferentiation14-Cycle1_B03"
14
+ / "raw.jpg",
15
+ labels=[
16
+ LabelsInfo(
17
+ name="nuclei",
18
+ label_path=resources
19
+ / "20200812-CardiomyocyteDifferentiation14-Cycle1_B03"
20
+ / "nuclei.png",
21
+ create_masking_table=False,
22
+ ensure_unique_labels=True,
23
+ ),
24
+ LabelsInfo(
25
+ name="nuclei_mask",
26
+ label_path=resources
27
+ / "20200812-CardiomyocyteDifferentiation14-Cycle1_B03"
28
+ / "mask.png",
29
+ create_masking_table=True,
30
+ ensure_unique_labels=False,
31
+ dtype="uint8",
32
+ ),
33
+ ],
34
+ xy_pixelsize=0.325,
35
+ z_spacing=1.0,
36
+ time_spacing=1.0,
37
+ name="Cardiomyocyte Differentiation",
38
+ info="20200812-CardiomyocyteDifferentiation14-Cycle1_B03",
39
+ )
40
+ }
41
+
42
+ AVAILABLE_SAMPLES = Literal["Cardiomyocyte"]
43
+
44
+
45
+ def get_sample_info(name: AVAILABLE_SAMPLES) -> SampleInfo:
46
+ """Get a predefined resource by name."""
47
+ image_info = _resources.get(name)
48
+ if image_info is None:
49
+ raise ValueError(
50
+ f"Sample '{name}' not found. Available samples: {_resources.keys()}"
51
+ )
52
+ return image_info
53
+
54
+
55
+ __all__ = ["AVAILABLE_SAMPLES", "LabelsInfo", "SampleInfo"]
@@ -0,0 +1,36 @@
1
+ """Models for programmatic description of image resources."""
2
+
3
+ from pathlib import Path
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from ngio.ome_zarr_meta.ngio_specs import (
8
+ DefaultSpaceUnit,
9
+ DefaultTimeUnit,
10
+ SpaceUnits,
11
+ TimeUnits,
12
+ )
13
+
14
+
15
+ class LabelsInfo(BaseModel):
16
+ """Metadata for a label image."""
17
+
18
+ name: str
19
+ label_path: Path
20
+ ensure_unique_labels: bool = True
21
+ create_masking_table: bool = False
22
+ dtype: str = "uint32"
23
+
24
+
25
+ class SampleInfo(BaseModel):
26
+ """Metadata necessary to create an OME-Ngff from image files."""
27
+
28
+ img_path: Path
29
+ labels: list[LabelsInfo] = Field(default_factory=list)
30
+ xy_pixelsize: float
31
+ z_spacing: float = 1.0
32
+ time_spacing: float = 1.0
33
+ space_unit: SpaceUnits = DefaultSpaceUnit
34
+ time_unit: TimeUnits = DefaultTimeUnit
35
+ name: str | None = None
36
+ info: str | None = None
@@ -0,0 +1,43 @@
1
+ """Ngio Tables implementations."""
2
+
3
+ from ngio.tables._tables_container import (
4
+ ConditionTable,
5
+ FeatureTable,
6
+ GenericRoiTable,
7
+ MaskingRoiTable,
8
+ RoiTable,
9
+ Table,
10
+ TablesContainer,
11
+ TableType,
12
+ TypedTable,
13
+ open_table,
14
+ open_table_as,
15
+ open_tables_container,
16
+ )
17
+ from ngio.tables.backends import (
18
+ DefaultTableBackend,
19
+ ImplementedTableBackends,
20
+ TableBackend,
21
+ TableBackendProtocol,
22
+ )
23
+ from ngio.tables.v1._generic_table import GenericTable
24
+
25
+ __all__ = [
26
+ "ConditionTable",
27
+ "DefaultTableBackend",
28
+ "FeatureTable",
29
+ "GenericRoiTable",
30
+ "GenericTable",
31
+ "ImplementedTableBackends",
32
+ "MaskingRoiTable",
33
+ "RoiTable",
34
+ "Table",
35
+ "TableBackend",
36
+ "TableBackendProtocol",
37
+ "TableType",
38
+ "TablesContainer",
39
+ "TypedTable",
40
+ "open_table",
41
+ "open_table_as",
42
+ "open_tables_container",
43
+ ]