Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

- Add `set_config()` (exported from `ngio` and `ngio.config`) to replace the global `NgioConfig` from code at any time. It replaces the previous configuration (a zarr setting forwarded earlier stays unless the new config sets it) and immediately applies the `s3fs` retry markers and the `zarr` section, so libraries can configure ngio without setting `NGIO_CONFIG_PATH` before `import ngio`.

### Fixes

- `derive_label` and `add_table` on a container opened with `mode="r"` that has no `labels`/`tables` group yet raise `NgioValueError("The group is read only. Cannot derive a label.")` (or `... add a table.`) instead of `NgioValidationError("No labels found in the image.")`: the missing group could not be created, and the error said it did not exist. Same for `OmeZarrPlate.add_table`. Reading on such a container (`list_labels`, `labels_container`) still reports "No labels found" ([#279](https://github.com/BioVisionCenter/ngio/issues/279)).
- `axes_order` only virtualises canonical axes. A canonical axis (`t`, `c`, `z`, `y`, `x`) missing on disk still comes back as a singleton, by its canonical name or the name the `AxesSetup` maps to it, so one `"czyx"` keeps working on 2D and 3D data. Any other name that is not an axis of the image raises `NgioValueError` naming it, the full order, the image axes and the canonical set; it used to become a phantom dimension (`axes_order="czyq"` returned a 4D array with `x` dropped and a size-1 axis appended). The iterators run the check in the constructor instead of at the first read, and the duplicate-axis error names the repeated axis ([#277](https://github.com/BioVisionCenter/ngio/issues/277)).

### Tests
Expand Down
2 changes: 2 additions & 0 deletions src/ngio/hcs/_plate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,8 @@ def add_table(

If `backend` is `None` (default), the table's own backend is preserved.
"""
if self._group_handler.read_only:
raise NgioValueError("The group is read only. Cannot add a table.")
self.tables_container.add(
name=name, table=table, backend=backend, overwrite=overwrite
)
Expand Down
7 changes: 7 additions & 0 deletions src/ngio/images/_ome_zarr_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ def refresh(self) -> None:
self._tables_container = None
self._tables_absent = False

def _require_writable(self, action: str) -> None:
"""Raise before a write that needs a group this container cannot create."""
if self._group_handler.read_only:
raise NgioValueError(f"The group is read only. Cannot {action}.")

@property
def images_container(self) -> ImagesContainer:
"""Return the images container.
Expand Down Expand Up @@ -820,6 +825,7 @@ def add_table(

If `backend` is `None` (default), the table's own backend is preserved.
"""
self._require_writable("add a table")
self.tables_container.add(
name=name, table=table, backend=backend, overwrite=overwrite
)
Expand Down Expand Up @@ -992,6 +998,7 @@ def derive_label(
Label: The new derived label.

"""
self._require_writable("derive a label")
if ref_image is None:
ref_image = self.get_image()
return self.labels_container.derive(
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/hcs/test_plate_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ def test_tables_container_missing_on_readonly_plate(tmp_path: Path):
assert plate.list_tables() == []
with pytest.raises(NgioValidationError, match="No tables found"):
_ = plate.tables_container
with pytest.raises(NgioValueError, match="read only"):
plate.add_table("t", RoiTable(rois=[]))


def test_typed_table_getters(tmp_path: Path):
Expand Down
8 changes: 7 additions & 1 deletion tests/unit/images/test_container_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,11 @@ def test_labels_missing_on_read_only_container(tmp_path: Path):

# a read-only container without a labels group degrades gracefully
assert container.list_labels() == []
with pytest.raises(NgioValidationError):
with pytest.raises(NgioValidationError, match="No labels found"):
_ = container.labels_container

# a write names the real problem: the group cannot be created (#279)
with pytest.raises(NgioValueError, match="read only"):
container.derive_label("x")
with pytest.raises(NgioValueError, match="read only"):
container.add_table("t", RoiTable(rois=[]))
Loading