Skip to content

Commit ad0f4b5

Browse files
youri-krschwanhold
andauthored
[wkcuber] Make tiff and czi reading more robust (#335)
* use different indexing for tiff reading * formatting * adapt czi reading and include new z axis names * pr feedback 2, includes new channel and sample index * add new config options for power users * fix cli interface * add tests * fix typo in test * pr feedback * remove method artifact * fix test syntax * add debuging * add dependency * remove unnecessary debugging Co-authored-by: Robert S <[email protected]>
1 parent 0e64c95 commit ad0f4b5

File tree

16 files changed

+860
-259
lines changed

16 files changed

+860
-259
lines changed

wkcuber/Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ For upgrade instructions, please check the respective *Breaking Changes* section
2828
- Adjust downsampling scheme to always try to minimize the scaled difference between the different dimensions of a mag and renamed the sampling mode `auto` to `anisotropic`. [#391](https://github.com/scalableminds/webknossos-libs/pull/391)
2929
- Make parameter `executor` optional for `View.for_each_chunk` and `View.for_zipped_chunks`. [#404](https://github.com/scalableminds/webknossos-libs/pull/404)
3030
- Add option to rename foreign layer with add_{symlink,copy}_layer. [#419](https://github.com/scalableminds/webknossos-libs/pull/419)
31+
- Improved the `TIFF` and `CZI` reader to work with a wider variety of formats. The module `convert_image_stack_to_wkw` is now capable of making the result webKnossos compatible. [#335](https://github.com/scalableminds/webknossos-libs/pull/335)
3132

3233
### Fixed
3334
- Reverted that `dataset.add_symlink_layer` and `dataset.add_copy_layer` resolved the layer path if it was a symlink. [#408](https://github.com/scalableminds/webknossos-libs/pull/408)
5.05 MB
Binary file not shown.
15.1 MB
Binary file not shown.
2.01 MB
Binary file not shown.
6.01 MB
Binary file not shown.

wkcuber/tests/scripts/all_tests.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ rm -r testdata/tiff_mag_2_reference
1818
sh ${BASEDIR}/anisotropic_downsampling.sh
1919
sh ${BASEDIR}/compression_and_verification.sh
2020
rm -r testoutput/tiff_compress
21+
rm -r testoutput/tiff_compress_broken
2122

2223
sh ${BASEDIR}/in_place_compression.sh
2324
rm -r testoutput/tiff_compress2
25+
rm -r testoutput/tiff_compress2.bak
2426
rm -r testoutput/tiff
2527

2628
sh ${BASEDIR}/tile_cubing.sh
@@ -32,5 +34,8 @@ rm -r testoutput/tiff2
3234
sh ${BASEDIR}/simple_tiff_cubing_no_compression.sh
3335
rm -r testoutput/tiff3
3436

37+
sh ${BASEDIR}/tiff_formats_cubing.sh
38+
rm -r testoutput/tiff4
39+
3540
sh ${BASEDIR}/knossos_conversion.sh
3641
rm -r testoutput/knossos

wkcuber/tests/scripts/compression_and_verification.sh

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@ echo "Check equality for uncompressed and compressed dataset"
1616
python -m wkcuber.check_equality testoutput/tiff testoutput/tiff_compress
1717

1818
echo "Create broken copy of dataset"
19-
rm -rf testoutput/tiff_compress-broken
20-
cp -R testoutput/tiff_compress testoutput/tiff_compress-broken
21-
rm -r testoutput/tiff_compress-broken/color/1/z0/y0/x0.wkw
19+
cp -R testoutput/tiff_compress testoutput/tiff_compress_broken
20+
rm -r testoutput/tiff_compress_broken/color/1/z0/y0/x0.wkw
2221

2322
echo "Compare original dataset to broken one and expect to determine difference"
24-
if python -m wkcuber.check_equality testoutput/tiff testoutput/tiff_compress-broken ; then
23+
if python -m wkcuber.check_equality testoutput/tiff testoutput/tiff_compress_broken ; then
2524
echo "Equality check did not fail even though the dataset is broken."
2625
exit 1
2726
else
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env bash
2+
set -xe
3+
mkdir -p testoutput/tiff4
4+
5+
# simplest case: Only XY and I (alternative Z axis name) axis
6+
python -m wkcuber.convert_image_stack_to_wkw \
7+
--jobs 2 \
8+
--batch_size 8 \
9+
--layer_name color \
10+
--max_mag 4 \
11+
--target_mag 2\
12+
--scale 1,1,1 \
13+
--name awesome_data \
14+
--no_compress \
15+
--wkw_file_len 8 \
16+
testdata/various_tiff_formats/test_I.tif testoutput/tiff4
17+
[ -d testoutput/tiff4/color ]
18+
[ -d testoutput/tiff4/color/2 ]
19+
[ $(find testoutput/tiff4/color/2 -mindepth 3 -name "*.wkw" | wc -l) -eq 1 ]
20+
[ -e testoutput/tiff4/datasource-properties.json ]
21+
rm -r testoutput/tiff4/*
22+
23+
# to make output wk_compatible, these files require multiple layer
24+
python -m wkcuber.convert_image_stack_to_wkw \
25+
--jobs 2 \
26+
--batch_size 8 \
27+
--layer_name color \
28+
--max_mag 1 \
29+
--scale 1,1,1 \
30+
--name awesome_data \
31+
--no_compress \
32+
--wkw_file_len 8 \
33+
testdata/various_tiff_formats/test_C.tif testoutput/tiff4
34+
[ -d testoutput/tiff4/color_0 ]
35+
[ -d testoutput/tiff4/color_1 ]
36+
[ -d testoutput/tiff4/color_2 ]
37+
[ -d testoutput/tiff4/color_3 ]
38+
[ -d testoutput/tiff4/color_4 ]
39+
[ -d testoutput/tiff4/color_0/1 ]
40+
[ $(find testoutput/tiff4/color_0/1 -mindepth 3 -name "*.wkw" | wc -l) -eq 1 ]
41+
[ -e testoutput/tiff4/datasource-properties.json ]
42+
rm -r testoutput/tiff4/*
43+
44+
python -m wkcuber.convert_image_stack_to_wkw \
45+
--jobs 2 \
46+
--batch_size 8 \
47+
--layer_name color \
48+
--max_mag 1 \
49+
--scale 1,1,1 \
50+
--name awesome_data \
51+
--no_compress \
52+
--wkw_file_len 8 \
53+
testdata/various_tiff_formats/test_S.tif testoutput/tiff4
54+
[ -d testoutput/tiff4/color_0 ]
55+
[ -d testoutput/tiff4/color_1 ]
56+
[ -d testoutput/tiff4/color_2 ]
57+
[ -d testoutput/tiff4/color_0/1 ]
58+
[ $(find testoutput/tiff4/color_0/1 -mindepth 3 -name "*.wkw" | wc -l) -eq 1 ]
59+
[ -e testoutput/tiff4/datasource-properties.json ]
60+
rm -r testoutput/tiff4/*
61+
62+
python -m wkcuber.convert_image_stack_to_wkw \
63+
--jobs 2 \
64+
--batch_size 8 \
65+
--layer_name color \
66+
--max_mag 1 \
67+
--scale 1,1,1 \
68+
--name awesome_data \
69+
--no_compress \
70+
--wkw_file_len 8 \
71+
testdata/various_tiff_formats/test_CS.tif testoutput/tiff4
72+
[ -d testoutput/tiff4/color_0 ]
73+
[ -d testoutput/tiff4/color_1 ]
74+
[ -d testoutput/tiff4/color_2 ]
75+
[ -d testoutput/tiff4/color_3 ]
76+
[ -d testoutput/tiff4/color_4 ]
77+
[ -d testoutput/tiff4/color_0/1 ]
78+
[ $(find testoutput/tiff4/color_0/1 -mindepth 3 -name "*.wkw" | wc -l) -eq 1 ]
79+
[ -e testoutput/tiff4/datasource-properties.json ]
80+
rm -r testoutput/tiff4/*
81+
82+
# test wk incompatible configs, program should fail because force parameter was not given
83+
if python -m wkcuber.convert_image_stack_to_wkw \
84+
--jobs 2 \
85+
--batch_size 8 \
86+
--layer_name color \
87+
--max_mag 1 \
88+
--scale 1,1,1 \
89+
--prefer_channels \
90+
--name awesome_data \
91+
--no_compress \
92+
--wkw_file_len 8 \
93+
testdata/various_tiff_formats/test_C.tif testoutput/tiff4; then
94+
echo "Conversion worked although invalid config should have been detected."
95+
exit 1
96+
else
97+
echo "Conversion did not work as expected due to invalid config."
98+
fi
99+
100+
# power user configuration: should only create single layer
101+
python -m wkcuber.convert_image_stack_to_wkw \
102+
--jobs 2 \
103+
--batch_size 8 \
104+
--layer_name color \
105+
--max_mag 1 \
106+
--scale 1,1,1 \
107+
--channel_index 3 \
108+
--sample_index 2 \
109+
--name awesome_data \
110+
--no_compress \
111+
--wkw_file_len 8 \
112+
testdata/various_tiff_formats/test_CS.tif testoutput/tiff4
113+
[ -d testoutput/tiff4/color ]
114+
[ -d testoutput/tiff4/color/1 ]
115+
[ $(find testoutput/tiff4/color/1 -mindepth 3 -name "*.wkw" | wc -l) -eq 1 ]
116+
[ -e testoutput/tiff4/datasource-properties.json ]

wkcuber/tests/test_image_readers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_single_channel_conversion() -> None:
2727
single_channel_data = np.empty((3, 32, 32, 1, 1), multi_channel_data.dtype)
2828
for i in range(3):
2929
single_channel_data[i] = image_reader_manager.read_array(
30-
TESTDATA_DIR / "rgb_tiff" / "test_rgb.tif", np.uint8, 0, i
30+
TESTDATA_DIR / "rgb_tiff" / "test_rgb.tif", np.uint8, 0, 0, i
3131
)
3232

3333
single_channel_data = single_channel_data.transpose((1, 2, 0, 3, 4))

wkcuber/wkcuber/__main__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def detect_present_mags(target_path: Path) -> Dict[Path, List[Mag]]:
2626
mag_paths = list([p for p in layer_p.iterdir() if p.is_dir()])
2727
for mag_p in mag_paths:
2828
try:
29-
mag = Mag(mag_p.stem)
29+
mag = Mag(mag_p.name)
3030
except (AssertionError, ValueError) as _:
3131
continue
3232
layer_path_to_mags[layer_p].append(mag)
@@ -80,12 +80,12 @@ def main(args: Namespace) -> None:
8080

8181
if not args.no_compress:
8282
for (layer_path, mags) in layer_path_to_mags.items():
83-
layer_name = layer_path.stem
83+
layer_name = layer_path.name
8484
for mag in mags:
8585
compress_mag_inplace(args.target_path, layer_name, mag, args)
8686

8787
for (layer_path, mags) in layer_path_to_mags.items():
88-
layer_name = layer_path.stem
88+
layer_name = layer_path.name
8989
mags.sort()
9090
downsample_mags(
9191
path=args.target_path,

0 commit comments

Comments
 (0)