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
2 changes: 1 addition & 1 deletion docs/contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ file's schema or statistical interpretation.
| `channels_from_rgb_samples` | `true` when the C role is the RGB samples axis of images stored as RGB colour (§13), `false` otherwise; absent in manifests written before it. Optional key. |
| `intensity_checks` | The limits of the intensity checks run on the table (§14): `IntensityCheckSettings.to_dict()` of the normalization brick (`library_version`, `outlier_limit`, `saturation_limit`, `min_images`); absent in manifests written before it. Optional key. Changing the limits recomputes nothing. |
| `narrow_histogram_ranges` | The channel planes whose range check found the central range too narrow (§4), sorted by plane and channel: `relative_path`, `plane_id`, `channel` and the fields of the normalization brick's `RangeCheck` (`histogram_range`, `central_percentiles`, `central_bins`, `robust_quantiles`, `robust_limits`, `outside_robust_count`, `robust_central_bins`, `min_central_bins`). Empty when there are none; absent in manifests written before follow-up P6. Optional key: the manifest stays version 1. |
| Flags | `missing_as_singleton`, `convert_tiffs`, `read_in_blocks` and `channels_from_rgb_samples` are JSON booleans (`true`/`false`); any other value (`"false"`, `0`) makes the manifest malformed, never read as true or false, and `write_manifest` refuses to write one (`ValueError`), so a written manifest always reads back. |
| Flags | `missing_as_singleton`, `convert_tiffs`, `read_in_blocks`, `channel_names_trimmed` and `channels_from_rgb_samples` are JSON booleans (`true`/`false`); any other value (`"false"`, `0`) makes the manifest malformed, never read as true or false, and `write_manifest` refuses to write one (`ValueError`), so a written manifest always reads back. |
| `versions` | Versions of `morphobricks-preprocessing`, `morphobricks-normalization` (which computes the histograms and writes the CSV; absent in manifests written before it), `numpy`, `tifffile` and Python. Information only: a different version never causes a rebuild. |

Channel names and significant bits come from OME metadata. Significant bits are for
Expand Down
4 changes: 2 additions & 2 deletions src/morphobricks_preprocessing/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ def _file_dict(entry: FileEntry) -> dict:
"ome_zarr_path": entry.ome_zarr_path,
"read_in_blocks": _flag(entry.read_in_blocks, "read_in_blocks"),
"position_id": entry.position_id,
"channel_names_trimmed": entry.channel_names_trimmed,
"channel_names_trimmed": _flag(entry.channel_names_trimmed, "channel_names_trimmed"),
"roles": None if entry.roles is None else list(entry.roles),
}

Expand All @@ -568,7 +568,7 @@ def _file_entry(data: dict) -> FileEntry:
ome_zarr_path=None if data.get("ome_zarr_path") is None else str(data["ome_zarr_path"]),
read_in_blocks=_flag(data.get("read_in_blocks", False)),
position_id=None if data.get("position_id") is None else str(data["position_id"]),
channel_names_trimmed=bool(data.get("channel_names_trimmed", False)),
channel_names_trimmed=_flag(data.get("channel_names_trimmed", False)),
roles=_roles(data.get("roles"), str(data["axes"])),
)

Expand Down
14 changes: 11 additions & 3 deletions tests/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ def test_bad_role_in_manifest_is_refused():
("settings", "missing_as_singleton"),
("settings", "convert_tiffs"),
("file", "read_in_blocks"),
("file", "channel_names_trimmed"),
("top", "channels_from_rgb_samples"),
],
)
Expand All @@ -271,15 +272,22 @@ def test_flags_must_be_json_booleans(where, key, value):


def _with_flag(key, value):
if key == "read_in_blocks":
return manifest(files=(entry(read_in_blocks=value),))
if key in ("read_in_blocks", "channel_names_trimmed"):
return manifest(files=(entry(**{key: value}),))
if key == "channels_from_rgb_samples":
return manifest(channels_from_rgb_samples=value)
return manifest(settings=replace(RunSettings(65_536, 2**30, False, ()), **{key: value}))


@pytest.mark.parametrize(
"key", ["missing_as_singleton", "convert_tiffs", "read_in_blocks", "channels_from_rgb_samples"]
"key",
[
"missing_as_singleton",
"convert_tiffs",
"read_in_blocks",
"channel_names_trimmed",
"channels_from_rgb_samples",
],
)
@pytest.mark.parametrize("value", ["false", 0, 1, np.bool_(True)])
def test_the_writer_refuses_flags_that_are_not_booleans(tmp_path, key, value):
Expand Down
Loading