ngio 0.5.0b6__py3-none-any.whl → 0.5.1__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.
@@ -1,6 +1,6 @@
1
1
  """HCS (High Content Screening) specific metadata classes for NGIO."""
2
2
 
3
- import warnings
3
+ import logging
4
4
  from typing import Annotated
5
5
 
6
6
  from ome_zarr_models.common.plate import (
@@ -16,16 +16,17 @@ from pydantic import BaseModel, SkipValidation, field_serializer
16
16
  from ngio.ome_zarr_meta.ngio_specs._ngio_image import DefaultNgffVersion, NgffVersions
17
17
  from ngio.utils import NgioValueError
18
18
 
19
+ logger = logging.getLogger(f"ngio:{__name__}")
20
+
19
21
 
20
22
  def path_in_well_validation(path: str) -> str:
21
23
  """Validate the path in the well."""
22
24
  # Check if the value contains only alphanumeric characters
23
25
  if not path.isalnum():
24
- warnings.warn(
26
+ logger.warning(
25
27
  f"Path '{path}' contains non-alphanumeric characters. "
26
28
  "This may cause issues with some tools. "
27
- "Consider using only alphanumeric characters in the path.",
28
- stacklevel=2,
29
+ "Consider using only alphanumeric characters in the path."
29
30
  )
30
31
  return path
31
32
 
@@ -147,23 +148,58 @@ class NgioWellMeta(BaseModel):
147
148
  raise NgioValueError(f"Image at path {path} not found in the well.")
148
149
 
149
150
 
150
- def _stringify_column(column: str | int) -> str:
151
+ def _format_int_column(column: int, num_digits: int = 2) -> str:
152
+ """Format the column as a string.
153
+
154
+ We make sure to pad the column with zeros
155
+ to have a consistent format.
156
+
157
+ Args:
158
+ column (int): The column to format.
159
+ num_digits (int): The number of digits to pad the column.
160
+
161
+ Returns:
162
+ str: The column as a string.
163
+ """
164
+ return f"{column:0{num_digits}d}"
165
+
166
+
167
+ def _stringify_column(column: str | int, num_digits: int = 2) -> str:
151
168
  """Convert the column to a string.
152
169
 
170
+ This will ensure that columns are always strings.
171
+ and will help with sorting and comparison.
172
+
153
173
  Args:
154
174
  column (str | int): The column to convert.
175
+ num_digits (int): The number of digits to pad the column.
155
176
 
156
177
  Returns:
157
178
  str: The column as a string.
158
179
  """
159
- if isinstance(column, str):
160
- return column
180
+ if isinstance(column, int):
181
+ return _format_int_column(column, num_digits=num_digits)
161
182
 
162
- # Maybe we should pad the column with zeros
163
- return str(column)
183
+ elif isinstance(column, str):
184
+ try:
185
+ column_int = int(column)
186
+ return _format_int_column(column_int, num_digits=num_digits)
187
+ except ValueError:
188
+ pass
189
+ return column
190
+ raise NgioValueError(f"Column {column} must be a string or an integer.")
164
191
 
165
192
 
166
193
  def _find_row_index(rows: list[str], row: str) -> int | None:
194
+ """Find the index of a row in the list of rows.
195
+
196
+ Args:
197
+ rows: List of row names.
198
+ row: The row name to find.
199
+
200
+ Returns:
201
+ The index of the row, or None if not found.
202
+ """
167
203
  try:
168
204
  return rows.index(row)
169
205
  except ValueError:
@@ -171,8 +207,17 @@ def _find_row_index(rows: list[str], row: str) -> int | None:
171
207
 
172
208
 
173
209
  def _find_column_index(columns: list[str], column: str | int) -> int | None:
174
- _num_columns = [int(columns) for columns in columns]
175
- column = int(column)
210
+ """Find the index of a column in the list of columns.
211
+
212
+ Args:
213
+ columns: List of column names.
214
+ column: The column name or number to find.
215
+
216
+ Returns:
217
+ The index of the column, or None if not found.
218
+ """
219
+ _num_columns = [_stringify_column(columns) for columns in columns]
220
+ column = _stringify_column(column)
176
221
  try:
177
222
  return _num_columns.index(column)
178
223
  except ValueError:
@@ -182,6 +227,16 @@ def _find_column_index(columns: list[str], column: str | int) -> int | None:
182
227
  def _relabel_wells(
183
228
  wells: list[WellInPlate], rows: list[Row], columns: list[Column]
184
229
  ) -> list[WellInPlate]:
230
+ """Relabel well indices after rows or columns have been added.
231
+
232
+ Args:
233
+ wells: List of wells to relabel.
234
+ rows: Updated list of rows.
235
+ columns: Updated list of columns.
236
+
237
+ Returns:
238
+ List of wells with updated row and column indices.
239
+ """
185
240
  new_wells = []
186
241
  _rows = [row.name for row in rows]
187
242
  _columns = [column.name for column in columns]
@@ -286,23 +341,8 @@ class NgioPlateMeta(BaseModel):
286
341
  Returns:
287
342
  str: The path of the well.
288
343
  """
289
- if row not in self.rows:
290
- raise NgioValueError(
291
- f"Row {row} not found in the plate. Available rows are {self.rows}."
292
- )
293
-
294
- row_idx = self.rows.index(row)
295
-
296
- _num_columns = [int(columns) for columns in self.columns]
297
-
298
- try:
299
- _column = int(column)
300
- except ValueError:
301
- raise NgioValueError(
302
- f"Column {column} must be an integer or convertible to an integer."
303
- ) from None
304
-
305
- column_idx = _num_columns.index(_column)
344
+ row_idx = _find_row_index(self.rows, row)
345
+ column_idx = _find_column_index(self.columns, column)
306
346
 
307
347
  for well in self.plate.wells:
308
348
  if well.columnIndex == column_idx and well.rowIndex == row_idx:
@@ -365,7 +405,7 @@ class NgioPlateMeta(BaseModel):
365
405
 
366
406
  columns_names.append(_stringify_column(column))
367
407
  # sort as numbers
368
- columns_names.sort(key=lambda x: int(x))
408
+ columns_names.sort(key=lambda x: _stringify_column(x))
369
409
  column_idx = columns_names.index(_stringify_column(column))
370
410
  relabel_wells = True
371
411
 
@@ -392,11 +432,14 @@ class NgioPlateMeta(BaseModel):
392
432
  row: str,
393
433
  column: str | int,
394
434
  ) -> "NgioPlateMeta":
395
- """Add an image to the well.
435
+ """Add a well to the plate.
396
436
 
397
437
  Args:
398
438
  row (str): The row of the well.
399
439
  column (str | int): The column of the well.
440
+
441
+ Returns:
442
+ NgioPlateMeta: Updated plate metadata with the new well.
400
443
  """
401
444
  plate, row_idx = self.add_row(row=row)
402
445
  plate, column_idx = plate.add_column(column=column)
@@ -509,10 +552,13 @@ class NgioPlateMeta(BaseModel):
509
552
  """Derive the plate metadata.
510
553
 
511
554
  Args:
512
- name (str): The name of the derived plate.
513
- ngff_version (NgffVersion | None): The version of the derived plate.
555
+ name (str | None): The name of the derived plate.
556
+ ngff_version (NgffVersions | None): The version of the derived plate.
514
557
  If None, use the version of the original plate.
515
558
  keep_acquisitions (bool): If True, keep the acquisitions in the plate.
559
+
560
+ Returns:
561
+ NgioPlateMeta: The derived plate metadata.
516
562
  """
517
563
  columns = self.plate.columns
518
564
  rows = self.plate.rows
@@ -129,6 +129,42 @@ class AbstractNgioImageMeta:
129
129
  datasets=new_datasets,
130
130
  )
131
131
 
132
+ def rename_axes(self, axes_names: Sequence[str]):
133
+ """Rename axes in the metadata.
134
+
135
+ Args:
136
+ axes_names(Sequence[str]): The new axes names in the order of the current
137
+ axes.
138
+ """
139
+ new_axes_handler = self.axes_handler.rename_axes(axes_names=axes_names)
140
+ new_datasets = []
141
+ for dataset in self.datasets:
142
+ new_dataset = Dataset(
143
+ path=dataset.path,
144
+ axes_handler=new_axes_handler,
145
+ scale=dataset.scale,
146
+ translation=dataset.translation,
147
+ )
148
+ new_datasets.append(new_dataset)
149
+
150
+ return type(self)(
151
+ version=self.version,
152
+ name=self.name,
153
+ datasets=new_datasets,
154
+ )
155
+
156
+ def rename_image(self, name: str):
157
+ """Rename the image in the metadata.
158
+
159
+ Args:
160
+ name(str): The new name of the image.
161
+ """
162
+ return type(self)(
163
+ version=self.version,
164
+ name=name,
165
+ datasets=self.datasets,
166
+ )
167
+
132
168
  @property
133
169
  def version(self) -> NgffVersions:
134
170
  """Version of the OME-NFF metadata used to build the object."""
@@ -9,6 +9,9 @@ For Images and Labels implements the following functionalities:
9
9
  - A function to convert a ngio image metadata to a v04 image metadata.
10
10
  """
11
11
 
12
+ from ome_zarr_models.common.coordinate_transformations import (
13
+ ValidTransform as ValidTransformV04,
14
+ )
12
15
  from ome_zarr_models.v04.axes import Axis as AxisV04
13
16
  from ome_zarr_models.v04.coordinate_transformations import VectorScale as VectorScaleV04
14
17
  from ome_zarr_models.v04.coordinate_transformations import (
@@ -20,7 +23,6 @@ from ome_zarr_models.v04.image_label import ImageLabelAttrs as ImageLabelAttrsV0
20
23
  from ome_zarr_models.v04.labels import LabelsAttrs as LabelsAttrsV04
21
24
  from ome_zarr_models.v04.multiscales import Dataset as DatasetV04
22
25
  from ome_zarr_models.v04.multiscales import Multiscale as MultiscaleV04
23
- from ome_zarr_models.v04.multiscales import ValidTransform as ValidTransformV04
24
26
  from ome_zarr_models.v04.omero import Channel as ChannelV04
25
27
  from ome_zarr_models.v04.omero import Omero as OmeroV04
26
28
  from ome_zarr_models.v04.omero import Window as WindowV04
@@ -117,8 +119,6 @@ def _compute_scale_translation(
117
119
  def _v04_to_ngio_datasets(
118
120
  v04_multiscale: MultiscaleV04,
119
121
  axes_setup: AxesSetup,
120
- allow_non_canonical_axes: bool = False,
121
- strict_canonical_order: bool = True,
122
122
  ) -> list[Dataset]:
123
123
  """Convert a v04 multiscale to a list of ngio datasets."""
124
124
  datasets = []
@@ -149,8 +149,6 @@ def _v04_to_ngio_datasets(
149
149
  axes_handler = AxesHandler(
150
150
  axes=axes,
151
151
  axes_setup=axes_setup,
152
- allow_non_canonical_axes=allow_non_canonical_axes,
153
- strict_canonical_order=strict_canonical_order,
154
152
  )
155
153
 
156
154
  for v04_dataset in v04_multiscale.datasets:
@@ -170,9 +168,7 @@ def _v04_to_ngio_datasets(
170
168
 
171
169
  def v04_to_ngio_image_meta(
172
170
  metadata: dict,
173
- axes_setup: AxesSetup | None = None,
174
- allow_non_canonical_axes: bool = False,
175
- strict_canonical_order: bool = True,
171
+ axes_setup: AxesSetup,
176
172
  ) -> NgioImageMeta:
177
173
  """Convert a v04 image metadata to a ngio image metadata.
178
174
 
@@ -180,8 +176,6 @@ def v04_to_ngio_image_meta(
180
176
  metadata (dict): The v04 image metadata.
181
177
  axes_setup (AxesSetup, optional): The axes setup. This is
182
178
  required to convert image with non-canonical axes names.
183
- allow_non_canonical_axes (bool, optional): Allow non-canonical axes.
184
- strict_canonical_order (bool, optional): Strict canonical order.
185
179
 
186
180
  Returns:
187
181
  NgioImageMeta: The ngio image metadata.
@@ -196,12 +190,9 @@ def v04_to_ngio_image_meta(
196
190
  v04_muliscale = v04_image.multiscales[0]
197
191
 
198
192
  channels_meta = _v04_omero_to_channels(v04_image.omero)
199
- axes_setup = axes_setup if axes_setup is not None else AxesSetup()
200
193
  datasets = _v04_to_ngio_datasets(
201
194
  v04_muliscale,
202
195
  axes_setup=axes_setup,
203
- allow_non_canonical_axes=allow_non_canonical_axes,
204
- strict_canonical_order=strict_canonical_order,
205
196
  )
206
197
 
207
198
  name = v04_muliscale.name
@@ -217,9 +208,7 @@ def v04_to_ngio_image_meta(
217
208
 
218
209
  def v04_to_ngio_label_meta(
219
210
  metadata: dict,
220
- axes_setup: AxesSetup | None = None,
221
- allow_non_canonical_axes: bool = False,
222
- strict_canonical_order: bool = True,
211
+ axes_setup: AxesSetup,
223
212
  ) -> NgioLabelMeta:
224
213
  """Convert a v04 image metadata to a ngio image metadata.
225
214
 
@@ -227,8 +216,6 @@ def v04_to_ngio_label_meta(
227
216
  metadata (dict): The v04 image metadata.
228
217
  axes_setup (AxesSetup, optional): The axes setup. This is
229
218
  required to convert image with non-canonical axes names.
230
- allow_non_canonical_axes (bool, optional): Allow non-canonical axes.
231
- strict_canonical_order (bool, optional): Strict canonical order.
232
219
 
233
220
  Returns:
234
221
  NgioImageMeta: The ngio image metadata.
@@ -241,13 +228,9 @@ def v04_to_ngio_label_meta(
241
228
  )
242
229
 
243
230
  v04_muliscale = v04_label.multiscales[0]
244
-
245
- axes_setup = axes_setup if axes_setup is not None else AxesSetup()
246
231
  datasets = _v04_to_ngio_datasets(
247
232
  v04_muliscale,
248
233
  axes_setup=axes_setup,
249
- allow_non_canonical_axes=allow_non_canonical_axes,
250
- strict_canonical_order=strict_canonical_order,
251
234
  )
252
235
 
253
236
  source = v04_label.image_label.source
@@ -9,6 +9,9 @@ For Images and Labels implements the following functionalities:
9
9
  - A function to convert a ngio image metadata to a v05 image metadata.
10
10
  """
11
11
 
12
+ from ome_zarr_models.common.coordinate_transformations import (
13
+ ValidTransform as ValidTransformV05,
14
+ )
12
15
  from ome_zarr_models.common.omero import Channel as ChannelV05
13
16
  from ome_zarr_models.common.omero import Omero as OmeroV05
14
17
  from ome_zarr_models.common.omero import Window as WindowV05
@@ -24,7 +27,6 @@ from ome_zarr_models.v05.labels import Labels as Labels
24
27
  from ome_zarr_models.v05.labels import LabelsAttrs as LabelsAttrsV05
25
28
  from ome_zarr_models.v05.multiscales import Dataset as DatasetV05
26
29
  from ome_zarr_models.v05.multiscales import Multiscale as MultiscaleV05
27
- from ome_zarr_models.v05.multiscales import ValidTransform as ValidTransformV05
28
30
  from pydantic import BaseModel
29
31
 
30
32
  from ngio.ome_zarr_meta.ngio_specs import (
@@ -131,8 +133,6 @@ def _compute_scale_translation(
131
133
  def _v05_to_ngio_datasets(
132
134
  v05_multiscale: MultiscaleV05,
133
135
  axes_setup: AxesSetup,
134
- allow_non_canonical_axes: bool = False,
135
- strict_canonical_order: bool = True,
136
136
  ) -> list[Dataset]:
137
137
  """Convert a v05 multiscale to a list of ngio datasets."""
138
138
  datasets = []
@@ -163,8 +163,6 @@ def _v05_to_ngio_datasets(
163
163
  axes_handler = AxesHandler(
164
164
  axes=axes,
165
165
  axes_setup=axes_setup,
166
- allow_non_canonical_axes=allow_non_canonical_axes,
167
- strict_canonical_order=strict_canonical_order,
168
166
  )
169
167
 
170
168
  for v05_dataset in v05_multiscale.datasets:
@@ -184,18 +182,14 @@ def _v05_to_ngio_datasets(
184
182
 
185
183
  def v05_to_ngio_image_meta(
186
184
  metadata: dict,
187
- axes_setup: AxesSetup | None = None,
188
- allow_non_canonical_axes: bool = False,
189
- strict_canonical_order: bool = True,
185
+ axes_setup: AxesSetup,
190
186
  ) -> NgioImageMeta:
191
187
  """Convert a v05 image metadata to a ngio image metadata.
192
188
 
193
189
  Args:
194
190
  metadata (dict): The v05 image metadata.
195
- axes_setup (AxesSetup, optional): The axes setup. This is
191
+ axes_setup (AxesSetup): The axes setup. This is
196
192
  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
193
 
200
194
  Returns:
201
195
  NgioImageMeta: The ngio image metadata.
@@ -210,12 +204,9 @@ def v05_to_ngio_image_meta(
210
204
  v05_multiscale = v05_image.multiscales[0]
211
205
 
212
206
  channels_meta = _v05_omero_to_channels(v05_image.omero)
213
- axes_setup = axes_setup if axes_setup is not None else AxesSetup()
214
207
  datasets = _v05_to_ngio_datasets(
215
208
  v05_multiscale,
216
209
  axes_setup=axes_setup,
217
- allow_non_canonical_axes=allow_non_canonical_axes,
218
- strict_canonical_order=strict_canonical_order,
219
210
  )
220
211
 
221
212
  name = v05_multiscale.name
@@ -231,18 +222,14 @@ def v05_to_ngio_image_meta(
231
222
 
232
223
  def v05_to_ngio_label_meta(
233
224
  metadata: dict,
234
- axes_setup: AxesSetup | None = None,
235
- allow_non_canonical_axes: bool = False,
236
- strict_canonical_order: bool = True,
225
+ axes_setup: AxesSetup,
237
226
  ) -> NgioLabelMeta:
238
227
  """Convert a v05 image metadata to a ngio image metadata.
239
228
 
240
229
  Args:
241
230
  metadata (dict): The v05 image metadata.
242
- axes_setup (AxesSetup, optional): The axes setup. This is
231
+ axes_setup (AxesSetup): The axes setup. This is
243
232
  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
233
 
247
234
  Returns:
248
235
  NgioLabelMeta: The ngio label metadata.
@@ -257,12 +244,9 @@ def v05_to_ngio_label_meta(
257
244
 
258
245
  v05_multiscale = v05_label.multiscales[0]
259
246
 
260
- axes_setup = axes_setup if axes_setup is not None else AxesSetup()
261
247
  datasets = _v05_to_ngio_datasets(
262
248
  v05_multiscale,
263
249
  axes_setup=axes_setup,
264
- allow_non_canonical_axes=allow_non_canonical_axes,
265
- strict_canonical_order=strict_canonical_order,
266
250
  )
267
251
 
268
252
  if v05_label.image_label is not None:
@@ -31,7 +31,7 @@ _resources = {
31
31
  dtype="uint8",
32
32
  ),
33
33
  ],
34
- xy_pixelsize=0.325,
34
+ pixelsize=0.325,
35
35
  z_spacing=1.0,
36
36
  time_spacing=1.0,
37
37
  name="Cardiomyocyte Differentiation",
@@ -27,7 +27,7 @@ class SampleInfo(BaseModel):
27
27
 
28
28
  img_path: Path
29
29
  labels: list[LabelsInfo] = Field(default_factory=list)
30
- xy_pixelsize: float
30
+ pixelsize: float
31
31
  z_spacing: float = 1.0
32
32
  time_spacing: float = 1.0
33
33
  space_unit: SpaceUnits = DefaultSpaceUnit
@@ -229,10 +229,10 @@ class ImplementedTables:
229
229
 
230
230
 
231
231
  class TablesContainer:
232
- """A class to handle the /labels group in an OME-NGFF file."""
232
+ """A class to handle the /tables group in an OME-NGFF file."""
233
233
 
234
234
  def __init__(self, group_handler: ZarrGroupHandler) -> None:
235
- """Initialize the LabelGroupHandler."""
235
+ """Initialize the TablesContainer."""
236
236
  self._group_handler = group_handler
237
237
 
238
238
  # Validate the group
@@ -252,7 +252,7 @@ class TablesContainer:
252
252
  )
253
253
 
254
254
  def _get_tables_list(self) -> list[str]:
255
- """Create the /tables group if it doesn't exist."""
255
+ """Return the list of table names from the group attributes."""
256
256
  attrs = self._group_handler.load_attrs()
257
257
  return attrs.get("tables", [])
258
258
 
@@ -262,7 +262,14 @@ class TablesContainer:
262
262
  return handler
263
263
 
264
264
  def list(self, filter_types: TypedTable | str | None = None) -> list[str]:
265
- """List all labels in the group."""
265
+ """List all tables in the group.
266
+
267
+ Args:
268
+ filter_types: If provided, only return tables of this type.
269
+
270
+ Returns:
271
+ A list of table names.
272
+ """
266
273
  tables = self._get_tables_list()
267
274
  if filter_types is None:
268
275
  return tables
@@ -281,7 +288,16 @@ class TablesContainer:
281
288
  backend: TableBackend | None = None,
282
289
  strict: bool = True,
283
290
  ) -> Table:
284
- """Get a label from the group."""
291
+ """Get a table from the group.
292
+
293
+ Args:
294
+ name: The name of the table.
295
+ backend: The backend to use for reading the table.
296
+ strict: If True, raise an error if the table type is not implemented.
297
+
298
+ Returns:
299
+ The table object.
300
+ """
285
301
  if name not in self.list():
286
302
  raise NgioValueError(f"Table '{name}' not found in the group.")
287
303
 
@@ -301,7 +317,16 @@ class TablesContainer:
301
317
  table_cls: type[TableType],
302
318
  backend: TableBackend | None = None,
303
319
  ) -> TableType:
304
- """Get a table from the group as a specific type."""
320
+ """Get a table from the group as a specific type.
321
+
322
+ Args:
323
+ name: The name of the table.
324
+ table_cls: The table class to use for loading the table.
325
+ backend: The backend to use for reading the table.
326
+
327
+ Returns:
328
+ The table object of the specified type.
329
+ """
305
330
  if name not in self.list():
306
331
  raise NgioValueError(f"Table '{name}' not found in the group.")
307
332
 
@@ -339,7 +364,14 @@ class TablesContainer:
339
364
  backend: TableBackend = DefaultTableBackend,
340
365
  overwrite: bool = False,
341
366
  ) -> None:
342
- """Add a table to the group."""
367
+ """Add a table to the group.
368
+
369
+ Args:
370
+ name: The name of the table.
371
+ table: The table object to add.
372
+ backend: The backend to use for writing the table.
373
+ overwrite: Whether to overwrite an existing table with the same name.
374
+ """
343
375
  existing_tables = self._get_tables_list()
344
376
  if name in existing_tables and not overwrite:
345
377
  raise NgioValueError(
@@ -4,7 +4,7 @@ This class follows the roi_table specification at:
4
4
  https://fractal-analytics-platform.github.io/fractal-tasks-core/tables/
5
5
  """
6
6
 
7
- import warnings
7
+ import logging
8
8
  from collections.abc import Iterable
9
9
  from typing import Literal
10
10
  from uuid import uuid4
@@ -29,6 +29,8 @@ from ngio.utils import (
29
29
  ZarrGroupHandler,
30
30
  )
31
31
 
32
+ logger = logging.getLogger(f"ngio:{__name__}")
33
+
32
34
  REQUIRED_COLUMNS = [
33
35
  "x_micrometer",
34
36
  "y_micrometer",
@@ -77,9 +79,7 @@ OPTIONAL_COLUMNS = ORIGIN_COLUMNS + TRANSLATION_COLUMNS + PLATE_COLUMNS + INDEX_
77
79
  def _check_optional_columns(col_name: str) -> None:
78
80
  """Check if the column name is in the optional columns."""
79
81
  if col_name not in OPTIONAL_COLUMNS + TIME_COLUMNS:
80
- warnings.warn(
81
- f"Column {col_name} is not in the optional columns.", stacklevel=2
82
- )
82
+ logger.warning(f"Column {col_name} is not in the optional columns.")
83
83
 
84
84
 
85
85
  def _dataframe_to_rois(
ngio/utils/_zarr_utils.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Common utilities for working with Zarr groups in consistent ways."""
2
2
 
3
3
  import json
4
- import warnings
4
+ import logging
5
5
  from pathlib import Path
6
6
  from typing import Literal, TypeAlias
7
7
 
@@ -22,6 +22,8 @@ from ngio.utils._errors import (
22
22
  NgioValueError,
23
23
  )
24
24
 
25
+ logger = logging.getLogger(f"ngio:{__name__}")
26
+
25
27
  AccessModeLiteral = Literal["r", "r+", "w", "w-", "a"]
26
28
  # StoreLike is more restrictive than it could be
27
29
  # but to make sure we can handle the store correctly
@@ -36,12 +38,10 @@ StoreOrGroup: TypeAlias = NgioSupportedStore | zarr.Group
36
38
  def _check_store(store) -> NgioSupportedStore:
37
39
  """Check the store and return a valid store."""
38
40
  if not isinstance(store, NgioSupportedStore):
39
- warnings.warn(
41
+ logger.warning(
40
42
  f"Store type {type(store)} is not explicitly supported. "
41
43
  f"Supported types are: {NgioSupportedStore}. "
42
- "Proceeding, but this may lead to unexpected behavior.",
43
- UserWarning,
44
- stacklevel=2,
44
+ "Proceeding, but this may lead to unexpected behavior."
45
45
  )
46
46
  return store
47
47
 
@@ -114,7 +114,6 @@ class ZarrGroupHandler:
114
114
 
115
115
  Args:
116
116
  store (StoreOrGroup): The Zarr store or group containing the image data.
117
- meta_mode (str): The mode of the metadata handler.
118
117
  zarr_format (int | None): The Zarr format version to use.
119
118
  cache (bool): Whether to cache the metadata.
120
119
  mode (str | None): The mode of the store.
@@ -154,11 +153,7 @@ class ZarrGroupHandler:
154
153
  return (self.store.path / self.group.path).as_posix()
155
154
  elif isinstance(self.store, MemoryStore):
156
155
  return None
157
- warnings.warn(
158
- f"Cannot determine full URL for store type {type(self.store)}. ",
159
- UserWarning,
160
- stacklevel=2,
161
- )
156
+ logger.warning(f"Cannot determine full URL for store type {type(self.store)}.")
162
157
  return None
163
158
 
164
159
  @property
@@ -524,11 +519,9 @@ def copy_group(
524
519
  _fsspec_copy(src_group.store, src_group.path, dest_group.store, dest_group.path)
525
520
  return
526
521
  if not suppress_warnings:
527
- warnings.warn(
522
+ logger.warning(
528
523
  "Fsspec copy not possible, falling back to Zarr Python API for the copy. "
529
524
  "This will preserve some tabular data non-zarr native (parquet, and csv), "
530
- "and it will be slower for large datasets.",
531
- UserWarning,
532
- stacklevel=2,
525
+ "and it will be slower for large datasets."
533
526
  )
534
527
  _zarr_python_copy(src_group, dest_group)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngio
3
- Version: 0.5.0b6
3
+ Version: 0.5.1
4
4
  Summary: Next Generation file format IO
5
5
  Project-URL: homepage, https://github.com/BioVisionCenter/ngio
6
6
  Project-URL: repository, https://github.com/BioVisionCenter/ngio
@@ -23,7 +23,7 @@ Requires-Dist: dask[distributed]<2025.11.0
23
23
  Requires-Dist: filelock
24
24
  Requires-Dist: numpy
25
25
  Requires-Dist: ome-zarr-models
26
- Requires-Dist: pandas>=1.2.0
26
+ Requires-Dist: pandas<3.0.0,>=1.2.0
27
27
  Requires-Dist: pillow
28
28
  Requires-Dist: polars
29
29
  Requires-Dist: pooch
@@ -58,6 +58,7 @@ Requires-Dist: mkdocs-jupyter; extra == 'docs'
58
58
  Requires-Dist: mkdocs-material; extra == 'docs'
59
59
  Requires-Dist: mkdocstrings[python]; extra == 'docs'
60
60
  Requires-Dist: rich; extra == 'docs'
61
+ Requires-Dist: ruff; extra == 'docs'
61
62
  Requires-Dist: scikit-image; extra == 'docs'
62
63
  Requires-Dist: tabulate; extra == 'docs'
63
64
  Provides-Extra: test