ngio 0.2.0b3__py3-none-any.whl → 0.2.2__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 +30 -10
- ngio/common/__init__.py +3 -3
- ngio/common/_array_pipe.py +7 -1
- ngio/common/_masking_roi.py +4 -4
- ngio/common/_roi.py +14 -14
- ngio/hcs/__init__.py +16 -2
- ngio/hcs/plate.py +465 -54
- ngio/images/__init__.py +7 -7
- ngio/images/abstract_image.py +30 -10
- ngio/images/create.py +25 -35
- ngio/images/image.py +40 -8
- ngio/images/label.py +33 -8
- ngio/images/masked_image.py +19 -5
- ngio/images/{omezarr_container.py → ome_zarr_container.py} +84 -47
- ngio/ome_zarr_meta/__init__.py +5 -0
- ngio/ome_zarr_meta/ngio_specs/__init__.py +10 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +90 -65
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +46 -8
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +242 -69
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +53 -19
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +28 -11
- ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +3 -4
- ngio/tables/__init__.py +2 -2
- ngio/tables/tables_container.py +3 -3
- ngio/tables/v1/__init__.py +2 -2
- ngio/tables/v1/_feature_table.py +20 -1
- ngio/tables/v1/_generic_table.py +10 -0
- ngio/tables/v1/_roi_table.py +35 -13
- {ngio-0.2.0b3.dist-info → ngio-0.2.2.dist-info}/METADATA +8 -5
- ngio-0.2.2.dist-info/RECORD +55 -0
- ngio-0.2.0b3.dist-info/RECORD +0 -54
- {ngio-0.2.0b3.dist-info → ngio-0.2.2.dist-info}/WHEEL +0 -0
- {ngio-0.2.0b3.dist-info → ngio-0.2.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,7 +5,7 @@ from typing import Literal, overload
|
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
|
-
from ngio.images.create import
|
|
8
|
+
from ngio.images.create import create_empty_image_container
|
|
9
9
|
from ngio.images.image import Image, ImagesContainer
|
|
10
10
|
from ngio.images.label import Label, LabelsContainer
|
|
11
11
|
from ngio.images.masked_image import MaskedImage, MaskedLabel
|
|
@@ -14,13 +14,17 @@ from ngio.ome_zarr_meta import (
|
|
|
14
14
|
PixelSize,
|
|
15
15
|
)
|
|
16
16
|
from ngio.ome_zarr_meta.ngio_specs import (
|
|
17
|
+
DefaultNgffVersion,
|
|
18
|
+
DefaultSpaceUnit,
|
|
19
|
+
DefaultTimeUnit,
|
|
20
|
+
NgffVersions,
|
|
17
21
|
SpaceUnits,
|
|
18
22
|
TimeUnits,
|
|
19
23
|
)
|
|
20
24
|
from ngio.tables import (
|
|
21
25
|
FeatureTable,
|
|
22
26
|
GenericRoiTable,
|
|
23
|
-
|
|
27
|
+
MaskingRoiTable,
|
|
24
28
|
RoiTable,
|
|
25
29
|
Table,
|
|
26
30
|
TablesContainer,
|
|
@@ -155,7 +159,17 @@ class OmeZarrContainer:
|
|
|
155
159
|
"""Return True if the image is multichannel."""
|
|
156
160
|
return self.get_image().is_multi_channels
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
@property
|
|
163
|
+
def space_unit(self) -> str | None:
|
|
164
|
+
"""Return the space unit of the image."""
|
|
165
|
+
return self.image_meta.space_unit
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def time_unit(self) -> str | None:
|
|
169
|
+
"""Return the time unit of the image."""
|
|
170
|
+
return self.image_meta.time_unit
|
|
171
|
+
|
|
172
|
+
def set_channel_meta(
|
|
159
173
|
self,
|
|
160
174
|
labels: Collection[str] | int | None = None,
|
|
161
175
|
wavelength_id: Collection[str] | None = None,
|
|
@@ -165,7 +179,7 @@ class OmeZarrContainer:
|
|
|
165
179
|
**omero_kwargs: dict,
|
|
166
180
|
) -> None:
|
|
167
181
|
"""Create a ChannelsMeta object with the default unit."""
|
|
168
|
-
self._images_container.
|
|
182
|
+
self._images_container.set_channel_meta(
|
|
169
183
|
labels=labels,
|
|
170
184
|
wavelength_id=wavelength_id,
|
|
171
185
|
percentiles=percentiles,
|
|
@@ -174,16 +188,36 @@ class OmeZarrContainer:
|
|
|
174
188
|
**omero_kwargs,
|
|
175
189
|
)
|
|
176
190
|
|
|
177
|
-
def
|
|
191
|
+
def set_channel_percentiles(
|
|
178
192
|
self,
|
|
179
193
|
start_percentile: float = 0.1,
|
|
180
194
|
end_percentile: float = 99.9,
|
|
181
195
|
) -> None:
|
|
182
196
|
"""Update the percentiles of the image."""
|
|
183
|
-
self._images_container.
|
|
197
|
+
self._images_container.set_channel_percentiles(
|
|
184
198
|
start_percentile=start_percentile, end_percentile=end_percentile
|
|
185
199
|
)
|
|
186
200
|
|
|
201
|
+
def set_axes_units(
|
|
202
|
+
self,
|
|
203
|
+
space_unit: SpaceUnits = DefaultSpaceUnit,
|
|
204
|
+
time_unit: TimeUnits = DefaultTimeUnit,
|
|
205
|
+
set_labels: bool = True,
|
|
206
|
+
) -> None:
|
|
207
|
+
"""Set the units of the image.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
space_unit (SpaceUnits): The unit of space.
|
|
211
|
+
time_unit (TimeUnits): The unit of time.
|
|
212
|
+
set_labels (bool): Whether to set the units for the labels as well.
|
|
213
|
+
"""
|
|
214
|
+
self._images_container.set_axes_unit(space_unit=space_unit, time_unit=time_unit)
|
|
215
|
+
if not set_labels:
|
|
216
|
+
return
|
|
217
|
+
for label_name in self.list_labels():
|
|
218
|
+
label = self.get_label(label_name)
|
|
219
|
+
label.set_axes_unit(space_unit=space_unit, time_unit=time_unit)
|
|
220
|
+
|
|
187
221
|
def get_image(
|
|
188
222
|
self,
|
|
189
223
|
path: str | None = None,
|
|
@@ -193,7 +227,7 @@ class OmeZarrContainer:
|
|
|
193
227
|
"""Get an image at a specific level.
|
|
194
228
|
|
|
195
229
|
Args:
|
|
196
|
-
path (str | None): The path to the image in the
|
|
230
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
197
231
|
pixel_size (PixelSize | None): The pixel size of the image.
|
|
198
232
|
strict (bool): Only used if the pixel size is provided. If True, the
|
|
199
233
|
pixel size must match the image pixel size exactly. If False, the
|
|
@@ -217,7 +251,7 @@ class OmeZarrContainer:
|
|
|
217
251
|
Args:
|
|
218
252
|
masking_label_name (str): The name of the label.
|
|
219
253
|
masking_table_name (str | None): The name of the masking table.
|
|
220
|
-
path (str | None): The path to the image in the
|
|
254
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
221
255
|
pixel_size (PixelSize | None): The pixel size of the image.
|
|
222
256
|
strict (bool): Only used if the pixel size is provided. If True, the
|
|
223
257
|
pixel size must match the image pixel size exactly. If False, the
|
|
@@ -250,6 +284,7 @@ class OmeZarrContainer:
|
|
|
250
284
|
labels: Collection[str] | None = None,
|
|
251
285
|
pixel_size: PixelSize | None = None,
|
|
252
286
|
axes_names: Collection[str] | None = None,
|
|
287
|
+
name: str | None = None,
|
|
253
288
|
chunks: Collection[int] | None = None,
|
|
254
289
|
dtype: str | None = None,
|
|
255
290
|
copy_labels: bool = False,
|
|
@@ -268,6 +303,7 @@ class OmeZarrContainer:
|
|
|
268
303
|
axes_names (Collection[str] | None): The axes names of the new image.
|
|
269
304
|
chunks (Collection[int] | None): The chunk shape of the new image.
|
|
270
305
|
dtype (str | None): The data type of the new image.
|
|
306
|
+
name (str | None): The name of the new image.
|
|
271
307
|
copy_labels (bool): Whether to copy the labels from the reference image.
|
|
272
308
|
copy_tables (bool): Whether to copy the tables from the reference image.
|
|
273
309
|
overwrite (bool): Whether to overwrite an existing image.
|
|
@@ -283,6 +319,7 @@ class OmeZarrContainer:
|
|
|
283
319
|
labels=labels,
|
|
284
320
|
pixel_size=pixel_size,
|
|
285
321
|
axes_names=axes_names,
|
|
322
|
+
name=name,
|
|
286
323
|
chunks=chunks,
|
|
287
324
|
dtype=dtype,
|
|
288
325
|
overwrite=overwrite,
|
|
@@ -292,21 +329,21 @@ class OmeZarrContainer:
|
|
|
292
329
|
store, cache=self._group_handler.use_cache, mode=self._group_handler.mode
|
|
293
330
|
)
|
|
294
331
|
|
|
295
|
-
|
|
332
|
+
new_ome_zarr = OmeZarrContainer(
|
|
296
333
|
group_handler=handler,
|
|
297
334
|
validate_arrays=False,
|
|
298
335
|
)
|
|
299
336
|
|
|
300
337
|
if copy_labels:
|
|
301
338
|
self.labels_container._group_handler.copy_handler(
|
|
302
|
-
|
|
339
|
+
new_ome_zarr.labels_container._group_handler
|
|
303
340
|
)
|
|
304
341
|
|
|
305
342
|
if copy_tables:
|
|
306
343
|
self.tables_container._group_handler.copy_handler(
|
|
307
|
-
|
|
344
|
+
new_ome_zarr.tables_container._group_handler
|
|
308
345
|
)
|
|
309
|
-
return
|
|
346
|
+
return new_ome_zarr
|
|
310
347
|
|
|
311
348
|
def list_tables(self) -> list[str]:
|
|
312
349
|
"""List all tables in the image."""
|
|
@@ -325,7 +362,7 @@ class OmeZarrContainer:
|
|
|
325
362
|
@overload
|
|
326
363
|
def get_table(
|
|
327
364
|
self, name: str, check_type: Literal["masking_roi_table"]
|
|
328
|
-
) ->
|
|
365
|
+
) -> MaskingRoiTable: ...
|
|
329
366
|
|
|
330
367
|
@overload
|
|
331
368
|
def get_table(
|
|
@@ -348,7 +385,7 @@ class OmeZarrContainer:
|
|
|
348
385
|
)
|
|
349
386
|
return table
|
|
350
387
|
case "masking_roi_table":
|
|
351
|
-
if not isinstance(table,
|
|
388
|
+
if not isinstance(table, MaskingRoiTable):
|
|
352
389
|
raise NgioValueError(
|
|
353
390
|
f"Table '{name}' is not a masking ROI table. "
|
|
354
391
|
f"Found type: {table.type()}"
|
|
@@ -379,7 +416,7 @@ class OmeZarrContainer:
|
|
|
379
416
|
"""Compute the ROI table for an image."""
|
|
380
417
|
return self.get_image().build_image_roi_table(name=name)
|
|
381
418
|
|
|
382
|
-
def build_masking_roi_table(self, label: str) ->
|
|
419
|
+
def build_masking_roi_table(self, label: str) -> MaskingRoiTable:
|
|
383
420
|
"""Compute the masking ROI table for a label."""
|
|
384
421
|
return self.get_label(label).build_masking_roi_table()
|
|
385
422
|
|
|
@@ -410,7 +447,7 @@ class OmeZarrContainer:
|
|
|
410
447
|
|
|
411
448
|
Args:
|
|
412
449
|
name (str): The name of the label.
|
|
413
|
-
path (str | None): The path to the image in the
|
|
450
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
414
451
|
pixel_size (PixelSize | None): The pixel size of the image.
|
|
415
452
|
strict (bool): Only used if the pixel size is provided. If True, the
|
|
416
453
|
pixel size must match the image pixel size exactly. If False, the
|
|
@@ -435,7 +472,7 @@ class OmeZarrContainer:
|
|
|
435
472
|
label_name (str): The name of the label.
|
|
436
473
|
masking_label_name (str): The name of the masking label.
|
|
437
474
|
masking_table_name (str | None): The name of the masking table.
|
|
438
|
-
path (str | None): The path to the image in the
|
|
475
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
439
476
|
pixel_size (PixelSize | None): The pixel size of the image.
|
|
440
477
|
strict (bool): Only used if the pixel size is provided. If True, the
|
|
441
478
|
pixel size must match the image pixel size exactly. If False, the
|
|
@@ -507,7 +544,7 @@ class OmeZarrContainer:
|
|
|
507
544
|
)
|
|
508
545
|
|
|
509
546
|
|
|
510
|
-
def
|
|
547
|
+
def open_ome_zarr_container(
|
|
511
548
|
store: StoreOrGroup,
|
|
512
549
|
cache: bool = False,
|
|
513
550
|
mode: AccessModeLiteral = "r+",
|
|
@@ -533,7 +570,7 @@ def open_image(
|
|
|
533
570
|
|
|
534
571
|
Args:
|
|
535
572
|
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
536
|
-
path (str | None): The path to the image in the
|
|
573
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
537
574
|
pixel_size (PixelSize | None): The pixel size of the image.
|
|
538
575
|
strict (bool): Only used if the pixel size is provided. If True, the
|
|
539
576
|
pixel size must match the image pixel size exactly. If False, the
|
|
@@ -551,7 +588,7 @@ def open_image(
|
|
|
551
588
|
)
|
|
552
589
|
|
|
553
590
|
|
|
554
|
-
def
|
|
591
|
+
def create_empty_ome_zarr(
|
|
555
592
|
store: StoreOrGroup,
|
|
556
593
|
shape: Collection[int],
|
|
557
594
|
xy_pixelsize: float,
|
|
@@ -560,8 +597,8 @@ def create_empty_omezarr(
|
|
|
560
597
|
levels: int | list[str] = 5,
|
|
561
598
|
xy_scaling_factor: float = 2,
|
|
562
599
|
z_scaling_factor: float = 1.0,
|
|
563
|
-
space_unit: SpaceUnits
|
|
564
|
-
time_unit: TimeUnits
|
|
600
|
+
space_unit: SpaceUnits = DefaultSpaceUnit,
|
|
601
|
+
time_unit: TimeUnits = DefaultTimeUnit,
|
|
565
602
|
axes_names: Collection[str] | None = None,
|
|
566
603
|
name: str | None = None,
|
|
567
604
|
chunks: Collection[int] | None = None,
|
|
@@ -572,7 +609,7 @@ def create_empty_omezarr(
|
|
|
572
609
|
channel_colors: Collection[str] | None = None,
|
|
573
610
|
channel_active: Collection[bool] | None = None,
|
|
574
611
|
overwrite: bool = False,
|
|
575
|
-
version:
|
|
612
|
+
version: NgffVersions = DefaultNgffVersion,
|
|
576
613
|
) -> OmeZarrContainer:
|
|
577
614
|
"""Create an empty OME-Zarr image with the given shape and metadata.
|
|
578
615
|
|
|
@@ -589,10 +626,10 @@ def create_empty_omezarr(
|
|
|
589
626
|
dimensions. Defaults to 2.0.
|
|
590
627
|
z_scaling_factor (float, optional): The down-scaling factor in z dimension.
|
|
591
628
|
Defaults to 1.0.
|
|
592
|
-
space_unit (SpaceUnits
|
|
593
|
-
|
|
594
|
-
time_unit (TimeUnits
|
|
595
|
-
|
|
629
|
+
space_unit (SpaceUnits, optional): The unit of space. Defaults to
|
|
630
|
+
DefaultSpaceUnit.
|
|
631
|
+
time_unit (TimeUnits, optional): The unit of time. Defaults to
|
|
632
|
+
DefaultTimeUnit.
|
|
596
633
|
axes_names (Collection[str] | None, optional): The names of the axes.
|
|
597
634
|
If None the canonical names are used. Defaults to None.
|
|
598
635
|
name (str | None, optional): The name of the image. Defaults to None.
|
|
@@ -611,10 +648,10 @@ def create_empty_omezarr(
|
|
|
611
648
|
active. Defaults to None.
|
|
612
649
|
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
613
650
|
Defaults to True.
|
|
614
|
-
version (
|
|
615
|
-
Defaults to
|
|
651
|
+
version (NgffVersion, optional): The version of the OME-Zarr specification.
|
|
652
|
+
Defaults to DefaultNgffVersion.
|
|
616
653
|
"""
|
|
617
|
-
handler =
|
|
654
|
+
handler = create_empty_image_container(
|
|
618
655
|
store=store,
|
|
619
656
|
shape=shape,
|
|
620
657
|
pixelsize=xy_pixelsize,
|
|
@@ -633,18 +670,18 @@ def create_empty_omezarr(
|
|
|
633
670
|
version=version,
|
|
634
671
|
)
|
|
635
672
|
|
|
636
|
-
|
|
637
|
-
|
|
673
|
+
ome_zarr = OmeZarrContainer(group_handler=handler)
|
|
674
|
+
ome_zarr.set_channel_meta(
|
|
638
675
|
labels=channel_labels,
|
|
639
676
|
wavelength_id=channel_wavelengths,
|
|
640
677
|
percentiles=percentiles,
|
|
641
678
|
colors=channel_colors,
|
|
642
679
|
active=channel_active,
|
|
643
680
|
)
|
|
644
|
-
return
|
|
681
|
+
return ome_zarr
|
|
645
682
|
|
|
646
683
|
|
|
647
|
-
def
|
|
684
|
+
def create_ome_zarr_from_array(
|
|
648
685
|
store: StoreOrGroup,
|
|
649
686
|
array: np.ndarray,
|
|
650
687
|
xy_pixelsize: float,
|
|
@@ -653,8 +690,8 @@ def create_omezarr_from_array(
|
|
|
653
690
|
levels: int | list[str] = 5,
|
|
654
691
|
xy_scaling_factor: float = 2.0,
|
|
655
692
|
z_scaling_factor: float = 1.0,
|
|
656
|
-
space_unit: SpaceUnits
|
|
657
|
-
time_unit: TimeUnits
|
|
693
|
+
space_unit: SpaceUnits = DefaultSpaceUnit,
|
|
694
|
+
time_unit: TimeUnits = DefaultTimeUnit,
|
|
658
695
|
axes_names: Collection[str] | None = None,
|
|
659
696
|
channel_labels: list[str] | None = None,
|
|
660
697
|
channel_wavelengths: list[str] | None = None,
|
|
@@ -664,7 +701,7 @@ def create_omezarr_from_array(
|
|
|
664
701
|
name: str | None = None,
|
|
665
702
|
chunks: Collection[int] | None = None,
|
|
666
703
|
overwrite: bool = False,
|
|
667
|
-
version:
|
|
704
|
+
version: NgffVersions = DefaultNgffVersion,
|
|
668
705
|
) -> OmeZarrContainer:
|
|
669
706
|
"""Create an OME-Zarr image from a numpy array.
|
|
670
707
|
|
|
@@ -681,10 +718,10 @@ def create_omezarr_from_array(
|
|
|
681
718
|
dimensions. Defaults to 2.0.
|
|
682
719
|
z_scaling_factor (float, optional): The down-scaling factor in z dimension.
|
|
683
720
|
Defaults to 1.0.
|
|
684
|
-
space_unit (SpaceUnits
|
|
685
|
-
|
|
686
|
-
time_unit (TimeUnits
|
|
687
|
-
|
|
721
|
+
space_unit (SpaceUnits, optional): The unit of space. Defaults to
|
|
722
|
+
DefaultSpaceUnit.
|
|
723
|
+
time_unit (TimeUnits, optional): The unit of time. Defaults to
|
|
724
|
+
DefaultTimeUnit.
|
|
688
725
|
axes_names (Collection[str] | None, optional): The names of the axes.
|
|
689
726
|
If None the canonical names are used. Defaults to None.
|
|
690
727
|
name (str | None, optional): The name of the image. Defaults to None.
|
|
@@ -703,9 +740,9 @@ def create_omezarr_from_array(
|
|
|
703
740
|
overwrite (bool, optional): Whether to overwrite an existing image.
|
|
704
741
|
Defaults to True.
|
|
705
742
|
version (str, optional): The version of the OME-Zarr specification.
|
|
706
|
-
Defaults to
|
|
743
|
+
Defaults to DefaultNgffVersion.
|
|
707
744
|
"""
|
|
708
|
-
handler =
|
|
745
|
+
handler = create_empty_image_container(
|
|
709
746
|
store=store,
|
|
710
747
|
shape=array.shape,
|
|
711
748
|
pixelsize=xy_pixelsize,
|
|
@@ -724,15 +761,15 @@ def create_omezarr_from_array(
|
|
|
724
761
|
version=version,
|
|
725
762
|
)
|
|
726
763
|
|
|
727
|
-
|
|
728
|
-
image =
|
|
764
|
+
ome_zarr = OmeZarrContainer(group_handler=handler)
|
|
765
|
+
image = ome_zarr.get_image()
|
|
729
766
|
image.set_array(array)
|
|
730
767
|
image.consolidate()
|
|
731
|
-
|
|
768
|
+
ome_zarr.set_channel_meta(
|
|
732
769
|
labels=channel_labels,
|
|
733
770
|
wavelength_id=channel_wavelengths,
|
|
734
771
|
percentiles=percentiles,
|
|
735
772
|
colors=channel_colors,
|
|
736
773
|
active=channel_active,
|
|
737
774
|
)
|
|
738
|
-
return
|
|
775
|
+
return ome_zarr
|
ngio/ome_zarr_meta/__init__.py
CHANGED
|
@@ -16,11 +16,13 @@ from ngio.ome_zarr_meta.ngio_specs import (
|
|
|
16
16
|
AxesMapper,
|
|
17
17
|
Dataset,
|
|
18
18
|
ImageInWellPath,
|
|
19
|
+
NgffVersions,
|
|
19
20
|
NgioImageMeta,
|
|
20
21
|
NgioLabelMeta,
|
|
21
22
|
NgioPlateMeta,
|
|
22
23
|
NgioWellMeta,
|
|
23
24
|
PixelSize,
|
|
25
|
+
path_in_well_validation,
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
__all__ = [
|
|
@@ -31,6 +33,8 @@ __all__ = [
|
|
|
31
33
|
"ImageMetaHandler",
|
|
32
34
|
"LabelMetaHandler",
|
|
33
35
|
"LabelMetaHandler",
|
|
36
|
+
"NgffVersions",
|
|
37
|
+
"NgffVersions",
|
|
34
38
|
"NgioImageMeta",
|
|
35
39
|
"NgioLabelMeta",
|
|
36
40
|
"NgioPlateMeta",
|
|
@@ -44,4 +48,5 @@ __all__ = [
|
|
|
44
48
|
"get_label_meta_handler",
|
|
45
49
|
"get_plate_meta_handler",
|
|
46
50
|
"get_well_meta_handler",
|
|
51
|
+
"path_in_well_validation",
|
|
47
52
|
]
|
|
@@ -15,6 +15,8 @@ from ngio.ome_zarr_meta.ngio_specs._axes import (
|
|
|
15
15
|
AxesTranspose,
|
|
16
16
|
Axis,
|
|
17
17
|
AxisType,
|
|
18
|
+
DefaultSpaceUnit,
|
|
19
|
+
DefaultTimeUnit,
|
|
18
20
|
SpaceUnits,
|
|
19
21
|
TimeUnits,
|
|
20
22
|
canonical_axes_order,
|
|
@@ -32,9 +34,12 @@ from ngio.ome_zarr_meta.ngio_specs._ngio_hcs import (
|
|
|
32
34
|
ImageInWellPath,
|
|
33
35
|
NgioPlateMeta,
|
|
34
36
|
NgioWellMeta,
|
|
37
|
+
path_in_well_validation,
|
|
35
38
|
)
|
|
36
39
|
from ngio.ome_zarr_meta.ngio_specs._ngio_image import (
|
|
40
|
+
DefaultNgffVersion,
|
|
37
41
|
ImageLabelSource,
|
|
42
|
+
NgffVersions,
|
|
38
43
|
NgioImageLabelMeta,
|
|
39
44
|
NgioImageMeta,
|
|
40
45
|
NgioLabelMeta,
|
|
@@ -54,8 +59,12 @@ __all__ = [
|
|
|
54
59
|
"ChannelVisualisation",
|
|
55
60
|
"ChannelsMeta",
|
|
56
61
|
"Dataset",
|
|
62
|
+
"DefaultNgffVersion",
|
|
63
|
+
"DefaultSpaceUnit",
|
|
64
|
+
"DefaultTimeUnit",
|
|
57
65
|
"ImageInWellPath",
|
|
58
66
|
"ImageLabelSource",
|
|
67
|
+
"NgffVersions",
|
|
59
68
|
"NgioColors",
|
|
60
69
|
"NgioImageLabelMeta",
|
|
61
70
|
"NgioImageMeta",
|
|
@@ -68,4 +77,5 @@ __all__ = [
|
|
|
68
77
|
"canonical_axes_order",
|
|
69
78
|
"canonical_label_axes_order",
|
|
70
79
|
"default_channel_name",
|
|
80
|
+
"path_in_well_validation",
|
|
71
81
|
]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from collections.abc import Collection
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from logging import Logger
|
|
6
|
-
from typing import TypeVar
|
|
6
|
+
from typing import Literal, TypeVar
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from pydantic import BaseModel, ConfigDict, Field
|
|
@@ -32,98 +32,108 @@ class AxisType(str, Enum):
|
|
|
32
32
|
space = "space"
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
SpaceUnits = Literal[
|
|
36
|
+
"micrometer",
|
|
37
|
+
"nanometer",
|
|
38
|
+
"angstrom",
|
|
39
|
+
"picometer",
|
|
40
|
+
"millimeter",
|
|
41
|
+
"centimeter",
|
|
42
|
+
"decimeter",
|
|
43
|
+
"meter",
|
|
44
|
+
"inch",
|
|
45
|
+
"foot",
|
|
46
|
+
"yard",
|
|
47
|
+
"mile",
|
|
48
|
+
"kilometer",
|
|
49
|
+
"hectometer",
|
|
50
|
+
"megameter",
|
|
51
|
+
"gigameter",
|
|
52
|
+
"terameter",
|
|
53
|
+
"petameter",
|
|
54
|
+
"exameter",
|
|
55
|
+
"parsec",
|
|
56
|
+
"femtometer",
|
|
57
|
+
"attometer",
|
|
58
|
+
"zeptometer",
|
|
59
|
+
"yoctometer",
|
|
60
|
+
"zettameter",
|
|
61
|
+
"yottameter",
|
|
62
|
+
]
|
|
63
|
+
DefaultSpaceUnit = "micrometer"
|
|
64
|
+
|
|
65
|
+
TimeUnits = Literal[
|
|
66
|
+
"attosecond",
|
|
67
|
+
"centisecond",
|
|
68
|
+
"day",
|
|
69
|
+
"decisecond",
|
|
70
|
+
"exasecond",
|
|
71
|
+
"femtosecond",
|
|
72
|
+
"gigasecond",
|
|
73
|
+
"hectosecond",
|
|
74
|
+
"hour",
|
|
75
|
+
"kilosecond",
|
|
76
|
+
"megasecond",
|
|
77
|
+
"microsecond",
|
|
78
|
+
"millisecond",
|
|
79
|
+
"minute",
|
|
80
|
+
"nanosecond",
|
|
81
|
+
"petasecond",
|
|
82
|
+
"picosecond",
|
|
83
|
+
"second",
|
|
84
|
+
"terasecond",
|
|
85
|
+
"yoctosecond",
|
|
86
|
+
"yottasecond",
|
|
87
|
+
"zeptosecond",
|
|
88
|
+
"zettasecond",
|
|
89
|
+
]
|
|
90
|
+
DefaultTimeUnit = "second"
|
|
61
91
|
|
|
62
92
|
|
|
63
93
|
class Axis(BaseModel):
|
|
64
94
|
"""Axis infos model."""
|
|
65
95
|
|
|
66
96
|
on_disk_name: str
|
|
67
|
-
unit:
|
|
97
|
+
unit: str | None = None
|
|
68
98
|
axis_type: AxisType | None = None
|
|
69
99
|
|
|
70
100
|
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
71
101
|
|
|
72
102
|
def implicit_type_cast(self, cast_type: AxisType) -> "Axis":
|
|
103
|
+
unit = self.unit
|
|
73
104
|
if self.axis_type != cast_type:
|
|
74
105
|
logger.warning(
|
|
75
106
|
f"Axis {self.on_disk_name} has type {self.axis_type}. "
|
|
76
107
|
f"Casting to {cast_type}."
|
|
77
108
|
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
)
|
|
81
|
-
if cast_type == AxisType.time and not isinstance(self.unit, TimeUnits):
|
|
109
|
+
|
|
110
|
+
if cast_type == AxisType.time and unit is None:
|
|
82
111
|
logger.warning(
|
|
83
112
|
f"Time axis {self.on_disk_name} has unit {self.unit}. "
|
|
84
|
-
f"Casting to {
|
|
85
|
-
)
|
|
86
|
-
new_axis = Axis(
|
|
87
|
-
on_disk_name=self.on_disk_name,
|
|
88
|
-
axis_type=AxisType.time,
|
|
89
|
-
unit=TimeUnits.default(),
|
|
90
|
-
)
|
|
91
|
-
elif cast_type == AxisType.space and not isinstance(self.unit, SpaceUnits):
|
|
92
|
-
logger.warning(
|
|
93
|
-
f"Space axis {self.on_disk_name} has unit {self.unit}. "
|
|
94
|
-
f"Casting to {SpaceUnits.default()}."
|
|
113
|
+
f"Casting to {DefaultSpaceUnit}."
|
|
95
114
|
)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
unit=SpaceUnits.default(),
|
|
100
|
-
)
|
|
101
|
-
elif cast_type == AxisType.channel and self.unit is not None:
|
|
115
|
+
unit = DefaultTimeUnit
|
|
116
|
+
|
|
117
|
+
if cast_type == AxisType.space and unit is None:
|
|
102
118
|
logger.warning(
|
|
103
|
-
f"
|
|
104
|
-
|
|
105
|
-
new_axis = Axis(
|
|
106
|
-
on_disk_name=self.on_disk_name,
|
|
107
|
-
axis_type=AxisType.channel,
|
|
108
|
-
unit=None,
|
|
119
|
+
f"Space axis {self.on_disk_name} has unit {unit}. "
|
|
120
|
+
f"Casting to {DefaultSpaceUnit}."
|
|
109
121
|
)
|
|
110
|
-
|
|
122
|
+
unit = DefaultSpaceUnit
|
|
123
|
+
|
|
124
|
+
return Axis(on_disk_name=self.on_disk_name, axis_type=cast_type, unit=unit)
|
|
111
125
|
|
|
112
126
|
def canonical_axis_cast(self, canonical_name: str) -> "Axis":
|
|
113
127
|
"""Cast the implicit axis to the correct type."""
|
|
114
128
|
match canonical_name:
|
|
115
129
|
case "t":
|
|
116
|
-
if self.axis_type != AxisType.time or
|
|
117
|
-
self.unit, TimeUnits
|
|
118
|
-
):
|
|
130
|
+
if self.axis_type != AxisType.time or self.unit is None:
|
|
119
131
|
return self.implicit_type_cast(AxisType.time)
|
|
120
132
|
case "c":
|
|
121
|
-
if self.axis_type != AxisType.channel
|
|
133
|
+
if self.axis_type != AxisType.channel:
|
|
122
134
|
return self.implicit_type_cast(AxisType.channel)
|
|
123
135
|
case "z" | "y" | "x":
|
|
124
|
-
if self.axis_type != AxisType.space or
|
|
125
|
-
self.unit, SpaceUnits
|
|
126
|
-
):
|
|
136
|
+
if self.axis_type != AxisType.space or self.unit is None:
|
|
127
137
|
return self.implicit_type_cast(AxisType.space)
|
|
128
138
|
return self
|
|
129
139
|
|
|
@@ -345,6 +355,11 @@ class AxesMapper:
|
|
|
345
355
|
_index_mapping[canonical_key] = None
|
|
346
356
|
return _index_mapping
|
|
347
357
|
|
|
358
|
+
@property
|
|
359
|
+
def axes_setup(self) -> AxesSetup:
|
|
360
|
+
"""Return the axes setup."""
|
|
361
|
+
return self._axes_setup
|
|
362
|
+
|
|
348
363
|
@property
|
|
349
364
|
def on_disk_axes(self) -> list[Axis]:
|
|
350
365
|
return list(self._on_disk_axes)
|
|
@@ -353,6 +368,16 @@ class AxesMapper:
|
|
|
353
368
|
def on_disk_axes_names(self) -> list[str]:
|
|
354
369
|
return [ax.on_disk_name for ax in self._on_disk_axes]
|
|
355
370
|
|
|
371
|
+
@property
|
|
372
|
+
def allow_non_canonical_axes(self) -> bool:
|
|
373
|
+
"""Return if non canonical axes are allowed."""
|
|
374
|
+
return self._allow_non_canonical_axes
|
|
375
|
+
|
|
376
|
+
@property
|
|
377
|
+
def strict_canonical_order(self) -> bool:
|
|
378
|
+
"""Return if strict canonical order is enforced."""
|
|
379
|
+
return self._strict_canonical_order
|
|
380
|
+
|
|
356
381
|
def get_index(self, name: str) -> int | None:
|
|
357
382
|
"""Get the index of the axis by name."""
|
|
358
383
|
if name not in self._index_mapping.keys():
|
|
@@ -443,8 +468,8 @@ class AxesMapper:
|
|
|
443
468
|
|
|
444
469
|
def canonical_axes(
|
|
445
470
|
axes_names: Collection[str],
|
|
446
|
-
space_units: SpaceUnits | None =
|
|
447
|
-
time_units: TimeUnits | None =
|
|
471
|
+
space_units: SpaceUnits | None = DefaultSpaceUnit,
|
|
472
|
+
time_units: TimeUnits | None = DefaultTimeUnit,
|
|
448
473
|
) -> list[Axis]:
|
|
449
474
|
"""Create a new canonical axes mapper.
|
|
450
475
|
|