ngio 0.4.8__py3-none-any.whl → 0.5.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 (56) hide show
  1. ngio/__init__.py +5 -2
  2. ngio/common/__init__.py +11 -6
  3. ngio/common/_masking_roi.py +34 -54
  4. ngio/common/_pyramid.py +322 -75
  5. ngio/common/_roi.py +258 -330
  6. ngio/experimental/iterators/_feature.py +3 -3
  7. ngio/experimental/iterators/_rois_utils.py +10 -11
  8. ngio/hcs/_plate.py +192 -136
  9. ngio/images/_abstract_image.py +539 -35
  10. ngio/images/_create_synt_container.py +45 -47
  11. ngio/images/_create_utils.py +406 -0
  12. ngio/images/_image.py +524 -248
  13. ngio/images/_label.py +257 -180
  14. ngio/images/_masked_image.py +2 -2
  15. ngio/images/_ome_zarr_container.py +658 -255
  16. ngio/io_pipes/_io_pipes.py +9 -9
  17. ngio/io_pipes/_io_pipes_masked.py +7 -7
  18. ngio/io_pipes/_io_pipes_roi.py +6 -6
  19. ngio/io_pipes/_io_pipes_types.py +3 -3
  20. ngio/io_pipes/_match_shape.py +6 -8
  21. ngio/io_pipes/_ops_slices_utils.py +8 -5
  22. ngio/ome_zarr_meta/__init__.py +29 -18
  23. ngio/ome_zarr_meta/_meta_handlers.py +402 -689
  24. ngio/ome_zarr_meta/ngio_specs/__init__.py +4 -0
  25. ngio/ome_zarr_meta/ngio_specs/_axes.py +152 -51
  26. ngio/ome_zarr_meta/ngio_specs/_dataset.py +13 -22
  27. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +129 -91
  28. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +69 -69
  29. ngio/ome_zarr_meta/v04/__init__.py +5 -1
  30. ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +55 -86
  31. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  32. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  33. ngio/ome_zarr_meta/v05/_v05_spec.py +495 -0
  34. ngio/resources/__init__.py +1 -1
  35. ngio/resources/resource_model.py +1 -1
  36. ngio/tables/_tables_container.py +82 -24
  37. ngio/tables/backends/_abstract_backend.py +7 -0
  38. ngio/tables/backends/_anndata.py +60 -7
  39. ngio/tables/backends/_anndata_utils.py +2 -4
  40. ngio/tables/backends/_csv.py +3 -19
  41. ngio/tables/backends/_json.py +10 -13
  42. ngio/tables/backends/_parquet.py +3 -31
  43. ngio/tables/backends/_py_arrow_backends.py +222 -0
  44. ngio/tables/backends/_utils.py +1 -1
  45. ngio/tables/v1/_roi_table.py +41 -24
  46. ngio/utils/__init__.py +8 -12
  47. ngio/utils/_cache.py +48 -0
  48. ngio/utils/_zarr_utils.py +354 -236
  49. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/METADATA +12 -5
  50. ngio-0.5.0.dist-info/RECORD +88 -0
  51. ngio/images/_create.py +0 -276
  52. ngio/tables/backends/_non_zarr_backends.py +0 -196
  53. ngio/utils/_logger.py +0 -50
  54. ngio-0.4.8.dist-info/RECORD +0 -85
  55. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/WHEEL +0 -0
  56. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,17 +1,24 @@
1
1
  """Abstract class for handling OME-NGFF images."""
2
2
 
3
3
  import warnings
4
- from collections.abc import Sequence
4
+ from collections.abc import Mapping, Sequence
5
+ from typing import Any, Literal
5
6
 
6
7
  import numpy as np
7
- from zarr.types import DIMENSION_SEPARATOR
8
+ from zarr.core.array import CompressorLike
8
9
 
9
- from ngio.images._create import create_empty_image_container
10
+ from ngio.common._pyramid import ChunksLike, ShardsLike
11
+ from ngio.images._create_utils import init_image_like
10
12
  from ngio.images._image import Image, ImagesContainer
11
13
  from ngio.images._label import Label, LabelsContainer
12
14
  from ngio.images._masked_image import MaskedImage, MaskedLabel
13
- from ngio.ome_zarr_meta import NgioImageMeta, PixelSize, find_label_meta_handler
15
+ from ngio.ome_zarr_meta import (
16
+ LabelMetaHandler,
17
+ NgioImageMeta,
18
+ PixelSize,
19
+ )
14
20
  from ngio.ome_zarr_meta.ngio_specs import (
21
+ Channel,
15
22
  DefaultNgffVersion,
16
23
  DefaultSpaceUnit,
17
24
  DefaultTimeUnit,
@@ -19,6 +26,8 @@ from ngio.ome_zarr_meta.ngio_specs import (
19
26
  SpaceUnits,
20
27
  TimeUnits,
21
28
  )
29
+ from ngio.ome_zarr_meta.ngio_specs._axes import AxesSetup
30
+ from ngio.ome_zarr_meta.ngio_specs._channels import ChannelsMeta
22
31
  from ngio.tables import (
23
32
  ConditionTable,
24
33
  DefaultTableBackend,
@@ -34,6 +43,7 @@ from ngio.tables import (
34
43
  )
35
44
  from ngio.utils import (
36
45
  AccessModeLiteral,
46
+ NgioError,
37
47
  NgioValidationError,
38
48
  NgioValueError,
39
49
  StoreOrGroup,
@@ -41,18 +51,33 @@ from ngio.utils import (
41
51
  )
42
52
 
43
53
 
44
- def _default_table_container(handler: ZarrGroupHandler) -> TablesContainer | None:
54
+ def _try_get_table_container(
55
+ handler: ZarrGroupHandler, create_mode: bool = True
56
+ ) -> TablesContainer | None:
45
57
  """Return a default table container."""
46
- success, table_handler = handler.safe_derive_handler("tables")
47
- if success and isinstance(table_handler, ZarrGroupHandler):
58
+ try:
59
+ table_handler = handler.get_handler("tables", create_mode=create_mode)
48
60
  return TablesContainer(table_handler)
61
+ except NgioError:
62
+ return None
49
63
 
50
64
 
51
- def _default_label_container(handler: ZarrGroupHandler) -> LabelsContainer | None:
65
+ def _try_get_label_container(
66
+ handler: ZarrGroupHandler,
67
+ ngff_version: NgffVersions,
68
+ axes_setup: AxesSetup | None = None,
69
+ create_mode: bool = True,
70
+ ) -> LabelsContainer | None:
52
71
  """Return a default label container."""
53
- success, label_handler = handler.safe_derive_handler("labels")
54
- if success and isinstance(label_handler, ZarrGroupHandler):
55
- return LabelsContainer(label_handler)
72
+ try:
73
+ label_handler = handler.get_handler("labels", create_mode=create_mode)
74
+ return LabelsContainer(
75
+ group_handler=label_handler,
76
+ axes_setup=axes_setup,
77
+ ngff_version=ngff_version,
78
+ )
79
+ except FileNotFoundError:
80
+ return None
56
81
 
57
82
 
58
83
  class OmeZarrContainer:
@@ -81,6 +106,7 @@ class OmeZarrContainer:
81
106
  group_handler: ZarrGroupHandler,
82
107
  table_container: TablesContainer | None = None,
83
108
  label_container: LabelsContainer | None = None,
109
+ axes_setup: AxesSetup | None = None,
84
110
  validate_paths: bool = False,
85
111
  ) -> None:
86
112
  """Initialize the OmeZarrContainer.
@@ -89,16 +115,19 @@ class OmeZarrContainer:
89
115
  group_handler (ZarrGroupHandler): The Zarr group handler.
90
116
  table_container (TablesContainer | None): The tables container.
91
117
  label_container (LabelsContainer | None): The labels container.
118
+ axes_setup (AxesSetup | None): Axes setup to load ome-zarr with
119
+ non-standard axes configurations.
92
120
  validate_paths (bool): Whether to validate the paths of the image multiscale
93
121
  """
94
122
  self._group_handler = group_handler
95
- self._images_container = ImagesContainer(self._group_handler)
96
-
123
+ self._images_container = ImagesContainer(
124
+ self._group_handler, axes_setup=axes_setup
125
+ )
97
126
  self._labels_container = label_container
98
127
  self._tables_container = table_container
99
128
 
100
129
  if validate_paths:
101
- for level_path in self._images_container.levels_paths:
130
+ for level_path in self._images_container.level_paths:
102
131
  self.get_image(path=level_path)
103
132
 
104
133
  def __repr__(self) -> str:
@@ -127,13 +156,18 @@ class OmeZarrContainer:
127
156
  """
128
157
  return self._images_container
129
158
 
130
- def _get_labels_container(self) -> LabelsContainer | None:
159
+ def _get_labels_container(self, create_mode: bool = True) -> LabelsContainer | None:
131
160
  """Return the labels container."""
132
- if self._labels_container is None:
133
- _labels_container = _default_label_container(self._group_handler)
134
- if _labels_container is None:
135
- return None
136
- self._labels_container = _labels_container
161
+ if self._labels_container is not None:
162
+ return self._labels_container
163
+
164
+ _labels_container = _try_get_label_container(
165
+ self._group_handler,
166
+ create_mode=create_mode,
167
+ ngff_version=self.meta.version,
168
+ axes_setup=self._images_container.axes_setup,
169
+ )
170
+ self._labels_container = _labels_container
137
171
  return self._labels_container
138
172
 
139
173
  @property
@@ -144,13 +178,15 @@ class OmeZarrContainer:
144
178
  raise NgioValidationError("No labels found in the image.")
145
179
  return _labels_container
146
180
 
147
- def _get_tables_container(self) -> TablesContainer | None:
181
+ def _get_tables_container(self, create_mode: bool = True) -> TablesContainer | None:
148
182
  """Return the tables container."""
149
- if self._tables_container is None:
150
- _tables_container = _default_table_container(self._group_handler)
151
- if _tables_container is None:
152
- return None
153
- self._tables_container = _tables_container
183
+ if self._tables_container is not None:
184
+ return self._tables_container
185
+
186
+ _tables_container = _try_get_table_container(
187
+ self._group_handler, create_mode=create_mode
188
+ )
189
+ self._tables_container = _tables_container
154
190
  return self._tables_container
155
191
 
156
192
  @property
@@ -161,116 +197,238 @@ class OmeZarrContainer:
161
197
  raise NgioValidationError("No tables found in the image.")
162
198
  return _tables_container
163
199
 
200
+ @property
201
+ def meta(self) -> NgioImageMeta:
202
+ """Return the image metadata."""
203
+ return self.images_container.meta
204
+
164
205
  @property
165
206
  def image_meta(self) -> NgioImageMeta:
166
207
  """Return the image metadata."""
167
- return self._images_container.meta
208
+ warnings.warn(
209
+ "'image_meta' is deprecated and will be removed in ngio=0.6. "
210
+ "Please use 'meta' instead.",
211
+ DeprecationWarning,
212
+ stacklevel=2,
213
+ )
214
+ return self.images_container.meta
215
+
216
+ @property
217
+ def axes_setup(self) -> AxesSetup:
218
+ """Return the axes setup."""
219
+ return self.images_container.axes_setup
168
220
 
169
221
  @property
170
222
  def levels(self) -> int:
171
223
  """Return the number of levels in the image."""
172
- return self._images_container.levels
224
+ return self.images_container.levels
173
225
 
174
226
  @property
175
- def levels_paths(self) -> list[str]:
227
+ def level_paths(self) -> list[str]:
176
228
  """Return the paths of the levels in the image."""
177
- return self._images_container.levels_paths
229
+ return self.images_container.level_paths
230
+
231
+ @property
232
+ def levels_paths(self) -> list[str]:
233
+ """Deprecated: use 'level_paths' instead."""
234
+ warnings.warn(
235
+ "'levels_paths' is deprecated and will be removed in ngio=0.6. "
236
+ "Please use 'level_paths' instead.",
237
+ DeprecationWarning,
238
+ stacklevel=2,
239
+ )
240
+ return self.images_container.level_paths
178
241
 
179
242
  @property
180
243
  def is_3d(self) -> bool:
181
244
  """Return True if the image is 3D."""
182
- return self.get_image().is_3d
245
+ return self.images_container.is_3d
183
246
 
184
247
  @property
185
248
  def is_2d(self) -> bool:
186
249
  """Return True if the image is 2D."""
187
- return self.get_image().is_2d
250
+ return self.images_container.is_2d
188
251
 
189
252
  @property
190
253
  def is_time_series(self) -> bool:
191
254
  """Return True if the image is a time series."""
192
- return self.get_image().is_time_series
255
+ return self.images_container.is_time_series
193
256
 
194
257
  @property
195
258
  def is_2d_time_series(self) -> bool:
196
259
  """Return True if the image is a 2D time series."""
197
- return self.get_image().is_2d_time_series
260
+ return self.images_container.is_2d_time_series
198
261
 
199
262
  @property
200
263
  def is_3d_time_series(self) -> bool:
201
264
  """Return True if the image is a 3D time series."""
202
- return self.get_image().is_3d_time_series
265
+ return self.images_container.is_3d_time_series
203
266
 
204
267
  @property
205
268
  def is_multi_channels(self) -> bool:
206
269
  """Return True if the image is multichannel."""
207
- return self.get_image().is_multi_channels
270
+ return self.images_container.is_multi_channels
208
271
 
209
272
  @property
210
273
  def space_unit(self) -> str | None:
211
274
  """Return the space unit of the image."""
212
- return self.image_meta.space_unit
275
+ return self.images_container.space_unit
213
276
 
214
277
  @property
215
278
  def time_unit(self) -> str | None:
216
279
  """Return the time unit of the image."""
217
- return self.image_meta.time_unit
280
+ return self.images_container.time_unit
218
281
 
219
282
  @property
220
283
  def channel_labels(self) -> list[str]:
221
284
  """Return the channels of the image."""
222
- image = self.get_image()
223
- return image.channel_labels
285
+ return self.images_container.channel_labels
224
286
 
225
287
  @property
226
288
  def wavelength_ids(self) -> list[str | None]:
227
289
  """Return the list of wavelength of the image."""
228
- image = self.get_image()
229
- return image.wavelength_ids
290
+ return self.images_container.wavelength_ids
230
291
 
231
292
  @property
232
293
  def num_channels(self) -> int:
233
294
  """Return the number of channels."""
234
- return len(self.channel_labels)
295
+ return self.images_container.num_channels
235
296
 
236
297
  def get_channel_idx(
237
298
  self, channel_label: str | None = None, wavelength_id: str | None = None
238
299
  ) -> int:
239
300
  """Get the index of a channel by its label or wavelength ID."""
240
- image = self.get_image()
241
- return image.channels_meta.get_channel_idx(
301
+ return self.images_container.get_channel_idx(
242
302
  channel_label=channel_label, wavelength_id=wavelength_id
243
303
  )
244
304
 
245
305
  def set_channel_meta(
246
306
  self,
247
- labels: Sequence[str] | int | None = None,
248
- wavelength_id: Sequence[str] | None = None,
307
+ channel_meta: ChannelsMeta | None = None,
308
+ labels: Sequence[str | None] | int | None = None,
309
+ wavelength_id: Sequence[str | None] | None = None,
310
+ start: Sequence[float | None] | None = None,
311
+ end: Sequence[float | None] | None = None,
249
312
  percentiles: tuple[float, float] | None = None,
250
- colors: Sequence[str] | None = None,
251
- active: Sequence[bool] | None = None,
313
+ colors: Sequence[str | None] | None = None,
314
+ active: Sequence[bool | None] | None = None,
252
315
  **omero_kwargs: dict,
253
316
  ) -> None:
254
- """Create a ChannelsMeta object with the default unit."""
317
+ """Create a ChannelsMeta object with the default unit.
318
+
319
+ Args:
320
+ channel_meta (ChannelsMeta | None): The channels metadata to set.
321
+ If none, it will fall back to the deprecated parameters.
322
+ labels(Sequence[str | None] | int): Deprecated. The list of channels names
323
+ in the image. If an integer is provided, the channels will
324
+ be named "channel_i".
325
+ wavelength_id(Sequence[str | None]): Deprecated. The wavelength ID of the
326
+ channel. If None, the wavelength ID will be the same as
327
+ the channel name.
328
+ start(Sequence[float | None]): Deprecated. The start value for each channel.
329
+ If None, the start value will be computed from the image.
330
+ end(Sequence[float | None]): Deprecated. The end value for each channel.
331
+ If None, the end value will be computed from the image.
332
+ percentiles(tuple[float, float] | None): Deprecated. The start and end
333
+ percentiles for each channel. If None, the percentiles will
334
+ not be computed.
335
+ colors(Sequence[str | None]): Deprecated. The list of colors for the
336
+ channels. If None, the colors will be random.
337
+ active (Sequence[bool | None]): Deprecated. Whether the channel should
338
+ be shown by default.
339
+ omero_kwargs(dict): Deprecated. Extra fields to store in the omero
340
+ attributes.
341
+ """
255
342
  self._images_container.set_channel_meta(
343
+ channel_meta=channel_meta,
256
344
  labels=labels,
257
345
  wavelength_id=wavelength_id,
258
- start=None,
259
- end=None,
346
+ start=start,
347
+ end=end,
260
348
  percentiles=percentiles,
261
349
  colors=colors,
262
350
  active=active,
263
351
  **omero_kwargs,
264
352
  )
265
353
 
354
+ def set_channel_labels(
355
+ self,
356
+ labels: Sequence[str],
357
+ ) -> None:
358
+ """Update the labels of the channels.
359
+
360
+ Args:
361
+ labels (Sequence[str]): The new labels for the channels.
362
+ """
363
+ self._images_container.set_channel_labels(labels=labels)
364
+
365
+ def set_channel_colors(
366
+ self,
367
+ colors: Sequence[str],
368
+ ) -> None:
369
+ """Update the colors of the channels.
370
+
371
+ Args:
372
+ colors (Sequence[str]): The new colors for the channels.
373
+ """
374
+ self._images_container.set_channel_colors(colors=colors)
375
+
266
376
  def set_channel_percentiles(
267
377
  self,
268
378
  start_percentile: float = 0.1,
269
379
  end_percentile: float = 99.9,
270
380
  ) -> None:
271
- """Update the percentiles of the image."""
272
- self._images_container.set_channel_percentiles(
273
- start_percentile=start_percentile, end_percentile=end_percentile
381
+ """Deprecated: Update the channel windows using percentiles.
382
+
383
+ Args:
384
+ start_percentile (float): The start percentile.
385
+ end_percentile (float): The end percentile.
386
+ """
387
+ warnings.warn(
388
+ "The 'set_channel_percentiles' method is deprecated and will be removed in "
389
+ "ngio=0.6. Please use 'set_channel_windows_with_percentiles' instead.",
390
+ DeprecationWarning,
391
+ stacklevel=2,
392
+ )
393
+ self._images_container.set_channel_windows_with_percentiles(
394
+ percentiles=(start_percentile, end_percentile)
395
+ )
396
+
397
+ def set_channel_windows(
398
+ self,
399
+ starts_ends: Sequence[tuple[float, float]],
400
+ min_max: Sequence[tuple[float, float]] | None = None,
401
+ ) -> None:
402
+ """Update the channel windows.
403
+
404
+ These values are used by viewers to set the display
405
+ range of each channel.
406
+
407
+ Args:
408
+ starts_ends (Sequence[tuple[float, float]]): The start and end values
409
+ for each channel.
410
+ min_max (Sequence[tuple[float, float]] | None): The min and max values
411
+ for each channel. If None, the min and max values will not be updated.
412
+ """
413
+ self._images_container.set_channel_windows(
414
+ starts_ends=starts_ends,
415
+ min_max=min_max,
416
+ )
417
+
418
+ def set_channel_windows_with_percentiles(
419
+ self,
420
+ percentiles: tuple[float, float] | list[tuple[float, float]] = (0.1, 99.9),
421
+ ) -> None:
422
+ """Update the channel windows using percentiles.
423
+
424
+ Args:
425
+ percentiles (tuple[float, float] | list[tuple[float, float]]):
426
+ The start and end percentiles for each channel.
427
+ If a single tuple is provided,
428
+ the same percentiles will be used for all channels.
429
+ """
430
+ self._images_container.set_channel_windows_with_percentiles(
431
+ percentiles=percentiles
274
432
  )
275
433
 
276
434
  def set_axes_units(
@@ -286,12 +444,35 @@ class OmeZarrContainer:
286
444
  time_unit (TimeUnits): The unit of time.
287
445
  set_labels (bool): Whether to set the units for the labels as well.
288
446
  """
447
+ if set_labels:
448
+ for label_name in self.list_labels():
449
+ label = self.get_label(label_name)
450
+ label.set_axes_unit(space_unit=space_unit, time_unit=time_unit)
289
451
  self._images_container.set_axes_unit(space_unit=space_unit, time_unit=time_unit)
290
- if not set_labels:
291
- return
292
- for label_name in self.list_labels():
293
- label = self.get_label(label_name)
294
- label.set_axes_unit(space_unit=space_unit, time_unit=time_unit)
452
+
453
+ def set_axes_names(
454
+ self,
455
+ axes_names: Sequence[str],
456
+ ) -> None:
457
+ """Set the axes names of the image.
458
+
459
+ Args:
460
+ axes_names (Sequence[str]): The axes names of the image.
461
+ """
462
+ self._images_container.set_axes_names(axes_names=axes_names)
463
+
464
+ def set_name(
465
+ self,
466
+ name: str,
467
+ ) -> None:
468
+ """Set the name of the image in the metadata.
469
+
470
+ This does not change the group name or any paths.
471
+
472
+ Args:
473
+ name (str): The name of the image.
474
+ """
475
+ self._images_container.set_name(name=name)
295
476
 
296
477
  def get_image(
297
478
  self,
@@ -402,83 +583,122 @@ class OmeZarrContainer:
402
583
  self,
403
584
  store: StoreOrGroup,
404
585
  ref_path: str | None = None,
586
+ # Metadata parameters
405
587
  shape: Sequence[int] | None = None,
406
- labels: Sequence[str] | None = None,
407
- pixel_size: PixelSize | None = None,
408
- axes_names: Sequence[str] | None = None,
588
+ pixelsize: float | tuple[float, float] | None = None,
589
+ z_spacing: float | None = None,
590
+ time_spacing: float | None = None,
409
591
  name: str | None = None,
410
- chunks: Sequence[int] | None = None,
411
- dtype: str | None = None,
412
- dimension_separator: DIMENSION_SEPARATOR | None = None,
413
- compressor=None,
592
+ translation: Sequence[float] | None = None,
593
+ channels_policy: Literal["squeeze", "same", "singleton"] | int = "same",
594
+ channels_meta: Sequence[str | Channel] | None = None,
595
+ ngff_version: NgffVersions | None = None,
596
+ # Zarr Array parameters
597
+ chunks: ChunksLike | None = None,
598
+ shards: ShardsLike | None = None,
599
+ dtype: str = "uint16",
600
+ dimension_separator: Literal[".", "/"] = "/",
601
+ compressors: CompressorLike = "auto",
602
+ extra_array_kwargs: Mapping[str, Any] | None = None,
603
+ overwrite: bool = False,
604
+ # Copy from current image
414
605
  copy_labels: bool = False,
415
606
  copy_tables: bool = False,
416
- overwrite: bool = False,
607
+ # Deprecated arguments
608
+ labels: Sequence[str] | None = None,
609
+ pixel_size: PixelSize | None = None,
417
610
  ) -> "OmeZarrContainer":
418
- """Create an empty OME-Zarr container from an existing image.
611
+ """Derive a new OME-Zarr container from the current image.
612
+
613
+ If a kwarg is not provided, the value from the reference image will be used.
419
614
 
420
615
  Args:
421
616
  store (StoreOrGroup): The Zarr store or group to create the image in.
422
- ref_path (str | None): The path to the reference image in
423
- the image container.
617
+ ref_path (str | None): The path to the reference image in the image
618
+ container.
424
619
  shape (Sequence[int] | None): The shape of the new image.
425
- labels (Sequence[str] | None): The labels of the new image.
426
- pixel_size (PixelSize | None): The pixel size of the new image.
427
- axes_names (Sequence[str] | None): The axes names of the new image.
428
- chunks (Sequence[int] | None): The chunk shape of the new image.
429
- dtype (str | None): The data type of the new image.
620
+ pixelsize (float | tuple[float, float] | None): The pixel size of the new
621
+ image.
622
+ z_spacing (float | None): The z spacing of the new image.
623
+ time_spacing (float | None): The time spacing of the new image.
430
624
  name (str | None): The name of the new image.
431
- dimension_separator (DIMENSION_SEPARATOR | None): The dimension
432
- separator to use. If None, the dimension separator of the
433
- reference image will be used.
434
- compressor: The compressor to use. If None, the compressor of the
435
- reference image will be used.
436
- copy_labels (bool): Whether to copy the labels from the reference image.
437
- copy_tables (bool): Whether to copy the tables from the reference image.
438
- overwrite (bool): Whether to overwrite an existing image.
625
+ translation (Sequence[float] | None): The translation for each axis
626
+ at the highest resolution level. Defaults to None.
627
+ channels_policy (Literal["squeeze", "same", "singleton"] | int): Possible
628
+ policies:
629
+ - If "squeeze", the channels axis will be removed (no matter its size).
630
+ - If "same", the channels axis will be kept as is (if it exists).
631
+ - If "singleton", the channels axis will be set to size 1.
632
+ - If an integer is provided, the channels axis will be changed to have
633
+ that size.
634
+ channels_meta (Sequence[str | Channel] | None): The channels metadata
635
+ of the new image.
636
+ ngff_version (NgffVersions | None): The NGFF version to use.
637
+ chunks (ChunksLike | None): The chunk shape of the new image.
638
+ shards (ShardsLike | None): The shard shape of the new image.
639
+ dtype (str): The data type of the new image. Defaults to "uint16".
640
+ dimension_separator (Literal[".", "/"]): The separator to use for
641
+ dimensions. Defaults to "/".
642
+ compressors (CompressorLike): The compressors to use. Defaults to "auto".
643
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
644
+ the zarr array creation.
645
+ overwrite (bool): Whether to overwrite an existing image. Defaults to False.
646
+ copy_labels (bool): Whether to copy the labels from the current image.
647
+ Defaults to False.
648
+ copy_tables (bool): Whether to copy the tables from the current image.
649
+ Defaults to False.
650
+ labels (Sequence[str] | None): Deprecated. This argument is deprecated,
651
+ please use channels_meta instead.
652
+ pixel_size (PixelSize | None): Deprecated. The pixel size of the new image.
653
+ This argument is deprecated, please use pixelsize, z_spacing,
654
+ and time_spacing instead.
439
655
 
440
656
  Returns:
441
- OmeZarrContainer: The new image container.
657
+ OmeZarrContainer: The new derived OME-Zarr container.
442
658
 
443
659
  """
444
- _ = self._images_container.derive(
660
+ new_container = self._images_container.derive(
445
661
  store=store,
446
662
  ref_path=ref_path,
447
663
  shape=shape,
448
- labels=labels,
449
- pixel_size=pixel_size,
450
- axes_names=axes_names,
664
+ pixelsize=pixelsize,
665
+ z_spacing=z_spacing,
666
+ time_spacing=time_spacing,
451
667
  name=name,
668
+ translation=translation,
669
+ channels_meta=channels_meta,
670
+ channels_policy=channels_policy,
671
+ ngff_version=ngff_version,
452
672
  chunks=chunks,
673
+ shards=shards,
453
674
  dtype=dtype,
454
675
  dimension_separator=dimension_separator,
455
- compressor=compressor,
676
+ compressors=compressors,
677
+ extra_array_kwargs=extra_array_kwargs,
456
678
  overwrite=overwrite,
679
+ labels=labels,
680
+ pixel_size=pixel_size,
457
681
  )
458
-
459
- handler = ZarrGroupHandler(
460
- store, cache=self._group_handler.use_cache, mode=self._group_handler.mode
461
- )
462
-
463
682
  new_ome_zarr = OmeZarrContainer(
464
- group_handler=handler,
683
+ group_handler=new_container._group_handler,
465
684
  validate_paths=False,
685
+ axes_setup=new_container.meta.axes_handler.axes_setup,
466
686
  )
467
687
 
468
688
  if copy_labels:
469
- self.labels_container._group_handler.copy_handler(
470
- new_ome_zarr.labels_container._group_handler
689
+ self.labels_container._group_handler.copy_group(
690
+ new_ome_zarr.labels_container._group_handler.group
471
691
  )
472
692
 
473
693
  if copy_tables:
474
- self.tables_container._group_handler.copy_handler(
475
- new_ome_zarr.tables_container._group_handler
694
+ self.tables_container._group_handler.copy_group(
695
+ new_ome_zarr.tables_container._group_handler.group
476
696
  )
477
697
  return new_ome_zarr
478
698
 
479
699
  def list_tables(self, filter_types: TypedTable | str | None = None) -> list[str]:
480
700
  """List all tables in the image."""
481
- table_container = self._get_tables_container()
701
+ table_container = self._get_tables_container(create_mode=False)
482
702
  if table_container is None:
483
703
  return []
484
704
 
@@ -571,8 +791,8 @@ class OmeZarrContainer:
571
791
  """
572
792
  if check_type is not None:
573
793
  warnings.warn(
574
- "The 'check_type' argument is deprecated, and will be removed in "
575
- "ngio=0.3. Use 'get_table_as' instead or one of the "
794
+ "The 'check_type' argument is deprecated and will be removed in "
795
+ "ngio=0.6. Please use 'get_table_as' instead or one of the "
576
796
  "type specific get_*table() methods.",
577
797
  DeprecationWarning,
578
798
  stacklevel=2,
@@ -619,9 +839,28 @@ class OmeZarrContainer:
619
839
  name=name, table=table, backend=backend, overwrite=overwrite
620
840
  )
621
841
 
842
+ def delete_table(self, name: str, missing_ok: bool = False) -> None:
843
+ """Delete a table from the group.
844
+
845
+ Args:
846
+ name (str): The name of the table to delete.
847
+ missing_ok (bool): If True, do not raise an error if the table does not
848
+ exist.
849
+
850
+ """
851
+ table_container = self._get_tables_container(create_mode=False)
852
+ if table_container is None and missing_ok:
853
+ return
854
+ if table_container is None:
855
+ raise NgioValueError(
856
+ f"No tables found in the image, cannot delete {name}. "
857
+ "Set missing_ok=True to ignore this error."
858
+ )
859
+ table_container.delete(name=name, missing_ok=missing_ok)
860
+
622
861
  def list_labels(self) -> list[str]:
623
862
  """List all labels in the image."""
624
- label_container = self._get_labels_container()
863
+ label_container = self._get_labels_container(create_mode=False)
625
864
  if label_container is None:
626
865
  return []
627
866
  return label_container.list()
@@ -684,42 +923,90 @@ class OmeZarrContainer:
684
923
  masking_roi_table=masking_table,
685
924
  )
686
925
 
926
+ def delete_label(self, name: str, missing_ok: bool = False) -> None:
927
+ """Delete a label from the group.
928
+
929
+ Args:
930
+ name (str): The name of the label to delete.
931
+ missing_ok (bool): If True, do not raise an error if the label does not
932
+ exist.
933
+
934
+ """
935
+ label_container = self._get_labels_container(create_mode=False)
936
+ if label_container is None and missing_ok:
937
+ return
938
+ if label_container is None:
939
+ raise NgioValueError(
940
+ f"No labels found in the image, cannot delete {name}. "
941
+ "Set missing_ok=True to ignore this error."
942
+ )
943
+ label_container.delete(name=name, missing_ok=missing_ok)
944
+
687
945
  def derive_label(
688
946
  self,
689
947
  name: str,
690
948
  ref_image: Image | Label | None = None,
949
+ # Metadata parameters
691
950
  shape: Sequence[int] | None = None,
692
- pixel_size: PixelSize | None = None,
693
- axes_names: Sequence[str] | None = None,
694
- chunks: Sequence[int] | None = None,
695
- dtype: str = "uint32",
696
- dimension_separator: DIMENSION_SEPARATOR | None = None,
697
- compressor=None,
951
+ pixelsize: float | tuple[float, float] | None = None,
952
+ z_spacing: float | None = None,
953
+ time_spacing: float | None = None,
954
+ translation: Sequence[float] | None = None,
955
+ channels_policy: Literal["same", "squeeze", "singleton"] | int = "squeeze",
956
+ ngff_version: NgffVersions | None = None,
957
+ # Zarr Array parameters
958
+ chunks: ChunksLike | None = None,
959
+ shards: ShardsLike | None = None,
960
+ dtype: str | None = None,
961
+ dimension_separator: Literal[".", "/"] | None = None,
962
+ compressors: CompressorLike | None = None,
963
+ extra_array_kwargs: Mapping[str, Any] | None = None,
698
964
  overwrite: bool = False,
965
+ # Deprecated arguments
966
+ labels: Sequence[str] | None = None,
967
+ pixel_size: PixelSize | None = None,
699
968
  ) -> "Label":
700
- """Create an empty OME-Zarr label from a reference image.
969
+ """Derive a new label from an existing image or label.
701
970
 
702
- And add the label to the /labels group.
971
+ If a kwarg is not provided, the value from the reference image will be used.
703
972
 
704
973
  Args:
705
- name (str): The name of the new image.
706
- ref_image (Image | Label | None): A reference image that will be used
707
- to create the new image.
708
- shape (Sequence[int] | None): The shape of the new image.
709
- pixel_size (PixelSize | None): The pixel size of the new image.
710
- axes_names (Sequence[str] | None): The axes names of the new image.
711
- For labels, the channel axis is not allowed.
712
- chunks (Sequence[int] | None): The chunk shape of the new image.
713
- dtype (str): The data type of the new label.
714
- dimension_separator (DIMENSION_SEPARATOR | None): The dimension
715
- separator to use. If None, the dimension separator of the
716
- reference image will be used.
717
- compressor: The compressor to use. If None, the compressor of the
718
- reference image will be used.
719
- overwrite (bool): Whether to overwrite an existing image.
974
+ name (str): The name of the new label.
975
+ ref_image (Image | Label | None): The reference image to derive the new
976
+ label from. If None, the first level image will be used.
977
+ shape (Sequence[int] | None): The shape of the new label.
978
+ pixelsize (float | tuple[float, float] | None): The pixel size of the new
979
+ label.
980
+ z_spacing (float | None): The z spacing of the new label.
981
+ time_spacing (float | None): The time spacing of the new label.
982
+ translation (Sequence[float] | None): The translation for each axis
983
+ at the highest resolution level. Defaults to None.
984
+ channels_policy (Literal["same", "squeeze", "singleton"] | int): Possible
985
+ policies:
986
+ - If "squeeze", the channels axis will be removed (no matter its size).
987
+ - If "same", the channels axis will be kept as is (if it exists).
988
+ - If "singleton", the channels axis will be set to size 1.
989
+ - If an integer is provided, the channels axis will be changed to have
990
+ that size.
991
+ Defaults to "squeeze".
992
+ ngff_version (NgffVersions | None): The NGFF version to use.
993
+ chunks (ChunksLike | None): The chunk shape of the new label.
994
+ shards (ShardsLike | None): The shard shape of the new label.
995
+ dtype (str | None): The data type of the new label.
996
+ dimension_separator (Literal[".", "/"] | None): The separator to use for
997
+ dimensions.
998
+ compressors (CompressorLike | None): The compressors to use.
999
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
1000
+ the zarr array creation.
1001
+ overwrite (bool): Whether to overwrite an existing label. Defaults to False.
1002
+ labels (Sequence[str] | None): Deprecated. This argument is deprecated,
1003
+ please use channels_meta instead.
1004
+ pixel_size (PixelSize | None): Deprecated. The pixel size of the new label.
1005
+ This argument is deprecated, please use pixelsize, z_spacing,
1006
+ and time_spacing instead.
720
1007
 
721
1008
  Returns:
722
- Label: The new label.
1009
+ Label: The new derived label.
723
1010
 
724
1011
  """
725
1012
  if ref_image is None:
@@ -728,13 +1015,21 @@ class OmeZarrContainer:
728
1015
  name=name,
729
1016
  ref_image=ref_image,
730
1017
  shape=shape,
731
- pixel_size=pixel_size,
732
- axes_names=axes_names,
1018
+ pixelsize=pixelsize,
1019
+ z_spacing=z_spacing,
1020
+ time_spacing=time_spacing,
1021
+ translation=translation,
1022
+ channels_policy=channels_policy,
1023
+ ngff_version=ngff_version,
733
1024
  chunks=chunks,
1025
+ shards=shards,
734
1026
  dtype=dtype,
735
1027
  dimension_separator=dimension_separator,
736
- compressor=compressor,
1028
+ compressors=compressors,
1029
+ extra_array_kwargs=extra_array_kwargs,
737
1030
  overwrite=overwrite,
1031
+ labels=labels,
1032
+ pixel_size=pixel_size,
738
1033
  )
739
1034
 
740
1035
 
@@ -742,6 +1037,7 @@ def open_ome_zarr_container(
742
1037
  store: StoreOrGroup,
743
1038
  cache: bool = False,
744
1039
  mode: AccessModeLiteral = "r+",
1040
+ axes_setup: AxesSetup | None = None,
745
1041
  validate_arrays: bool = True,
746
1042
  ) -> OmeZarrContainer:
747
1043
  """Open an OME-Zarr image."""
@@ -749,6 +1045,7 @@ def open_ome_zarr_container(
749
1045
  return OmeZarrContainer(
750
1046
  group_handler=handler,
751
1047
  validate_paths=validate_arrays,
1048
+ axes_setup=axes_setup,
752
1049
  )
753
1050
 
754
1051
 
@@ -757,6 +1054,7 @@ def open_image(
757
1054
  path: str | None = None,
758
1055
  pixel_size: PixelSize | None = None,
759
1056
  strict: bool = True,
1057
+ axes_setup: AxesSetup | None = None,
760
1058
  cache: bool = False,
761
1059
  mode: AccessModeLiteral = "r+",
762
1060
  ) -> Image:
@@ -769,12 +1067,14 @@ def open_image(
769
1067
  strict (bool): Only used if the pixel size is provided. If True, the
770
1068
  pixel size must match the image pixel size exactly. If False, the
771
1069
  closest pixel size level will be returned.
1070
+ axes_setup (AxesSetup | None): Axes setup to load ome-zarr with
1071
+ non-standard axes configurations.
772
1072
  cache (bool): Whether to use a cache for the zarr group metadata.
773
1073
  mode (AccessModeLiteral): The
774
1074
  access mode for the image. Defaults to "r+".
775
1075
  """
776
- group_handler = ZarrGroupHandler(store, cache, mode)
777
- images_container = ImagesContainer(group_handler)
1076
+ group_handler = ZarrGroupHandler(store=store, cache=cache, mode=mode)
1077
+ images_container = ImagesContainer(group_handler, axes_setup=axes_setup)
778
1078
  return images_container.get(
779
1079
  path=path,
780
1080
  pixel_size=pixel_size,
@@ -788,6 +1088,7 @@ def open_label(
788
1088
  path: str | None = None,
789
1089
  pixel_size: PixelSize | None = None,
790
1090
  strict: bool = True,
1091
+ axes_setup: AxesSetup | None = None,
791
1092
  cache: bool = False,
792
1093
  mode: AccessModeLiteral = "r+",
793
1094
  ) -> Label:
@@ -802,19 +1103,23 @@ def open_label(
802
1103
  strict (bool): Only used if the pixel size is provided. If True, the
803
1104
  pixel size must match the image pixel size exactly. If False, the
804
1105
  closest pixel size level will be returned.
1106
+ axes_setup (AxesSetup | None): Axes setup to load ome-zarr with
1107
+ non-standard axes configurations.
805
1108
  cache (bool): Whether to use a cache for the zarr group metadata.
806
1109
  mode (AccessModeLiteral): The access mode for the image. Defaults to "r+".
807
1110
 
808
1111
  """
809
- group_handler = ZarrGroupHandler(store, cache, mode)
1112
+ group_handler = ZarrGroupHandler(store=store, cache=cache, mode=mode)
810
1113
  if name is None:
811
- label_meta_handler = find_label_meta_handler(group_handler)
812
- path = label_meta_handler.meta.get_dataset(
813
- path=path, pixel_size=pixel_size, strict=strict
814
- ).path
1114
+ label_meta_handler = LabelMetaHandler(group_handler, axes_setup=axes_setup)
1115
+ path = (
1116
+ label_meta_handler.get_meta()
1117
+ .get_dataset(path=path, pixel_size=pixel_size, strict=strict)
1118
+ .path
1119
+ )
815
1120
  return Label(group_handler, path, label_meta_handler)
816
1121
 
817
- labels_container = LabelsContainer(group_handler)
1122
+ labels_container = LabelsContainer(group_handler, axes_setup=axes_setup)
818
1123
  return labels_container.get(
819
1124
  name=name,
820
1125
  path=path,
@@ -826,196 +1131,294 @@ def open_label(
826
1131
  def create_empty_ome_zarr(
827
1132
  store: StoreOrGroup,
828
1133
  shape: Sequence[int],
829
- xy_pixelsize: float,
1134
+ pixelsize: float | tuple[float, float] | None = None,
830
1135
  z_spacing: float = 1.0,
831
1136
  time_spacing: float = 1.0,
1137
+ scaling_factors: Sequence[float] | Literal["auto"] = "auto",
832
1138
  levels: int | list[str] = 5,
833
- xy_scaling_factor: float = 2,
834
- z_scaling_factor: float = 1.0,
1139
+ translation: Sequence[float] | None = None,
835
1140
  space_unit: SpaceUnits = DefaultSpaceUnit,
836
1141
  time_unit: TimeUnits = DefaultTimeUnit,
837
1142
  axes_names: Sequence[str] | None = None,
1143
+ channels_meta: Sequence[str | Channel] | None = None,
838
1144
  name: str | None = None,
839
- chunks: Sequence[int] | None = None,
1145
+ axes_setup: AxesSetup | None = None,
1146
+ ngff_version: NgffVersions = DefaultNgffVersion,
1147
+ chunks: ChunksLike = "auto",
1148
+ shards: ShardsLike | None = None,
840
1149
  dtype: str = "uint16",
841
- dimension_separator: DIMENSION_SEPARATOR = "/",
842
- compressor="default",
1150
+ dimension_separator: Literal[".", "/"] = "/",
1151
+ compressors: CompressorLike = "auto",
1152
+ extra_array_kwargs: Mapping[str, Any] | None = None,
1153
+ overwrite: bool = False,
1154
+ # Deprecated arguments
1155
+ xy_pixelsize: float | None = None,
1156
+ xy_scaling_factor: float | None = None,
1157
+ z_scaling_factor: float | None = None,
843
1158
  channel_labels: list[str] | None = None,
844
1159
  channel_wavelengths: list[str] | None = None,
845
1160
  channel_colors: Sequence[str] | None = None,
846
1161
  channel_active: Sequence[bool] | None = None,
847
- overwrite: bool = False,
848
- version: NgffVersions = DefaultNgffVersion,
849
1162
  ) -> OmeZarrContainer:
850
1163
  """Create an empty OME-Zarr image with the given shape and metadata.
851
1164
 
852
1165
  Args:
853
1166
  store (StoreOrGroup): The Zarr store or group to create the image in.
854
1167
  shape (Sequence[int]): The shape of the image.
855
- xy_pixelsize (float): The pixel size in x and y dimensions.
856
- z_spacing (float, optional): The spacing between z slices. Defaults to 1.0.
857
- time_spacing (float, optional): The spacing between time points.
858
- Defaults to 1.0.
859
- levels (int | list[str], optional): The number of levels in the pyramid or a
860
- list of level names. Defaults to 5.
861
- xy_scaling_factor (float, optional): The down-scaling factor in x and y
862
- dimensions. Defaults to 2.0.
863
- z_scaling_factor (float, optional): The down-scaling factor in z dimension.
864
- Defaults to 1.0.
865
- space_unit (SpaceUnits, optional): The unit of space. Defaults to
866
- DefaultSpaceUnit.
867
- time_unit (TimeUnits, optional): The unit of time. Defaults to
868
- DefaultTimeUnit.
869
- axes_names (Sequence[str] | None, optional): The names of the axes.
870
- If None the canonical names are used. Defaults to None.
871
- name (str | None, optional): The name of the image. Defaults to None.
872
- chunks (Sequence[int] | None, optional): The chunk shape. If None the shape
873
- is used. Defaults to None.
874
- dtype (str, optional): The data type of the image. Defaults to "uint16".
875
- dimension_separator (DIMENSION_SEPARATOR): The dimension
876
- separator to use. Defaults to "/".
877
- compressor: The compressor to use. Defaults to "default".
878
- channel_labels (list[str] | None, optional): The labels of the channels.
1168
+ pixelsize (float | tuple[float, float] | None): The pixel size in x and y
1169
+ dimensions.
1170
+ z_spacing (float): The spacing between z slices. Defaults to 1.0.
1171
+ time_spacing (float): The spacing between time points. Defaults to 1.0.
1172
+ scaling_factors (Sequence[float] | Literal["auto"]): The down-scaling factors
1173
+ for the pyramid levels. Defaults to "auto".
1174
+ levels (int | list[str]): The number of levels in the pyramid or a list of
1175
+ level names. Defaults to 5.
1176
+ translation (Sequence[float] | None): The translation for each axis.
1177
+ at the highest resolution level. Defaults to None.
1178
+ space_unit (SpaceUnits): The unit of space. Defaults to DefaultSpaceUnit.
1179
+ time_unit (TimeUnits): The unit of time. Defaults to DefaultTimeUnit.
1180
+ axes_names (Sequence[str] | None): The names of the axes. If None the
1181
+ canonical names are used. Defaults to None.
1182
+ channels_meta (Sequence[str | Channel] | None): The channels metadata.
879
1183
  Defaults to None.
880
- channel_wavelengths (list[str] | None, optional): The wavelengths of the
881
- channels. Defaults to None.
882
- channel_colors (Sequence[str] | None, optional): The colors of the channels.
883
- Defaults to None.
884
- channel_active (Sequence[bool] | None, optional): Whether the channels are
885
- active. Defaults to None.
886
- overwrite (bool, optional): Whether to overwrite an existing image.
887
- Defaults to True.
888
- version (NgffVersion, optional): The version of the OME-Zarr specification.
1184
+ name (str | None): The name of the image. Defaults to None.
1185
+ axes_setup (AxesSetup | None): Axes setup to create ome-zarr with
1186
+ non-standard axes configurations. Defaults to None.
1187
+ ngff_version (NgffVersions): The version of the OME-Zarr specification.
889
1188
  Defaults to DefaultNgffVersion.
1189
+ chunks (ChunksLike): The chunk shape. Defaults to "auto".
1190
+ shards (ShardsLike | None): The shard shape. Defaults to None.
1191
+ dtype (str): The data type of the image. Defaults to "uint16".
1192
+ dimension_separator (Literal[".", "/"]): The dimension separator to use.
1193
+ Defaults to "/".
1194
+ compressors (CompressorLike): The compressor to use. Defaults to "auto".
1195
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
1196
+ the zarr array creation. Defaults to None.
1197
+ overwrite (bool): Whether to overwrite an existing image. Defaults to False.
1198
+ xy_pixelsize (float | None): Deprecated. Use pixelsize instead.
1199
+ xy_scaling_factor (float | None): Deprecated. Use scaling_factors instead.
1200
+ z_scaling_factor (float | None): Deprecated. Use scaling_factors instead.
1201
+ channel_labels (list[str] | None): Deprecated. Use channels_meta instead.
1202
+ channel_wavelengths (list[str] | None): Deprecated. Use channels_meta instead.
1203
+ channel_colors (Sequence[str] | None): Deprecated. Use channels_meta instead.
1204
+ channel_active (Sequence[bool] | None): Deprecated. Use channels_meta instead.
890
1205
  """
891
- handler = create_empty_image_container(
1206
+ if xy_pixelsize is not None:
1207
+ warnings.warn(
1208
+ "'xy_pixelsize' is deprecated and will be removed in ngio=0.6. "
1209
+ "Please use 'pixelsize' instead.",
1210
+ DeprecationWarning,
1211
+ stacklevel=2,
1212
+ )
1213
+ pixelsize = xy_pixelsize
1214
+ if xy_scaling_factor is not None or z_scaling_factor is not None:
1215
+ warnings.warn(
1216
+ "'xy_scaling_factor' and 'z_scaling_factor' are deprecated and will be "
1217
+ "removed in ngio=0.6. Please use 'scaling_factors' instead.",
1218
+ DeprecationWarning,
1219
+ stacklevel=2,
1220
+ )
1221
+ xy_scaling_factor_ = xy_scaling_factor or 2.0
1222
+ z_scaling_factor_ = z_scaling_factor or 1.0
1223
+ if len(shape) == 2:
1224
+ scaling_factors = (xy_scaling_factor_, xy_scaling_factor_)
1225
+ else:
1226
+ zyx_factors = (z_scaling_factor_, xy_scaling_factor_, xy_scaling_factor_)
1227
+ scaling_factors = (1.0,) * (len(shape) - 3) + zyx_factors
1228
+
1229
+ if channel_labels is not None:
1230
+ warnings.warn(
1231
+ "'channel_labels' is deprecated and will be removed in ngio=0.6. "
1232
+ "Please use 'channels_meta' instead.",
1233
+ DeprecationWarning,
1234
+ stacklevel=2,
1235
+ )
1236
+ channels_meta = channel_labels
1237
+
1238
+ if channel_wavelengths is not None:
1239
+ warnings.warn(
1240
+ "'channel_wavelengths' is deprecated and will be removed in ngio=0.6. "
1241
+ "Please use 'channels_meta' instead.",
1242
+ DeprecationWarning,
1243
+ stacklevel=2,
1244
+ )
1245
+ if channel_colors is not None:
1246
+ warnings.warn(
1247
+ "'channel_colors' is deprecated and will be removed in ngio=0.6. "
1248
+ "Please use 'channels_meta' instead.",
1249
+ DeprecationWarning,
1250
+ stacklevel=2,
1251
+ )
1252
+ if channel_active is not None:
1253
+ warnings.warn(
1254
+ "'channel_active' is deprecated and will be removed in ngio=0.6. "
1255
+ "Please use 'channels_meta' instead.",
1256
+ DeprecationWarning,
1257
+ stacklevel=2,
1258
+ )
1259
+
1260
+ if pixelsize is None:
1261
+ raise NgioValueError("pixelsize must be provided.")
1262
+
1263
+ handler, axes_setup = init_image_like(
892
1264
  store=store,
1265
+ meta_type=NgioImageMeta,
893
1266
  shape=shape,
894
- pixelsize=xy_pixelsize,
1267
+ pixelsize=pixelsize,
895
1268
  z_spacing=z_spacing,
896
1269
  time_spacing=time_spacing,
1270
+ scaling_factors=scaling_factors,
897
1271
  levels=levels,
898
- yx_scaling_factor=xy_scaling_factor,
899
- z_scaling_factor=z_scaling_factor,
1272
+ translation=translation,
900
1273
  space_unit=space_unit,
901
1274
  time_unit=time_unit,
902
1275
  axes_names=axes_names,
1276
+ channels_meta=channels_meta,
903
1277
  name=name,
1278
+ axes_setup=axes_setup,
1279
+ ngff_version=ngff_version,
904
1280
  chunks=chunks,
1281
+ shards=shards,
905
1282
  dtype=dtype,
906
1283
  dimension_separator=dimension_separator,
907
- compressor=compressor,
1284
+ compressors=compressors,
1285
+ extra_array_kwargs=extra_array_kwargs,
908
1286
  overwrite=overwrite,
909
- version=version,
910
1287
  )
911
1288
 
912
- ome_zarr = OmeZarrContainer(group_handler=handler)
913
- ome_zarr.set_channel_meta(
914
- labels=channel_labels,
915
- wavelength_id=channel_wavelengths,
916
- percentiles=None,
917
- colors=channel_colors,
918
- active=channel_active,
919
- )
1289
+ ome_zarr = OmeZarrContainer(group_handler=handler, axes_setup=axes_setup)
1290
+ if (
1291
+ channel_wavelengths is not None
1292
+ or channel_colors is not None
1293
+ or channel_active is not None
1294
+ ):
1295
+ channel_names = ome_zarr.channel_labels
1296
+ ome_zarr.set_channel_meta(
1297
+ labels=channel_names,
1298
+ wavelength_id=channel_wavelengths,
1299
+ percentiles=None,
1300
+ colors=channel_colors,
1301
+ active=channel_active,
1302
+ )
1303
+ else:
1304
+ ome_zarr.set_channel_meta(
1305
+ labels=ome_zarr.channel_labels,
1306
+ percentiles=None,
1307
+ )
920
1308
  return ome_zarr
921
1309
 
922
1310
 
923
1311
  def create_ome_zarr_from_array(
924
1312
  store: StoreOrGroup,
925
1313
  array: np.ndarray,
926
- xy_pixelsize: float,
1314
+ pixelsize: float | tuple[float, float] | None = None,
927
1315
  z_spacing: float = 1.0,
928
1316
  time_spacing: float = 1.0,
1317
+ scaling_factors: Sequence[float] | Literal["auto"] = "auto",
929
1318
  levels: int | list[str] = 5,
930
- xy_scaling_factor: float = 2.0,
931
- z_scaling_factor: float = 1.0,
1319
+ translation: Sequence[float] | None = None,
932
1320
  space_unit: SpaceUnits = DefaultSpaceUnit,
933
1321
  time_unit: TimeUnits = DefaultTimeUnit,
934
1322
  axes_names: Sequence[str] | None = None,
1323
+ channels_meta: Sequence[str | Channel] | None = None,
1324
+ percentiles: tuple[float, float] = (0.1, 99.9),
1325
+ name: str | None = None,
1326
+ axes_setup: AxesSetup | None = None,
1327
+ ngff_version: NgffVersions = DefaultNgffVersion,
1328
+ chunks: ChunksLike = "auto",
1329
+ shards: ShardsLike | None = None,
1330
+ dimension_separator: Literal[".", "/"] = "/",
1331
+ compressors: CompressorLike = "auto",
1332
+ extra_array_kwargs: Mapping[str, Any] | None = None,
1333
+ overwrite: bool = False,
1334
+ # Deprecated arguments
1335
+ xy_pixelsize: float | None = None,
1336
+ xy_scaling_factor: float | None = None,
1337
+ z_scaling_factor: float | None = None,
935
1338
  channel_labels: list[str] | None = None,
936
1339
  channel_wavelengths: list[str] | None = None,
937
- percentiles: tuple[float, float] | None = (0.1, 99.9),
938
1340
  channel_colors: Sequence[str] | None = None,
939
1341
  channel_active: Sequence[bool] | None = None,
940
- name: str | None = None,
941
- chunks: Sequence[int] | None = None,
942
- dimension_separator: DIMENSION_SEPARATOR = "/",
943
- compressor: str = "default",
944
- overwrite: bool = False,
945
- version: NgffVersions = DefaultNgffVersion,
946
1342
  ) -> OmeZarrContainer:
947
1343
  """Create an OME-Zarr image from a numpy array.
948
1344
 
949
1345
  Args:
950
1346
  store (StoreOrGroup): The Zarr store or group to create the image in.
951
1347
  array (np.ndarray): The image data.
952
- xy_pixelsize (float): The pixel size in x and y dimensions.
953
- z_spacing (float, optional): The spacing between z slices. Defaults to 1.0.
954
- time_spacing (float, optional): The spacing between time points.
955
- Defaults to 1.0.
956
- levels (int | list[str], optional): The number of levels in the pyramid or a
957
- list of level names. Defaults to 5.
958
- xy_scaling_factor (float, optional): The down-scaling factor in x and y
959
- dimensions. Defaults to 2.0.
960
- z_scaling_factor (float, optional): The down-scaling factor in z dimension.
961
- Defaults to 1.0.
962
- space_unit (SpaceUnits, optional): The unit of space. Defaults to
963
- DefaultSpaceUnit.
964
- time_unit (TimeUnits, optional): The unit of time. Defaults to
965
- DefaultTimeUnit.
966
- axes_names (Sequence[str] | None, optional): The names of the axes.
967
- If None the canonical names are used. Defaults to None.
968
- name (str | None, optional): The name of the image. Defaults to None.
969
- chunks (Sequence[int] | None, optional): The chunk shape. If None the shape
970
- is used. Defaults to None.
971
- channel_labels (list[str] | None, optional): The labels of the channels.
1348
+ pixelsize (float | tuple[float, float] | None): The pixel size in x and y
1349
+ dimensions.
1350
+ z_spacing (float): The spacing between z slices. Defaults to 1.0.
1351
+ time_spacing (float): The spacing between time points. Defaults to 1.0.
1352
+ scaling_factors (Sequence[float] | Literal["auto"]): The down-scaling factors
1353
+ for the pyramid levels. Defaults to "auto".
1354
+ levels (int | list[str]): The number of levels in the pyramid or a list of
1355
+ level names. Defaults to 5.
1356
+ translation (Sequence[float] | None): The translation for each axis.
1357
+ at the highest resolution level. Defaults to None.
1358
+ space_unit (SpaceUnits): The unit of space. Defaults to DefaultSpaceUnit.
1359
+ time_unit (TimeUnits): The unit of time. Defaults to DefaultTimeUnit.
1360
+ axes_names (Sequence[str] | None): The names of the axes. If None the
1361
+ canonical names are used. Defaults to None.
1362
+ channels_meta (Sequence[str | Channel] | None): The channels metadata.
972
1363
  Defaults to None.
973
- channel_wavelengths (list[str] | None, optional): The wavelengths of the
974
- channels. Defaults to None.
975
- percentiles (tuple[float, float] | None, optional): The percentiles of the
976
- channels. Defaults to None.
977
- channel_colors (Sequence[str] | None, optional): The colors of the channels.
978
- Defaults to None.
979
- channel_active (Sequence[bool] | None, optional): Whether the channels are
980
- active. Defaults to None.
981
- dimension_separator (DIMENSION_SEPARATOR): The separator to use for
982
- dimensions. Defaults to "/".
983
- compressor: The compressor to use. Defaults to "default".
984
- overwrite (bool, optional): Whether to overwrite an existing image.
985
- Defaults to True.
986
- version (str, optional): The version of the OME-Zarr specification.
1364
+ percentiles (tuple[float, float]): The percentiles of the channels for
1365
+ computing display ranges. Defaults to (0.1, 99.9).
1366
+ name (str | None): The name of the image. Defaults to None.
1367
+ axes_setup (AxesSetup | None): Axes setup to create ome-zarr with
1368
+ non-standard axes configurations. Defaults to None.
1369
+ ngff_version (NgffVersions): The version of the OME-Zarr specification.
987
1370
  Defaults to DefaultNgffVersion.
1371
+ chunks (ChunksLike): The chunk shape. Defaults to "auto".
1372
+ shards (ShardsLike | None): The shard shape. Defaults to None.
1373
+ dimension_separator (Literal[".", "/"]): The separator to use for
1374
+ dimensions. Defaults to "/".
1375
+ compressors (CompressorLike): The compressors to use. Defaults to "auto".
1376
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
1377
+ the zarr array creation. Defaults to None.
1378
+ overwrite (bool): Whether to overwrite an existing image. Defaults to False.
1379
+ xy_pixelsize (float | None): Deprecated. Use pixelsize instead.
1380
+ xy_scaling_factor (float | None): Deprecated. Use scaling_factors instead.
1381
+ z_scaling_factor (float | None): Deprecated. Use scaling_factors instead.
1382
+ channel_labels (list[str] | None): Deprecated. Use channels_meta instead.
1383
+ channel_wavelengths (list[str] | None): Deprecated. Use channels_meta instead.
1384
+ channel_colors (Sequence[str] | None): Deprecated. Use channels_meta instead.
1385
+ channel_active (Sequence[bool] | None): Deprecated. Use channels_meta instead.
988
1386
  """
989
- handler = create_empty_image_container(
1387
+ ome_zarr = create_empty_ome_zarr(
990
1388
  store=store,
991
1389
  shape=array.shape,
992
- pixelsize=xy_pixelsize,
1390
+ pixelsize=pixelsize,
993
1391
  z_spacing=z_spacing,
994
1392
  time_spacing=time_spacing,
1393
+ scaling_factors=scaling_factors,
995
1394
  levels=levels,
996
- yx_scaling_factor=xy_scaling_factor,
997
- z_scaling_factor=z_scaling_factor,
1395
+ translation=translation,
998
1396
  space_unit=space_unit,
999
1397
  time_unit=time_unit,
1000
1398
  axes_names=axes_names,
1399
+ channels_meta=channels_meta,
1001
1400
  name=name,
1401
+ ngff_version=ngff_version,
1002
1402
  chunks=chunks,
1003
- dtype=str(array.dtype),
1004
- overwrite=overwrite,
1403
+ shards=shards,
1005
1404
  dimension_separator=dimension_separator,
1006
- compressor=compressor,
1007
- version=version,
1405
+ compressors=compressors,
1406
+ extra_array_kwargs=extra_array_kwargs,
1407
+ overwrite=overwrite,
1408
+ xy_pixelsize=xy_pixelsize,
1409
+ xy_scaling_factor=xy_scaling_factor,
1410
+ z_scaling_factor=z_scaling_factor,
1411
+ channel_labels=channel_labels,
1412
+ channel_wavelengths=channel_wavelengths,
1413
+ channel_colors=channel_colors,
1414
+ channel_active=channel_active,
1008
1415
  )
1009
-
1010
- ome_zarr = OmeZarrContainer(group_handler=handler)
1011
1416
  image = ome_zarr.get_image()
1012
1417
  image.set_array(array)
1013
1418
  image.consolidate()
1014
- ome_zarr.set_channel_meta(
1015
- labels=channel_labels,
1016
- wavelength_id=channel_wavelengths,
1017
- percentiles=percentiles,
1018
- colors=channel_colors,
1019
- active=channel_active,
1020
- )
1419
+ if len(percentiles) != 2:
1420
+ raise NgioValueError(
1421
+ f"'percentiles' must be a tuple of two values. Got {percentiles}"
1422
+ )
1423
+ ome_zarr.set_channel_windows_with_percentiles(percentiles=percentiles)
1021
1424
  return ome_zarr