Skip to content

Commit 521dd88

Browse files
authored
Dataset API changes: parameter 'dtype' is now interpreted as 'dtype_per_layer' and parameter list for 'read(...)' was reordered to match wkw.Dataset.read(...) (#239)
* change semantic from 'dtype' in dataset api to dtype_per_layer (opposed to dtype_per_channel) * reformat code * add optional parameter 'dtype_per_channel' to 'add_layer' * remove requirement that the dtype_per_layer must contain a number * reformat code * fix test after merge * change order of parameters (offset, size) from 'read'-methods in dataset API to match wkw.Dataset behaviour
1 parent 887f1ce commit 521dd88

File tree

9 files changed

+217
-73
lines changed

9 files changed

+217
-73
lines changed

testdata/simple_wk_dataset/datasource-properties.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"dataFormat": "wkw",
1212
"name": "color",
1313
"category": "color",
14-
"elementClass": "uint8",
14+
"elementClass": "uint24",
1515
"num_channels": 3,
1616
"boundingBox": {
1717
"topLeft": [

tests/test_dataset.py

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def chunk_job(args):
3232
view, additional_args = args
3333

3434
# increment the color value of each voxel
35-
data = view.read(view.size)
35+
data = view.read(size=view.size)
3636
if data.shape[0] == 1:
3737
data = data[0, :, :, :]
3838
data += 50
@@ -43,7 +43,7 @@ def advanced_chunk_job(args):
4343
view, additional_args = args
4444

4545
# write different data for each chunk (depending on the global_offset of the chunk)
46-
data = view.read(view.size)
46+
data = view.read(size=view.size)
4747
data = np.ones(data.shape, dtype=np.uint8) * np.uint8(sum(view.global_offset))
4848
view.write(data)
4949

@@ -108,7 +108,7 @@ def for_each_chunking_advanced(ds, view):
108108
((128, 128, 10), (32, 32, 54)),
109109
]:
110110
chunk = ds.get_view("color", "1", size=size, offset=offset, is_bounded=False)
111-
chunk_data = chunk.read(chunk.size)
111+
chunk_data = chunk.read(size=chunk.size)
112112
assert np.array_equal(
113113
np.ones(chunk_data.shape, dtype=np.uint8)
114114
* np.uint8(sum(chunk.global_offset)),
@@ -147,7 +147,7 @@ def test_create_wk_dataset_with_explicit_header_fields():
147147
delete_dir("./testoutput/wk_dataset_advanced")
148148

149149
ds = WKDataset.create("./testoutput/wk_dataset_advanced", scale=(1, 1, 1))
150-
ds.add_layer("color", "color", dtype=np.uint16, num_channels=3)
150+
ds.add_layer("color", "color", dtype_per_layer="uint48", num_channels=3)
151151

152152
ds.get_layer("color").add_mag("1", block_len=64, file_len=64)
153153
ds.get_layer("color").add_mag("2-2-1")
@@ -158,7 +158,7 @@ def test_create_wk_dataset_with_explicit_header_fields():
158158
assert len(ds.properties.data_layers) == 1
159159
assert len(ds.properties.data_layers["color"].wkw_magnifications) == 2
160160

161-
assert ds.properties.data_layers["color"].element_class == np.dtype(np.uint16)
161+
assert ds.properties.data_layers["color"].element_class == "uint48"
162162
assert (
163163
ds.properties.data_layers["color"].wkw_magnifications[0].cube_length == 64 * 64
164164
) # mag "1"
@@ -212,7 +212,7 @@ def test_view_read_with_open():
212212
with wk_view.open():
213213
assert wk_view._is_opened
214214

215-
data = wk_view.read((10, 10, 10))
215+
data = wk_view.read(size=(10, 10, 10))
216216
assert data.shape == (3, 10, 10, 10) # three channel
217217

218218
assert not wk_view._is_opened
@@ -224,7 +224,7 @@ def test_tiff_mag_read_with_open():
224224
layer = tiff_dataset.get_layer("color")
225225
mag = layer.get_mag("1")
226226
mag.open()
227-
data = mag.read((10, 10, 10))
227+
data = mag.read(size=(10, 10, 10))
228228
assert data.shape == (1, 10, 10, 10) # single channel
229229

230230

@@ -238,7 +238,7 @@ def test_view_read_without_open():
238238
assert not wk_view._is_opened
239239

240240
# 'read()' checks if it was already opened. If not, it opens and closes automatically
241-
data = wk_view.read((10, 10, 10))
241+
data = wk_view.read(size=(10, 10, 10))
242242
assert data.shape == (3, 10, 10, 10) # three channel
243243

244244
assert not wk_view._is_opened
@@ -258,7 +258,7 @@ def test_view_wk_write():
258258

259259
wk_view.write(write_data)
260260

261-
data = wk_view.read((10, 10, 10))
261+
data = wk_view.read(size=(10, 10, 10))
262262
assert np.array_equal(data, write_data)
263263

264264

@@ -276,7 +276,7 @@ def test_view_tiff_write():
276276

277277
tiff_view.write(write_data)
278278

279-
data = tiff_view.read((5, 5, 5))
279+
data = tiff_view.read(size=(5, 5, 5))
280280
assert data.shape == (1, 5, 5, 5) # this dataset has only one channel
281281
assert np.array_equal(data, np.expand_dims(write_data, 0))
282282

@@ -436,7 +436,7 @@ def test_other_file_extensions_for_tiff_dataset():
436436
np.random.seed(1234)
437437
write_data = (np.random.rand(10, 10, 10) * 255).astype(np.uint8)
438438
mag.write(write_data)
439-
assert np.array_equal(mag.read((10, 10, 10)), np.expand_dims(write_data, 0))
439+
assert np.array_equal(mag.read(size=(10, 10, 10)), np.expand_dims(write_data, 0))
440440

441441

442442
def test_tiff_write_multi_channel_uint8():
@@ -475,7 +475,7 @@ def test_tiff_write_multi_channel_uint16():
475475

476476
ds_tiff = TiffDataset.create(dataset_path, scale=(1, 1, 1))
477477
mag = ds_tiff.add_layer(
478-
"color", Layer.COLOR_TYPE, num_channels=3, dtype=np.uint16
478+
"color", Layer.COLOR_TYPE, num_channels=3, dtype_per_layer="uint48"
479479
).add_mag("1")
480480

481481
# 10 images (z-layers), each 250x200, dtype=np.uint16
@@ -495,7 +495,7 @@ def test_wk_write_multi_channel_uint16():
495495

496496
ds_tiff = WKDataset.create(dataset_path, scale=(1, 1, 1))
497497
mag = ds_tiff.add_layer(
498-
"color", Layer.COLOR_TYPE, num_channels=3, dtype=np.uint16
498+
"color", Layer.COLOR_TYPE, num_channels=3, dtype_per_layer="uint48"
499499
).add_mag("1")
500500

501501
# 10 images (z-layers), each 250x200, dtype=np.uint16
@@ -516,7 +516,7 @@ def test_wkw_empty_read():
516516
.add_layer("color", Layer.COLOR_TYPE)
517517
.add_mag("1")
518518
)
519-
data = mag.read(size=(0, 0, 0), offset=(1, 1, 1))
519+
data = mag.read(offset=(1, 1, 1), size=(0, 0, 0))
520520

521521
assert data.shape == (1, 0, 0, 0)
522522

@@ -530,7 +530,7 @@ def test_tiff_empty_read():
530530
.add_layer("color", Layer.COLOR_TYPE)
531531
.add_mag("1")
532532
)
533-
data = mag.read(size=(0, 0, 0), offset=(1, 1, 1))
533+
data = mag.read(offset=(1, 1, 1), size=(0, 0, 0))
534534

535535
assert data.shape == (1, 0, 0, 0)
536536

@@ -612,22 +612,22 @@ def test_get_or_add_layer():
612612

613613
# layer did not exist before
614614
layer = ds.get_or_add_layer(
615-
"color", Layer.COLOR_TYPE, dtype=np.uint8, num_channels=1
615+
"color", Layer.COLOR_TYPE, dtype_per_layer="uint8", num_channels=1
616616
)
617617
assert "color" in ds.layers.keys()
618618
assert layer.name == "color"
619619

620620
# layer did exist before
621621
layer = ds.get_or_add_layer(
622-
"color", Layer.COLOR_TYPE, dtype=np.uint8, num_channels=1
622+
"color", Layer.COLOR_TYPE, dtype_per_layer="uint8", num_channels=1
623623
)
624624
assert "color" in ds.layers.keys()
625625
assert layer.name == "color"
626626

627627
try:
628-
# layer did exist before but with another 'dtype' (this would work the same for 'category' and 'num_channels')
628+
# layer did exist before but with another 'dtype_per_layer' (this would work the same for 'category' and 'num_channels')
629629
layer = ds.get_or_add_layer(
630-
"color", Layer.COLOR_TYPE, dtype=np.uint16, num_channels=1
630+
"color", Layer.COLOR_TYPE, dtype_per_layer="uint16", num_channels=1
631631
)
632632

633633
raise Exception(
@@ -701,7 +701,7 @@ def test_tiled_tiff_read_and_write_multichannel():
701701
data = get_multichanneled_data(np.uint8)
702702

703703
mag.write(data, offset=(5, 5, 5))
704-
written_data = mag.read(size=(250, 200, 10), offset=(5, 5, 5))
704+
written_data = mag.read(offset=(5, 5, 5), size=(250, 200, 10))
705705
assert written_data.shape == (3, 250, 200, 10)
706706
assert np.array_equal(data, written_data)
707707

@@ -724,7 +724,7 @@ def test_tiled_tiff_read_and_write():
724724
data[i, j, h] = i + j % 250
725725

726726
mag.write(data, offset=(5, 5, 5))
727-
written_data = mag.read(size=(250, 200, 10), offset=(5, 5, 5))
727+
written_data = mag.read(offset=(5, 5, 5), size=(250, 200, 10))
728728
assert written_data.shape == (1, 250, 200, 10)
729729
assert np.array_equal(written_data, np.expand_dims(data, 0))
730730

@@ -868,7 +868,7 @@ def test_chunking_wk():
868868
"color", "1", size=(256, 256, 256), is_bounded=False
869869
)
870870

871-
original_data = view.read(view.size)
871+
original_data = view.read(size=view.size)
872872

873873
with get_executor_for_args(None) as executor:
874874
view.for_each_chunk(
@@ -878,7 +878,7 @@ def test_chunking_wk():
878878
executor=executor,
879879
)
880880

881-
assert np.array_equal(original_data + 50, view.read(view.size))
881+
assert np.array_equal(original_data + 50, view.read(size=view.size))
882882

883883

884884
def test_chunking_wk_advanced():
@@ -916,7 +916,7 @@ def test_chunking_tiff():
916916
"color", "1", size=(265, 265, 10)
917917
)
918918

919-
original_data = view.read(view.size)
919+
original_data = view.read(size=view.size)
920920

921921
with get_executor_for_args(None) as executor:
922922
view.for_each_chunk(
@@ -926,7 +926,7 @@ def test_chunking_tiff():
926926
executor=executor,
927927
)
928928

929-
new_data = view.read(view.size)
929+
new_data = view.read(size=view.size)
930930
assert np.array_equal(original_data + 50, new_data)
931931

932932

@@ -992,7 +992,7 @@ def test_tiled_tiff_inverse_pattern():
992992
data[i, j, h] = i + j % 250
993993

994994
mag.write(data, offset=(5, 5, 5))
995-
written_data = mag.read(size=(250, 200, 10), offset=(5, 5, 5))
995+
written_data = mag.read(offset=(5, 5, 5), size=(250, 200, 10))
996996
assert written_data.shape == (1, 250, 200, 10)
997997
assert np.array_equal(written_data, np.expand_dims(data, 0))
998998

@@ -1174,22 +1174,22 @@ def test_changing_layer_bounding_box():
11741174

11751175
bbox_size = ds.properties.data_layers["color"].get_bounding_box_size()
11761176
assert bbox_size == (265, 265, 10)
1177-
original_data = mag.read(bbox_size)
1177+
original_data = mag.read(size=bbox_size)
11781178
assert original_data.shape == (1, 265, 265, 10)
11791179

11801180
layer.set_bounding_box_size((100, 100, 10)) # decrease boundingbox
11811181

11821182
bbox_size = ds.properties.data_layers["color"].get_bounding_box_size()
11831183
assert bbox_size == (100, 100, 10)
1184-
less_data = mag.read(bbox_size)
1184+
less_data = mag.read(size=bbox_size)
11851185
assert less_data.shape == (1, 100, 100, 10)
11861186
assert np.array_equal(original_data[:, :100, :100, :10], less_data)
11871187

11881188
layer.set_bounding_box_size((300, 300, 10)) # increase the boundingbox
11891189

11901190
bbox_size = ds.properties.data_layers["color"].get_bounding_box_size()
11911191
assert bbox_size == (300, 300, 10)
1192-
more_data = mag.read(bbox_size)
1192+
more_data = mag.read(size=bbox_size)
11931193
assert more_data.shape == (1, 300, 300, 10)
11941194
assert np.array_equal(more_data[:, :265, :265, :10], original_data)
11951195

@@ -1205,7 +1205,7 @@ def test_changing_layer_bounding_box():
12051205
new_bbox_size = ds.properties.data_layers["color"].get_bounding_box_size()
12061206
assert new_bbox_offset == (10, 10, 0)
12071207
assert new_bbox_size == (255, 255, 10)
1208-
new_data = mag.read(new_bbox_size)
1208+
new_data = mag.read(size=new_bbox_size)
12091209
assert new_data.shape == (1, 255, 255, 10)
12101210
assert np.array_equal(original_data[:, 10:, 10:, :], new_data)
12111211

@@ -1282,6 +1282,31 @@ def test_view_offsets():
12821282
pass
12831283

12841284

1285+
def test_adding_layer_with_invalid_dtype_per_layer():
1286+
delete_dir("./testoutput/invalid_dtype")
1287+
1288+
ds = WKDataset.create("./testoutput/invalid_dtype", scale=(1, 1, 1))
1289+
with pytest.raises(TypeError):
1290+
# this would lead to a dtype_per_channel of "uint10", but that is not a valid dtype
1291+
ds.add_layer("color", "color", dtype_per_layer="uint30", num_channels=3)
1292+
with pytest.raises(TypeError):
1293+
# "int" is interpreted as "int64", but 64 bit cannot be split into 3 channels
1294+
ds.add_layer("color", "color", dtype_per_layer="int", num_channels=3)
1295+
ds.add_layer(
1296+
"color", "color", dtype_per_layer="int", num_channels=4
1297+
) # "int"/"int64" works with 4 channels
1298+
1299+
1300+
def test_adding_layer_with_valid_dtype_per_layer():
1301+
delete_dir("./testoutput/valid_dtype")
1302+
1303+
ds = WKDataset.create("./testoutput/valid_dtype", scale=(1, 1, 1))
1304+
ds.add_layer("color1", Layer.COLOR_TYPE, dtype_per_layer="uint24", num_channels=3)
1305+
ds.add_layer("color2", Layer.COLOR_TYPE, dtype_per_layer=np.uint8, num_channels=1)
1306+
ds.add_layer("color3", Layer.COLOR_TYPE, dtype_per_channel=np.uint8, num_channels=3)
1307+
ds.add_layer("color4", Layer.COLOR_TYPE, dtype_per_channel="uint8", num_channels=3)
1308+
1309+
12851310
def test_writing_subset_of_compressed_data_multi_channel():
12861311
delete_dir("./testoutput/compressed_data/")
12871312

@@ -1458,5 +1483,5 @@ def test_add_symlink_layer():
14581483
write_data = (np.random.rand(3, 10, 10, 10) * 255).astype(np.uint8)
14591484
mag.write(write_data)
14601485

1461-
assert np.array_equal(mag.read((10, 10, 10)), write_data)
1462-
assert np.array_equal(original_mag.read((10, 10, 10)), write_data)
1486+
assert np.array_equal(mag.read(size=(10, 10, 10)), write_data)
1487+
assert np.array_equal(original_mag.read(size=(10, 10, 10)), write_data)

0 commit comments

Comments
 (0)