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.
- ngio/__init__.py +69 -0
- ngio/common/__init__.py +28 -0
- ngio/common/_dimensions.py +335 -0
- ngio/common/_masking_roi.py +153 -0
- ngio/common/_pyramid.py +408 -0
- ngio/common/_roi.py +315 -0
- ngio/common/_synt_images_utils.py +101 -0
- ngio/common/_zoom.py +188 -0
- ngio/experimental/__init__.py +5 -0
- ngio/experimental/iterators/__init__.py +15 -0
- ngio/experimental/iterators/_abstract_iterator.py +390 -0
- ngio/experimental/iterators/_feature.py +189 -0
- ngio/experimental/iterators/_image_processing.py +130 -0
- ngio/experimental/iterators/_mappers.py +48 -0
- ngio/experimental/iterators/_rois_utils.py +126 -0
- ngio/experimental/iterators/_segmentation.py +235 -0
- ngio/hcs/__init__.py +19 -0
- ngio/hcs/_plate.py +1354 -0
- ngio/images/__init__.py +44 -0
- ngio/images/_abstract_image.py +967 -0
- ngio/images/_create_synt_container.py +132 -0
- ngio/images/_create_utils.py +423 -0
- ngio/images/_image.py +926 -0
- ngio/images/_label.py +411 -0
- ngio/images/_masked_image.py +531 -0
- ngio/images/_ome_zarr_container.py +1237 -0
- ngio/images/_table_ops.py +471 -0
- ngio/io_pipes/__init__.py +75 -0
- ngio/io_pipes/_io_pipes.py +361 -0
- ngio/io_pipes/_io_pipes_masked.py +488 -0
- ngio/io_pipes/_io_pipes_roi.py +146 -0
- ngio/io_pipes/_io_pipes_types.py +56 -0
- ngio/io_pipes/_match_shape.py +377 -0
- ngio/io_pipes/_ops_axes.py +344 -0
- ngio/io_pipes/_ops_slices.py +411 -0
- ngio/io_pipes/_ops_slices_utils.py +199 -0
- ngio/io_pipes/_ops_transforms.py +104 -0
- ngio/io_pipes/_zoom_transform.py +180 -0
- ngio/ome_zarr_meta/__init__.py +65 -0
- ngio/ome_zarr_meta/_meta_handlers.py +536 -0
- ngio/ome_zarr_meta/ngio_specs/__init__.py +77 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +515 -0
- ngio/ome_zarr_meta/ngio_specs/_channels.py +462 -0
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +89 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +539 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +438 -0
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +122 -0
- ngio/ome_zarr_meta/v04/__init__.py +27 -0
- ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
- ngio/ome_zarr_meta/v04/_v04_spec.py +473 -0
- ngio/ome_zarr_meta/v05/__init__.py +27 -0
- ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
- ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
- ngio/resources/__init__.py +55 -0
- ngio/resources/resource_model.py +36 -0
- ngio/tables/__init__.py +43 -0
- ngio/tables/_abstract_table.py +270 -0
- ngio/tables/_tables_container.py +449 -0
- ngio/tables/backends/__init__.py +57 -0
- ngio/tables/backends/_abstract_backend.py +240 -0
- ngio/tables/backends/_anndata.py +139 -0
- ngio/tables/backends/_anndata_utils.py +90 -0
- ngio/tables/backends/_csv.py +19 -0
- ngio/tables/backends/_json.py +92 -0
- ngio/tables/backends/_parquet.py +19 -0
- ngio/tables/backends/_py_arrow_backends.py +222 -0
- ngio/tables/backends/_table_backends.py +226 -0
- ngio/tables/backends/_utils.py +608 -0
- ngio/tables/v1/__init__.py +23 -0
- ngio/tables/v1/_condition_table.py +71 -0
- ngio/tables/v1/_feature_table.py +125 -0
- ngio/tables/v1/_generic_table.py +49 -0
- ngio/tables/v1/_roi_table.py +575 -0
- ngio/transforms/__init__.py +5 -0
- ngio/transforms/_zoom.py +19 -0
- ngio/utils/__init__.py +45 -0
- ngio/utils/_cache.py +48 -0
- ngio/utils/_datasets.py +165 -0
- ngio/utils/_errors.py +37 -0
- ngio/utils/_fractal_fsspec_store.py +42 -0
- ngio/utils/_zarr_utils.py +534 -0
- ngio-0.5.0b6.dist-info/METADATA +148 -0
- ngio-0.5.0b6.dist-info/RECORD +88 -0
- ngio-0.5.0b6.dist-info/WHEEL +4 -0
- 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
|
ngio/tables/__init__.py
ADDED
|
@@ -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
|
+
]
|