Skip to content

Commit

Permalink
Add layer_name to kwargs of from_images (#1054)
Browse files Browse the repository at this point in the history
* Add layer_name to parameters of from_images method.

* Update Changelog.md

* Update webknossos/webknossos/dataset/dataset.py

Co-authored-by: Norman Rzepka <[email protected]>

---------

Co-authored-by: Norman Rzepka <[email protected]>
  • Loading branch information
markbader and normanrz authored Apr 29, 2024
1 parent 11f9931 commit 7bc9773
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
1 change: 1 addition & 0 deletions webknossos/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ For upgrade instructions, please check the respective _Breaking Changes_ section
### Added

### Changed
- Added `layer_name` as optional argument to `Dataset.from_images` method. If the created dataset contains only a single layer, `layer_name` is used, otherwise the given `layer_name` is a common prefix for all layers. [1054](https://github.com/scalableminds/webknossos-libs/pull/1054)
- The context variable of View.get_buffered_slice_writer() is a BufferedSliceWriter now instead of a Generator. Interaction with the SliceWriter does not change, but updating the offset after first initialization is possible now. [1052](https://github.com/scalableminds/webknossos-libs/pull/1052)

### Fixed
Expand Down
14 changes: 8 additions & 6 deletions webknossos/tests/dataset/test_from_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ def test_compare_tifffile(tmp_path: Path) -> None:
tmp_path,
(1, 1, 1),
compress=True,
layer_name="tiff_stack",
layer_category="segmentation",
chunks_per_shard=(8, 8, 8),
map_filepath_to_layer_name=wk.Dataset.ConversionLayerMapping.ENFORCE_SINGLE_LAYER,
)
assert len(ds.layers) == 1
assert "tiff" in ds.layers
data = ds.layers["tiff"].get_finest_mag().read()[0, :, :]
assert "tiff_stack" in ds.layers
data = ds.layers["tiff_stack"].get_finest_mag().read()[0, :, :]
for z_index in range(0, data.shape[-1]):
with TiffFile(TESTDATA_DIR / "tiff" / "test.0000.tiff") as tif_file:
comparison_slice = tif_file.asarray().T
Expand All @@ -43,14 +44,15 @@ def test_multiple_multitiffs(tmp_path: Path) -> None:
TESTDATA_DIR / "various_tiff_formats",
tmp_path,
(1, 1, 1),
layer_name="tiffs",
)
assert len(ds.layers) == 4

expected_dtype_channels_size_per_layer = {
"test_CS.tif": ("uint8", 3, (128, 128, 320)),
"test_C.tif": ("uint8", 1, (128, 128, 320)),
"test_I.tif": ("uint32", 1, (64, 128, 64)),
"test_S.tif": ("uint16", 3, (128, 128, 64)),
"tiffs_test_CS.tif": ("uint8", 3, (128, 128, 320)),
"tiffs_test_C.tif": ("uint8", 1, (128, 128, 320)),
"tiffs_test_I.tif": ("uint32", 1, (64, 128, 64)),
"tiffs_test_S.tif": ("uint16", 3, (128, 128, 64)),
}

for layer_name, layer in ds.layers.items():
Expand Down
7 changes: 7 additions & 0 deletions webknossos/webknossos/cli/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ def main(
metavar="VOXEL_SIZE",
),
],
layer_name: Annotated[
Optional[str],
typer.Option(
help="This name is used if only one layer is created. Otherwise this name is used as a common prefix for all layers.",
),
] = None,
category: Annotated[
Optional[LayerCategory],
typer.Option(
Expand Down Expand Up @@ -107,5 +113,6 @@ def main(
data_format=data_format,
executor=executor,
compress=compress,
layer_name=layer_name,
layer_category=category.value if category else None,
)
26 changes: 21 additions & 5 deletions webknossos/webknossos/dataset/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ def from_images(
ConversionLayerMapping, Callable[[Path], str]
] = ConversionLayerMapping.INSPECT_SINGLE_FILE,
z_slices_sort_key: Callable[[Path], Any] = natsort_keygen(),
layer_name: Optional[str] = None,
layer_category: Optional[LayerCategoryType] = None,
data_format: Union[str, DataFormat] = DEFAULT_DATA_FORMAT,
chunk_shape: Optional[Union[Vec3IntLike, int]] = None,
Expand Down Expand Up @@ -593,6 +594,9 @@ def from_images(
The order of the z-slices can be customized by setting
`z_slices_sort_key`.
If a layer_name is set, this name is used if a single layer is created.
Otherwise the layer_name is used as a common prefix for all layers.
The category of layers (`color` vs `segmentation`) is determined
automatically by checking if `segmentation` is part of the path.
Alternatively, a category can be enforced by passing `layer_category`.
Expand Down Expand Up @@ -634,20 +638,32 @@ def from_images(

filepaths_per_layer: Dict[str, List[Path]] = {}
for input_file in input_files:
layer_name = map_filepath_to_layer_name(input_file)
layer_name_from_mapping = map_filepath_to_layer_name(input_file)
# Remove characters from layer name that are not allowed
layer_name = _UNALLOWED_LAYER_NAME_CHARS.sub("", layer_name)
layer_name_from_mapping = _UNALLOWED_LAYER_NAME_CHARS.sub(
"", layer_name_from_mapping
)
# Ensure layer name does not start with a dot
layer_name = layer_name.lstrip(".")
layer_name_from_mapping = layer_name_from_mapping.lstrip(".")

assert (
layer_name != ""
layer_name_from_mapping != ""
), f"Could not determine a layer name for {input_file}."

filepaths_per_layer.setdefault(layer_name, []).append(
filepaths_per_layer.setdefault(layer_name_from_mapping, []).append(
input_path / input_file
)

if layer_name is not None:
if len(filepaths_per_layer) == 1:
filepaths_per_layer[layer_name] = filepaths_per_layer.pop(
layer_name_from_mapping
)
else:
filepaths_per_layer = {
f"{layer_name}_{k}": v for k, v in filepaths_per_layer.items()
}

for layer_name, filepaths in filepaths_per_layer.items():
filepaths.sort(key=z_slices_sort_key)
category: LayerCategoryType
Expand Down

0 comments on commit 7bc9773

Please sign in to comment.