Skip to content

Commit 0482c3b

Browse files
authored
search for datasets also in the path with the long mag name (#243)
1 parent 521dd88 commit 0482c3b

File tree

6 files changed

+80
-29
lines changed

6 files changed

+80
-29
lines changed

tests/test_dataset.py

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import filecmp
22
import json
33
import os
4-
from os.path import dirname
4+
from os.path import dirname, join
55
import pytest
66

77
import numpy as np
@@ -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_per_layer="uint48", num_channels=3)
150+
ds.add_layer("color", Layer.COLOR_TYPE, 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")
@@ -696,7 +696,9 @@ def test_tiled_tiff_read_and_write_multichannel():
696696
pattern="{xxx}_{yyy}_{zzz}.tif",
697697
)
698698

699-
mag = tiled_tiff_ds.add_layer("color", "color", num_channels=3).add_mag("1")
699+
mag = tiled_tiff_ds.add_layer("color", Layer.COLOR_TYPE, num_channels=3).add_mag(
700+
"1"
701+
)
700702

701703
data = get_multichanneled_data(np.uint8)
702704

@@ -715,7 +717,7 @@ def test_tiled_tiff_read_and_write():
715717
pattern="{xxx}_{yyy}_{zzz}.tif",
716718
)
717719

718-
mag = tiled_tiff_ds.add_layer("color", "color").add_mag("1")
720+
mag = tiled_tiff_ds.add_layer("color", Layer.COLOR_TYPE).add_mag("1")
719721

720722
data = np.zeros((250, 200, 10), dtype=np.uint8)
721723
for h in range(10):
@@ -812,11 +814,11 @@ def test_largest_segment_id_requirement():
812814
ds = WKDataset.create(path, scale=(10, 10, 10))
813815

814816
with pytest.raises(AssertionError):
815-
ds.add_layer("segmentation", "segmentation")
817+
ds.add_layer("segmentation", Layer.SEGMENTATION_TYPE)
816818

817819
largest_segment_id = 10
818820
ds.add_layer(
819-
"segmentation", "segmentation", largest_segment_id=largest_segment_id
821+
"segmentation", Layer.SEGMENTATION_TYPE, largest_segment_id=largest_segment_id
820822
).add_mag(Mag(1))
821823

822824
ds = WKDataset(path)
@@ -1018,7 +1020,7 @@ def test_view_write_without_open():
10181020
delete_dir("./testoutput/wk_dataset_write_without_open")
10191021

10201022
ds = WKDataset.create("./testoutput/wk_dataset_write_without_open", scale=(1, 1, 1))
1021-
ds.add_layer("color", "color")
1023+
ds.add_layer("color", Layer.COLOR_TYPE)
10221024

10231025
ds.get_layer("color").add_mag("1")
10241026

@@ -1214,7 +1216,7 @@ def test_view_offsets():
12141216
delete_dir("./testoutput/wk_offset_tests")
12151217

12161218
ds = WKDataset.create("./testoutput/wk_offset_tests", scale=(1, 1, 1))
1217-
mag = ds.add_layer("color", "color").add_mag("1")
1219+
mag = ds.add_layer("color", Layer.COLOR_TYPE).add_mag("1")
12181220

12191221
# The dataset is new -> no data has been written.
12201222
# Therefore, the size of the bounding box in the properties.json is (0, 0, 0)
@@ -1288,12 +1290,14 @@ def test_adding_layer_with_invalid_dtype_per_layer():
12881290
ds = WKDataset.create("./testoutput/invalid_dtype", scale=(1, 1, 1))
12891291
with pytest.raises(TypeError):
12901292
# 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)
1293+
ds.add_layer(
1294+
"color", Layer.COLOR_TYPE, dtype_per_layer="uint30", num_channels=3
1295+
)
12921296
with pytest.raises(TypeError):
12931297
# "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)
1298+
ds.add_layer("color", Layer.COLOR_TYPE, dtype_per_layer="int", num_channels=3)
12951299
ds.add_layer(
1296-
"color", "color", dtype_per_layer="int", num_channels=4
1300+
"color", Layer.COLOR_TYPE, dtype_per_layer="int", num_channels=4
12971301
) # "int"/"int64" works with 4 channels
12981302

12991303

@@ -1485,3 +1489,39 @@ def test_add_symlink_layer():
14851489

14861490
assert np.array_equal(mag.read(size=(10, 10, 10)), write_data)
14871491
assert np.array_equal(original_mag.read(size=(10, 10, 10)), write_data)
1492+
1493+
1494+
def test_search_dataset_also_for_long_layer_name():
1495+
delete_dir("./testoutput/long_layer_name")
1496+
1497+
ds = WKDataset.create("./testoutput/long_layer_name", scale=(1, 1, 1))
1498+
mag = ds.add_layer("color", Layer.COLOR_TYPE).add_mag("2")
1499+
1500+
assert mag.name == "2"
1501+
short_mag_file_path = join(ds.path, "color", Mag(mag.name).to_layer_name())
1502+
long_mag_file_path = join(ds.path, "color", Mag(mag.name).to_long_layer_name())
1503+
1504+
assert os.path.exists(short_mag_file_path)
1505+
assert not os.path.exists(long_mag_file_path)
1506+
1507+
write_data = (np.random.rand(10, 10, 10) * 255).astype(np.uint8)
1508+
mag.write(write_data, offset=(10, 10, 10))
1509+
1510+
assert np.array_equal(
1511+
mag.read(offset=(10, 10, 10), size=(10, 10, 10)), np.expand_dims(write_data, 0)
1512+
)
1513+
1514+
# rename the path from "long_layer_name/color/2" to "long_layer_name/color/2-2-2"
1515+
os.rename(short_mag_file_path, long_mag_file_path)
1516+
1517+
with pytest.raises(WKWException):
1518+
# the dataset has to be reopened to notice the changed directory
1519+
mag.read(offset=(10, 10, 10), size=(10, 10, 10))
1520+
1521+
# when opening the dataset, it searches both for the long and the short path
1522+
layer = WKDataset("./testoutput/long_layer_name").get_layer("color")
1523+
mag = layer.get_mag("2")
1524+
assert np.array_equal(
1525+
mag.read(offset=(10, 10, 10), size=(10, 10, 10)), np.expand_dims(write_data, 0)
1526+
)
1527+
layer.delete_mag("2")

wkcuber/api/Layer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
WKMagDataset,
1313
TiffMagDataset,
1414
TiledTiffMagDataset,
15+
find_mag_path_on_disk,
1516
)
1617
from wkcuber.mag import Mag
1718
from wkcuber.utils import DEFAULT_WKW_FILE_LEN
@@ -48,7 +49,7 @@ def delete_mag(self, mag):
4849
del self.mags[mag]
4950
self.dataset.properties._delete_mag(self.name, mag)
5051
# delete files on disk
51-
full_path = join(self.dataset.path, self.name, mag)
52+
full_path = find_mag_path_on_disk(self.dataset.path, self.name, mag)
5253
rmtree(full_path)
5354

5455
def _create_dir_for_mag(self, mag):
@@ -138,7 +139,9 @@ def setup_mag(self, mag):
138139

139140
self._assert_mag_does_not_exist_yet(mag)
140141

141-
with wkw.Dataset.open(join(self.dataset.path, self.name, mag)) as wkw_dataset:
142+
with wkw.Dataset.open(
143+
find_mag_path_on_disk(self.dataset.path, self.name, mag)
144+
) as wkw_dataset:
142145
wk_header = wkw_dataset.header
143146

144147
self.mags[mag] = WKMagDataset(

wkcuber/api/MagDataset.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from os.path import join
23

34
from wkw import wkw
@@ -9,6 +10,16 @@
910
from wkcuber.mag import Mag
1011

1112

13+
def find_mag_path_on_disk(dataset_path: str, layer_name: str, mag_name: str):
14+
mag = Mag(mag_name)
15+
short_mag_file_path = join(dataset_path, layer_name, mag.to_layer_name())
16+
long_mag_file_path = join(dataset_path, layer_name, mag.to_long_layer_name())
17+
if os.path.exists(short_mag_file_path):
18+
return short_mag_file_path
19+
else:
20+
return long_mag_file_path
21+
22+
1223
class MagDataset:
1324
def __init__(self, layer, name):
1425
self.layer = layer
@@ -99,7 +110,9 @@ def get_view(self, size=None, offset=None, is_bounded=True):
99110
f"Use is_bounded=False if you intend to write outside out the existing bounding box."
100111
)
101112

102-
mag_file_path = join(self.layer.dataset.path, self.layer.name, self.name)
113+
mag_file_path = find_mag_path_on_disk(
114+
self.layer.dataset.path, self.layer.name, self.name
115+
)
103116
return self._get_view_type()(
104117
mag_file_path, self.header, size, offset, is_bounded
105118
)

wkcuber/api/Properties/DatasetProperties.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
SegmentationLayerProperties,
66
LayerProperties,
77
)
8-
from wkcuber.api.Properties.ResolutionProperties import WkResolution, TiffResolution
8+
from wkcuber.api.Properties.ResolutionProperties import WkResolution, Resolution
99
from wkcuber.mag import Mag
1010

1111

@@ -155,11 +155,11 @@ def _from_json(cls, path) -> Properties:
155155
for layer in data["dataLayers"]:
156156
if layer["category"] == Layer.SEGMENTATION_TYPE:
157157
data_layers[layer["name"]] = SegmentationLayerProperties._from_json(
158-
layer, TiffResolution, path
158+
layer, Resolution, path
159159
)
160160
else:
161161
data_layers[layer["name"]] = LayerProperties._from_json(
162-
layer, TiffResolution, path
162+
layer, Resolution, path
163163
)
164164

165165
return cls(
@@ -196,5 +196,5 @@ def _add_mag(self, layer_name, mag):
196196
for res in self.data_layers[layer_name].wkw_magnifications
197197
]
198198
):
199-
self.data_layers[layer_name]._add_resolution(TiffResolution(mag))
199+
self.data_layers[layer_name]._add_resolution(Resolution(mag))
200200
self._export_as_json()

wkcuber/api/Properties/LayerProperties.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ def _add_resolution(self, resolution):
106106
self._wkw_magnifications.append(resolution)
107107

108108
def _delete_resolution(self, resolution):
109-
self._wkw_magnifications.delete(resolution)
109+
resolutions_to_delete = [
110+
res for res in self._wkw_magnifications if res.mag == Mag(resolution)
111+
]
112+
for res in resolutions_to_delete:
113+
self._wkw_magnifications.remove(res)
110114

111115
def get_bounding_box(self) -> BoundingBox:
112116

wkcuber/api/Properties/ResolutionProperties.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,6 @@
22

33

44
class Resolution:
5-
def _to_json(self) -> dict:
6-
pass
7-
8-
@classmethod
9-
def _from_json(cls, json_data):
10-
pass
11-
12-
13-
class TiffResolution(Resolution):
145
def __init__(self, mag):
156
self._mag = Mag(mag)
167

@@ -28,7 +19,7 @@ def mag(self) -> Mag:
2819

2920
class WkResolution(Resolution):
3021
def __init__(self, mag, cube_length):
31-
self._mag = Mag(mag)
22+
super().__init__(mag)
3223
self._cube_length = cube_length
3324

3425
def _to_json(self) -> dict:

0 commit comments

Comments
 (0)