Skip to content

Commit 44d6e8b

Browse files
authored
Add various improvements to nifti conversion and fix tiff-api transpose bug (#222)
* add various improvements to nifti conversion * fix transpose error in high-level tiff api * refactor and clean up convert-nifti code further * format * refactor wkw constants * allow to flip nifti data again with --flip_axes * refactor bounding box parsing * format * format * try to fix CI by downgrading pyyaml see: actions/runner-images#1202 * remove pyyaml dependency * fix linting * fix transpose again * format
1 parent 0f7c5bc commit 44d6e8b

File tree

9 files changed

+310
-114
lines changed

9 files changed

+310
-114
lines changed

poetry.lock

Lines changed: 1 addition & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ python = "^3.6"
1010
scipy = "^1.4.0"
1111
numpy = "^1.17.4"
1212
pillow = "^6.2.1"
13-
pyyaml = "^5.2"
1413
wkw = "0.1.2"
1514
requests = "^2.22.0"
1615
cluster_tools = "1.49"

tests/test_pad_or_crop.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
from wkcuber.utils import pad_or_crop_to_size_and_topleft
3+
4+
5+
def test_pad_or_crop_to_size_and_topleft():
6+
target_topleft = np.array((0, 50, 36, 1))
7+
target_size = np.array((1, 156, 112, 30))
8+
9+
test_shapes = [(1, 117, 95, 16), (1, 128, 128, 16), (1, 196, 196, 12)]
10+
expected_voxel_counts = [117 * 95 * 16, 128 * 112 * 16, 156 * 112 * 12]
11+
12+
for shape, expected_voxel_count in zip(test_shapes, expected_voxel_counts):
13+
cube_data = np.ones(shape)
14+
cube_data = pad_or_crop_to_size_and_topleft(
15+
cube_data, target_size, target_topleft
16+
)
17+
assert cube_data.shape[1:3] == tuple((target_size + target_topleft)[1:3])
18+
19+
cube_data_from_top_left = cube_data[
20+
:, target_topleft[1] :, target_topleft[2] :, :
21+
]
22+
cube_data_from_top_left_to_size = cube_data_from_top_left[
23+
:, : target_size[1], : target_size[2], :
24+
]
25+
assert cube_data_from_top_left.shape[0:3] == tuple(target_size)[0:3]
26+
assert np.sum(cube_data) == expected_voxel_count
27+
assert np.sum(cube_data_from_top_left_to_size) == expected_voxel_count

wkcuber/api/Layer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
TiledTiffMagDataset,
1111
)
1212
from wkcuber.mag import Mag
13+
from wkcuber.utils import DEFAULT_WKW_FILE_LEN
1314

1415

1516
class Layer:
@@ -68,7 +69,7 @@ def add_mag(
6869
if block_len is None:
6970
block_len = 32
7071
if file_len is None:
71-
file_len = 32
72+
file_len = DEFAULT_WKW_FILE_LEN
7273
if block_type is None:
7374
block_type = wkw.Header.BLOCK_TYPE_RAW
7475

wkcuber/api/TiffData/TiffMag.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def assert_correct_data_format(self, data):
352352
if self.has_only_one_channel():
353353
if not len(data.shape) == 3:
354354
raise AttributeError(
355-
"The shape of the provided data does not match the expected shape."
355+
"The shape of the provided data does not match the expected shape. Expected three-dimensional data shape, since target data is single-channel."
356356
)
357357
else:
358358
if not len(data.shape) == 4:
@@ -399,6 +399,15 @@ def __init__(
399399
self.tile_size = tile_size
400400

401401

402+
def transpose_for_skimage(data):
403+
if len(data.shape) == 2:
404+
return data.transpose()
405+
elif len(data.shape) == 3:
406+
return data.transpose((1, 0, 2))
407+
else:
408+
raise ValueError("Cannot handle shape for data.")
409+
410+
402411
class TiffReader:
403412
def __init__(self, file_name):
404413
self.file_name = file_name
@@ -414,11 +423,12 @@ def open(cls, file_name):
414423
return cls(file_name)
415424

416425
def read(self) -> np.array:
417-
return io.imread(self.file_name)
426+
data = io.imread(self.file_name)
427+
return transpose_for_skimage(data)
418428

419429
def write(self, pixels):
420430
os.makedirs(os.path.dirname(self.file_name), exist_ok=True)
421-
io.imsave(self.file_name, pixels, check_contrast=False)
431+
io.imsave(self.file_name, transpose_for_skimage(pixels), check_contrast=False)
422432

423433
def merge_with_image(self, foreground_pixels, offset):
424434
background_pixels = self.read()

wkcuber/api/bounding_box.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,20 @@ def from_checkpoint_name(checkpoint_name: str) -> "BoundingBox":
7575
size = bbox_tuple[3:6]
7676
return BoundingBox.from_tuple2((topleft, size))
7777

78+
@staticmethod
79+
def from_csv(csv_bbox: str) -> "BoundingBox":
80+
bbox_tuple = tuple(int(x) for x in csv_bbox.split(","))
81+
return BoundingBox.from_tuple6(bbox_tuple)
82+
7883
@staticmethod
7984
def from_auto(obj) -> "BoundingBox":
8085
if isinstance(obj, BoundingBox):
8186
return obj
8287
elif isinstance(obj, str):
83-
return BoundingBox.from_auto(json.loads(obj))
88+
if ":" in obj:
89+
return BoundingBox.from_auto(json.loads(obj))
90+
else:
91+
return BoundingBox.from_csv(obj)
8492
elif isinstance(obj, dict):
8593
return BoundingBox.from_wkw(obj)
8694
elif isinstance(obj, BoundingBoxNamedTuple):

0 commit comments

Comments
 (0)