Skip to content

Commit 21a7d18

Browse files
fixed float/double to float32, float64 conversion (#126)
* fixed bug and implemented test * integrated feedback * formatted code
1 parent f315333 commit 21a7d18

File tree

3 files changed

+100
-3
lines changed

3 files changed

+100
-3
lines changed

tests/scripts/simple_anisotropic_tiff_cubing.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ docker run \
1010
--batch_size 8 \
1111
--layer_name color \
1212
--max 8 \
13+
--scale "11.24,11.24,25"\
1314
--name awesome_data \
1415
/testdata/tiff /testoutput/tiff3
1516
[ -d testoutput/tiff3/color ]

tests/test_metadata.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import numpy as np
2+
import os
3+
4+
from wkcuber.cubing import ensure_wkw
5+
from wkcuber.utils import WkwDatasetInfo, open_wkw
6+
from wkcuber.metadata import (
7+
write_webknossos_metadata,
8+
refresh_metadata,
9+
read_datasource_properties,
10+
read_metadata_for_layer,
11+
)
12+
13+
14+
def test_element_class_convertion():
15+
test_wkw_path = os.path.join("testoutput", "test_metadata")
16+
prediction_layer_name = "prediction"
17+
prediction_wkw_info = WkwDatasetInfo(
18+
test_wkw_path, prediction_layer_name, np.float32, 1
19+
)
20+
ensure_wkw(prediction_wkw_info, num_channels=3)
21+
22+
write_custom_layer(test_wkw_path, "prediction", np.float32, num_channels=3)
23+
write_webknossos_metadata(
24+
test_wkw_path,
25+
"test_metadata",
26+
[11.24, 11.24, 28],
27+
compute_max_id=True,
28+
exact_bounding_box={"topLeft": [0, 0, 0], "width": 4, "height": 4, "depth": 4},
29+
)
30+
write_custom_layer(test_wkw_path, "segmentation", np.float64, num_channels=1)
31+
write_custom_layer(test_wkw_path, "color", np.uint8, num_channels=3)
32+
33+
refresh_metadata(test_wkw_path)
34+
35+
check_element_class_of_layer(test_wkw_path, "prediction", "float", np.float32)
36+
check_element_class_of_layer(test_wkw_path, "segmentation", "double", np.float64)
37+
check_element_class_of_layer(test_wkw_path, "color", "uint24", np.uint8)
38+
39+
40+
def check_element_class_of_layer(
41+
test_wkw_path, layer_name, expected_element_class, expected_dtype
42+
):
43+
datasource_properties = read_datasource_properties(test_wkw_path)
44+
layer_to_check = None
45+
for layer in datasource_properties["dataLayers"]:
46+
if layer["name"] == layer_name:
47+
layer_to_check = layer
48+
49+
assert (
50+
layer_to_check
51+
), f"Did not find layer {layer_name} in datasource_properties.json."
52+
assert layer_to_check["elementClass"] == expected_element_class
53+
_, converted_dtype, _, _ = read_metadata_for_layer(test_wkw_path, layer_name)
54+
assert converted_dtype == expected_dtype
55+
56+
57+
def write_custom_layer(target_path, layer_name, dtype, num_channels):
58+
data = (
59+
np.arange(4 * 4 * 4 * num_channels)
60+
.reshape((num_channels, 4, 4, 4))
61+
.astype(dtype)
62+
)
63+
prediction_wkw_info = WkwDatasetInfo(target_path, layer_name, dtype, 1)
64+
ensure_wkw(prediction_wkw_info, num_channels=num_channels)
65+
with open_wkw(prediction_wkw_info, num_channels=num_channels) as dataset:
66+
dataset.write(off=(0, 0, 0), data=data)
67+
68+
69+
if __name__ == "__main__":
70+
test_element_class_convertion()

wkcuber/metadata.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,26 @@ def refresh_metadata(
131131
write_datasource_properties(wkw_path, datasource_properties)
132132

133133

134+
def convert_element_class_to_dtype(elementClass):
135+
default_dtype = np.uint8 if "uint" in elementClass else np.dtype(elementClass)
136+
conversion_map = {
137+
"float": np.float32,
138+
"double": np.float64,
139+
"uint8": np.uint8,
140+
"uint16": np.uint16,
141+
"uint32": np.uint32,
142+
"uint64": np.uint64,
143+
}
144+
return conversion_map.get(elementClass, default_dtype)
145+
146+
134147
def read_metadata_for_layer(wkw_path, layer_name):
135148
datasource_properties = read_datasource_properties(wkw_path)
136149

137150
layers = datasource_properties["dataLayers"]
138151
layer_info = next(layer for layer in layers if layer["name"] == layer_name)
139152

140-
dtype = np.dtype(layer_info["elementClass"])
153+
dtype = convert_element_class_to_dtype(layer_info["elementClass"])
141154
bounding_box = layer_info["boundingBox"]
142155
origin = bounding_box["topLeft"]
143156
bounding_box = [
@@ -149,6 +162,19 @@ def read_metadata_for_layer(wkw_path, layer_name):
149162
return layer_info, dtype, bounding_box, origin
150163

151164

165+
def convert_dype_to_element_class(dtype):
166+
element_class_to_dtype_map = {
167+
"float": np.float32,
168+
"double": np.float64,
169+
"uint8": np.uint8,
170+
"uint16": np.uint16,
171+
"uint32": np.uint32,
172+
"uint64": np.uint64,
173+
}
174+
conversion_map = {v: k for k, v in element_class_to_dtype_map.items()}
175+
return conversion_map.get(dtype.type, str(dtype))
176+
177+
152178
def detect_dtype(dataset_path, layer, mag: Mag = Mag(1)):
153179
layer_path = path.join(dataset_path, layer, str(mag))
154180
if path.exists(layer_path):
@@ -159,7 +185,7 @@ def detect_dtype(dataset_path, layer, mag: Mag = Mag(1)):
159185
if voxel_size == np.uint8 and num_channels > 1:
160186
return "uint" + str(8 * num_channels)
161187
else:
162-
return str(np.dtype(voxel_type))
188+
return convert_dype_to_element_class(voxel_size)
163189

164190

165191
def detect_cubeLength(dataset_path, layer, mag: Mag = Mag(1)):
@@ -302,7 +328,7 @@ def detect_layers(dataset_path, max_id, compute_max_id, exact_bounding_box=None)
302328
)
303329
else:
304330
if args.name is not None:
305-
logging.warn(
331+
logging.warning(
306332
"The --name argument is ignored, since --refresh was provided."
307333
)
308334
refresh_metadata(args.path, args.max_id, args.compute_max_id)

0 commit comments

Comments
 (0)