Skip to content

Commit efbc32c

Browse files
authored
Raise ValueError for unsupported dtypes. (#1316)
* Raise ValueError for unsupported dtypes. * Add type and fix test. * Update changelog. * refactor. * implement requested change.
1 parent a6e3f0b commit efbc32c

File tree

3 files changed

+86
-46
lines changed

3 files changed

+86
-46
lines changed

webknossos/Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ For upgrade instructions, please check the respective _Breaking Changes_ section
1717
### Added
1818

1919
### Changed
20+
- When adding a layer, the used dtype is only valid if it is supported by webknossos. [#1316](https://github.com/scalableminds/webknossos-libs/pull/1316)
2021

2122
### Fixed
2223
- Fixed an issue that creates an Error when `add_mag()` was called just with a `chunk_shape`. [#1315](https://github.com/scalableminds/webknossos-libs/pull/1315)

webknossos/tests/dataset/test_dataset.py

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
COLOR_CATEGORY,
2525
SEGMENTATION_CATEGORY,
2626
Dataset,
27+
LayerCategoryType,
2728
RemoteDataset,
2829
View,
2930
)
@@ -1554,41 +1555,6 @@ def test_adding_layer_with_valid_dtype_per_layer() -> None:
15541555
ds.add_layer(
15551556
"color4", COLOR_CATEGORY, dtype_per_channel="uint8", num_channels=3
15561557
)
1557-
ds.add_layer(
1558-
"seg1",
1559-
SEGMENTATION_CATEGORY,
1560-
dtype_per_channel="float",
1561-
num_channels=1,
1562-
largest_segment_id=100000,
1563-
)
1564-
ds.add_layer(
1565-
"seg2",
1566-
SEGMENTATION_CATEGORY,
1567-
dtype_per_channel=float,
1568-
num_channels=1,
1569-
largest_segment_id=100000,
1570-
)
1571-
ds.add_layer(
1572-
"seg3",
1573-
SEGMENTATION_CATEGORY,
1574-
dtype_per_channel=float,
1575-
num_channels=1,
1576-
largest_segment_id=100000,
1577-
)
1578-
ds.add_layer(
1579-
"seg4",
1580-
SEGMENTATION_CATEGORY,
1581-
dtype_per_channel="double",
1582-
num_channels=1,
1583-
largest_segment_id=100000,
1584-
)
1585-
ds.add_layer(
1586-
"seg5",
1587-
SEGMENTATION_CATEGORY,
1588-
dtype_per_channel="float",
1589-
num_channels=3,
1590-
largest_segment_id=100000,
1591-
)
15921558

15931559
with open(
15941560
ds_path / "datasource-properties.json",
@@ -1600,11 +1566,6 @@ def test_adding_layer_with_valid_dtype_per_layer() -> None:
16001566
assert data["dataLayers"][1]["elementClass"] == "uint8"
16011567
assert data["dataLayers"][2]["elementClass"] == "uint24"
16021568
assert data["dataLayers"][3]["elementClass"] == "uint24"
1603-
assert data["dataLayers"][4]["elementClass"] == "float"
1604-
assert data["dataLayers"][5]["elementClass"] == "float"
1605-
assert data["dataLayers"][6]["elementClass"] == "float"
1606-
assert data["dataLayers"][7]["elementClass"] == "double"
1607-
assert data["dataLayers"][8]["elementClass"] == "float96"
16081569

16091570
reopened_ds = Dataset.open(
16101571
ds_path
@@ -1613,12 +1574,6 @@ def test_adding_layer_with_valid_dtype_per_layer() -> None:
16131574
assert reopened_ds.get_layer("color2").dtype_per_layer == "uint8"
16141575
assert reopened_ds.get_layer("color3").dtype_per_layer == "uint24"
16151576
assert reopened_ds.get_layer("color4").dtype_per_layer == "uint24"
1616-
# Note that 'float' and 'double' are stored as 'float32' and 'float64'
1617-
assert reopened_ds.get_layer("seg1").dtype_per_layer == "float32"
1618-
assert reopened_ds.get_layer("seg2").dtype_per_layer == "float32"
1619-
assert reopened_ds.get_layer("seg3").dtype_per_layer == "float32"
1620-
assert reopened_ds.get_layer("seg4").dtype_per_layer == "float64"
1621-
assert reopened_ds.get_layer("seg5").dtype_per_layer == "float96"
16221577

16231578
assure_exported_properties(ds)
16241579

@@ -3044,6 +2999,57 @@ def test_add_layer_like(data_format: DataFormat, output_path: Path) -> None:
30442999
assure_exported_properties(ds)
30453000

30463001

3002+
@pytest.mark.parametrize(
3003+
"dtype_per_channel,category,is_supported",
3004+
[
3005+
("uint8", COLOR_CATEGORY, True),
3006+
("uint16", COLOR_CATEGORY, True),
3007+
("uint32", COLOR_CATEGORY, True),
3008+
("uint64", COLOR_CATEGORY, False),
3009+
("int8", COLOR_CATEGORY, True),
3010+
("int16", COLOR_CATEGORY, True),
3011+
("int32", COLOR_CATEGORY, True),
3012+
("int64", COLOR_CATEGORY, False),
3013+
("float32", COLOR_CATEGORY, True),
3014+
("float64", COLOR_CATEGORY, False),
3015+
("uint8", SEGMENTATION_CATEGORY, True),
3016+
("uint16", SEGMENTATION_CATEGORY, True),
3017+
("uint32", SEGMENTATION_CATEGORY, True),
3018+
("uint64", SEGMENTATION_CATEGORY, True),
3019+
("int8", SEGMENTATION_CATEGORY, True),
3020+
("int16", SEGMENTATION_CATEGORY, True),
3021+
("int32", SEGMENTATION_CATEGORY, True),
3022+
("int64", SEGMENTATION_CATEGORY, True),
3023+
("float32", SEGMENTATION_CATEGORY, False),
3024+
("float64", SEGMENTATION_CATEGORY, False),
3025+
],
3026+
)
3027+
def test_add_layer_dtype_per_channel(
3028+
dtype_per_channel: str, category: LayerCategoryType, is_supported: bool
3029+
) -> None:
3030+
ds_path = prepare_dataset_path(
3031+
DataFormat.Zarr3, TESTOUTPUT_DIR, "dtype_per_channel"
3032+
)
3033+
ds = Dataset(ds_path, voxel_size=(1, 1, 1))
3034+
if is_supported:
3035+
layer = ds.add_layer(
3036+
"test_layer",
3037+
category=category,
3038+
dtype_per_channel=dtype_per_channel,
3039+
)
3040+
assert layer.dtype_per_channel == np.dtype(dtype_per_channel)
3041+
else:
3042+
with pytest.raises(
3043+
ValueError,
3044+
match="Supported dtypes are:",
3045+
):
3046+
ds.add_layer(
3047+
"test_layer",
3048+
category=category,
3049+
dtype_per_channel=dtype_per_channel,
3050+
)
3051+
3052+
30473053
def test_pickle_view() -> None:
30483054
ds_path = prepare_dataset_path(DataFormat.WKW, TESTOUTPUT_DIR, "pickle")
30493055
ds = Dataset(ds_path, voxel_size=(1, 1, 1))

webknossos/webknossos/dataset/dataset.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,39 @@ def add_layer(
12991299
else:
13001300
dtype_per_channel = np.dtype("uint" + str(DEFAULT_BIT_DEPTH))
13011301

1302+
# assert that the dtype_per_channel is supported by webknossos
1303+
if category == COLOR_CATEGORY:
1304+
color_dtypes = (
1305+
"uint8",
1306+
"uint16",
1307+
"uint32",
1308+
"int8",
1309+
"int16",
1310+
"int32",
1311+
"float32",
1312+
)
1313+
if dtype_per_channel.name not in color_dtypes:
1314+
raise ValueError(
1315+
f"Cannot add color layer with dtype {dtype_per_channel.name}. "
1316+
f"Supported dtypes are: {', '.join(color_dtypes)}.",
1317+
)
1318+
else:
1319+
segmentation_dtypes = (
1320+
"uint8",
1321+
"uint16",
1322+
"uint32",
1323+
"uint64",
1324+
"int8",
1325+
"int16",
1326+
"int32",
1327+
"int64",
1328+
)
1329+
if dtype_per_channel.name not in segmentation_dtypes:
1330+
raise ValueError(
1331+
f"Cannot add segmentation layer with dtype {dtype_per_channel.name}. "
1332+
f"Supported dtypes are: {', '.join(segmentation_dtypes)}.",
1333+
)
1334+
13021335
if layer_name in self.layers.keys():
13031336
raise IndexError(
13041337
f"Adding layer {layer_name} failed. There is already a layer with this name"

0 commit comments

Comments
 (0)