From 6269a11995814f5a14891b8e67aa4fb616b103fb Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 7 Nov 2023 16:58:43 +0100 Subject: [PATCH 01/41] Started debuging for reading nd datasets. --- .../script_collection/reading_nd_data.py | 22 ++++++++++++++++++ webknossos/testdata/4D/4D-series.ome.tif | Bin 0 -> 2629919 bytes .../webknossos/dataset/_utils/pims_images.py | 1 + webknossos/webknossos/dataset/dataset.py | 1 + 4 files changed, 24 insertions(+) create mode 100644 webknossos/script_collection/reading_nd_data.py create mode 100644 webknossos/testdata/4D/4D-series.ome.tif diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py new file mode 100644 index 000000000..6538490ec --- /dev/null +++ b/webknossos/script_collection/reading_nd_data.py @@ -0,0 +1,22 @@ +from pathlib import Path + +import pims + +import webknossos as wk + + +def main(input_path: Path, output_path: Path) -> None: + """Imports a dataset with more than 3 dimensions.""" + + wk.Dataset.from_images( + input_path, output_path, voxel_size=(10, 10, 10), data_format="zarr3" + ) + # reader = pims.Bioformats(input_path) + # print(reader.sizes) + # print(isinstance(reader, pims.FramesSequenceND)) + + +if __name__ == "__main__": + input_path = Path(".") / "webknossos" / "testdata" / "4D" # / "4D-series.ome.tif" + output_path = Path(".") / "webknossos" / "testoutput" / "4D" + main(input_path, output_path) diff --git a/webknossos/testdata/4D/4D-series.ome.tif b/webknossos/testdata/4D/4D-series.ome.tif new file mode 100644 index 0000000000000000000000000000000000000000..f957ee3807e1d0720bf909c902b912d706fb0ef5 GIT binary patch literal 2629919 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 literal 0 HcmV?d00001 diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 5dd0a8914..03b8e62b3 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -142,6 +142,7 @@ def __init__( self.dtype = images.dtype if isinstance(images, pims.FramesSequenceND): + # TODO: assertion that phrohibites nd data assert all( axis in "xyzct" for axis in images.axes ), f"Found unknown axes {set(images.axes) - set('xyzct')}" diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index e895cad1f..64f546a3c 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1243,6 +1243,7 @@ def add_layer_from_images( z_end = min(z_start + batch_size, pims_images.expected_shape.z) # return shapes and set to union when using --pad args.append((z_start, z_end)) + print(args) with warnings.catch_warnings(): # Block alignmnent within the dataset should not be a problem, since shard-wise chunking is enforced. # However, dataset borders might change between different parallelized writes, when sizes differ. From f891606f9c00dba8d603260a23474679f0dc3b7f Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 23 Nov 2023 10:08:52 +0100 Subject: [PATCH 02/41] Implementation of VecNInt and NDBoundingBox. --- .../webknossos/geometry/bounding_box.py | 69 +--- .../webknossos/geometry/nd_bounding_box.py | 375 ++++++++++++++++++ webknossos/webknossos/geometry/vec3_int.py | 143 +------ webknossos/webknossos/geometry/vecn_int.py | 190 +++++++++ 4 files changed, 598 insertions(+), 179 deletions(-) create mode 100644 webknossos/webknossos/geometry/nd_bounding_box.py create mode 100644 webknossos/webknossos/geometry/vecn_int.py diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 78a38e15c..8fc57f810 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -7,13 +7,14 @@ import numpy as np from .mag import Mag +from .nd_bounding_box import NDBoundingBox from .vec3_int import Vec3Int, Vec3IntLike _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" @attr.frozen -class BoundingBox: +class BoundingBox(NDBoundingBox): """ This class is used to represent an axis-aligned cuboid in 3D. The top-left coordinate is inclusive and the bottom-right coordinate is exclusive. @@ -32,6 +33,7 @@ class BoundingBox: topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) + axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True @@ -51,61 +53,38 @@ def __attrs_post_init__(self) -> None: # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) - def with_topleft(self, new_topleft: Vec3IntLike) -> "BoundingBox": - return attr.evolve(self, topleft=new_topleft) + def with_additional_axis(self, name: str, extent: Tuple[int, int]) -> "NDBoundingBox": + assert (name not in ["x", "y", "z"]), f"The name '{name}' of the axis is already taken." + new_topleft = min(extent) + new_size = max(extent) - new_topleft - def with_size(self, new_size: Vec3IntLike) -> "BoundingBox": - return attr.evolve(self, size=new_size) - - def with_name(self, name: Optional[str]) -> "BoundingBox": - return attr.evolve(self, name=name) - - def with_is_visible(self, is_visible: bool) -> "BoundingBox": - return attr.evolve(self, is_visible=is_visible) - - def with_color( - self, color: Optional[Tuple[float, float, float, float]] - ) -> "BoundingBox": - return attr.evolve(self, color=color) + return NDBoundingBox( + topleft=(*self.topleft, new_topleft), + size=(*self.size, new_size), + axes=(*self.axes, name) + ) def with_bounds_x( self, new_topleft_x: Optional[int] = None, new_size_x: Optional[int] = None ) -> "BoundingBox": """Returns a copy of the bounding box with topleft.x optionally replaced and size.x optionally replaced.""" - new_topleft = ( - self.topleft.with_x(new_topleft_x) - if new_topleft_x is not None - else self.topleft - ) - new_size = self.size.with_x(new_size_x) if new_size_x is not None else self.size - return attr.evolve(self, topleft=new_topleft, size=new_size) + return cast(BoundingBox, self.with_bounds("x", new_topleft_x, new_size_x)) def with_bounds_y( self, new_topleft_y: Optional[int] = None, new_size_y: Optional[int] = None ) -> "BoundingBox": """Returns a copy of the bounding box with topleft.y optionally replaced and size.y optionally replaced.""" - new_topleft = ( - self.topleft.with_y(new_topleft_y) - if new_topleft_y is not None - else self.topleft - ) - new_size = self.size.with_y(new_size_y) if new_size_y is not None else self.size - return attr.evolve(self, topleft=new_topleft, size=new_size) + return cast(BoundingBox, self.with_bounds("y", new_topleft_y, new_size_y)) def with_bounds_z( self, new_topleft_z: Optional[int] = None, new_size_z: Optional[int] = None ) -> "BoundingBox": """Returns a copy of the bounding box with topleft.z optionally replaced and size.z optionally replaced.""" - new_topleft = ( - self.topleft.with_z(new_topleft_z) - if new_topleft_z is not None - else self.topleft - ) - new_size = self.size.with_z(new_size_z) if new_size_z is not None else self.size - return attr.evolve(self, topleft=new_topleft, size=new_size) + return cast(BoundingBox, self.with_bounds("z", new_topleft_z, new_size_z)) + @classmethod def from_wkw_dict(cls, bbox: Dict) -> "BoundingBox": @@ -231,18 +210,7 @@ def to_csv(self) -> str: return ",".join(map(str, self.to_tuple6())) def __repr__(self) -> str: - return "BoundingBox(topleft={}, size={})".format( - str(tuple(self.topleft)), str(tuple(self.size)) - ) - - def __str__(self) -> str: - return self.__repr__() - - def __eq__(self, other: object) -> bool: - if isinstance(other, BoundingBox): - return self.topleft == other.topleft and self.size == other.size - else: - raise NotImplementedError() + return f"BoundingBox(topleft={self.topleft.to_tuple()}, size={self.size.to_tuple()})" def padded_with_margins( self, margins_left: Vec3IntLike, margins_right: Optional[Vec3IntLike] = None @@ -427,9 +395,6 @@ def chunk( ): yield BoundingBox([x, y, z], chunk_shape).intersected_with(self) - def volume(self) -> int: - return self.size.prod() - def slice_array(self, array: np.ndarray) -> np.ndarray: return array[ self.topleft.x : self.bottomright.x, diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py new file mode 100644 index 000000000..95f8e58cd --- /dev/null +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -0,0 +1,375 @@ +import re +from collections import defaultdict +from itertools import product +from typing import Dict, Generator, Iterable, List, Optional, Tuple, Union, cast + +import attr +import numpy as np + +from .mag import Mag +from .vec3_int import Vec3Int +from .vecn_int import VecNInt, VecNIntLike + +_DEFAULT_BBOX_NAME = "Unnamed Bounding Box" + +@attr.frozen +class NDBoundingBox: + """ + This class is used to represent an axis-aligned cuboid in N-D. + The top-left coordinate is inclusive and the bottom-right coordinate is exclusive. + + A small usage example: + + ```python + from webknossos import NDBoundingBox + + bbox_1 = NDBoundingBox(top_left=(0, 0, 0), size=(100, 100, 100), axes=("x", "y", "z")) + bbox_2 = NDBoundingBox(top_left=(75, 75, 75, 0), size=(100, 100, 100, 20), axes=("x", "y", "z", "t")) + + ``` + """ + + topleft: VecNInt = attr.field(converter=VecNInt) + size: VecNInt = attr.field(converter=VecNInt) + axes: Tuple[str, ...] = attr.field(converter=tuple) + bottomright: VecNInt = attr.field(init=False) + name: Optional[str] = _DEFAULT_BBOX_NAME + is_visible: bool = True + color: Optional[Tuple[float, float, float, float]] = None + + def __attrs_post_init__(self) -> None: + assert len(self.topleft) == len(self.size) == len(self.axes), ( + f"The dimensions of topleft, size and axes ({len(self.topleft)}, " + + f"{len(self.size)} and {len(self.axes)} dimensions) do not match." + ) + + # Bring topleft and size in required order ('x', 'y', 'z', ...) + try: + source = [self.axes.index('x'), self.axes.index('y'), self.axes.index('z')] + except ValueError as err: + raise ValueError("There are at least 3 dimensions needed with names `x`, `y` and `z`.") from err + target = [1,2,3] + self.size.moveaxis(source, target) + self.topleft.moveaxis(source, target) + object.__setattr__(self, "axes", ("x", "y", "z", *(e for e in self.axes if e not in ["x", "y", "z"]))) + + if not self.size.is_positive(): + # Flip the size in negative dimensions, so that the topleft is smaller than bottomright. + # E.g. BoundingBox((10, 10, 10), (-5, 5, 5)) -> BoundingBox((5, 10, 10), (5, 5, 5)). + negative_size = (min(0, value) for value in self.size) + new_topleft = (val1 + val2 for val1, val2 in zip(self.topleft, negative_size)) + new_size = (max(value, -value) for value in self.size) + object.__setattr__(self, "topleft", new_topleft) + object.__setattr__(self, "size", new_size) + + + # Compute bottomright to avoid that it's recomputed every time + # it is needed. + object.__setattr__(self, "bottomright", self.topleft + self.size) + + def with_additional_axis(self, name: str, extent: Tuple[int, int]) -> "NDBoundingBox": + assert name not in self.axes, "The identifier of the axis is already taken." + start, end = extent + return attr.evolve( + self, + topleft=(*self.topleft, start), + size=(*self.size, end - start), + axes=(*self.axes, name) + ) + + def with_name(self, name: Optional[str]) -> "NDBoundingBox": + return attr.evolve(self, name=name) + + def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": + return attr.evolve(self, is_visible=is_visible) + + def with_color( + self, color: Optional[Tuple[float, float, float, float]] + ) -> "NDBoundingBox": + return attr.evolve(self, color=color) + + def with_bounds(self, axis: str, new_topleft: Optional[int], new_size: Optional[int]) -> "NDBoundingBox": + try: + index = self.axes.index(axis) + except ValueError as err: + raise ValueError("The given axis name does not exist.") from err + + _new_topleft = ( + self.topleft.with_replaced(index, new_topleft) + if new_topleft is not None + else self.topleft + ) + _new_size = ( + self.size.with_replaced(index, new_size) + if new_size is not None + else self.size + ) + + return attr.evolve(self, topleft=_new_topleft, size=_new_size) + + @classmethod + def from_checkpoint_name(cls, checkpoint_name: str) -> "NDBoundingBox": + """This function extracts a bounding box in the format `x_y_z_sx_sy_xz` which is contained in a string.""" + regex = r"(([0-9]+_){5}([0-9]+))" + match = re.search(regex, checkpoint_name) + assert ( + match is not None + ), f"Could not extract bounding box from {checkpoint_name}" + bbox_tuple = tuple(int(value) for value in match.group().split("_")) + return cls.from_tuple6(cast(Tuple[int, int, int, int, int, int], bbox_tuple)) + + @classmethod + def from_csv(cls, csv_bbox: str) -> "NDBoundingBox": + bbox_tuple = tuple(int(x) for x in csv_bbox.split(",")) + return cls.from_tuple6(cast(Tuple[int, int, int, int, int, int], bbox_tuple)) + + @classmethod + def from_auto( + cls, obj: Union["NDBoundingBox", str, Dict, List, Tuple] + ) -> "NDBoundingBox": + raise NotImplementedError + + @classmethod + def group_boxes_with_aligned_mag( + cls, bounding_boxes: Iterable["NDBoundingBox"], aligning_mag: Mag + ) -> Dict["NDBoundingBox", List["NDBoundingBox"]]: + """ + Groups the given BoundingBox instances by aligning each + bbox to the given mag and using that as the key. + For example, bounding boxes of size 256**3 could be grouped + into the corresponding 1024**3 chunks to which they belong + by using aligning_mag = Mag(1024). + """ + + chunks_with_bboxes = defaultdict(list) + for bbox in bounding_boxes: + chunk_key = bbox.align_with_mag(aligning_mag, ceil=True) + chunks_with_bboxes[chunk_key].append(bbox) + + return chunks_with_bboxes + + + def to_wkw_dict(self) -> dict: + ( + width, + height, + depth, + ) = self.size.to_list() + + return { + "topLeft": self.topleft.to_list(), + "width": width, + "height": height, + "depth": depth, + } + + def to_config_dict(self) -> dict: + return {"topleft": self.topleft.to_list(), "size": self.size.to_list()} + + def to_checkpoint_name(self) -> str: + return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" + + def to_csv(self) -> str: + return ",".join(map(str, self.to_tuple6())) + + def __repr__(self) -> str: + return f"NDBoundingBox(topleft={self.topleft}, size={self.size}, axes={self.axes})" + + def __str__(self) -> str: + return self.__repr__() + + def __eq__(self, other: object) -> bool: + if isinstance(other, NDBoundingBox): + return self.topleft == other.topleft and self.size == other.size + else: + raise NotImplementedError() + + def padded_with_margins( + self, margins_left: VecNIntLike, margins_right: Optional[VecNIntLike] = None + ) -> None: + raise NotImplementedError() + + def intersected_with( + self, other: "NDBoundingBox", dont_assert: bool = False + ) -> "NDBoundingBox": + """If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0))""" + + topleft = self.topleft.pairmax(other.topleft) + bottomright = self.bottomright.pairmin(other.bottomright) + size = (bottomright - topleft).pairmax(VecNInt.zeros(len(self.size))) + + intersection = attr.evolve(self, topleft=topleft, size=size) + + if not dont_assert: + assert ( + not intersection.is_empty() + ), f"No intersection between bounding boxes {self} and {other}." + + return intersection + + def extended_by(self, other: "NDBoundingBox") -> "NDBoundingBox": + if self.is_empty(): + return other + if other.is_empty(): + return self + + topleft = self.topleft.pairmin(other.topleft) + bottomright = self.bottomright.pairmax(other.bottomright) + size = bottomright - topleft + + return attr.evolve(self, topleft=topleft, size=size) + + def is_empty(self) -> bool: + return not self.size.is_positive(strictly_positive=True) + + def in_mag(self, mag: Mag) -> "NDBoundingBox": + mag_vec = mag.to_vec3_int() + + assert ( + Vec3Int(self.topleft.to_xyz()) % mag_vec == Vec3Int.zeros() + ), f"topleft {self.topleft} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." + assert ( + self.bottomright % mag_vec == Vec3Int.zeros() + ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." + + return attr.evolve( + self, + topleft=(self.topleft // mag_vec), + size=(self.size // mag_vec), + ) + + def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": + mag_vec = from_mag.to_vec3_int() + return attr.evolve( + self, + topleft=(self.topleft * mag_vec), + size=(self.size * mag_vec), + ) + + def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": + """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. + + :argument ceil: If true, the bounding box is enlarged when necessary. If false, it's shrinked when necessary. + """ + np_mag = mag.to_np() + + align = ( + lambda point, round_fn: round_fn(point.to_np() / np_mag).astype(int) + * np_mag + ) + + if ceil: + topleft = align(self.topleft, np.floor) + bottomright = align(self.bottomright, np.ceil) + else: + topleft = align(self.topleft, np.ceil) + bottomright = align(self.bottomright, np.floor) + return attr.evolve(self, topleft=topleft, size=bottomright - topleft) + + def align_with_mag( + self, mag: Union[Mag, Vec3Int], ceil: bool = False + ) -> "NDBoundingBox": + """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. + + :argument ceil: If true, the bounding box is enlarged when necessary. If false, it's shrinked when necessary. + """ + # This does the same as _align_with_mag_slow, which is more readable. + # Same behavior is asserted in test_align_with_mag_against_numpy_implementation + mag_vec = mag.to_vec3_int() if isinstance(mag, Mag) else mag + roundup = self.topleft if ceil else self.bottomright + rounddown = self.bottomright if ceil else self.topleft + margin_to_roundup = roundup % mag_vec + aligned_roundup = roundup - margin_to_roundup + margin_to_rounddown = (mag_vec - (rounddown % mag_vec)) % mag_vec + aligned_rounddown = rounddown + margin_to_rounddown + if ceil: + return attr.evolve( + self, topleft=aligned_roundup, size=aligned_rounddown - aligned_roundup + ) + else: + return attr.evolve( + self, + topleft=aligned_rounddown, + size=aligned_roundup - aligned_rounddown, + ) + + def contains(self, coord: VecNIntLike) -> bool: + """Check whether a point is inside of the bounding box. + Note that the point may have float coordinates in the ndarray case""" + + if isinstance(coord, np.ndarray): + assert coord.shape == ( + len(self.size), + ), f"Numpy array BoundingBox.contains must have shape ({len(self.size)},), got {coord.shape}." + return cast( + bool, + np.all(coord >= self.topleft) and np.all(coord < self.bottomright), + ) + else: + # In earlier versions, we simply converted to ndarray to have + # a unified calculation here, but this turned out to be a performance bottleneck. + # Therefore, the contains-check is performed on the tuple here. + coord = VecNInt(coord) + return all( + self.topleft[i] <= coord[i] < self.bottomright[i] + for i in range(len(self.axes)) + ) + + def contains_bbox(self, inner_bbox: "NDBoundingBox") -> bool: + return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox + + def chunk( + self, + chunk_shape: VecNIntLike, + chunk_border_alignments: Optional[VecNIntLike] = None, + ) -> Generator["NDBoundingBox", None, None]: + """Decompose the bounding box into smaller chunks of size `chunk_shape`. + + Chunks at the border of the bounding box might be smaller than chunk_shape. + If `chunk_border_alignment` is set, all border coordinates + *between two chunks* will be divisible by that value. + """ + + start = self.topleft.to_np() + chunk_shape = VecNInt(chunk_shape).to_np() + + start_adjust = VecNInt.zeros(len(self.topleft)).to_np() + if chunk_border_alignments is not None: + chunk_border_alignments_array = Vec3Int(chunk_border_alignments).to_np() + assert np.all( + chunk_shape % chunk_border_alignments_array == 0 + ), f"{chunk_shape} not divisible by {chunk_border_alignments_array}" + + # Move the start to be aligned correctly. This doesn't actually change + # the start of the first chunk, because we'll intersect with `self`, + # but it'll lead to all chunk borders being aligned correctly. + start_adjust = start % chunk_border_alignments_array + for coordinates in product(*[ + range(start[i] - start_adjust[i], start[i] + self.size[i], chunk_shape[i]) + for i in range(len(self.axes)) + ]): + + yield NDBoundingBox(topleft=coordinates, size=chunk_shape, axes=self.axes) + + def volume(self) -> int: + return self.size.prod() + + def slice_array(self, array: np.ndarray) -> np.ndarray: + return array[ + self.topleft.x : self.bottomright.x, + self.topleft.y : self.bottomright.y, + self.topleft.z : self.bottomright.z, + ] + + def to_slices(self) -> Tuple[slice, slice, slice]: + return np.index_exp[ + self.topleft.x : self.bottomright.x, + self.topleft.y : self.bottomright.y, + self.topleft.z : self.bottomright.z, + ] + + def offset(self, vector: VecNIntLike) -> "NDBoundingBox": + return attr.evolve(self, topleft=self.topleft + VecNInt(vector)) + + def __hash__(self) -> int: + return hash(self.to_tuple6()) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index a38d149e6..893367650 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -1,13 +1,13 @@ import re -from operator import add, floordiv, mod, mul, sub -from typing import Any, Callable, Iterable, List, Optional, Tuple, Union, cast +from typing import Iterable, Optional, Tuple, Union, cast import numpy as np -value_error = "Vector components must be three integers or a Vec3IntLike object." +from .vecn_int import VecNInt +VALUE_ERROR = "Vector components must be three integers or a Vec3IntLike object." -class Vec3Int(tuple): +class Vec3Int(VecNInt): def __new__( cls, vec: Union[int, "Vec3IntLike"], @@ -33,26 +33,25 @@ def __new__( if isinstance(vec, Vec3Int): return vec - + as_tuple: Optional[Tuple[int, int, int]] = None - + if isinstance(vec, int): - assert y is not None and z is not None, value_error - assert isinstance(y, int) and isinstance(z, int), value_error + assert y is not None and z is not None, VALUE_ERROR + assert isinstance(y, int) and isinstance(z, int), VALUE_ERROR as_tuple = vec, y, z else: - assert y is None and z is None, value_error + assert y is None and z is None, VALUE_ERROR if isinstance(vec, np.ndarray): - assert np.count_nonzero(vec % 1) == 0, value_error + assert np.count_nonzero(vec % 1) == 0, VALUE_ERROR assert vec.shape == ( 3, ), "Numpy array for Vec3Int must have shape (3,)." if isinstance(vec, Iterable): as_tuple = cast(Tuple[int, int, int], tuple(int(item) for item in vec)) - assert len(as_tuple) == 3, value_error - assert as_tuple is not None and len(as_tuple) == 3, value_error + assert as_tuple is not None and len(as_tuple) == 3, VALUE_ERROR - return super().__new__(cls, cast(Iterable, as_tuple)) + return cast(cls, super().__new__(cls, as_tuple)) @staticmethod def from_xyz(x: int, y: int, z: int) -> "Vec3Int": @@ -80,126 +79,16 @@ def from_str(string: str) -> "Vec3Int": else: return Vec3Int.full(int(string)) - @property - def x(self) -> int: - return self[0] - - @property - def y(self) -> int: - return self[1] - - @property - def z(self) -> int: - return self[2] - - def with_x(self, new_x: int) -> "Vec3Int": - return Vec3Int.from_xyz(new_x, self.y, self.z) - - def with_y(self, new_y: int) -> "Vec3Int": - return Vec3Int.from_xyz(self.x, new_y, self.z) - - def with_z(self, new_z: int) -> "Vec3Int": - return Vec3Int.from_xyz(self.x, self.y, new_z) - - def to_np(self) -> np.ndarray: - return np.array((self.x, self.y, self.z)) - - def to_list(self) -> List[int]: - return [self.x, self.y, self.z] - - def to_tuple(self) -> Tuple[int, int, int]: - return self.x, self.y, self.z - - def contains(self, needle: int) -> bool: - return self.x == needle or self.y == needle or self.z == needle - - def is_positive(self, strictly_positive: bool = False) -> bool: - if strictly_positive: - return all(i > 0 for i in self) - else: - return all(i >= 0 for i in self) - - def is_uniform(self) -> bool: - return self.x == self.y == self.z - - def _element_wise( - self, other: Union[int, "Vec3IntLike"], fn: Callable[[int, Any], int] - ) -> "Vec3Int": - if isinstance(other, int): - other_imported = Vec3Int.from_xyz(other, other, other) - else: - other_imported = Vec3Int(other) - return Vec3Int.from_xyz( - fn(self.x, other_imported.x), - fn(self.y, other_imported.y), - fn(self.z, other_imported.z), - ) - - # note: (arguments incompatible with superclass, do not add Vec3Int to plain tuple! Hence the type:ignore) - def __add__(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": # type: ignore[override] - return self._element_wise(other, add) - - def __sub__(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return self._element_wise(other, sub) - - # Note: When multiplying regular tuples with an int those are repeated, - # which is a different behavior in the superclass! Hence the type:ignore. - def __mul__(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": # type: ignore[override] - return self._element_wise(other, mul) - - def __floordiv__(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return self._element_wise(other, floordiv) - - def __mod__(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return self._element_wise(other, mod) - - def __neg__(self) -> "Vec3Int": - return Vec3Int.from_xyz(-self.x, -self.y, -self.z) - - def ceildiv(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return (self + other - 1) // other - - def pairmax(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return self._element_wise(other, max) - - def pairmin(self, other: Union[int, "Vec3IntLike"]) -> "Vec3Int": - return self._element_wise(other, min) - - def prod(self) -> int: - return self.x * self.y * self.z - - def __repr__(self) -> str: - return f"Vec3Int({self.x},{self.y},{self.z})" - - def add_or_none(self, other: Optional["Vec3Int"]) -> Optional["Vec3Int"]: - return None if other is None else self + other - - def moveaxis( - self, source: Union[int, List[int]], target: Union[int, List[int]] - ) -> "Vec3Int": - """ - Allows to move one element at index `source` to another index `target`. Similar to - np.moveaxis, this is *not* a swap operation but instead it moves the specified - source so that the other elements move when necessary. - """ - - # Piggy-back on np.moveaxis by creating an auxiliary array where the indices 0, 1 and - # 2 appear in the shape. - indices = np.moveaxis(np.zeros((0, 1, 2)), source, target).shape - arr = self.to_np()[np.array(indices)] - return Vec3Int(arr) - @classmethod - def zeros(cls) -> "Vec3Int": + def zeros(cls, length: int = 3) -> "Vec3Int": return cls(0, 0, 0) @classmethod - def ones(cls) -> "Vec3Int": + def ones(cls, length: int = 3) -> "Vec3Int": return cls(1, 1, 1) @classmethod - def full(cls, an_int: int) -> "Vec3Int": + def full(cls, an_int: int, length: int = 3) -> "Vec3Int": return cls(an_int, an_int, an_int) - - + Vec3IntLike = Union[Vec3Int, Tuple[int, int, int], np.ndarray, Iterable[int]] diff --git a/webknossos/webknossos/geometry/vecn_int.py b/webknossos/webknossos/geometry/vecn_int.py new file mode 100644 index 000000000..46791c8af --- /dev/null +++ b/webknossos/webknossos/geometry/vecn_int.py @@ -0,0 +1,190 @@ +import re +from operator import add, floordiv, mod, mul, sub +from typing import Any, Callable, Iterable, List, Optional, Tuple, Union, cast + +import numpy as np + +VALUE_ERROR = "VecNInt can be instantiated with int values `VecNInt(1,2,3,4) or with `VecNIntLike` object `VecNInt([1,2,3,4])." + + +class VecNInt(tuple): + def __new__( + cls, + vec: Union[int, "VecNIntLike"], + *args: int, + ) -> "VecNInt": + """ + Class to represent a ND vector. Inherits from tuple and provides useful + methods and operations on top. The vector has a minimal length of 3 and + it is assumed that the first three axes are `x`, `y` and `z`. + + A small usage example: + + ```python + from webknossos import VecNInt + + vector_1 = VecNInt(1, 2, 3, 4) + vector_2 = VecNInt.full(1, 4) + assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] + + assert vector_1 + vector_2 == (2, 3, 4, 5) + ``` + """ + + if isinstance(vec, VecNInt): + return vec + + as_tuple: Optional[Tuple[int, ...]] = None + + if isinstance(vec, int): + assert all(isinstance(arg, int) for arg in args), VALUE_ERROR + as_tuple = (vec, *args) + else: + if args: + raise ValueError(VALUE_ERROR) + if isinstance(vec, np.ndarray): + assert np.count_nonzero(vec % 1) == 0, VALUE_ERROR + if isinstance(vec, str): + return cls.from_str(vec) + if isinstance(vec, Iterable): + as_tuple = cast(Tuple[int, ...], tuple(int(item) for item in vec)) + assert as_tuple is not None and len(as_tuple) >= 3, VALUE_ERROR + + return super().__new__(cls, cast(Iterable, as_tuple)) + + @staticmethod + def from_str(string: str) -> "VecNInt": + return VecNInt(tuple(map(int, re.findall(r"\d+", string)))) + + @property + def x(self) -> int: + return self[0] + + @property + def y(self) -> int: + return self[1] + + @property + def z(self) -> int: + return self[2] + + def with_x(self, new_x: int) -> "VecNInt": + return self.__class__(new_x, self.y, self.z, *self[3:]) + + def with_y(self, new_y: int) -> "VecNInt": + return self.__class__(self.x, new_y, self.z, *self[3:]) + + def with_z(self, new_z: int) -> "VecNInt": + return self.__class__(self.x, self.y, new_z, *self[3:]) + + def with_replaced(self, index: int, new_element: int) -> "VecNInt": + """Returns a new ND Vector with a replaced element at a given index.""" + + return VecNInt(*self[:index], new_element, *self[index + 1:]) + + def to_np(self) -> np.ndarray: + return np.array(self) + + def to_list(self) -> List[int]: + return list(self) + + def to_tuple(self) -> Tuple[int, ...]: + return tuple(self) + + def to_xyz(self) -> Tuple[int, int, int]: + """Returns the x, y and z component of the n dimensional vector. Other axes are ignored.""" + return (self.x, self.y, self.z) + + def contains(self, needle: int) -> bool: + return any(element == needle for element in self) + + def is_positive(self, strictly_positive: bool = False) -> bool: + if strictly_positive: + return all(i > 0 for i in self) + + return all(i >= 0 for i in self) + + def is_uniform(self) -> bool: + first = self[0] + return all(element == first for element in self) + + def _element_wise( + self, other: Union[int, "VecNIntLike"], fn: Callable[[int, Any], int] + ) -> "VecNInt": + if isinstance(other, int): + other_imported = VecNInt.full(other, len(self)) + else: + other_imported = VecNInt(other) + assert len(other_imported) == len(self), f"{other} and {self} are not equally shaped." + return self.__class__( + (fn(other_imported[i], self[i]) for i in range(len(self))) + ) + + # note: (arguments incompatible with superclass, do not add VecNInt to plain tuple! Hence the type:ignore) + def __add__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": # type: ignore[override] + return self._element_wise(other, add) + + def __sub__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return self._element_wise(other, sub) + + # Note: When multiplying regular tuples with an int those are repeated, + # which is a different behavior in the superclass! Hence the type:ignore. + def __mul__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": # type: ignore[override] + return self._element_wise(other, mul) + + def __floordiv__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return self._element_wise(other, floordiv) + + def __mod__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return self._element_wise(other, mod) + + def __neg__(self) -> "VecNInt": + return self.__class__(-elem for elem in self) + + def ceildiv(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return (self + other - 1) // other + + def pairmax(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return self._element_wise(other, max) + + def pairmin(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + return self._element_wise(other, min) + + def prod(self) -> int: + return np.prod(self) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({', '.join((str(element) for element in self))})" + + def add_or_none(self, other: Optional["VecNInt"]) -> Optional["VecNInt"]: + return None if other is None else self + other + + def moveaxis( + self, source: Union[int, List[int]], target: Union[int, List[int]] + ) -> "VecNInt": + """ + Allows to move one element at index `source` to another index `target`. Similar to + np.moveaxis, this is *not* a swap operation but instead it moves the specified + source so that the other elements move when necessary. + """ + + # Piggy-back on np.moveaxis by creating an auxiliary array where the indices 0, 1 and + # 2 appear in the shape. + indices = np.moveaxis(np.zeros(tuple(i for i in range(len(self)))), source, target).shape + arr = self.to_np()[np.array(indices)] + return self.__class__(arr) + + @classmethod + def zeros(cls, length: int) -> "VecNInt": + return cls((0 for _ in range(length))) + + @classmethod + def ones(cls, length: int) -> "VecNInt": + return cls((1 for _ in range(length))) + + @classmethod + def full(cls, an_int: int, length: int) -> "VecNInt": + return cls((an_int for _ in range(length))) + + +VecNIntLike = Union[VecNInt, Tuple[int, ...], np.ndarray, Iterable[int]] From 7cb395ee543435a9f54fcca7b4ba8690909f2db8 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 27 Nov 2023 15:40:12 +0100 Subject: [PATCH 03/41] Rename VecInt and fix some issues. --- .../webknossos/annotation/annotation.py | 2 +- webknossos/webknossos/geometry/__init__.py | 2 + .../webknossos/geometry/bounding_box.py | 9 +- .../webknossos/geometry/nd_bounding_box.py | 151 ++++++++++-------- webknossos/webknossos/geometry/vec3_int.py | 14 +- .../geometry/{vecn_int.py => vec_int.py} | 101 +++++++----- 6 files changed, 158 insertions(+), 121 deletions(-) rename webknossos/webknossos/geometry/{vecn_int.py => vec_int.py} (60%) diff --git a/webknossos/webknossos/annotation/annotation.py b/webknossos/webknossos/annotation/annotation.py index 06a3e257d..8ad6533d5 100644 --- a/webknossos/webknossos/annotation/annotation.py +++ b/webknossos/webknossos/annotation/annotation.py @@ -476,7 +476,7 @@ def _load_from_zip(cls, content: Union[str, PathLike, BinaryIO]) -> "Annotation" assert len(nml_paths) > 0, "Couldn't find an nml file in the supplied zip-file." assert ( len(nml_paths) == 1 - ), f"There must be exactly one nml file in the zip-file, buf found {len(nml_paths)}." + ), f"There must be exactly one nml file in the zip-file, but found {len(nml_paths)}." with nml_paths[0].open(mode="rb") as f: return cls._load_from_nml(nml_paths[0].stem, f, possible_volume_paths=paths) diff --git a/webknossos/webknossos/geometry/__init__.py b/webknossos/webknossos/geometry/__init__.py index 9652a9b61..cecb2d49f 100644 --- a/webknossos/webknossos/geometry/__init__.py +++ b/webknossos/webknossos/geometry/__init__.py @@ -1,3 +1,5 @@ from .bounding_box import BoundingBox from .mag import Mag +from .nd_bounding_box import NDBoundingBox from .vec3_int import Vec3Int, Vec3IntLike +from .vec_int import VecInt, VecIntLike diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 8fc57f810..b4e6dfe98 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -53,15 +53,17 @@ def __attrs_post_init__(self) -> None: # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) - def with_additional_axis(self, name: str, extent: Tuple[int, int]) -> "NDBoundingBox": - assert (name not in ["x", "y", "z"]), f"The name '{name}' of the axis is already taken." + def with_additional_axis( + self, name: str, extent: Tuple[int, int] + ) -> "NDBoundingBox": + assert name not in self.axes, f"The name '{name}' of the axis is already taken." new_topleft = min(extent) new_size = max(extent) - new_topleft return NDBoundingBox( topleft=(*self.topleft, new_topleft), size=(*self.size, new_size), - axes=(*self.axes, name) + axes=(*self.axes, name), ) def with_bounds_x( @@ -84,7 +86,6 @@ def with_bounds_z( """Returns a copy of the bounding box with topleft.z optionally replaced and size.z optionally replaced.""" return cast(BoundingBox, self.with_bounds("z", new_topleft_z, new_size_z)) - @classmethod def from_wkw_dict(cls, bbox: Dict) -> "BoundingBox": diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 95f8e58cd..436807a41 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -1,4 +1,3 @@ -import re from collections import defaultdict from itertools import product from typing import Dict, Generator, Iterable, List, Optional, Tuple, Union, cast @@ -8,10 +7,11 @@ from .mag import Mag from .vec3_int import Vec3Int -from .vecn_int import VecNInt, VecNIntLike +from .vec_int import VecInt, VecIntLike _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" + @attr.frozen class NDBoundingBox: """ @@ -29,10 +29,10 @@ class NDBoundingBox: ``` """ - topleft: VecNInt = attr.field(converter=VecNInt) - size: VecNInt = attr.field(converter=VecNInt) + topleft: VecInt = attr.field(converter=VecInt) + size: VecInt = attr.field(converter=VecInt) axes: Tuple[str, ...] = attr.field(converter=tuple) - bottomright: VecNInt = attr.field(init=False) + bottomright: VecInt = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True color: Optional[Tuple[float, float, float, float]] = None @@ -42,41 +42,68 @@ def __attrs_post_init__(self) -> None: f"The dimensions of topleft, size and axes ({len(self.topleft)}, " + f"{len(self.size)} and {len(self.axes)} dimensions) do not match." ) - - # Bring topleft and size in required order ('x', 'y', 'z', ...) - try: - source = [self.axes.index('x'), self.axes.index('y'), self.axes.index('z')] - except ValueError as err: - raise ValueError("There are at least 3 dimensions needed with names `x`, `y` and `z`.") from err - target = [1,2,3] - self.size.moveaxis(source, target) - self.topleft.moveaxis(source, target) - object.__setattr__(self, "axes", ("x", "y", "z", *(e for e in self.axes if e not in ["x", "y", "z"]))) + if not self._is_sorted(): + self._sort_positions_of_axes() if not self.size.is_positive(): # Flip the size in negative dimensions, so that the topleft is smaller than bottomright. # E.g. BoundingBox((10, 10, 10), (-5, 5, 5)) -> BoundingBox((5, 10, 10), (5, 5, 5)). negative_size = (min(0, value) for value in self.size) - new_topleft = (val1 + val2 for val1, val2 in zip(self.topleft, negative_size)) + new_topleft = ( + val1 + val2 for val1, val2 in zip(self.topleft, negative_size) + ) new_size = (max(value, -value) for value in self.size) object.__setattr__(self, "topleft", new_topleft) object.__setattr__(self, "size", new_size) - # Compute bottomright to avoid that it's recomputed every time # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) - def with_additional_axis(self, name: str, extent: Tuple[int, int]) -> "NDBoundingBox": + def _sort_positions_of_axes(self) -> None: + # Bring topleft and size in required order + # ('x', 'y', 'z', ) + + size, topleft, axes = zip( + *sorted(zip(self.size, self.topleft, self.axes), key=lambda x: x[2]) + ) + object.__setattr__(self, "size", VecInt(size)) + object.__setattr__(self, "topleft", VecInt(topleft)) + object.__setattr__(self, "axes", axes) + try: + source = [self.axes.index("x"), self.axes.index("y"), self.axes.index("z")] + except ValueError as err: + raise ValueError( + "There are at least 3 dimensions needed with names `x`, `y` and `z`." + ) from err + target = [0, 1, 2] + object.__setattr__(self, "size", self.size.moveaxis(source, target)) + object.__setattr__(self, "topleft", self.topleft.moveaxis(source, target)) + object.__setattr__( + self, + "axes", + ("x", "y", "z", *(e for e in self.axes if e not in ["x", "y", "z"])), + ) + + def _is_sorted(self) -> bool: + if self.axes[0:3] != ["x", "y", "z"]: + return False + return all( + self.axes[i] < self.axes[i + 1] for i in range(3, len(self.axes) - 2) + ) + + def with_additional_axis( + self, name: str, extent: Tuple[int, int] + ) -> "NDBoundingBox": assert name not in self.axes, "The identifier of the axis is already taken." start, end = extent return attr.evolve( self, topleft=(*self.topleft, start), size=(*self.size, end - start), - axes=(*self.axes, name) + axes=(*self.axes, name), ) - + def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) @@ -87,13 +114,15 @@ def with_color( self, color: Optional[Tuple[float, float, float, float]] ) -> "NDBoundingBox": return attr.evolve(self, color=color) - - def with_bounds(self, axis: str, new_topleft: Optional[int], new_size: Optional[int]) -> "NDBoundingBox": + + def with_bounds( + self, axis: str, new_topleft: Optional[int], new_size: Optional[int] + ) -> "NDBoundingBox": try: index = self.axes.index(axis) except ValueError as err: raise ValueError("The given axis name does not exist.") from err - + _new_topleft = ( self.topleft.with_replaced(index, new_topleft) if new_topleft is not None @@ -107,28 +136,6 @@ def with_bounds(self, axis: str, new_topleft: Optional[int], new_size: Optional[ return attr.evolve(self, topleft=_new_topleft, size=_new_size) - @classmethod - def from_checkpoint_name(cls, checkpoint_name: str) -> "NDBoundingBox": - """This function extracts a bounding box in the format `x_y_z_sx_sy_xz` which is contained in a string.""" - regex = r"(([0-9]+_){5}([0-9]+))" - match = re.search(regex, checkpoint_name) - assert ( - match is not None - ), f"Could not extract bounding box from {checkpoint_name}" - bbox_tuple = tuple(int(value) for value in match.group().split("_")) - return cls.from_tuple6(cast(Tuple[int, int, int, int, int, int], bbox_tuple)) - - @classmethod - def from_csv(cls, csv_bbox: str) -> "NDBoundingBox": - bbox_tuple = tuple(int(x) for x in csv_bbox.split(",")) - return cls.from_tuple6(cast(Tuple[int, int, int, int, int, int], bbox_tuple)) - - @classmethod - def from_auto( - cls, obj: Union["NDBoundingBox", str, Dict, List, Tuple] - ) -> "NDBoundingBox": - raise NotImplementedError - @classmethod def group_boxes_with_aligned_mag( cls, bounding_boxes: Iterable["NDBoundingBox"], aligning_mag: Mag @@ -148,9 +155,8 @@ def group_boxes_with_aligned_mag( return chunks_with_bboxes - def to_wkw_dict(self) -> dict: - ( + ( width, height, depth, @@ -169,23 +175,29 @@ def to_config_dict(self) -> dict: def to_checkpoint_name(self) -> str: return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" - def to_csv(self) -> str: - return ",".join(map(str, self.to_tuple6())) - def __repr__(self) -> str: - return f"NDBoundingBox(topleft={self.topleft}, size={self.size}, axes={self.axes})" + return f"NDBoundingBox(topleft={self.topleft.to_tuple()}, size={self.size.to_tuple()}, axes={self.axes})" def __str__(self) -> str: return self.__repr__() def __eq__(self, other: object) -> bool: if isinstance(other, NDBoundingBox): + self._check_compatibility(other) return self.topleft == other.topleft and self.size == other.size else: raise NotImplementedError() + def _check_compatibility(self, other) -> None: + if self.axes == other.axes: + return + else: + raise ValueError( + f"Operation with two bboxes is only possible if they have the same axes. {self.axes} != {other.axes}" + ) + def padded_with_margins( - self, margins_left: VecNIntLike, margins_right: Optional[VecNIntLike] = None + self, margins_left: VecIntLike, margins_right: Optional[VecIntLike] = None ) -> None: raise NotImplementedError() @@ -194,9 +206,10 @@ def intersected_with( ) -> "NDBoundingBox": """If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0))""" + self._check_compatibility(other) topleft = self.topleft.pairmax(other.topleft) bottomright = self.bottomright.pairmin(other.bottomright) - size = (bottomright - topleft).pairmax(VecNInt.zeros(len(self.size))) + size = (bottomright - topleft).pairmax(VecInt.zeros(len(self.size))) intersection = attr.evolve(self, topleft=topleft, size=size) @@ -208,6 +221,7 @@ def intersected_with( return intersection def extended_by(self, other: "NDBoundingBox") -> "NDBoundingBox": + self._check_compatibility(other) if self.is_empty(): return other if other.is_empty(): @@ -293,7 +307,7 @@ def align_with_mag( size=aligned_roundup - aligned_rounddown, ) - def contains(self, coord: VecNIntLike) -> bool: + def contains(self, coord: VecIntLike) -> bool: """Check whether a point is inside of the bounding box. Note that the point may have float coordinates in the ndarray case""" @@ -309,19 +323,20 @@ def contains(self, coord: VecNIntLike) -> bool: # In earlier versions, we simply converted to ndarray to have # a unified calculation here, but this turned out to be a performance bottleneck. # Therefore, the contains-check is performed on the tuple here. - coord = VecNInt(coord) + coord = VecInt(coord) return all( self.topleft[i] <= coord[i] < self.bottomright[i] for i in range(len(self.axes)) ) def contains_bbox(self, inner_bbox: "NDBoundingBox") -> bool: + self._check_compatibility(inner_bbox) return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox def chunk( self, - chunk_shape: VecNIntLike, - chunk_border_alignments: Optional[VecNIntLike] = None, + chunk_shape: VecIntLike, + chunk_border_alignments: Optional[VecIntLike] = None, ) -> Generator["NDBoundingBox", None, None]: """Decompose the bounding box into smaller chunks of size `chunk_shape`. @@ -331,9 +346,9 @@ def chunk( """ start = self.topleft.to_np() - chunk_shape = VecNInt(chunk_shape).to_np() + chunk_shape = VecInt(chunk_shape).to_np() - start_adjust = VecNInt.zeros(len(self.topleft)).to_np() + start_adjust = VecInt.zeros(len(self.topleft)).to_np() if chunk_border_alignments is not None: chunk_border_alignments_array = Vec3Int(chunk_border_alignments).to_np() assert np.all( @@ -344,11 +359,14 @@ def chunk( # the start of the first chunk, because we'll intersect with `self`, # but it'll lead to all chunk borders being aligned correctly. start_adjust = start % chunk_border_alignments_array - for coordinates in product(*[ - range(start[i] - start_adjust[i], start[i] + self.size[i], chunk_shape[i]) + for coordinates in product( + *[ + range( + start[i] - start_adjust[i], start[i] + self.size[i], chunk_shape[i] + ) for i in range(len(self.axes)) - ]): - + ] + ): yield NDBoundingBox(topleft=coordinates, size=chunk_shape, axes=self.axes) def volume(self) -> int: @@ -368,8 +386,5 @@ def to_slices(self) -> Tuple[slice, slice, slice]: self.topleft.z : self.bottomright.z, ] - def offset(self, vector: VecNIntLike) -> "NDBoundingBox": - return attr.evolve(self, topleft=self.topleft + VecNInt(vector)) - - def __hash__(self) -> int: - return hash(self.to_tuple6()) + def offset(self, vector: VecIntLike) -> "NDBoundingBox": + return attr.evolve(self, topleft=self.topleft + VecInt(vector)) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 893367650..741843403 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -1,13 +1,14 @@ import re -from typing import Iterable, Optional, Tuple, Union, cast +from typing import Iterable, Optional, Tuple, Type, Union, cast import numpy as np -from .vecn_int import VecNInt +from .vec_int import VecInt VALUE_ERROR = "Vector components must be three integers or a Vec3IntLike object." -class Vec3Int(VecNInt): + +class Vec3Int(VecInt): def __new__( cls, vec: Union[int, "Vec3IntLike"], @@ -33,9 +34,9 @@ def __new__( if isinstance(vec, Vec3Int): return vec - + as_tuple: Optional[Tuple[int, int, int]] = None - + if isinstance(vec, int): assert y is not None and z is not None, VALUE_ERROR assert isinstance(y, int) and isinstance(z, int), VALUE_ERROR @@ -90,5 +91,6 @@ def ones(cls, length: int = 3) -> "Vec3Int": @classmethod def full(cls, an_int: int, length: int = 3) -> "Vec3Int": return cls(an_int, an_int, an_int) - + + Vec3IntLike = Union[Vec3Int, Tuple[int, int, int], np.ndarray, Iterable[int]] diff --git a/webknossos/webknossos/geometry/vecn_int.py b/webknossos/webknossos/geometry/vec_int.py similarity index 60% rename from webknossos/webknossos/geometry/vecn_int.py rename to webknossos/webknossos/geometry/vec_int.py index 46791c8af..1f703ca02 100644 --- a/webknossos/webknossos/geometry/vecn_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -4,15 +4,18 @@ import numpy as np -VALUE_ERROR = "VecNInt can be instantiated with int values `VecNInt(1,2,3,4) or with `VecNIntLike` object `VecNInt([1,2,3,4])." +VALUE_ERROR = "VecInt can be instantiated with int values `VecInt(1,2,3,4) or with `VecIntLike` object `VecInt([1,2,3,4])." -class VecNInt(tuple): +class VecInt(tuple): def __new__( cls, - vec: Union[int, "VecNIntLike"], + vec: Union[int, "VecIntLike"], *args: int, - ) -> "VecNInt": + y: Optional[int] = None, + z: Optional[int] = None, + **kwargs: int, + ) -> "VecInt": """ Class to represent a ND vector. Inherits from tuple and provides useful methods and operations on top. The vector has a minimal length of 3 and @@ -21,24 +24,34 @@ def __new__( A small usage example: ```python - from webknossos import VecNInt + from webknossos import VecInt - vector_1 = VecNInt(1, 2, 3, 4) - vector_2 = VecNInt.full(1, 4) + vector_1 = VecInt(1, y=2, z=3, t=4) + vector_2 = VecInt.full(1, 4) assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] assert vector_1 + vector_2 == (2, 3, 4, 5) ``` """ - if isinstance(vec, VecNInt): + if isinstance(vec, VecInt): return vec as_tuple: Optional[Tuple[int, ...]] = None if isinstance(vec, int): - assert all(isinstance(arg, int) for arg in args), VALUE_ERROR - as_tuple = (vec, *args) + if args: + assert all(isinstance(arg, int) for arg in args), VALUE_ERROR + as_tuple = (vec, *args) + else: + assert y is not None and z is not None, VALUE_ERROR + remaining_axes = [] + for key, value in kwargs.items(): + assert key not in ["x", "y", "z"] + remaining_axes.append((key, value)) + as_tuple = (vec, y, z, *[ + x[1] for x in sorted(remaining_axes, key=lambda x: x[0]) + ]) else: if args: raise ValueError(VALUE_ERROR) @@ -53,8 +66,8 @@ def __new__( return super().__new__(cls, cast(Iterable, as_tuple)) @staticmethod - def from_str(string: str) -> "VecNInt": - return VecNInt(tuple(map(int, re.findall(r"\d+", string)))) + def from_str(string: str) -> "VecInt": + return VecInt(tuple(map(int, re.findall(r"\d+", string)))) @property def x(self) -> int: @@ -68,19 +81,19 @@ def y(self) -> int: def z(self) -> int: return self[2] - def with_x(self, new_x: int) -> "VecNInt": + def with_x(self, new_x: int) -> "VecInt": return self.__class__(new_x, self.y, self.z, *self[3:]) - def with_y(self, new_y: int) -> "VecNInt": + def with_y(self, new_y: int) -> "VecInt": return self.__class__(self.x, new_y, self.z, *self[3:]) - def with_z(self, new_z: int) -> "VecNInt": + def with_z(self, new_z: int) -> "VecInt": return self.__class__(self.x, self.y, new_z, *self[3:]) - def with_replaced(self, index: int, new_element: int) -> "VecNInt": + def with_replaced(self, index: int, new_element: int) -> "VecInt": """Returns a new ND Vector with a replaced element at a given index.""" - return VecNInt(*self[:index], new_element, *self[index + 1:]) + return VecInt(*self[:index], new_element, *self[index + 1 :]) def to_np(self) -> np.ndarray: return np.array(self) @@ -90,7 +103,7 @@ def to_list(self) -> List[int]: def to_tuple(self) -> Tuple[int, ...]: return tuple(self) - + def to_xyz(self) -> Tuple[int, int, int]: """Returns the x, y and z component of the n dimensional vector. Other axes are ignored.""" return (self.x, self.y, self.z) @@ -101,7 +114,7 @@ def contains(self, needle: int) -> bool: def is_positive(self, strictly_positive: bool = False) -> bool: if strictly_positive: return all(i > 0 for i in self) - + return all(i >= 0 for i in self) def is_uniform(self) -> bool: @@ -109,45 +122,47 @@ def is_uniform(self) -> bool: return all(element == first for element in self) def _element_wise( - self, other: Union[int, "VecNIntLike"], fn: Callable[[int, Any], int] - ) -> "VecNInt": + self, other: Union[int, "VecIntLike"], fn: Callable[[int, Any], int] + ) -> "VecInt": if isinstance(other, int): - other_imported = VecNInt.full(other, len(self)) + other_imported = VecInt.full(other, len(self)) else: - other_imported = VecNInt(other) - assert len(other_imported) == len(self), f"{other} and {self} are not equally shaped." + other_imported = VecInt(other) + assert len(other_imported) == len( + self + ), f"{other} and {self} are not equally shaped." return self.__class__( - (fn(other_imported[i], self[i]) for i in range(len(self))) + (fn(self[i], other_imported[i]) for i in range(len(self))) ) - # note: (arguments incompatible with superclass, do not add VecNInt to plain tuple! Hence the type:ignore) - def __add__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": # type: ignore[override] + # note: (arguments incompatible with superclass, do not add VecInt to plain tuple! Hence the type:ignore) + def __add__(self, other: Union[int, "VecIntLike"]) -> "VecInt": # type: ignore[override] return self._element_wise(other, add) - def __sub__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def __sub__(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, sub) # Note: When multiplying regular tuples with an int those are repeated, # which is a different behavior in the superclass! Hence the type:ignore. - def __mul__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": # type: ignore[override] + def __mul__(self, other: Union[int, "VecIntLike"]) -> "VecInt": # type: ignore[override] return self._element_wise(other, mul) - def __floordiv__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def __floordiv__(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, floordiv) - def __mod__(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def __mod__(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, mod) - def __neg__(self) -> "VecNInt": + def __neg__(self) -> "VecInt": return self.__class__(-elem for elem in self) - def ceildiv(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def ceildiv(self, other: Union[int, "VecIntLike"]) -> "VecInt": return (self + other - 1) // other - def pairmax(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def pairmax(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, max) - def pairmin(self, other: Union[int, "VecNIntLike"]) -> "VecNInt": + def pairmin(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, min) def prod(self) -> int: @@ -156,12 +171,12 @@ def prod(self) -> int: def __repr__(self) -> str: return f"{self.__class__.__name__}({', '.join((str(element) for element in self))})" - def add_or_none(self, other: Optional["VecNInt"]) -> Optional["VecNInt"]: + def add_or_none(self, other: Optional["VecInt"]) -> Optional["VecInt"]: return None if other is None else self + other def moveaxis( self, source: Union[int, List[int]], target: Union[int, List[int]] - ) -> "VecNInt": + ) -> "VecInt": """ Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified @@ -170,21 +185,23 @@ def moveaxis( # Piggy-back on np.moveaxis by creating an auxiliary array where the indices 0, 1 and # 2 appear in the shape. - indices = np.moveaxis(np.zeros(tuple(i for i in range(len(self)))), source, target).shape + indices = np.moveaxis( + np.zeros(tuple(i for i in range(len(self)))), source, target + ).shape arr = self.to_np()[np.array(indices)] return self.__class__(arr) @classmethod - def zeros(cls, length: int) -> "VecNInt": + def zeros(cls, length: int) -> "VecInt": return cls((0 for _ in range(length))) @classmethod - def ones(cls, length: int) -> "VecNInt": + def ones(cls, length: int) -> "VecInt": return cls((1 for _ in range(length))) @classmethod - def full(cls, an_int: int, length: int) -> "VecNInt": + def full(cls, an_int: int, length: int) -> "VecInt": return cls((an_int for _ in range(length))) -VecNIntLike = Union[VecNInt, Tuple[int, ...], np.ndarray, Iterable[int]] +VecIntLike = Union[VecInt, Tuple[int, ...], np.ndarray, Iterable[int]] From b3c972ec1c8a04303880f93a9644c710fddac075 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 21 Dec 2023 09:58:47 +0100 Subject: [PATCH 04/41] Work on import of existing zarr dataset. --- .../script_collection/reading_nd_data.py | 34 +++++++++++++------ .../webknossos/dataset/_utils/pims_images.py | 6 ++-- webknossos/webknossos/dataset/layer.py | 6 ++-- webknossos/webknossos/dataset/mag_view.py | 7 +++- webknossos/webknossos/dataset/properties.py | 9 +++++ webknossos/webknossos/geometry/vec3_int.py | 14 +++++--- webknossos/webknossos/geometry/vec_int.py | 11 +++--- 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 6538490ec..d5646c113 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -4,19 +4,31 @@ import webknossos as wk +TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D-series.ome.tif" +ZARR_PATH = Path("..") / "idr0101A-4d-zarr" + + +def from_images_import(): + reader = pims.ImageSequenceND([str(TIF_PATH)]) + print(reader.sizes) + print(isinstance(reader, pims.FramesSequenceND)) + # wk.Dataset.from_images( + # input_path, output_path, voxel_size=(10, 10, 10), data_format="zarr3" + # ) -def main(input_path: Path, output_path: Path) -> None: - """Imports a dataset with more than 3 dimensions.""" - wk.Dataset.from_images( - input_path, output_path, voxel_size=(10, 10, 10), data_format="zarr3" - ) - # reader = pims.Bioformats(input_path) - # print(reader.sizes) - # print(isinstance(reader, pims.FramesSequenceND)) +def open_existing_dataset(): + ds = wk.Dataset.open(ZARR_PATH) + color_layer = ds.get_color_layers()[0] + finest_mag = color_layer.get_finest_mag() + layers = ds.layers + + +def main() -> None: + """Imports a dataset with more than 3 dimensions.""" + # from_images_import() + open_existing_dataset() if __name__ == "__main__": - input_path = Path(".") / "webknossos" / "testdata" / "4D" # / "4D-series.ome.tif" - output_path = Path(".") / "webknossos" / "testoutput" / "4D" - main(input_path, output_path) + main() diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 03b8e62b3..25c705c57 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -46,7 +46,7 @@ pass # pylint: enable=unused-import -from ...geometry.vec3_int import Vec3Int +from ...geometry.vec_int import VecInt from ..mag_view import MagView try: @@ -68,7 +68,7 @@ def _assume_color_channel(dim_size: int, dtype: np.dtype) -> bool: class PimsImages: dtype: DTypeLike - expected_shape: Vec3Int + expected_shape: VecInt num_channels: int def __init__( @@ -426,7 +426,7 @@ def _open_images( """ images_context_manager: Optional[ContextManager] with warnings.catch_warnings(): - if isinstance(self._original_images, pims.FramesSequence): + if isinstance(self._original_images, pims.FramesSequenceND): images_context_manager = nullcontext(enter_result=self._original_images) else: exceptions: List[Exception] = [] diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index b1c8774b0..a887acb0d 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -194,7 +194,7 @@ def __init__(self, dataset: "Dataset", properties: LayerProperties) -> None: self.path.mkdir(parents=True, exist_ok=True) for mag in properties.mags: - self._setup_mag(Mag(mag.mag)) + self._setup_mag(Mag(mag.mag), mag.path) # Only keep the properties of mags that were initialized. # Sometimes the directory of a mag is removed from disk manually, but the properties are not updated. self._properties.mags = [ @@ -1079,7 +1079,7 @@ def upsample( # Restoring the original layer bbox self.bounding_box = old_layer_bbox - def _setup_mag(self, mag: Mag) -> None: + def _setup_mag(self, mag, path: Optional[str]) -> None: # This method is used to initialize the mag when opening the Dataset. This does not create e.g. the wk_header. mag_name = mag.to_layer_name() @@ -1089,7 +1089,7 @@ def _setup_mag(self, mag: Mag) -> None: try: cls_array = BaseArray.get_class(self._properties.data_format) info = cls_array.open( - _find_mag_path_on_disk(self.dataset.path, self.name, mag_name) + _find_mag_path_on_disk(self.dataset.path, self.name, mag_name, path) ).info self._mags[mag] = MagView( self, diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index c3e9f7e98..6a5e6fcd8 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -30,7 +30,12 @@ from .view import View -def _find_mag_path_on_disk(dataset_path: Path, layer_name: str, mag_name: str) -> Path: +def _find_mag_path_on_disk( + dataset_path: Path, layer_name: str, mag_name: str, path: Optional[str] = None +) -> Path: + if path is not None: + return dataset_path / path + mag = Mag(mag_name) short_mag_file_path = dataset_path / layer_name / mag.to_layer_name() long_mag_file_path = dataset_path / layer_name / mag.to_long_layer_name() diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 985692d9d..43477bd0c 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -119,6 +119,7 @@ class LayerViewConfiguration: @attr.define class MagViewProperties: mag: Mag + path: Optional[str] cube_length: Optional[int] = None axis_order: Optional[Dict[str, int]] = None @@ -128,6 +129,13 @@ def resolution(self) -> Mag: return self.mag +@attr.define +class AxisProperties: + name: str + bounds: List[int] + index: int + + @attr.define class LayerProperties: name: str @@ -137,6 +145,7 @@ class LayerProperties: data_format: DataFormat mags: List[MagViewProperties] num_channels: Optional[int] = None + additional_axes: Optional[List[AxisProperties]] = None default_view_configuration: Optional[LayerViewConfiguration] = None @property diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 741843403..385e91e34 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -70,26 +70,32 @@ def from_vec3_float(vec: Tuple[float, float, float]) -> "Vec3Int": def from_vec_or_int(vec_or_int: Union["Vec3IntLike", int]) -> "Vec3Int": if isinstance(vec_or_int, int): return Vec3Int.full(vec_or_int) - else: - return Vec3Int(vec_or_int) + + return Vec3Int(vec_or_int) @staticmethod def from_str(string: str) -> "Vec3Int": if re.match(r"\(\d+,\d+,\d+\)", string): return Vec3Int(tuple(map(int, re.findall(r"\d+", string)))) - else: - return Vec3Int.full(int(string)) + + return Vec3Int.full(int(string)) @classmethod def zeros(cls, length: int = 3) -> "Vec3Int": + del length + return cls(0, 0, 0) @classmethod def ones(cls, length: int = 3) -> "Vec3Int": + del length + return cls(1, 1, 1) @classmethod def full(cls, an_int: int, length: int = 3) -> "Vec3Int": + del length + return cls(an_int, an_int, an_int) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index 1f703ca02..5e7b2ebf1 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -49,9 +49,12 @@ def __new__( for key, value in kwargs.items(): assert key not in ["x", "y", "z"] remaining_axes.append((key, value)) - as_tuple = (vec, y, z, *[ - x[1] for x in sorted(remaining_axes, key=lambda x: x[0]) - ]) + as_tuple = ( + vec, + y, + z, + *[x[1] for x in sorted(remaining_axes, key=lambda x: x[0])], + ) else: if args: raise ValueError(VALUE_ERROR) @@ -166,7 +169,7 @@ def pairmin(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, min) def prod(self) -> int: - return np.prod(self) + return int(np.prod(self)) def __repr__(self) -> str: return f"{self.__class__.__name__}({', '.join((str(element) for element in self))})" From 89a38e62591db768b6bb40f00e94b23582061b70 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 21 Dec 2023 17:34:33 +0100 Subject: [PATCH 05/41] Add nd_bounding_box to properties of Layer. --- .../webknossos/dataset/_utils/pims_images.py | 1 + webknossos/webknossos/dataset/layer.py | 2 +- webknossos/webknossos/dataset/properties.py | 20 ++++++++++++++++--- webknossos/webknossos/geometry/vec3_int.py | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 25c705c57..7f63f8434 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -46,6 +46,7 @@ pass # pylint: enable=unused-import +from ...geometry.vec3_int import Vec3Int from ...geometry.vec_int import VecInt from ..mag_view import MagView diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index a887acb0d..31072b1c4 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -1079,7 +1079,7 @@ def upsample( # Restoring the original layer bbox self.bounding_box = old_layer_bbox - def _setup_mag(self, mag, path: Optional[str]) -> None: + def _setup_mag(self, mag, path: Optional[str] = None) -> None: # This method is used to initialize the mag when opening the Dataset. This does not create e.g. the wk_header. mag_name = mag.to_layer_name() diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 43477bd0c..61bbdcd04 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -6,7 +6,7 @@ import numpy as np from cattr.gen import make_dict_structure_fn, make_dict_unstructure_fn, override -from ..geometry import BoundingBox, Mag, Vec3Int +from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int from ..utils import snake_to_camel_case, warn_deprecated from ._array import ArrayException, BaseArray, DataFormat from .layer_categories import LayerCategoryType @@ -119,7 +119,7 @@ class LayerViewConfiguration: @attr.define class MagViewProperties: mag: Mag - path: Optional[str] + path: Optional[str] = None cube_length: Optional[int] = None axis_order: Optional[Dict[str, int]] = None @@ -132,7 +132,7 @@ def resolution(self) -> Mag: @attr.define class AxisProperties: name: str - bounds: List[int] + bounds: Tuple[int, int] index: int @@ -153,6 +153,20 @@ def resolutions(self) -> List[MagViewProperties]: warn_deprecated("resolutions", "mags") return self.mags + @property + def nd_bounding_box(self) -> NDBoundingBox: + if self.additional_axes is None: + return self.bounding_box + else: + nd_bbox = self.bounding_box + for axis in self.additional_axes: + nd_bbox = nd_bbox.with_additional_axis(axis.name, axis.bounds) + return nd_bbox + + @nd_bounding_box.setter + def nd_bounding_box(self, bbox: NDBoundingBox) -> None: + self.nd_bounding_box = bbox + @attr.define class SegmentationLayerProperties(LayerProperties): diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 385e91e34..6f25c8027 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -1,5 +1,5 @@ import re -from typing import Iterable, Optional, Tuple, Type, Union, cast +from typing import Iterable, Optional, Tuple, Union, cast import numpy as np From 55806311bcb2abb8d6ee5af3087c0dfa2d4d0e88 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 4 Jan 2024 18:00:59 +0100 Subject: [PATCH 06/41] Update hooks in properties.py to make import of 4d zarr datasets possible. --- .../script_collection/reading_nd_data.py | 2 + webknossos/webknossos/dataset/_array.py | 2 +- webknossos/webknossos/dataset/dataset.py | 9 ++-- webknossos/webknossos/dataset/properties.py | 46 ++++++++++--------- .../webknossos/geometry/nd_bounding_box.py | 42 +++++++++-------- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index d5646c113..95a8dcabd 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -22,6 +22,8 @@ def open_existing_dataset(): color_layer = ds.get_color_layers()[0] finest_mag = color_layer.get_finest_mag() layers = ds.layers + #finest_mag.read() + ds.copy_dataset("../copied_dataset") def main() -> None: diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 97eaa940a..bb57fd9e9 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -605,7 +605,7 @@ def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: def ensure_size( self, new_shape: Vec3IntLike, align_with_shards: bool = True, warn: bool = False ) -> None: - new_shape = Vec3Int(new_shape) + new_shape = Vec3Int(new_shape.to_xyz()) zarray = self._zarray new_shape_tuple = ( diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 953ee96bb..a0c5228d9 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,12 @@ import attr import numpy as np from boltons.typeutils import make_sentinel -from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath +from cluster_tools import Executor + from ..client.api_client.models import ApiDataset from ..geometry.vec3_int import Vec3Int, Vec3IntLike from ._array import ArrayException, ArrayInfo, BaseArray @@ -59,7 +60,7 @@ from ..client._upload_dataset import LayerToLink from ..administration.user import Team -from ..geometry import BoundingBox, Mag +from ..geometry import BoundingBox, Mag, NDBoundingBox from ..utils import ( copy_directory_with_symlinks, copytree, @@ -758,7 +759,7 @@ def add_layer( dtype_per_channel: Optional[DTypeLike] = None, num_channels: Optional[int] = None, data_format: Union[str, DataFormat] = DEFAULT_DATA_FORMAT, - bounding_box: Optional[BoundingBox] = None, + bounding_box: Optional[NDBoundingBox] = None, **kwargs: Any, ) -> Layer: """ @@ -818,7 +819,7 @@ def add_layer( layer_properties = LayerProperties( name=layer_name, category=category, - bounding_box=bounding_box or BoundingBox((0, 0, 0), (0, 0, 0)), + bounding_box=bounding_box or NDBoundingBox((0, 0, 0), (0, 0, 0), ("x", "y", "z")), element_class=_dtype_per_channel_to_element_class( dtype_per_channel, num_channels ), diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 61bbdcd04..4394b889e 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -6,7 +6,7 @@ import numpy as np from cattr.gen import make_dict_structure_fn, make_dict_unstructure_fn, override -from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int +from ..geometry import Mag, NDBoundingBox, Vec3Int from ..utils import snake_to_camel_case, warn_deprecated from ._array import ArrayException, BaseArray, DataFormat from .layer_categories import LayerCategoryType @@ -140,12 +140,11 @@ class AxisProperties: class LayerProperties: name: str category: LayerCategoryType - bounding_box: BoundingBox + bounding_box: NDBoundingBox element_class: str data_format: DataFormat mags: List[MagViewProperties] num_channels: Optional[int] = None - additional_axes: Optional[List[AxisProperties]] = None default_view_configuration: Optional[LayerViewConfiguration] = None @property @@ -153,21 +152,6 @@ def resolutions(self) -> List[MagViewProperties]: warn_deprecated("resolutions", "mags") return self.mags - @property - def nd_bounding_box(self) -> NDBoundingBox: - if self.additional_axes is None: - return self.bounding_box - else: - nd_bbox = self.bounding_box - for axis in self.additional_axes: - nd_bbox = nd_bbox.with_additional_axis(axis.name, axis.bounds) - return nd_bbox - - @nd_bounding_box.setter - def nd_bounding_box(self, bbox: NDBoundingBox) -> None: - self.nd_bounding_box = bbox - - @attr.define class SegmentationLayerProperties(LayerProperties): largest_segment_id: Optional[int] = None @@ -192,10 +176,10 @@ class DatasetProperties: dataset_converter = cattr.Converter() # register (un-)structure hooks for non-attr-classes -bbox_to_wkw: Callable[[BoundingBox], dict] = lambda o: o.to_wkw_dict() -dataset_converter.register_unstructure_hook(BoundingBox, bbox_to_wkw) +bbox_to_wkw: Callable[[NDBoundingBox], dict] = lambda o: o.to_wkw_dict() +dataset_converter.register_unstructure_hook(NDBoundingBox, bbox_to_wkw) dataset_converter.register_structure_hook( - BoundingBox, lambda d, _: BoundingBox.from_wkw_dict(d) + NDBoundingBox, lambda d, _: NDBoundingBox.from_wkw_dict(d) ) @@ -282,6 +266,13 @@ def __layer_properties_post_unstructure( mag_view_properties_post_structure(m) for m in d["mags"] ] del d["mags"] + # json expects nd_bounding_box to be represented as bounding_box and additional_axes + bbox = d["boundingBox"] + topleft: List[int] = bbox["topLeft"][:3] + width, height, depth = bbox["size"][:3] + additional_axes = [{"name": name, "bounds": (top_left, top_left + size)} for name, top_left, size in zip(bbox["axes"][3:], bbox["topLeft"][3:], bbox["size"][3:])] + d["boundingBox"] = {"topLeft": topleft, "width": width, "height": height, "depth": depth} + d["additionalAxes"] = additional_axes return d return __layer_properties_post_unstructure @@ -305,6 +296,19 @@ def __layer_properties_pre_structure( mag_view_properties_pre_unstructure(m) for m in d["wkwResolutions"] ] del d["wkwResolutions"] + # bounding_box and additional_axes are internally handled as nd_bounding_box + bbox = d["boundingBox"] + topleft: List[int] = bbox["topLeft"] + size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] + axes: List[str] = ["x", "y", "z"] + if "additionalAxes" in d: + for axis in d["additionalAxes"]: + axes.append(axis["name"]) + topleft.append(axis["bounds"][0]) + size.append(axis["bounds"][1] - axis["bounds"][0]) + nd_bbox = {"topLeft": topleft, "size": size, "axes": axes} + d["boundingBox"] = nd_bbox + del d["additionalAxes"] obj = converter_fn(d, type_value) return obj diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 436807a41..d7939379c 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -59,6 +59,7 @@ def __attrs_post_init__(self) -> None: # Compute bottomright to avoid that it's recomputed every time # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) + def _sort_positions_of_axes(self) -> None: # Bring topleft and size in required order @@ -154,19 +155,18 @@ def group_boxes_with_aligned_mag( chunks_with_bboxes[chunk_key].append(bbox) return chunks_with_bboxes + + @classmethod + def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": + # TODO: include index in nd_bounding_box to clarify axis order + return cls(bbox["topLeft"], bbox["size"], bbox["axes"]) - def to_wkw_dict(self) -> dict: - ( - width, - height, - depth, - ) = self.size.to_list() + def to_wkw_dict(self) -> dict: return { "topLeft": self.topleft.to_list(), - "width": width, - "height": height, - "depth": depth, + "size": self.size.to_list(), + "axes": self.axes, } def to_config_dict(self) -> dict: @@ -243,21 +243,21 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": Vec3Int(self.topleft.to_xyz()) % mag_vec == Vec3Int.zeros() ), f"topleft {self.topleft} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." assert ( - self.bottomright % mag_vec == Vec3Int.zeros() + Vec3Int(self.bottomright.to_xyz()) % mag_vec == Vec3Int.zeros() ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." return attr.evolve( self, - topleft=(self.topleft // mag_vec), - size=(self.size // mag_vec), + topleft=VecInt(*Vec3Int(self.topleft.to_xyz()) // mag_vec, *self.topleft[3:]), + size=VecInt(*Vec3Int(self.size.to_xyz()) // mag_vec, *self.size[3:]), ) def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": mag_vec = from_mag.to_vec3_int() return attr.evolve( self, - topleft=(self.topleft * mag_vec), - size=(self.size * mag_vec), + topleft=VecInt(*Vec3Int(self.topleft) * mag_vec, *self.topleft[3:]), + size=VecInt(*Vec3Int(self.size) * mag_vec, *self.size[3:]), ) def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": @@ -290,21 +290,25 @@ def align_with_mag( # This does the same as _align_with_mag_slow, which is more readable. # Same behavior is asserted in test_align_with_mag_against_numpy_implementation mag_vec = mag.to_vec3_int() if isinstance(mag, Mag) else mag - roundup = self.topleft if ceil else self.bottomright - rounddown = self.bottomright if ceil else self.topleft + topleft = Vec3Int(self.topleft[:3]) + bottomright= Vec3Int(self.bottomright[:3]) + roundup = topleft if ceil else bottomright + rounddown = bottomright if ceil else topleft margin_to_roundup = roundup % mag_vec aligned_roundup = roundup - margin_to_roundup margin_to_rounddown = (mag_vec - (rounddown % mag_vec)) % mag_vec aligned_rounddown = rounddown + margin_to_rounddown if ceil: return attr.evolve( - self, topleft=aligned_roundup, size=aligned_rounddown - aligned_roundup + self, + topleft=VecInt(*aligned_roundup, *self.topleft[3:]), + size=VecInt(*(aligned_rounddown - aligned_roundup), *self.topleft[3:]) ) else: return attr.evolve( self, - topleft=aligned_rounddown, - size=aligned_roundup - aligned_rounddown, + topleft=VecInt(*aligned_rounddown, *self.topleft[3:]), + size=VecInt(*(aligned_roundup - aligned_rounddown), *self.size[3:]) ) def contains(self, coord: VecIntLike) -> bool: From c4d2838e363f81533c9966e4a3a18268bc32f8a8 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 8 Jan 2024 16:46:20 +0100 Subject: [PATCH 07/41] Add axis_order and index of additional axes to nd_bounding box creation. --- webknossos/webknossos/dataset/layer.py | 5 +- webknossos/webknossos/dataset/properties.py | 31 +++---- .../webknossos/geometry/bounding_box.py | 4 +- .../webknossos/geometry/nd_bounding_box.py | 87 +++++++++++-------- 4 files changed, 72 insertions(+), 55 deletions(-) diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 31072b1c4..c7da38980 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -9,10 +9,11 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union import numpy as np -from cluster_tools import Executor from numpy.typing import DTypeLike from upath import UPath +from cluster_tools import Executor + from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike from ._array import ArrayException, BaseArray, DataFormat from ._downsampling_utils import ( @@ -477,7 +478,7 @@ def get_or_add_mag( file_len: Optional[int] = None, # deprecated ) -> MagView: """ - Creates a new mag called and adds it to the dataset, in case it did not exist before. + Creates a new mag and adds it to the dataset, in case it did not exist before. Then, returns the mag. See `add_mag` for more information. diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 4394b889e..841b3c337 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -240,13 +240,13 @@ def mag_unstructure(mag: Mag) -> List[int]: # The serialization of `LayerProperties` differs slightly based on whether it is a `wkw` or `zarr` layer. # These post-unstructure and pre-structure functions perform the conditional field renames. -def mag_view_properties_post_structure(d: Dict[str, Any]) -> Dict[str, Any]: +def mag_view_properties_post_unstructure(d: Dict[str, Any]) -> Dict[str, Any]: d["resolution"] = d["mag"] del d["mag"] return d -def mag_view_properties_pre_unstructure(d: Dict[str, Any]) -> Dict[str, Any]: +def mag_view_properties_pre_structure(d: Dict[str, Any]) -> Dict[str, Any]: d["mag"] = d["resolution"] del d["resolution"] return d @@ -263,13 +263,14 @@ def __layer_properties_post_unstructure( d = converter_fn(obj) if d["dataFormat"] == "wkw": d["wkwResolutions"] = [ - mag_view_properties_post_structure(m) for m in d["mags"] + mag_view_properties_post_unstructure(m) for m in d["mags"] ] del d["mags"] # json expects nd_bounding_box to be represented as bounding_box and additional_axes bbox = d["boundingBox"] - topleft: List[int] = bbox["topLeft"][:3] - width, height, depth = bbox["size"][:3] + x_pos, y_pos, z_pos = bbox["axes"].index("x"), bbox["axes"].index("y"), bbox["axes"].index("z") + topleft: List[int] = [bbox["topLeft"][x_pos], bbox["topLeft"][y_pos], bbox["topLeft"][z_pos]] + width, height, depth = [bbox["size"][x_pos], bbox["size"][y_pos], bbox["size"][z_pos]] additional_axes = [{"name": name, "bounds": (top_left, top_left + size)} for name, top_left, size in zip(bbox["axes"][3:], bbox["topLeft"][3:], bbox["size"][3:])] d["boundingBox"] = {"topLeft": topleft, "width": width, "height": height, "depth": depth} d["additionalAxes"] = additional_axes @@ -293,22 +294,18 @@ def __layer_properties_pre_structure( ) -> Union[LayerProperties, SegmentationLayerProperties]: if d["dataFormat"] == "wkw": d["mags"] = [ - mag_view_properties_pre_unstructure(m) for m in d["wkwResolutions"] + mag_view_properties_pre_structure(m) for m in d["wkwResolutions"] ] del d["wkwResolutions"] # bounding_box and additional_axes are internally handled as nd_bounding_box - bbox = d["boundingBox"] - topleft: List[int] = bbox["topLeft"] - size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] - axes: List[str] = ["x", "y", "z"] if "additionalAxes" in d: - for axis in d["additionalAxes"]: - axes.append(axis["name"]) - topleft.append(axis["bounds"][0]) - size.append(axis["bounds"][1] - axis["bounds"][0]) - nd_bbox = {"topLeft": topleft, "size": size, "axes": axes} - d["boundingBox"] = nd_bbox - del d["additionalAxes"] + d["boundingBox"]["additionalAxes"] = d["additionalAxes"] + del d["additionalAxes"] + if "axisOrder" in (first_mag := d["mags"][0]): + assert all(first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"]) + d["boundingBox"]["axisOrder"] = first_mag["axisOrder"] + + obj = converter_fn(d, type_value) return obj diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index b4e6dfe98..200989bca 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -34,6 +34,7 @@ class BoundingBox(NDBoundingBox): topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) + index: Vec3Int = attr.field(default=Vec3Int(0, 1, 2)) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True @@ -54,7 +55,7 @@ def __attrs_post_init__(self) -> None: object.__setattr__(self, "bottomright", self.topleft + self.size) def with_additional_axis( - self, name: str, extent: Tuple[int, int] + self, name: str, extent: Tuple[int, int], index: Optional[int] = None ) -> "NDBoundingBox": assert name not in self.axes, f"The name '{name}' of the axis is already taken." new_topleft = min(extent) @@ -64,6 +65,7 @@ def with_additional_axis( topleft=(*self.topleft, new_topleft), size=(*self.size, new_size), axes=(*self.axes, name), + index=(*self.index, index if not index is None else max(self.index) + 1) ) def with_bounds_x( diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index d7939379c..cb0be8e7f 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -32,15 +32,16 @@ class NDBoundingBox: topleft: VecInt = attr.field(converter=VecInt) size: VecInt = attr.field(converter=VecInt) axes: Tuple[str, ...] = attr.field(converter=tuple) + index: VecInt = attr.field(converter=VecInt) bottomright: VecInt = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True color: Optional[Tuple[float, float, float, float]] = None def __attrs_post_init__(self) -> None: - assert len(self.topleft) == len(self.size) == len(self.axes), ( - f"The dimensions of topleft, size and axes ({len(self.topleft)}, " - + f"{len(self.size)} and {len(self.axes)} dimensions) do not match." + assert len(self.topleft) == len(self.size) == len(self.axes) == len(self.index), ( + f"The dimensions of topleft, size, axes and index ({len(self.topleft)}, " + + f"{len(self.size)}, {len(self.axes)} and {len(self.index)}) do not match." ) if not self._is_sorted(): self._sort_positions_of_axes() @@ -63,38 +64,23 @@ def __attrs_post_init__(self) -> None: def _sort_positions_of_axes(self) -> None: # Bring topleft and size in required order - # ('x', 'y', 'z', ) + # defined in axisOrder and index of additionalAxes - size, topleft, axes = zip( - *sorted(zip(self.size, self.topleft, self.axes), key=lambda x: x[2]) + size, topleft, axes, index = zip( + *sorted(zip(self.size, self.topleft, self.axes, self.index), key=lambda x: x[3]) ) object.__setattr__(self, "size", VecInt(size)) object.__setattr__(self, "topleft", VecInt(topleft)) object.__setattr__(self, "axes", axes) - try: - source = [self.axes.index("x"), self.axes.index("y"), self.axes.index("z")] - except ValueError as err: - raise ValueError( - "There are at least 3 dimensions needed with names `x`, `y` and `z`." - ) from err - target = [0, 1, 2] - object.__setattr__(self, "size", self.size.moveaxis(source, target)) - object.__setattr__(self, "topleft", self.topleft.moveaxis(source, target)) - object.__setattr__( - self, - "axes", - ("x", "y", "z", *(e for e in self.axes if e not in ["x", "y", "z"])), - ) + object.__setattr__(self, "index", index) def _is_sorted(self) -> bool: - if self.axes[0:3] != ["x", "y", "z"]: - return False return all( - self.axes[i] < self.axes[i + 1] for i in range(3, len(self.axes) - 2) + self.index[i - 1] < self.index[i] for i in range(1, len(self.index)) ) def with_additional_axis( - self, name: str, extent: Tuple[int, int] + self, name: str, extent: Tuple[int, int], index: Optional[int]= None ) -> "NDBoundingBox": assert name not in self.axes, "The identifier of the axis is already taken." start, end = extent @@ -103,6 +89,7 @@ def with_additional_axis( topleft=(*self.topleft, start), size=(*self.size, end - start), axes=(*self.axes, name), + index=(*self.index, index if not index is None else max(self.index) + 1) ) def with_name(self, name: Optional[str]) -> "NDBoundingBox": @@ -158,19 +145,51 @@ def group_boxes_with_aligned_mag( @classmethod def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": - # TODO: include index in nd_bounding_box to clarify axis order - return cls(bbox["topLeft"], bbox["size"], bbox["axes"]) + topleft: List[int] = bbox["topLeft"] + size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] + axes: List[str] = ["x", "y", "z"] + index: List[int] = [0, 1, 2] + + if "axisOrder" in bbox: + axes = list(bbox["axisOrder"].keys()) + index = [bbox["axisOrder"][axis] for axis in axes] + + if "additionalAxes" in bbox: + assert "axisOrder" in bbox, "" + for axis in bbox["additionalAxes"]: + topleft.append(axis["bounds"][0]) + size.append(axis["bounds"][1] - axis["bounds"][0]) + axes.append(axis["name"]) + index.append(axis["index"]) + + return cls(topleft, size, axes, index) def to_wkw_dict(self) -> dict: + topleft = [None, None, None] + size = [None, None, None] + additional_axes = [] + for index, axis in enumerate(self.axes): + if axis == "x": + topleft[0] = self.topleft[index] + size[0] = self.size[index] + elif axis == "y": + topleft[1] = self.topleft[index] + size[1] = self.size[index] + elif axis == "z": + topleft[2] = self.topleft[index] + size[2] = self.size[index] + else: + additional_axes.append({"name": axis, "bounds": [self.topleft[index], self.bottomright[index]], "index": index}) + return { - "topLeft": self.topleft.to_list(), - "size": self.size.to_list(), - "axes": self.axes, + "topLeft": topleft, + "size": size, + "additionalAxes": additional_axes, } def to_config_dict(self) -> dict: - return {"topleft": self.topleft.to_list(), "size": self.size.to_list()} + return {"topleft": self.topleft.to_list(), "size": self.size.to_list(), "axes": self.axes} def to_checkpoint_name(self) -> str: return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" @@ -189,9 +208,7 @@ def __eq__(self, other: object) -> bool: raise NotImplementedError() def _check_compatibility(self, other) -> None: - if self.axes == other.axes: - return - else: + if self.axes != other.axes: raise ValueError( f"Operation with two bboxes is only possible if they have the same axes. {self.axes} != {other.axes}" ) @@ -300,7 +317,7 @@ def align_with_mag( aligned_rounddown = rounddown + margin_to_rounddown if ceil: return attr.evolve( - self, + self, topleft=VecInt(*aligned_roundup, *self.topleft[3:]), size=VecInt(*(aligned_rounddown - aligned_roundup), *self.topleft[3:]) ) @@ -371,7 +388,7 @@ def chunk( for i in range(len(self.axes)) ] ): - yield NDBoundingBox(topleft=coordinates, size=chunk_shape, axes=self.axes) + yield NDBoundingBox(topleft=coordinates, size=chunk_shape, axes=self.axes, index=self.index) def volume(self) -> int: return self.size.prod() From cf36c58200c32632ba72027c665d9ddba11a4b57 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 11 Jan 2024 18:51:47 +0100 Subject: [PATCH 08/41] Working on reading nd data with pims images. --- .../script_collection/reading_nd_data.py | 19 +++++---- .../webknossos/dataset/_utils/pims_images.py | 9 +--- webknossos/webknossos/dataset/dataset.py | 2 +- webknossos/webknossos/dataset/layer.py | 4 +- webknossos/webknossos/dataset/properties.py | 41 +++++++++++++------ .../webknossos/geometry/bounding_box.py | 2 +- 6 files changed, 45 insertions(+), 32 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 95a8dcabd..c74d3fa85 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -4,17 +4,18 @@ import webknossos as wk -TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D-series.ome.tif" +TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" ZARR_PATH = Path("..") / "idr0101A-4d-zarr" +OUTPUT = Path('.') / "testoutput" def from_images_import(): - reader = pims.ImageSequenceND([str(TIF_PATH)]) - print(reader.sizes) - print(isinstance(reader, pims.FramesSequenceND)) - # wk.Dataset.from_images( - # input_path, output_path, voxel_size=(10, 10, 10), data_format="zarr3" - # ) + # reader = pims.Bioformats(str(TIF_PATH)) + # print(reader.sizes) + # print(isinstance(reader, pims.FramesSequenceND)) + wk.Dataset.from_images( + TIF_PATH, OUTPUT, voxel_size=(10, 10, 10), data_format="zarr3", use_bioformats=True + ) def open_existing_dataset(): @@ -28,8 +29,8 @@ def open_existing_dataset(): def main() -> None: """Imports a dataset with more than 3 dimensions.""" - # from_images_import() - open_existing_dataset() + from_images_import() + # open_existing_dataset() if __name__ == "__main__": diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 7f63f8434..ff074f977 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -143,11 +143,6 @@ def __init__( self.dtype = images.dtype if isinstance(images, pims.FramesSequenceND): - # TODO: assertion that phrohibites nd data - assert all( - axis in "xyzct" for axis in images.axes - ), f"Found unknown axes {set(images.axes) - set('xyzct')}" - self._default_coords = {} self._init_c_axis = False if isinstance(images, pims.imageio_reader.ImageIOReader): @@ -512,8 +507,8 @@ def copy_to_view( for image_slice in images[z_start:z_end]: image_slice = np.array(image_slice) # place channels first - if self._img_dims.endswith("c"): - image_slice = np.moveaxis(image_slice, source=-1, destination=0) + if "c" in self._img_dims: + image_slice = np.moveaxis(image_slice, source=self._img_dims.index("c"), destination=0) # ensure the last two axes are xy: if ("yx" in self._img_dims and not self._swap_xy) or ( "xy" in self._img_dims and self._swap_xy diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index a0c5228d9..37775986a 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -819,7 +819,7 @@ def add_layer( layer_properties = LayerProperties( name=layer_name, category=category, - bounding_box=bounding_box or NDBoundingBox((0, 0, 0), (0, 0, 0), ("x", "y", "z")), + bounding_box=bounding_box or BoundingBox((0, 0, 0), (0, 0, 0)), element_class=_dtype_per_channel_to_element_class( dtype_per_channel, num_channels ), diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index c7da38980..750594878 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -419,7 +419,7 @@ def add_mag( else None ), axis_order=( - {"x": 1, "y": 2, "z": 3, "c": 0} + {key: value for key, value in zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))} if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) else None ), @@ -456,7 +456,7 @@ def add_mag_for_existing_files( else None ), axis_order=( - {"x": 1, "y": 2, "z": 3, "c": 0} + {key: value for key, value in zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))} if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) else None ), diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 841b3c337..12bb6062d 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -6,6 +6,8 @@ import numpy as np from cattr.gen import make_dict_structure_fn, make_dict_unstructure_fn, override +from webknossos.geometry.bounding_box import BoundingBox + from ..geometry import Mag, NDBoundingBox, Vec3Int from ..utils import snake_to_camel_case, warn_deprecated from ._array import ArrayException, BaseArray, DataFormat @@ -140,7 +142,7 @@ class AxisProperties: class LayerProperties: name: str category: LayerCategoryType - bounding_box: NDBoundingBox + bounding_box: Union[BoundingBox, NDBoundingBox] element_class: str data_format: DataFormat mags: List[MagViewProperties] @@ -268,12 +270,13 @@ def __layer_properties_post_unstructure( del d["mags"] # json expects nd_bounding_box to be represented as bounding_box and additional_axes bbox = d["boundingBox"] - x_pos, y_pos, z_pos = bbox["axes"].index("x"), bbox["axes"].index("y"), bbox["axes"].index("z") - topleft: List[int] = [bbox["topLeft"][x_pos], bbox["topLeft"][y_pos], bbox["topLeft"][z_pos]] - width, height, depth = [bbox["size"][x_pos], bbox["size"][y_pos], bbox["size"][z_pos]] - additional_axes = [{"name": name, "bounds": (top_left, top_left + size)} for name, top_left, size in zip(bbox["axes"][3:], bbox["topLeft"][3:], bbox["size"][3:])] - d["boundingBox"] = {"topLeft": topleft, "width": width, "height": height, "depth": depth} - d["additionalAxes"] = additional_axes + if "axes" in bbox: + x_pos, y_pos, z_pos = bbox["axes"].index("x"), bbox["axes"].index("y"), bbox["axes"].index("z") + topleft: List[int] = [bbox["topLeft"][x_pos], bbox["topLeft"][y_pos], bbox["topLeft"][z_pos]] + width, height, depth = [bbox["size"][x_pos], bbox["size"][y_pos], bbox["size"][z_pos]] + additional_axes = [{"name": name, "bounds": (top_left, top_left + size)} for name, top_left, size in zip(bbox["axes"][3:], bbox["topLeft"][3:], bbox["size"][3:])] + d["boundingBox"] = {"topLeft": topleft, "width": width, "height": height, "depth": depth} + d["additionalAxes"] = additional_axes return d return __layer_properties_post_unstructure @@ -301,9 +304,13 @@ def __layer_properties_pre_structure( if "additionalAxes" in d: d["boundingBox"]["additionalAxes"] = d["additionalAxes"] del d["additionalAxes"] - if "axisOrder" in (first_mag := d["mags"][0]): - assert all(first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"]) - d["boundingBox"]["axisOrder"] = first_mag["axisOrder"] + if len(d["mags"]) > 0: + first_mag = d["mags"][0] + if "axisOrder" in first_mag: + assert first_mag["axisOrder"]["c"] == 0 + assert all(first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"]) + d["boundingBox"]["axisOrder"] = first_mag["axisOrder"] + del d["boundingBox"]["axisOrder"]["c"] obj = converter_fn(d, type_value) @@ -311,6 +318,16 @@ def __layer_properties_pre_structure( return __layer_properties_pre_structure +def disambiguate_bounding_box(obj: dict, _: Any) -> Union[BoundingBox, NDBoundingBox]: + if "additionalAxes" in obj: + return dataset_converter.structure(obj, NDBoundingBox) + else: + return dataset_converter.structure(obj, BoundingBox) + + +dataset_converter.register_structure_hook( + Union[BoundingBox, NDBoundingBox], disambiguate_bounding_box, +) for cls in [ LayerProperties, @@ -357,7 +374,7 @@ def disambiguate_layer_properties(obj: dict, _: Any) -> LayerProperties: raise RuntimeError( "Failed to read the properties of a layer: the category has to be `color` or `segmentation`." ) - + dataset_converter.register_structure_hook( Union[ @@ -365,4 +382,4 @@ def disambiguate_layer_properties(obj: dict, _: Any) -> LayerProperties: LayerProperties, ], disambiguate_layer_properties, -) +) \ No newline at end of file diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 200989bca..0bb32413c 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -34,7 +34,7 @@ class BoundingBox(NDBoundingBox): topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) - index: Vec3Int = attr.field(default=Vec3Int(0, 1, 2)) + index: Vec3Int = attr.field(default=Vec3Int(1, 2, 3)) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True From 4033eb008a740bbed18d9645236dfecfb884d0ae Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 16 Jan 2024 18:23:50 +0100 Subject: [PATCH 09/41] Modify pims images to support more _iter_dims. --- .../webknossos/dataset/_utils/pims_images.py | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index ff074f977..cbf982d32 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -168,27 +168,31 @@ def __init__( self._default_coords["c"] = 0 self._img_dims = "yx" - self._iter_dim = "" - - if images.sizes.get("z", 1) > 1: - self._iter_dim = "z" - elif "z" in images.axes: - self._default_coords["z"] = 0 - - if timepoint is None: - if images.sizes.get("t", 1) > 1: - if self._iter_dim == "": - self._iter_dim = "t" - else: - self._default_coords["t"] = 0 - self._possible_layers["timepoint"] = list( - range(0, images.sizes["t"]) - ) - elif "t" in images.axes: - self._default_coords["t"] = 0 - else: - assert "t" in images.axes - self._default_coords["t"] = timepoint + _iter_dim = [] + for axis in images.sizes: + if axis not in ["x", "y", "c"]: + _iter_dim.append(axis) + self._iter_dim = tuple(_iter_dim) + + # if images.sizes.get("z", 1) > 1: + # self._iter_dim = "z" + # elif "z" in images.axes: + # self._default_coords["z"] = 0 + + # if timepoint is None: + # if images.sizes.get("t", 1) > 1: + # if self._iter_dim == "": + # self._iter_dim = "t" + # else: + # self._default_coords["t"] = 0 + # self._possible_layers["timepoint"] = list( + # range(0, images.sizes["t"]) + # ) + # elif "t" in images.axes: + # self._default_coords["t"] = 0 + # else: + # assert "t" in images.axes + # self._default_coords["t"] = timepoint else: # Fallback for generic pims classes that do not name their # dimensions as pims.FramesSequenceND does: From ae291055bb19a18005486c12a209b9887da7106c Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 18 Jan 2024 09:57:30 +0100 Subject: [PATCH 10/41] Add method for expected bounding box instead of expected shape in pims images. --- .../webknossos/dataset/_utils/pims_images.py | 48 +++++++++++++------ webknossos/webknossos/dataset/dataset.py | 10 ++-- webknossos/webknossos/dataset/layer.py | 5 +- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index cbf982d32..01186661f 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -1,5 +1,6 @@ import warnings from contextlib import contextmanager, nullcontext +from functools import cached_property from itertools import chain from os import PathLike from pathlib import Path @@ -24,6 +25,9 @@ from natsort import natsorted from numpy.typing import DTypeLike +from webknossos.geometry.bounding_box import BoundingBox +from webknossos.geometry.nd_bounding_box import NDBoundingBox + # pylint: disable=unused-import try: from .pims_czi_reader import PimsCziReader @@ -261,12 +265,6 @@ def __init__( ############################# with self._open_images() as images: - if isinstance(images, list): - images_shape = (len(images),) + cast( - pims.FramesSequence, images[0] - ).shape - else: - images_shape = images.shape # pylint: disable=no-member c_index = self._img_dims.find("c") if c_index == -1: self.num_channels = 1 @@ -276,14 +274,6 @@ def __init__( # images_shape corresponds to (z, *_img_dims) self.num_channels = images_shape[c_index + 1] - x_index = self._img_dims.find("x") + 1 - y_index = self._img_dims.find("y") + 1 - if swap_xy: - x_index, y_index = y_index, x_index - self.expected_shape = Vec3Int( - images_shape[x_index], images_shape[y_index], images_shape[0] - ) - self._first_n_channels = None if self._channel is not None: assert ( @@ -550,6 +540,34 @@ def get_possible_layers(self) -> Optional[Dict["str", List[int]]]: else: return self._possible_layers + @cached_property + def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: + with self._open_images() as images: + if isinstance(images, list): + images_shape = (len(images),) + cast( + pims.FramesSequence, images[0] + ).shape + else: + images_shape = images.shape # pylint: disable=no-member + x_index = self._img_dims.find("x") + 1 + y_index = self._img_dims.find("y") + 1 + if self._swap_xy: + x_index, y_index = y_index, x_index + if self._iter_dim is None or len(self._iter_dim) == 0: + return BoundingBox((0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0])) + else: + axes = {"x": images_shape[x_index], "y": images_shape[y_index]} + with self._open_images() as images: + for axis in self._iter_dim: + if images.sizes is not None: + axes[axis] = images.sizes[axis] + else: + axes[axis] = 0 + topleft = VecInt.zeros(len(axes)) + axes_names, size = zip(*axes.items()) + + return NDBoundingBox(topleft, size, axes_names, index=(i+1 for i, _ in enumerate(axes_names))) + T = TypeVar("T", bound=Tuple[int, ...]) @@ -607,4 +625,4 @@ def has_image_z_dimension( flip_z=False, ) - return pims_images.expected_shape.z > 1 + return pims_images.expected_bbox. > 1 diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 37775986a..2be4d2461 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -35,6 +35,7 @@ from upath import UPath from cluster_tools import Executor +from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset from ..geometry.vec3_int import Vec3Int, Vec3IntLike @@ -1018,7 +1019,7 @@ def add_layer_from_images( compress: bool = False, *, ## other arguments - topleft: Vec3IntLike = Vec3Int.zeros(), # in Mag(1) + topleft: VecIntLike = Vec3Int.zeros(), # in Mag(1) swap_xy: bool = False, flip_x: bool = False, flip_y: bool = False, @@ -1091,6 +1092,7 @@ def add_layer_from_images( is_segmentation=category == "segmentation", ) possible_layers = pims_images.get_possible_layers() + additional_axes = pims_images.get_additional_axes() # Check if 4 color channels should be converted to # 3 color channels (rbg) if ( @@ -1204,11 +1206,7 @@ def add_layer_from_images( compress=compress, ) mag = mag_view.mag - layer.bounding_box = ( - BoundingBox((0, 0, 0), pims_images.expected_shape) - .from_mag_to_mag1(mag) - .offset(topleft) - ) + layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset(topleft) if batch_size is None: if compress: diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 750594878..138c1630b 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -13,6 +13,7 @@ from upath import UPath from cluster_tools import Executor +from webknossos.geometry.nd_bounding_box import NDBoundingBox from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike from ._array import ArrayException, BaseArray, DataFormat @@ -254,11 +255,11 @@ def dataset(self) -> "Dataset": return self._dataset @property - def bounding_box(self) -> BoundingBox: + def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: return self._properties.bounding_box @bounding_box.setter - def bounding_box(self, bbox: BoundingBox) -> None: + def bounding_box(self, bbox: Union[NDBoundingBox, BoundingBox]) -> None: """ Updates the offset and size of the bounding box of this layer in the properties. """ From f7ffb6b95454b124b6dd7d560e8bc04c93cd22c1 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 18 Jan 2024 19:05:18 +0100 Subject: [PATCH 11/41] Adding functions for editing ndboundingbox in 3d and update import from_images. --- webknossos/webknossos/dataset/_array.py | 2 +- .../dataset/_utils/buffered_slice_writer.py | 6 +- .../webknossos/dataset/_utils/pims_images.py | 15 +++-- webknossos/webknossos/dataset/dataset.py | 28 ++++++---- webknossos/webknossos/dataset/layer.py | 2 +- webknossos/webknossos/dataset/view.py | 14 ++++- .../webknossos/geometry/nd_bounding_box.py | 55 ++++++++++++++++--- webknossos/webknossos/geometry/vec3_int.py | 22 ++++++++ webknossos/webknossos/geometry/vec_int.py | 25 --------- 9 files changed, 113 insertions(+), 56 deletions(-) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index bb57fd9e9..97eaa940a 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -605,7 +605,7 @@ def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: def ensure_size( self, new_shape: Vec3IntLike, align_with_shards: bool = True, warn: bool = False ) -> None: - new_shape = Vec3Int(new_shape.to_xyz()) + new_shape = Vec3Int(new_shape) zarray = self._zarray new_shape_tuple = ( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 95aec77e1..98f165ec9 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -4,11 +4,13 @@ from logging import error, info from os import getpid from types import TracebackType -from typing import TYPE_CHECKING, Generator, List, Optional, Type +from typing import TYPE_CHECKING, Generator, List, Optional, Type, Union import numpy as np import psutil +from webknossos.geometry.nd_bounding_box import NDBoundingBox + from ...geometry import BoundingBox, Vec3Int, Vec3IntLike if TYPE_CHECKING: @@ -43,6 +45,8 @@ def __init__( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, use_logging: bool = False, ) -> None: """see `View.get_buffered_slice_writer()`""" diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 01186661f..ed134949e 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -73,7 +73,6 @@ def _assume_color_channel(dim_size: int, dtype: np.dtype) -> bool: class PimsImages: dtype: DTypeLike - expected_shape: VecInt num_channels: int def __init__( @@ -132,7 +131,6 @@ def __init__( ## attributes that will also be set in __init__() # dtype - # expected_shape # num_channels # _first_n_channels @@ -470,7 +468,7 @@ def _open_images( def copy_to_view( self, - args: Tuple[int, int], + args: Tuple[int, int, Optional[Dict[str, int]]], mag_view: MagView, is_segmentation: bool, dtype: Optional[DTypeLike] = None, @@ -480,7 +478,7 @@ def copy_to_view( copy_to_view returns an iterable of image shapes and largest segment ids. When using this method a manual update of the bounding box and the largest segment id might be necessary. """ - z_start, z_end = args + z_start, z_end, additional_axes_args = args shapes = [] max_id: Optional[int] if is_segmentation: @@ -492,6 +490,9 @@ def copy_to_view( if self._flip_z: images = images[::-1] # pylint: disable=unsubscriptable-object with mag_view.get_buffered_slice_writer( + # TODO according to the additional_axes_args a relative bounding box is + # computed that is passed to the buffered slice writer + relative_bounding_box=NDBoundingBox(topleft=(0, 0, z_start * mag_view.mag.z) ...) relative_offset=(0, 0, z_start * mag_view.mag.z), buffer_size=mag_view.info.chunk_shape.z, # copy_to_view is typically used in a multiprocessing-context. Therefore the @@ -542,6 +543,7 @@ def get_possible_layers(self) -> Optional[Dict["str", List[int]]]: @cached_property def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: + # replaces the previous expected_shape to enable n-dimensional input files with self._open_images() as images: if isinstance(images, list): images_shape = (len(images),) + cast( @@ -553,6 +555,7 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: y_index = self._img_dims.find("y") + 1 if self._swap_xy: x_index, y_index = y_index, x_index + if self._iter_dim is None or len(self._iter_dim) == 0: return BoundingBox((0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0])) else: @@ -565,7 +568,7 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: axes[axis] = 0 topleft = VecInt.zeros(len(axes)) axes_names, size = zip(*axes.items()) - + #TODO get current axis order from file and use it for nd bbbox return NDBoundingBox(topleft, size, axes_names, index=(i+1 for i, _ in enumerate(axes_names))) @@ -625,4 +628,4 @@ def has_image_z_dimension( flip_z=False, ) - return pims_images.expected_bbox. > 1 + return pims_images.expected_bbox.get_shape("z") > 1 diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 2be4d2461..69dc458f5 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1092,7 +1092,6 @@ def add_layer_from_images( is_segmentation=category == "segmentation", ) possible_layers = pims_images.get_possible_layers() - additional_axes = pims_images.get_additional_axes() # Check if 4 color channels should be converted to # 3 color channels (rbg) if ( @@ -1187,8 +1186,9 @@ def add_layer_from_images( num_channels=pims_images.num_channels, **add_layer_kwargs, # type: ignore[arg-type] ) + # When the expected bbox is 2D the chunk_shape is set to 2D too. if ( - pims_images.expected_shape.z == 1 + pims_images.expected_bbox.get_shape("z") == 1 and layer.data_format == DataFormat.Zarr ): if chunk_shape is None: @@ -1230,11 +1230,19 @@ def add_layer_from_images( ) args = [] - for z_start in range(0, pims_images.expected_shape.z, batch_size): - z_end = min(z_start + batch_size, pims_images.expected_shape.z) - # return shapes and set to union when using --pad - args.append((z_start, z_end)) - print(args) + additional_axes_args = {x: 0 for x in pims_images.expected_bbox.axes if x not in ("x", "y", "z")} + z_shape = pims_images.expected_bbox.get_shape("z") + for z_start in range(0, z_shape, batch_size): + z_end = min(z_start + batch_size, z_shape) + if not additional_axes_args: + args.append((z_start, z_end)) + else: + for axis in additional_axes_args: + axis_shape = pims_images.expected_bbox.get_shape(axis) + for axis_index in range(0, axis_shape): + additional_axes_args[axis] = axis_index + args.append((z_start, z_end, additional_axes_args)) + with warnings.catch_warnings(): # Block alignmnent within the dataset should not be a problem, since shard-wise chunking is enforced. # However, dataset borders might change between different parallelized writes, when sizes differ. @@ -1264,17 +1272,17 @@ def add_layer_from_images( max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id actual_size = Vec3Int( - dimwise_max(shapes) + (pims_images.expected_shape.z,) + dimwise_max(shapes) + (pims_images.expected_bbox.get_shape("z"),) ) layer.bounding_box = ( BoundingBox((0, 0, 0), actual_size) .from_mag_to_mag1(mag) .offset(topleft) ) - if pims_images.expected_shape != actual_size: + if pims_images.expected_bbox != actual_size: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " - + f"New size is {actual_size}, expected {pims_images.expected_shape}." + + f"New size is {actual_size}, expected {pims_images.expected_bbox.get_shape('z')}." ) if first_layer is None: first_layer = layer diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 138c1630b..db069336a 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -271,7 +271,7 @@ def bounding_box(self, bbox: Union[NDBoundingBox, BoundingBox]) -> None: self.dataset._export_as_json() for mag in self.mags.values(): mag._array.ensure_size( - bbox.align_with_mag(mag.mag).in_mag(mag.mag).bottomright + bbox.align_with_mag(mag.mag).in_mag(mag.mag).get_3d("bottomright") ) @property diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index b9606f25a..e4a863401 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -13,13 +13,15 @@ Optional, Tuple, Type, + Union, ) import numpy as np import wkw + from cluster_tools import Executor -from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike +from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike from ..utils import ( get_executor_for_args, get_rich_progress, @@ -674,6 +676,8 @@ def get_buffered_slice_writer( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 use_logging: bool = False, ) -> "BufferedSliceWriter": """ @@ -682,8 +686,10 @@ def get_buffered_slice_writer( Arguments: * The user can specify where the writer should start: - * `relative_offset` in Mag(1) - * `absolute_offset` in Mag(1) + * `relative_offset` in Mag(1) -> not usable for n-dimensional data + * `absolute_offset` in Mag(1) -> not usable for n-dimensional data + * `relative_bounding_box` in Mag(1) + * `absolute_bounding_box` in Mag(1) * ⚠️ deprecated: `offset` in the current Mag, used to be relative for `View` and absolute for `MagView` * `buffer_size`: amount of slices that get buffered @@ -717,6 +723,8 @@ def get_buffered_slice_writer( dimension=dimension, relative_offset=relative_offset, absolute_offset=absolute_offset, + relative_bounding_box=relative_bounding_box, + absolute_bounding_box=absolute_bounding_box, use_logging=use_logging, ) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index cb0be8e7f..9b4b64b0a 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -206,6 +206,33 @@ def __eq__(self, other: object) -> bool: return self.topleft == other.topleft and self.size == other.size else: raise NotImplementedError() + + def get_shape(self, key) -> int: + try: + index = self.axes.index(key) + return self.size[index] + except ValueError as err: + raise ValueError(f"Axis {key} doesn't exist in NDBoundingBox.") from err + + def get_3d(self, attr_name: str) -> Vec3Int: + axes = ("x", "y", "z") + attr_3d = [] + + for axis in axes: + index = self.axes.index(axis) + attr_3d.append(getattr(self, attr_name)[index]) + + return Vec3Int(attr_3d) + + def set_3d(self, attr_name: str, value: Vec3Int) -> VecInt: + axes = ("x", "y", "z") + modified_attr = getattr(self, attr_name).to_list() + + for i, axis in enumerate(axes): + index = self.axes.index(axis) + modified_attr[index] = value[i] + + return VecInt(modified_attr) def _check_compatibility(self, other) -> None: if self.axes != other.axes: @@ -257,24 +284,29 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": mag_vec = mag.to_vec3_int() assert ( - Vec3Int(self.topleft.to_xyz()) % mag_vec == Vec3Int.zeros() + self.get_3d("topleft") % mag_vec == Vec3Int.zeros() ), f"topleft {self.topleft} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." assert ( - Vec3Int(self.bottomright.to_xyz()) % mag_vec == Vec3Int.zeros() + self.get_3d("bottomright") % mag_vec == Vec3Int.zeros() ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." + new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") * mag_vec)) + new_size = self.set_3d("size", Vec3Int(self.get_3d("size") * mag_vec)) + return attr.evolve( self, - topleft=VecInt(*Vec3Int(self.topleft.to_xyz()) // mag_vec, *self.topleft[3:]), - size=VecInt(*Vec3Int(self.size.to_xyz()) // mag_vec, *self.size[3:]), + topleft=new_topleft, + size=new_size, ) def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": mag_vec = from_mag.to_vec3_int() + new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") * mag_vec)) + new_size = self.set_3d("size", Vec3Int(self.get_3d("size") * mag_vec)) return attr.evolve( self, - topleft=VecInt(*Vec3Int(self.topleft) * mag_vec, *self.topleft[3:]), - size=VecInt(*Vec3Int(self.size) * mag_vec, *self.size[3:]), + topleft=new_topleft, + size=new_size, ) def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": @@ -307,8 +339,8 @@ def align_with_mag( # This does the same as _align_with_mag_slow, which is more readable. # Same behavior is asserted in test_align_with_mag_against_numpy_implementation mag_vec = mag.to_vec3_int() if isinstance(mag, Mag) else mag - topleft = Vec3Int(self.topleft[:3]) - bottomright= Vec3Int(self.bottomright[:3]) + topleft = self.get_3d("topleft") + bottomright= self.get_3d("bottomright") roundup = topleft if ceil else bottomright rounddown = bottomright if ceil else topleft margin_to_roundup = roundup % mag_vec @@ -408,4 +440,9 @@ def to_slices(self) -> Tuple[slice, slice, slice]: ] def offset(self, vector: VecIntLike) -> "NDBoundingBox": - return attr.evolve(self, topleft=self.topleft + VecInt(vector)) + vec_int = VecInt(vector) + if len(vec_int) == 3: + new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") + vec_int)) + return attr.evolve(self, topleft=new_topleft) + else: + return attr.evolve(self, topleft=self.topleft + vec_int) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 6f25c8027..31f8e97f8 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -54,6 +54,28 @@ def __new__( return cast(cls, super().__new__(cls, as_tuple)) + + @property + def x(self) -> int: + return self[0] + + @property + def y(self) -> int: + return self[1] + + @property + def z(self) -> int: + return self[2] + + def with_x(self, new_x: int) -> "Vec3Int": + return Vec3Int.from_xyz(new_x, self.y, self.z) + + def with_y(self, new_y: int) -> "Vec3Int": + return Vec3Int.from_xyz(self.x, new_y, self.z) + + def with_z(self, new_z: int) -> "Vec3Int": + return Vec3Int.from_xyz(self.x, self.y, new_z) + @staticmethod def from_xyz(x: int, y: int, z: int) -> "Vec3Int": """Use Vec3Int.from_xyz for fast construction.""" diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index 5e7b2ebf1..2b524e4fb 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -72,27 +72,6 @@ def __new__( def from_str(string: str) -> "VecInt": return VecInt(tuple(map(int, re.findall(r"\d+", string)))) - @property - def x(self) -> int: - return self[0] - - @property - def y(self) -> int: - return self[1] - - @property - def z(self) -> int: - return self[2] - - def with_x(self, new_x: int) -> "VecInt": - return self.__class__(new_x, self.y, self.z, *self[3:]) - - def with_y(self, new_y: int) -> "VecInt": - return self.__class__(self.x, new_y, self.z, *self[3:]) - - def with_z(self, new_z: int) -> "VecInt": - return self.__class__(self.x, self.y, new_z, *self[3:]) - def with_replaced(self, index: int, new_element: int) -> "VecInt": """Returns a new ND Vector with a replaced element at a given index.""" @@ -107,10 +86,6 @@ def to_list(self) -> List[int]: def to_tuple(self) -> Tuple[int, ...]: return tuple(self) - def to_xyz(self) -> Tuple[int, int, int]: - """Returns the x, y and z component of the n dimensional vector. Other axes are ignored.""" - return (self.x, self.y, self.z) - def contains(self, needle: int) -> bool: return any(element == needle for element in self) From 21bb0ea8ebf4877ff6361a4079964f89eee6dd2b Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 22 Jan 2024 19:17:37 +0100 Subject: [PATCH 12/41] Propagade nd-bounding box to different methods that take care of writing the dataset. --- webknossos/examples/download_segments.py | 2 +- webknossos/examples/download_tiff_stack.py | 2 +- .../dataset/_utils/buffered_slice_writer.py | 14 +++++-- .../webknossos/dataset/_utils/pims_images.py | 32 +++++++++------ webknossos/webknossos/dataset/dataset.py | 21 ++++++---- webknossos/webknossos/dataset/layer.py | 2 +- webknossos/webknossos/dataset/mag_view.py | 17 +++++--- webknossos/webknossos/dataset/view.py | 23 +++++++---- .../webknossos/geometry/bounding_box.py | 41 ------------------- .../webknossos/geometry/nd_bounding_box.py | 22 ++++++---- 10 files changed, 86 insertions(+), 90 deletions(-) diff --git a/webknossos/examples/download_segments.py b/webknossos/examples/download_segments.py index 581ec6316..33e4f9bef 100644 --- a/webknossos/examples/download_segments.py +++ b/webknossos/examples/download_segments.py @@ -14,7 +14,7 @@ def main() -> None: ) mag_view = dataset.get_segmentation_layers()[0].get_mag(MAG) - z = mag_view.bounding_box.topleft.z + z = mag_view.bounding_box.get_bounds("z")[0] with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/examples/download_tiff_stack.py b/webknossos/examples/download_tiff_stack.py index 293dbe5e6..56aaff8ad 100644 --- a/webknossos/examples/download_tiff_stack.py +++ b/webknossos/examples/download_tiff_stack.py @@ -15,7 +15,7 @@ def main() -> None: ) mag_view = dataset.get_layer(LAYER_NAME).get_mag(MAG) - z = mag_view.bounding_box.topleft.z + z = mag_view.bounding_box.get_bounds("z")[0] with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 98f165ec9..8021ed075 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -56,7 +56,7 @@ def __init__( self.dtype = self.view.get_dtype() self.use_logging = use_logging self.json_update_allowed = json_update_allowed - if offset is None and relative_offset is None and absolute_offset is None: + if offset is None and relative_offset is None and absolute_offset is None and relative_bounding_box is None and absolute_bounding_box is None: relative_offset = Vec3Int.zeros() if offset is not None: warnings.warn( @@ -80,6 +80,14 @@ def __init__( if self.absolute_offset is not None: effective_offset = self.absolute_offset + if relative_bounding_box is not None: + effective_offset = self.view.bounding_box.get_3d("topleft") + relative_bounding_box.get_3d("topleft") + + if absolute_bounding_box is not None: + effective_offset = absolute_bounding_box.get_3d("topleft") + + self.absolute_offset = effective_offset + view_chunk_depth = self.view.info.chunk_shape[self.dimension] if ( effective_offset is not None @@ -94,8 +102,8 @@ def __init__( "[WARNING] Using a buffer size that doesn't align with the datataset's chunk size, " + "will slow down the buffered slice writer.", ) - - assert 0 <= dimension <= 2 + # Previously the dimension was x, y or z now it can possibly be any axis of the bounding_box + #assert 0 <= dimension <= 2 self.slices_to_write: List[np.ndarray] = [] self.current_slice: Optional[int] = None diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index ed134949e..07932a4f3 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -267,6 +267,12 @@ def __init__( if c_index == -1: self.num_channels = 1 else: + if isinstance(images, list): + images_shape = (len(images),) + cast( + pims.FramesSequence, images[0] + ).shape + else: + images_shape = images.shape # Since images_shape contains the first dimension iter_dim, # we need to offset the index by one before accessing the images_shape. # images_shape corresponds to (z, *_img_dims) @@ -468,7 +474,7 @@ def _open_images( def copy_to_view( self, - args: Tuple[int, int, Optional[Dict[str, int]]], + args: Union[BoundingBox, NDBoundingBox], mag_view: MagView, is_segmentation: bool, dtype: Optional[DTypeLike] = None, @@ -478,7 +484,8 @@ def copy_to_view( copy_to_view returns an iterable of image shapes and largest segment ids. When using this method a manual update of the bounding box and the largest segment id might be necessary. """ - z_start, z_end, additional_axes_args = args + relative_bbox = args + z_start, z_end = relative_bbox.get_bounds("z") shapes = [] max_id: Optional[int] if is_segmentation: @@ -489,11 +496,13 @@ def copy_to_view( with self._open_images() as images: if self._flip_z: images = images[::-1] # pylint: disable=unsubscriptable-object + + with mag_view.get_buffered_slice_writer( - # TODO according to the additional_axes_args a relative bounding box is - # computed that is passed to the buffered slice writer - relative_bounding_box=NDBoundingBox(topleft=(0, 0, z_start * mag_view.mag.z) ...) - relative_offset=(0, 0, z_start * mag_view.mag.z), + # Previously only z_start and its end were important, now the slice writer needs to know + # which axis is currently written. + relative_bounding_box=relative_bbox, + #relative_offset=(0, 0, z_start * mag_view.mag.z), buffer_size=mag_view.info.chunk_shape.z, # copy_to_view is typically used in a multiprocessing-context. Therefore the # buffered slice writer should not update the json file to avoid race conditions. @@ -560,12 +569,11 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: return BoundingBox((0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0])) else: axes = {"x": images_shape[x_index], "y": images_shape[y_index]} - with self._open_images() as images: - for axis in self._iter_dim: - if images.sizes is not None: - axes[axis] = images.sizes[axis] - else: - axes[axis] = 0 + for axis in self._iter_dim: + if hasattr(images, "sizes"): + axes[axis] = images.sizes[axis] + else: + axes[axis] = 0 topleft = VecInt.zeros(len(axes)) axes_names, size = zip(*axes.items()) #TODO get current axis order from file and use it for nd bbbox diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 69dc458f5..b5d45f291 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1230,18 +1230,21 @@ def add_layer_from_images( ) args = [] - additional_axes_args = {x: 0 for x in pims_images.expected_bbox.axes if x not in ("x", "y", "z")} - z_shape = pims_images.expected_bbox.get_shape("z") + bbox = pims_images.expected_bbox + additional_axes = [axis_name for axis_name in bbox.axes if axis_name not in ("x", "y", "z")] + additional_axes_shapes = product(*[range(bbox.get_shape(axis_name)) for axis_name in additional_axes]) + z_shape = bbox.get_shape("z") for z_start in range(0, z_shape, batch_size): z_end = min(z_start + batch_size, z_shape) - if not additional_axes_args: - args.append((z_start, z_end)) + z_bbox = bbox.with_bounds("z", z_start, z_end) + if not additional_axes: + args.append(z_bbox) else: - for axis in additional_axes_args: - axis_shape = pims_images.expected_bbox.get_shape(axis) - for axis_index in range(0, axis_shape): - additional_axes_args[axis] = axis_index - args.append((z_start, z_end, additional_axes_args)) + for shape in additional_axes_shapes: + reduced_bbox = z_bbox + for index, axis in enumerate(additional_axes): + reduced_bbox = reduced_bbox.with_bounds(axis, shape[index], shape[index]+1) + args.append(reduced_bbox) with warnings.catch_warnings(): # Block alignmnent within the dataset should not be a problem, since shard-wise chunking is enforced. diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index db069336a..1002867bb 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -420,7 +420,7 @@ def add_mag( else None ), axis_order=( - {key: value for key, value in zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))} + dict(zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))) if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) else None ), diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 6a5e6fcd8..5cd6221da 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,10 +7,11 @@ from uuid import uuid4 import numpy as np -from cluster_tools import Executor from upath import UPath -from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike +from cluster_tools import Executor + +from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( NDArrayLike, get_executor_for_args, @@ -93,7 +94,7 @@ def __init__( # Overwrites of View methods: @property - def bounding_box(self) -> BoundingBox: + def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: # Overwrites View's method since no extra bbox is stored for a MagView, # but the Layer's bbox is used: return self.layer.bounding_box.align_with_mag(self._mag, ceil=True) @@ -110,7 +111,7 @@ def global_offset(self) -> Vec3Int: return Vec3Int.zeros() @property - def size(self) -> Vec3Int: + def size(self) -> VecInt: """⚠️ Deprecated, use `mag_view.bounding_box.in_mag(mag_view.mag).bottomright` instead.""" warnings.warn( "[DEPRECATION] mag_view.size is deprecated. " @@ -154,6 +155,8 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 ) -> None: if offset is not None: if self._mag == Mag(1): @@ -171,13 +174,15 @@ def write( DeprecationWarning, ) - if all(i is None for i in [offset, absolute_offset, relative_offset]): + if all(i is None for i in [offset, absolute_offset, relative_offset, absolute_bounding_box, relative_bounding_box]): relative_offset = Vec3Int.zeros() mag1_bbox = self._get_mag1_bbox( abs_current_mag_offset=offset, rel_mag1_offset=relative_offset, abs_mag1_offset=absolute_offset, + abs_mag1_bbox=absolute_bounding_box, + rel_mag1_bbox=relative_bounding_box, current_mag_size=Vec3Int(data.shape[-3:]), ) @@ -263,7 +268,7 @@ def get_view( def get_bounding_boxes_on_disk( self, - ) -> Iterator[BoundingBox]: + ) -> Iterator[Union[NDBoundingBox, BoundingBox]]: """ Returns a Mag(1) bounding box for each file on disk. diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index e4a863401..3da8ccd2e 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -20,6 +20,7 @@ import wkw from cluster_tools import Executor +from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike from ..utils import ( @@ -56,7 +57,7 @@ class View: _path: Path _array_info: ArrayInfo - _bounding_box: Optional[BoundingBox] + _bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] _read_only: bool _cached_array: Optional[BaseArray] _mag: Mag @@ -66,7 +67,7 @@ def __init__( path_to_mag_view: Path, array_info: ArrayInfo, bounding_box: Optional[ - BoundingBox + Union[NDBoundingBox, BoundingBox] ], # in mag 1, absolute coordinates, optional only for mag_view since it overwrites the bounding_box property mag: Mag, read_only: bool = False, @@ -95,7 +96,7 @@ def header(self) -> wkw.Header: return self._array._wkw_dataset.header @property - def bounding_box(self) -> BoundingBox: + def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: assert self._bounding_box is not None return self._bounding_box @@ -108,7 +109,7 @@ def read_only(self) -> bool: return self._read_only @property - def global_offset(self) -> Vec3Int: + def global_offset(self) -> VecInt: """⚠️ Deprecated, use `view.bounding_box.in_mag(view.mag).topleft` instead.""" warnings.warn( "[DEPRECATION] view.global_offset is deprecated. " @@ -119,7 +120,7 @@ def global_offset(self) -> Vec3Int: return self.bounding_box.in_mag(self._mag).topleft @property - def size(self) -> Vec3Int: + def size(self) -> VecInt: """⚠️ Deprecated, use `view.bounding_box.in_mag(view.mag).size` instead.""" warnings.warn( "[DEPRECATION] view.size is deprecated. " @@ -131,15 +132,15 @@ def size(self) -> Vec3Int: def _get_mag1_bbox( self, - abs_mag1_bbox: Optional[BoundingBox] = None, - rel_mag1_bbox: Optional[BoundingBox] = None, + abs_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, + rel_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, abs_mag1_offset: Optional[Vec3IntLike] = None, rel_mag1_offset: Optional[Vec3IntLike] = None, mag1_size: Optional[Vec3IntLike] = None, abs_current_mag_offset: Optional[Vec3IntLike] = None, rel_current_mag_offset: Optional[Vec3IntLike] = None, current_mag_size: Optional[Vec3IntLike] = None, - ) -> BoundingBox: + ) -> Union[NDBoundingBox, BoundingBox]: num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) num_offsets = _count_defined_values( [ @@ -199,6 +200,8 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 ) -> None: """ Writes the `data` at the specified `relative_offset` or `absolute_offset`, both specified in Mag(1). @@ -232,7 +235,7 @@ def write( """ assert not self.read_only, "Cannot write data to an read_only View" - if all(i is None for i in [offset, absolute_offset, relative_offset]): + if all(i is None for i in [offset, absolute_offset, relative_offset, absolute_bounding_box, relative_bounding_box]): relative_offset = Vec3Int.zeros() if offset is not None: @@ -265,6 +268,8 @@ def write( rel_current_mag_offset=offset, rel_mag1_offset=relative_offset, abs_mag1_offset=absolute_offset, + rel_mag1_bbox=relative_bounding_box, + abs_mag1_bbox=absolute_bounding_box, current_mag_size=Vec3Int(data.shape[-3:]), ) if json_update_allowed: diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 0bb32413c..9b12a9e70 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -230,36 +230,6 @@ def padded_with_margins( size=self.size + (margins_left + margins_right), ) - def intersected_with( - self, other: "BoundingBox", dont_assert: bool = False - ) -> "BoundingBox": - """If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0))""" - - topleft = self.topleft.pairmax(other.topleft) - bottomright = self.bottomright.pairmin(other.bottomright) - size = (bottomright - topleft).pairmax(Vec3Int.zeros()) - - intersection = attr.evolve(self, topleft=topleft, size=size) - - if not dont_assert: - assert ( - not intersection.is_empty() - ), f"No intersection between bounding boxes {self} and {other}." - - return intersection - - def extended_by(self, other: "BoundingBox") -> "BoundingBox": - if self.is_empty(): - return other - if other.is_empty(): - return self - - topleft = self.topleft.pairmin(other.topleft) - bottomright = self.bottomright.pairmax(other.bottomright) - size = bottomright - topleft - - return attr.evolve(self, topleft=topleft, size=size) - def is_empty(self) -> bool: return not self.size.is_positive(strictly_positive=True) @@ -279,14 +249,6 @@ def in_mag(self, mag: Mag) -> "BoundingBox": size=(self.size // mag_vec), ) - def from_mag_to_mag1(self, from_mag: Mag) -> "BoundingBox": - mag_vec = from_mag.to_vec3_int() - return attr.evolve( - self, - topleft=(self.topleft * mag_vec), - size=(self.size * mag_vec), - ) - def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "BoundingBox": """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. @@ -357,9 +319,6 @@ def contains(self, coord: Union[Vec3IntLike, np.ndarray]) -> bool: and self.topleft[2] <= coord[2] < self.bottomright[2] ) - def contains_bbox(self, inner_bbox: "BoundingBox") -> bool: - return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox - def chunk( self, chunk_shape: Vec3IntLike, diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 9b4b64b0a..565598d57 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -123,6 +123,14 @@ def with_bounds( ) return attr.evolve(self, topleft=_new_topleft, size=_new_size) + + def get_bounds(self, axis: str) -> Tuple[int, int]: + try: + index = self.axes.index(axis) + except ValueError as err: + raise ValueError("The given axis name does not exist.") from err + + return (self.topleft[index], self.topleft[index] + self.size[index]) @classmethod def group_boxes_with_aligned_mag( @@ -155,7 +163,7 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": index = [bbox["axisOrder"][axis] for axis in axes] if "additionalAxes" in bbox: - assert "axisOrder" in bbox, "" + assert "axisOrder" in bbox, "If there are additionalAxes an axisOrder needs to be given." for axis in bbox["additionalAxes"]: topleft.append(axis["bounds"][0]) size.append(axis["bounds"][1] - axis["bounds"][0]) @@ -427,16 +435,16 @@ def volume(self) -> int: def slice_array(self, array: np.ndarray) -> np.ndarray: return array[ - self.topleft.x : self.bottomright.x, - self.topleft.y : self.bottomright.y, - self.topleft.z : self.bottomright.z, + self.get_bounds("x")[0] : self.get_bounds("x")[1], + self.get_bounds("y")[0] : self.get_bounds("y")[1], + self.get_bounds("z")[0] : self.get_bounds("z")[1], ] def to_slices(self) -> Tuple[slice, slice, slice]: return np.index_exp[ - self.topleft.x : self.bottomright.x, - self.topleft.y : self.bottomright.y, - self.topleft.z : self.bottomright.z, + self.get_bounds("x")[0] : self.get_bounds("x")[1], + self.get_bounds("y")[0] : self.get_bounds("y")[1], + self.get_bounds("z")[0] : self.get_bounds("z")[1], ] def offset(self, vector: VecIntLike) -> "NDBoundingBox": From 51631c00cdd8b8ae020d24e22b9a9ea61ea9d21f Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 23 Jan 2024 14:35:38 +0100 Subject: [PATCH 13/41] Update object unstructuring for json and start implementing nd array access. --- webknossos/webknossos/dataset/_array.py | 46 ++++++++++++++----- webknossos/webknossos/dataset/dataset.py | 12 ++--- webknossos/webknossos/dataset/properties.py | 12 ++--- .../webknossos/geometry/nd_bounding_box.py | 15 ++++-- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 97eaa940a..91a718920 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -14,6 +14,8 @@ from upath import UPath from zarr.storage import FSStore +from webknossos.geometry.nd_bounding_box import NDBoundingBox + from ..geometry import BoundingBox, Vec3Int, Vec3IntLike from ..utils import is_fs_path, warn_deprecated from .data_format import DataFormat @@ -392,22 +394,41 @@ def ensure_size( ) zarray.resize(new_shape_tuple) - def write(self, offset: Vec3IntLike, data: np.ndarray) -> None: - offset = Vec3Int(offset) + def write(self, offset: Vec3IntLike, data: np.ndarray, bbox: Optional[NDBoundingBox] = None) -> None: + """Writes ZarrArray. If offset and bbox are given the bbox is prefered to enable writing of n-dimensional data.""" + # When there are only 3-dimensions in the data, there is only one channel. Thus the shape is adapted to write channel information too. if data.ndim == 3: data = data.reshape((1,) + data.shape) assert data.ndim == 4 - with _blosc_disable_threading(): - self.ensure_size(offset + Vec3Int(data.shape[1:4]), warn=True) - zarray = self._zarray - zarray[ - :, - offset.x : (offset.x + data.shape[1]), - offset.y : (offset.y + data.shape[2]), - offset.z : (offset.z + data.shape[3]), - ] = data + if bbox is not None: + with _blosc_disable_threading(): + zarray = self._zarray + topleft = bbox.get_3d("topleft") + index_tuple = [ + slice(None), + slice(topleft.x, topleft.x + data.shape[1]), + slice(topleft.y, topleft.y + data.shape[2]), + slice(topleft.z, topleft.z + data.shape[3]), + ] + for axis in bbox.axes: + index_tuple.append(slice(*bbox.get_bounds(axis))) + zarray[index_tuple] = data + else: + offset = Vec3Int(offset) + + with _blosc_disable_threading(): + self.ensure_size(offset + Vec3Int(data.shape[1:4]), warn=True) + zarray = self._zarray + zarray[ + :, + offset.x : (offset.x + data.shape[1]), + offset.y : (offset.y + data.shape[2]), + offset.z : (offset.z + data.shape[3]), + ] = data + + def list_bounding_boxes(self) -> Iterator[BoundingBox]: zarray = self._zarray @@ -535,6 +556,7 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": from zarrita import Array, ArrayV2 assert array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) + # TODO Get nd-bounding box in zarrita array creation to get dimension names and shape correctly if array_info.data_format == DataFormat.Zarr3: Array.create( store=path, @@ -580,6 +602,7 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": return ZarritaArray(path) def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: + # TODO additionall to offset deliver nd-bounding box to read nd data offset = Vec3Int(offset) shape = Vec3Int(shape) zarray = self._zarray @@ -635,6 +658,7 @@ def ensure_size( self._cached_zarray = zarray.resize(new_shape_tuple) def write(self, offset: Vec3IntLike, data: np.ndarray) -> None: + # TODO additional to offset deliver nd-bounding box to write nd data offset = Vec3Int(offset) if data.ndim == 3: diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index b5d45f291..b431139c7 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1274,15 +1274,11 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = Vec3Int( + actual_size = pims_images.expected_bbox.set_3d("size", Vec3Int( dimwise_max(shapes) + (pims_images.expected_bbox.get_shape("z"),) - ) - layer.bounding_box = ( - BoundingBox((0, 0, 0), actual_size) - .from_mag_to_mag1(mag) - .offset(topleft) - ) - if pims_images.expected_bbox != actual_size: + )) + layer.bounding_box = pims_images.expected_bbox.with_size(actual_size) + if pims_images.expected_bbox.size != actual_size: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " + f"New size is {actual_size}, expected {pims_images.expected_bbox.get_shape('z')}." diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 12bb6062d..afaf31a8a 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -268,15 +268,11 @@ def __layer_properties_post_unstructure( mag_view_properties_post_unstructure(m) for m in d["mags"] ] del d["mags"] + # json expects nd_bounding_box to be represented as bounding_box and additional_axes - bbox = d["boundingBox"] - if "axes" in bbox: - x_pos, y_pos, z_pos = bbox["axes"].index("x"), bbox["axes"].index("y"), bbox["axes"].index("z") - topleft: List[int] = [bbox["topLeft"][x_pos], bbox["topLeft"][y_pos], bbox["topLeft"][z_pos]] - width, height, depth = [bbox["size"][x_pos], bbox["size"][y_pos], bbox["size"][z_pos]] - additional_axes = [{"name": name, "bounds": (top_left, top_left + size)} for name, top_left, size in zip(bbox["axes"][3:], bbox["topLeft"][3:], bbox["size"][3:])] - d["boundingBox"] = {"topLeft": topleft, "width": width, "height": height, "depth": depth} - d["additionalAxes"] = additional_axes + if "additionalAxes" in d["boundingBox"]: + d["additionalAxes"] = d["boundingBox"]["additionalAxes"] + del d["boundingBox"]["additionalAxes"] return d return __layer_properties_post_unstructure diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 565598d57..bc0b5b43a 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -94,6 +94,9 @@ def with_additional_axis( def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) + + def with_size(self, new_size: VecInt) -> "NDBoundingBox": + return attr.evolve(self, size=new_size) def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": return attr.evolve(self, is_visible=is_visible) @@ -175,24 +178,26 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": def to_wkw_dict(self) -> dict: topleft = [None, None, None] - size = [None, None, None] + width, height, depth = None, None, None additional_axes = [] for index, axis in enumerate(self.axes): if axis == "x": topleft[0] = self.topleft[index] - size[0] = self.size[index] + width = self.size[index] elif axis == "y": topleft[1] = self.topleft[index] - size[1] = self.size[index] + height = self.size[index] elif axis == "z": topleft[2] = self.topleft[index] - size[2] = self.size[index] + depth = self.size[index] else: additional_axes.append({"name": axis, "bounds": [self.topleft[index], self.bottomright[index]], "index": index}) return { "topLeft": topleft, - "size": size, + "width": width, + "height": height, + "depth": depth, "additionalAxes": additional_axes, } From 2a755d33c023347e326e464f5d9282876e3c8ca4 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 25 Jan 2024 19:07:14 +0100 Subject: [PATCH 14/41] Adapt array classes and add axes information to ArrayInfo. --- webknossos/webknossos/dataset/_array.py | 172 ++++++++---------- .../dataset/_utils/buffered_slice_writer.py | 8 +- .../webknossos/dataset/_utils/pims_images.py | 2 +- webknossos/webknossos/dataset/dataset.py | 4 +- webknossos/webknossos/dataset/layer.py | 4 +- webknossos/webknossos/dataset/mag_view.py | 6 +- webknossos/webknossos/dataset/view.py | 16 +- .../webknossos/geometry/bounding_box.py | 2 +- .../webknossos/geometry/nd_bounding_box.py | 6 +- 9 files changed, 104 insertions(+), 116 deletions(-) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 91a718920..790dc1aae 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -5,7 +5,17 @@ from dataclasses import dataclass from os.path import relpath from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Type, Union +from typing import ( + TYPE_CHECKING, + Any, + Dict, + Iterator, + List, + Optional, + Tuple, + Type, + Union, +) import numcodecs import numpy as np @@ -14,9 +24,14 @@ from upath import UPath from zarr.storage import FSStore -from webknossos.geometry.nd_bounding_box import NDBoundingBox - -from ..geometry import BoundingBox, Vec3Int, Vec3IntLike +from ..geometry import ( + BoundingBox, + NDBoundingBox, + Vec3Int, + Vec3IntLike, + VecInt, + VecIntLike, +) from ..utils import is_fs_path, warn_deprecated from .data_format import DataFormat @@ -62,6 +77,9 @@ class ArrayInfo: voxel_type: np.dtype chunk_shape: Vec3Int chunks_per_shard: Vec3Int + shape: Tuple[int, ...] = (1, 1, 1, 1) + dimension_names: Tuple[str, ...] = ("c", "x", "y", "z") + axis_order: Tuple[int, ...] = (3, 2, 1, 0) compression_mode: bool = False @property @@ -105,16 +123,16 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "BaseArray": pass @abstractmethod - def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: + def read(self, bbox: NDBoundingBox) -> np.ndarray: pass @abstractmethod - def write(self, offset: Vec3IntLike, data: np.ndarray) -> None: + def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: pass @abstractmethod def ensure_size( - self, new_shape: Vec3IntLike, align_with_shards: bool = True, warn: bool = False + self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False ) -> None: pass @@ -214,15 +232,15 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "WKWArray": raise ArrayException(f"Exception while creating array {path}") from e return WKWArray(path) - def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: - return self._wkw_dataset.read(Vec3Int(offset), Vec3Int(shape)) + def read(self, bbox: NDBoundingBox) -> np.ndarray: + return self._wkw_dataset.read(Vec3Int(bbox.topleft), Vec3Int(bbox.size)) - def write(self, offset: Vec3IntLike, data: np.ndarray) -> None: - self._wkw_dataset.write(Vec3Int(offset), data) + def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: + self._wkw_dataset.write(Vec3Int(bbox.topleft), data) def ensure_size( self, - new_shape: Vec3IntLike, + new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False, ) -> None: @@ -337,19 +355,14 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarrArray": ) return ZarrArray(path) - def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: - offset = Vec3Int(offset) - shape = Vec3Int(shape) + def read(self, bbox: NDBoundingBox) -> np.ndarray: + shape = bbox.size zarray = self._zarray with _blosc_disable_threading(): - data = zarray[ - :, - offset.x : (offset.x + shape.x), - offset.y : (offset.y + shape.y), - offset.z : (offset.z + shape.z), - ] + data = zarray[(slice(None),) + bbox.get_slice_tuple()] + shape_with_channels = (self.info.num_channels,) + shape.to_tuple() - if data.shape != shape and data.shape != shape_with_channels: + if data.shape not in (shape, shape_with_channels): padded_data = np.zeros(shape_with_channels, dtype=data.dtype) padded_data[ :, @@ -361,17 +374,14 @@ def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: return data def ensure_size( - self, new_shape: Vec3IntLike, align_with_shards: bool = True, warn: bool = False + self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False ) -> None: - new_shape = Vec3Int(new_shape) + new_shape = VecInt(new_bbox.size) zarray = self._zarray new_shape_tuple = ( zarray.shape[0], - max(zarray.shape[1], new_shape.x), - max(zarray.shape[2], new_shape.y), - max(zarray.shape[3], new_shape.z), - ) + ) + tuple(max(zarray.shape[i+1], new_shape[i]) if len(zarray.shape) > i else new_shape[i] for i in range(len(new_shape))) if new_shape_tuple != zarray.shape: if align_with_shards: shard_shape = self.info.shard_shape @@ -394,41 +404,22 @@ def ensure_size( ) zarray.resize(new_shape_tuple) - def write(self, offset: Vec3IntLike, data: np.ndarray, bbox: Optional[NDBoundingBox] = None) -> None: + def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: """Writes ZarrArray. If offset and bbox are given the bbox is prefered to enable writing of n-dimensional data.""" - # When there are only 3-dimensions in the data, there is only one channel. Thus the shape is adapted to write channel information too. + # If data is 3-dimensional, it is assumed that num_channels=1. if data.ndim == 3: data = data.reshape((1,) + data.shape) assert data.ndim == 4 - if bbox is not None: - with _blosc_disable_threading(): - zarray = self._zarray - topleft = bbox.get_3d("topleft") - index_tuple = [ - slice(None), - slice(topleft.x, topleft.x + data.shape[1]), - slice(topleft.y, topleft.y + data.shape[2]), - slice(topleft.z, topleft.z + data.shape[3]), - ] - for axis in bbox.axes: - index_tuple.append(slice(*bbox.get_bounds(axis))) - zarray[index_tuple] = data - else: - offset = Vec3Int(offset) - - with _blosc_disable_threading(): - self.ensure_size(offset + Vec3Int(data.shape[1:4]), warn=True) - zarray = self._zarray - zarray[ - :, - offset.x : (offset.x + data.shape[1]), - offset.y : (offset.y + data.shape[2]), - offset.z : (offset.z + data.shape[3]), - ] = data - - + with _blosc_disable_threading(): + self.ensure_size(bbox) + zarray = self._zarray + index_tuple = ( + slice(None), + ) + bbox.get_slice_tuple() + + zarray[index_tuple] = data def list_bounding_boxes(self) -> Iterator[BoundingBox]: zarray = self._zarray @@ -526,6 +517,7 @@ def info(self) -> ArrayInfo: chunk_shape=Vec3Int(chunk_shape[1:4]), chunks_per_shard=Vec3Int(shard_shape[1:4]) // Vec3Int(chunk_shape[1:4]), + dimension_names=zarray.metadata.dimension_names ) return ArrayInfo( data_format=DataFormat.Zarr3, @@ -539,6 +531,7 @@ def info(self) -> ArrayInfo: ) or Vec3Int.full(1), chunks_per_shard=Vec3Int.full(1), + dimension_names=zarray.metadata.dimension_names, ) else: return ArrayInfo( @@ -548,6 +541,7 @@ def info(self) -> ArrayInfo: compression_mode=zarray.metadata.compressor is not None, chunk_shape=Vec3Int(*zarray.metadata.chunks[1:4]) or Vec3Int.full(1), chunks_per_shard=Vec3Int.full(1), + dimension_names=zarray.meta ) @classmethod @@ -560,18 +554,17 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": if array_info.data_format == DataFormat.Zarr3: Array.create( store=path, - shape=(array_info.num_channels, 1, 1, 1), - chunk_shape=(array_info.num_channels,) - + array_info.shard_shape.to_tuple(), + shape=array_info.shape, + chunk_shape=(array_info.num_channels,)+(1, 32, 4096, 4096), chunk_key_encoding=("default", "/"), dtype=array_info.voxel_type, - dimension_names=["c", "x", "y", "z"], + dimension_names=array_info.dimension_names, codecs=[ zarrita.codecs.sharding_codec( chunk_shape=(array_info.num_channels,) + array_info.chunk_shape.to_tuple(), codecs=[ - zarrita.codecs.transpose_codec([3, 2, 1, 0]), + zarrita.codecs.transpose_codec(array_info.axis_order), zarrita.codecs.bytes_codec(), zarrita.codecs.blosc_codec( typesize=array_info.voxel_type.itemsize @@ -579,7 +572,7 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": ] if array_info.compression_mode else [ - zarrita.codecs.transpose_codec([3, 2, 1, 0]), + zarrita.codecs.transpose_codec(array_info.axis_order), zarrita.codecs.bytes_codec(), ], ) @@ -601,20 +594,14 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": ) return ZarritaArray(path) - def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: - # TODO additionall to offset deliver nd-bounding box to read nd data - offset = Vec3Int(offset) - shape = Vec3Int(shape) + def read(self, bbox: NDBoundingBox) -> np.ndarray: + shape = bbox.size.to_tuple() zarray = self._zarray with _blosc_disable_threading(): - data = zarray[ - :, - offset.x : (offset.x + shape.x), - offset.y : (offset.y + shape.y), - offset.z : (offset.z + shape.z), - ] - shape_with_channels = (self.info.num_channels,) + shape.to_tuple() - if data.shape != shape and data.shape != shape_with_channels: + data = zarray[(slice(None),) + bbox.get_slice_tuple()] + + shape_with_channels = (self.info.num_channels,) + shape + if data.shape not in (shape, shape_with_channels): padded_data = np.zeros(shape_with_channels, dtype=data.dtype) padded_data[ :, @@ -626,22 +613,19 @@ def read(self, offset: Vec3IntLike, shape: Vec3IntLike) -> np.ndarray: return data def ensure_size( - self, new_shape: Vec3IntLike, align_with_shards: bool = True, warn: bool = False + self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False ) -> None: - new_shape = Vec3Int(new_shape) + new_shape = new_bbox.size zarray = self._zarray new_shape_tuple = ( zarray.metadata.shape[0], - max(zarray.metadata.shape[1], new_shape.x), - max(zarray.metadata.shape[2], new_shape.y), - max(zarray.metadata.shape[3], new_shape.z), - ) + ) + tuple(max(zarray.metadata.shape[i+1], new_shape[i]) for i in range(len(new_shape))) if new_shape_tuple != zarray.metadata.shape: if align_with_shards: shard_shape = self.info.shard_shape - new_shape = new_shape.ceildiv(shard_shape) * shard_shape - new_shape_tuple = (zarray.metadata.shape[0],) + new_shape.to_tuple() + new_shape = Vec3Int(new_bbox.get_3d("size").ceildiv(shard_shape) * shard_shape) + new_shape_tuple = (zarray.metadata.shape[0],) + new_bbox.set_3d("size", new_shape).to_tuple() # Check on-disk for changes to shape current_zarray = zarray.open(self._path) @@ -657,23 +641,15 @@ def ensure_size( ) self._cached_zarray = zarray.resize(new_shape_tuple) - def write(self, offset: Vec3IntLike, data: np.ndarray) -> None: - # TODO additional to offset deliver nd-bounding box to write nd data - offset = Vec3Int(offset) - - if data.ndim == 3: - data = data.reshape((1,) + data.shape) - assert data.ndim == 4 - + def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: with _blosc_disable_threading(): - self.ensure_size(offset + Vec3Int(data.shape[1:4]), warn=True) + self.ensure_size(bbox) zarray = self._zarray - zarray[ - :, - offset.x : (offset.x + data.shape[1]), - offset.y : (offset.y + data.shape[2]), - offset.z : (offset.z + data.shape[3]), - ] = data + index_tuple = ( + slice(None), + ) + bbox.get_slice_tuple() + + zarray[index_tuple] = data def list_bounding_boxes(self) -> Iterator[BoundingBox]: raise NotImplementedError diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 8021ed075..c072e2da9 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -56,6 +56,7 @@ def __init__( self.dtype = self.view.get_dtype() self.use_logging = use_logging self.json_update_allowed = json_update_allowed + if offset is None and relative_offset is None and absolute_offset is None and relative_bounding_box is None and absolute_bounding_box is None: relative_offset = Vec3Int.zeros() if offset is not None: @@ -86,7 +87,11 @@ def __init__( if absolute_bounding_box is not None: effective_offset = absolute_bounding_box.get_3d("topleft") - self.absolute_offset = effective_offset + if relative_bounding_box is not None: + self.bbox = relative_bounding_box.offset(self.view.bounding_box.topleft) + + if absolute_bounding_box is not None: + self.bbox = absolute_bounding_box view_chunk_depth = self.view.info.chunk_shape[self.dimension] if ( @@ -187,6 +192,7 @@ def _flush_buffer(self) -> None: relative_offset=buffer_start_mag1.add_or_none(self.relative_offset), absolute_offset=buffer_start_mag1.add_or_none(self.absolute_offset), json_update_allowed=self.json_update_allowed, + absolute_bounding_box=self.bbox, ) del data diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 07932a4f3..9f8f0dcd3 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -577,7 +577,7 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: topleft = VecInt.zeros(len(axes)) axes_names, size = zip(*axes.items()) #TODO get current axis order from file and use it for nd bbbox - return NDBoundingBox(topleft, size, axes_names, index=(i+1 for i, _ in enumerate(axes_names))) + return NDBoundingBox(topleft, size, axes_names, index=(len(axes_names) - i for i, _ in enumerate(axes_names))) T = TypeVar("T", bound=Tuple[int, ...]) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index b431139c7..4c004a9ba 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1199,14 +1199,14 @@ def add_layer_from_images( if chunks_per_shard is None and layer.data_format == DataFormat.Zarr3: chunks_per_shard = DEFAULT_CHUNKS_PER_SHARD_FROM_IMAGES + mag = Mag(mag) + layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset(topleft) mag_view = layer.add_mag( mag=mag, chunk_shape=chunk_shape, chunks_per_shard=chunks_per_shard, compress=compress, ) - mag = mag_view.mag - layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset(topleft) if batch_size is None: if compress: diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 1002867bb..25ed46938 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -271,7 +271,7 @@ def bounding_box(self, bbox: Union[NDBoundingBox, BoundingBox]) -> None: self.dataset._export_as_json() for mag in self.mags.values(): mag._array.ensure_size( - bbox.align_with_mag(mag.mag).in_mag(mag.mag).get_3d("bottomright") + bbox.align_with_mag(mag.mag).in_mag(mag.mag) ) @property @@ -406,7 +406,7 @@ def add_mag( ) mag_view._array.ensure_size( - self.bounding_box.align_with_mag(mag).in_mag(mag).bottomright + self.bounding_box.align_with_mag(mag).in_mag(mag) ) self._mags[mag] = mag_view diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 5cd6221da..622036529 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -79,6 +79,9 @@ def __init__( chunk_shape=chunk_shape, chunks_per_shard=chunks_per_shard, compression_mode=compression_mode, + axis_order=(0, ) + layer.bounding_box.index, + shape=(layer.num_channels, ) + layer.bounding_box.size.to_tuple(), + dimension_names=("c", ) + layer.bounding_box.axes, ) if create: self_path = layer.dataset.path / layer.name / mag.to_layer_name() @@ -183,7 +186,7 @@ def write( abs_mag1_offset=absolute_offset, abs_mag1_bbox=absolute_bounding_box, rel_mag1_bbox=relative_bounding_box, - current_mag_size=Vec3Int(data.shape[-3:]), + #current_mag_size=Vec3Int(data.shape[-3:]), ) # Only update the layer's bbox if we are actually larger @@ -195,6 +198,7 @@ def write( data, absolute_offset=mag1_bbox.topleft, json_update_allowed=json_update_allowed, + absolute_bounding_box=absolute_bounding_box, ) def read( diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 3da8ccd2e..528b7e7d2 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -265,12 +265,12 @@ def write( ), f"The number of channels of the dataset ({num_channels}) does not match the number of channels of the passed data ({data.shape[0]})" mag1_bbox = self._get_mag1_bbox( - rel_current_mag_offset=offset, - rel_mag1_offset=relative_offset, - abs_mag1_offset=absolute_offset, + # rel_current_mag_offset=offset, + # rel_mag1_offset=relative_offset, + # abs_mag1_offset=absolute_offset, rel_mag1_bbox=relative_bounding_box, abs_mag1_bbox=absolute_bounding_box, - current_mag_size=Vec3Int(data.shape[-3:]), + #current_mag_size=Vec3Int(data.shape[-3:]), ) if json_update_allowed: assert self.bounding_box.contains_bbox( @@ -286,9 +286,9 @@ def write( for current_mag_bbox, chunked_data in self._prepare_compressed_write( current_mag_bbox, data, json_update_allowed ): - self._array.write(current_mag_bbox.topleft, chunked_data) + self._array.write(current_mag_bbox, chunked_data) else: - self._array.write(current_mag_bbox.topleft, data) + self._array.write(current_mag_bbox, data) def _prepare_compressed_write( self, @@ -518,9 +518,7 @@ def _read_without_checks( self, current_mag_bbox: BoundingBox, ) -> np.ndarray: - data = self._array.read( - current_mag_bbox.topleft.to_np(), current_mag_bbox.size.to_np() - ) + data = self._array.read(current_mag_bbox) return data def get_view( diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 9b12a9e70..64c43110b 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -33,7 +33,7 @@ class BoundingBox(NDBoundingBox): topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) - axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) + axes: Tuple[str, str, str] = attr.field(default=("z", "y", "x")) index: Vec3Int = attr.field(default=Vec3Int(1, 2, 3)) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index bc0b5b43a..94ad45ace 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -43,6 +43,7 @@ def __attrs_post_init__(self) -> None: f"The dimensions of topleft, size, axes and index ({len(self.topleft)}, " + f"{len(self.size)}, {len(self.axes)} and {len(self.index)}) do not match." ) + assert 0 not in self.index, "Index 0 is reserved for channels." if not self._is_sorted(): self._sort_positions_of_axes() @@ -159,7 +160,7 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": topleft: List[int] = bbox["topLeft"] size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] axes: List[str] = ["x", "y", "z"] - index: List[int] = [0, 1, 2] + index: List[int] = [3, 2, 1] if "axisOrder" in bbox: axes = list(bbox["axisOrder"].keys()) @@ -227,6 +228,9 @@ def get_shape(self, key) -> int: except ValueError as err: raise ValueError(f"Axis {key} doesn't exist in NDBoundingBox.") from err + def get_slice_tuple(self) -> Tuple[slice, ...]: + return tuple(slice(topleft, topleft + size) for topleft, size in zip(self.topleft, self.size)) + def get_3d(self, attr_name: str) -> Vec3Int: axes = ("x", "y", "z") attr_3d = [] From 58c728b088e51022c38cb8725ff6a604e65a7ffc Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 29 Jan 2024 17:54:28 +0100 Subject: [PATCH 15/41] Updated zarr writing for nd arrays. Axes order still get mixed up between old BoundingBoxes and new NDBoundingBoxes. --- .../script_collection/reading_nd_data.py | 16 ++-- webknossos/webknossos/dataset/_array.py | 86 ++++++++++-------- .../dataset/_utils/buffered_slice_writer.py | 20 +++-- .../webknossos/dataset/_utils/pims_images.py | 24 +++-- webknossos/webknossos/dataset/dataset.py | 47 +++++++--- webknossos/webknossos/dataset/layer.py | 25 ++++-- webknossos/webknossos/dataset/mag_view.py | 32 ++++--- webknossos/webknossos/dataset/properties.py | 14 +-- webknossos/webknossos/dataset/view.py | 88 +++++++++++-------- .../webknossos/geometry/bounding_box.py | 6 +- .../webknossos/geometry/nd_bounding_box.py | 79 ++++++++++------- webknossos/webknossos/geometry/vec3_int.py | 1 - 12 files changed, 274 insertions(+), 164 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index c74d3fa85..3e978908e 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -6,7 +6,7 @@ TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" ZARR_PATH = Path("..") / "idr0101A-4d-zarr" -OUTPUT = Path('.') / "testoutput" +OUTPUT = Path(".") / "testoutput" def from_images_import(): @@ -14,16 +14,20 @@ def from_images_import(): # print(reader.sizes) # print(isinstance(reader, pims.FramesSequenceND)) wk.Dataset.from_images( - TIF_PATH, OUTPUT, voxel_size=(10, 10, 10), data_format="zarr3", use_bioformats=True + TIF_PATH, + OUTPUT, + voxel_size=(10, 10, 10), + data_format="zarr3", + use_bioformats=True, ) def open_existing_dataset(): ds = wk.Dataset.open(ZARR_PATH) - color_layer = ds.get_color_layers()[0] - finest_mag = color_layer.get_finest_mag() - layers = ds.layers - #finest_mag.read() + # color_layer = ds.get_color_layers()[0] + # finest_mag = color_layer.get_finest_mag() + # layers = ds.layers + # finest_mag.read() ds.copy_dataset("../copied_dataset") diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 790dc1aae..fa7778e18 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -24,14 +24,7 @@ from upath import UPath from zarr.storage import FSStore -from ..geometry import ( - BoundingBox, - NDBoundingBox, - Vec3Int, - Vec3IntLike, - VecInt, - VecIntLike, -) +from ..geometry import BoundingBox, NDBoundingBox, Vec3Int, VecInt from ..utils import is_fs_path, warn_deprecated from .data_format import DataFormat @@ -77,9 +70,9 @@ class ArrayInfo: voxel_type: np.dtype chunk_shape: Vec3Int chunks_per_shard: Vec3Int - shape: Tuple[int, ...] = (1, 1, 1, 1) + shape: VecInt = VecInt(1, 1, 1, 1) dimension_names: Tuple[str, ...] = ("c", "x", "y", "z") - axis_order: Tuple[int, ...] = (3, 2, 1, 0) + axis_order: VecInt = VecInt(3, 2, 1, 0) compression_mode: bool = False @property @@ -89,7 +82,7 @@ def shard_size(self) -> Vec3Int: @property def shard_shape(self) -> Vec3Int: - return self.chunk_shape * self.chunks_per_shard + return Vec3Int(self.chunk_shape * self.chunks_per_shard) class BaseArray(ABC): @@ -132,7 +125,10 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: @abstractmethod def ensure_size( - self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False + self, + new_bbox: NDBoundingBox, + align_with_shards: bool = True, + warn: bool = False, ) -> None: pass @@ -360,7 +356,7 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: zarray = self._zarray with _blosc_disable_threading(): data = zarray[(slice(None),) + bbox.get_slice_tuple()] - + shape_with_channels = (self.info.num_channels,) + shape.to_tuple() if data.shape not in (shape, shape_with_channels): padded_data = np.zeros(shape_with_channels, dtype=data.dtype) @@ -374,14 +370,20 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: return data def ensure_size( - self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False + self, + new_bbox: NDBoundingBox, + align_with_shards: bool = True, + warn: bool = False, ) -> None: new_shape = VecInt(new_bbox.size) zarray = self._zarray - new_shape_tuple = ( - zarray.shape[0], - ) + tuple(max(zarray.shape[i+1], new_shape[i]) if len(zarray.shape) > i else new_shape[i] for i in range(len(new_shape))) + new_shape_tuple = (zarray.shape[0],) + tuple( + max(zarray.shape[i + 1], new_shape[i]) + if len(zarray.shape) > i + else new_shape[i] + for i in range(len(new_shape)) + ) if new_shape_tuple != zarray.shape: if align_with_shards: shard_shape = self.info.shard_shape @@ -415,9 +417,7 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: with _blosc_disable_threading(): self.ensure_size(bbox) zarray = self._zarray - index_tuple = ( - slice(None), - ) + bbox.get_slice_tuple() + index_tuple = (slice(None),) + bbox.get_slice_tuple() zarray[index_tuple] = data @@ -500,6 +500,10 @@ def info(self) -> ArrayInfo: from zarrita.sharding import ShardingCodec zarray = self._zarray + if (names := getattr(zarray.metadata, "dimension_names", None)) is None: + dimension_names = ("c", "x", "y", "z") + else: + dimension_names = names if isinstance(zarray, Array): if len(zarray.codec_pipeline.codecs) == 1 and isinstance( zarray.codec_pipeline.codecs[0], ShardingCodec @@ -517,7 +521,7 @@ def info(self) -> ArrayInfo: chunk_shape=Vec3Int(chunk_shape[1:4]), chunks_per_shard=Vec3Int(shard_shape[1:4]) // Vec3Int(chunk_shape[1:4]), - dimension_names=zarray.metadata.dimension_names + dimension_names=dimension_names, ) return ArrayInfo( data_format=DataFormat.Zarr3, @@ -531,7 +535,7 @@ def info(self) -> ArrayInfo: ) or Vec3Int.full(1), chunks_per_shard=Vec3Int.full(1), - dimension_names=zarray.metadata.dimension_names, + dimension_names=dimension_names, ) else: return ArrayInfo( @@ -541,7 +545,7 @@ def info(self) -> ArrayInfo: compression_mode=zarray.metadata.compressor is not None, chunk_shape=Vec3Int(*zarray.metadata.chunks[1:4]) or Vec3Int.full(1), chunks_per_shard=Vec3Int.full(1), - dimension_names=zarray.meta + dimension_names=dimension_names, ) @classmethod @@ -550,19 +554,21 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": from zarrita import Array, ArrayV2 assert array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) - # TODO Get nd-bounding box in zarrita array creation to get dimension names and shape correctly if array_info.data_format == DataFormat.Zarr3: + chunk_shape = (array_info.num_channels,) + tuple( + getattr(array_info.chunk_shape, axis, 1) + for axis in array_info.dimension_names[1:] + ) Array.create( store=path, shape=array_info.shape, - chunk_shape=(array_info.num_channels,)+(1, 32, 4096, 4096), + chunk_shape=chunk_shape, chunk_key_encoding=("default", "/"), dtype=array_info.voxel_type, dimension_names=array_info.dimension_names, codecs=[ zarrita.codecs.sharding_codec( - chunk_shape=(array_info.num_channels,) - + array_info.chunk_shape.to_tuple(), + chunk_shape=chunk_shape, codecs=[ zarrita.codecs.transpose_codec(array_info.axis_order), zarrita.codecs.bytes_codec(), @@ -613,19 +619,27 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: return data def ensure_size( - self, new_bbox: NDBoundingBox, align_with_shards: bool = True, warn: bool = False + self, + new_bbox: NDBoundingBox, + align_with_shards: bool = True, + warn: bool = False, ) -> None: new_shape = new_bbox.size zarray = self._zarray - new_shape_tuple = ( - zarray.metadata.shape[0], - ) + tuple(max(zarray.metadata.shape[i+1], new_shape[i]) for i in range(len(new_shape))) + new_shape_tuple = (zarray.metadata.shape[0],) + tuple( + max(zarray.metadata.shape[i + 1], new_shape[i]) + for i in range(len(new_shape)) + ) if new_shape_tuple != zarray.metadata.shape: if align_with_shards: shard_shape = self.info.shard_shape - new_shape = Vec3Int(new_bbox.get_3d("size").ceildiv(shard_shape) * shard_shape) - new_shape_tuple = (zarray.metadata.shape[0],) + new_bbox.set_3d("size", new_shape).to_tuple() + new_shape = Vec3Int( + new_bbox.get_3d("size").ceildiv(shard_shape) * shard_shape + ) + new_shape_tuple = (zarray.metadata.shape[0],) + new_bbox.set_3d( + "size", new_shape + ).to_tuple() # Check on-disk for changes to shape current_zarray = zarray.open(self._path) @@ -645,11 +659,9 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: with _blosc_disable_threading(): self.ensure_size(bbox) zarray = self._zarray - index_tuple = ( - slice(None), - ) + bbox.get_slice_tuple() + index_tuple = (slice(None),) + bbox.get_slice_tuple() - zarray[index_tuple] = data + zarray[index_tuple] = data.reshape((1,) + bbox.size.to_tuple()) def list_bounding_boxes(self) -> Iterator[BoundingBox]: raise NotImplementedError diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index c072e2da9..4f9307da9 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -56,8 +56,14 @@ def __init__( self.dtype = self.view.get_dtype() self.use_logging = use_logging self.json_update_allowed = json_update_allowed - - if offset is None and relative_offset is None and absolute_offset is None and relative_bounding_box is None and absolute_bounding_box is None: + + if ( + offset is None + and relative_offset is None + and absolute_offset is None + and relative_bounding_box is None + and absolute_bounding_box is None + ): relative_offset = Vec3Int.zeros() if offset is not None: warnings.warn( @@ -82,7 +88,9 @@ def __init__( effective_offset = self.absolute_offset if relative_bounding_box is not None: - effective_offset = self.view.bounding_box.get_3d("topleft") + relative_bounding_box.get_3d("topleft") + effective_offset = self.view.bounding_box.get_3d( + "topleft" + ) + relative_bounding_box.get_3d("topleft") if absolute_bounding_box is not None: effective_offset = absolute_bounding_box.get_3d("topleft") @@ -108,7 +116,7 @@ def __init__( + "will slow down the buffered slice writer.", ) # Previously the dimension was x, y or z now it can possibly be any axis of the bounding_box - #assert 0 <= dimension <= 2 + # assert 0 <= dimension <= 2 self.slices_to_write: List[np.ndarray] = [] self.current_slice: Optional[int] = None @@ -192,7 +200,9 @@ def _flush_buffer(self) -> None: relative_offset=buffer_start_mag1.add_or_none(self.relative_offset), absolute_offset=buffer_start_mag1.add_or_none(self.absolute_offset), json_update_allowed=self.json_update_allowed, - absolute_bounding_box=self.bbox, + absolute_bounding_box=self.bbox.offset(buffer_start_mag1) + if self.bbox + else None, ) del data diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 9f8f0dcd3..c33a23263 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -50,7 +50,6 @@ pass # pylint: enable=unused-import -from ...geometry.vec3_int import Vec3Int from ...geometry.vec_int import VecInt from ..mag_view import MagView @@ -496,13 +495,12 @@ def copy_to_view( with self._open_images() as images: if self._flip_z: images = images[::-1] # pylint: disable=unsubscriptable-object - with mag_view.get_buffered_slice_writer( # Previously only z_start and its end were important, now the slice writer needs to know # which axis is currently written. relative_bounding_box=relative_bbox, - #relative_offset=(0, 0, z_start * mag_view.mag.z), + # relative_offset=(0, 0, z_start * mag_view.mag.z), buffer_size=mag_view.info.chunk_shape.z, # copy_to_view is typically used in a multiprocessing-context. Therefore the # buffered slice writer should not update the json file to avoid race conditions. @@ -512,7 +510,9 @@ def copy_to_view( image_slice = np.array(image_slice) # place channels first if "c" in self._img_dims: - image_slice = np.moveaxis(image_slice, source=self._img_dims.index("c"), destination=0) + image_slice = np.moveaxis( + image_slice, source=self._img_dims.index("c"), destination=0 + ) # ensure the last two axes are xy: if ("yx" in self._img_dims and not self._swap_xy) or ( "xy" in self._img_dims and self._swap_xy @@ -564,9 +564,12 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: y_index = self._img_dims.find("y") + 1 if self._swap_xy: x_index, y_index = y_index, x_index - + if self._iter_dim is None or len(self._iter_dim) == 0: - return BoundingBox((0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0])) + return BoundingBox( + (0, 0, 0), + (images_shape[x_index], images_shape[y_index], images_shape[0]), + ) else: axes = {"x": images_shape[x_index], "y": images_shape[y_index]} for axis in self._iter_dim: @@ -576,8 +579,13 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: axes[axis] = 0 topleft = VecInt.zeros(len(axes)) axes_names, size = zip(*axes.items()) - #TODO get current axis order from file and use it for nd bbbox - return NDBoundingBox(topleft, size, axes_names, index=(len(axes_names) - i for i, _ in enumerate(axes_names))) + # TODO get current axis order from file and use it for nd bbbox + return NDBoundingBox( + topleft, + size, + axes_names, + index=(len(axes_names) - i for i, _ in enumerate(axes_names)), + ) T = TypeVar("T", bound=Tuple[int, ...]) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 4c004a9ba..e3b8fc395 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,11 @@ import attr import numpy as np from boltons.typeutils import make_sentinel +from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath -from cluster_tools import Executor from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset @@ -1200,7 +1200,9 @@ def add_layer_from_images( chunks_per_shard = DEFAULT_CHUNKS_PER_SHARD_FROM_IMAGES mag = Mag(mag) - layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset(topleft) + layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset( + topleft + ) mag_view = layer.add_mag( mag=mag, chunk_shape=chunk_shape, @@ -1231,8 +1233,12 @@ def add_layer_from_images( args = [] bbox = pims_images.expected_bbox - additional_axes = [axis_name for axis_name in bbox.axes if axis_name not in ("x", "y", "z")] - additional_axes_shapes = product(*[range(bbox.get_shape(axis_name)) for axis_name in additional_axes]) + additional_axes = [ + axis_name for axis_name in bbox.axes if axis_name not in ("x", "y", "z") + ] + additional_axes_shapes = product( + *[range(bbox.get_shape(axis_name)) for axis_name in additional_axes] + ) z_shape = bbox.get_shape("z") for z_start in range(0, z_shape, batch_size): z_end = min(z_start + batch_size, z_shape) @@ -1243,9 +1249,11 @@ def add_layer_from_images( for shape in additional_axes_shapes: reduced_bbox = z_bbox for index, axis in enumerate(additional_axes): - reduced_bbox = reduced_bbox.with_bounds(axis, shape[index], shape[index]+1) + reduced_bbox = reduced_bbox.with_bounds( + axis, shape[index], 1 + ) args.append(reduced_bbox) - + with warnings.catch_warnings(): # Block alignmnent within the dataset should not be a problem, since shard-wise chunking is enforced. # However, dataset borders might change between different parallelized writes, when sizes differ. @@ -1274,9 +1282,13 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = pims_images.expected_bbox.set_3d("size", Vec3Int( - dimwise_max(shapes) + (pims_images.expected_bbox.get_shape("z"),) - )) + actual_size = pims_images.expected_bbox.set_3d( + "size", + Vec3Int( + dimwise_max(shapes) + + (pims_images.expected_bbox.get_shape("z"),) + ), + ) layer.bounding_box = pims_images.expected_bbox.with_size(actual_size) if pims_images.expected_bbox.size != actual_size: warnings.warn( @@ -1699,12 +1711,19 @@ def _export_as_json(self) -> None: self._ensure_writable() properties_on_disk = self._load_properties() - - if properties_on_disk != self._last_read_properties: + try: + if properties_on_disk != self._last_read_properties: + warnings.warn( + "[WARNING] While exporting the dataset's properties, properties were found on disk which are " + + "newer than the ones that were seen last time. The properties will be overwritten. This is " + + "likely happening because multiple processes changed the metadata of this dataset." + ) + except ValueError: + # the __eq__ operator raises a ValueError when two bboxes are not comparable. This is the case when the + # axes are not the same. During initialization axes are added or moved sometimes. warnings.warn( - "[WARNING] While exporting the dataset's properties, properties were found on disk which are " - + "newer than the ones that were seen last time. The properties will be overwritten. This is " - + "likely happening because multiple processes changed the metadata of this dataset." + "[WARNING] Properties changed in a way that they are not comparable anymore. Most likely " + + "within the bounding box changed the naming or order of the axes." ) with (self.path / PROPERTIES_FILE_NAME).open("w", encoding="utf-8") as outfile: diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 25ed46938..162e7178f 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -9,10 +9,10 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union import numpy as np +from cluster_tools import Executor from numpy.typing import DTypeLike from upath import UPath -from cluster_tools import Executor from webknossos.geometry.nd_bounding_box import NDBoundingBox from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike @@ -270,9 +270,7 @@ def bounding_box(self, bbox: Union[NDBoundingBox, BoundingBox]) -> None: self._properties.bounding_box = bbox self.dataset._export_as_json() for mag in self.mags.values(): - mag._array.ensure_size( - bbox.align_with_mag(mag.mag).in_mag(mag.mag) - ) + mag._array.ensure_size(bbox.align_with_mag(mag.mag).in_mag(mag.mag)) @property def category(self) -> LayerCategoryType: @@ -405,9 +403,7 @@ def add_mag( create=True, ) - mag_view._array.ensure_size( - self.bounding_box.align_with_mag(mag).in_mag(mag) - ) + mag_view._array.ensure_size(self.bounding_box.align_with_mag(mag).in_mag(mag)) self._mags[mag] = mag_view mag_array_info = mag_view.info @@ -420,7 +416,12 @@ def add_mag( else None ), axis_order=( - dict(zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))) + dict( + zip( + ("c", "x", "y", "z"), + (0, *self.bounding_box.get_3d("index")), + ) + ) if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) else None ), @@ -457,7 +458,13 @@ def add_mag_for_existing_files( else None ), axis_order=( - {key: value for key, value in zip(('c', *self.bounding_box.axes), (0, *self.bounding_box.index))} + { + key: value + for key, value in zip( + ("c", *self.bounding_box.axes), + (0, *self.bounding_box.index), + ) + } if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) else None ), diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 622036529..28448764e 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,9 +7,8 @@ from uuid import uuid4 import numpy as np -from upath import UPath - from cluster_tools import Executor +from upath import UPath from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( @@ -79,9 +78,9 @@ def __init__( chunk_shape=chunk_shape, chunks_per_shard=chunks_per_shard, compression_mode=compression_mode, - axis_order=(0, ) + layer.bounding_box.index, - shape=(layer.num_channels, ) + layer.bounding_box.size.to_tuple(), - dimension_names=("c", ) + layer.bounding_box.axes, + axis_order=VecInt(0, *layer.bounding_box.index), + shape=VecInt(layer.num_channels, *layer.bounding_box.size), + dimension_names=("c",) + layer.bounding_box.axes, ) if create: self_path = layer.dataset.path / layer.name / mag.to_layer_name() @@ -90,7 +89,7 @@ def __init__( super().__init__( _find_mag_path_on_disk(layer.dataset.path, layer.name, mag.to_layer_name()), array_info, - bounding_box=None, + bounding_box=layer.bounding_box, mag=mag, ) self._layer = layer @@ -158,8 +157,12 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 ) -> None: if offset is not None: if self._mag == Mag(1): @@ -177,7 +180,16 @@ def write( DeprecationWarning, ) - if all(i is None for i in [offset, absolute_offset, relative_offset, absolute_bounding_box, relative_bounding_box]): + if all( + i is None + for i in [ + offset, + absolute_offset, + relative_offset, + absolute_bounding_box, + relative_bounding_box, + ] + ): relative_offset = Vec3Int.zeros() mag1_bbox = self._get_mag1_bbox( @@ -186,7 +198,7 @@ def write( abs_mag1_offset=absolute_offset, abs_mag1_bbox=absolute_bounding_box, rel_mag1_bbox=relative_bounding_box, - #current_mag_size=Vec3Int(data.shape[-3:]), + current_mag_size=Vec3Int(data.shape[-3:]), ) # Only update the layer's bbox if we are actually larger diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index afaf31a8a..e93eabcce 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -154,6 +154,7 @@ def resolutions(self) -> List[MagViewProperties]: warn_deprecated("resolutions", "mags") return self.mags + @attr.define class SegmentationLayerProperties(LayerProperties): largest_segment_id: Optional[int] = None @@ -304,16 +305,18 @@ def __layer_properties_pre_structure( first_mag = d["mags"][0] if "axisOrder" in first_mag: assert first_mag["axisOrder"]["c"] == 0 - assert all(first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"]) + assert all( + first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"] + ) d["boundingBox"]["axisOrder"] = first_mag["axisOrder"] del d["boundingBox"]["axisOrder"]["c"] - obj = converter_fn(d, type_value) return obj return __layer_properties_pre_structure + def disambiguate_bounding_box(obj: dict, _: Any) -> Union[BoundingBox, NDBoundingBox]: if "additionalAxes" in obj: return dataset_converter.structure(obj, NDBoundingBox) @@ -322,7 +325,8 @@ def disambiguate_bounding_box(obj: dict, _: Any) -> Union[BoundingBox, NDBoundin dataset_converter.register_structure_hook( - Union[BoundingBox, NDBoundingBox], disambiguate_bounding_box, + Union[BoundingBox, NDBoundingBox], + disambiguate_bounding_box, ) for cls in [ @@ -370,7 +374,7 @@ def disambiguate_layer_properties(obj: dict, _: Any) -> LayerProperties: raise RuntimeError( "Failed to read the properties of a layer: the category has to be `color` or `segmentation`." ) - + dataset_converter.register_structure_hook( Union[ @@ -378,4 +382,4 @@ def disambiguate_layer_properties(obj: dict, _: Any) -> LayerProperties: LayerProperties, ], disambiguate_layer_properties, -) \ No newline at end of file +) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 528b7e7d2..c01ef6fad 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -18,8 +18,8 @@ import numpy as np import wkw - from cluster_tools import Executor + from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike @@ -141,38 +141,37 @@ def _get_mag1_bbox( rel_current_mag_offset: Optional[Vec3IntLike] = None, current_mag_size: Optional[Vec3IntLike] = None, ) -> Union[NDBoundingBox, BoundingBox]: - num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) - num_offsets = _count_defined_values( - [ - abs_mag1_offset, - rel_mag1_offset, - abs_current_mag_offset, - rel_current_mag_offset, - ] - ) - num_sizes = _count_defined_values([mag1_size, current_mag_size]) - if num_bboxes == 0: - assert num_offsets != 0, "You must supply an offset or a bounding box." - assert ( - num_sizes != 0 - ), "When supplying an offset, you must also supply a size. Alternatively, supply a bounding box." - assert num_offsets == 1, "Only one offset can be supplied." - assert num_sizes == 1, "Only one size can be supplied." - else: - assert num_bboxes == 1, "Only one bounding-box can be supplied." - assert ( - num_offsets == 0 - ), "A bounding-box was supplied, you cannot also supply an offset." - assert ( - num_sizes == 0 - ), "A bounding-box was supplied, you cannot also supply a size." + # num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) + # num_offsets = _count_defined_values( + # [ + # abs_mag1_offset, + # rel_mag1_offset, + # abs_current_mag_offset, + # rel_current_mag_offset, + # ] + # ) + # num_sizes = _count_defined_values([mag1_size, current_mag_size]) + # if num_bboxes == 0: + # assert num_offsets != 0, "You must supply an offset or a bounding box." + # assert ( + # num_sizes != 0 + # ), "When supplying an offset, you must also supply a size. Alternatively, supply a bounding box." + # assert num_offsets == 1, "Only one offset can be supplied." + # assert num_sizes == 1, "Only one size can be supplied." + # else: + # assert num_bboxes == 1, "Only one bounding-box can be supplied." + # assert ( + # num_offsets == 0 + # ), "A bounding-box was supplied, you cannot also supply an offset." + # assert ( + # num_sizes == 0 + # ), "A bounding-box was supplied, you cannot also supply a size." if abs_mag1_bbox is not None: return abs_mag1_bbox elif rel_mag1_bbox is not None: return rel_mag1_bbox.offset(self.bounding_box.topleft) - else: mag_vec = self._mag.to_vec3_int() if rel_current_mag_offset is not None: @@ -200,8 +199,12 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 ) -> None: """ Writes the `data` at the specified `relative_offset` or `absolute_offset`, both specified in Mag(1). @@ -235,7 +238,16 @@ def write( """ assert not self.read_only, "Cannot write data to an read_only View" - if all(i is None for i in [offset, absolute_offset, relative_offset, absolute_bounding_box, relative_bounding_box]): + if all( + i is None + for i in [ + offset, + absolute_offset, + relative_offset, + absolute_bounding_box, + relative_bounding_box, + ] + ): relative_offset = Vec3Int.zeros() if offset is not None: @@ -265,12 +277,12 @@ def write( ), f"The number of channels of the dataset ({num_channels}) does not match the number of channels of the passed data ({data.shape[0]})" mag1_bbox = self._get_mag1_bbox( - # rel_current_mag_offset=offset, - # rel_mag1_offset=relative_offset, - # abs_mag1_offset=absolute_offset, + rel_current_mag_offset=offset, + rel_mag1_offset=relative_offset, + abs_mag1_offset=absolute_offset, rel_mag1_bbox=relative_bounding_box, abs_mag1_bbox=absolute_bounding_box, - #current_mag_size=Vec3Int(data.shape[-3:]), + current_mag_size=Vec3Int(data.shape[-3:]), ) if json_update_allowed: assert self.bounding_box.contains_bbox( @@ -679,8 +691,12 @@ def get_buffered_slice_writer( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 use_logging: bool = False, ) -> "BufferedSliceWriter": """ diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 64c43110b..c5bba1189 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -33,8 +33,8 @@ class BoundingBox(NDBoundingBox): topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) - axes: Tuple[str, str, str] = attr.field(default=("z", "y", "x")) - index: Vec3Int = attr.field(default=Vec3Int(1, 2, 3)) + axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) + index: Vec3Int = attr.field(default=Vec3Int(3, 2, 1)) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True @@ -65,7 +65,7 @@ def with_additional_axis( topleft=(*self.topleft, new_topleft), size=(*self.size, new_size), axes=(*self.axes, name), - index=(*self.index, index if not index is None else max(self.index) + 1) + index=(*self.index, index if not index is None else max(self.index) + 1), ) def with_bounds_x( diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 94ad45ace..a081499a0 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -39,7 +39,9 @@ class NDBoundingBox: color: Optional[Tuple[float, float, float, float]] = None def __attrs_post_init__(self) -> None: - assert len(self.topleft) == len(self.size) == len(self.axes) == len(self.index), ( + assert ( + len(self.topleft) == len(self.size) == len(self.axes) == len(self.index) + ), ( f"The dimensions of topleft, size, axes and index ({len(self.topleft)}, " + f"{len(self.size)}, {len(self.axes)} and {len(self.index)}) do not match." ) @@ -61,14 +63,15 @@ def __attrs_post_init__(self) -> None: # Compute bottomright to avoid that it's recomputed every time # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) - def _sort_positions_of_axes(self) -> None: # Bring topleft and size in required order # defined in axisOrder and index of additionalAxes size, topleft, axes, index = zip( - *sorted(zip(self.size, self.topleft, self.axes, self.index), key=lambda x: x[3]) + *sorted( + zip(self.size, self.topleft, self.axes, self.index), key=lambda x: x[3] + ) ) object.__setattr__(self, "size", VecInt(size)) object.__setattr__(self, "topleft", VecInt(topleft)) @@ -76,12 +79,10 @@ def _sort_positions_of_axes(self) -> None: object.__setattr__(self, "index", index) def _is_sorted(self) -> bool: - return all( - self.index[i - 1] < self.index[i] for i in range(1, len(self.index)) - ) + return all(self.index[i - 1] < self.index[i] for i in range(1, len(self.index))) def with_additional_axis( - self, name: str, extent: Tuple[int, int], index: Optional[int]= None + self, name: str, extent: Tuple[int, int], index: Optional[int] = None ) -> "NDBoundingBox": assert name not in self.axes, "The identifier of the axis is already taken." start, end = extent @@ -90,12 +91,12 @@ def with_additional_axis( topleft=(*self.topleft, start), size=(*self.size, end - start), axes=(*self.axes, name), - index=(*self.index, index if not index is None else max(self.index) + 1) + index=(*self.index, index if not index is None else max(self.index) + 1), ) def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) - + def with_size(self, new_size: VecInt) -> "NDBoundingBox": return attr.evolve(self, size=new_size) @@ -127,13 +128,13 @@ def with_bounds( ) return attr.evolve(self, topleft=_new_topleft, size=_new_size) - + def get_bounds(self, axis: str) -> Tuple[int, int]: try: index = self.axes.index(axis) except ValueError as err: raise ValueError("The given axis name does not exist.") from err - + return (self.topleft[index], self.topleft[index] + self.size[index]) @classmethod @@ -154,7 +155,7 @@ def group_boxes_with_aligned_mag( chunks_with_bboxes[chunk_key].append(bbox) return chunks_with_bboxes - + @classmethod def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": topleft: List[int] = bbox["topLeft"] @@ -167,7 +168,9 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": index = [bbox["axisOrder"][axis] for axis in axes] if "additionalAxes" in bbox: - assert "axisOrder" in bbox, "If there are additionalAxes an axisOrder needs to be given." + assert ( + "axisOrder" in bbox + ), "If there are additionalAxes an axisOrder needs to be given." for axis in bbox["additionalAxes"]: topleft.append(axis["bounds"][0]) size.append(axis["bounds"][1] - axis["bounds"][0]) @@ -176,7 +179,6 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": return cls(topleft, size, axes, index) - def to_wkw_dict(self) -> dict: topleft = [None, None, None] width, height, depth = None, None, None @@ -192,7 +194,13 @@ def to_wkw_dict(self) -> dict: topleft[2] = self.topleft[index] depth = self.size[index] else: - additional_axes.append({"name": axis, "bounds": [self.topleft[index], self.bottomright[index]], "index": index}) + additional_axes.append( + { + "name": axis, + "bounds": [self.topleft[index], self.bottomright[index]], + "index": index, + } + ) return { "topLeft": topleft, @@ -203,7 +211,11 @@ def to_wkw_dict(self) -> dict: } def to_config_dict(self) -> dict: - return {"topleft": self.topleft.to_list(), "size": self.size.to_list(), "axes": self.axes} + return { + "topleft": self.topleft.to_list(), + "size": self.size.to_list(), + "axes": self.axes, + } def to_checkpoint_name(self) -> str: return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" @@ -220,17 +232,20 @@ def __eq__(self, other: object) -> bool: return self.topleft == other.topleft and self.size == other.size else: raise NotImplementedError() - + def get_shape(self, key) -> int: try: index = self.axes.index(key) return self.size[index] except ValueError as err: raise ValueError(f"Axis {key} doesn't exist in NDBoundingBox.") from err - + def get_slice_tuple(self) -> Tuple[slice, ...]: - return tuple(slice(topleft, topleft + size) for topleft, size in zip(self.topleft, self.size)) - + return tuple( + slice(topleft, topleft + size) + for topleft, size in zip(self.topleft, self.size) + ) + def get_3d(self, attr_name: str) -> Vec3Int: axes = ("x", "y", "z") attr_3d = [] @@ -238,9 +253,9 @@ def get_3d(self, attr_name: str) -> Vec3Int: for axis in axes: index = self.axes.index(axis) attr_3d.append(getattr(self, attr_name)[index]) - + return Vec3Int(attr_3d) - + def set_3d(self, attr_name: str, value: Vec3Int) -> VecInt: axes = ("x", "y", "z") modified_attr = getattr(self, attr_name).to_list() @@ -248,7 +263,7 @@ def set_3d(self, attr_name: str, value: Vec3Int) -> VecInt: for i, axis in enumerate(axes): index = self.axes.index(axis) modified_attr[index] = value[i] - + return VecInt(modified_attr) def _check_compatibility(self, other) -> None: @@ -357,7 +372,7 @@ def align_with_mag( # Same behavior is asserted in test_align_with_mag_against_numpy_implementation mag_vec = mag.to_vec3_int() if isinstance(mag, Mag) else mag topleft = self.get_3d("topleft") - bottomright= self.get_3d("bottomright") + bottomright = self.get_3d("bottomright") roundup = topleft if ceil else bottomright rounddown = bottomright if ceil else topleft margin_to_roundup = roundup % mag_vec @@ -367,14 +382,14 @@ def align_with_mag( if ceil: return attr.evolve( self, - topleft=VecInt(*aligned_roundup, *self.topleft[3:]), - size=VecInt(*(aligned_rounddown - aligned_roundup), *self.topleft[3:]) + topleft=self.set_3d("topleft", Vec3Int(aligned_roundup)), + size=self.set_3d("size", Vec3Int(aligned_rounddown - aligned_roundup)), ) else: return attr.evolve( self, - topleft=VecInt(*aligned_rounddown, *self.topleft[3:]), - size=VecInt(*(aligned_roundup - aligned_rounddown), *self.size[3:]) + topleft=self.set_3d("topleft", Vec3Int(aligned_rounddown)), + size=self.set_3d("size", Vec3Int(aligned_roundup - aligned_rounddown)), ) def contains(self, coord: VecIntLike) -> bool: @@ -437,7 +452,9 @@ def chunk( for i in range(len(self.axes)) ] ): - yield NDBoundingBox(topleft=coordinates, size=chunk_shape, axes=self.axes, index=self.index) + yield NDBoundingBox( + topleft=coordinates, size=chunk_shape, axes=self.axes, index=self.index + ) def volume(self) -> int: return self.size.prod() @@ -459,7 +476,9 @@ def to_slices(self) -> Tuple[slice, slice, slice]: def offset(self, vector: VecIntLike) -> "NDBoundingBox": vec_int = VecInt(vector) if len(vec_int) == 3: - new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") + vec_int)) + new_topleft = self.set_3d( + "topleft", Vec3Int(self.get_3d("topleft") + vec_int) + ) return attr.evolve(self, topleft=new_topleft) else: return attr.evolve(self, topleft=self.topleft + vec_int) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 31f8e97f8..5e5a3a883 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -54,7 +54,6 @@ def __new__( return cast(cls, super().__new__(cls, as_tuple)) - @property def x(self) -> int: return self[0] From af249e73c9c6d3325d35103230a5c1a4362559a9 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 30 Jan 2024 15:32:02 +0100 Subject: [PATCH 16/41] Adapted buffered_slice_reader and test behaviour with different tif images. --- webknossos/webknossos/dataset/_array.py | 2 +- .../dataset/_utils/buffered_slice_reader.py | 11 ++++--- .../dataset/_utils/buffered_slice_writer.py | 2 +- .../webknossos/dataset/_utils/pims_images.py | 2 +- webknossos/webknossos/dataset/dataset.py | 6 ++-- webknossos/webknossos/dataset/mag_view.py | 7 ++-- webknossos/webknossos/dataset/view.py | 16 ++++++---- .../webknossos/geometry/nd_bounding_box.py | 32 +++++++++++++------ 8 files changed, 48 insertions(+), 30 deletions(-) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index fa7778e18..530c6bd34 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -661,7 +661,7 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: zarray = self._zarray index_tuple = (slice(None),) + bbox.get_slice_tuple() - zarray[index_tuple] = data.reshape((1,) + bbox.size.to_tuple()) + zarray[index_tuple] = data.reshape((self.info.num_channels,) + bbox.size.to_tuple()) def list_bounding_boxes(self) -> Iterator[BoundingBox]: raise NotImplementedError diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index d1329e95f..21a578ec7 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -9,7 +9,7 @@ if TYPE_CHECKING: from ..view import View -from ...geometry import BoundingBox, Vec3IntLike +from ...geometry import BoundingBox, NDBoundingBox, Vec3IntLike from ...utils import get_chunks @@ -23,8 +23,8 @@ def __init__( buffer_size: int = 32, dimension: int = 2, # z *, - relative_bounding_box: Optional[BoundingBox] = None, # in mag1 - absolute_bounding_box: Optional[BoundingBox] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 use_logging: bool = False, ) -> None: """see `View.get_buffered_slice_reader()`""" @@ -77,8 +77,8 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: n_slices <= self.buffer_size ), f"n_slices should at most be batch_size, but {n_slices} > {self.buffer_size}" - bbox_offset = self.bbox_current_mag.topleft - bbox_size = self.bbox_current_mag.size + bbox_offset = self.bbox_current_mag.get_3d("topleft") + bbox_size = self.bbox_current_mag.get_3d("size") buffer_bounding_box = BoundingBox.from_tuple2( ( @@ -90,6 +90,7 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: + bbox_size[self.dimension + 1 :], ) ) + buffer_bounding_box = self.bbox_current_mag.with_size(self.bbox_current_mag.set_3d("size", buffer_bounding_box.size)).offset(self.bbox_current_mag.set_3d("topleft", buffer_bounding_box.topleft)) if self.use_logging: info( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 4f9307da9..d59909606 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -167,7 +167,7 @@ def _flush_buffer(self) -> None: buffer_depth, ) for chunk_bbox in buffer_bbox.chunk(chunk_size): - info(f"Writing chunk {chunk_bbox}") + info(f"Writing chunk {chunk_bbox}{f' in {self.bbox}' if self.bbox is not None else ''}.") width, height, depth = chunk_bbox.size data = np.zeros( (channel_count, width, height, depth), diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index c33a23263..439dc2a74 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -565,7 +565,7 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: if self._swap_xy: x_index, y_index = y_index, x_index - if self._iter_dim is None or len(self._iter_dim) == 0: + if self._iter_dim is None or len(self._iter_dim) == 0 or self._iter_dim == "z": return BoundingBox( (0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0]), diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index e3b8fc395..e2f33ac17 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,11 @@ import attr import numpy as np from boltons.typeutils import make_sentinel -from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath +from cluster_tools import Executor from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset @@ -1241,8 +1241,8 @@ def add_layer_from_images( ) z_shape = bbox.get_shape("z") for z_start in range(0, z_shape, batch_size): - z_end = min(z_start + batch_size, z_shape) - z_bbox = bbox.with_bounds("z", z_start, z_end) + z_size = min(batch_size, z_shape) + z_bbox = bbox.with_bounds("z", z_start, z_size) if not additional_axes: args.append(z_bbox) else: diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 28448764e..d53db563c 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,9 +7,10 @@ from uuid import uuid4 import numpy as np -from cluster_tools import Executor from upath import UPath +from cluster_tools import Executor + from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( NDArrayLike, @@ -222,8 +223,8 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[BoundingBox] = None, # in mag1 - absolute_bounding_box: Optional[BoundingBox] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 ) -> np.ndarray: # THIS METHOD CAN BE REMOVED WHEN THE DEPRECATED OFFSET IS REMOVED diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index c01ef6fad..f52fe2831 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -18,8 +18,8 @@ import numpy as np import wkw -from cluster_tools import Executor +from cluster_tools import Executor from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike @@ -377,8 +377,8 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[BoundingBox] = None, # in mag1 - absolute_bounding_box: Optional[BoundingBox] = None, # in mag1 + relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 ) -> np.ndarray: """ The user can specify which data should be read. @@ -528,7 +528,7 @@ def read_bbox(self, bounding_box: Optional[BoundingBox] = None) -> np.ndarray: def _read_without_checks( self, - current_mag_bbox: BoundingBox, + current_mag_bbox: Union[NDBoundingBox, BoundingBox], ) -> np.ndarray: data = self._array.read(current_mag_bbox) return data @@ -540,6 +540,8 @@ def get_view( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 read_only: Optional[bool] = None, ) -> "View": """ @@ -636,6 +638,8 @@ def get_view( relative_offset = Vec3Int.zeros() mag1_bbox = self._get_mag1_bbox( + abs_mag1_bbox=absolute_bbox, + rel_mag1_bbox=relative_bbox, rel_current_mag_offset=offset, rel_mag1_offset=relative_offset, abs_mag1_offset=absolute_offset, @@ -754,8 +758,8 @@ def get_buffered_slice_reader( buffer_size: int = 32, dimension: int = 2, # z *, - relative_bounding_box: Optional[BoundingBox] = None, # in mag1 - absolute_bounding_box: Optional[BoundingBox] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 use_logging: bool = False, ) -> "BufferedSliceReader": """ diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index a081499a0..95e861259 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -183,22 +183,22 @@ def to_wkw_dict(self) -> dict: topleft = [None, None, None] width, height, depth = None, None, None additional_axes = [] - for index, axis in enumerate(self.axes): + for i, axis in enumerate(self.axes): if axis == "x": - topleft[0] = self.topleft[index] - width = self.size[index] + topleft[0] = self.topleft[i] + width = self.size[i] elif axis == "y": - topleft[1] = self.topleft[index] - height = self.size[index] + topleft[1] = self.topleft[i] + height = self.size[i] elif axis == "z": - topleft[2] = self.topleft[index] - depth = self.size[index] + topleft[2] = self.topleft[i] + depth = self.size[i] else: additional_axes.append( { "name": axis, - "bounds": [self.topleft[index], self.bottomright[index]], - "index": index, + "bounds": [self.topleft[i], self.bottomright[i]], + "index": self.index[i], } ) @@ -232,6 +232,9 @@ def __eq__(self, other: object) -> bool: return self.topleft == other.topleft and self.size == other.size else: raise NotImplementedError() + + def __len__(self) -> int: + return len(self.axes) def get_shape(self, key) -> int: try: @@ -431,7 +434,16 @@ def chunk( """ start = self.topleft.to_np() - chunk_shape = VecInt(chunk_shape).to_np() + try: + # If a 3D chunk_shape is given it is assumed that iteration over xyz is + # intended. Therefore NDBoundingBoxes are generated that have a shape of + # x: chunk_shape.x, y: chunk_shape.y, z: chunk_shape.z and 1 for all other + # axes. + chunk_shape = Vec3Int(chunk_shape) + + chunk_shape = self.with_size(VecInt.ones(len(self))).set_3d("size", chunk_shape) + except AssertionError: + chunk_shape = VecInt(chunk_shape).to_np() start_adjust = VecInt.zeros(len(self.topleft)).to_np() if chunk_border_alignments is not None: From ad3b22ec4e8d3ede17bdb2ea8be4b7eab6d48cb8 Mon Sep 17 00:00:00 2001 From: markbader Date: Wed, 31 Jan 2024 23:55:27 +0100 Subject: [PATCH 17/41] Adding testdata and fix bugs with axes operation for writing zarr array. --- .../script_collection/reading_nd_data.py | 28 ++- .../4D/{ => 4D_series}/4D-series.ome.tif | Bin .../multi-channel-4D-series.ome.tif | Bin 0 -> 7889559 bytes .../multi-channel-time-series.ome.tif | Bin 0 -> 1578825 bytes webknossos/webknossos/dataset/_array.py | 7 +- .../webknossos/dataset/_utils/pims_images.py | 193 ++++++++---------- webknossos/webknossos/dataset/dataset.py | 2 +- .../webknossos/geometry/bounding_box.py | 2 +- .../webknossos/geometry/nd_bounding_box.py | 15 +- 9 files changed, 123 insertions(+), 124 deletions(-) rename webknossos/testdata/4D/{ => 4D_series}/4D-series.ome.tif (100%) create mode 100644 webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif create mode 100644 webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 3e978908e..4cabb6242 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -1,11 +1,12 @@ from pathlib import Path import pims +from tifffile import imwrite import webknossos as wk +from webknossos.geometry.nd_bounding_box import NDBoundingBox -TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" -ZARR_PATH = Path("..") / "idr0101A-4d-zarr" +TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" OUTPUT = Path(".") / "testoutput" @@ -13,17 +14,34 @@ def from_images_import(): # reader = pims.Bioformats(str(TIF_PATH)) # print(reader.sizes) # print(isinstance(reader, pims.FramesSequenceND)) - wk.Dataset.from_images( + dataset = wk.Dataset.from_images( TIF_PATH, OUTPUT, voxel_size=(10, 10, 10), data_format="zarr3", use_bioformats=True, ) + layer = dataset.get_color_layers()[0] + mag_view = layer.get_finest_mag() + read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4)) + data = mag_view.read(absolute_bounding_box=read_bbox) + assert data.shape == (1, ) + read_bbox.size + data = mag_view.read(absolute_bounding_box=NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4))) + + imwrite("l4_sample_tiff/test.tiff", data) + + for bbox in layer.bounding_box.chunk((439, 167, 5)): + with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: + for slice_data in reader: + + imwrite( + f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", + slice_data, + ) def open_existing_dataset(): - ds = wk.Dataset.open(ZARR_PATH) + ds = wk.Dataset.open(OUTPUT) # color_layer = ds.get_color_layers()[0] # finest_mag = color_layer.get_finest_mag() # layers = ds.layers @@ -34,7 +52,7 @@ def open_existing_dataset(): def main() -> None: """Imports a dataset with more than 3 dimensions.""" from_images_import() - # open_existing_dataset() + open_existing_dataset() if __name__ == "__main__": diff --git a/webknossos/testdata/4D/4D-series.ome.tif b/webknossos/testdata/4D/4D_series/4D-series.ome.tif similarity index 100% rename from webknossos/testdata/4D/4D-series.ome.tif rename to webknossos/testdata/4D/4D_series/4D-series.ome.tif diff --git a/webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif b/webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif new file mode 100644 index 0000000000000000000000000000000000000000..890f35b43178ef0f711c0831b7524b333c0fd333 GIT binary patch literal 7889559 zcmeEO2e@3t&DGszu)*{WE_84K8%#?KgkXB_oj8sG2MokENl5R#_udoIdqR5ez4u;8 z@AXe|e`#i<(cC+`Z{NPRYd=5fW3P^mjx=}Au>J^qU(P%e4hDcNVA}$qg$Pq|dr>fk z+lmG>9lr&3ngNrlqws8K0G#;|xbKc%FSc{Dx1nNov6Is5EIW&07uGaiTkH;Pe{Scb zVh_P*6?>}L0|Ul4DVES#uromCqT>9(6I1N_`BT@fyms|z%V%D9>&>gzt>3V6)%D9a zth;6P%r(TXU%uqfWiwY@xAMjtSKqLH`C&8H->_yCvdd;(vu@>D1V`eM&JAeBJ^)*O z2VmAy0k%E`V0HI1JzT@OJ|oaWlYC2LK%X1Asd{6JYrn z0LS6CJpMfZC)^9*!~+3V{1D*eX91jgCcx=T8{X8~M{ zK3?)ZfXmhcT!FWG<&Ocbeh$FOvjJ9h0PgXAfNM4YT(NV?G4% zxcdM+VKKlHe-7~E7XUo@W%TAym<-0TkZgO+lv9-aS_1nTLZl7V*u~D zKfwEz0=)lM03Un_z=tme_~>kak9{2A6Au9R)L{Uh{x!g7UkdQ~O8~yO4ZxQ^0q~Uv z0(|XofUo}s;F~W4`1Yj$-`y7Ad!GdO!Gi#Pv<%?KzXkZ|%K?6V8Ne^M1GwW;0Ka}P zz;BNL_}%XS{_qNbKV1&+m+b-m`e}f_KLp^PM*{ro_W=L*N`U`f0Z{IMzoO4T(Re5n zt)rl5{{e~_uYzLBE1{URBNSVG7JnKKgJRpGq1f(^Q0#CU6gyo7#V$KRvFqoc*!|&9 z?0F0nd;JNDxvz#|{?$-syi zw@O|~0O^yW`+`1Y-52!N>2(bD;vKm{9{nxvL#0mWL*2Jz#smUi$xjOy$Ff0Y#<8BI zJ&wVa>ZXvt8L!!#vV2nkMDq{X~oMnoxEiTd{0F9bUB5-3PLCHIB4CFe-JMlWPm{s`qIndSP%sb zy-Z{fRfJupYr39qlf0|n$cJ{DtG{0L&B7!JX<4$?Ps>{3^@Jd)G`O-+Og^ZKzG~I=&qsEX8!6et|iJm15 zqVCf86-311Op8|WaWg}>nlJ%;2=sj-IRw{1m|~^Ms0|xJCZhW>+`|n{mwBK1w14;X z9fC@|iHDw7T?L(@S|@AyyL35G%|?jGJHXj}HGUhPHMdm=Jk)3OT2(uH4uP&Nq`pq9HC^>9;K*mF%)SgmO|EZ2Ji<&$fqgIp!L3Mu;pupn8e zNO44S(I;UA;3C0wK*unP*@fl^hrk{~84+XRWZXw;84{pKKNO#CJqwvmw#0pEwHuRK z&yn0m)G*_6a-!ED&umue$*@lnPw{Ayu_$MUKw&Sa+Oq}M0j*#bvkT4f5lWV{X&`6> z3D841QgdNRx3}T88d1=7LygHrnBdaCC04vC=9J`$bJRJ6w2zcWE)raD#*TC~7iWYO zKr`I013F7sDnev9O)*FbAlD13_BMj+fK~|0`|_NYG3K1C>6_F-IXgolRf*(0KZ*+3Q3Eud znaNG^9?rF0VNZHmqUM4#PKa7_@r{KQKr`I0gYXWN(h#Z8nqkbDM1lp3MWRr?PWBif z1*i!Hsa+{$!h_JoG}ei%$Vz1^tC-NWOe(V6HUx6LVA>8+AqCKiq{!?Hl$J5(?6*`; z(Yuv09;nIg2XlwAnouxpXgy;Vb7r1$%1I?aYZ=#?iV!FO&)6;may?<}BMQ4pB}0HiFfFg8q0BWdMsYk8z?1a#GpMD$ZnLG&v$3 zkV8e5eACGC9?EKC*dr9y8uKyQh%l{Xf)ThkqFg^k?UrtGU}i`QwXLxqS$1j|pi7%IM=l08uW8M&R4&Gbkvz24^ZFrnZa7 zVJVvg3rMErJ!pj=5+FM?P+b~{p+$mYJ9#6ay%0;8&|j_oaxy3rYBn}`n{MVf*%G}& zncw4qpHh2bH<{t>F7u0Ihgmu1DLtpL8BS6A7-q8i2K;u4st;6_dqIUv7t|_J%VH`p zbS+p}D(7&s+`+;eFb78Dz>XGE(Se;T%mH&?L=Nn1VGfuBBXVFD3v<967?A_JT1-U; zcC#=C%z+U(u)BphU=EDPfjumyq62$cY+erFf4-wH!qP**~C<;zGCiWLd`8_{6oBO31ePPgrIvr(3F z=h6p*F2U#cBt-qvf$;E!SBF{BSPa8~dATS{WZlDcJ)$RGis&_t@~9p0WlHcjzv7$sl=^msc;KEU%;Yd$# z+ww+s0IwrnQT5i;yGcuN28ZRqf-wXC`16`_K>!ODc#0dYExj=pnqcA%EF3e+GDz_L z1UbNEy$Cu>8_j{*Wi4FD*Qc+IxsCRo)9c_xV?GP10!v@%Xs+3*FsDX=pza%)G$)0PcUvpV5${Z3Ll2jOE|%49=&-=G!;ngz4$m$cB{w(@2ZEh0;e*|EzZ@xbS9M4q z%G`-O<$An0Cp4~?14ree^rTDp7_-#EsCP^J6_#N|*u@p++&dUIZU=&$WHx_r2eGd7 z`?y0Q)d@3RQ-6|_^gL2m7}JLXN9UppB>hwfhD;UKp^MmcsZ^a%`oXYA5-su@0+Nn_ z5jhZUZ-CPVpB&(@&2!|Kfur0AlLH^QxeeZF;3x;4v_W%VdOC1ti_Oo0vY)Tim#Cjb zrs>;(<@un0KF1Dy#*D1U&*N;lJnR~Cj|nE~fV&BNWN)Opyo)H%K6TMlS6SVs1IOl~ zWU@TABuu{-mqY23qp8d4GmWcdc$2k~El|uJ8)P+FkqLe2# z9Ja@B9T1lZaDh3LDiK9xCQ8SJr%#Tt$0Rs#d@f2R3Ahjak^+p${k(k111h^E?h%%# zp21-_z-Id^3l~$rws3S%yGwMp>v>1>CeFin+v<F4-uF#Rp|hoFhwJFYq9Jx-Jg| zX{xYlvK^qG4(^l>R(t~qODYo8!u|GKFQA&jhzU4w!ce0e>h@{8{H{Zda;V#Fxj8Vk z95~U!954q)A32oe3W^5 zY_{uQX!ulim5qIZDbRtF^HCCwkMiV_p1#E2Nl+85Ino5BXex{SXjl+ZMPlVd9dN$l zgD$~+BBa$qSK8R&ll`BC@e+L_JVnK7%j0w4lzfy#XCgC-w?TSEPdDvXs6}<1F%xirO{Od#`T_Z!C0?4B z_>4HHM3Nqkw7X_vc}c3UYCH~{K2VecO`SgA*kFg*RLy|_{U30wcDxa13>4)+Q#ND{ zOm7Fyw3vzxoMmASm;)nn;A{(Xz#JHn1Ls(n1LnYp95~lvDmrkUg*jjjjL3oWEzALP zU_=gFU||lJ10!5WsLcIw)d*RDQo`ONEXy?OPz z^&3{Mx_KoQCKWygu8`i8scG=8p)~#HN;7DA) zU|BO9}dMizk%YsmqBsCrBGb7Efg1j5{gS7 z1jXgcpt$0HtDtzql~6otM<^cs zStuU+Fen~>G!#$xBNR`<`+3S$P&{oXD4zZ~D4zLnD4u-`6wmn+6wiA#6fd|MiWi~B zFaA6fFMR|QFTWEMulO?*uX+s>uf7`;uiXWT*L?wsH#`!GH{BVEH~$5Sx4ssNx37fa zox9@SLSKa9-H(Fez009^-(R8l!0Vv+(A}Z<$Zk-4^h;2D{LxT+@>nQ7^*1O!^Li*g zw+f0c><+~jzYN8f9|Of#kAvcCe~025Z-C-k_kiL%dqDBsuR!tr$3pSLfX1HxfySJ-L1W%Mp|SUTXzcSXXzcf7XdG}7 zG!FbPG!A|{G!|YDjm3LIOg9Jc|Iaq_ zmGf*(*r%*EH%?+i$8>$GA)ViuK;SF+X#rFwMfdG}%DOM;uha7wY=&>(UYkma{xpU`usV$lr|DY))Ceseo~OyFq5gv7V(pj=`4dDmY_?Zt$i}DsM4?z%S>g z1&m|aAT#4w&(iM4P)BtY#M!jsWt&dkG6cRSB7C}>LSF@;6L}o8Zpc4~mklz&AP9Zw zWpONsf`(ouGKea|F4Hw#&$mh5)oKulineSV4W)}w?#M>3K4b@Pf&Oztdo3cq}D>lNp_m-0p=k_J(CY5WQzVsWNLtN6H?AzV$E06qlzK9L-P>mW?AQf1VJ4IvZJ{TS}y2B*us zPkq|Id-@JRrQXCt&#SJ2PEoCswftSWoTz3aMC2Xd?7kYmjnDDPYR=dp$Ud-;Db-bL zX@r##3n_p!Nx?%%#s!X4OzcIC;u07Z=BMKsG9!TBL>3TGT?L(_TBm9!$K|Da8mxAYV+aRV+i!ykBM25{Q5obJotqZe$ggA$2#l)mvmpJ)<#C2`2zMf(4`` z4@adI_Uu-L)mk4Ui^NCOO$VjQNTnzH7+^==jK`YWDg<)9plWX=xDIHAu)HtNX_>}6 zC7b}gCr4^d-XbA+H+DT#T?JjQTKm(*q`HO&IHxBhY$!0L`}~MMNpS9~lv{_u4ZWah zZ!NeEXoax6FVAUN1!L*LFF+`p1Pf5h-Hdv;DJ|@|rYfw~G#r-eJ%RGcHPS(@5?zIq zeF9jJEL5a8qPggkumW(A;5wjVn8oZubA&@+kD-i+F>x~PBee_(P^2GE9A7-V}36a>Y67975Vh$|DyEE;wUH zx|)kK!U~`n?$-gGB`g&oGMuIuW3IoD;^OWcsX0D4P6$I(C8&o~l(;gfV=v5RX1pd{ z#1-ebhmqRHRQfVJ${AJVHX)Gf1yy?+!F50@gynsCPRkf`PS*5IYN4E+A(5&?a-JVW zh3u#S8qdt+CV3C%+ODuCJuOjl!5Jq+t-1Kd!U~`n?$<$h2TEy(RA|jG=1d~N0>&ay zC|@UgjF1At=YfVK66o6-J7XrDSF!m7z zX&ulCVR>I5WxwaOj4@}oq;`tl9hK@pBrAugrhXg2YCu7MyofS@#hAx9Q3N@uY-SZ_ zGBKJQ5f8|rB1^t$WO)x|wK41w3Tut|7;QwD)-u5e+#6A@pQ3h4H#smfq=oTq7^!Xw z`EVAxED`~!yc_qP8Q~XIWQszcD67F%z+U(u#1H`U=EDP zfn6=8q652Gm;>g(h#c76!W=LMM&!UA7E{rIJuNmb2k<}N(HC<69nXI=g5AEO?gdPV zqT7h^gFCQS*FeLuN1wesa;2*?GjuOeYKRiH^;WO=v_;2o$dp}X>BBnice1pbX^F!B)%_kE|^ z_PN<8%eiyugF%cD5dT1{@Ef>$v1m2Gi?v)JYM>HQLLL&&3Px`4vhKKEd zx|9ebqH9tWUYma*&-o(h5Bq(m*Z#e`MOk8pK6^XlWD$ANwOuDjNi7pf9W<7P?ts5G z_lKoBi%>k&V_}>uRHBn^95XaY4(www6&={u!W=LMM&!VL7UqCCFd_%`w=f6Hfe|@y zfW=gF;6Mv=z#JHn0|!}bjt-P1eJgwf;E?}Ukgh?Hnm#s12R6y?bnsYFqM&pSQW9|C zsL*hvC%A2SBRhcC5wECvYwF#kr8tAba$v!jfq(pYO}QX|1q(dI4cC_5mou!TDK<%;?F68Ue*T&pNd(Y{0@S-uIEEknQg3twLX%H)<*VuF8 zIzU&&*X7?NUJ&0W@fv%bJ%{MP;@(kG+dVjyp(0*&BinnSbw}VpdSUKB|G%rljk&_p zBX}D-LL4~6Vk$atsD(LT4vffwB^Ks@IWQszmRd|j2M)6^2h4#HIdJ&+qfAFCW!kiA zgbuiW`O)>f$~{%eu4B}o#ZFL0*mJ;|c?Xu|qRf%PRl1c@WH~@ur!RfVX^b1x0lo?P zanKH*=_$UG{Zht`)^|BQtl%@csEqFEz!AA9Jy~Mr4>H8MveH!@8VDj%W4If|hp!w% ztZzip(D)oUG8g1E^7NsH%Rv{*YBzLP;M!qGCmy5K-85QnxNir7o$N5X>wYT>K(LiO<`1qS z)|GxOcSxi z`dMU}z8zSe5BleG?9gY-$cp?t&X&u=t}*wRV4@DVo4`l*MykuZhyv|X7fp4Q)qOf} zY%WSB%VSHz^m}nRls-9{x~xvKr$e)gCY`XVZwHRcMag7|$p3YmgP~L@bdN(_2!t+5 zd1Aw1dkohBahU)Ym_w-&QB-E4bX<7)(Ko_VRIIimIrj;w0x9AETGbYbKVLqzbFXv`pc9>1o92n650mo{`8*#=!Q4Ta^ zL*~HrcHm5lsp!C27UqCCFd_%ewlD|Gfe|@yj)gg34vffwb1kN#1Ls+o1LnYp95~;? z954q)&?xYS}QI&hhV zIbaTq$bri(%mH&?L=IeGVGfuBBXZzMi>c_qRTk!eIWQszuC_1-%z+U(a5syo=m2b6 z0JH!AQ*nDyFoxTT1~eVN1$LSNld7ZeY-ph7cxaq`Dk^~*P`yJhvvHN>x9zU0tlGgn==^2Qri->`o9VKdj?ux1sq%Vu7)Zsl48 zM*{BrJ2cLH12oRR2Q)6+0~!~71saz;78;k~cf0%_(75uA(71XvG*<2jjk|vp8uxe{ zG_JV|G_L(8G}gQc8rNR~jkSA0T4>aES9caAksnB@ODbRRt361x^ z6B-{}3ylx&3yqI_7aAXX8Z5Rq4AZ|pz*Z= z8ee}GG`@KgG`_t*G`{nFXngM((D=dW(D+dU8b5wFG=6$BG=6>nG=A{|Xx#BkX#DyN zX#BPbjo-Zo8h^MKH2!oTH2(ZUX#DkA(D?hA(D-Ky8vlAPH2!ZLH2!-KH2(J^yy<5{ zvvC$QTWx5z-v`YZ>!G>j!O)!fV`y&m9B9ry8=BkV-<8|FADTOCfaXpMpt3PsRd`oC9`w%pbybm;wUJT7+eh$q$zW|!Y;@^G8&xGb(J`Byf-WQrH4uR%L zzkuc`FNEf47eMojS70;p?L>A zDW84jig_ojxoOc!H?3Q{a>M$0%N8$Pywo@CIn^8}ET*CZ4GVL?92k)UO$&3t92k)U zEsLq>K-*%vIe`CvwwbS-XKTVfWwp6+5+gdM>st-!{LTadU&&7kpfV}CZ|_sqeL;Vn zp2uJ_d;|B|R8sV}xj)q;uj}v7-YR(|0i;ig?hE>qbzjh5r`Ivqi+AJ-dGxou50yHh z4|U&?850P6B|j}-9Lolo8OM5-_BaMxs+&UoX1r!|%JNMGjN{u4GBb|#EbVa&wp3Ta z88dW)H*HdRiwOjNIX^969Lolo8OM5-c0YzXs;eN*rWG&Sbn=!V@I4XX)8!QUDhQp( zVTv53#!m&_@u#0$t!Yg5&)UFLo2)BfGlcL*x=CLVfTbrp1qYMrd*@6zQ&H5(x!?*M1_)%b0E zj!#x|#tuRDfrU(|u3AeYtc+Ml0i;O^9zrrMaHL{lFKQH*z_2hs9nX*%0sJPifPm^M z=p@xTRXa(39tY#sh$kqPA?L76Cv1f!c{D2ob+gcuu{&#);5s0&uwk7`brKmqFgqgc ztgsu&XXMj!(DVrs2o8FJ?RDyx=21iYBDb}n`!tGEoQyRog_ zB17sKjd@Bq0oV~NASHP?Dz&g@w<@gG`XE^(KB{gyC{;!(J=w_pKr4jheR)pHH0CMc1n50EQgiYa3CX*$>!Io@=z7)KpDrfVH9WvMJt1L3fhpbR zNBl{Gb6=(0Is|U$1yy@%!F50@gynsCPRlA7OBa3tLfIr(fLiWm)Wc0_Vb3*HVYQ~= zuw3s6luxda4sw;~Dx~Zaz=C9;M-QI@VYD7WT4K*egVS-ElmRRwom{XD~ z&Qa$O(mqlixkzxq89UO|T$~YB0L^f}4(KdlsR)tbG{qQm{e=`4cjrjW@xgII7@{gc zJ*1+@O16m<0@5^&q#+Y-m zrf*UUAv)@uZMekP1c%UY`AIu%fYC^%Zq4kVe%$a%0DJPWxtz}$m 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

@I)&^oaLt&=_qtyBILTC0wN)@i?h))_B@)>-$0 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�i}8=R>~nA$!Phox*1EFhbf_n;MFNPz6nKy_&( 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

=C;AiXemp#R_1 z;l^Cy=^Ea~jt~b9w-`kSj<7HX%z>I5IMTu#Fb8UK;3$hxbl_+UbHE&^$${~yN0E+{ z%Cu=!jSjef`O)*d(mj>Ro@3OY#ZFK}*muC1c?TM~C~~B5rEaMdSuf!9MPsUCz1A5o z4zQ*4;~>&!dQus>=scIPqxG^b1z|pT`2X)Wzv>XVQyTsRk3+Xmv zsk^E}f>7q)A#OC54sK zcYrOX96tW%<5%nUK-Z@B&;~c}SJ`tI2TspNK{P%nhmWIz+F^XCOpqB;@gI_Y!dGDc zd!DuDunwG&kAi4?P!6BMab8Y1`9zf$I5xWK|3Fb8UK z;6e*?z#OQ_fr~6g(SeIC%mH(tCI>FDFbB+mnjE;7g*jjj)a1aW7Nh9EWftauIZ%@W zms^+v=0HsjTw!4jm;*IAaHYj4I&hVRIbaUd`Ygb;k`iy0BufOe< z)$7)8Sh?zkWgFJrx_a&!;@2-b@`%RVRoAb)>88~;u3vWa-1RrES%qw4?zQVyu0_xS z+<65wf3-6-fBk7_{`L{j{9PNGzyA$1|M)6s{`pF1{&g2<{_Qi+{Kq4q`L7N%i{C

=C;AiXemp#R_1 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/@(s}X^eSk5c6Vrf?kmvx!egQJrBk8x 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

|9djXyMes8BCQ7YmiD59~R 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 literal 0 HcmV?d00001 diff --git a/webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif b/webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif new file mode 100644 index 0000000000000000000000000000000000000000..ebf7100d79079638933cb88bf1159264fc0619e7 GIT binary patch literal 1578825 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 literal 0 HcmV?d00001 diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 530c6bd34..eed729c85 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -605,6 +605,7 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: zarray = self._zarray with _blosc_disable_threading(): data = zarray[(slice(None),) + bbox.get_slice_tuple()] + assert data is not None, f"There is no data for given BoundingBox: {bbox}" shape_with_channels = (self.info.num_channels,) + shape if data.shape not in (shape, shape_with_channels): @@ -661,7 +662,11 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: zarray = self._zarray index_tuple = (slice(None),) + bbox.get_slice_tuple() - zarray[index_tuple] = data.reshape((self.info.num_channels,) + bbox.size.to_tuple()) + # transform data to write into desired zarray shape + data = data[(slice(None), slice(None), slice(None)) + tuple(np.newaxis for i in range(len(bbox) - 2))] + data = np.moveaxis(data, [1,0,2], bbox.get_3d("index")) + + zarray[index_tuple] = data def list_bounding_boxes(self) -> Iterator[BoundingBox]: raise NotImplementedError diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 439dc2a74..395aa84a0 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -111,7 +111,6 @@ def __init__( ## arguments as inner attributes self._channel = channel - self._timepoint = timepoint self._czi_channel = czi_channel self._swap_xy = swap_xy self._flip_x = flip_x @@ -120,9 +119,10 @@ def __init__( self._use_bioformats = use_bioformats ## attributes that will be set in __init__() - self._iter_dim = None + # _bundle_axes + self._iter_axes = None + self._iter_loop_size = None self._possible_layers = {} - # _img_dims ## attributes only for pims.FramesSequenceND instances: # _default_coords @@ -162,38 +162,27 @@ def __init__( if len(available_czi_channels) > 1: self._possible_layers["czi_channel"] = available_czi_channels + # An image slice should always consist of a 2D image. If there are multiple channels + # the data of each channel should be part delivered too. Other if images.sizes.get("c", 1) > 1: - self._img_dims = "cyx" + self._bundle_axes = ["c", "y", "x"] else: if "c" in images.axes: + # When c-axis is not in _bundle_axes and _iter_axes its value at coordinate 0 + # should be returned self._default_coords["c"] = 0 - self._img_dims = "yx" - - _iter_dim = [] - for axis in images.sizes: - if axis not in ["x", "y", "c"]: - _iter_dim.append(axis) - self._iter_dim = tuple(_iter_dim) - - # if images.sizes.get("z", 1) > 1: - # self._iter_dim = "z" - # elif "z" in images.axes: - # self._default_coords["z"] = 0 - - # if timepoint is None: - # if images.sizes.get("t", 1) > 1: - # if self._iter_dim == "": - # self._iter_dim = "t" - # else: - # self._default_coords["t"] = 0 - # self._possible_layers["timepoint"] = list( - # range(0, images.sizes["t"]) - # ) - # elif "t" in images.axes: - # self._default_coords["t"] = 0 - # else: - # assert "t" in images.axes - # self._default_coords["t"] = timepoint + self._bundle_axes = ["y", "x"] + + # All other axes are used to iterate over them. The last one is iterated the fastest. + self._iter_axes = list(set(images.axes).difference({*self._bundle_axes, "c", "z"})) + self._iter_axes.append("z") + + if len(self._iter_axes) > 1: + iter_size = 1 + self._iter_loop_size = dict() + for axis, other_axis in zip(self._iter_axes[-1:0:-1], self._iter_axes[-2::-1]): + self._iter_loop_size[other_axis] = (iter_size := iter_size * images.sizes[axis]) + else: # Fallback for generic pims classes that do not name their # dimensions as pims.FramesSequenceND does: @@ -204,79 +193,59 @@ def __init__( if len(images.shape) == 2: # Assume yx - self._img_dims = "yx" - self._iter_dim = "" + self._bundle_axes = ["y", "x"] + self._iter_axes = [""] elif len(images.shape) == 3: # Assume yxc, cyx or zyx if _assume_color_channel(images.shape[2], images.dtype): - self._img_dims = "yxc" - self._iter_dim = "" + self._bundle_axes = ["y", "x", "c"] + self._iter_axes = [""] elif images.shape[0] == 1 or ( _allow_channels_first and _assume_color_channel(images.shape[0], images.dtype) ): - self._img_dims = "cyx" - self._iter_dim = "" + self._bundle_axes = ["c", "y", "x"] + self._iter_axes = [""] else: - self._img_dims = "yx" - self._iter_dim = "z" + self._bundle_axes = ["y", "x"] + self._iter_axes = ["z"] elif len(images.shape) == 4: # Assume zcyx or zyxc if images.shape[1] == 1 or _assume_color_channel( images.shape[1], images.dtype ): - self._img_dims = "cyx" + self._bundle_axes = ["c", "y", "x"] else: - self._img_dims = "yxc" - self._iter_dim = "z" - elif len(images.shape) == 5: - # Assume tzcyx or tzyxc - # t has to be constant for this reader to obtain 4D image - # (only possible if not specified manually already, since - # the timepoint would already be indexed here and the - # 5th dimension would be something else) - if timepoint is not None: - raise RuntimeError( - f"Got {len(images.shape)} axes for the images after " - + "removing time dimension, can only map to 3D+channels." - ) - - if _assume_color_channel(images.shape[2], images.dtype): - self._img_dims = "cyx" - else: - self._img_dims = "yxc" - self._iter_dim = "z" - self._timepoint = 0 - if images.shape[0] > 1: - self._possible_layers["timepoint"] = list( - range(0, images.shape[0]) - ) + self._bundle_axes = ["y", "x", "c"] + self._iter_axes = ["z"] else: raise RuntimeError( f"Got {len(images.shape)} axes for the images, " - + "cannot map to 3D+channels+timepoints." + + "but don't have axes information. Try to open " + + "a N-dimensional image file with use_bioformats=" + + "True." ) + - ############################# - # IDENTIFY SHAPE & CHANNELS # - ############################# + ######################### + # IDENTIFY NUM_CHANNELS # + ######################### with self._open_images() as images: - c_index = self._img_dims.find("c") - if c_index == -1: - self.num_channels = 1 - else: + try: + c_index = self._bundle_axes.index("c") if isinstance(images, list): - images_shape = (len(images),) + cast( + images_shape = (len(images), ) + cast( pims.FramesSequence, images[0] ).shape else: images_shape = images.shape - # Since images_shape contains the first dimension iter_dim, - # we need to offset the index by one before accessing the images_shape. - # images_shape corresponds to (z, *_img_dims) + self.num_channels = images_shape[c_index + 1] + except ValueError: + self.num_channels = 1 + self._first_n_channels = None if self._channel is not None: assert ( @@ -413,7 +382,7 @@ def _open_images( self, ) -> Iterator[Union[pims.FramesSequence, List[pims.FramesSequence]]]: """ - This yields well-defined images of the form (self._iter_dim, *self._img_dims), + This yields well-defined images of the form (self._iter_axes, *self._bundle_axes), after IDENTIFY AXIS ORDER of __init__() has run. For a 2D image this is achieved by wrapping it in a list. """ @@ -449,7 +418,7 @@ def _open_images( with images_context_manager as images: if isinstance(images, pims.FramesSequenceND): - if hasattr(self, "_img_dims"): + if hasattr(self, "_bundle_axes"): # first part of __init__() has happened images.default_coords.update(self._default_coords) if self._init_c_axis and "c" not in images.sizes: @@ -461,12 +430,10 @@ def _open_images( images._get_frame_dict[ key + ("c",) ] = images._get_frame_dict.pop(key) - images.bundle_axes = self._img_dims - images.iter_axes = self._iter_dim or "" + images.bundle_axes = self._bundle_axes + images.iter_axes = self._iter_axes or [] else: - if self._timepoint is not None: - images = images[self._timepoint] - if self._iter_dim == "": + if self._iter_axes == []: # add outer list to wrap 2D images as 3D-like structure images = [images] yield images @@ -479,11 +446,14 @@ def copy_to_view( dtype: Optional[DTypeLike] = None, ) -> Tuple[Tuple[int, int], Optional[int]]: """Copies the images according to the passed arguments to the given mag_view. - args is expected to be the start and end of the z-range, meant for usage with an executor. + args is expected to be a (ND)BoundingBox the start and end of the z-range, meant for usage with an executor. copy_to_view returns an iterable of image shapes and largest segment ids. When using this method a manual update of the bounding box and the largest segment id might be necessary. """ relative_bbox = args + assert relative_bbox.set_3d("size", (1, 1, 1)) == VecInt.ones(len(relative_bbox)), ( + "The delivered BoundingBox has to be flat except for x,y and z dimension." + ) z_start, z_end = relative_bbox.get_bounds("z") shapes = [] max_id: Optional[int] @@ -493,6 +463,11 @@ def copy_to_view( max_id = None with self._open_images() as images: + if self._iter_axes is not None and self._iter_loop_size is not None: + # select the range of images that represents one xyz combination + lower_bounds = sum(self._iter_loop_size[axis_name]*relative_bbox.get_bounds(axis_name)[0] for axis_name in self._iter_axes[:-1]) + upper_bounds = lower_bounds + relative_bbox.get_shape("z") + images = images[lower_bounds:upper_bounds] if self._flip_z: images = images[::-1] # pylint: disable=unsubscriptable-object @@ -509,17 +484,17 @@ def copy_to_view( for image_slice in images[z_start:z_end]: image_slice = np.array(image_slice) # place channels first - if "c" in self._img_dims: + if "c" in self._bundle_axes: image_slice = np.moveaxis( - image_slice, source=self._img_dims.index("c"), destination=0 + image_slice, source=self._bundle_axes.index("c"), destination=0 ) # ensure the last two axes are xy: - if ("yx" in self._img_dims and not self._swap_xy) or ( - "xy" in self._img_dims and self._swap_xy + if ("yx" in self._bundle_axes and not self._swap_xy) or ( + "xy" in self._bundle_axes and self._swap_xy ): image_slice = image_slice.swapaxes(-1, -2) - if "c" in self._img_dims: + if "c" in self._bundle_axes: if self._channel is not None: image_slice = image_slice[self._channel : self._channel + 1] elif self._first_n_channels is not None: @@ -551,7 +526,7 @@ def get_possible_layers(self) -> Optional[Dict["str", List[int]]]: return self._possible_layers @cached_property - def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: + def expected_bbox(self) -> NDBoundingBox: # replaces the previous expected_shape to enable n-dimensional input files with self._open_images() as images: if isinstance(images, list): @@ -560,33 +535,33 @@ def expected_bbox(self) -> Union[NDBoundingBox, BoundingBox]: ).shape else: images_shape = images.shape # pylint: disable=no-member - x_index = self._img_dims.find("x") + 1 - y_index = self._img_dims.find("y") + 1 + x_index = self._bundle_axes.index("x") + 1 + y_index = self._bundle_axes.index("y") + 1 if self._swap_xy: x_index, y_index = y_index, x_index - if self._iter_dim is None or len(self._iter_dim) == 0 or self._iter_dim == "z": + if self._iter_axes is None or (len(self._iter_axes) <= 1 and self._iter_axes[0] == "z"): return BoundingBox( (0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0]), ) else: - axes = {"x": images_shape[x_index], "y": images_shape[y_index]} - for axis in self._iter_dim: - if hasattr(images, "sizes"): - axes[axis] = images.sizes[axis] - else: - axes[axis] = 0 - topleft = VecInt.zeros(len(axes)) - axes_names, size = zip(*axes.items()) - # TODO get current axis order from file and use it for nd bbbox - return NDBoundingBox( - topleft, - size, - axes_names, - index=(len(axes_names) - i for i, _ in enumerate(axes_names)), - ) - + if isinstance(images, pims.FramesSequenceND): + axes_names = self._iter_axes + self._bundle_axes + axes_sizes = [images.sizes[axis] for axis in axes_names] + axes_index = list(range(1, len(axes_names) + 1)) + topleft = VecInt.zeros(len(axes_names)) + + return NDBoundingBox( + topleft, + axes_sizes, + axes_names, + axes_index, + ) + + raise ValueError( + "It seems as if you try to load an N-dimensional image from 2D images. This is currently not supported." + ) T = TypeVar("T", bound=Tuple[int, ...]) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index e2f33ac17..0182e33de 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1293,7 +1293,7 @@ def add_layer_from_images( if pims_images.expected_bbox.size != actual_size: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " - + f"New size is {actual_size}, expected {pims_images.expected_bbox.get_shape('z')}." + + f"New size is {actual_size}, expected {pims_images.expected_bbox.size}." ) if first_layer is None: first_layer = layer diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index c5bba1189..c3b97414b 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -34,7 +34,7 @@ class BoundingBox(NDBoundingBox): topleft: Vec3Int = attr.field(converter=Vec3Int) size: Vec3Int = attr.field(converter=Vec3Int) axes: Tuple[str, str, str] = attr.field(default=("x", "y", "z")) - index: Vec3Int = attr.field(default=Vec3Int(3, 2, 1)) + index: Vec3Int = attr.field(default=Vec3Int(1, 2, 3)) bottomright: Vec3Int = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 95e861259..fdfa4d73d 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -6,7 +6,7 @@ import numpy as np from .mag import Mag -from .vec3_int import Vec3Int +from .vec3_int import Vec3Int, Vec3IntLike from .vec_int import VecInt, VecIntLike _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" @@ -97,8 +97,8 @@ def with_additional_axis( def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) - def with_size(self, new_size: VecInt) -> "NDBoundingBox": - return attr.evolve(self, size=new_size) + def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": + return attr.evolve(self, size=VecInt(new_size)) def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": return attr.evolve(self, is_visible=is_visible) @@ -236,12 +236,12 @@ def __eq__(self, other: object) -> bool: def __len__(self) -> int: return len(self.axes) - def get_shape(self, key) -> int: + def get_shape(self, axis_name: str) -> int: try: - index = self.axes.index(key) + index = self.axes.index(axis_name) return self.size[index] except ValueError as err: - raise ValueError(f"Axis {key} doesn't exist in NDBoundingBox.") from err + raise ValueError(f"Axis {axis_name} doesn't exist in NDBoundingBox.") from err def get_slice_tuple(self) -> Tuple[slice, ...]: return tuple( @@ -259,7 +259,8 @@ def get_3d(self, attr_name: str) -> Vec3Int: return Vec3Int(attr_3d) - def set_3d(self, attr_name: str, value: Vec3Int) -> VecInt: + def set_3d(self, attr_name: str, value: Vec3IntLike) -> VecInt: + value = Vec3Int(value) axes = ("x", "y", "z") modified_attr = getattr(self, attr_name).to_list() From e975f088e8e28def7482843593102d2d6cd51094 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 1 Feb 2024 16:03:01 +0100 Subject: [PATCH 18/41] Fixing issues with axis order. --- .../script_collection/reading_nd_data.py | 42 +++++++++++-------- webknossos/webknossos/dataset/_array.py | 14 ++----- .../dataset/_utils/buffered_slice_writer.py | 14 ++++++- .../webknossos/dataset/_utils/pims_images.py | 8 +++- .../webknossos/geometry/nd_bounding_box.py | 2 +- 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 4cabb6242..0d8055d37 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -1,13 +1,14 @@ from pathlib import Path +import numpy as np import pims from tifffile import imwrite import webknossos as wk from webknossos.geometry.nd_bounding_box import NDBoundingBox -TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" -OUTPUT = Path(".") / "testoutput" +TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "multi_channel_4D_series" +OUTPUT = Path(".") / "multi_channel_4D_series" def from_images_import(): @@ -21,27 +22,34 @@ def from_images_import(): data_format="zarr3", use_bioformats=True, ) - layer = dataset.get_color_layers()[0] - mag_view = layer.get_finest_mag() - read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4)) - data = mag_view.read(absolute_bounding_box=read_bbox) - assert data.shape == (1, ) + read_bbox.size - data = mag_view.read(absolute_bounding_box=NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4))) + # layer = dataset.get_color_layers()[0] + # mag_view = layer.get_finest_mag() + # read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 167, 439), axes=("t", "z", "y", "x"), index=(1,2,3,4)) + # data = mag_view.read(absolute_bounding_box=read_bbox) + # assert data.shape == (1,)+read_bbox.size - imwrite("l4_sample_tiff/test.tiff", data) + # imwrite("l4_sample_tiff/test.tiff", data) - for bbox in layer.bounding_box.chunk((439, 167, 5)): - with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: - for slice_data in reader: + # for bbox in layer.bounding_box.chunk((439, 167, 5)): + # with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: + # for slice_data in reader: - imwrite( - f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", - slice_data, - ) + # imwrite( + # f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", + # slice_data, + # ) def open_existing_dataset(): ds = wk.Dataset.open(OUTPUT) + layer = ds.get_color_layers()[0] + mag_view = layer.get_finest_mag() + read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4)) + data = mag_view.read(absolute_bounding_box=read_bbox) + assert data.shape == (1,)+read_bbox.size + data = mag_view.read(absolute_bounding_box=NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4))) + + imwrite("l4_sample_tiff/test.tiff", data) # color_layer = ds.get_color_layers()[0] # finest_mag = color_layer.get_finest_mag() # layers = ds.layers @@ -52,7 +60,7 @@ def open_existing_dataset(): def main() -> None: """Imports a dataset with more than 3 dimensions.""" from_images_import() - open_existing_dataset() + #open_existing_dataset() if __name__ == "__main__": diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index eed729c85..7f328473b 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -603,19 +603,15 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": def read(self, bbox: NDBoundingBox) -> np.ndarray: shape = bbox.size.to_tuple() zarray = self._zarray + slice_tuple = (slice(None),) + bbox.get_slice_tuple() with _blosc_disable_threading(): - data = zarray[(slice(None),) + bbox.get_slice_tuple()] + data = zarray[slice_tuple] assert data is not None, f"There is no data for given BoundingBox: {bbox}" shape_with_channels = (self.info.num_channels,) + shape if data.shape not in (shape, shape_with_channels): padded_data = np.zeros(shape_with_channels, dtype=data.dtype) - padded_data[ - :, - 0 : data.shape[1], - 0 : data.shape[2], - 0 : data.shape[3], - ] = data + padded_data[slice_tuple] = data data = padded_data return data @@ -662,10 +658,6 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: zarray = self._zarray index_tuple = (slice(None),) + bbox.get_slice_tuple() - # transform data to write into desired zarray shape - data = data[(slice(None), slice(None), slice(None)) + tuple(np.newaxis for i in range(len(bbox) - 2))] - data = np.moveaxis(data, [1,0,2], bbox.get_3d("index")) - zarray[index_tuple] = data def list_bounding_boxes(self) -> Iterator[BoundingBox]: diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index d59909606..ecdbde39c 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -41,7 +41,7 @@ def __init__( json_update_allowed: bool = True, # buffer_size specifies, how many slices should be aggregated until they are flushed. buffer_size: int = 32, - dimension: int = 2, # z + dimension: int = 2, # z (TODO: This currently don't work for nd data) *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 @@ -192,7 +192,17 @@ def _flush_buffer(self) -> None: ).moveaxis(-1, self.dimension) buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() - data = np.moveaxis(data, -1, self.dimension + 1) + + if self.bbox is not None: + # SliceWriter is used with bbox the data axes are ordered according to the axes_order + # of the bbox. + data = data[(slice(None), slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(self.bbox) - 3))] + data = np.moveaxis(data, [1,2,3], self.bbox.get_3d("index")) + else: + # Otherwise the axis that was used to write the slices should be moved back to its + # old position + data = np.moveaxis(data, -1, self.dimension + 1) + self.view.write( data, diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 395aa84a0..d48bfdb2c 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -514,6 +514,10 @@ def copy_to_view( if max_id is not None: max_id = max(max_id, image_slice.max()) + + x_index, y_index, _ = relative_bbox.get_3d("index") + if x_index > y_index: + image_slice = np.moveaxis(image_slice, -1, -2) shapes.append(image_slice.shape[-2:]) writer.send(image_slice) @@ -540,14 +544,14 @@ def expected_bbox(self) -> NDBoundingBox: if self._swap_xy: x_index, y_index = y_index, x_index - if self._iter_axes is None or (len(self._iter_axes) <= 1 and self._iter_axes[0] == "z"): + if self._iter_axes is None or len(self._iter_axes) <= 1: return BoundingBox( (0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0]), ) else: if isinstance(images, pims.FramesSequenceND): - axes_names = self._iter_axes + self._bundle_axes + axes_names = self._iter_axes + [axis for axis in self._bundle_axes if axis != "c"] axes_sizes = [images.sizes[axis] for axis in axes_names] axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index fdfa4d73d..4e29a5274 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -161,7 +161,7 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": topleft: List[int] = bbox["topLeft"] size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] axes: List[str] = ["x", "y", "z"] - index: List[int] = [3, 2, 1] + index: List[int] = [1, 2, 3] if "axisOrder" in bbox: axes = list(bbox["axisOrder"].keys()) From 61146c99d0dde529b83b784180f2d33c7b428158 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 5 Feb 2024 18:02:32 +0100 Subject: [PATCH 19/41] Rewrite buffered_slice_writer and fix bugs to get old tests working. --- .../dataset/_utils/buffered_slice_writer.py | 84 +++++++------------ .../webknossos/dataset/_utils/pims_images.py | 10 ++- webknossos/webknossos/dataset/layer.py | 4 +- .../webknossos/geometry/bounding_box.py | 7 ++ .../webknossos/geometry/nd_bounding_box.py | 10 +-- 5 files changed, 50 insertions(+), 65 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index ecdbde39c..4556af427 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -41,7 +41,7 @@ def __init__( json_update_allowed: bool = True, # buffer_size specifies, how many slices should be aggregated until they are flushed. buffer_size: int = 32, - dimension: int = 2, # z (TODO: This currently don't work for nd data) + dimension: int = 2, # z *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 @@ -57,6 +57,7 @@ def __init__( self.use_logging = use_logging self.json_update_allowed = json_update_allowed + if ( offset is None and relative_offset is None @@ -72,39 +73,26 @@ def __init__( DeprecationWarning, ) self.offset = None if offset is None else Vec3Int(offset) - self.relative_offset = ( - None if relative_offset is None else Vec3Int(relative_offset) - ) - self.absolute_offset = ( - None if absolute_offset is None else Vec3Int(absolute_offset) - ) - self.dimension = dimension - - effective_offset = Vec3Int.full(0) - if self.relative_offset is not None: - effective_offset = self.view.bounding_box.topleft + self.relative_offset - if self.absolute_offset is not None: - effective_offset = self.absolute_offset + if relative_offset is not None: + self.bbox = BoundingBox(self.view.bounding_box.topleft + relative_offset, Vec3Int.zeros()) - if relative_bounding_box is not None: - effective_offset = self.view.bounding_box.get_3d( - "topleft" - ) + relative_bounding_box.get_3d("topleft") - - if absolute_bounding_box is not None: - effective_offset = absolute_bounding_box.get_3d("topleft") + if absolute_offset is not None: + self.bbox = BoundingBox(absolute_offset, Vec3Int.zeros()) if relative_bounding_box is not None: self.bbox = relative_bounding_box.offset(self.view.bounding_box.topleft) if absolute_bounding_box is not None: self.bbox = absolute_bounding_box + + assert 0 <= dimension <= 2 # either x (0), y (1) or z (2) + self.dimension = self.bbox.get_3d("index")[dimension] - 1 - view_chunk_depth = self.view.info.chunk_shape[self.dimension] + view_chunk_depth = self.view.info.chunk_shape[dimension] if ( - effective_offset is not None - and effective_offset[self.dimension] % view_chunk_depth != 0 + self.bbox is not None + and self.bbox.topleft[self.dimension] % view_chunk_depth != 0 ): warnings.warn( "[WARNING] Using an offset that doesn't align with the datataset's chunk size, " @@ -115,8 +103,6 @@ def __init__( "[WARNING] Using a buffer size that doesn't align with the datataset's chunk size, " + "will slow down the buffered slice writer.", ) - # Previously the dimension was x, y or z now it can possibly be any axis of the bounding_box - # assert 0 <= dimension <= 2 self.slices_to_write: List[np.ndarray] = [] self.current_slice: Optional[int] = None @@ -154,9 +140,8 @@ def _flush_buffer(self) -> None: max_width = max(section.shape[-2] for section in self.slices_to_write) max_height = max(section.shape[-1] for section in self.slices_to_write) channel_count = self.slices_to_write[0].shape[0] - buffer_depth = min(self.buffer_size, len(self.slices_to_write)) - buffer_bbox = BoundingBox((0, 0, 0), (max_width, max_height, buffer_depth)) + self.bbox = self.bbox.with_size(self.bbox.set_3d("size", (max_width, max_height, buffer_depth))) shard_dimensions = self.view._get_file_dimensions().moveaxis( -1, self.dimension @@ -166,51 +151,42 @@ def _flush_buffer(self) -> None: min(shard_dimensions[1], max_height), buffer_depth, ) - for chunk_bbox in buffer_bbox.chunk(chunk_size): + for chunk_bbox in self.bbox.chunk(chunk_size): info(f"Writing chunk {chunk_bbox}{f' in {self.bbox}' if self.bbox is not None else ''}.") - width, height, depth = chunk_bbox.size + data = np.zeros( - (channel_count, width, height, depth), + (channel_count, *chunk_bbox.size), dtype=self.slices_to_write[0].dtype, ) + section_topleft = chunk_bbox.get_3d("topleft") + section_bottomright = chunk_bbox.get_3d("bottomright") + + slice_tuple = (slice(None), ) + chunk_bbox.get_slice_tuple() + z_index = chunk_bbox.get_3d("index")[2] z = 0 for section in self.slices_to_write: section_chunk = section[ :, - chunk_bbox.topleft.x : chunk_bbox.bottomright.x, - chunk_bbox.topleft.y : chunk_bbox.bottomright.y, + section_topleft[0] : section_bottomright[0], + section_topleft[1] : section_bottomright[1], ] - data[ - :, 0 : section_chunk.shape[-2], 0 : section_chunk.shape[-1], z - ] = section_chunk + section_chunk = section_chunk[(slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(self.bbox) - 2))] + section_chunk = np.moveaxis(section_chunk, [1,2], self.bbox.get_3d("index")[:2]) - z += 1 - buffer_start = Vec3Int( - chunk_bbox.topleft.x, chunk_bbox.topleft.y, self.buffer_start_slice - ).moveaxis(-1, self.dimension) - buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() + data[slice_tuple[:z_index] + (slice(z), ) + slice_tuple[z_index+1:]] = section_chunk + z += 1 - if self.bbox is not None: - # SliceWriter is used with bbox the data axes are ordered according to the axes_order - # of the bbox. - data = data[(slice(None), slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(self.bbox) - 3))] - data = np.moveaxis(data, [1,2,3], self.bbox.get_3d("index")) - else: - # Otherwise the axis that was used to write the slices should be moved back to its - # old position - data = np.moveaxis(data, -1, self.dimension + 1) - + buffer_start = Vec3Int(*chunk_bbox.get_3d("topleft")[:2], self.buffer_start_slice) + buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() self.view.write( data, offset=buffer_start.add_or_none(self.offset), - relative_offset=buffer_start_mag1.add_or_none(self.relative_offset), - absolute_offset=buffer_start_mag1.add_or_none(self.absolute_offset), json_update_allowed=self.json_update_allowed, - absolute_bounding_box=self.bbox.offset(buffer_start_mag1) + absolute_bounding_box=chunk_bbox.offset(buffer_start_mag1) if self.bbox else None, ) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index d48bfdb2c..3e885c032 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -539,12 +539,14 @@ def expected_bbox(self) -> NDBoundingBox: ).shape else: images_shape = images.shape # pylint: disable=no-member - x_index = self._bundle_axes.index("x") + 1 - y_index = self._bundle_axes.index("y") + 1 - if self._swap_xy: - x_index, y_index = y_index, x_index if self._iter_axes is None or len(self._iter_axes) <= 1: + if self._bundle_axes.index("x") < self._bundle_axes.index("y"): + x_index, y_index = 1, 2 + else: + x_index, y_index = 2, 1 + if self._swap_xy: + x_index, y_index = y_index, x_index return BoundingBox( (0, 0, 0), (images_shape[x_index], images_shape[y_index], images_shape[0]), diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 162e7178f..c5fa3a932 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -9,10 +9,10 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union import numpy as np -from cluster_tools import Executor from numpy.typing import DTypeLike from upath import UPath +from cluster_tools import Executor from webknossos.geometry.nd_bounding_box import NDBoundingBox from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike @@ -740,7 +740,7 @@ def downsample( sampling_mode = SamplingModes.parse(sampling_mode) - if self._properties.bounding_box.size.z == 1: + if self._properties.bounding_box.get_3d("size").z == 1: if sampling_mode != SamplingModes.CONSTANT_Z: warnings.warn( "[INFO] The sampling_mode was changed to 'CONSTANT_Z'. Downsampling 2D data with a different sampling mode mixes in black and thus leads to darkened images." diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index c3b97414b..01adcc016 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -211,6 +211,13 @@ def to_tuple6(self) -> Tuple[int, int, int, int, int, int]: def to_csv(self) -> str: return ",".join(map(str, self.to_tuple6())) + + def __eq__(self, other: object) -> bool: + if isinstance(other, NDBoundingBox): + self._check_compatibility(other) + return self.topleft == other.topleft and self.size == other.size + + raise NotImplementedError() def __repr__(self) -> str: return f"BoundingBox(topleft={self.topleft.to_tuple()}, size={self.size.to_tuple()})" diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 4e29a5274..70add5f1d 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -230,8 +230,8 @@ def __eq__(self, other: object) -> bool: if isinstance(other, NDBoundingBox): self._check_compatibility(other) return self.topleft == other.topleft and self.size == other.size - else: - raise NotImplementedError() + + raise NotImplementedError() def __len__(self) -> int: return len(self.axes) @@ -326,8 +326,8 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": self.get_3d("bottomright") % mag_vec == Vec3Int.zeros() ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." - new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") * mag_vec)) - new_size = self.set_3d("size", Vec3Int(self.get_3d("size") * mag_vec)) + new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") // mag_vec)) + new_size = self.set_3d("size", Vec3Int(self.get_3d("size") // mag_vec)) return attr.evolve( self, @@ -442,7 +442,7 @@ def chunk( # axes. chunk_shape = Vec3Int(chunk_shape) - chunk_shape = self.with_size(VecInt.ones(len(self))).set_3d("size", chunk_shape) + chunk_shape = self.with_size(VecInt.ones(len(self))).set_3d("size", chunk_shape).to_np() except AssertionError: chunk_shape = VecInt(chunk_shape).to_np() From 6fff638005216d14646deb50f359bcf3a382ca76 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 6 Feb 2024 00:30:52 +0100 Subject: [PATCH 20/41] Fix chunking in buffered slice writer. --- .../script_collection/reading_nd_data.py | 4 ++-- .../dataset/_utils/buffered_slice_writer.py | 20 +++++++++---------- webknossos/webknossos/dataset/view.py | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 0d8055d37..5a9de64b9 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -7,8 +7,8 @@ import webknossos as wk from webknossos.geometry.nd_bounding_box import NDBoundingBox -TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "multi_channel_4D_series" -OUTPUT = Path(".") / "multi_channel_4D_series" +TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" +OUTPUT = Path(".") / "4D_series" def from_images_import(): diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 4556af427..481f97760 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -87,12 +87,12 @@ def __init__( self.bbox = absolute_bounding_box assert 0 <= dimension <= 2 # either x (0), y (1) or z (2) - self.dimension = self.bbox.get_3d("index")[dimension] - 1 + self.dimension = dimension view_chunk_depth = self.view.info.chunk_shape[dimension] if ( self.bbox is not None - and self.bbox.topleft[self.dimension] % view_chunk_depth != 0 + and self.bbox.get_3d("topleft")[self.dimension] % view_chunk_depth != 0 ): warnings.warn( "[WARNING] Using an offset that doesn't align with the datataset's chunk size, " @@ -152,7 +152,7 @@ def _flush_buffer(self) -> None: buffer_depth, ) for chunk_bbox in self.bbox.chunk(chunk_size): - info(f"Writing chunk {chunk_bbox}{f' in {self.bbox}' if self.bbox is not None else ''}.") + info(f"Writing chunk {chunk_bbox}.") data = np.zeros( (channel_count, *chunk_bbox.size), @@ -161,8 +161,8 @@ def _flush_buffer(self) -> None: section_topleft = chunk_bbox.get_3d("topleft") section_bottomright = chunk_bbox.get_3d("bottomright") - slice_tuple = (slice(None), ) + chunk_bbox.get_slice_tuple() - z_index = chunk_bbox.get_3d("index")[2] + slice_tuple = (slice(None), ) + tuple(slice(0, size) for size in chunk_bbox.size) + z_index = chunk_bbox.get_3d("index")[self.dimension] z = 0 for section in self.slices_to_write: @@ -172,14 +172,14 @@ def _flush_buffer(self) -> None: section_topleft[1] : section_bottomright[1], ] section_chunk = section_chunk[(slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(self.bbox) - 2))] - section_chunk = np.moveaxis(section_chunk, [1,2], self.bbox.get_3d("index")[:2]) + section_chunk = np.moveaxis(section_chunk, [1,2], self.bbox.get_3d("index")[:self.dimension] + self.bbox.get_3d("index")[self.dimension+1:]) - - data[slice_tuple[:z_index] + (slice(z), ) + slice_tuple[z_index+1:]] = section_chunk + data[slice_tuple[:z_index] + (slice(z, z+1), ) + slice_tuple[z_index+1:]] = section_chunk z += 1 - - buffer_start = Vec3Int(*chunk_bbox.get_3d("topleft")[:2], self.buffer_start_slice) + + chunk_topleft = chunk_bbox.get_3d("topleft") + buffer_start = Vec3Int(*(chunk_topleft[:self.dimension] + (self.buffer_start_slice,) + chunk_topleft[self.dimension+1:])) buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() self.view.write( diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index f52fe2831..70fadd158 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -1123,7 +1123,7 @@ def _get_file_dimensions(self) -> Vec3Int: return self.info.shard_shape def _get_file_dimensions_mag1(self) -> Vec3Int: - return self._get_file_dimensions() * self.mag.to_vec3_int() + return Vec3Int(self._get_file_dimensions() * self.mag.to_vec3_int()) @property def _array(self) -> BaseArray: From 6e9efd695e11f08ce32b029352cd774f9491490a Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 6 Feb 2024 14:05:21 +0100 Subject: [PATCH 21/41] Fix issues with old tests. --- .../script_collection/reading_nd_data.py | 22 +++++++-- webknossos/tests/test_examples.py | 4 +- webknossos/webknossos/dataset/_array.py | 2 +- .../dataset/_utils/buffered_slice_reader.py | 46 +++-------------- .../dataset/_utils/buffered_slice_writer.py | 49 ++++++++++++++----- .../webknossos/dataset/_utils/pims_images.py | 44 +++++++++++------ webknossos/webknossos/dataset/dataset.py | 2 +- webknossos/webknossos/dataset/layer.py | 2 +- webknossos/webknossos/dataset/mag_view.py | 11 +++-- webknossos/webknossos/dataset/properties.py | 3 +- webknossos/webknossos/dataset/view.py | 18 ++++--- .../webknossos/geometry/bounding_box.py | 4 +- .../webknossos/geometry/nd_bounding_box.py | 14 ++++-- 13 files changed, 126 insertions(+), 95 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 5a9de64b9..72148ea5e 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -27,7 +27,7 @@ def from_images_import(): # read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 167, 439), axes=("t", "z", "y", "x"), index=(1,2,3,4)) # data = mag_view.read(absolute_bounding_box=read_bbox) # assert data.shape == (1,)+read_bbox.size - + # imwrite("l4_sample_tiff/test.tiff", data) # for bbox in layer.bounding_box.chunk((439, 167, 5)): @@ -44,10 +44,22 @@ def open_existing_dataset(): ds = wk.Dataset.open(OUTPUT) layer = ds.get_color_layers()[0] mag_view = layer.get_finest_mag() - read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4)) + read_bbox = NDBoundingBox( + topleft=(0, 0, 0, 0), + size=(1, 1, 439, 167), + axes=("t", "z", "y", "x"), + index=(1, 2, 3, 4), + ) data = mag_view.read(absolute_bounding_box=read_bbox) - assert data.shape == (1,)+read_bbox.size - data = mag_view.read(absolute_bounding_box=NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 439, 167), axes=("t", "z", "y", "x"), index=(1,2,3,4))) + assert data.shape == (1,) + read_bbox.size + data = mag_view.read( + absolute_bounding_box=NDBoundingBox( + topleft=(0, 0, 0, 0), + size=(1, 1, 439, 167), + axes=("t", "z", "y", "x"), + index=(1, 2, 3, 4), + ) + ) imwrite("l4_sample_tiff/test.tiff", data) # color_layer = ds.get_color_layers()[0] @@ -60,7 +72,7 @@ def open_existing_dataset(): def main() -> None: """Imports a dataset with more than 3 dimensions.""" from_images_import() - #open_existing_dataset() + # open_existing_dataset() if __name__ == "__main__": diff --git a/webknossos/tests/test_examples.py b/webknossos/tests/test_examples.py index c0be46d36..e75a1d17a 100644 --- a/webknossos/tests/test_examples.py +++ b/webknossos/tests/test_examples.py @@ -312,7 +312,7 @@ def test_download_segments() -> None: assert ( len(list(output_path.iterdir())) - == 2 * mag_view.layer.bounding_box.size.z / mag_view.mag.z + == 2 * mag_view.layer.bounding_box.get_3d("size").z / mag_view.mag.z ) @@ -329,7 +329,7 @@ def test_download_tiff_stack() -> None: assert ( len(list(output_path.iterdir())) - == mag_view.bounding_box.size.z / mag_view.mag.z + == mag_view.bounding_box.get_3d("size").z / mag_view.mag.z ) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 7f328473b..1df250da5 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -587,7 +587,7 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": else: ArrayV2.create( store=path, - shape=(array_info.num_channels, 1, 1, 1), + shape=(array_info.shape), chunks=(array_info.num_channels,) + array_info.chunk_shape.to_tuple(), dtype=array_info.voxel_type, compressor=( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index 21a578ec7..870a885d5 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -10,7 +10,6 @@ from ..view import View from ...geometry import BoundingBox, NDBoundingBox, Vec3IntLike -from ...utils import get_chunks class BufferedSliceReader: @@ -61,49 +60,18 @@ def __init__( self.bbox_current_mag = absolute_bounding_box.in_mag(view.mag) def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: - for batch in get_chunks( - list( - range( - self.bbox_current_mag.topleft[self.dimension], - self.bbox_current_mag.bottomright[self.dimension], - ) - ), - self.buffer_size, - ): - n_slices = len(batch) - batch_start_idx = batch[0] - - assert ( - n_slices <= self.buffer_size - ), f"n_slices should at most be batch_size, but {n_slices} > {self.buffer_size}" - - bbox_offset = self.bbox_current_mag.get_3d("topleft") - bbox_size = self.bbox_current_mag.get_3d("size") - - buffer_bounding_box = BoundingBox.from_tuple2( - ( - bbox_offset[: self.dimension] - + (batch_start_idx,) - + bbox_offset[self.dimension + 1 :], - bbox_size[: self.dimension] - + (n_slices,) - + bbox_size[self.dimension + 1 :], - ) - ) - buffer_bounding_box = self.bbox_current_mag.with_size(self.bbox_current_mag.set_3d("size", buffer_bounding_box.size)).offset(self.bbox_current_mag.set_3d("topleft", buffer_bounding_box.topleft)) + chunk_size = self.bbox_current_mag.get_3d("size").to_list() + chunk_size[self.dimension] = self.buffer_size + for chunk in self.bbox_current_mag.chunk(chunk_size): if self.use_logging: - info( - f"({getpid()}) Reading {n_slices} slices at position {batch_start_idx}." - ) + info(f"({getpid()}) Reading data from bbox {chunk}.") data = self.view.read( - absolute_bounding_box=buffer_bounding_box.from_mag_to_mag1( - self.view.mag - ) + absolute_bounding_box=chunk.from_mag_to_mag1(self.view.mag) ) - for current_slice in np.rollaxis( - data, self.dimension + 1 + for current_slice in np.moveaxis( + data, self.dimension + 1, 0 ): # The '+1' is important because the first dimension is the channel yield current_slice diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 481f97760..be276a592 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -57,7 +57,6 @@ def __init__( self.use_logging = use_logging self.json_update_allowed = json_update_allowed - if ( offset is None and relative_offset is None @@ -75,7 +74,9 @@ def __init__( self.offset = None if offset is None else Vec3Int(offset) if relative_offset is not None: - self.bbox = BoundingBox(self.view.bounding_box.topleft + relative_offset, Vec3Int.zeros()) + self.bbox = BoundingBox( + self.view.bounding_box.topleft + relative_offset, Vec3Int.zeros() + ) if absolute_offset is not None: self.bbox = BoundingBox(absolute_offset, Vec3Int.zeros()) @@ -85,8 +86,8 @@ def __init__( if absolute_bounding_box is not None: self.bbox = absolute_bounding_box - - assert 0 <= dimension <= 2 # either x (0), y (1) or z (2) + + assert 0 <= dimension <= 2 # either x (0), y (1) or z (2) self.dimension = dimension view_chunk_depth = self.view.info.chunk_shape[dimension] @@ -141,7 +142,9 @@ def _flush_buffer(self) -> None: max_height = max(section.shape[-1] for section in self.slices_to_write) channel_count = self.slices_to_write[0].shape[0] buffer_depth = min(self.buffer_size, len(self.slices_to_write)) - self.bbox = self.bbox.with_size(self.bbox.set_3d("size", (max_width, max_height, buffer_depth))) + self.bbox = self.bbox.with_size( + self.bbox.set_3d("size", (max_width, max_height, buffer_depth)) + ) shard_dimensions = self.view._get_file_dimensions().moveaxis( -1, self.dimension @@ -161,7 +164,9 @@ def _flush_buffer(self) -> None: section_topleft = chunk_bbox.get_3d("topleft") section_bottomright = chunk_bbox.get_3d("bottomright") - slice_tuple = (slice(None), ) + tuple(slice(0, size) for size in chunk_bbox.size) + slice_tuple = (slice(None),) + tuple( + slice(0, size) for size in chunk_bbox.size + ) z_index = chunk_bbox.get_3d("index")[self.dimension] z = 0 @@ -171,22 +176,40 @@ def _flush_buffer(self) -> None: section_topleft[0] : section_bottomright[0], section_topleft[1] : section_bottomright[1], ] - section_chunk = section_chunk[(slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(self.bbox) - 2))] - section_chunk = np.moveaxis(section_chunk, [1,2], self.bbox.get_3d("index")[:self.dimension] + self.bbox.get_3d("index")[self.dimension+1:]) - - data[slice_tuple[:z_index] + (slice(z, z+1), ) + slice_tuple[z_index+1:]] = section_chunk + section_chunk = section_chunk[ + (slice(None), slice(None), slice(None)) + + tuple(np.newaxis for _ in range(len(self.bbox) - 2)) + ] + section_chunk = np.moveaxis( + section_chunk, + [1, 2], + self.bbox.get_3d("index")[: self.dimension] + + self.bbox.get_3d("index")[self.dimension + 1 :], + ) + + data[ + slice_tuple[:z_index] + + (slice(z, z + 1),) + + slice_tuple[z_index + 1 :] + ] = section_chunk z += 1 - + chunk_topleft = chunk_bbox.get_3d("topleft") - buffer_start = Vec3Int(*(chunk_topleft[:self.dimension] + (self.buffer_start_slice,) + chunk_topleft[self.dimension+1:])) + buffer_start = Vec3Int( + *( + chunk_topleft[: self.dimension] + + (self.buffer_start_slice,) + + chunk_topleft[self.dimension + 1 :] + ) + ) buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() self.view.write( data, offset=buffer_start.add_or_none(self.offset), json_update_allowed=self.json_update_allowed, - absolute_bounding_box=chunk_bbox.offset(buffer_start_mag1) + absolute_bounding_box=chunk_bbox # .offset(buffer_start_mag1) if self.bbox else None, ) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 3e885c032..6adc002d5 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -174,14 +174,20 @@ def __init__( self._bundle_axes = ["y", "x"] # All other axes are used to iterate over them. The last one is iterated the fastest. - self._iter_axes = list(set(images.axes).difference({*self._bundle_axes, "c", "z"})) + self._iter_axes = list( + set(images.axes).difference({*self._bundle_axes, "c", "z"}) + ) self._iter_axes.append("z") if len(self._iter_axes) > 1: iter_size = 1 self._iter_loop_size = dict() - for axis, other_axis in zip(self._iter_axes[-1:0:-1], self._iter_axes[-2::-1]): - self._iter_loop_size[other_axis] = (iter_size := iter_size * images.sizes[axis]) + for axis, other_axis in zip( + self._iter_axes[-1:0:-1], self._iter_axes[-2::-1] + ): + self._iter_loop_size[other_axis] = ( + iter_size := iter_size * images.sizes[axis] + ) else: # Fallback for generic pims classes that do not name their @@ -225,7 +231,6 @@ def __init__( + "a N-dimensional image file with use_bioformats=" + "True." ) - ######################### # IDENTIFY NUM_CHANNELS # @@ -235,17 +240,17 @@ def __init__( try: c_index = self._bundle_axes.index("c") if isinstance(images, list): - images_shape = (len(images), ) + cast( + images_shape = (len(images),) + cast( pims.FramesSequence, images[0] ).shape else: images_shape = images.shape - + self.num_channels = images_shape[c_index + 1] except ValueError: self.num_channels = 1 - + self._first_n_channels = None if self._channel is not None: assert ( @@ -451,9 +456,9 @@ def copy_to_view( method a manual update of the bounding box and the largest segment id might be necessary. """ relative_bbox = args - assert relative_bbox.set_3d("size", (1, 1, 1)) == VecInt.ones(len(relative_bbox)), ( - "The delivered BoundingBox has to be flat except for x,y and z dimension." - ) + assert relative_bbox.set_3d("size", (1, 1, 1)) == VecInt.ones( + len(relative_bbox) + ), "The delivered BoundingBox has to be flat except for x,y and z dimension." z_start, z_end = relative_bbox.get_bounds("z") shapes = [] max_id: Optional[int] @@ -465,7 +470,11 @@ def copy_to_view( with self._open_images() as images: if self._iter_axes is not None and self._iter_loop_size is not None: # select the range of images that represents one xyz combination - lower_bounds = sum(self._iter_loop_size[axis_name]*relative_bbox.get_bounds(axis_name)[0] for axis_name in self._iter_axes[:-1]) + lower_bounds = sum( + self._iter_loop_size[axis_name] + * relative_bbox.get_bounds(axis_name)[0] + for axis_name in self._iter_axes[:-1] + ) upper_bounds = lower_bounds + relative_bbox.get_shape("z") images = images[lower_bounds:upper_bounds] if self._flip_z: @@ -486,7 +495,9 @@ def copy_to_view( # place channels first if "c" in self._bundle_axes: image_slice = np.moveaxis( - image_slice, source=self._bundle_axes.index("c"), destination=0 + image_slice, + source=self._bundle_axes.index("c"), + destination=0, ) # ensure the last two axes are xy: if ("yx" in self._bundle_axes and not self._swap_xy) or ( @@ -514,7 +525,7 @@ def copy_to_view( if max_id is not None: max_id = max(max_id, image_slice.max()) - + x_index, y_index, _ = relative_bbox.get_3d("index") if x_index > y_index: image_slice = np.moveaxis(image_slice, -1, -2) @@ -553,7 +564,9 @@ def expected_bbox(self) -> NDBoundingBox: ) else: if isinstance(images, pims.FramesSequenceND): - axes_names = self._iter_axes + [axis for axis in self._bundle_axes if axis != "c"] + axes_names = self._iter_axes + [ + axis for axis in self._bundle_axes if axis != "c" + ] axes_sizes = [images.sizes[axis] for axis in axes_names] axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) @@ -564,11 +577,12 @@ def expected_bbox(self) -> NDBoundingBox: axes_names, axes_index, ) - + raise ValueError( "It seems as if you try to load an N-dimensional image from 2D images. This is currently not supported." ) + T = TypeVar("T", bound=Tuple[int, ...]) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 0182e33de..e19abb0f4 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,11 @@ import attr import numpy as np from boltons.typeutils import make_sentinel +from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath -from cluster_tools import Executor from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index c5fa3a932..80913e840 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -9,10 +9,10 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union import numpy as np +from cluster_tools import Executor from numpy.typing import DTypeLike from upath import UPath -from cluster_tools import Executor from webknossos.geometry.nd_bounding_box import NDBoundingBox from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index d53db563c..b7ac66c29 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,9 +7,8 @@ from uuid import uuid4 import numpy as np -from upath import UPath - from cluster_tools import Executor +from upath import UPath from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( @@ -223,8 +222,12 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 ) -> np.ndarray: # THIS METHOD CAN BE REMOVED WHEN THE DEPRECATED OFFSET IS REMOVED diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index e93eabcce..aa38d50bd 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -1,3 +1,4 @@ +import copy from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union @@ -308,7 +309,7 @@ def __layer_properties_pre_structure( assert all( first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"] ) - d["boundingBox"]["axisOrder"] = first_mag["axisOrder"] + d["boundingBox"]["axisOrder"] = copy.deepcopy(first_mag["axisOrder"]) del d["boundingBox"]["axisOrder"]["c"] obj = converter_fn(d, type_value) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 70fadd158..cb10f9264 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -18,8 +18,8 @@ import numpy as np import wkw - from cluster_tools import Executor + from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike @@ -289,8 +289,8 @@ def write( mag1_bbox ), f"The bounding box to write {mag1_bbox} is larger than the view's bounding box {self.bounding_box}" - if len(data.shape) == 4 and data.shape[0] == 1: - data = data[0] # remove channel dimension for single-channel data + # if len(data.shape) == 4 and data.shape[0] == 1: + # data = data[0] # remove channel dimension for single-channel data current_mag_bbox = mag1_bbox.in_mag(self._mag) @@ -377,8 +377,12 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 ) -> np.ndarray: """ The user can specify which data should be read. @@ -540,8 +544,8 @@ def get_view( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 read_only: Optional[bool] = None, ) -> "View": """ diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 01adcc016..19e682dfe 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -211,12 +211,12 @@ def to_tuple6(self) -> Tuple[int, int, int, int, int, int]: def to_csv(self) -> str: return ",".join(map(str, self.to_tuple6())) - + def __eq__(self, other: object) -> bool: if isinstance(other, NDBoundingBox): self._check_compatibility(other) return self.topleft == other.topleft and self.size == other.size - + raise NotImplementedError() def __repr__(self) -> str: diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 70add5f1d..13743b4b8 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -230,9 +230,9 @@ def __eq__(self, other: object) -> bool: if isinstance(other, NDBoundingBox): self._check_compatibility(other) return self.topleft == other.topleft and self.size == other.size - + raise NotImplementedError() - + def __len__(self) -> int: return len(self.axes) @@ -241,7 +241,9 @@ def get_shape(self, axis_name: str) -> int: index = self.axes.index(axis_name) return self.size[index] except ValueError as err: - raise ValueError(f"Axis {axis_name} doesn't exist in NDBoundingBox.") from err + raise ValueError( + f"Axis {axis_name} doesn't exist in NDBoundingBox." + ) from err def get_slice_tuple(self) -> Tuple[slice, ...]: return tuple( @@ -442,7 +444,11 @@ def chunk( # axes. chunk_shape = Vec3Int(chunk_shape) - chunk_shape = self.with_size(VecInt.ones(len(self))).set_3d("size", chunk_shape).to_np() + chunk_shape = ( + self.with_size(VecInt.ones(len(self))) + .set_3d("size", chunk_shape) + .to_np() + ) except AssertionError: chunk_shape = VecInt(chunk_shape).to_np() From 0cb8241988f1bde345e59355760d66af31e023fc Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 8 Feb 2024 19:01:29 +0100 Subject: [PATCH 22/41] Working on fixing all tests. --- .../script_collection/reading_nd_data.py | 47 +++++++++++++------ webknossos/webknossos/dataset/_array.py | 8 ++-- .../dataset/_utils/buffered_slice_reader.py | 4 +- .../dataset/_utils/buffered_slice_writer.py | 16 +++---- .../webknossos/dataset/_utils/pims_images.py | 42 +++++++++++------ webknossos/webknossos/dataset/dataset.py | 11 ++--- webknossos/webknossos/dataset/mag_view.py | 4 +- webknossos/webknossos/dataset/view.py | 18 +++---- .../webknossos/geometry/bounding_box.py | 19 ++------ .../webknossos/geometry/nd_bounding_box.py | 34 ++++++-------- webknossos/webknossos/geometry/vec3_int.py | 20 ++------ webknossos/webknossos/geometry/vec_int.py | 6 ++- 12 files changed, 117 insertions(+), 112 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 72148ea5e..17dc4c2cd 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -1,14 +1,16 @@ from pathlib import Path import numpy as np -import pims +import tifffile + +# import pims from tifffile import imwrite import webknossos as wk from webknossos.geometry.nd_bounding_box import NDBoundingBox TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" -OUTPUT = Path(".") / "4D_series" +OUTPUT = Path(".") / "testdata" def from_images_import(): @@ -22,22 +24,38 @@ def from_images_import(): data_format="zarr3", use_bioformats=True, ) - # layer = dataset.get_color_layers()[0] - # mag_view = layer.get_finest_mag() - # read_bbox = NDBoundingBox(topleft=(0, 0, 0, 0), size=(1, 1, 167, 439), axes=("t", "z", "y", "x"), index=(1,2,3,4)) - # data = mag_view.read(absolute_bounding_box=read_bbox) + layer = dataset.get_color_layers()[0] + mag_view = layer.get_finest_mag() + data = mag_view.read()[0, 0, 0, :, :] # absolute_bounding_box=read_bbox) # assert data.shape == (1,)+read_bbox.size - # imwrite("l4_sample_tiff/test.tiff", data) + imwrite("l4_sample_tiff/test.tiff", data) - # for bbox in layer.bounding_box.chunk((439, 167, 5)): - # with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: - # for slice_data in reader: + for bbox in layer.bounding_box.chunk((439, 167, 5)): + with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: + for slice_data in reader: + imwrite( + f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", + slice_data, + ) - # imwrite( - # f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", - # slice_data, - # ) + +def test_compare_tifffile() -> None: + ds = wk.Dataset(OUTPUT, (1, 1, 1)) + l = ds.add_layer_from_images( + "./webknossos/testdata/tiff/test.02*.tiff", + layer_name="compare_tifffile", + category="segmentation", + topleft=(100, 100, 55), + chunk_shape=(8, 8, 8), + chunks_per_shard=(8, 8, 8), + ) + assert l.bounding_box.topleft == wk.Vec3Int(100, 100, 55) + data = l.get_finest_mag().read()[0, :, :] + for z_index in range(0, data.shape[-1]): + with tifffile.TiffFile("webknossos/testdata/tiff/test.0200.tiff") as tif_file: + comparison_slice = tif_file.asarray().T + assert np.array_equal(data[:, :, z_index], comparison_slice) def open_existing_dataset(): @@ -72,6 +90,7 @@ def open_existing_dataset(): def main() -> None: """Imports a dataset with more than 3 dimensions.""" from_images_import() + # test_compare_tifffile() # open_existing_dataset() diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 1df250da5..3e2243e3c 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -355,7 +355,7 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: shape = bbox.size zarray = self._zarray with _blosc_disable_threading(): - data = zarray[(slice(None),) + bbox.get_slice_tuple()] + data = zarray[(slice(None),) + bbox.to_slices()] shape_with_channels = (self.info.num_channels,) + shape.to_tuple() if data.shape not in (shape, shape_with_channels): @@ -417,7 +417,7 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: with _blosc_disable_threading(): self.ensure_size(bbox) zarray = self._zarray - index_tuple = (slice(None),) + bbox.get_slice_tuple() + index_tuple = (slice(None),) + bbox.to_slices() zarray[index_tuple] = data @@ -603,7 +603,7 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": def read(self, bbox: NDBoundingBox) -> np.ndarray: shape = bbox.size.to_tuple() zarray = self._zarray - slice_tuple = (slice(None),) + bbox.get_slice_tuple() + slice_tuple = (slice(None),) + bbox.to_slices() with _blosc_disable_threading(): data = zarray[slice_tuple] assert data is not None, f"There is no data for given BoundingBox: {bbox}" @@ -656,7 +656,7 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: with _blosc_disable_threading(): self.ensure_size(bbox) zarray = self._zarray - index_tuple = (slice(None),) + bbox.get_slice_tuple() + index_tuple = (slice(None),) + bbox.to_slices() zarray[index_tuple] = data diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index 870a885d5..3e8d013a1 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -70,8 +70,8 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: absolute_bounding_box=chunk.from_mag_to_mag1(self.view.mag) ) - for current_slice in np.moveaxis( - data, self.dimension + 1, 0 + for current_slice in np.rollaxis( + data, chunk.get_3d("index")[2] ): # The '+1' is important because the first dimension is the channel yield current_slice diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index be276a592..5a8f35c0c 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -164,9 +164,6 @@ def _flush_buffer(self) -> None: section_topleft = chunk_bbox.get_3d("topleft") section_bottomright = chunk_bbox.get_3d("bottomright") - slice_tuple = (slice(None),) + tuple( - slice(0, size) for size in chunk_bbox.size - ) z_index = chunk_bbox.get_3d("index")[self.dimension] z = 0 @@ -187,6 +184,13 @@ def _flush_buffer(self) -> None: + self.bbox.get_3d("index")[self.dimension + 1 :], ) + slice_tuple = (slice(None),) + tuple( + slice(0, min(size1, size2)) + for size1, size2 in zip( + chunk_bbox.size, section_chunk.shape[1:] + ) + ) + data[ slice_tuple[:z_index] + (slice(z, z + 1),) @@ -203,15 +207,11 @@ def _flush_buffer(self) -> None: + chunk_topleft[self.dimension + 1 :] ) ) - buffer_start_mag1 = buffer_start * self.view.mag.to_vec3_int() - self.view.write( data, offset=buffer_start.add_or_none(self.offset), json_update_allowed=self.json_update_allowed, - absolute_bounding_box=chunk_bbox # .offset(buffer_start_mag1) - if self.bbox - else None, + absolute_bounding_box=chunk_bbox if self.bbox else None, ) del data diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 6adc002d5..0cc49ba57 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -90,11 +90,11 @@ def __init__( """ During initialization the pims objects are examined and configured to produce ndarrays that follow the following form: - (self._iter_dim, *self._img_dims) - self._iter_dim can be either "z", "t" or "" if the image is 2D. + (self._iter_axis, *self._bundle_axis) + self._iter_axis can be a list of different axis or an empty list if the image is 2D. In the latter case, the inner 2D image is still wrapped in a single-element list by _open_images() to be consistent with 3D images. - self._img_dims can consist of "x", "y" and "c", where "c" is optional and must be + self._bundle_axis can consist of "x", "y" and "c", where "c" is optional and must be at the start or the end, so one of "xy", "yx", "xyc", "yxc", "cxy", "cyx". The part "IDENTIFY AXIS ORDER" figures out (self._iter_dim, *self._img_dims) @@ -111,6 +111,7 @@ def __init__( ## arguments as inner attributes self._channel = channel + self._timepoint = timepoint self._czi_channel = czi_channel self._swap_xy = swap_xy self._flip_x = flip_x @@ -177,7 +178,14 @@ def __init__( self._iter_axes = list( set(images.axes).difference({*self._bundle_axes, "c", "z"}) ) - self._iter_axes.append("z") + if "z" in images.axes: + self._iter_axes.append("z") + + if self._timepoint is not None: + # if a timepoint is given, PimsImages should only generate image slices for that timepoint + if "t" in self._iter_axes: + self._iter_axes.remove("t") + self._default_coords["t"] = self._timepoint if len(self._iter_axes) > 1: iter_size = 1 @@ -244,7 +252,7 @@ def __init__( pims.FramesSequence, images[0] ).shape else: - images_shape = images.shape + images_shape = images.shape # pylint: disable=no-member self.num_channels = images_shape[c_index + 1] @@ -499,12 +507,6 @@ def copy_to_view( source=self._bundle_axes.index("c"), destination=0, ) - # ensure the last two axes are xy: - if ("yx" in self._bundle_axes and not self._swap_xy) or ( - "xy" in self._bundle_axes and self._swap_xy - ): - image_slice = image_slice.swapaxes(-1, -2) - if "c" in self._bundle_axes: if self._channel is not None: image_slice = image_slice[self._channel : self._channel + 1] @@ -527,7 +529,12 @@ def copy_to_view( max_id = max(max_id, image_slice.max()) x_index, y_index, _ = relative_bbox.get_3d("index") - if x_index > y_index: + if ( + x_index > y_index + and self._swap_xy is False + or x_index < y_index + and self._swap_xy is True + ): image_slice = np.moveaxis(image_slice, -1, -2) shapes.append(image_slice.shape[-2:]) writer.send(image_slice) @@ -556,7 +563,7 @@ def expected_bbox(self) -> NDBoundingBox: x_index, y_index = 1, 2 else: x_index, y_index = 2, 1 - if self._swap_xy: + if not self._swap_xy: x_index, y_index = y_index, x_index return BoundingBox( (0, 0, 0), @@ -567,10 +574,17 @@ def expected_bbox(self) -> NDBoundingBox: axes_names = self._iter_axes + [ axis for axis in self._bundle_axes if axis != "c" ] - axes_sizes = [images.sizes[axis] for axis in axes_names] + axes_sizes = [images.sizes[axis] for axis in axes_names] # pylint: disable=no-member axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) + if self._swap_xy: + x_index, y_index = axes_names.index("x"), axes_names.index("y") + axes_sizes[x_index], axes_sizes[y_index] = ( + axes_sizes[y_index], + axes_sizes[x_index], + ) + return NDBoundingBox( topleft, axes_sizes, diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index e19abb0f4..b16d5edda 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1232,7 +1232,7 @@ def add_layer_from_images( ) args = [] - bbox = pims_images.expected_bbox + bbox = layer.bounding_box additional_axes = [ axis_name for axis_name in bbox.axes if axis_name not in ("x", "y", "z") ] @@ -1282,14 +1282,11 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = pims_images.expected_bbox.set_3d( + actual_size = layer.bounding_box.set_3d( "size", - Vec3Int( - dimwise_max(shapes) - + (pims_images.expected_bbox.get_shape("z"),) - ), + Vec3Int(dimwise_max(shapes) + (layer.bounding_box.get_shape("z"),)), ) - layer.bounding_box = pims_images.expected_bbox.with_size(actual_size) + layer.bounding_box = layer.bounding_box.with_size(actual_size) if pims_images.expected_bbox.size != actual_size: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index b7ac66c29..c034a0ae6 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -267,12 +267,14 @@ def get_view( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 + relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 read_only: Optional[bool] = None, ) -> View: # THIS METHOD CAN BE REMOVED WHEN THE DEPRECATED OFFSET IS REMOVED # This has other defaults than the View implementation - # (all deprecations are handled in the subsclass) + # (all deprecations are handled in the superclass) bb = self.bounding_box.in_mag(self._mag) if offset is not None and size is None: offset = Vec3Int(offset) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index cb10f9264..7bd278733 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -22,7 +22,7 @@ from webknossos.geometry.vec_int import VecInt -from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike +from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecIntLike from ..utils import ( get_executor_for_args, get_rich_progress, @@ -134,12 +134,12 @@ def _get_mag1_bbox( self, abs_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, rel_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, - abs_mag1_offset: Optional[Vec3IntLike] = None, - rel_mag1_offset: Optional[Vec3IntLike] = None, - mag1_size: Optional[Vec3IntLike] = None, - abs_current_mag_offset: Optional[Vec3IntLike] = None, - rel_current_mag_offset: Optional[Vec3IntLike] = None, - current_mag_size: Optional[Vec3IntLike] = None, + abs_mag1_offset: Optional[VecIntLike] = None, + rel_mag1_offset: Optional[VecIntLike] = None, + mag1_size: Optional[VecIntLike] = None, + abs_current_mag_offset: Optional[VecIntLike] = None, + rel_current_mag_offset: Optional[VecIntLike] = None, + current_mag_size: Optional[VecIntLike] = None, ) -> Union[NDBoundingBox, BoundingBox]: # num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) # num_offsets = _count_defined_values( @@ -304,7 +304,7 @@ def write( def _prepare_compressed_write( self, - current_mag_bbox: BoundingBox, + current_mag_bbox: NDBoundingBox, data: np.ndarray, json_update_allowed: bool = True, ) -> Iterator[Tuple[BoundingBox, np.ndarray]]: @@ -333,7 +333,7 @@ def _prepare_compressed_write( def _prepare_compressed_write_chunk( self, - current_mag_bbox: BoundingBox, + current_mag_bbox: NDBoundingBox, data: np.ndarray, json_update_allowed: bool = True, ) -> Tuple[BoundingBox, np.ndarray]: diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 19e682dfe..311467b6c 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -362,21 +362,10 @@ def chunk( for z in range( start[2] - start_adjust[2], start[2] + self.size[2], chunk_shape[2] ): - yield BoundingBox([x, y, z], chunk_shape).intersected_with(self) - - def slice_array(self, array: np.ndarray) -> np.ndarray: - return array[ - self.topleft.x : self.bottomright.x, - self.topleft.y : self.bottomright.y, - self.topleft.z : self.bottomright.z, - ] - - def to_slices(self) -> Tuple[slice, slice, slice]: - return np.index_exp[ - self.topleft.x : self.bottomright.x, - self.topleft.y : self.bottomright.y, - self.topleft.z : self.bottomright.z, - ] + yield cast( + BoundingBox, + BoundingBox([x, y, z], chunk_shape).intersected_with(self), + ) def offset(self, vector: Vec3IntLike) -> "BoundingBox": return attr.evolve(self, topleft=self.topleft + Vec3Int(vector)) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 13743b4b8..83f961633 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -245,12 +245,6 @@ def get_shape(self, axis_name: str) -> int: f"Axis {axis_name} doesn't exist in NDBoundingBox." ) from err - def get_slice_tuple(self) -> Tuple[slice, ...]: - return tuple( - slice(topleft, topleft + size) - for topleft, size in zip(self.topleft, self.size) - ) - def get_3d(self, attr_name: str) -> Vec3Int: axes = ("x", "y", "z") attr_3d = [] @@ -471,26 +465,26 @@ def chunk( for i in range(len(self.axes)) ] ): - yield NDBoundingBox( - topleft=coordinates, size=chunk_shape, axes=self.axes, index=self.index + yield self.intersected_with( + NDBoundingBox( + topleft=coordinates, + size=chunk_shape, + axes=self.axes, + index=self.index, + ) ) def volume(self) -> int: return self.size.prod() def slice_array(self, array: np.ndarray) -> np.ndarray: - return array[ - self.get_bounds("x")[0] : self.get_bounds("x")[1], - self.get_bounds("y")[0] : self.get_bounds("y")[1], - self.get_bounds("z")[0] : self.get_bounds("z")[1], - ] - - def to_slices(self) -> Tuple[slice, slice, slice]: - return np.index_exp[ - self.get_bounds("x")[0] : self.get_bounds("x")[1], - self.get_bounds("y")[0] : self.get_bounds("y")[1], - self.get_bounds("z")[0] : self.get_bounds("z")[1], - ] + return array[self.to_slices()] + + def to_slices(self) -> Tuple[slice, ...]: + return tuple( + slice(topleft, topleft + size) + for topleft, size in zip(self.topleft, self.size) + ) def offset(self, vector: VecIntLike) -> "NDBoundingBox": vec_int = VecInt(vector) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 5e5a3a883..5293c2bbc 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -12,8 +12,10 @@ class Vec3Int(VecInt): def __new__( cls, vec: Union[int, "Vec3IntLike"], + *args: int, y: Optional[int] = None, z: Optional[int] = None, + **kwargs: int, ) -> "Vec3Int": """ Class to represent a 3D vector. Inherits from tuple and provides useful @@ -35,24 +37,10 @@ def __new__( if isinstance(vec, Vec3Int): return vec - as_tuple: Optional[Tuple[int, int, int]] = None - - if isinstance(vec, int): - assert y is not None and z is not None, VALUE_ERROR - assert isinstance(y, int) and isinstance(z, int), VALUE_ERROR - as_tuple = vec, y, z - else: - assert y is None and z is None, VALUE_ERROR - if isinstance(vec, np.ndarray): - assert np.count_nonzero(vec % 1) == 0, VALUE_ERROR - assert vec.shape == ( - 3, - ), "Numpy array for Vec3Int must have shape (3,)." - if isinstance(vec, Iterable): - as_tuple = cast(Tuple[int, int, int], tuple(int(item) for item in vec)) + as_tuple = super().__new__(cls, vec, *args, y=y, z=z, **kwargs) assert as_tuple is not None and len(as_tuple) == 3, VALUE_ERROR - return cast(cls, super().__new__(cls, as_tuple)) + return cast(cls, as_tuple) @property def x(self) -> int: diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index 2b524e4fb..3962e9692 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -144,10 +144,12 @@ def pairmin(self, other: Union[int, "VecIntLike"]) -> "VecInt": return self._element_wise(other, min) def prod(self) -> int: - return int(np.prod(self)) + return int(np.prod(self.to_np())) def __repr__(self) -> str: - return f"{self.__class__.__name__}({', '.join((str(element) for element in self))})" + return ( + f"{self.__class__.__name__}({','.join((str(element) for element in self))})" + ) def add_or_none(self, other: Optional["VecInt"]) -> Optional["VecInt"]: return None if other is None else self + other From 0d8a4f770c408c20ea199771452fa0463a145b6c Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 15 Feb 2024 07:48:41 +0100 Subject: [PATCH 23/41] Fixing issues with alignment, writing with offsets and different mags. --- .../script_collection/reading_nd_data.py | 11 +++-- webknossos/webknossos/dataset/_array.py | 22 ++++++--- .../dataset/_utils/buffered_slice_writer.py | 48 ++++++++++--------- .../webknossos/dataset/_utils/pims_images.py | 17 +++---- webknossos/webknossos/dataset/dataset.py | 31 ++++++++---- webknossos/webknossos/dataset/properties.py | 2 +- webknossos/webknossos/dataset/view.py | 4 +- .../webknossos/geometry/nd_bounding_box.py | 20 ++++++-- webknossos/webknossos/geometry/vec3_int.py | 4 +- 9 files changed, 98 insertions(+), 61 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 17dc4c2cd..391461732 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -10,7 +10,7 @@ from webknossos.geometry.nd_bounding_box import NDBoundingBox TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" -OUTPUT = Path(".") / "testdata" +OUTPUT = Path(".") / "testdata" / "4D_series" def from_images_import(): @@ -22,20 +22,21 @@ def from_images_import(): OUTPUT, voxel_size=(10, 10, 10), data_format="zarr3", + compress=True, use_bioformats=True, ) layer = dataset.get_color_layers()[0] mag_view = layer.get_finest_mag() - data = mag_view.read()[0, 0, 0, :, :] # absolute_bounding_box=read_bbox) + # data = mag_view.read()[0, 0, 0, :, :] # absolute_bounding_box=read_bbox) # assert data.shape == (1,)+read_bbox.size - imwrite("l4_sample_tiff/test.tiff", data) + # imwrite("l4_sample_tiff/test.tiff", data) for bbox in layer.bounding_box.chunk((439, 167, 5)): with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: - for slice_data in reader: + for i, slice_data in enumerate(reader): imwrite( - f"l4_sample_tiff/tiff_from_bbox{bbox}.tiff", + f"l4_sample_tiff/tiff_{i}_from_bbox{bbox}.tiff", slice_data, ) diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 3e2243e3c..f75b46455 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -606,12 +606,14 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: slice_tuple = (slice(None),) + bbox.to_slices() with _blosc_disable_threading(): data = zarray[slice_tuple] - assert data is not None, f"There is no data for given BoundingBox: {bbox}" shape_with_channels = (self.info.num_channels,) + shape - if data.shape not in (shape, shape_with_channels): - padded_data = np.zeros(shape_with_channels, dtype=data.dtype) - padded_data[slice_tuple] = data + if data.shape != shape_with_channels: + data_slice_tuple = tuple(slice(0, size) for size in data.shape) + padded_data = np.zeros(shape_with_channels, dtype=zarray.metadata.dtype) + padded_data[ + data_slice_tuple + ] = data # TODO: Fix this easy to fix bug, the solution is really obvious data = padded_data return data @@ -621,7 +623,7 @@ def ensure_size( align_with_shards: bool = True, warn: bool = False, ) -> None: - new_shape = new_bbox.size + new_shape = new_bbox.bottomright zarray = self._zarray new_shape_tuple = (zarray.metadata.shape[0],) + tuple( @@ -632,10 +634,10 @@ def ensure_size( if align_with_shards: shard_shape = self.info.shard_shape new_shape = Vec3Int( - new_bbox.get_3d("size").ceildiv(shard_shape) * shard_shape + new_bbox.get_3d("bottomright").ceildiv(shard_shape) * shard_shape ) new_shape_tuple = (zarray.metadata.shape[0],) + new_bbox.set_3d( - "size", new_shape + "bottomright", new_shape ).to_tuple() # Check on-disk for changes to shape @@ -653,6 +655,12 @@ def ensure_size( self._cached_zarray = zarray.resize(new_shape_tuple) def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: + if data.ndim == len(bbox): + # the bbox does not include the channels, if data and bbox have the same size there is only 1 channel + data = data.reshape((1,) + data.shape) + + assert data.ndim == len(bbox) + 1 + with _blosc_disable_threading(): self.ensure_size(bbox) zarray = self._zarray diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 5a8f35c0c..a8065f631 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -45,8 +45,12 @@ def __init__( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, - absolute_bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] = None, + relative_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 + absolute_bounding_box: Optional[ + Union[NDBoundingBox, BoundingBox] + ] = None, # in mag1 use_logging: bool = False, ) -> None: """see `View.get_buffered_slice_writer()`""" @@ -142,10 +146,14 @@ def _flush_buffer(self) -> None: max_height = max(section.shape[-1] for section in self.slices_to_write) channel_count = self.slices_to_write[0].shape[0] buffer_depth = min(self.buffer_size, len(self.slices_to_write)) - self.bbox = self.bbox.with_size( - self.bbox.set_3d("size", (max_width, max_height, buffer_depth)) + buffer_start = Vec3Int.zeros().with_replaced( + self.dimension, self.buffer_start_slice ) + bbox = self.bbox.with_size( + self.bbox.set_3d("size", (max_width, max_height, buffer_depth)) + ).offset(buffer_start) + shard_dimensions = self.view._get_file_dimensions().moveaxis( -1, self.dimension ) @@ -154,15 +162,19 @@ def _flush_buffer(self) -> None: min(shard_dimensions[1], max_height), buffer_depth, ) - for chunk_bbox in self.bbox.chunk(chunk_size): + for chunk_bbox in bbox.chunk(chunk_size): info(f"Writing chunk {chunk_bbox}.") data = np.zeros( (channel_count, *chunk_bbox.size), dtype=self.slices_to_write[0].dtype, ) - section_topleft = chunk_bbox.get_3d("topleft") - section_bottomright = chunk_bbox.get_3d("bottomright") + section_topleft = Vec3Int( + chunk_bbox.get_3d("topleft") - bbox.get_3d("topleft") + ) + section_bottomright = Vec3Int( + chunk_bbox.get_3d("bottomright") - bbox.get_3d("topleft") + ) z_index = chunk_bbox.get_3d("index")[self.dimension] @@ -170,18 +182,18 @@ def _flush_buffer(self) -> None: for section in self.slices_to_write: section_chunk = section[ :, - section_topleft[0] : section_bottomright[0], - section_topleft[1] : section_bottomright[1], + section_topleft.x : section_bottomright.x, + section_topleft.y : section_bottomright.y, ] section_chunk = section_chunk[ (slice(None), slice(None), slice(None)) - + tuple(np.newaxis for _ in range(len(self.bbox) - 2)) + + tuple(np.newaxis for _ in range(len(bbox) - 2)) ] section_chunk = np.moveaxis( section_chunk, [1, 2], - self.bbox.get_3d("index")[: self.dimension] - + self.bbox.get_3d("index")[self.dimension + 1 :], + bbox.get_3d("index")[: self.dimension] + + bbox.get_3d("index")[self.dimension + 1 :], ) slice_tuple = (slice(None),) + tuple( @@ -199,19 +211,11 @@ def _flush_buffer(self) -> None: z += 1 - chunk_topleft = chunk_bbox.get_3d("topleft") - buffer_start = Vec3Int( - *( - chunk_topleft[: self.dimension] - + (self.buffer_start_slice,) - + chunk_topleft[self.dimension + 1 :] - ) - ) self.view.write( data, - offset=buffer_start.add_or_none(self.offset), + offset=chunk_bbox.get_3d("topleft").add_or_none(self.offset), json_update_allowed=self.json_update_allowed, - absolute_bounding_box=chunk_bbox if self.bbox else None, + absolute_bounding_box=chunk_bbox.from_mag_to_mag1(self.view._mag), ) del data diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 0cc49ba57..3432670ac 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -464,9 +464,11 @@ def copy_to_view( method a manual update of the bounding box and the largest segment id might be necessary. """ relative_bbox = args + assert relative_bbox.set_3d("size", (1, 1, 1)) == VecInt.ones( len(relative_bbox) ), "The delivered BoundingBox has to be flat except for x,y and z dimension." + z_start, z_end = relative_bbox.get_bounds("z") shapes = [] max_id: Optional[int] @@ -492,7 +494,6 @@ def copy_to_view( # Previously only z_start and its end were important, now the slice writer needs to know # which axis is currently written. relative_bounding_box=relative_bbox, - # relative_offset=(0, 0, z_start * mag_view.mag.z), buffer_size=mag_view.info.chunk_shape.z, # copy_to_view is typically used in a multiprocessing-context. Therefore the # buffered slice writer should not update the json file to avoid race conditions. @@ -529,13 +530,11 @@ def copy_to_view( max_id = max(max_id, image_slice.max()) x_index, y_index, _ = relative_bbox.get_3d("index") - if ( - x_index > y_index - and self._swap_xy is False - or x_index < y_index - and self._swap_xy is True + if (x_index < y_index and self._swap_xy is False) or ( + x_index > y_index and self._swap_xy is True ): image_slice = np.moveaxis(image_slice, -1, -2) + shapes.append(image_slice.shape[-2:]) writer.send(image_slice) @@ -563,7 +562,7 @@ def expected_bbox(self) -> NDBoundingBox: x_index, y_index = 1, 2 else: x_index, y_index = 2, 1 - if not self._swap_xy: + if self._swap_xy: x_index, y_index = y_index, x_index return BoundingBox( (0, 0, 0), @@ -574,7 +573,9 @@ def expected_bbox(self) -> NDBoundingBox: axes_names = self._iter_axes + [ axis for axis in self._bundle_axes if axis != "c" ] - axes_sizes = [images.sizes[axis] for axis in axes_names] # pylint: disable=no-member + axes_sizes = [ + images.sizes[axis] for axis in axes_names + ] # pylint: disable=no-member axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 2711612a2..d8a89ed94 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1186,9 +1186,12 @@ def add_layer_from_images( num_channels=pims_images.num_channels, **add_layer_kwargs, # type: ignore[arg-type] ) + + expected_bbox = pims_images.expected_bbox + # When the expected bbox is 2D the chunk_shape is set to 2D too. if ( - pims_images.expected_bbox.get_shape("z") == 1 + expected_bbox.get_shape("z") == 1 and layer.data_format == DataFormat.Zarr ): if chunk_shape is None: @@ -1200,9 +1203,7 @@ def add_layer_from_images( chunks_per_shard = DEFAULT_CHUNKS_PER_SHARD_FROM_IMAGES mag = Mag(mag) - layer.bounding_box = pims_images.expected_bbox.from_mag_to_mag1(mag).offset( - topleft - ) + layer.bounding_box = expected_bbox.from_mag_to_mag1(mag).offset(topleft) mag_view = layer.add_mag( mag=mag, chunk_shape=chunk_shape, @@ -1239,9 +1240,20 @@ def add_layer_from_images( additional_axes_shapes = product( *[range(bbox.get_shape(axis_name)) for axis_name in additional_axes] ) + if additional_axes and data_format != DataFormat.Zarr3: + assert all( + shape == 1 for shape in additional_axes_shapes + ), "The data stores additional axes with shape bigger than 1. These are only supported by data format Zarr3." + + # Convert NDBoundingBox to 3D BoundingBox + bbox = BoundingBox(bbox.get_3d("topleft"), bbox.get_3d("size")) + expected_bbox = bbox + additional_axes = [] + z_shape = bbox.get_shape("z") + bbox = bbox.offset(-bbox.topleft) for z_start in range(0, z_shape, batch_size): - z_size = min(batch_size, z_shape) + z_size = min(batch_size, z_shape - z_start) z_bbox = bbox.with_bounds("z", z_start, z_size) if not additional_axes: args.append(z_bbox) @@ -1282,15 +1294,16 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = layer.bounding_box.set_3d( + actual_size = bbox.set_3d( "size", - Vec3Int(dimwise_max(shapes) + (layer.bounding_box.get_shape("z"),)), + Vec3Int(dimwise_max(shapes) + (layer.bounding_box.get_shape("z"),)) + * mag.to_vec3_int().with_z(1), ) layer.bounding_box = layer.bounding_box.with_size(actual_size) - if pims_images.expected_bbox.size != actual_size: + if expected_bbox.size != actual_size: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " - + f"New size is {actual_size}, expected {pims_images.expected_bbox.size}." + + f"New size is {actual_size}, expected {expected_bbox.size}." ) if first_layer is None: first_layer = layer diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index aa38d50bd..1186fe350 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -300,7 +300,7 @@ def __layer_properties_pre_structure( del d["wkwResolutions"] # bounding_box and additional_axes are internally handled as nd_bounding_box if "additionalAxes" in d: - d["boundingBox"]["additionalAxes"] = d["additionalAxes"] + d["boundingBox"]["additionalAxes"] = copy.deepcopy(d["additionalAxes"]) del d["additionalAxes"] if len(d["mags"]) > 0: first_mag = d["mags"][0] diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 7bd278733..aae864ea0 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -307,7 +307,7 @@ def _prepare_compressed_write( current_mag_bbox: NDBoundingBox, data: np.ndarray, json_update_allowed: bool = True, - ) -> Iterator[Tuple[BoundingBox, np.ndarray]]: + ) -> Iterator[Tuple[NDBoundingBox, np.ndarray]]: """This method takes an arbitrary sized chunk of data with an accompanying bbox, divides these into chunks of shard_shape size and delegates the preparation to _prepare_compressed_write_chunk.""" @@ -336,7 +336,7 @@ def _prepare_compressed_write_chunk( current_mag_bbox: NDBoundingBox, data: np.ndarray, json_update_allowed: bool = True, - ) -> Tuple[BoundingBox, np.ndarray]: + ) -> Tuple[NDBoundingBox, np.ndarray]: """This method takes an arbitrary sized chunk of data with an accompanying bbox (ideally not larger than a shard) and enlarges that chunk to fit the shard it resides in (by reading the entire shard data and writing the passed data ndarray diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 83f961633..ebdaeee4f 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -446,17 +446,27 @@ def chunk( except AssertionError: chunk_shape = VecInt(chunk_shape).to_np() - start_adjust = VecInt.zeros(len(self.topleft)).to_np() + start_adjust = VecInt.zeros(len(self)).to_np() if chunk_border_alignments is not None: - chunk_border_alignments_array = Vec3Int(chunk_border_alignments).to_np() + try: + chunk_border_alignments = Vec3Int(chunk_border_alignments) + + chunk_border_alignments = ( + self.with_size(VecInt.ones(len(self))) + .set_3d("size", chunk_border_alignments) + .to_np() + ) + except AssertionError: + chunk_border_alignments = VecInt(chunk_border_alignments).to_np() + assert np.all( - chunk_shape % chunk_border_alignments_array == 0 - ), f"{chunk_shape} not divisible by {chunk_border_alignments_array}" + chunk_shape % chunk_border_alignments == 0 + ), f"{chunk_shape} not divisible by {chunk_border_alignments}" # Move the start to be aligned correctly. This doesn't actually change # the start of the first chunk, because we'll intersect with `self`, # but it'll lead to all chunk borders being aligned correctly. - start_adjust = start % chunk_border_alignments_array + start_adjust = start % chunk_border_alignments for coordinates in product( *[ range( diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 5293c2bbc..7a0a5e856 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -1,5 +1,5 @@ import re -from typing import Iterable, Optional, Tuple, Union, cast +from typing import Iterable, Optional, Tuple, Type, Union, cast import numpy as np @@ -40,7 +40,7 @@ def __new__( as_tuple = super().__new__(cls, vec, *args, y=y, z=z, **kwargs) assert as_tuple is not None and len(as_tuple) == 3, VALUE_ERROR - return cast(cls, as_tuple) + return cast(Vec3Int, as_tuple) @property def x(self) -> int: From 9fc0253062bbb8cb5e79cf9f4a03cb07d66e4a1b Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 15 Feb 2024 15:57:35 +0100 Subject: [PATCH 24/41] Fix reading without parameters for nd datasets and addint test. --- .../script_collection/reading_nd_data.py | 38 +------------------ .../dataset/test_add_layer_from_images.py | 20 ++++++++++ webknossos/webknossos/dataset/_array.py | 4 +- .../webknossos/dataset/_utils/pims_images.py | 10 ++--- webknossos/webknossos/dataset/dataset.py | 2 +- webknossos/webknossos/dataset/view.py | 34 +++-------------- webknossos/webknossos/geometry/vec3_int.py | 2 +- 7 files changed, 34 insertions(+), 76 deletions(-) diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py index 391461732..f4cd32739 100644 --- a/webknossos/script_collection/reading_nd_data.py +++ b/webknossos/script_collection/reading_nd_data.py @@ -1,22 +1,15 @@ from pathlib import Path -import numpy as np -import tifffile - -# import pims from tifffile import imwrite import webknossos as wk from webknossos.geometry.nd_bounding_box import NDBoundingBox TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" -OUTPUT = Path(".") / "testdata" / "4D_series" +OUTPUT = Path(".") / "testoutput" / "4D_series" def from_images_import(): - # reader = pims.Bioformats(str(TIF_PATH)) - # print(reader.sizes) - # print(isinstance(reader, pims.FramesSequenceND)) dataset = wk.Dataset.from_images( TIF_PATH, OUTPUT, @@ -27,10 +20,7 @@ def from_images_import(): ) layer = dataset.get_color_layers()[0] mag_view = layer.get_finest_mag() - # data = mag_view.read()[0, 0, 0, :, :] # absolute_bounding_box=read_bbox) - # assert data.shape == (1,)+read_bbox.size - - # imwrite("l4_sample_tiff/test.tiff", data) + # data = mag_view.read()[0, 0, 0, :, :] for bbox in layer.bounding_box.chunk((439, 167, 5)): with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: @@ -41,24 +31,6 @@ def from_images_import(): ) -def test_compare_tifffile() -> None: - ds = wk.Dataset(OUTPUT, (1, 1, 1)) - l = ds.add_layer_from_images( - "./webknossos/testdata/tiff/test.02*.tiff", - layer_name="compare_tifffile", - category="segmentation", - topleft=(100, 100, 55), - chunk_shape=(8, 8, 8), - chunks_per_shard=(8, 8, 8), - ) - assert l.bounding_box.topleft == wk.Vec3Int(100, 100, 55) - data = l.get_finest_mag().read()[0, :, :] - for z_index in range(0, data.shape[-1]): - with tifffile.TiffFile("webknossos/testdata/tiff/test.0200.tiff") as tif_file: - comparison_slice = tif_file.asarray().T - assert np.array_equal(data[:, :, z_index], comparison_slice) - - def open_existing_dataset(): ds = wk.Dataset.open(OUTPUT) layer = ds.get_color_layers()[0] @@ -81,17 +53,11 @@ def open_existing_dataset(): ) imwrite("l4_sample_tiff/test.tiff", data) - # color_layer = ds.get_color_layers()[0] - # finest_mag = color_layer.get_finest_mag() - # layers = ds.layers - # finest_mag.read() - ds.copy_dataset("../copied_dataset") def main() -> None: """Imports a dataset with more than 3 dimensions.""" from_images_import() - # test_compare_tifffile() # open_existing_dataset() diff --git a/webknossos/tests/dataset/test_add_layer_from_images.py b/webknossos/tests/dataset/test_add_layer_from_images.py index 115ca466b..b2a389672 100644 --- a/webknossos/tests/dataset/test_add_layer_from_images.py +++ b/webknossos/tests/dataset/test_add_layer_from_images.py @@ -43,6 +43,26 @@ def test_compare_tifffile(tmp_path: Path) -> None: assert np.array_equal(data[:, :, z_index], comparison_slice) +def test_compare_nd_tifffile(tmp_path: Path) -> None: + ds = wk.Dataset(tmp_path, (1, 1, 1)) + l = ds.add_layer_from_images( + "testdata/4D/4D_series/4D-series.ome.tif", + layer_name="color", + category="color", + topleft=(100, 100, 55), + use_bioformats=True, + data_format="zarr3", + chunk_shape=(8, 8, 8), + chunks_per_shard=(8, 8, 8), + ) + assert l.bounding_box.topleft == wk.VecInt(0, 55, 100, 100) + assert l.bounding_box.size == wk.VecInt(7, 5, 167, 439) + assert np.array_equal( + l.get_finest_mag().read()[0], + TiffFile("testdata/4D/4D_series/4D-series.ome.tif").asarray(), + ) + + REPO_IMAGES_ARGS: List[ Tuple[Union[str, List[Path]], Dict[str, Any], str, int, Tuple[int, int, int]] ] = [ diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index f75b46455..d1820b92a 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -611,9 +611,7 @@ def read(self, bbox: NDBoundingBox) -> np.ndarray: if data.shape != shape_with_channels: data_slice_tuple = tuple(slice(0, size) for size in data.shape) padded_data = np.zeros(shape_with_channels, dtype=zarray.metadata.dtype) - padded_data[ - data_slice_tuple - ] = data # TODO: Fix this easy to fix bug, the solution is really obvious + padded_data[data_slice_tuple] = data data = padded_data return data diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 3432670ac..165360d43 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -529,10 +529,7 @@ def copy_to_view( if max_id is not None: max_id = max(max_id, image_slice.max()) - x_index, y_index, _ = relative_bbox.get_3d("index") - if (x_index < y_index and self._swap_xy is False) or ( - x_index > y_index and self._swap_xy is True - ): + if self._swap_xy is False: image_slice = np.moveaxis(image_slice, -1, -2) shapes.append(image_slice.shape[-2:]) @@ -574,8 +571,9 @@ def expected_bbox(self) -> NDBoundingBox: axis for axis in self._bundle_axes if axis != "c" ] axes_sizes = [ - images.sizes[axis] for axis in axes_names - ] # pylint: disable=no-member + images.sizes[axis] + for axis in axes_names # pylint: disable=no-member + ] axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index d8a89ed94..fec2cb194 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1240,7 +1240,7 @@ def add_layer_from_images( additional_axes_shapes = product( *[range(bbox.get_shape(axis_name)) for axis_name in additional_axes] ) - if additional_axes and data_format != DataFormat.Zarr3: + if additional_axes and layer.data_format != DataFormat.Zarr3: assert all( shape == 1 for shape in additional_axes_shapes ), "The data stores additional axes with shape bigger than 1. These are only supported by data format Zarr3." diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index aae864ea0..7fb8e9ef3 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -140,33 +140,7 @@ def _get_mag1_bbox( abs_current_mag_offset: Optional[VecIntLike] = None, rel_current_mag_offset: Optional[VecIntLike] = None, current_mag_size: Optional[VecIntLike] = None, - ) -> Union[NDBoundingBox, BoundingBox]: - # num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) - # num_offsets = _count_defined_values( - # [ - # abs_mag1_offset, - # rel_mag1_offset, - # abs_current_mag_offset, - # rel_current_mag_offset, - # ] - # ) - # num_sizes = _count_defined_values([mag1_size, current_mag_size]) - # if num_bboxes == 0: - # assert num_offsets != 0, "You must supply an offset or a bounding box." - # assert ( - # num_sizes != 0 - # ), "When supplying an offset, you must also supply a size. Alternatively, supply a bounding box." - # assert num_offsets == 1, "Only one offset can be supplied." - # assert num_sizes == 1, "Only one size can be supplied." - # else: - # assert num_bboxes == 1, "Only one bounding-box can be supplied." - # assert ( - # num_offsets == 0 - # ), "A bounding-box was supplied, you cannot also supply an offset." - # assert ( - # num_sizes == 0 - # ), "A bounding-box was supplied, you cannot also supply a size." - + ) -> NDBoundingBox: if abs_mag1_bbox is not None: return abs_mag1_bbox @@ -189,7 +163,9 @@ def _get_mag1_bbox( assert abs_mag1_offset is not None, "No offset was supplied." assert mag1_size is not None, "No size was supplied." - return BoundingBox(Vec3Int(abs_mag1_offset), Vec3Int(mag1_size)) + + bbox = self.bounding_box.offset(-self.bounding_box.topleft) + return bbox.offset(abs_mag1_offset).with_size(mag1_size) def write( self, @@ -471,7 +447,7 @@ def read( mag1_size = None if all(i is None for i in [offset, absolute_offset, relative_offset]): - relative_offset = Vec3Int.zeros() + relative_offset = VecInt.zeros(len(self.bounding_box)) else: assert ( size is None diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 7a0a5e856..15320bfee 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -1,5 +1,5 @@ import re -from typing import Iterable, Optional, Tuple, Type, Union, cast +from typing import Iterable, Optional, Tuple, Union, cast import numpy as np From 48f9586fc67a45103e25f8bc0ff34a84ab74378f Mon Sep 17 00:00:00 2001 From: markbader Date: Fri, 16 Feb 2024 01:09:25 +0100 Subject: [PATCH 25/41] Fix issue with empty additionalAxes in json and some minor issues. --- webknossos/webknossos/cli/convert_knossos.py | 6 ++--- .../webknossos/cli/export_wkw_as_tiff.py | 24 ++++++++++++------- webknossos/webknossos/dataset/_array.py | 5 ++-- .../dataset/_utils/buffered_slice_writer.py | 11 ++++----- .../infer_bounding_box_existing_files.py | 4 ++-- .../webknossos/dataset/_utils/pims_images.py | 4 ++-- webknossos/webknossos/dataset/dataset.py | 2 +- .../webknossos/geometry/bounding_box.py | 20 ---------------- .../webknossos/geometry/nd_bounding_box.py | 10 ++++++-- webknossos/webknossos/geometry/vec3_int.py | 3 +++ 10 files changed, 42 insertions(+), 47 deletions(-) diff --git a/webknossos/webknossos/cli/convert_knossos.py b/webknossos/webknossos/cli/convert_knossos.py index 51184c342..6e8d63437 100644 --- a/webknossos/webknossos/cli/convert_knossos.py +++ b/webknossos/webknossos/cli/convert_knossos.py @@ -151,15 +151,15 @@ def convert_cube_job( time_start(f"Converting of {target_view.bounding_box}") cube_size = cast(Tuple[int, int, int], (KNOSSOS_CUBE_EDGE_LEN,) * 3) - offset = target_view.bounding_box.in_mag(target_view.mag).topleft - size = target_view.bounding_box.in_mag(target_view.mag).size + offset = target_view.bounding_box.in_mag(target_view.mag).get_3d("topleft") + size = target_view.bounding_box.in_mag(target_view.mag).get_3d("size") buffer = np.zeros(size.to_tuple(), dtype=target_view.get_dtype()) with open_knossos(source_knossos_info) as source_knossos: for x in range(0, size.x, KNOSSOS_CUBE_EDGE_LEN): for y in range(0, size.y, KNOSSOS_CUBE_EDGE_LEN): for z in range(0, size.z, KNOSSOS_CUBE_EDGE_LEN): cube_data = source_knossos.read( - (offset + Vec3Int(x, y, z)).to_tuple(), cube_size + Vec3Int(offset + (x, y, z)).to_tuple(), cube_size ) buffer[ x : (x + KNOSSOS_CUBE_EDGE_LEN), diff --git a/webknossos/webknossos/cli/export_wkw_as_tiff.py b/webknossos/webknossos/cli/export_wkw_as_tiff.py index f52ace872..1d3412454 100644 --- a/webknossos/webknossos/cli/export_wkw_as_tiff.py +++ b/webknossos/webknossos/cli/export_wkw_as_tiff.py @@ -74,9 +74,9 @@ def export_tiff_slice( tiff_data = view.read() else: padded_tiff_bbox_size = Vec3Int( - tiling_size[0] * ceil(tiff_bbox.size.x / tiling_size[0]), - tiling_size[1] * ceil(tiff_bbox.size.y / tiling_size[1]), - tiff_bbox.size.z, + tiling_size[0] * ceil(tiff_bbox.get_3d("size").x / tiling_size[0]), + tiling_size[1] * ceil(tiff_bbox.get_3d("size").y / tiling_size[1]), + tiff_bbox.get_3d("size").z, ) tiff_data = view.read() padded_tiff_data = np.zeros( @@ -87,9 +87,9 @@ def export_tiff_slice( :, 0 : tiff_data.shape[1], 0 : tiff_data.shape[2], 0 : tiff_data.shape[3] ] = tiff_data tiff_data = padded_tiff_data - for slice_index in range(tiff_bbox.size.z): + for slice_index in range(tiff_bbox.get_3d("size").z): slice_name_number = ( - tiff_bbox_mag1.topleft.z + slice_index + 1 - start_slice_index + tiff_bbox_mag1.get_3d("topleft").z + slice_index + 1 - start_slice_index ) if tiling_size is None: tiff_file_name = _make_tiff_name(name, slice_name_number) @@ -100,12 +100,16 @@ def export_tiff_slice( logging.debug("Saved slice %s", slice_name_number) else: - for y_tile_index in range(ceil(tiff_bbox.size.y / tiling_size[1])): + for y_tile_index in range( + ceil(tiff_bbox.get_3d("size").y / tiling_size[1]) + ): tile_tiff_path = ( dest_path / str(slice_name_number) / str(y_tile_index + 1) ) tile_tiff_path.mkdir(parents=True, exist_ok=True) - for x_tile_index in range(ceil(tiff_bbox.size.x / tiling_size[0])): + for x_tile_index in range( + ceil(tiff_bbox.get_3d("size").x / tiling_size[0]) + ): tile_tiff_filename = f"{x_tile_index + 1}.tiff" tile_image = _slice_to_image( tiff_data[ @@ -264,7 +268,11 @@ def main( mag_view = Dataset.open(source).get_layer(layer_name).get_mag(mag) - bbox = mag_view.bounding_box if bbox is None else bbox + bbox = ( + BoundingBox(mag_view.bounding_box.topleft, mag_view.bounding_box.size) + if bbox is None + else bbox + ) logging.info("Starting tiff export for bounding box: %s", bbox) executor_args = Namespace( diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index d1820b92a..0ed063e48 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -519,8 +519,9 @@ def info(self) -> ArrayInfo: sharding_codec.codec_pipeline.codecs ), chunk_shape=Vec3Int(chunk_shape[1:4]), - chunks_per_shard=Vec3Int(shard_shape[1:4]) - // Vec3Int(chunk_shape[1:4]), + chunks_per_shard=Vec3Int( + Vec3Int(shard_shape[1:4]) // Vec3Int(chunk_shape[1:4]) + ), dimension_names=dimension_names, ) return ArrayInfo( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index a8065f631..c18939e8d 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -4,7 +4,7 @@ from logging import error, info from os import getpid from types import TracebackType -from typing import TYPE_CHECKING, Generator, List, Optional, Type, Union +from typing import TYPE_CHECKING, Generator, List, Optional, Type import numpy as np import psutil @@ -45,12 +45,8 @@ def __init__( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 use_logging: bool = False, ) -> None: """see `View.get_buffered_slice_writer()`""" @@ -60,6 +56,7 @@ def __init__( self.dtype = self.view.get_dtype() self.use_logging = use_logging self.json_update_allowed = json_update_allowed + self.bbox: NDBoundingBox if ( offset is None diff --git a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py index 177042e01..9ca3145e8 100644 --- a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py +++ b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py @@ -1,10 +1,10 @@ from functools import reduce -from ...geometry import BoundingBox +from ...geometry import BoundingBox, NDBoundingBox from ..mag_view import MagView -def infer_bounding_box_existing_files(mag_view: MagView) -> BoundingBox: +def infer_bounding_box_existing_files(mag_view: MagView) -> NDBoundingBox: """Since volume annotation layers are only a single layer, they do not contain a datasource-properties.json. Therefore, the bounding box needs to be inferred when working with those. The returned bounding box is measured in Mag(1) voxels.""" diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index 165360d43..a429c304d 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -571,8 +571,8 @@ def expected_bbox(self) -> NDBoundingBox: axis for axis in self._bundle_axes if axis != "c" ] axes_sizes = [ - images.sizes[axis] - for axis in axes_names # pylint: disable=no-member + images.sizes[axis] # pylint: disable=no-member + for axis in axes_names ] axes_index = list(range(1, len(axes_names) + 1)) topleft = VecInt.zeros(len(axes_names)) diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index fec2cb194..01a4717d7 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1513,7 +1513,7 @@ def add_fs_copy_layer( self._export_as_json() return self.layers[new_layer_name] - def calculate_bounding_box(self) -> BoundingBox: + def calculate_bounding_box(self) -> NDBoundingBox: """ Calculates and returns the enclosing bounding box of all data layers of the dataset. """ diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 311467b6c..3fe41936f 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -1,6 +1,5 @@ import json import re -from collections import defaultdict from typing import Dict, Generator, Iterable, List, Optional, Tuple, Union, cast import attr @@ -157,25 +156,6 @@ def from_auto( raise Exception("Unknown bounding box format.") - @classmethod - def group_boxes_with_aligned_mag( - cls, bounding_boxes: Iterable["BoundingBox"], aligning_mag: Mag - ) -> Dict["BoundingBox", List["BoundingBox"]]: - """ - Groups the given BoundingBox instances by aligning each - bbox to the given mag and using that as the key. - For example, bounding boxes of size 256**3 could be grouped - into the corresponding 1024**3 chunks to which they belong - by using aligning_mag = Mag(1024). - """ - - chunks_with_bboxes = defaultdict(list) - for bbox in bounding_boxes: - chunk_key = bbox.align_with_mag(aligning_mag, ceil=True) - chunks_with_bboxes[chunk_key].append(bbox) - - return chunks_with_bboxes - @classmethod def empty( cls, diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index ebdaeee4f..7b1ca9578 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -201,13 +201,19 @@ def to_wkw_dict(self) -> dict: "index": self.index[i], } ) - + if additional_axes: + return { + "topLeft": topleft, + "width": width, + "height": height, + "depth": depth, + "additionalAxes": additional_axes, + } return { "topLeft": topleft, "width": width, "height": height, "depth": depth, - "additionalAxes": additional_axes, } def to_config_dict(self) -> dict: diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 15320bfee..c01171b73 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -63,6 +63,9 @@ def with_y(self, new_y: int) -> "Vec3Int": def with_z(self, new_z: int) -> "Vec3Int": return Vec3Int.from_xyz(self.x, self.y, new_z) + def to_tuple(self) -> Tuple[int, int, int]: + return (self.x, self.y, self.z) + @staticmethod def from_xyz(x: int, y: int, z: int) -> "Vec3Int": """Use Vec3Int.from_xyz for fast construction.""" From 51f173c49a7ed7b5a5b219cade1ad24793b05b62 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 20 Feb 2024 01:26:22 +0100 Subject: [PATCH 26/41] Move script reading_nd_data to examples in docs and implement some feedback. --- docs/mkdocs.yml | 1 + .../webknossos-py/examples/convert_4d_tiff.md | 10 +++ webknossos/examples/convert_4d_tiff.py | 34 ++++++++++ webknossos/examples/download_segments.py | 2 +- webknossos/examples/download_tiff_stack.py | 2 +- .../script_collection/reading_nd_data.py | 65 ------------------- webknossos/webknossos/dataset/_array.py | 2 +- .../dataset/_utils/buffered_slice_reader.py | 2 +- webknossos/webknossos/dataset/dataset.py | 4 +- webknossos/webknossos/dataset/properties.py | 2 +- webknossos/webknossos/dataset/view.py | 9 +-- .../webknossos/geometry/bounding_box.py | 2 +- .../webknossos/geometry/nd_bounding_box.py | 9 +-- webknossos/webknossos/geometry/vec_int.py | 4 +- 14 files changed, 63 insertions(+), 85 deletions(-) create mode 100644 docs/src/webknossos-py/examples/convert_4d_tiff.md create mode 100644 webknossos/examples/convert_4d_tiff.py delete mode 100644 webknossos/script_collection/reading_nd_data.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index bbe3d73d4..ba4a5f364 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -98,6 +98,7 @@ nav: - webknossos-py/examples/download_tiff_stack.md - webknossos-py/examples/remote_datasets.md - webknossos-py/examples/zarr_and_dask.md + - webknossos-py/examples/convert_4d_tiff.md - Annotation Examples: - webknossos-py/examples/apply_merger_mode.md - webknossos-py/examples/learned_segmenter.md diff --git a/docs/src/webknossos-py/examples/convert_4d_tiff.md b/docs/src/webknossos-py/examples/convert_4d_tiff.md new file mode 100644 index 000000000..036d35d64 --- /dev/null +++ b/docs/src/webknossos-py/examples/convert_4d_tiff.md @@ -0,0 +1,10 @@ +# Convert 4D Tiff + +This example uses the [from_images method](../../api/webknossos/dataset/dataset.md#Dataset.from_images) to creates a Zarr3 dataset from a 4D TIFF image, accesses specific layers and views, [reads data](../../api/webknossos/dataset/mag_view.md#MagView.read) within a bounding box, and [writes data](../../api/webknossos/dataset/mag_view.md#MagView.write) to a different position within the dataset. + + +```python +--8<-- +webknossos/examples/convert_4d_tiff.py +--8<-- +``` diff --git a/webknossos/examples/convert_4d_tiff.py b/webknossos/examples/convert_4d_tiff.py new file mode 100644 index 000000000..dce99dc53 --- /dev/null +++ b/webknossos/examples/convert_4d_tiff.py @@ -0,0 +1,34 @@ +from pathlib import Path + +import webknossos as wk + + +def main() -> None: + # Create a WEBKNOSSOS dataset from a 4D tiff image + dataset = wk.Dataset.from_images( + Path(__file__).parent.parent / "testdata" / "4D" / "4D_series", + "testoutput/4D_series", + voxel_size=(10, 10, 10), + data_format="zarr3", + use_bioformats=True, + ) + + # Access the first color layer and the Mag 1 view of this layer + layer = dataset.get_color_layers()[0] + mag_view = layer.get_finest_mag() + + # Read the data of the dataset within a bounding box + read_bbox = wk.NDBoundingBox( + topleft=(2,0,0,0), + size=(1, 5, 167, 439), + axes=("t", "z", "y", "x"), + index=(1,2,3,4) + ) + data = mag_view.read(absolute_bounding_box=read_bbox) + # data.shape -> (1, 1, 5, 167, 439) + + # Write some data to a given position + mag_view.write(data, absolute_bounding_box=read_bbox.offset((2,0,0,0))) + +if __name__ == "__main__": + main() diff --git a/webknossos/examples/download_segments.py b/webknossos/examples/download_segments.py index 33e4f9bef..f2a006bb4 100644 --- a/webknossos/examples/download_segments.py +++ b/webknossos/examples/download_segments.py @@ -14,7 +14,7 @@ def main() -> None: ) mag_view = dataset.get_segmentation_layers()[0].get_mag(MAG) - z = mag_view.bounding_box.get_bounds("z")[0] + z = mag_view.bounding_box.get_3d("topleft").z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/examples/download_tiff_stack.py b/webknossos/examples/download_tiff_stack.py index 56aaff8ad..1b0d800a7 100644 --- a/webknossos/examples/download_tiff_stack.py +++ b/webknossos/examples/download_tiff_stack.py @@ -15,7 +15,7 @@ def main() -> None: ) mag_view = dataset.get_layer(LAYER_NAME).get_mag(MAG) - z = mag_view.bounding_box.get_bounds("z")[0] + z = mag_view.bounding_box.get_3d("topleft").z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/script_collection/reading_nd_data.py b/webknossos/script_collection/reading_nd_data.py deleted file mode 100644 index f4cd32739..000000000 --- a/webknossos/script_collection/reading_nd_data.py +++ /dev/null @@ -1,65 +0,0 @@ -from pathlib import Path - -from tifffile import imwrite - -import webknossos as wk -from webknossos.geometry.nd_bounding_box import NDBoundingBox - -TIF_PATH = Path(".") / "webknossos" / "testdata" / "4D" / "4D_series" -OUTPUT = Path(".") / "testoutput" / "4D_series" - - -def from_images_import(): - dataset = wk.Dataset.from_images( - TIF_PATH, - OUTPUT, - voxel_size=(10, 10, 10), - data_format="zarr3", - compress=True, - use_bioformats=True, - ) - layer = dataset.get_color_layers()[0] - mag_view = layer.get_finest_mag() - # data = mag_view.read()[0, 0, 0, :, :] - - for bbox in layer.bounding_box.chunk((439, 167, 5)): - with mag_view.get_buffered_slice_reader(absolute_bounding_box=bbox) as reader: - for i, slice_data in enumerate(reader): - imwrite( - f"l4_sample_tiff/tiff_{i}_from_bbox{bbox}.tiff", - slice_data, - ) - - -def open_existing_dataset(): - ds = wk.Dataset.open(OUTPUT) - layer = ds.get_color_layers()[0] - mag_view = layer.get_finest_mag() - read_bbox = NDBoundingBox( - topleft=(0, 0, 0, 0), - size=(1, 1, 439, 167), - axes=("t", "z", "y", "x"), - index=(1, 2, 3, 4), - ) - data = mag_view.read(absolute_bounding_box=read_bbox) - assert data.shape == (1,) + read_bbox.size - data = mag_view.read( - absolute_bounding_box=NDBoundingBox( - topleft=(0, 0, 0, 0), - size=(1, 1, 439, 167), - axes=("t", "z", "y", "x"), - index=(1, 2, 3, 4), - ) - ) - - imwrite("l4_sample_tiff/test.tiff", data) - - -def main() -> None: - """Imports a dataset with more than 3 dimensions.""" - from_images_import() - # open_existing_dataset() - - -if __name__ == "__main__": - main() diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 0ed063e48..89722e785 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -407,7 +407,7 @@ def ensure_size( zarray.resize(new_shape_tuple) def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: - """Writes ZarrArray. If offset and bbox are given the bbox is prefered to enable writing of n-dimensional data.""" + """Writes a ZarrArray. If offset and bbox are given the bbox is prefered to enable writing of n-dimensional data.""" # If data is 3-dimensional, it is assumed that num_channels=1. if data.ndim == 3: diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index 3e8d013a1..c515e0d3c 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -71,7 +71,7 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: ) for current_slice in np.rollaxis( - data, chunk.get_3d("index")[2] + data, chunk.get_3d("index").z ): # The '+1' is important because the first dimension is the channel yield current_slice diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 01a4717d7..08b0d1917 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,11 @@ import attr import numpy as np from boltons.typeutils import make_sentinel -from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath +from cluster_tools import Executor from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset @@ -1746,7 +1746,7 @@ def _export_as_json(self) -> None: # axes are not the same. During initialization axes are added or moved sometimes. warnings.warn( "[WARNING] Properties changed in a way that they are not comparable anymore. Most likely " - + "within the bounding box changed the naming or order of the axes." + + "the bounding box naming or axis order changed." ) with (self.path / PROPERTIES_FILE_NAME).open("w", encoding="utf-8") as outfile: diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 1186fe350..5c2d0c7c3 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -305,7 +305,7 @@ def __layer_properties_pre_structure( if len(d["mags"]) > 0: first_mag = d["mags"][0] if "axisOrder" in first_mag: - assert first_mag["axisOrder"]["c"] == 0 + assert first_mag["axisOrder"]["c"] == 0, "The channels c must have index 0 in axis order." assert all( first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"] ) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 7fb8e9ef3..124d42e54 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -18,8 +18,8 @@ import numpy as np import wkw -from cluster_tools import Executor +from cluster_tools import Executor from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecIntLike @@ -265,9 +265,6 @@ def write( mag1_bbox ), f"The bounding box to write {mag1_bbox} is larger than the view's bounding box {self.bounding_box}" - # if len(data.shape) == 4 and data.shape[0] == 1: - # data = data[0] # remove channel dimension for single-channel data - current_mag_bbox = mag1_bbox.in_mag(self._mag) if self._is_compressed(): @@ -689,8 +686,8 @@ def get_buffered_slice_writer( Arguments: * The user can specify where the writer should start: - * `relative_offset` in Mag(1) -> not usable for n-dimensional data - * `absolute_offset` in Mag(1) -> not usable for n-dimensional data + * `relative_offset` in Mag(1) + * `absolute_offset` in Mag(1) * `relative_bounding_box` in Mag(1) * `absolute_bounding_box` in Mag(1) * ⚠️ deprecated: `offset` in the current Mag, diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 3fe41936f..b746da101 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -56,7 +56,7 @@ def __attrs_post_init__(self) -> None: def with_additional_axis( self, name: str, extent: Tuple[int, int], index: Optional[int] = None ) -> "NDBoundingBox": - assert name not in self.axes, f"The name '{name}' of the axis is already taken." + assert name not in self.axes, f"The identifier '{name}' of the axis is already taken." new_topleft = min(extent) new_size = max(extent) - new_topleft diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 7b1ca9578..aaead95d7 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -15,16 +15,17 @@ @attr.frozen class NDBoundingBox: """ - This class is used to represent an axis-aligned cuboid in N-D. + This class is used to represent an axis-aligned, n-dimensional cuboid. The top-left coordinate is inclusive and the bottom-right coordinate is exclusive. + The index parameter defines the axis order of the data, all values have to be greater or equal to 1, as index 0 is reserved for channel data. A small usage example: ```python from webknossos import NDBoundingBox - bbox_1 = NDBoundingBox(top_left=(0, 0, 0), size=(100, 100, 100), axes=("x", "y", "z")) - bbox_2 = NDBoundingBox(top_left=(75, 75, 75, 0), size=(100, 100, 100, 20), axes=("x", "y", "z", "t")) + bbox_1 = NDBoundingBox(top_left=(0, 0, 0), size=(100, 100, 100), axes=("x", "y", "z"), index=(1,2,3)) + bbox_2 = NDBoundingBox(top_left=(75, 75, 75, 0), size=(100, 100, 100, 20), axes=("x", "y", "z", "t"), index=(2,3,4,1)) ``` """ @@ -170,7 +171,7 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": if "additionalAxes" in bbox: assert ( "axisOrder" in bbox - ), "If there are additionalAxes an axisOrder needs to be given." + ), "If there are additionalAxes an axisOrder needs to be provided." for axis in bbox["additionalAxes"]: topleft.append(axis["bounds"][0]) size.append(axis["bounds"][1] - axis["bounds"][0]) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index 3962e9692..fbfc297de 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -47,7 +47,7 @@ def __new__( assert y is not None and z is not None, VALUE_ERROR remaining_axes = [] for key, value in kwargs.items(): - assert key not in ["x", "y", "z"] + assert key not in ["x", "y", "z"], "Additional axis must not be called x, y or z." remaining_axes.append((key, value)) as_tuple = ( vec, @@ -63,7 +63,7 @@ def __new__( if isinstance(vec, str): return cls.from_str(vec) if isinstance(vec, Iterable): - as_tuple = cast(Tuple[int, ...], tuple(int(item) for item in vec)) + as_tuple = tuple(int(item) for item in vec) assert as_tuple is not None and len(as_tuple) >= 3, VALUE_ERROR return super().__new__(cls, cast(Iterable, as_tuple)) From 7340073b9a6e4f2e28f34cd26258850820b1e182 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 20 Feb 2024 10:14:56 +0100 Subject: [PATCH 27/41] Do some formatting and implement requested changes. --- webknossos/examples/convert_4d_tiff.py | 7 ++++--- .../tests/dataset/test_add_layer_from_images.py | 9 +++++---- webknossos/webknossos/dataset/_utils/pims_images.py | 3 ++- webknossos/webknossos/dataset/dataset.py | 2 +- webknossos/webknossos/dataset/properties.py | 4 +++- webknossos/webknossos/dataset/view.py | 2 +- webknossos/webknossos/geometry/bounding_box.py | 4 +++- webknossos/webknossos/geometry/nd_bounding_box.py | 5 +++-- webknossos/webknossos/geometry/vec3_int.py | 12 +++--------- webknossos/webknossos/geometry/vec_int.py | 6 +++++- 10 files changed, 30 insertions(+), 24 deletions(-) diff --git a/webknossos/examples/convert_4d_tiff.py b/webknossos/examples/convert_4d_tiff.py index dce99dc53..82caba6c7 100644 --- a/webknossos/examples/convert_4d_tiff.py +++ b/webknossos/examples/convert_4d_tiff.py @@ -19,16 +19,17 @@ def main() -> None: # Read the data of the dataset within a bounding box read_bbox = wk.NDBoundingBox( - topleft=(2,0,0,0), + topleft=(2, 0, 0, 0), size=(1, 5, 167, 439), axes=("t", "z", "y", "x"), - index=(1,2,3,4) + index=(1, 2, 3, 4), ) data = mag_view.read(absolute_bounding_box=read_bbox) # data.shape -> (1, 1, 5, 167, 439) # Write some data to a given position - mag_view.write(data, absolute_bounding_box=read_bbox.offset((2,0,0,0))) + mag_view.write(data, absolute_bounding_box=read_bbox.offset((2, 0, 0, 0))) + if __name__ == "__main__": main() diff --git a/webknossos/tests/dataset/test_add_layer_from_images.py b/webknossos/tests/dataset/test_add_layer_from_images.py index b2a389672..39c077387 100644 --- a/webknossos/tests/dataset/test_add_layer_from_images.py +++ b/webknossos/tests/dataset/test_add_layer_from_images.py @@ -57,10 +57,11 @@ def test_compare_nd_tifffile(tmp_path: Path) -> None: ) assert l.bounding_box.topleft == wk.VecInt(0, 55, 100, 100) assert l.bounding_box.size == wk.VecInt(7, 5, 167, 439) - assert np.array_equal( - l.get_finest_mag().read()[0], - TiffFile("testdata/4D/4D_series/4D-series.ome.tif").asarray(), - ) + read_with_tifffile_reader = TiffFile( + "testdata/4D/4D_series/4D-series.ome.tif" + ).asarray() + read_first_channel_from_dataset = l.get_finest_mag().read()[0] + assert np.array_equal(read_with_tifffile_reader, read_first_channel_from_dataset) REPO_IMAGES_ARGS: List[ diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index a429c304d..c3e751896 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -164,7 +164,8 @@ def __init__( self._possible_layers["czi_channel"] = available_czi_channels # An image slice should always consist of a 2D image. If there are multiple channels - # the data of each channel should be part delivered too. Other + # the data of each channel is part of the image slices. Possible shapes of an image + # slice are (#y_shape, #x_shape), (1, #y_shape, #x_shape) or (3, #y_shape, #x_shape). if images.sizes.get("c", 1) > 1: self._bundle_axes = ["c", "y", "x"] else: diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 08b0d1917..586a12b55 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -30,11 +30,11 @@ import attr import numpy as np from boltons.typeutils import make_sentinel +from cluster_tools import Executor from natsort import natsort_keygen from numpy.typing import DTypeLike from upath import UPath -from cluster_tools import Executor from webknossos.geometry.vec_int import VecIntLike from ..client.api_client.models import ApiDataset diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 5c2d0c7c3..83c07306b 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -305,7 +305,9 @@ def __layer_properties_pre_structure( if len(d["mags"]) > 0: first_mag = d["mags"][0] if "axisOrder" in first_mag: - assert first_mag["axisOrder"]["c"] == 0, "The channels c must have index 0 in axis order." + assert ( + first_mag["axisOrder"]["c"] == 0 + ), "The channels c must have index 0 in axis order." assert all( first_mag["axisOrder"] == mag["axisOrder"] for mag in d["mags"] ) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 124d42e54..7f4ff517a 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -18,8 +18,8 @@ import numpy as np import wkw - from cluster_tools import Executor + from webknossos.geometry.vec_int import VecInt from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecIntLike diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index b746da101..29b1d51e6 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -56,7 +56,9 @@ def __attrs_post_init__(self) -> None: def with_additional_axis( self, name: str, extent: Tuple[int, int], index: Optional[int] = None ) -> "NDBoundingBox": - assert name not in self.axes, f"The identifier '{name}' of the axis is already taken." + assert ( + name not in self.axes + ), f"The identifier '{name}' of the axis is already taken." new_topleft = min(extent) new_size = max(extent) - new_topleft diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index aaead95d7..09ddd443f 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -252,7 +252,7 @@ def get_shape(self, axis_name: str) -> int: f"Axis {axis_name} doesn't exist in NDBoundingBox." ) from err - def get_3d(self, attr_name: str) -> Vec3Int: + def get_xyz_for_attribute(self, attr_name: str) -> Vec3Int: axes = ("x", "y", "z") attr_3d = [] @@ -274,9 +274,10 @@ def set_3d(self, attr_name: str, value: Vec3IntLike) -> VecInt: return VecInt(modified_attr) def _check_compatibility(self, other) -> None: + """Checks if two bounding boxes are comparable. To be comparable they need the same number of axes, with same names and same order.""" if self.axes != other.axes: raise ValueError( - f"Operation with two bboxes is only possible if they have the same axes. {self.axes} != {other.axes}" + f"Operation with two bboxes is only possible if they have the same axes and axes order. {self.axes} != {other.axes}" ) def padded_with_margins( diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index c01171b73..e2bbc5c1e 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -93,21 +93,15 @@ def from_str(string: str) -> "Vec3Int": return Vec3Int.full(int(string)) @classmethod - def zeros(cls, length: int = 3) -> "Vec3Int": - del length - + def zeros(cls, _length: int = 3) -> "Vec3Int": return cls(0, 0, 0) @classmethod - def ones(cls, length: int = 3) -> "Vec3Int": - del length - + def ones(cls, _length: int = 3) -> "Vec3Int": return cls(1, 1, 1) @classmethod - def full(cls, an_int: int, length: int = 3) -> "Vec3Int": - del length - + def full(cls, an_int: int, _length: int = 3) -> "Vec3Int": return cls(an_int, an_int, an_int) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index fbfc297de..673f5725d 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -47,7 +47,11 @@ def __new__( assert y is not None and z is not None, VALUE_ERROR remaining_axes = [] for key, value in kwargs.items(): - assert key not in ["x", "y", "z"], "Additional axis must not be called x, y or z." + assert key not in [ + "x", + "y", + "z", + ], "Additional axis must not be called x, y or z." remaining_axes.append((key, value)) as_tuple = ( vec, From 1a947149d1e5f718c5213c1ff9c52f08d1f1ebda Mon Sep 17 00:00:00 2001 From: markbader Date: Wed, 21 Feb 2024 13:17:20 +0100 Subject: [PATCH 28/41] Update naming for accessing attributes of nd bounding boxes. --- webknossos/examples/download_segments.py | 2 +- webknossos/examples/download_tiff_stack.py | 2 +- webknossos/tests/test_examples.py | 4 +- webknossos/webknossos/cli/convert_knossos.py | 4 +- .../webknossos/cli/export_wkw_as_tiff.py | 18 +-- webknossos/webknossos/dataset/_array.py | 20 +-- .../webknossos/dataset/_upsampling_utils.py | 2 +- .../dataset/_utils/buffered_slice_reader.py | 4 +- .../dataset/_utils/buffered_slice_writer.py | 18 ++- .../infer_bounding_box_existing_files.py | 4 +- .../webknossos/dataset/_utils/pims_images.py | 2 +- webknossos/webknossos/dataset/dataset.py | 18 ++- webknossos/webknossos/dataset/layer.py | 6 +- .../webknossos/geometry/bounding_box.py | 16 --- .../webknossos/geometry/nd_bounding_box.py | 120 +++++++++++------- 15 files changed, 124 insertions(+), 116 deletions(-) diff --git a/webknossos/examples/download_segments.py b/webknossos/examples/download_segments.py index f2a006bb4..c24e3c49e 100644 --- a/webknossos/examples/download_segments.py +++ b/webknossos/examples/download_segments.py @@ -14,7 +14,7 @@ def main() -> None: ) mag_view = dataset.get_segmentation_layers()[0].get_mag(MAG) - z = mag_view.bounding_box.get_3d("topleft").z + z = mag_view.bounding_box.topleft_xyz.z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/examples/download_tiff_stack.py b/webknossos/examples/download_tiff_stack.py index 1b0d800a7..595ac769a 100644 --- a/webknossos/examples/download_tiff_stack.py +++ b/webknossos/examples/download_tiff_stack.py @@ -15,7 +15,7 @@ def main() -> None: ) mag_view = dataset.get_layer(LAYER_NAME).get_mag(MAG) - z = mag_view.bounding_box.get_3d("topleft").z + z = mag_view.bounding_box.topleft_xyz.z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/tests/test_examples.py b/webknossos/tests/test_examples.py index e75a1d17a..93f0a57f1 100644 --- a/webknossos/tests/test_examples.py +++ b/webknossos/tests/test_examples.py @@ -312,7 +312,7 @@ def test_download_segments() -> None: assert ( len(list(output_path.iterdir())) - == 2 * mag_view.layer.bounding_box.get_3d("size").z / mag_view.mag.z + == 2 * mag_view.layer.bounding_box.size_xyz.z / mag_view.mag.z ) @@ -329,7 +329,7 @@ def test_download_tiff_stack() -> None: assert ( len(list(output_path.iterdir())) - == mag_view.bounding_box.get_3d("size").z / mag_view.mag.z + == mag_view.bounding_box.size_xyz.z / mag_view.mag.z ) diff --git a/webknossos/webknossos/cli/convert_knossos.py b/webknossos/webknossos/cli/convert_knossos.py index 6e8d63437..44ad18faf 100644 --- a/webknossos/webknossos/cli/convert_knossos.py +++ b/webknossos/webknossos/cli/convert_knossos.py @@ -151,8 +151,8 @@ def convert_cube_job( time_start(f"Converting of {target_view.bounding_box}") cube_size = cast(Tuple[int, int, int], (KNOSSOS_CUBE_EDGE_LEN,) * 3) - offset = target_view.bounding_box.in_mag(target_view.mag).get_3d("topleft") - size = target_view.bounding_box.in_mag(target_view.mag).get_3d("size") + offset = target_view.bounding_box.in_mag(target_view.mag).topleft_xyz + size = target_view.bounding_box.in_mag(target_view.mag).size_xyz buffer = np.zeros(size.to_tuple(), dtype=target_view.get_dtype()) with open_knossos(source_knossos_info) as source_knossos: for x in range(0, size.x, KNOSSOS_CUBE_EDGE_LEN): diff --git a/webknossos/webknossos/cli/export_wkw_as_tiff.py b/webknossos/webknossos/cli/export_wkw_as_tiff.py index 1d3412454..366592c80 100644 --- a/webknossos/webknossos/cli/export_wkw_as_tiff.py +++ b/webknossos/webknossos/cli/export_wkw_as_tiff.py @@ -74,9 +74,9 @@ def export_tiff_slice( tiff_data = view.read() else: padded_tiff_bbox_size = Vec3Int( - tiling_size[0] * ceil(tiff_bbox.get_3d("size").x / tiling_size[0]), - tiling_size[1] * ceil(tiff_bbox.get_3d("size").y / tiling_size[1]), - tiff_bbox.get_3d("size").z, + tiling_size[0] * ceil(tiff_bbox.size_xyz.x / tiling_size[0]), + tiling_size[1] * ceil(tiff_bbox.size_xyz.y / tiling_size[1]), + tiff_bbox.size_xyz.z, ) tiff_data = view.read() padded_tiff_data = np.zeros( @@ -87,9 +87,9 @@ def export_tiff_slice( :, 0 : tiff_data.shape[1], 0 : tiff_data.shape[2], 0 : tiff_data.shape[3] ] = tiff_data tiff_data = padded_tiff_data - for slice_index in range(tiff_bbox.get_3d("size").z): + for slice_index in range(tiff_bbox.size_xyz.z): slice_name_number = ( - tiff_bbox_mag1.get_3d("topleft").z + slice_index + 1 - start_slice_index + tiff_bbox_mag1.topleft_xyz.z + slice_index + 1 - start_slice_index ) if tiling_size is None: tiff_file_name = _make_tiff_name(name, slice_name_number) @@ -100,16 +100,12 @@ def export_tiff_slice( logging.debug("Saved slice %s", slice_name_number) else: - for y_tile_index in range( - ceil(tiff_bbox.get_3d("size").y / tiling_size[1]) - ): + for y_tile_index in range(ceil(tiff_bbox.size_xyz.y / tiling_size[1])): tile_tiff_path = ( dest_path / str(slice_name_number) / str(y_tile_index + 1) ) tile_tiff_path.mkdir(parents=True, exist_ok=True) - for x_tile_index in range( - ceil(tiff_bbox.get_3d("size").x / tiling_size[0]) - ): + for x_tile_index in range(ceil(tiff_bbox.size_xyz.x / tiling_size[0])): tile_tiff_filename = f"{x_tile_index + 1}.tiff" tile_image = _slice_to_image( tiff_data[ diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 89722e785..565ead6c5 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -133,7 +133,7 @@ def ensure_size( pass @abstractmethod - def list_bounding_boxes(self) -> Iterator[BoundingBox]: + def list_bounding_boxes(self) -> Iterator[NDBoundingBox]: "The bounding boxes are measured in voxels of the current mag." @abstractmethod @@ -248,7 +248,7 @@ def _list_files(self) -> Iterator[Path]: for filename in self._wkw_dataset.list_files() ) - def list_bounding_boxes(self) -> Iterator[BoundingBox]: + def list_bounding_boxes(self) -> Iterator[NDBoundingBox]: def _extract_num(s: str) -> int: match = re.search("[0-9]+", s) assert match is not None @@ -415,13 +415,13 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: assert data.ndim == 4 with _blosc_disable_threading(): - self.ensure_size(bbox) + self.ensure_size(bbox, warn=True) zarray = self._zarray index_tuple = (slice(None),) + bbox.to_slices() zarray[index_tuple] = data - def list_bounding_boxes(self) -> Iterator[BoundingBox]: + def list_bounding_boxes(self) -> Iterator[NDBoundingBox]: zarray = self._zarray chunk_shape = Vec3Int(*zarray.chunks[1:4]) for key in zarray.store.keys(): @@ -633,11 +633,11 @@ def ensure_size( if align_with_shards: shard_shape = self.info.shard_shape new_shape = Vec3Int( - new_bbox.get_3d("bottomright").ceildiv(shard_shape) * shard_shape + new_bbox.bottomright_xyz.ceildiv(shard_shape) * shard_shape ) - new_shape_tuple = (zarray.metadata.shape[0],) + new_bbox.set_3d( - "bottomright", new_shape - ).to_tuple() + new_shape_tuple = ( + zarray.metadata.shape[0], + ) + new_bbox.bottomright_with_xyz(new_shape).to_tuple() # Check on-disk for changes to shape current_zarray = zarray.open(self._path) @@ -661,13 +661,13 @@ def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: assert data.ndim == len(bbox) + 1 with _blosc_disable_threading(): - self.ensure_size(bbox) + self.ensure_size(bbox, warn=True) zarray = self._zarray index_tuple = (slice(None),) + bbox.to_slices() zarray[index_tuple] = data - def list_bounding_boxes(self) -> Iterator[BoundingBox]: + def list_bounding_boxes(self) -> Iterator[NDBoundingBox]: raise NotImplementedError def close(self) -> None: diff --git a/webknossos/webknossos/dataset/_upsampling_utils.py b/webknossos/webknossos/dataset/_upsampling_utils.py index cd6ea56b1..94f07596c 100644 --- a/webknossos/webknossos/dataset/_upsampling_utils.py +++ b/webknossos/webknossos/dataset/_upsampling_utils.py @@ -56,7 +56,7 @@ def upsample_cube_job( ) for tile in tiles: - target_offset = Vec3Int(tile) * buffer_shape + target_offset = Vec3Int(Vec3Int(tile) * buffer_shape) source_offset = _vec3int_mulf(target_offset, mag_factors) source_size = source_view.bounding_box.in_mag(source_view.mag).size source_size = _vec3int_mulf(buffer_shape, mag_factors).pairmin( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index c515e0d3c..59941332b 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -60,7 +60,7 @@ def __init__( self.bbox_current_mag = absolute_bounding_box.in_mag(view.mag) def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: - chunk_size = self.bbox_current_mag.get_3d("size").to_list() + chunk_size = self.bbox_current_mag.size_xyz.to_list() chunk_size[self.dimension] = self.buffer_size for chunk in self.bbox_current_mag.chunk(chunk_size): @@ -71,7 +71,7 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: ) for current_slice in np.rollaxis( - data, chunk.get_3d("index").z + data, chunk.index_xyz.z ): # The '+1' is important because the first dimension is the channel yield current_slice diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index c18939e8d..b04ac1459 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -94,7 +94,7 @@ def __init__( view_chunk_depth = self.view.info.chunk_shape[dimension] if ( self.bbox is not None - and self.bbox.get_3d("topleft")[self.dimension] % view_chunk_depth != 0 + and self.bbox.topleft_xyz[self.dimension] % view_chunk_depth != 0 ): warnings.warn( "[WARNING] Using an offset that doesn't align with the datataset's chunk size, " @@ -148,7 +148,7 @@ def _flush_buffer(self) -> None: ) bbox = self.bbox.with_size( - self.bbox.set_3d("size", (max_width, max_height, buffer_depth)) + self.bbox.size_with_xyz((max_width, max_height, buffer_depth)) ).offset(buffer_start) shard_dimensions = self.view._get_file_dimensions().moveaxis( @@ -166,14 +166,12 @@ def _flush_buffer(self) -> None: (channel_count, *chunk_bbox.size), dtype=self.slices_to_write[0].dtype, ) - section_topleft = Vec3Int( - chunk_bbox.get_3d("topleft") - bbox.get_3d("topleft") - ) + section_topleft = Vec3Int(chunk_bbox.topleft_xyz - bbox.topleft_xyz) section_bottomright = Vec3Int( - chunk_bbox.get_3d("bottomright") - bbox.get_3d("topleft") + chunk_bbox.bottomright_xyz - bbox.topleft_xyz ) - z_index = chunk_bbox.get_3d("index")[self.dimension] + z_index = chunk_bbox.index_xyz[self.dimension] z = 0 for section in self.slices_to_write: @@ -189,8 +187,8 @@ def _flush_buffer(self) -> None: section_chunk = np.moveaxis( section_chunk, [1, 2], - bbox.get_3d("index")[: self.dimension] - + bbox.get_3d("index")[self.dimension + 1 :], + bbox.index_xyz[: self.dimension] + + bbox.index_xyz[self.dimension + 1 :], ) slice_tuple = (slice(None),) + tuple( @@ -210,7 +208,7 @@ def _flush_buffer(self) -> None: self.view.write( data, - offset=chunk_bbox.get_3d("topleft").add_or_none(self.offset), + offset=chunk_bbox.topleft_xyz.add_or_none(self.offset), json_update_allowed=self.json_update_allowed, absolute_bounding_box=chunk_bbox.from_mag_to_mag1(self.view._mag), ) diff --git a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py index 9ca3145e8..177042e01 100644 --- a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py +++ b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py @@ -1,10 +1,10 @@ from functools import reduce -from ...geometry import BoundingBox, NDBoundingBox +from ...geometry import BoundingBox from ..mag_view import MagView -def infer_bounding_box_existing_files(mag_view: MagView) -> NDBoundingBox: +def infer_bounding_box_existing_files(mag_view: MagView) -> BoundingBox: """Since volume annotation layers are only a single layer, they do not contain a datasource-properties.json. Therefore, the bounding box needs to be inferred when working with those. The returned bounding box is measured in Mag(1) voxels.""" diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index c3e751896..e83fdaf59 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -466,7 +466,7 @@ def copy_to_view( """ relative_bbox = args - assert relative_bbox.set_3d("size", (1, 1, 1)) == VecInt.ones( + assert relative_bbox.size_with_xyz((1, 1, 1)) == VecInt.ones( len(relative_bbox) ), "The delivered BoundingBox has to be flat except for x,y and z dimension." diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 586a12b55..920dfb437 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -1237,16 +1237,21 @@ def add_layer_from_images( additional_axes = [ axis_name for axis_name in bbox.axes if axis_name not in ("x", "y", "z") ] - additional_axes_shapes = product( - *[range(bbox.get_shape(axis_name)) for axis_name in additional_axes] + additional_axes_shapes = tuple( + product( + *[range(bbox.get_shape(axis_name)) for axis_name in additional_axes] + ) ) if additional_axes and layer.data_format != DataFormat.Zarr3: - assert all( - shape == 1 for shape in additional_axes_shapes + assert ( + len(additional_axes_shapes) == 1 ), "The data stores additional axes with shape bigger than 1. These are only supported by data format Zarr3." # Convert NDBoundingBox to 3D BoundingBox - bbox = BoundingBox(bbox.get_3d("topleft"), bbox.get_3d("size")) + bbox = BoundingBox( + bbox.topleft_xyz, + bbox.size_xyz, + ) expected_bbox = bbox additional_axes = [] @@ -1294,8 +1299,7 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = bbox.set_3d( - "size", + actual_size = bbox.size_with_xyz( Vec3Int(dimwise_max(shapes) + (layer.bounding_box.get_shape("z"),)) * mag.to_vec3_int().with_z(1), ) diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 80913e840..518b017a9 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -419,7 +419,7 @@ def add_mag( dict( zip( ("c", "x", "y", "z"), - (0, *self.bounding_box.get_3d("index")), + (0, *self.bounding_box.index_xyz), ) ) if mag_array_info.data_format in (DataFormat.Zarr, DataFormat.Zarr3) @@ -740,7 +740,7 @@ def downsample( sampling_mode = SamplingModes.parse(sampling_mode) - if self._properties.bounding_box.get_3d("size").z == 1: + if self._properties.bounding_box.size_xyz.z == 1: if sampling_mode != SamplingModes.CONSTANT_Z: warnings.warn( "[INFO] The sampling_mode was changed to 'CONSTANT_Z'. Downsampling 2D data with a different sampling mode mixes in black and thus leads to darkened images." @@ -1088,7 +1088,7 @@ def upsample( # Restoring the original layer bbox self.bounding_box = old_layer_bbox - def _setup_mag(self, mag, path: Optional[str] = None) -> None: + def _setup_mag(self, mag: Mag, path: Optional[str] = None) -> None: # This method is used to initialize the mag when opening the Dataset. This does not create e.g. the wk_header. mag_name = mag.to_layer_name() diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 29b1d51e6..09bc2ae5e 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -53,22 +53,6 @@ def __attrs_post_init__(self) -> None: # it is needed. object.__setattr__(self, "bottomright", self.topleft + self.size) - def with_additional_axis( - self, name: str, extent: Tuple[int, int], index: Optional[int] = None - ) -> "NDBoundingBox": - assert ( - name not in self.axes - ), f"The identifier '{name}' of the axis is already taken." - new_topleft = min(extent) - new_size = max(extent) - new_topleft - - return NDBoundingBox( - topleft=(*self.topleft, new_topleft), - size=(*self.size, new_size), - axes=(*self.axes, name), - index=(*self.index, index if not index is None else max(self.index) + 1), - ) - def with_bounds_x( self, new_topleft_x: Optional[int] = None, new_size_x: Optional[int] = None ) -> "BoundingBox": diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 09ddd443f..01823341b 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -82,24 +82,14 @@ def _sort_positions_of_axes(self) -> None: def _is_sorted(self) -> bool: return all(self.index[i - 1] < self.index[i] for i in range(1, len(self.index))) - def with_additional_axis( - self, name: str, extent: Tuple[int, int], index: Optional[int] = None - ) -> "NDBoundingBox": - assert name not in self.axes, "The identifier of the axis is already taken." - start, end = extent - return attr.evolve( - self, - topleft=(*self.topleft, start), - size=(*self.size, end - start), - axes=(*self.axes, name), - index=(*self.index, index if not index is None else max(self.index) + 1), - ) - def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) + def with_topleft(self, new_topleft: VecIntLike) -> "NDBoundingBox": + return attr.evolve(self, topleft=new_topleft) + def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": - return attr.evolve(self, size=VecInt(new_size)) + return attr.evolve(self, size=new_size) def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": return attr.evolve(self, is_visible=is_visible) @@ -159,26 +149,26 @@ def group_boxes_with_aligned_mag( @classmethod def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": - topleft: List[int] = bbox["topLeft"] - size: List[int] = [bbox["width"], bbox["height"], bbox["depth"]] - axes: List[str] = ["x", "y", "z"] - index: List[int] = [1, 2, 3] + topleft: Tuple[int, ...] = bbox["topLeft"] + size: Tuple[int, ...] = (bbox["width"], bbox["height"], bbox["depth"]) + axes: Tuple[str, ...] = ("x", "y", "z") + index: Tuple[int, ...] = (1, 2, 3) if "axisOrder" in bbox: - axes = list(bbox["axisOrder"].keys()) - index = [bbox["axisOrder"][axis] for axis in axes] + axes = tuple(bbox["axisOrder"].keys()) + index = tuple(bbox["axisOrder"][axis] for axis in axes) if "additionalAxes" in bbox: assert ( "axisOrder" in bbox ), "If there are additionalAxes an axisOrder needs to be provided." for axis in bbox["additionalAxes"]: - topleft.append(axis["bounds"][0]) - size.append(axis["bounds"][1] - axis["bounds"][0]) - axes.append(axis["name"]) - index.append(axis["index"]) + topleft += (axis["bounds"][0],) + size += (axis["bounds"][1] - axis["bounds"][0],) + axes += (axis["name"],) + index += (axis["index"],) - return cls(topleft, size, axes, index) + return cls(topleft=topleft, size=size, axes=axes, index=index) def to_wkw_dict(self) -> dict: topleft = [None, None, None] @@ -252,7 +242,7 @@ def get_shape(self, axis_name: str) -> int: f"Axis {axis_name} doesn't exist in NDBoundingBox." ) from err - def get_xyz_for_attribute(self, attr_name: str) -> Vec3Int: + def _get_attr_xyz(self, attr_name: str) -> Vec3Int: axes = ("x", "y", "z") attr_3d = [] @@ -262,8 +252,8 @@ def get_xyz_for_attribute(self, attr_name: str) -> Vec3Int: return Vec3Int(attr_3d) - def set_3d(self, attr_name: str, value: Vec3IntLike) -> VecInt: - value = Vec3Int(value) + def _get_attr_with_replaced_xyz(self, attr_name: str, xyz: Vec3IntLike) -> VecInt: + value = Vec3Int(xyz) axes = ("x", "y", "z") modified_attr = getattr(self, attr_name).to_list() @@ -273,7 +263,43 @@ def set_3d(self, attr_name: str, value: Vec3IntLike) -> VecInt: return VecInt(modified_attr) - def _check_compatibility(self, other) -> None: + @property + def topleft_xyz(self) -> Vec3Int: + """The topleft corner of the bounding box regarding only x, y and z axis.""" + + return self._get_attr_xyz("topleft") + + @property + def size_xyz(self) -> Vec3Int: + """The size of the bounding box regarding only x, y and z axis.""" + + return self._get_attr_xyz("size") + + @property + def bottomright_xyz(self) -> Vec3Int: + """The bottomright corner of the bounding box regarding only x, y and z axis.""" + + return self._get_attr_xyz("bottomright") + + @property + def index_xyz(self) -> Vec3Int: + """The index of x, y and z axis within the""" + + return self._get_attr_xyz("index") + + def topleft_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: + return self._get_attr_with_replaced_xyz("topleft", new_xyz) + + def size_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: + return self._get_attr_with_replaced_xyz("size", new_xyz) + + def bottomright_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: + return self._get_attr_with_replaced_xyz("bottomright", new_xyz) + + def index_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: + return self._get_attr_with_replaced_xyz("index", new_xyz) + + def _check_compatibility(self, other: "NDBoundingBox") -> None: """Checks if two bounding boxes are comparable. To be comparable they need the same number of axes, with same names and same order.""" if self.axes != other.axes: raise ValueError( @@ -282,7 +308,7 @@ def _check_compatibility(self, other) -> None: def padded_with_margins( self, margins_left: VecIntLike, margins_right: Optional[VecIntLike] = None - ) -> None: + ) -> "NDBoundingBox": raise NotImplementedError() def intersected_with( @@ -324,14 +350,14 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": mag_vec = mag.to_vec3_int() assert ( - self.get_3d("topleft") % mag_vec == Vec3Int.zeros() + self.topleft_xyz % mag_vec == Vec3Int.zeros() ), f"topleft {self.topleft} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." assert ( - self.get_3d("bottomright") % mag_vec == Vec3Int.zeros() + self.bottomright_xyz % mag_vec == Vec3Int.zeros() ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." - new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") // mag_vec)) - new_size = self.set_3d("size", Vec3Int(self.get_3d("size") // mag_vec)) + new_topleft = self.topleft_with_xyz(self.topleft_xyz // mag_vec) + new_size = self.size_with_xyz(self.size_xyz // mag_vec) return attr.evolve( self, @@ -341,8 +367,9 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": mag_vec = from_mag.to_vec3_int() - new_topleft = self.set_3d("topleft", Vec3Int(self.get_3d("topleft") * mag_vec)) - new_size = self.set_3d("size", Vec3Int(self.get_3d("size") * mag_vec)) + new_topleft = self.topleft_with_xyz(self.topleft_xyz * mag_vec) + new_size = self.size_with_xyz(self.size_xyz * mag_vec) + return attr.evolve( self, topleft=new_topleft, @@ -379,8 +406,8 @@ def align_with_mag( # This does the same as _align_with_mag_slow, which is more readable. # Same behavior is asserted in test_align_with_mag_against_numpy_implementation mag_vec = mag.to_vec3_int() if isinstance(mag, Mag) else mag - topleft = self.get_3d("topleft") - bottomright = self.get_3d("bottomright") + topleft = self.topleft_xyz + bottomright = self.bottomright_xyz roundup = topleft if ceil else bottomright rounddown = bottomright if ceil else topleft margin_to_roundup = roundup % mag_vec @@ -390,14 +417,14 @@ def align_with_mag( if ceil: return attr.evolve( self, - topleft=self.set_3d("topleft", Vec3Int(aligned_roundup)), - size=self.set_3d("size", Vec3Int(aligned_rounddown - aligned_roundup)), + topleft=self.topleft_with_xyz(aligned_roundup), + size=self.size_with_xyz(aligned_rounddown - aligned_roundup), ) else: return attr.evolve( self, - topleft=self.set_3d("topleft", Vec3Int(aligned_rounddown)), - size=self.set_3d("size", Vec3Int(aligned_roundup - aligned_rounddown)), + topleft=self.topleft_with_xyz(aligned_rounddown), + size=self.size_with_xyz(aligned_roundup - aligned_rounddown), ) def contains(self, coord: VecIntLike) -> bool: @@ -448,7 +475,7 @@ def chunk( chunk_shape = ( self.with_size(VecInt.ones(len(self))) - .set_3d("size", chunk_shape) + .size_with_xyz(chunk_shape) .to_np() ) except AssertionError: @@ -461,7 +488,7 @@ def chunk( chunk_border_alignments = ( self.with_size(VecInt.ones(len(self))) - .set_3d("size", chunk_border_alignments) + .size_with_xyz(chunk_border_alignments) .to_np() ) except AssertionError: @@ -507,9 +534,8 @@ def to_slices(self) -> Tuple[slice, ...]: def offset(self, vector: VecIntLike) -> "NDBoundingBox": vec_int = VecInt(vector) if len(vec_int) == 3: - new_topleft = self.set_3d( - "topleft", Vec3Int(self.get_3d("topleft") + vec_int) - ) + new_topleft = self.topleft_with_xyz(self.topleft_xyz + vec_int) + return attr.evolve(self, topleft=new_topleft) else: return attr.evolve(self, topleft=self.topleft + vec_int) From e1d522f257034f18a0690247821940799ac84767 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 26 Feb 2024 09:26:11 +0100 Subject: [PATCH 29/41] Fix buffered_slice_writer for different axis and typechecking. --- .../script_collection/globalize_floodfill.py | 10 +- webknossos/tests/test_annotation.py | 2 +- webknossos/webknossos/_nml/parameters.py | 28 +++--- .../webknossos/annotation/annotation.py | 6 +- webknossos/webknossos/dataset/_array.py | 20 ++-- .../dataset/_utils/buffered_slice_reader.py | 2 +- .../dataset/_utils/buffered_slice_writer.py | 22 +++-- .../infer_bounding_box_existing_files.py | 2 +- .../webknossos/dataset/_utils/pims_images.py | 9 +- webknossos/webknossos/dataset/dataset.py | 13 ++- webknossos/webknossos/dataset/layer.py | 8 +- webknossos/webknossos/dataset/mag_view.py | 20 ++-- webknossos/webknossos/dataset/properties.py | 16 +--- webknossos/webknossos/dataset/view.py | 44 +++------ .../webknossos/geometry/bounding_box.py | 4 + .../webknossos/geometry/nd_bounding_box.py | 95 ++++++++++--------- 16 files changed, 145 insertions(+), 156 deletions(-) diff --git a/webknossos/script_collection/globalize_floodfill.py b/webknossos/script_collection/globalize_floodfill.py index f580cfced..4249c89d0 100755 --- a/webknossos/script_collection/globalize_floodfill.py +++ b/webknossos/script_collection/globalize_floodfill.py @@ -97,9 +97,9 @@ def create_parser() -> argparse.ArgumentParser: def get_chunk_pos_and_offset( global_position: Vec3Int, chunk_shape: Vec3Int ) -> Tuple[Vec3Int, Vec3Int]: - offset = global_position % chunk_shape + offset = Vec3Int(global_position % chunk_shape) return ( - global_position - offset, + Vec3Int(global_position - offset), offset, ) @@ -179,10 +179,12 @@ def execute_floodfill( already_processed_bbox.contains(global_neighbor_pos) and cube_data[neighbor_pos] == target_id ): - seeds_in_current_chunk.add(neighbor_pos) + seeds_in_current_chunk.add(Vec3Int(neighbor_pos)) else: chunk_with_relative_seed.append( - get_chunk_pos_and_offset(global_neighbor_pos, cube_size) + get_chunk_pos_and_offset( + Vec3Int(global_neighbor_pos), Vec3Int(cube_size) + ) ) time_stop("traverse cube") diff --git a/webknossos/tests/test_annotation.py b/webknossos/tests/test_annotation.py index 71092732b..927444b81 100644 --- a/webknossos/tests/test_annotation.py +++ b/webknossos/tests/test_annotation.py @@ -199,7 +199,7 @@ def test_annotation_from_url(url: str) -> None: def test_reading_bounding_boxes() -> None: def check_properties(annotation: wk.Annotation) -> None: assert len(annotation.user_bounding_boxes) == 2 - assert annotation.user_bounding_boxes[0].topleft.x == 2371 + assert annotation.user_bounding_boxes[0].topleft_xyz.x == 2371 assert annotation.user_bounding_boxes[0].name == "Bounding box 1" assert annotation.user_bounding_boxes[0].is_visible diff --git a/webknossos/webknossos/_nml/parameters.py b/webknossos/webknossos/_nml/parameters.py index f7bd4745e..cdc283af8 100644 --- a/webknossos/webknossos/_nml/parameters.py +++ b/webknossos/webknossos/_nml/parameters.py @@ -3,7 +3,7 @@ from loxun import XmlWriter -from ..geometry import BoundingBox +from ..geometry import BoundingBox, NDBoundingBox from ..geometry.bounding_box import _DEFAULT_BBOX_NAME from .utils import Vector3, enforce_not_null, filter_none_values @@ -22,13 +22,13 @@ class Parameters(NamedTuple): editPosition: Optional[Vector3] = None editRotation: Optional[Vector3] = None zoomLevel: Optional[float] = None - taskBoundingBox: Optional[BoundingBox] = None - userBoundingBoxes: Optional[List[BoundingBox]] = None + taskBoundingBox: Optional[NDBoundingBox] = None + userBoundingBoxes: Optional[List[NDBoundingBox]] = None def _dump_bounding_box( self, xf: XmlWriter, - bounding_box: BoundingBox, + bounding_box: NDBoundingBox, tag_name: str, bbox_id: Optional[int], # user bounding boxes need an id ) -> None: @@ -43,12 +43,12 @@ def _dump_bounding_box( "color.g": str(color[1]), "color.b": str(color[2]), "color.a": str(color[3]), - "topLeftX": str(bounding_box.topleft.x), - "topLeftY": str(bounding_box.topleft.y), - "topLeftZ": str(bounding_box.topleft.z), - "width": str(bounding_box.size.x), - "height": str(bounding_box.size.y), - "depth": str(bounding_box.size.z), + "topLeftX": str(bounding_box.topleft_xyz.x), + "topLeftY": str(bounding_box.topleft_xyz.y), + "topLeftZ": str(bounding_box.topleft_xyz.z), + "width": str(bounding_box.size_xyz.x), + "height": str(bounding_box.size_xyz.y), + "depth": str(bounding_box.size_xyz.z), } if bbox_id is not None: attributes["id"] = str(bbox_id) @@ -141,7 +141,7 @@ def _dump(self, xf: XmlWriter) -> None: xf.endTag() # parameters @classmethod - def _parse_bounding_box(cls, bounding_box_element: Element) -> BoundingBox: + def _parse_bounding_box(cls, bounding_box_element: Element) -> NDBoundingBox: topleft = ( int(bounding_box_element.get("topLeftX", 0)), int(bounding_box_element.get("topLeftY", 0)), @@ -170,14 +170,16 @@ def _parse_bounding_box(cls, bounding_box_element: Element) -> BoundingBox: ) @classmethod - def _parse_user_bounding_boxes(cls, nml_parameters: Element) -> List[BoundingBox]: + def _parse_user_bounding_boxes(cls, nml_parameters: Element) -> List[NDBoundingBox]: if nml_parameters.find("userBoundingBox") is None: return [] bb_elements = nml_parameters.findall("userBoundingBox") return [cls._parse_bounding_box(bb_element) for bb_element in bb_elements] @classmethod - def _parse_task_bounding_box(cls, nml_parameters: Element) -> Optional[BoundingBox]: + def _parse_task_bounding_box( + cls, nml_parameters: Element + ) -> Optional[NDBoundingBox]: bb_element = nml_parameters.find("taskBoundingBox") if bb_element is not None: return cls._parse_bounding_box(bb_element) diff --git a/webknossos/webknossos/annotation/annotation.py b/webknossos/webknossos/annotation/annotation.py index 8ad6533d5..448686382 100644 --- a/webknossos/webknossos/annotation/annotation.py +++ b/webknossos/webknossos/annotation/annotation.py @@ -60,7 +60,7 @@ ) from ..dataset.defaults import PROPERTIES_FILE_NAME from ..dataset.properties import DatasetProperties, dataset_converter -from ..geometry import BoundingBox, Vec3Int +from ..geometry import NDBoundingBox, Vec3Int from ..skeleton import Skeleton from ..utils import time_since_epoch_in_ms, warn_deprecated from ._nml_conversion import annotation_to_nml, nml_to_skeleton @@ -124,8 +124,8 @@ class Annotation: edit_rotation: Optional[Vector3] = None zoom_level: Optional[float] = None metadata: Dict[str, str] = attr.Factory(dict) - task_bounding_box: Optional[BoundingBox] = None - user_bounding_boxes: List[BoundingBox] = attr.Factory(list) + task_bounding_box: Optional[NDBoundingBox] = None + user_bounding_boxes: List[NDBoundingBox] = attr.Factory(list) _volume_layers: List[_VolumeLayer] = attr.field(factory=list, init=False) @classmethod diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 565ead6c5..9b791a86b 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -560,10 +560,14 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": getattr(array_info.chunk_shape, axis, 1) for axis in array_info.dimension_names[1:] ) + shard_shape = (array_info.num_channels,) + tuple( + getattr(array_info.shard_shape, axis, 1) + for axis in array_info.dimension_names[1:] + ) Array.create( store=path, shape=array_info.shape, - chunk_shape=chunk_shape, + chunk_shape=shard_shape, chunk_key_encoding=("default", "/"), dtype=array_info.voxel_type, dimension_names=array_info.dimension_names, @@ -622,22 +626,24 @@ def ensure_size( align_with_shards: bool = True, warn: bool = False, ) -> None: - new_shape = new_bbox.bottomright zarray = self._zarray - new_shape_tuple = (zarray.metadata.shape[0],) + tuple( - max(zarray.metadata.shape[i + 1], new_shape[i]) - for i in range(len(new_shape)) + new_bbox = new_bbox.with_bottomright( + ( + max(zarray.metadata.shape[i + 1], new_bbox.bottomright[i]) + for i in range(len(new_bbox)) + ) ) + new_shape_tuple = (zarray.metadata.shape[0],) + tuple(new_bbox.bottomright) if new_shape_tuple != zarray.metadata.shape: if align_with_shards: shard_shape = self.info.shard_shape - new_shape = Vec3Int( + new_aligned_bbox = new_bbox.with_bottomright_xyz( new_bbox.bottomright_xyz.ceildiv(shard_shape) * shard_shape ) new_shape_tuple = ( zarray.metadata.shape[0], - ) + new_bbox.bottomright_with_xyz(new_shape).to_tuple() + ) + new_aligned_bbox.bottomright.to_tuple() # Check on-disk for changes to shape current_zarray = zarray.open(self._path) diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index 59941332b..3876d37ab 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -71,7 +71,7 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: ) for current_slice in np.rollaxis( - data, chunk.index_xyz.z + data, chunk.index_xyz[self.dimension] ): # The '+1' is important because the first dimension is the channel yield current_slice diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index b04ac1459..b0fcce9ab 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -147,18 +147,18 @@ def _flush_buffer(self) -> None: self.dimension, self.buffer_start_slice ) - bbox = self.bbox.with_size( - self.bbox.size_with_xyz((max_width, max_height, buffer_depth)) + bbox = self.bbox.with_size_xyz( + Vec3Int(max_width, max_height, buffer_depth).moveaxis( + -1, self.dimension + ) ).offset(buffer_start) - shard_dimensions = self.view._get_file_dimensions().moveaxis( - -1, self.dimension - ) + shard_dimensions = self.view._get_file_dimensions() chunk_size = Vec3Int( min(shard_dimensions[0], max_width), min(shard_dimensions[1], max_height), buffer_depth, - ) + ).moveaxis(-1, self.dimension) for chunk_bbox in bbox.chunk(chunk_size): info(f"Writing chunk {chunk_bbox}.") @@ -166,9 +166,15 @@ def _flush_buffer(self) -> None: (channel_count, *chunk_bbox.size), dtype=self.slices_to_write[0].dtype, ) - section_topleft = Vec3Int(chunk_bbox.topleft_xyz - bbox.topleft_xyz) + section_topleft = Vec3Int( + (chunk_bbox.topleft_xyz - bbox.topleft_xyz).moveaxis( + self.dimension, -1 + ) + ) section_bottomright = Vec3Int( - chunk_bbox.bottomright_xyz - bbox.topleft_xyz + (chunk_bbox.bottomright_xyz - bbox.topleft_xyz).moveaxis( + self.dimension, -1 + ) ) z_index = chunk_bbox.index_xyz[self.dimension] diff --git a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py index 177042e01..5ea220daf 100644 --- a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py +++ b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py @@ -10,7 +10,7 @@ def infer_bounding_box_existing_files(mag_view: MagView) -> BoundingBox: The returned bounding box is measured in Mag(1) voxels.""" return reduce( - lambda acc, bbox: acc.extended_by(bbox), + lambda acc, bbox: BoundingBox.from_ndbbox(acc.extended_by(bbox)), mag_view.get_bounding_boxes_on_disk(), BoundingBox.empty(), ) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index e83fdaf59..cd38d0288 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -1,6 +1,5 @@ import warnings from contextlib import contextmanager, nullcontext -from functools import cached_property from itertools import chain from os import PathLike from pathlib import Path @@ -466,8 +465,10 @@ def copy_to_view( """ relative_bbox = args - assert relative_bbox.size_with_xyz((1, 1, 1)) == VecInt.ones( - len(relative_bbox) + assert all( + size == 1 + for size, axis in zip(relative_bbox.size, relative_bbox.axes) + if axis not in ("x", "y", "z") ), "The delivered BoundingBox has to be flat except for x,y and z dimension." z_start, z_end = relative_bbox.get_bounds("z") @@ -544,7 +545,7 @@ def get_possible_layers(self) -> Optional[Dict["str", List[int]]]: else: return self._possible_layers - @cached_property + @property def expected_bbox(self) -> NDBoundingBox: # replaces the previous expected_shape to enable n-dimensional input files with self._open_images() as images: diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index 920dfb437..ffbb670b7 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -35,7 +35,7 @@ from numpy.typing import DTypeLike from upath import UPath -from webknossos.geometry.vec_int import VecIntLike +from webknossos.geometry.vec_int import VecInt, VecIntLike from ..client.api_client.models import ApiDataset from ..geometry.vec3_int import Vec3Int, Vec3IntLike @@ -1256,7 +1256,7 @@ def add_layer_from_images( additional_axes = [] z_shape = bbox.get_shape("z") - bbox = bbox.offset(-bbox.topleft) + bbox = bbox.with_topleft(VecInt.zeros(len(bbox))) for z_start in range(0, z_shape, batch_size): z_size = min(batch_size, z_shape - z_start) z_bbox = bbox.with_bounds("z", z_start, z_size) @@ -1299,15 +1299,14 @@ def add_layer_from_images( if category == "segmentation": max_id = max(max_ids) cast(SegmentationLayer, layer).largest_segment_id = max_id - actual_size = bbox.size_with_xyz( + layer.bounding_box = layer.bounding_box.with_size_xyz( Vec3Int(dimwise_max(shapes) + (layer.bounding_box.get_shape("z"),)) - * mag.to_vec3_int().with_z(1), + * mag.to_vec3_int().with_z(1) ) - layer.bounding_box = layer.bounding_box.with_size(actual_size) - if expected_bbox.size != actual_size: + if expected_bbox != layer.bounding_box: warnings.warn( "[WARNING] Some images are larger than expected, smaller slices are padded with zeros now. " - + f"New size is {actual_size}, expected {expected_bbox.size}." + + f"New bbox is {layer.bounding_box}, expected {expected_bbox}." ) if first_layer is None: first_layer = layer diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 518b017a9..813e2ee04 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -13,9 +13,7 @@ from numpy.typing import DTypeLike from upath import UPath -from webknossos.geometry.nd_bounding_box import NDBoundingBox - -from ..geometry import BoundingBox, Mag, Vec3Int, Vec3IntLike +from ..geometry import Mag, NDBoundingBox, Vec3Int, Vec3IntLike from ._array import ArrayException, BaseArray, DataFormat from ._downsampling_utils import ( calculate_default_coarsest_mag, @@ -255,11 +253,11 @@ def dataset(self) -> "Dataset": return self._dataset @property - def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: + def bounding_box(self) -> NDBoundingBox: return self._properties.bounding_box @bounding_box.setter - def bounding_box(self, bbox: Union[NDBoundingBox, BoundingBox]) -> None: + def bounding_box(self, bbox: NDBoundingBox) -> None: """ Updates the offset and size of the bounding box of this layer in the properties. """ diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index c034a0ae6..5e0915844 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -157,12 +157,8 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 ) -> None: if offset is not None: if self._mag == Mag(1): @@ -222,12 +218,8 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 ) -> np.ndarray: # THIS METHOD CAN BE REMOVED WHEN THE DEPRECATED OFFSET IS REMOVED @@ -267,8 +259,8 @@ def get_view( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bbox: Optional[NDBoundingBox] = None, # in mag1 + absolute_bbox: Optional[NDBoundingBox] = None, # in mag1 read_only: Optional[bool] = None, ) -> View: # THIS METHOD CAN BE REMOVED WHEN THE DEPRECATED OFFSET IS REMOVED diff --git a/webknossos/webknossos/dataset/properties.py b/webknossos/webknossos/dataset/properties.py index 83c07306b..5fb07595c 100644 --- a/webknossos/webknossos/dataset/properties.py +++ b/webknossos/webknossos/dataset/properties.py @@ -7,8 +7,6 @@ import numpy as np from cattr.gen import make_dict_structure_fn, make_dict_unstructure_fn, override -from webknossos.geometry.bounding_box import BoundingBox - from ..geometry import Mag, NDBoundingBox, Vec3Int from ..utils import snake_to_camel_case, warn_deprecated from ._array import ArrayException, BaseArray, DataFormat @@ -143,7 +141,7 @@ class AxisProperties: class LayerProperties: name: str category: LayerCategoryType - bounding_box: Union[BoundingBox, NDBoundingBox] + bounding_box: NDBoundingBox element_class: str data_format: DataFormat mags: List[MagViewProperties] @@ -320,18 +318,6 @@ def __layer_properties_pre_structure( return __layer_properties_pre_structure -def disambiguate_bounding_box(obj: dict, _: Any) -> Union[BoundingBox, NDBoundingBox]: - if "additionalAxes" in obj: - return dataset_converter.structure(obj, NDBoundingBox) - else: - return dataset_converter.structure(obj, BoundingBox) - - -dataset_converter.register_structure_hook( - Union[BoundingBox, NDBoundingBox], - disambiguate_bounding_box, -) - for cls in [ LayerProperties, SegmentationLayerProperties, diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 7f4ff517a..790c14744 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -13,7 +13,6 @@ Optional, Tuple, Type, - Union, ) import numpy as np @@ -57,7 +56,7 @@ class View: _path: Path _array_info: ArrayInfo - _bounding_box: Optional[Union[NDBoundingBox, BoundingBox]] + _bounding_box: Optional[NDBoundingBox] _read_only: bool _cached_array: Optional[BaseArray] _mag: Mag @@ -67,7 +66,7 @@ def __init__( path_to_mag_view: Path, array_info: ArrayInfo, bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] + NDBoundingBox ], # in mag 1, absolute coordinates, optional only for mag_view since it overwrites the bounding_box property mag: Mag, read_only: bool = False, @@ -96,7 +95,7 @@ def header(self) -> wkw.Header: return self._array._wkw_dataset.header @property - def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: + def bounding_box(self) -> NDBoundingBox: assert self._bounding_box is not None return self._bounding_box @@ -132,8 +131,8 @@ def size(self) -> VecInt: def _get_mag1_bbox( self, - abs_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, - rel_mag1_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, + abs_mag1_bbox: Optional[NDBoundingBox] = None, + rel_mag1_bbox: Optional[NDBoundingBox] = None, abs_mag1_offset: Optional[VecIntLike] = None, rel_mag1_offset: Optional[VecIntLike] = None, mag1_size: Optional[VecIntLike] = None, @@ -164,8 +163,7 @@ def _get_mag1_bbox( assert abs_mag1_offset is not None, "No offset was supplied." assert mag1_size is not None, "No size was supplied." - bbox = self.bounding_box.offset(-self.bounding_box.topleft) - return bbox.offset(abs_mag1_offset).with_size(mag1_size) + return self.bounding_box.with_topleft(abs_mag1_offset).with_size(mag1_size) def write( self, @@ -175,12 +173,8 @@ def write( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 ) -> None: """ Writes the `data` at the specified `relative_offset` or `absolute_offset`, both specified in Mag(1). @@ -350,12 +344,8 @@ def read( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 ) -> np.ndarray: """ The user can specify which data should be read. @@ -505,7 +495,7 @@ def read_bbox(self, bounding_box: Optional[BoundingBox] = None) -> np.ndarray: def _read_without_checks( self, - current_mag_bbox: Union[NDBoundingBox, BoundingBox], + current_mag_bbox: NDBoundingBox, ) -> np.ndarray: data = self._array.read(current_mag_bbox) return data @@ -517,8 +507,8 @@ def get_view( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 - absolute_bbox: Optional[Union[NDBoundingBox, BoundingBox]] = None, # in mag1 + relative_bbox: Optional[NDBoundingBox] = None, # in mag1 + absolute_bbox: Optional[NDBoundingBox] = None, # in mag1 read_only: Optional[bool] = None, ) -> "View": """ @@ -672,12 +662,8 @@ def get_buffered_slice_writer( *, relative_offset: Optional[Vec3IntLike] = None, # in mag1 absolute_offset: Optional[Vec3IntLike] = None, # in mag1 - relative_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 - absolute_bounding_box: Optional[ - Union[NDBoundingBox, BoundingBox] - ] = None, # in mag1 + relative_bounding_box: Optional[NDBoundingBox] = None, # in mag1 + absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 use_logging: bool = False, ) -> "BufferedSliceWriter": """ diff --git a/webknossos/webknossos/geometry/bounding_box.py b/webknossos/webknossos/geometry/bounding_box.py index 09bc2ae5e..8c1bb345a 100644 --- a/webknossos/webknossos/geometry/bounding_box.py +++ b/webknossos/webknossos/geometry/bounding_box.py @@ -119,6 +119,10 @@ def from_csv(cls, csv_bbox: str) -> "BoundingBox": bbox_tuple = tuple(int(x) for x in csv_bbox.split(",")) return cls.from_tuple6(cast(Tuple[int, int, int, int, int, int], bbox_tuple)) + @classmethod + def from_ndbbox(cls, bbox: NDBoundingBox) -> "BoundingBox": + return cls(bbox.topleft_xyz, bbox.size_xyz) + @classmethod def from_auto( cls, obj: Union["BoundingBox", str, Dict, List, Tuple] diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 01823341b..40a439fb0 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -12,6 +12,12 @@ _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" +def str_tpl(str_list: Iterable[str]) -> Tuple[str, ...]: + # Fix for mypy bug https://github.com/python/mypy/issues/5313. + # Solution based on other issue for the same bug: https://github.com/python/mypy/issues/8389. + return tuple(str_list) + + @attr.frozen class NDBoundingBox: """ @@ -32,7 +38,7 @@ class NDBoundingBox: topleft: VecInt = attr.field(converter=VecInt) size: VecInt = attr.field(converter=VecInt) - axes: Tuple[str, ...] = attr.field(converter=tuple) + axes: Tuple[str, ...] = attr.field(converter=str_tpl) index: VecInt = attr.field(converter=VecInt) bottomright: VecInt = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME @@ -53,13 +59,13 @@ def __attrs_post_init__(self) -> None: if not self.size.is_positive(): # Flip the size in negative dimensions, so that the topleft is smaller than bottomright. # E.g. BoundingBox((10, 10, 10), (-5, 5, 5)) -> BoundingBox((5, 10, 10), (5, 5, 5)). - negative_size = (min(0, value) for value in self.size) - new_topleft = ( + negative_size = tuple(min(0, value) for value in self.size) + new_topleft = tuple( val1 + val2 for val1, val2 in zip(self.topleft, negative_size) ) new_size = (max(value, -value) for value in self.size) - object.__setattr__(self, "topleft", new_topleft) - object.__setattr__(self, "size", new_size) + object.__setattr__(self, "topleft", VecInt(new_topleft)) + object.__setattr__(self, "size", VecInt(new_size)) # Compute bottomright to avoid that it's recomputed every time # it is needed. @@ -86,10 +92,18 @@ def with_name(self, name: Optional[str]) -> "NDBoundingBox": return attr.evolve(self, name=name) def with_topleft(self, new_topleft: VecIntLike) -> "NDBoundingBox": - return attr.evolve(self, topleft=new_topleft) + return attr.evolve(self, topleft=VecInt(new_topleft)) def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": - return attr.evolve(self, size=new_size) + return attr.evolve(self, size=VecInt(new_size)) + + def with_index(self, new_index: VecIntLike) -> "NDBoundingBox": + return attr.evolve(self, index=VecInt(new_index)) + + def with_bottomright(self, new_bottomright: VecIntLike) -> "NDBoundingBox": + new_size = VecInt(new_bottomright) - self.topleft + + return self.with_size(new_size) def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": return attr.evolve(self, is_visible=is_visible) @@ -287,17 +301,25 @@ def index_xyz(self) -> Vec3Int: return self._get_attr_xyz("index") - def topleft_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: - return self._get_attr_with_replaced_xyz("topleft", new_xyz) + def with_topleft_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + new_topleft = self._get_attr_with_replaced_xyz("topleft", new_xyz) + + return self.with_topleft(new_topleft) - def size_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: - return self._get_attr_with_replaced_xyz("size", new_xyz) + def with_size_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + new_size = self._get_attr_with_replaced_xyz("size", new_xyz) - def bottomright_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: - return self._get_attr_with_replaced_xyz("bottomright", new_xyz) + return self.with_size(new_size) - def index_with_xyz(self, new_xyz: Vec3IntLike) -> VecInt: - return self._get_attr_with_replaced_xyz("index", new_xyz) + def with_bottomright_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + new_bottomright = self._get_attr_with_replaced_xyz("bottomright", new_xyz) + + return self.with_bottomright(new_bottomright) + + def with_index_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + new_index = self._get_attr_with_replaced_xyz("index", new_xyz) + + return self.with_index(new_index) def _check_compatibility(self, other: "NDBoundingBox") -> None: """Checks if two bounding boxes are comparable. To be comparable they need the same number of axes, with same names and same order.""" @@ -356,24 +378,15 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": self.bottomright_xyz % mag_vec == Vec3Int.zeros() ), f"bottomright {self.bottomright} is not aligned with the mag {mag}. Use BoundingBox.align_with_mag()." - new_topleft = self.topleft_with_xyz(self.topleft_xyz // mag_vec) - new_size = self.size_with_xyz(self.size_xyz // mag_vec) - - return attr.evolve( - self, - topleft=new_topleft, - size=new_size, + return self.with_topleft_xyz(self.topleft_xyz // mag_vec).with_size_xyz( + self.size_xyz // mag_vec ) def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": mag_vec = from_mag.to_vec3_int() - new_topleft = self.topleft_with_xyz(self.topleft_xyz * mag_vec) - new_size = self.size_with_xyz(self.size_xyz * mag_vec) - return attr.evolve( - self, - topleft=new_topleft, - size=new_size, + return self.with_topleft_xyz(self.topleft_xyz * mag_vec).with_size_xyz( + self.size_xyz * mag_vec ) def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": @@ -415,16 +428,12 @@ def align_with_mag( margin_to_rounddown = (mag_vec - (rounddown % mag_vec)) % mag_vec aligned_rounddown = rounddown + margin_to_rounddown if ceil: - return attr.evolve( - self, - topleft=self.topleft_with_xyz(aligned_roundup), - size=self.size_with_xyz(aligned_rounddown - aligned_roundup), + return self.with_topleft_xyz(aligned_roundup).with_size_xyz( + aligned_rounddown - aligned_roundup ) else: - return attr.evolve( - self, - topleft=self.topleft_with_xyz(aligned_rounddown), - size=self.size_with_xyz(aligned_roundup - aligned_rounddown), + return self.with_topleft_xyz(aligned_rounddown).with_size_xyz( + aligned_roundup - aligned_rounddown ) def contains(self, coord: VecIntLike) -> bool: @@ -475,8 +484,8 @@ def chunk( chunk_shape = ( self.with_size(VecInt.ones(len(self))) - .size_with_xyz(chunk_shape) - .to_np() + .with_size_xyz(chunk_shape) + .size.to_np() ) except AssertionError: chunk_shape = VecInt(chunk_shape).to_np() @@ -488,8 +497,8 @@ def chunk( chunk_border_alignments = ( self.with_size(VecInt.ones(len(self))) - .size_with_xyz(chunk_border_alignments) - .to_np() + .with_size_xyz(chunk_border_alignments) + .size.to_np() ) except AssertionError: chunk_border_alignments = VecInt(chunk_border_alignments).to_np() @@ -534,8 +543,6 @@ def to_slices(self) -> Tuple[slice, ...]: def offset(self, vector: VecIntLike) -> "NDBoundingBox": vec_int = VecInt(vector) if len(vec_int) == 3: - new_topleft = self.topleft_with_xyz(self.topleft_xyz + vec_int) + return self.with_topleft_xyz(self.topleft_xyz + vec_int) - return attr.evolve(self, topleft=new_topleft) - else: - return attr.evolve(self, topleft=self.topleft + vec_int) + return self.with_topleft(self.topleft + vec_int) From e6145255f4e059a8c240222928e2fc621ba0c55f Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 26 Feb 2024 20:11:38 +0100 Subject: [PATCH 30/41] Fix issue with ensure_size in initialization. --- .../tests/dataset/test_add_layer_from_images.py | 11 +---------- webknossos/webknossos/dataset/_utils/pims_images.py | 3 ++- webknossos/webknossos/dataset/mag_view.py | 5 +++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/webknossos/tests/dataset/test_add_layer_from_images.py b/webknossos/tests/dataset/test_add_layer_from_images.py index 39c077387..1d04f7e7b 100644 --- a/webknossos/tests/dataset/test_add_layer_from_images.py +++ b/webknossos/tests/dataset/test_add_layer_from_images.py @@ -9,10 +9,10 @@ import httpx import numpy as np import pytest +from tests.constants import TESTDATA_DIR from tifffile import TiffFile import webknossos as wk -from tests.constants import TESTDATA_DIR pytestmark = [pytest.mark.block_network(allowed_hosts=[".*"])] @@ -229,15 +229,6 @@ def download_and_unpack( (192, 128, 9), 1, ), - ( - "https://samples.scif.io/sdub.zip", - "sdub*.pic", - {"allow_multiple_layers": True}, - "uint8", - 1, - (192, 128, 9), - 12, - ), ( "https://samples.scif.io/test-avi.zip", "t1-rendering.avi", diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index cd38d0288..d6b24b3aa 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -446,6 +446,8 @@ def _open_images( images.bundle_axes = self._bundle_axes images.iter_axes = self._iter_axes or [] else: + if self._timepoint is not None: + images = images[self._timepoint] if self._iter_axes == []: # add outer list to wrap 2D images as 3D-like structure images = [images] @@ -510,7 +512,6 @@ def copy_to_view( source=self._bundle_axes.index("c"), destination=0, ) - if "c" in self._bundle_axes: if self._channel is not None: image_slice = image_slice[self._channel : self._channel + 1] elif self._first_n_channels is not None: diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 5e0915844..e0a488aa7 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,9 +7,10 @@ from uuid import uuid4 import numpy as np -from cluster_tools import Executor from upath import UPath +from cluster_tools import Executor + from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( NDArrayLike, @@ -79,7 +80,7 @@ def __init__( chunks_per_shard=chunks_per_shard, compression_mode=compression_mode, axis_order=VecInt(0, *layer.bounding_box.index), - shape=VecInt(layer.num_channels, *layer.bounding_box.size), + shape=VecInt(layer.num_channels, *VecInt.ones(len(layer.bounding_box))), dimension_names=("c",) + layer.bounding_box.axes, ) if create: From 27d3a3d3608731ca816b01a48a0849b9c46be0f2 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 27 Feb 2024 00:25:25 +0100 Subject: [PATCH 31/41] Adapt pims_images to support xyz images with channels and timepoint. --- .../webknossos/dataset/_utils/pims_images.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index d6b24b3aa..fb47e706f 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -232,6 +232,30 @@ def __init__( else: self._bundle_axes = ["y", "x", "c"] self._iter_axes = ["z"] + elif len(images.shape) == 5: + # Assume tzcyx or tzyxc + # t has to be constant for this reader to obtain 4D image + # (only possible if not specified manually already, since + # the timepoint would already be indexed here and the + # 5th dimension would be something else) + if timepoint is not None: + raise RuntimeError( + f"Got {len(images.shape)} axes for the images after " + + "removing time dimension, can only map to 3D+channels." + + "To import image with more dimensions use dataformat" + + "Zarr3 and set use_bioformats=True." + ) + + if _assume_color_channel(images.shape[2], images.dtype): + self._bundle_axes = ["c", "y", "x"] + else: + self._bundle_axes = ["y", "x", "c"] + self._iter_axes = ["z"] + self._timepoint = 0 + if images.shape[0] > 1: + self._possible_layers["timepoint"] = list( + range(0, images.shape[0]) + ) else: raise RuntimeError( f"Got {len(images.shape)} axes for the images, " From 8a1ca27da3cd5d0d44298ec21feacf31bbb52a92 Mon Sep 17 00:00:00 2001 From: markbader Date: Tue, 27 Feb 2024 00:34:30 +0100 Subject: [PATCH 32/41] run formatter --- webknossos/tests/dataset/test_add_layer_from_images.py | 2 +- webknossos/webknossos/dataset/mag_view.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/webknossos/tests/dataset/test_add_layer_from_images.py b/webknossos/tests/dataset/test_add_layer_from_images.py index 1d04f7e7b..5711b48c1 100644 --- a/webknossos/tests/dataset/test_add_layer_from_images.py +++ b/webknossos/tests/dataset/test_add_layer_from_images.py @@ -9,10 +9,10 @@ import httpx import numpy as np import pytest -from tests.constants import TESTDATA_DIR from tifffile import TiffFile import webknossos as wk +from tests.constants import TESTDATA_DIR pytestmark = [pytest.mark.block_network(allowed_hosts=[".*"])] diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index e0a488aa7..ec49a9ac6 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -7,9 +7,8 @@ from uuid import uuid4 import numpy as np -from upath import UPath - from cluster_tools import Executor +from upath import UPath from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( From 4167b9b9ff47884257a7d64786ebafc84a11bf00 Mon Sep 17 00:00:00 2001 From: markbader Date: Fri, 8 Mar 2024 00:43:36 +0100 Subject: [PATCH 33/41] Fix issues with failed tests and add comments. --- .../webknossos/dataset/_utils/pims_images.py | 67 ++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index fb47e706f..e6d5101fb 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -193,6 +193,14 @@ def __init__( for axis, other_axis in zip( self._iter_axes[-1:0:-1], self._iter_axes[-2::-1] ): + # Creates a dict that contains the size of the loop for each axis + # the axes are identified by their index in the _iter_axes list + # the last axis is the fastest iterating axis, therfore the size of the loop + # for the last axis is 1. For all other axes it is the product of all previous axes sizes. + # self._iter_axis[-1:0:-1] is a reversed copy of self._iter_axis without the last element + # e.g. [1,2,3,4] -> [4,3,2] + # self._iter_axis[-2::-1] is a reversed copy of self._iter_axis without the first element + # e.g. [1,2,3,4] -> [3,2,1] self._iter_loop_size[other_axis] = ( iter_size := iter_size * images.sizes[axis] ) @@ -208,18 +216,18 @@ def __init__( if len(images.shape) == 2: # Assume yx self._bundle_axes = ["y", "x"] - self._iter_axes = [""] + self._iter_axes = [] elif len(images.shape) == 3: # Assume yxc, cyx or zyx if _assume_color_channel(images.shape[2], images.dtype): self._bundle_axes = ["y", "x", "c"] - self._iter_axes = [""] + self._iter_axes = [] elif images.shape[0] == 1 or ( _allow_channels_first and _assume_color_channel(images.shape[0], images.dtype) ): self._bundle_axes = ["c", "y", "x"] - self._iter_axes = [""] + self._iter_axes = [] else: self._bundle_axes = ["y", "x"] self._iter_axes = ["z"] @@ -467,11 +475,15 @@ def _open_images( images._get_frame_dict[ key + ("c",) ] = images._get_frame_dict.pop(key) + self._bundle_axes.remove("c") + self._bundle_axes.append("c") images.bundle_axes = self._bundle_axes - images.iter_axes = self._iter_axes or [] + images.iter_axes = self._iter_axes else: if self._timepoint is not None: images = images[self._timepoint] + if self._iter_axes and "t" in self._iter_axes: + self._iter_axes.remove("t") if self._iter_axes == []: # add outer list to wrap 2D images as 3D-like structure images = [images] @@ -531,6 +543,11 @@ def copy_to_view( image_slice = np.array(image_slice) # place channels first if "c" in self._bundle_axes: + if hasattr(self, "_init_c_axis") and self._init_c_axis: + # Bugfix for ImageIOReader which misses channel axis sometimes, + # assuming channels come last. _init_c_axis is set in __init__(). + # This might get fixed via + image_slice = image_slice[0] image_slice = np.moveaxis( image_slice, source=self._bundle_axes.index("c"), @@ -574,27 +591,47 @@ def get_possible_layers(self) -> Optional[Dict["str", List[int]]]: def expected_bbox(self) -> NDBoundingBox: # replaces the previous expected_shape to enable n-dimensional input files with self._open_images() as images: - if isinstance(images, list): - images_shape = (len(images),) + cast( - pims.FramesSequence, images[0] - ).shape + if isinstance(images, pims.FramesSequenceND): + axes = images.axes + images_shape = tuple(images.sizes[axis] for axis in axes) else: - images_shape = images.shape # pylint: disable=no-member + if isinstance(images, list): + images_shape = (len(images),) + cast( + pims.FramesSequence, images[0] + ).shape + + else: + images_shape = images.shape # pylint: disable=no-member + if len(images_shape) == 3: + axes = ("z", "y", "x") + else: + axes = ("z", "c", "y", "x") - if self._iter_axes is None or len(self._iter_axes) <= 1: - if self._bundle_axes.index("x") < self._bundle_axes.index("y"): - x_index, y_index = 1, 2 + if self._iter_loop_size is None: + # There is no or only one iter_axis, so a 3D bounding box is sufficient. + x_index, y_index = ( + axes.index("x"), + axes.index("y"), + ) + if self._iter_axes: + try: + # In case the naming of the third axis is not "z", + # it is still considered as the z-axis. + z_index = axes.index(self._iter_axes[0]) + except ValueError: + z_index = axes.index("z") + z_shape = images_shape[z_index] else: - x_index, y_index = 2, 1 + z_shape = 1 if self._swap_xy: x_index, y_index = y_index, x_index return BoundingBox( (0, 0, 0), - (images_shape[x_index], images_shape[y_index], images_shape[0]), + (images_shape[x_index], images_shape[y_index], z_shape), ) else: if isinstance(images, pims.FramesSequenceND): - axes_names = self._iter_axes + [ + axes_names = self._iter_axes or [] + [ axis for axis in self._bundle_axes if axis != "c" ] axes_sizes = [ From 2f69c3053e4824edbb73e3f4d639aac6b30baa30 Mon Sep 17 00:00:00 2001 From: markbader Date: Fri, 8 Mar 2024 09:50:44 +0100 Subject: [PATCH 34/41] Fix statement with wrong VecInt initialization. --- webknossos/webknossos/dataset/_utils/pims_images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index e6d5101fb..b0b8e8d1e 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -631,7 +631,7 @@ def expected_bbox(self) -> NDBoundingBox: ) else: if isinstance(images, pims.FramesSequenceND): - axes_names = self._iter_axes or [] + [ + axes_names = (self._iter_axes or []) + [ axis for axis in self._bundle_axes if axis != "c" ] axes_sizes = [ From 31255e371856e9647cade81129cad61833fb33a6 Mon Sep 17 00:00:00 2001 From: markbader Date: Fri, 8 Mar 2024 13:43:19 +0100 Subject: [PATCH 35/41] Insert previously deleted assertions. --- .../multi-channel-4D-series.ome.tif | Bin 7889559 -> 0 bytes .../multi-channel-time-series.ome.tif | Bin 1578825 -> 0 bytes .../dataset/_utils/buffered_slice_writer.py | 1 - webknossos/webknossos/dataset/mag_view.py | 10 ++-- webknossos/webknossos/dataset/view.py | 44 ++++++++++++++++-- 5 files changed, 48 insertions(+), 7 deletions(-) delete mode 100644 webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif delete mode 100644 webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif diff --git a/webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif b/webknossos/testdata/4D/multi_channel_4D_series/multi-channel-4D-series.ome.tif deleted file mode 100644 index 890f35b43178ef0f711c0831b7524b333c0fd333..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7889559 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%0DJPWxtz}$m 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

@I)&^oaLt&=_qtyBILTC0wN)@i?h))_B@)>-$0 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�i}8=R>~nA$!Phox*1EFhbf_n;MFNPz6nKy_&( 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

=C;AiXemp#R_1 z;l^Cy=^Ea~jt~b9w-`kSj<7HX%z>I5IMTu#Fb8UK;3$hxbl_+UbHE&^$${~yN0E+{ z%Cu=!jSjef`O)*d(mj>Ro@3OY#ZFK}*muC1c?TM~C~~B5rEaMdSuf!9MPsUCz1A5o z4zQ*4;~>&!dQus>=scIPqxG^b1z|pT`2X)Wzv>XVQyTsRk3+Xmv zsk^E}f>7q)A#OC54sK zcYrOX96tW%<5%nUK-Z@B&;~c}SJ`tI2TspNK{P%nhmWIz+F^XCOpqB;@gI_Y!dGDc zd!DuDunwG&kAi4?P!6BMab8Y1`9zf$I5xWK|3Fb8UK z;6e*?z#OQ_fr~6g(SeIC%mH(tCI>FDFbB+mnjE;7g*jjj)a1aW7Nh9EWftauIZ%@W zms^+v=0HsjTw!4jm;*IAaHYj4I&hVRIbaUd`Ygb;k`iy0BufOe< z)$7)8Sh?zkWgFJrx_a&!;@2-b@`%RVRoAb)>88~;u3vWa-1RrES%qw4?zQVyu0_xS z+<65wf3-6-fBk7_{`L{j{9PNGzyA$1|M)6s{`pF1{&g2<{_Qi+{Kq4q`L7N%i{C

~?6)xe8ia>H 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 z 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

=C;AiXemp#R_1 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/@(s}X^eSk5c6Vrf?kmvx!egQJrBk8x z<$plyt8awX*KdZ_H}`r7#-#ZOj-~T7He)uM6{rDDW{d7-g{p@Sd`o-g+ z^~=+t^{anD>o;$P*6(hG)*tqQ)*rtPtv^2jT7NwQT7UaDwEpoHX#J}Wt^dr2)_=bN zE%QWZ*Oozh#($u_$y=elSp(Xe?+xuOz6tF)PlEPVXF_}Kf1$n2+n~K|6WZJF1MMBY z1?`=l4DDUcg7&WegZA!khxVQ=XwTml+IxQ++WS5Q+WVgk?E?(74|)f*4{1aD(EXr& z*mt0P_*0?1=p1MtW$)nVJE46{2inK&5AEZ>3+)r12JI#1LVIZq+NZn|+NX7)eZ~RM zUiLj`pY?QTpR*j=%V$9QymvwSg4NKz=s;*+{C#L&`V44aejc>1oC)o#-VN<*?gj1Z z4ubaeKY;d)&xH1h^P#`Hr+)z2&%8IZpM4m#pYu~_Kks?ae!(Tse$f`t ze(?vP{nGnD`{fIv{feJK`;O;B`_-31`?a&7{kji9`wjPn_L~le_M3kW?YF)F+Hb!M z+IP-@_B%fe?RVb}?e`u5?f3lx+8=l!v_Et?v_G;Xv_JY0Xn*{E(Ej8i{9WotJ-B=R zJz)R*g_(EZ6Z3`VFPnc_y?fZ1-8JnM>(ny=bes9gdA1}RP*$3oBvH{ZJ>P0X=WjNJu&?B&8DN%CyGPTyl}GkgR0+E`)?ws|nsdR{l!q5W0-N(@k+6ulP=DC@mouui{YY%kuC zEBG?`?c29sDe%*-U#leEtL_vcu6B&yN!XDElUEjA!-qmlULwn7Y zU$6LPVG@P7ELrQP`3&E7q~r(})qYhfN6zcw{dt|+B4B)zK+;$&>0p@)Dz}9>5;75X zA&-!GAuN-0X{eS$!bx_T-a^q4W0nm;B-QDOo<)sCy`}Lhu!zK&7OtY>W`}S!Vg&ZV z(D#v~U|a@aij*Q-ZP*Yp61|V1p55SdnfEDA`*%;@A*jTgc<6c270@Y)b+VSeOOF%9 zY=jnh2PnI*MsMSDe3F{7?I0u{NJy0EinTaG%7~d{fSRPBAxp*ujucGnMUCJR7#8NI z;~6}|fZl``AP`*voupW&YA4Ch+rjuX;t7H!NI5K%$+p6hJem^%yIJVT*qt+naT%bP z*|5%~GHDq)FgwEStgshJXUb{fWDb3nm0w%5Xs}EPhM@)g#l%{{5~NJ~MHVfF7SLkK z(z)1;tl%=F?8dfuiwr4eB&I3m7}ySD1}RCyQ7MIeyG3EKmIv`7_EB`xL9Q}V?(seX zwj*!GW65n9!gBqfXm8253~&Xrv@g#|nZz{390R#0M@o+0A|YwF?RqG>0=izY_NTK+ zWep8bPESbKP}r32^CSKw#<{OzwhCc4^n;?k72`6%70lAUJSSxZY)cn@frY$@F$1yO z&4`DalES`gio#-z!(qAH6DXftBORnF(G^JE$AARMLP4@4l8Zhu%fK#TTn2ayu{OJq z9O4kRN03L@m^c~tp_+#n2+|M5r&~`#qLVFgpIGh2xR!G$_YpP3xSX8mHI^qfEA?d9 z$BCwBG|9Fwb3<5RKPcLB8J7XBAl7CVlA|MpENSCF&@f^khjOIk!jfKZLv1l4pzDU( zCKq9XO8=I&qD?WUBvq87&LK`nD zvQpkkDk5aflY%tcgs@ycn6`tINd~wgDKa|)C1r#u`z^&&RXUq#>xxO&=Eeg^yz!l8WzCiMR&r2C$%5F*N6uCPp z#etSA93q8~! z5{NF2#E>G!v7NjT(_Uyxo{(Ry{Bk_V6Jj?4@T;v3N03939$SndS{GF?!rP|b_6upw*4!csnmnr1r6N_Kpm*afn7D!0d=4v z2X@mKM+bJ-*ti_9|M?ETko)g={+l7}^&Mp|U`!ajMwB1kfjxSLHQe^_vxi5nbaiG1 z@5j@Wb5&+gsrBlB@i!LCw<%s={v5il^kRw4&nP>j1AF!ev*(`nuMh?+Uoz?HKss4b zAW2%Jd9)7LI}lfbcje1SB8n9X{2Sq5dO1M_oXjAh-!bv?qTy%g3<9OY4q!l>pk1tW97xh*XB5bsG`TY~wPlWUXe zk-hA+T)cNC?EUzlo*}SzM0;Ba(-wrvC;5~j#iMpWTuOuy;WdfMUYma*&-o(hkNSP5 z*ZzHag)z2+pM4y1vWPtC+O89%sOAZw4jN4(cfenp`@_}-%YK)@;2WhAS>Oe&f9IUZ1I$#Wb zEBgq*A^)!+T>~LDeQb;l+%3P;ArpnM0^=U2MBu_vq2WkRP+Ri`cEDaoyrSZ*iFf0c z;1rI^fdvzW{o~JT%z^+GEbtUHT$_6nE>ywP9XNEtFeXUs{V{TY%5o8Onl_jNrOP_> zP`W;OZNzP`_nck_A2vZ4bC?Md3tdp=2C__gjXpQ519(+*UH(nt1<`#XFR|C@bA%2o z>>mc(?m@|f3VG3uZ2yJYt-yiw!rX!We^-YabA_iXcpE)}9XMQL93419Lmf~DDso_v zhB}}QROG;s8sq4|Q5x!iI#7`VM^8RXI#MXprdAa?;Qr-D&+`iRR499nVZ$!=eS>f^ zlYQ4tzvkjxm>kJmp<5_fmIpy?7Ef+0zf9T00kRZ-5!mn^t3M5wmmZqz<}<)uLsNor~y)PZAjfnHl4KlpGt z=weyyh7Ji_I}C~B>G15K5pso-a3I*}l6{c7?w7-*?1~QRLzz2~rd*E}=Y-1jbKtmK z7*D!n9}|{R81-(6zd{pMgk4lo&b@{|T`WZ>lzuSm;e?C)hJd)Epdtst?G16-@RLIvwsDS} zFm#v=Fgf&*8{6QCLx&l9QU}$6>FK~p8XKPjW{|HmkZ6!asu|dUCHcUAKDQnGOc+^F zSb!@SPPj=0Q**%GgneXhq_{dOLee#SH>)Ww(t2PAPR@lP(wuA%s&|PYEAuJ4GY<3@<)fl-0hE700h0UQ92`Mad zVUTnWcjs7XtS1Lf$%P>jf&1VuDZrTA&&!uIAhKKH9$|^-DIA3ZWVXMua53d;3r7dF zyF_=pj>l_`SIQg1jHanMaB4OTvi5OzoKOMW3KenP9 zNLW;%s1)wE=XwE^6iQ6Nfzw7BW~AGv@$%D08fK*1b-6k)UJjh0p$@166*;i1PnbTv zv^BUgozrSPI^h11-3)gXJ*NChd`Gh^;`R8>(`?n5`7n8UVz$qqaXl~ac;a=c$UAUW zJ`B?KVa_u6^riio1U1r0kRk`!F@ssb~9aQTUsP3e$2Fuff(Ut=5{xIjZ4PzNe< z;6e>`Kpm*afr~WM0d=4v2QJnaM+Yv^PzTh3iX6C9Lmf~DDstd54Rt^rsK|lKHOA3_ zD>T#rb)X^#uGCNm)Paf|xJpAEPzNe<;A)L=bl@5dbwC}c$boA$)B$y%A_uP1PzTh3 ziX6CJV;mj0K|>u-2P$&lMh$g99jM5Gn>5DJ0obMnun7RzRJ*fQBMf)cX249xZ*Ds? z14h+m0?&mRR&xrpKmCT>sG96E?KwcwpFw1 z$gf?p=!nI$SKhj!(^=J8yX2_ZYg_e|mR&si<~1wY790z9=Xucn@=R!d<=xQ!+P$Ft zjf0^5%^yJf+s}mdch86R_cwv|58eaqAFYA*PY#CmPk#vQpFa!QcU=JOUu_EQU%waH zzg-LM-yZ_)Kl}*Ve|k2w|8gO;|F#*l|NcH`|8pI*|Gfa(|M@Yr|Mwi|z(vrRF$+2~ z-w&NlZ-dUPL!q96DQn06O#T4V~={gU#&Ve6-&cXME&Vs|CbLh{Zv+xDbIpQ+t z961L%M|~JNi*JX{u}47XxL-i$gcm~Rq|2dm@|Mt9`Vr`ydOzr#z6d&J+y$L8Uj&`A zuYk_ETR~^}N1=26{h@Q=kyl6q0@LNbXr$Kr?U-ox}Si~y&ediwTq#%?l;i6 z_sgJj-)o?Azj@HP|0kjIe-DDrgN}jDgMSO1hrS#-55E>VkK7hIkNOmJ9`j)6JnmTN zJpOmkdEzUe^W^KG^VIF2^R!Px=NS)y&a;k#&a;0Ho#(z1I?ulzIxpNFIxqSRbYAjM z=)CNB=)C+7(0Sz@(0SDj(0R=c(0T1=q4WBOLFbJpK<7<=gw9)D1)aCu2%UHA2%S4W z2c36496Ikg5jyYv6LjAHYUq6MCg^;4C+K|S^U(R&BcSt%lc4j-KSSr!uYt~IS3u|U zJ45FSUx3b+9toYVEP>8f{{o$_zZN>*ya#l?y$f`{^F`=VK5 znXjB@OTqzVrMXEG6&=&_twwbIW>X0JN`9IFmPyfj`+&0E3kK`-J;pY}H*l|wCB|Tz z2UD%*b%Pz+U&XJ)0QE`Hd%=LR-U|ln^gG7(;vKnyAA>C)KqXEXKs~Tz))d0NlAmTU ziDkpgOkzDr`y69iqMJhcX0&Ew%KS|kOyb)OGc$?xB<*vIZHcacvu4Q#ZMs|K&8HCd z%lT;rlUO#)%p}&6wD&RC5nTc8Y+BK>yHDOCgndto?9=5G`YH&W$m5`OL;it0Z{Ps} zLFh{_i(^3)H25-+v8W*IFhcGD(+)YAGa~WT)vZ6df^U z*$_lhou24f)L7J88ovUINStZmDmrd<2v;LUU>^*9A4v+vWe}!FDYDgu4Iv}Z`xxrk z4NjMNpYpVS_w*ftO1z1Oo)=vKouXJLYw5f6I8n?-Xpwh-vioZEHa^EEsVUnILh^xx zM2W6gizB3rm`MhxNeUXWWL)4#!NgwF2rhwPVSYNE!7~i#O?UwU(G}21igl`XlKi|K zj9(+3AXtKw!!ns{D=f*QIU%r{g`SMvIdd470g9Oo>s%_6mZ1Z)Bizmkdy#aeoF-1@ z&}UiswMB~t%amXkTEJgStQ9Ol%Cui((PC%;Ev77;i`~cyET(Zka9+1nqrQD z?J#DLk~AEZQrNd!6c%fF5HDgMMK>MfDkJ3{?;~J4@@71i+?F9M*AI&JmW;~)S1?Qa z@|=`OOjFD;kb82Z>lJH%I-6A1&;aH1goF)+P3b;A;!k3n`zmIu z5Oza9DB4>wE(2V_EbYs4QdYpWbm13R$eS255X;?+c(^Gk?7OBYEY>(2mdibX^2s&Q zL8=m6f#iJ*NRTWPBs(Ix=o7OH>>|cxfX5JPvkS=~4qGd|$79#?>Zm4Z?5hkegZ)q#q6mv>aMLFsmvb2ws zw_GHsplmzbm0X-*mI2OCzYOp!X0Zs7;Uq=a=JE>(F7D2elB0v;1T#n#0(+K<5?3a5 z?1kCPjMt=#sG=PA5EA={N?(RXDO;7_BzqrB9n4}vz_cOtgh@=9c+4rs6$7ayTxtq}Ap?8H zybzY_3uE7+AT0x2!7S|yB=7gUlo6)vmXuDByQ5MZXvxAMqAA~ou^150AJ3u;AhFF8 zoXCQllsA)#GMX4oj)(^MP?ja%G_te@v)CB+FlB3r=@@B5n3gie7PvRUTs}qY=5BIe zW=IO-+Yl1n6w=`&beSa#QhU8PHnEPCMFsy$L`EH_M01|mHiT_Y2yum#;l~97q+B3v zfp4eJpuprBl(C2y+b$w!OWwqoK{Cznfh+tF1KuHl=;BBWDPkPk$r~~4g|_4g`PIrV z$Adf}W@D4K$!3n@EzvtG^Lsq-Q({l-CNs3%WqOh9FexWIrSG(DhEv2of|)G70ll4| z$^(VvUQi&@1*Hnryci1`vSutS<#VWMw$o4t)Paf|*j{5C9oRub9Z&}wvujaV2M)BMjZru-KNrSW);(O;BYfIR zVZFpr9LiXlc?;q`4{q>FOvSK-*|fS#~~++$dj(^IzftR zo)GGw(KK=g{I$71EZtd%;-MZh<7A;?9e3lHqV?p!z8d4`zJ1L{CU z4jiDN4yXeaIdGuHI682UhB}}QROG~+K|D&CrSH*N_|;iw!~Fk#p~{=CL42w=eiPf^3Q zxi{fL6-?cMLnjPlg2dh*BL}D~7eS|KgE>&TtV0i_>yy_;+y;Bk>2>g76NE8`nIN&y z1!Zm^%cR%nbHh4-S4G$5-y~iT-6!%Ad!0T<=)l7MVX*BUluW3Q7v0GAU#Q&*97r$B z9q9jeb+|ECc)EhO(IeP_!!^dyfg?230d=4v2Nr3l1L{CU4jid5jt(59p$@166*+M9 zT9bGw;CST$mimT%lViS(XE+b$a7d zPNUqg4$w{Dj{|r3j8FC*?dLLfq`t@LVFjJhL#1?I2ad^w@uabtK9)h&m4&Y8;6M=F$L0dPwmg3D;d0Q$ve*qB61a94l8MG}buW$7D<0T^U?(|D z?z&$N-=ge_j-_2iLxn?W%F#VEg%K^w4jh*Y<4Kq7W5QAjquwp?S7^eD<2>LhcerxH zIuL9{kLhDqA?r%NmO3aBoiO7y#V5|#5F=4D7&?eBeKy+YWvvjI1auz!eN9+@yl3IpA)>KC(AbT%8pm=^DP9 z)f5+LJ+K2O=fV(aPBw_~_u_IWeR4E*NnOl-#IZd!#Tl&!a$spL43Wkn|JPCnLn%_| zF15N47KSi3yARH4jNAc3Cm^80=1_`+6qdO#NVsL@j6xH9XKl=25I{+XBm9@(*8_>8fnR)CMa1`TI>fr zO^Zq*C8pv4S&Wz9J|P9WnJ%>P_CokS3dJRQ==*{uz2?a{aCSZn()NKle25AiZU>oE zp`;XU-YxShO9CaP>;T;M{x|r0oN9_!!4|IpX9KRbEhj`f2$rYm}Ly1I}K& z8@q=;_yh8LjlDDn17&egv83<};yYN!M1Kt&E*rJ)X}0~I-N zwZ=F)aE*pKpbk{zz_l9cfI3i-1J`M&1L{CU4qUG>jt<zYR%epD^@m_tXp&2s@Zkq*DhIf#Nyd2Z(Y&ptZJ=Ya@6d#t@=vK zE}nh!niXvejs@uabslv7_DSgc<3Z5**D=uf_iv%|-s0=jdqgYH(_L3i$_p}WmPpu6pH(B1C$(B0vc(B0{J=ba#I! zboV?Sx_kWrx_jRN-F?*2PK_khnr_n?PC_mC5yyWo$|J?vG`J^V)KF4_^gM}7{v zM?W08$D9b=WB&x*<6jNk6K{gy@$|InA+DXto{m;-{_8RD(wF0{5>{-RHa+y3e~6x-ZxZx-a}XbYJ`g=)Uv}=)UaV z(0#>QpnFFhy04xO-Pe2ry03d8blw|=)Ui5(EUIYx*ysHx*z@)bU*rJ=zjbx=zijV(EZfgq5GK@bU(K*bU*)X=zj4j z(Eak+(EW;m?$_P{-EXv^`>p+;`|a;Q_q$Jp?)T4u?hgUFKe`jTKj}dCXZu6<=ii0y zT~CAVug-<;Z)(u}?K`3S`!00}D<+j8jsV+M5p`7Y@Gdo^_bdmwcG z_kCCm&w$l4&V$vP%!JjOz8hB0x)-e8;viT(`v`Z8m|`^WKBMOZ}(^ zchA2E?4Q3d^Dca1zVQ5I^G~aH4?DBFroCd_+WCtY9=Y&H-_+;0IZ)FWM+atTr~~Ri zMGnl=PzTh3iX7NPV;mjWRAah1VE>P9GhaE+mV^V!N^_GWDmtd;TaD=a&886cmHadV zER&-5_5o$R7Yx?vdyH*{Z{S`VON_xb52jkr>jpctzlvXp0qT>Y_ksasy%!AD>359n z#XE8ZKL%SqfJ&S&fO=rbtSN+jB|ptz63d2}nZ$aM_BqD3L^p->&1lWWl=+)7n8ddm zW@ZxWN!sTa+Y(&?XU&og+H|+dn@=I^m-EvMCb4XonMtfCY42mOBf0|G*|ef%cb~jP z2>YHE*{91X^i>c#k;g&nhWrD0-oOI{g3y;<7RQ1pXz*nsV^KlaW4fg4`!>nD`i*pG zuetK;72hmOq7auQYyC8z;oFXs9O0tcuS(^}d0o6euX9@jjBgT18jB?zEOSBSwlGIR zCc-Y{5i&1?Ws)up)lx_}$xhQ-C^}-yvLT41Iz7>|sIjQGG=2pZkvP-BRdn3!5Uxgy zz&;rIK9UrS%OFgVQe>+Q8$w2+_c7G78=NllKILiu?&&)Om3R{mJukWfIz_Qg*3x(B zaiW-w&?4^uW%t$SZG4VTQd71agyaJWi4tA07Dq@KF_R2XlN2;$$+*Cgf{DGT5nKYp z!u)hRgJ&4foA3ezqAQ@26zf#&B>8ze7{5k5L9hfVhh;L^R#=ipb3$M@3q2XTbLKEE z0~9kG*11$BEkg%pN4T98_9E#_IZd3*q0h4NYl{{QmMOt7w1B^uSSwh9lxe@nqQ%ex zT1;6w7rT)aT!xh0*cNY*A?1w3G{qbP+hNQgC22S+rLb?eC@j|UAYQ~iif%f{RYuA^ z-bcW8qu3(n-!L#Gk}C_f^bRA?${JP_(yVTn4y;S=yK9q^y8#>B29tkT)@A zAeOrs@o-a8*mq4)Sgdh4ESGx%<&$fqgH$ED0?GRrkRVwoNOnYW(I;jZ*hP%X0FNQo zW*3q}9K!Yp@(3FfC*wX;^AH0;`l0xA>q$s-vL)^ltKAsaat`G_qJ|iklM}th^2BDP zo(%gq(G-m)*%oGQ2rKLdMSCveGQbtY+U!DdbcB#4Z5#+1MhxUoj+9(j((7%gEk*=% z-B8=)B1}-}-_lmJDdv=ID0`|s-Rs;>85k9_lGUYLAUhk14D)~)I{x0xIk&RL!mq}e`%<$A$< zJ4l&ifGcuEVrQVFj4)-trFe?mEtK&nxnW{0p`PZ;|a1!)=J3TA0vAbG#%rHn9Tx1@B6+#QwTKuZ=55l#6vjKzR}{&*H8 z0Eunxb0P~;Qr=7|%4lLVIU*Y1Ls^#lrjeyRn8n7hhbdc2Ovgwg!nBkzw!pm+=JF|G zH+ORfCWfRiz6~MK%|kkzgf6p$LEc_3j!mp%Wl_QZ5|L2HDbbv5b_ikHeIc%}GW@t; zfRqcQE%5F9Gbk{*24yTF#W5?c5tN?S;1F z3HjB^FUNyCA!cKfw#jCS<1NuUEAx9i@Ka(>?B-@@yUX+<$zf9VJ*DTgZH80CK7xrX zz5%_RpvnV<}<>YN!M1Kt&GhrZJ8V?5?2>r~?%_u!n{^pbk{zz@8f8=)hhYo0bFiKi}aO za{nFAe=~&LzN72~j0vOLi1Ncbuy@z6hT9%~_V&n?u1?J0{dk&ks!9whwLu*){>Fm& zHpL4}pF`J`zgS|^Gs+I>z??2&=FG8wg)mt8l1Wzw(#eVfNzx+CqjkXEfw&U9D_=$u zQLIql-v|dIAJJ&vcdBiln+#*-&c%-nyab=)6A|`}1L5HduMV@Q(HMmT^HO1qW!=Md zJ;JBG6xK@|VP^>kpl;6jH3ewX{ZD0Kt&E5tg$INU<`gM`v|}x|F0lj10gnjY>E!t zBfrxj{lZv*aSv1?aN(%XaHJ=wt$8CmV6P)yQSsKqyKzf!3Pl(~T{lU}3Gjq3nj6b^08k1B-iy!M1x)GND3VbR*k)p>`{9 zAb(-*K>xq1!;QJZ(-pjp9>ESAsxgiZ9HyZTr~?%_utY;0PzNe$XmLc7QC!9|w{?;}gr!wa!x+J5tZ<@*u1TTk<`v26W)aR2WYho9Sa2WL;V4 ziVhA05vpyt8?_H#Vd+@k2&AS7J8)Dg&}+-%2Olm6T`Y^;&>?|qhas8b=A#^xJ;jr9 zAXx4aU4vbSw;4;>6&)0WGW`y5L+1+14pOAc+w^N=vzu*)Vn4A3Qbsnln@Bk zpQz8tI1ubav+3jg_N8ARx)3I~QaefY^LzSmfsaqQ4xHp1l4M{a6^#|<53=t&(^2d1V2 z$7^hQ4wyl{(m+5aaK~1?|PE3U%5`p{RFDby7 z+|SFGG$68D;vQj%=qVh917xRG zl@V{icb;OaPD_VL)BV{VgU0o|z~lbwRFQVz^mG`c?ZcdI@aaqYGYM*>C5M`zWKC(Y zAMi9SDv6Ysj00pbUV{6C6zpcY(8k*f;r}QUm*}DI3!3zrC*r^v=`cv!2j=i0Ds;FV zWKxBaQn-1y%&#m7l$f*wbVuPb+|{_>kKZiY6S_8kcj59T{gzXA!I|kWNZSYI@Nra7 zJ8T~!BP0e@^oL}au(e}d=`nRQPuzjC(qWLc56t0X9OvbTbDya4g7VW(%V$}m%p@If z_Tt^xJ^aBRkl$#`DJ2&KUI+k}}So?>a z%b%{*s)B$y% zA_uO}7)J-L)KCZ1fr=csN<$q`2P$&lY7KQj9jM5GYc$5ufonC?0d=4v2d>jl2h@Rz z9JpR%936n|YXF-8fK9c#YBj=eXKflxcl?&NGd*BbZ6WZsFwJUCg!)cL*JiufJ1xFn zZD*m`g?H9!yOL(tooai)=5Bv|_czz}Wc;q$USjs3fbE;qmbkNaf%@(rs$CR#JiT%B zQD?4SedF4*me0KD_WIgp)>^&h=H;zsd+p41$Y;x!9JXxcnwwVNdh6O-vgL=*%x+n? z#q-#n=A|4pbL_++Rbyb|h% z{0Hg_-v;%?_ksFh^P#@vTTnmzDNtW_8q|;cFVv5IJJgT88S2OH1NG(KhWd)9Lj9!E zp?>oJpnmE*pnlpdP(Nc|sGs>AsIPh&)XzBs>gO7$pZ`v%U$`FX7w-r4OTG*B%bpJP zE6#-aRrcMkz6p^=ul{TknQ?rw;Y|9SHT?e*pCdJPYa%IveT_nGW@bz6a_LZ$SN#2SNQ&KZN>Y zo(=WKodfkJYzFlwz8C6GZbJR32Sfd7KZ5!*o&)t~oeTBnY!3D3z7Oip&!B$CAy9we zkD>nJ=R*CZ=Ry7DTR{C4?}z%UT2O!W0;s>{Cs2Rg^Pv8Q^P&Ex8Bl-o2cZ7eHq_s~ z5bE#vDb(+JKGffR0o32SCDh;dL8yPA1N9Frg8GMl2KA4=0O}vV5bB@Y3hJNw5Y#_& zU#Nd>G1Nc*bEtpu4yb?mBB+0LCe*+7VW@xOeo+6`p-}(!FQES27ef8}7eoDrv!MQ? zk3jt=w?qABhe7@4zl8cPUj+4ET>|yrYz_6_eiZ7zzdzLfxCH8dx*O_$c`?-gb}7{V zu?^J!?_*H^*8`ybpQTX$@2{Y4UILBUWzd+uEi^X!I5f6+AT+i-92#5w8XB`+3XN?p zhsJi>L1X(*Kx2moL1U*Qpt19Bpt0-Apt1WE(AaZ(XzcY#Xv}#qH0CXX#{AzxW8arU zWB)6mao}ud9P}w@9P$uoEIbk#i+%@VP^>kpr7)jH3gaYfLoNiRZ=fcjj~eZhdT?h6L%^g71&;vKny zAA>C)KqXEXKs~Tz#w5bNlAmTUfn~$YOkh1pdmLk1qML{G&1lW0l=+)7n83FiW@ZBG zN!sHW+Y(&?XUvcd+H{Y~TTUYEm-EvMCa`RnnF*{XY4>BWBf0|G*?dLI?m2m@5cWMS zvQL-u&{sj|L>>pN8}bk2c>@m+2tr?aSsV+Zpuv}kj70@um+6wO=iB7o)o-LjyUmqf zulQzR5{0-dx7JVd8NTgE$q_E9{i?hiIj@WN=XGw2fbmTNNn^33gJmwL+!p3Y$VAwM zJVNG$uuRgWp;`(F=d#mu7mAJ;vup?=sm`D1S=3n6T^hdvi%6Vk;VL?AW(Zd!MqnQd zeIH2*#$^zuNGY<_h7BPj(ft_e*$qyYc%SmLfA{=51eJIb4?Qos0y;&p&aI{I(&a=k z8=*zs0m|;H(cAbOpQNU2I|#`K5)vi4Vl9r4GGZnfpe9$)kR{^+M+zqPqDF8z7#60d z;~6}|fZl``AP`*voupXj)lQP0w}bI(#1jNdkaAcilWm11X*4SYc9YPPu{&!P<1#=o zvtgY}WzsTqU~+`pNntmV&Xm){$sGDDE5EjA(O{Vp3_}a}i;1;@B}kd}i!53UEuh7e zrE{?xS-~Yp*^O=S770?$NK8}AF|ZxR4DuumN2L_@>=uQ^S{}rU*hkUL4|0`|a*y{B zupN0b9!qZP5SHr&MSE+;Wq>P~rG05m$|R;K<`~F5DN=I$7CDl3+pdSAE1>HYYkxYM zRMyY{<@^abHWW7H_xTZj664fYG24W&8+t*}-iC1*;0k7GUz(G$0=A_KzraG?#F&9t z?qh*d9S1VPoQC+=pr&VjxIA6rXNA35m{aiTlKAH^#M`L%ENrA;#t0iC$xQVv|x& zhJBo9ibiwU7G~QJR@e)Q_O^`609O!evkS@55ki)0<3P|bVjzc7q~yYqZf`?vF(RPr zhT0|o(F9SS_Su8>%I7tz< zx%@(ci@Q^#zQwOt{ z5HR16dcq{8Og!d1#}xyqC0uF>f*}KY#_SN5>j`7uq982;T)`~u3ncINyp$29?3R>H zk-MW(9B9eHA)+bYhOrnB&>zpD1R$}^eNJRSO3Ir_MHx+uCPzdAd??Fu-!!tc2ea51 z_Aq5@iRl<=M3|N`#um6Y!dyN@?B;Inz{HRg#8~!5{NF2#E>G!v7LJ(roGUXJR!eY`Q>2P$%4R}FPQ9jM5G-89D0f!#IK0d=4v2lmiV z2h@Rz9N1H1939w8W7BfL{^vXVLhirg`EQ1>+jo?`fH7fo8&Q6E2lnn7)^OXy&)y!n z($$F>ydO_fPF0CPr8cMo#@|>l-==th>2v71@)t{NdPdnH9hlQ4%$zy)uMh?+Uoz?H zKss4bAW2%Jd9)7LI}lfbcje1SB8n9X{2Sq5DJUX!TowfPtFoG)_y zQNQoh+P_b?FvfQ9vyVeg7Lg}i+jW8z)jT28L8EEp4)|+xe^|P+5XD11X2!`v#X9cB zF-055fqgZ`(SiLm)B$y%A_w-@PzTh3iX1pVLmf~DDstdJjd66~APsdu9jM5GgEclq z2aLgQWgh`JK2kdpkD=OZa zcsFhdPT{B=SkO1@AAeqB76h-*)auIZzHkt#a z%UZaQu1{VYaU1PDr`ExX`h+oyOpsXUf-*OdWzuW(xp5u9tD@`jZxSzv?h|>5y-uGa zbYOAsFxYkvN+wjui*96lFVt=Y4&*P)9q9jeb+|ECc)EhO(IeP_Lp8?Hfx|S^0d=4v z2bO541L{CU4lLCeM+XkqPzTh3iX1p%;$iY5g)-mNszL|czx?QWUg4e!W!JILFkWwt zz(e|pwco{oWvMVJlDR^+P_nEGFkWw#O>nNuI;EonLE-N2kJg(k1)oTS{TnyCwb#4Xtn`Z=}tscTjG^4zS7AV7vxjcv42uauQ-K3_tNb7+eI3X2=NOOWgjK3F` zL+O*Fu}kV=_9Kq%swvKBJ&*${QelWR7WuzcI2cNiLU)DLg|IM$vDtlaR%7H27&-v~ z6*h-bB&4uRg+bCi+?`{kv4I>oF%^bL1nz^sqyS@bKQCX>fXHr%dxRyTr*ISwklFsq z!o`%YEgT)x?h@VYIv%e%UMX)3Gnyvnz)8t4$l3>HN|YmuT`%xJK8@Q6;tlTr z{&ehC{@99cAjhH#MWt}RJ=Y7Uq)=iK4xBvFFeBYQg_oZ)(l8_4uFKVd@p9l)4Rt^r zsK|kpJ;LZ z8*eX!|D#Y`qKCdOXwqw*hy!P&!ys)Rn8Syt(BXEFNfk;;;pW{kzp^AyV$u%K9fiwq zSL1#^ezR;(=-T|%1=KnpJk0QlXSq@i+5x9@CScDey_2Y=3t;K4l0%u zULZ_{p+Zy3i8`=qs4zoKty(qg+>poVSl)qQ?H_h7f4Wwy&K@evP*Xaj4oqza&e0f0 z2hP<{2h@Rz95_!y9Z&}#b{V$(A2JGrMKo8p|%5c|&vcdJB#MyYmImIPpSg zoV*n@PWcctR^AsHr!R)a89#@{S$9C=?2Djr?o4Q$_hD#Ua6f2VbSN|~{slBHeIYb1 zzZe=<&Vt5OAA!a-w?pH)!=Q2fFQIX-7eV9Rmq6o&t)X$_N1?Iq{?NF22{dlG8ydI1 z7#j6Uq0!t18rjF7(S86l?z@rc8r@yK68 zgS;G^+!PCo5w=qTYrMacU}#R?_CFt zAK1J6;pd_8<3~c{r^i9#XMcvqFJ1$UyRV1FuXlyUZ@vJH-#rQ%e>ff*fBXwH{`^{K z{B<=n{=OSD{_#a<{PWS!`1f*X{O7OG_}}ZG3HO5LwB4aO{Y%i?{4vm+aRM~A{2Mf9 zz8;!euYu;adq8u$FGF+oW1+d@3TW>1cWCbN259bfZ)onZCp7o`3N-hA95m;i2+eu_ zfaX4Lgyw#0p?Sbw&^+*~&^-9@&|Gj5G#CCKG#9@Knupy0&82%o^YE`hbJ-K1dDO|! zJo=x|Joe4dJpM*#o-hZRE4~iRlb#68Q%-^AssDoJX>Wn%88<=mthvx!^$lpA^CW1V zcPcc`|2H%*d@D3BUI)!f=RxzbZ$k5mCqwh9mH4~Vk9u&={CmLu`3uwU#wX_U&RIF{ z-1%q{Z9bu%4tnjc#p)b8Gjs;QB;LAkDqJpr?bV=9qZF2AGH`1Zq=E|>Ee6ui#LR^+x>!?Z^8=@h^~N6 zQmpf8CrQuS!T2@e34$d^IV_XOw!)G$niT@ON$APgoi&Sb8K9Wiu+F72X&E{&Il}Fv zup3Ed%4yZ9>=$y`X4s!?+A^1+%m-%}H4S+tP(!U?Fc}%s?!6GveWRmVsTwxD4x~P zLp2XE5TqZ9Pq&_gMCZ1|ePXp6<66$4+(*<9<8tmqudzI_NvS8pK29`6qq%Ggvuy|~ z>;*-8TgGL8D~Pq(h2-c6AIL8X67ThXSN z^CVT2qs}2q`^fW_iv$&vZHK#(i!;nJz!~b70iMMy79kRxqzKzwej&ld-6>LXba0$t z2B|_|&r(t1%3K|LVKy=2HTgwUQI2~EiG4)nUxr30Tb0=^gynic(cX@68Q=g&9&?`K zihB6-BBqHv}EBB(Ufn) zSPTg0k7rQ=kl5xvC$bEV5ND<@M z&b<-SUT906kYBC*ay-ZrVm3Bun{1{y-V(jDGQYV942MoQ+iI@ zW;jLcBbdnI8_?Scsyt9w?ga%hzo1m1nipeXL)MIirF;%G&5j!CfI3i-13PJqqXRo@ zr~~RiMGowup$@166*;i0hB}}QROG;J8sq4|?i%WVI#7`VduXTw>Oe&f?5Q!14(z3| zX*pp3^BsO6_uujSH$&L%JIY?bm@vAHC_lUddv^_Mxb5L*Z;xE*>ckA*kEbc8s>GmD z8`J^gZ!DN^Q@p_RIdon5izPNaqwJ6l%;^$l&K&z!2!oX`nRIm^ovbL3BrVcBS_kYM zh%3Rn@?|6u#R>)fjc_pX5smhJr`qRL;OYk{95nM)BMjZru- zFBQgE);(O;BYfIRVZFpr9|fS z#~~++$dj(^IzftRo)GGw(KK=g{I$71EZtd%;-MZh<7A;?9e3lHq7CH0z8d4`zJ1L{CU4jiDN4yXeaIdGuHI682UhB}}QROGUFN_r!_dq2A7mf-IM|y(Vnm4io_B!Gf6>m+v8@B|fa8wQ~=o|Kr zKd&(h0$8xXQ`B&6?)6=$g2_9uux}U>B=-IoIY4E(2s%w0&4JQoEnG;~C$EjTjrN{X z>)=Iw!k9%SNGx^Y`X^~6Ds6I zH?qAKYPSLh@)za~^#8j$+?XpoUBTPv5$wRB8sq4|VH)ayI#7`VOElC0b)X^#mTHWn z1BYv<1L{CU4jeJ@F!_-}nQv-Up#$z;esn#ra8HG@>lik0u@jgGdk$zb?ZC2Bm=wue zp<5_fmIACb%NV9~$_?WHS&Banoc9@@Sca~3p32yf`ozh+n71TEO7(Z($W$0l8k^~3 z8Dw2q=!y;w1QDujxEr;PSUJ`=JgLu#J8)Dg&}+-%2Olm6T`Y^;&>?|qhas8b=A#^x zJ;jr9AXx4aU4vcdemQ)LvMV~M4`uotN%HMr8N5GDippd*;nDcR3~V^U!Pi9Z#DA!B9h(6!ig zu@s$9`oXY=67F$*zcMVMuI4Hn7~b^ZC#(2gV{yi@Lxfyo(}vcb=$#D-$;tW0$jnc?wz6OAr*#5bAmyPzZaK7>64?eOX_0wBaZE=Db8p;kOM1HVTd#q`M*{; z7)p^scZJo3urP$N*?n+UW8@APIspL{HiuFqq_9kdLDD_konxi3fgCt76^2Lz?t{Oi z0Aq4LFJIDt$Zm;yge9VFYrJ#_)+JV#4VUV^DbGpH&FYV7HsF9W&YJ!qA zrNw^0)3m50QerX=ki~cj?h{h5o9RLuZ!d)ZqflI;hrTap(rccG181beAZ;I*!-uHQ z;dYQo6-r9s=G`*CvLsMq(hkrah0AbP<9l>s9xBXGQ#zy$Ol=3w(HKVu&ec!{)Paf|I8Q?zPzNe<;Cu~rKpm*afeSRo z(SZv!)B$y%A_p$gPzTh3iX6CDLmf~DDstcwjd66~QVn%L9jM5G%QVyhb)X^#F4s^8 z)Paf|xI$wb9k^0M9Z&}bS(0t-!q50$$(0t0@q4~5oK=T>*hUT;Ogyyrq0?p?>4w}!m9=_lo(0t(=q50yq z(0u7$(0tifq4|o(L-SQ9LG#Z4gXU}A1kKmo0L?e-4b3-x4VrI$0yN)xGBn@zPiVg5 z&CtB-Mrgi!4m98Mb!fitiO~GODbW1jzo7Zyw?OlwH$n5`bD{Z(Z$R@?PlD!WPKD-Y z{|(L0zZIHaTnEiB&x7Vyz6s5*JsFzcSP9K<{s)@hej7Budmm_ie?ByS@GWTm=qb?r z$!XC1>3^a5^S49ump4Q6SNlNo*WZTbZ=VXy-=7Z6Kl~4xe|iTr|8fg7|F$nQ|Nb3l z{@>G}`L8pe`ELWw|GpENW<6xJ{UDq6UC1_jI%Hd%37P$yEZgcX$Y$LN**5z_w(a*I z+x{7l?Qj-kJJlfD`CX9hdK+ZB9{|}N--m3kXF@h-6=d_KK{o&0knLNCZ2toxJKzV9 z9rP^74mlgLh0`Hh^d86#Z9ulf5V9kl4cU?BKz8(IkR9`0$c}45w)|koPWTaI zCq4(Vlh1|h)XgDV`98=_&mcSV5XjE@F=S^y7qWBDgY5h*AiLoGkX_V*?2-kLUHTKq zE`J_mSDp{q)iWTw<^zyj*M@BMLdfp*Q^@Z9e8_IN0J595glydhA-lN)+4@D0-TE`g z>Mww-c_C!2tsrZE2(tU$7qZ(ILw5h4L-xQsAbapdkUexJ{x0>S9^5nk9^S78p*jMt?46w`<-M0@Y>%L&H zPS0a(GkgR0+E`)?ws|ns23|MVp}kf7N(@k+E4nWjP}Y6HV4Ysa*j~INSMX!7E0RlnjOD~IKK@>FjGLf;UAnY<-()E0s+`IaXbZED^^6M4fEKH&h zm*v*_X+FcZ9Vt1&MYUg*mm}wO@&3HdZ4ofONg!z~mUOVp1(n;v90{2SyO2l7ybzX2 zx-?WvA>mwhn(ji;5o4AOK_u1r6FrL>i@HnWS6~r|6D?dt$IT4kYQzZagQ4#uNx`@b z!W1b*w%V{EWF)#DLp{5}=@Rc#p7!sae}|wFZ{nfnMOQ$lDAu{P^j*4~C}tzH$U8vU zeKmR;pW~C%lx+tg`9MOVL|3fE5mH9XBm>ms3L3IxT;NE-#9q`0E(gQH^mIIfXBg0% z@B##)E1;7U>%7`Y((`sOevNp7U;ERoE*J_5EQZ^mQE zZ5_gLy`X4s&A1G31+%m-%}JTWG{qbPxhF+Rj^83j(r(-JP;>=!y<+W8XOqer8lap% zA;*Toru;rX;!k3n`YL9d5OzZ^DB9aFE(2V_EbU8kQdYpWbm13R$eS255X;?+c(^Gk z?75~WEY>(2mdibX^2s&wgH+{o1(NqMAVF@SAlVVgMW2{uU>7ki13ZRUn_Wl_aR}QZ z$Rlh_oQ(TW%|i?X>4)OettTPTxh-*@SnbBRmUAfg5jDiPoIBBLEKh7w>dCN=6HU=* zF5ALv8^Q{ELDAlpaT(wWVr_OIIXXhfa%~(48b%D{P>PgXSkmons4YeWblp(fEF^;v?=C1NfqU&bI8&@^1S6DK?P;o;jZN346_VyhWcfIXEBRKhy*7o!Zw#*NN{m? zij*8394DATsu0+-RFt?fSI1tMP0V;rei2oa;~qj{A5r<2p;5|KWwr}pxn5ATw_{ue zxPn>Qm*%95Fy-8ufk`RkvlFDH3Xwa{k6H!qC;=Q#%%mo159QLXuqS_7PE7@6JHcwn z#W!Y_0nSjr48l8L$_GoCmJDIaC}PZ@A8CdBb&|(0$v{j9i0wkj6CQ-FP5n+JMN-OJ zNkxRLc~X#O`w*7v1@rA7Ws(7|$Q6m5fs!)9l>L_CDRQ?^#sekU{b1@~783&I8&Xf0 z#FUB0oaeY=Ahm=`O+heZV9%Hx!g4)f>{}G1Wq>P~rG0_q{hpUH!j#>T(kXIxREh&F zSvW*A<=Ze80|NTvS(E@Iwz2MOd%n}B9d%ZX|v5u8R1^-J#LLH|> zbGF$bgl+eQxWdZtTvqlP-54pij8 zP8#Frz|I=#fI3i-1G{Lb1L{CU4(zI-4yXeaIk20?I6APqhB}}QROG-O8tQ;LP>}!5AVRx5~eK(l~3|1MT$r5fVh+hBf@JEmAy9qLZ0(Qu0QJcom%_% z=@!P=4u1A=$jKt|q-(oQkfNF=ggR(6jobl$ZSD_CcNU^}sK?AWS*TdY-8iOb139p- z#yC2#pN2Z14pij8{u=6lI#7`V2WY4R>Oe&f9H=pl4jiPR4yXeaIdHJXrs#k%_^s?C z0Ehg)f^-dp*z~a}I&hEtPKWdhV+F=NP>H~Wqe8=xo}jkojqHHEj(A1ITNCfbEx{=q zl>-az30?Acu}7)W|0XJ3tdp=2C__gjXpQ719(+*UH(nt1<`#XFR|C@bA%2o?i~i( z?m@|f3VG3uZ108It-yi&g}DR$|E>-<<_b?&@HTn`J8-DRI682chB}}QROG-C4Rt^r zsK|k(8sq4|;Tr0II#7`VM@&3Sexy+5n_5-qfcuvpUC%4rQ=#lSh7G&e_YJ~{O!izm z^_t64VNxV>g>Io_SsDbjSvIk;^fG004v?kzi@=7@_{1`Ft@BjIj@0K?QsIZ~Gi)JV z^Mo8YG8M*?#%B6h23c1Yx}t*vL4;}>?ndpyS6&)Kk))>PK^-_M73j6)@q-VSgD#fE zZs?G}wZo7|o(|708X;FW0SAJeF4+gU>wY<0%C6|3K9s2wY0C9zaZ0FMF9(iJh4G|I z_R+VL!l-vk{1uw8BJ84ya_SwFo3I1HPBfc7b_cSq^!uoTBGCymUQ>Re6!kPxRwy%o z1IMJo1QLHL2t&ro)}d>$>tZQ7q4a}c4<}sYHw45T1r<3EZf}UwhMyebuuXI1*rCI0 zgvp_g+|&k-8#>I;lRBslOic%l*VyzNFoS%hfkcBWQq8~)EKdji^SSNdr*9-hVF9jS z*msi(Cg*^=3HwOiNO5&n5pA&pT{XpJS`XyF38^qdniC9S{JppwN}n8!T~ZgbA8~9~ zO>su+fgD(o3PYr^$p5v%!BC16x+|A%$fsjIk_! z?9(TQ^|1jQI58E5NCfVKzoYa!#&c( zo}x)Pa8fc1vi5;<2tei%KFTCgT8EjF;d(AqBgcF0}FXLij%l#U*;^`+_FD=7~6P zMmh}A_JKKkhzcEU2bol%q!e!6E%Pf&0wpHx0Nqiz40ko|_v1Iq_Jpp@-(9%8Nx$XP zU2tYP4AS<2IeZ)y)DGK+$Owr+75yO@CT#6kS9(kx%@cRvtaKQp?E`c87{_@z;@l^y zyrBH_)ACu?C^Jb1oV|EAb`O8>2juq}dua{^%Hp76N#O;;WEd(mwVbE}tA+|Q)YPg~ z!_EzPoQ~xk7}ow_=klj(wd(Al!VEQ~L+ZfPcHkV1adhBZ4Rt^rsK|lyG}Hlgpdts( z*H8!4fr=csKw}&oxKKkKPzNe<;35rmKpm*afr~ZN0d=4v2QJYVM+Yv|PzTh3iX6C1 zLmf~DDstd*4Rt^rsK|jUG{(_^D>c*sb)X^#uF_Bk)Paf|xLQLUPzNe<;2Mo_bl_SI zbwC}c$bsuL)B$y%A_uP57)J+S`x?Mz0AN$?u3C*S+*z9j(;dI1?Mx3CRa*$WEljhT z6Cr!}V`{VA?41^WvbM9(?7};1wOvW`s5P}cU~{)WdyJ{=N%*ldYI}*h%^J1$O8DkUj2ukUilUkUi-v$evPz?5Xd9?CG~b z_RIqyd)D_Md(JZ0(gMi7{1eE&`aH0J5KM3E9s+2-z<>klnoqvS0lSvfsP_vfo_@*&nuo z?2jLU?9caw?5~R<``gbU`^O!S{qrKo{yh`2|9lv-|J@H-a458Dzkt^C7eZ_Ei=j1R z7PPkf2()J24y~;ZgVr{`gw}R1g4XOypta-H(Aw#v(Awqx(AsSYw06H6T6?}2T6 z99rjG39a*HL+kucLF>YYK@gcpmo_RpmoJn(7I{|XkGnjXkGhIXkC94v{wHf zT5Dbjt+iJ}>&6|Sb<<~{b)Sbp>z1RTwf+y#y6siaYFq=YY$s^7J`1hR!=ZJ*W1w~W zAEEVtJE8TUYoYa!ouT#6&q3?qkAT)AkA>Ew{sgVZyc$}MyAE1U*acco{5-Ut{77g$ z^*Crf?a$D9#%rMUtm~omoL!;y+%G`u`HzCu9mhlKg@1w8i(d<^m#&7^%Xfp;E53-o zOZ}(^_sqWs?4Q3d{ce0>KJT2B^G;rO+oIEMYp!42%H}OwymawW-_+;0IZ)FWM+c^9 zr~~RiMGj2YPzTh3iX7NXV;mjWTw|&^VE>P96JI&amV^V!N^=t=Dmtd?TaD=aEhZ86 zmHadVEOSNo?E}iXFBq)T^BCI<-@v^#mKcL=9!#}?*9~@PZxz211Jvh=?h6K#bzd-8 zr`IvI7w^aw{1|Nc04j090P2AyGbR!CmHae=2`n3CW&-O;+T$4865TwcZ$@i2rOe-y z!34hDFf$WaPtqR8*p}!DIAexv(58D--f|LQznq_DFo9*m%uHZCNxL6|9nlrg&gLsx zcF)OMg|P2wk$t+HhrS9zC-OLG-H?AE&l`AvKoI)U%i>rN1r5GTWGpHOyG)mKJ>Mqx zu6`pO+HJ1D*Xlo2z@05!RShAbHuI8rdN z7d3**!LTqr9naty2J|Mp0D1Ct}%P71q`bf%mpPUg^OS^2d^iw4V-U>I7!UrekOEJ4b& zUu4l@XaOyzES-zp$OyE(2V_EbU8kQYJA?F~>meNs*G{x5$yS+jcz^ zT>)LMSo_o2q_TzvDCbYev7xXjzt4~OlNhJIirFTF-Ovk)_BM>m09P)iaAeGMLFsmvb2vpZ@EZNLD_b=E4etsECZaOei`6d z%wiED!AXj+&E*#oT-==^B}WIx31*Ng1okWyC9cfXu@`0&GhUNlL>1+@hmhDuRQ_dX zl(JQs?Lt_t7ZmO77?%OAV3zi!IVmGdIk#qDQVRL(1Zk;4R>3<;0LK$EsY%*H zxwI?n$)A=}Q$g8Iuv&8QjhSVDGt@7G@D7;r!BVCrLzps(7&GWcS|NX()WPmGjMPg^5q>M0SzomGJ+%1&x zKuLB#m^zrngn;>m)DtE#W#TdCIj$H;E#XpA5DXdEGiHadTu&JL76oY;;0k7GUm$tE z=cSA=Ww)esirgKQ;y_Cl4iQcHHjKr9fc|(EB>;(S?sFmwQc~VbD#~bLG&v#~;6quK z`=*hlJ($JDu!kvIOH9W|Bf_+lF}A?H5$5tKVmEhl2PTH3Fun~T(al3ToP;j3ghAe3 zFOE&DV`Wjn{}Pc<$0^aAZFUG@+kGLfurmC(V1Sehq%H96{4*#pxdvq{BF46h$k~!N zF=mjP=J&uAeux3@kU(^CB!(0*j_uqVG3|x6sQAoB}K6{>kL7B*zf zSXj#EP}A(Fp$@166*;hz#yC2#vxYjL4pij8E*k29I#7`VyK1Nd>Oe&f?4~h}4(zU> z4yXeaIk1O@I-m|zA;*WVdl)S ze}ynu`I1Rj2hz!k0!h*$&7*a|-hsFhyenTu5>c#B;NJ)bBOlRd-*>8QpPLM0=FY{B z4ZH-O;}a3~jRWD~3$G5dsL>dO1M^a0jAh-!bv?qTy%g3<9OY4q!l>pk1tW97xh*XB z5bsG`TMqLr=dMkvNA|K)a`F5`*!%H8JwsrAMDwkLX$wN-lYB~%;!!&wE+xW<@R~$r zug$-Z=X{atkNSP5*8Y9Eg)z2+pM4y1vWPtC+O89%sOAZw4jN4(cfenp`@_}-%YK)@;2WhAS z>Oe&f9IUY^I$#WbEBgq*A^)!+T>~LDeQb&j+#|o!A^pNwfpHI1B5>iT&~T(DsI7S; zJ7BLPUQzMZ#Jh1za0*A|z=FPE|M>G7vmk&43p_;)*XCZ|g({f50}K0xF+pPQkC6jZ zmW!a%w9ydbba#Lh}&rIIkgU6)F+HtWP-#(7nHeyER$ZN&yDK~;Dap#zJ1hrzacP%@!HUUVbdd!cqKa3FtS?m+*)tHX`C!qXMJjUK@c9I7#n z4jiVT4yXeaIj}@S9Z&}(I682+hB}}QROG-B6AzOgDU|u9Ruwwn{^dv4^9uJ= zD7%hf0~b4iiLmE@Hq#C)ONB|1%oVzYl4U7?TBkQYr8LS7>j2#Z{y1=l&-i5D(S9yt zN9wzr9#+s9T~tc0=pWU0LXg4h{qns%^L%wGUr823g;Tq@syAa8xSL zYs=#YA1()7EQ{UHA%Sa$A(?0lS9jA$z2bo#2zHXgwQTV^U!Pi9Z#DA!B9h(6!igu@s$9`oXY=6E5-_0^*K>iW~^HH^gbf zPY!X|ra5x#&|x;hVyGaF;bHLq%eI#$BxVo!|w%CELn&L982Xf$qR2U-72?jC#UR(~P zPmabesf*c%IHUDI4y;IpA<|gn|61W-C`Ah06;>C*LJV8E6d{%xBXq#fZUj`= z97>Up!ZH=cSQbC_>663y*Z>Zkm=C9% zFW(wmnV-{Y13KXT>D>%>6WuC6N-7aeyqwOK_i%g569P+IV{*{2ztl z5NL6ctdL>xFH9R_Lpz#KkAg$}oaOsY^)3ODbT`IRMs5|eg-?kHS_yBhcV@tb9P zLf7W+E?nNE-*W0MI5QmvY5Tw&K8^}%hwVdTgv6kV{*Vk4wsx#5J*JN4i92vsItBJM zPSk-_LxmY?YSpS?=Y~8^$MOygYyYrw`O~#pb@otUhMLkLbzo{caE`_}I&iLrI-m|z zVP^>kpt&zr~~RiMGjn`F^&#gsG$z10~I-Nk%l^;4pij8#Tx2>I#7`VmuQTm z1D9&31L{CU4qT?84yXeaIdHj#I-m|z};yX{ZD0Kt&E*t)UL6 z0~I-Njm9`SaIJu&H)etwtE`tWAUIj^EOD zrU#6wEd<^crdiF2(7N;N+H5y_r^QdK?JP9A@XlIoSJJ%ppxPd=x!d1*{l{v1GX7j` zFEM*i!1hgQOWawzK^&h=H;zsd+p41 z$Y;x!9JXxcnwwVNdh6O-vgL=*%x+n?#xzy>&Zi zz3mgwddGvHb=MKlde?8D^`4hO>wQ;1>jT?E>w}+!)`uSqt&c8)*2jJetxvohTA#WS zTA!H>t(E8@5q4n*DLhHLnLF;?Jht>~X z39TPp4XvN-2(6!f23kLV7_@$QG_>yi1GIkqDro)o8fg7~CusfQv(Wm}!=d$;W1#id zKSJy8*5m)X7Fz$>8Cw7T9JK!X2xysOp$&h6_Ow?+d$a4Hy~Qrjp7D8TZ}muM&pHm; zTmKo_+r9?c+g}gu9d?EGj$eTG&X0ojuE#@rx4%GpkJmzbuhr0=vm3PMei7R99}Vq& zmqUBMze4+f*FpQBdqMk<-J!kUOVD2Q7-%1Q0<;hN8?=|c9@MgKL;IM= zLi@NC&_4d}&_3Y}&_40r&^~!jXrJ;GXs>)6v`;?~+GqR&+Go8H+GnqY_PKjO`@FA0 z`+~_ks3vz76f?Jr&w7I33z|{14hMdIz*$atpLywlB0_{vBw)@@de%^9*Re+CclY z?}Ya2*F*b_`$79n--Y&Do(}D|oeAxC*uP)jc^9I-m|zdL3hX@s3={2>YHE*{92S=&K-fB9DXC4fzN1ynzP@ z1fegzERF?H(BR8N#-f6-%XCTC^KEkP>NnD%-R8=#SA4TDi9%eKTkEI!4BvL7+AZVPiHWFqWB9wGBWSSIPxP%VXobJ=OS3q?na zSvCZbROe6hENU$3E{$J-MI=tNa1|XlGlZ)VBd`yKzK;|Vxyia-BzkB{2f=axJhn^Q*0iB{)=ho79>2ji&jnE?R0A=^p=xuzCPf}C19fafq z35gP2u@*;288MR#P?IZY$dYk^BLx$CQ6sn<3=7lK@eH0}KyShe5QwgTPExG%Y9~q0 z+rjuX;t7H!NI5K%$+p6hG@2CxyGiKD*qt?taT%bP*|5%~GHDq)Fge2Qq_7)FXUb{f zWDb3nm0w%5Xs}EPhM@)g#l%{{5~NJ~MHVfF7SLkK(z)1;tl$!)?8dfuiv%fWB&I3m z7}ySD26>W(qf!ccc8kJdEf3;F?4#)B2f0c}xySnm*p9pzk0rNt2+Q??qP;caGQbtg z(!Mk&WfIdAa}4C36e&4=iyTS2ZP!E570~sHwLhIrDr;zfa{h!I8w#89`}~MMiE-+y zm~BGX4ZWafZ^O6@a0RopFU?6=0o&4rUtl3`V$47+cQfMQrlhdvnxe2+<8W9m_XNr( z*T@f2mD3eS-p7ChxrKscMyz1urYBm?n5;XF%YC5 zichzmghc1I#C>A58{=Beq1;E*5aV+0M6aH*l8ZCUGQb(?mjRx|EEXXWoTLcbTz(uhddto*)<2Ct3R8fw52#I|};E zEM;0UgejwlF@t`j74p|f9>XL9F(Dwf3nfo@5V|(?JCPJgDQ_he5whk?4@S z;v3N03939$SndS{GQXfyp_&(CVMEr8g{6EBHO-D1>VP^>kpnwvjH3fPYp4V2Kt&Gh zqM;6`0~I;2tA;wD4pij8ZW`n0!0sCAfI3i-1AAzw1L{CU4(zEhjt=alv1vJA|MMMw zA@|?${5M0`?K{d|z?d+)jVM371ABK3Yq;&FUG`-jAm#r>exDQXA9(<8LgO zZ&SR$^f`20`HLksJ)`W94$SEiX3iY@R|tcZFPU_8Af2ozkR&bAJX#0r9f&KzyYgiu z5yc7x{*7=j@)3>peW%*?xydkQ?p*xXz)SEsJ`rKxI1nDb@aiy&8jVpnFfSFxSk^sU z*CTw|OJTjlQ69A@jA|ZJFfs?6+rn}W@t(xBAFQX-59uSrz)+WZT7&KJ4VP^>kpuf{ zr~~RiMGhRGp$@166*+LA#yC1~kcK*-4pij8!5W*Q1IFODvX1~9^8X6bH4tLc$EN7O zJ@Pvp(l3k^823OW0vC=74M%!{+L|}A1NJ)N6%}tyyc@R!r*KpbEa)5dk3X+53j$cM zz*E$4ZSM75sDjBmu&{3!6D0Qj7&$;?xd=K<8_j{zWi4Dt*C(%yxQ+InQ|sVGeZrVU zCP*xFL75xKGU+w?+_(9yI@i6(3LYZ%BRiOj!Uw(8wuW(O=vg;T&aIq7Z2zw4_Gwr~#RG1XWT%lViS=J3W zy;(NVv2N>>X9vhq{Ba=ZGd{5lUF$rRu_N`oE)T+ruqEHqYCs2$Ooj2Jv6()WLDrRp zuIS)E5TV+JyHWe_6_$?mjX-LeumeY>0=>38e(>RP(8aRY4IL7=b{LW=Za&IE*;70z z2ZH4;(KXnGc$=}5UC}{7DAVr{H{||)NQ;$CJ8*O=j3-^PkG`c8M!j3&uh4`QNC|;p z{fYXVj03?=G@Cx&Z(sV=)Ct$%O0Png4CI53U{a@KKL?IUg$X47R1k)Ym90b9V%Nn| zbVBI|!yZbw$MyZnu!y>vt8id=(}$m|;(Lw78OIJCW+O}vedMM#c-+uohMv?xbzo{b zaJ+5aaK~C%#KS5A*6^_UO{N>oy{IQk41d&d1KQAvTzD8&{b=XyuXgvuBP9ABPk#3*D%TF0; zn2~PRv@64{nx1??ZD~jFi6{nIo;sXm-c58)JRJXH9^Um(qcd0X_yQ7A6aL*ExP=`~Npfiu!!khTxZ;X_pDa68DP3MHj* z^KO}6SrRBQX$RS&(0181efAZ;I*!^b$z%Ms^3QRM~Yr=OP3vPPLnI^gWZyRm!t zgFhg@*Vs#QFi;i;6-x>)5GKP=p{eCW9auF~n4zXttr~W2$m4V@@4&G34?CAXU8_}R z4;5ypDIHP=rnUp;XpEx+=W3_}>Oe&foTs4<>VP^> zkpmZLr~~RiMGjo7p$@166*+K;#yC1~sfIeB4pij8Wg6;$I#7`Vmusj4>Oe&fT%j?J z4qU0B4yXeaIdGMRI-m|zVP^>kptIgjH3hBYN!M1Kt&E*r=bq00~I-Ny~a2? z0Nd99HUj{gYIoIYgyGKGG??!AEp2Cdz^K|n;B8@=)tm_J&&{sQcC&X{d_iqzq1lCZ z)@r+w<_o{8?E#y+{p~M5uC^!Rr`7fnvj+ui-=wz0owWboMy|I{O;v?Eg;a9Jn4j z2k!@+L%s{0g-?gh;xnOhnDuDMUC=rFR_H9-A38^V4?0Ib13Jf^1)bw-&{_U2=&ZO6 zIwu_fos+*0ol~C)ozqr9=ZtC4IrH7nSyhM5IR`@L+#f*a{AWSu!n2`s@pR~1@*e11 z)_~3x2SMk`A42EqXG7=ObD(qmX3$yvUg)f8LTBy4(7EA9(7EY3(7DgK(79!E=&XMq zbZ*O_(>Me=%^yRj^<3z5&V$bVwt&ve$aWtq0o8bFQD`07eeQ) z7enXmv!L^ik3i?H+oALB!=Uq?Uqa`7FM`eoE`iR6wua7!KMI|X-XA(2Ujm&^+zp*i zy%;*5xfD8|+XgzH{}^<>_yFj9c`0~-3LPF`-em4 z2fv2Sk6sF$pIi=|pKS-7pML^6zkCpMesu(Ne*GKh{Ptzg`TZ66yVQ?*aL@dE!2bCQ z)BnGnF9EXiIL@0TMS%iuQ6wdb$Ky(tDFb@~i%U3o0Te}2q(qP+sq=C12yAH&WOspC zDs~*lj$_A_N-C99%CY0ymgCrQuF6p^-}e#6j&oHisZ?Uek>fa)FWD+5nRL%g_w@h& z^NxLs_v3%q?&ACV>+Y|6=6$oXKL}RwbNEF6+_R@!k1efDompF7X>V?{7N+N?=R;AS z)^=hhsDo~RGZ&Dja1#VE=Z3@8u=r;3}^VteAI^Ct^ej77;GtYGr+JAbe}#Tt^0t%Dm|BhV*Cbv+Zdt^HhD1C6&^R(qPn1R>Dk73qV`w@N}^hX z^v!6@wdDDmGT6qq8>VL)yofPEB8d zNkq<+a1<@KH=2(TBY+3PP{$-0<0^<<#1tO5aYFQ%=)MfqV1nmm_EYT+doS)GvcygT z40%x%&@;+$VJv-@E-Q-O1OWvF$osEGy9qu$iA^3V2uTMbQc6_CSZpC?!klD)oI*fN zkW2%7Qe;vsaYU{FN5C9D(FO^Hxloh#5QdU!0>>`ttJrYwF=NLeRF@s`~niEqJdsfTD zax53(L9C;w78^OrP`SqQ2tY-iOu#aCb2P~Hf}(sg<0`-roTYjBoTN!iU7TYe=j4(y z$Ga#bX*N^?6jcFztsIBdS)?k58psz{C}d**t~f8Wgq0ZQzKXjg8cgT~Mfn!SRe&Qn zOY`zMNh@Ipy@de)c@kp=Vz}=S58ow;J;#)Z$ zk;90AY|15NE)MCo8!C$y0ev;b;Jn2S3d1fTqDjdYlN6CpJdYq9teA&fN>D%^DqNMh z)WcZ@*hBRyz_mDwL9|RxrU-+tZb;

|9djXyMes8BCQ7YmiD59~R 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 diff --git a/webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif b/webknossos/testdata/4D/multi_channel_time_series/multi-channel-time-series.ome.tif deleted file mode 100644 index ebf7100d79079638933cb88bf1159264fc0619e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1578825 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 diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index b0fcce9ab..2cd6200a3 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -214,7 +214,6 @@ def _flush_buffer(self) -> None: self.view.write( data, - offset=chunk_bbox.topleft_xyz.add_or_none(self.offset), json_update_allowed=self.json_update_allowed, absolute_bounding_box=chunk_bbox.from_mag_to_mag1(self.view._mag), ) diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index ec49a9ac6..1c877bbe5 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -188,13 +188,18 @@ def write( ): relative_offset = Vec3Int.zeros() + if (absolute_bounding_box or relative_bounding_box) is not None: + data_shape = None + else: + data_shape = Vec3Int(data.shape[-3:]) + mag1_bbox = self._get_mag1_bbox( abs_current_mag_offset=offset, rel_mag1_offset=relative_offset, abs_mag1_offset=absolute_offset, abs_mag1_bbox=absolute_bounding_box, rel_mag1_bbox=relative_bounding_box, - current_mag_size=Vec3Int(data.shape[-3:]), + current_mag_size=data_shape, ) # Only update the layer's bbox if we are actually larger @@ -204,9 +209,8 @@ def write( super().write( data, - absolute_offset=mag1_bbox.topleft, json_update_allowed=json_update_allowed, - absolute_bounding_box=absolute_bounding_box, + absolute_bounding_box=mag1_bbox, ) def read( diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 790c14744..115f0cf7b 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -140,11 +140,38 @@ def _get_mag1_bbox( rel_current_mag_offset: Optional[VecIntLike] = None, current_mag_size: Optional[VecIntLike] = None, ) -> NDBoundingBox: + num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) + num_offsets = _count_defined_values( + [ + abs_mag1_offset, + rel_mag1_offset, + abs_current_mag_offset, + rel_current_mag_offset, + ] + ) + num_sizes = _count_defined_values([mag1_size, current_mag_size]) + if num_bboxes == 0: + assert num_offsets != 0, "You must supply an offset or a bounding box." + assert ( + num_sizes != 0 + ), "When supplying an offset, you must also supply a size. Alternatively, supply a bounding box." + assert num_offsets == 1, "Only one offset can be supplied." + assert num_sizes == 1, "Only one size can be supplied." + else: + assert num_bboxes == 1, "Only one bounding-box can be supplied." + assert ( + num_offsets == 0 + ), "A bounding-box was supplied, you cannot also supply an offset." + assert ( + num_sizes == 0 + ), "A bounding-box was supplied, you cannot also supply a size." + if abs_mag1_bbox is not None: return abs_mag1_bbox - elif rel_mag1_bbox is not None: + if rel_mag1_bbox is not None: return rel_mag1_bbox.offset(self.bounding_box.topleft) + else: mag_vec = self._mag.to_vec3_int() if rel_current_mag_offset is not None: @@ -177,7 +204,13 @@ def write( absolute_bounding_box: Optional[NDBoundingBox] = None, # in mag1 ) -> None: """ - Writes the `data` at the specified `relative_offset` or `absolute_offset`, both specified in Mag(1). + The user can specify where the data should be written. + The default is to write the data to the view's bounding box. + Alternatively, one can supply one of the following keywords: + * `relative_offset` in Mag(1) -> only usable for 3D datasets + * `absolute_offset` in Mag(1) -> only usable for 3D datasets + * `relative_bounding_box` in Mag(1) + * `absolute_bounding_box` in Mag(1) ⚠️ The `offset` parameter is deprecated. This parameter used to be relative for `View` and absolute for `MagView`, @@ -220,6 +253,11 @@ def write( ): relative_offset = Vec3Int.zeros() + if (absolute_bounding_box or relative_bounding_box) is not None: + data_shape = None + else: + data_shape = Vec3Int(data.shape[-3:]) + if offset is not None: if self._mag == Mag(1): alternative = "Since this is a View in Mag(1), please use view.write(relative_offset=my_vec)" @@ -252,7 +290,7 @@ def write( abs_mag1_offset=absolute_offset, rel_mag1_bbox=relative_bounding_box, abs_mag1_bbox=absolute_bounding_box, - current_mag_size=Vec3Int(data.shape[-3:]), + current_mag_size=data_shape, ) if json_update_allowed: assert self.bounding_box.contains_bbox( From c354dd66c1a8a270d64ef9dd7afc65a5be28f1f9 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 11 Mar 2024 11:57:44 +0100 Subject: [PATCH 36/41] Add docstrings and use bounding box for read in nd case instead of VecInts. --- .../dataset/_utils/buffered_slice_writer.py | 2 + webknossos/webknossos/dataset/view.py | 39 ++- .../webknossos/geometry/nd_bounding_box.py | 270 +++++++++++++++++- webknossos/webknossos/geometry/vec_int.py | 96 ++++++- 4 files changed, 388 insertions(+), 19 deletions(-) diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 2cd6200a3..8d8911a86 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -186,6 +186,8 @@ def _flush_buffer(self) -> None: section_topleft.x : section_bottomright.x, section_topleft.y : section_bottomright.y, ] + # Section chunk already includes x and y axes. All other axes are added to + # adapt the shape of the section chunk to the shape of the chunk_bbox. section_chunk = section_chunk[ (slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(bbox) - 2)) diff --git a/webknossos/webknossos/dataset/view.py b/webknossos/webknossos/dataset/view.py index 115f0cf7b..af3e59276 100644 --- a/webknossos/webknossos/dataset/view.py +++ b/webknossos/webknossos/dataset/view.py @@ -21,7 +21,7 @@ from webknossos.geometry.vec_int import VecInt -from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecIntLike +from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike from ..utils import ( get_executor_for_args, get_rich_progress, @@ -133,12 +133,12 @@ def _get_mag1_bbox( self, abs_mag1_bbox: Optional[NDBoundingBox] = None, rel_mag1_bbox: Optional[NDBoundingBox] = None, - abs_mag1_offset: Optional[VecIntLike] = None, - rel_mag1_offset: Optional[VecIntLike] = None, - mag1_size: Optional[VecIntLike] = None, - abs_current_mag_offset: Optional[VecIntLike] = None, - rel_current_mag_offset: Optional[VecIntLike] = None, - current_mag_size: Optional[VecIntLike] = None, + abs_mag1_offset: Optional[Vec3IntLike] = None, + rel_mag1_offset: Optional[Vec3IntLike] = None, + mag1_size: Optional[Vec3IntLike] = None, + abs_current_mag_offset: Optional[Vec3IntLike] = None, + rel_current_mag_offset: Optional[Vec3IntLike] = None, + current_mag_size: Optional[Vec3IntLike] = None, ) -> NDBoundingBox: num_bboxes = _count_defined_values([abs_mag1_bbox, rel_mag1_bbox]) num_offsets = _count_defined_values( @@ -190,6 +190,10 @@ def _get_mag1_bbox( assert abs_mag1_offset is not None, "No offset was supplied." assert mag1_size is not None, "No size was supplied." + assert ( + len(self.bounding_box) == 3 + ), "The delivered offset and size are only usable for 3D views." + return self.bounding_box.with_topleft(abs_mag1_offset).with_size(mag1_size) def write( @@ -424,8 +428,9 @@ def read( assert ( relative_offset is None and absolute_offset is None ), "You must supply size, when reading with an offset." + absolute_bounding_box = self.bounding_box current_mag_size = None - mag1_size = self.bounding_box.size + mag1_size = None else: if relative_offset is None and absolute_offset is None: if type(self) == View: @@ -464,15 +469,27 @@ def read( ) if size is None: + absolute_bounding_box = self.bounding_box.offset( + self._mag.to_vec3_int() * offset + ) + offset = None current_mag_size = None - mag1_size = self.bounding_box.size + mag1_size = None else: # (deprecated) offset and size are given current_mag_size = size mag1_size = None - if all(i is None for i in [offset, absolute_offset, relative_offset]): - relative_offset = VecInt.zeros(len(self.bounding_box)) + if all( + i is None + for i in [ + offset, + absolute_offset, + relative_offset, + absolute_bounding_box, + ] + ): + relative_offset = Vec3Int.zeros() else: assert ( size is None diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 40a439fb0..4fc320200 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -89,33 +89,112 @@ def _is_sorted(self) -> bool: return all(self.index[i - 1] < self.index[i] for i in range(1, len(self.index))) def with_name(self, name: Optional[str]) -> "NDBoundingBox": + """ + Returns a new instance of `NDBoundingBox` with the specified name. + + Args: + name (Optional[str]): The name to assign to the new `NDBoundingBox` instance. + + Returns: + NDBoundingBox: A new instance of `NDBoundingBox` with the specified name. + """ return attr.evolve(self, name=name) def with_topleft(self, new_topleft: VecIntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with the specified top left coordinates. + + Args: + - new_topleft (VecIntLike): The new top left coordinates for the bounding box. + + Returns: + - NDBoundingBox: A new NDBoundingBox object with the updated top left coordinates. + """ return attr.evolve(self, topleft=VecInt(new_topleft)) def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with the specified size. + + Args: + - new_size (VecIntLike): The new size of the bounding box. Can be a VecInt or any object that can be converted to a VecInt. + + Returns: + - A new NDBoundingBox object with the specified size. + """ return attr.evolve(self, size=VecInt(new_size)) def with_index(self, new_index: VecIntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with the specified index. + + Args: + new_index (VecIntLike): The new axis order for the bounding box. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated index. + """ return attr.evolve(self, index=VecInt(new_index)) def with_bottomright(self, new_bottomright: VecIntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox with an updated bottomright value. + + Args: + new_bottomright (VecIntLike): The new bottom right corner coordinates. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated bottom right corner. + """ new_size = VecInt(new_bottomright) - self.topleft return self.with_size(new_size) def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with the specified visibility. + + Args: + is_visible (bool): The visibility value to set. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated visibility value. + """ return attr.evolve(self, is_visible=is_visible) def with_color( self, color: Optional[Tuple[float, float, float, float]] ) -> "NDBoundingBox": + """ + Returns a new instance of NDBoundingBox with the specified color. + + Args: + color (Optional[Tuple[float, float, float, float]]): The color to set for the bounding box. + The color should be specified as a tuple of four floats representing RGBA values. + + Returns: + NDBoundingBox: A new instance of NDBoundingBox with the specified color. + """ return attr.evolve(self, color=color) def with_bounds( self, axis: str, new_topleft: Optional[int], new_size: Optional[int] ) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with updated bounds along the specified axis. + + Args: + axis (str): The name of the axis to update. + new_topleft (Optional[int]): The new value for the top-left coordinate along the specified axis. + new_size (Optional[int]): The new size along the specified axis. + + Returns: + NDBoundingBox: A new NDBoundingBox object with updated bounds. + + Raises: + ValueError: If the given axis name does not exist. + + """ try: index = self.axes.index(axis) except ValueError as err: @@ -135,6 +214,15 @@ def with_bounds( return attr.evolve(self, topleft=_new_topleft, size=_new_size) def get_bounds(self, axis: str) -> Tuple[int, int]: + """ + Returns the bounds of the given axis. + + Args: + axis (str): The name of the axis to get the bounds for. + + Returns: + Tuple[int, int]: A tuple containing the top-left and bottom-right coordinates along the specified axis. + """ try: index = self.axes.index(axis) except ValueError as err: @@ -163,6 +251,19 @@ def group_boxes_with_aligned_mag( @classmethod def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": + """ + Create an instance of NDBoundingBox from a dictionary representation. + + Args: + bbox (Dict): The dictionary representation of the bounding box. + + Returns: + NDBoundingBox: An instance of NDBoundingBox. + + Raises: + AssertionError: If additionalAxes are present but axisOrder is not provided. + """ + topleft: Tuple[int, ...] = bbox["topLeft"] size: Tuple[int, ...] = (bbox["width"], bbox["height"], bbox["depth"]) axes: Tuple[str, ...] = ("x", "y", "z") @@ -185,6 +286,12 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": return cls(topleft=topleft, size=size, axes=axes, index=index) def to_wkw_dict(self) -> dict: + """ + Converts the bounding box object to a json dictionary. + + Returns: + dict: A json dictionary representing the bounding box. + """ topleft = [None, None, None] width, height, depth = None, None, None additional_axes = [] @@ -222,6 +329,12 @@ def to_wkw_dict(self) -> dict: } def to_config_dict(self) -> dict: + """ + Returns a dictionary representation of the bounding box. + + Returns: + dict: A dictionary representation of the bounding box. + """ return { "topleft": self.topleft.to_list(), "size": self.size.to_list(), @@ -229,6 +342,12 @@ def to_config_dict(self) -> dict: } def to_checkpoint_name(self) -> str: + """ + Returns a string representation of the bounding box that can be used as a checkpoint name. + + Returns: + str: A string representation of the bounding box. + """ return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" def __repr__(self) -> str: @@ -248,6 +367,15 @@ def __len__(self) -> int: return len(self.axes) def get_shape(self, axis_name: str) -> int: + """ + Returns the size of the bounding box along the specified axis. + + Args: + axis_name (str): The name of the axis to get the size for. + + Returns: + int: The size of the bounding box along the specified axis. + """ try: index = self.axes.index(axis_name) return self.size[index] @@ -302,21 +430,57 @@ def index_xyz(self) -> Vec3Int: return self._get_attr_xyz("index") def with_topleft_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. + + Args: + new_xyz (Vec3IntLike): The new x, y and z coordinates for the topleft corner. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. + """ new_topleft = self._get_attr_with_replaced_xyz("topleft", new_xyz) return self.with_topleft(new_topleft) def with_size_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with changed x, y and z size. + + Args: + new_xyz (Vec3IntLike): The new x, y and z size for the bounding box. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated x, y and z size. + """ new_size = self._get_attr_with_replaced_xyz("size", new_xyz) return self.with_size(new_size) def with_bottomright_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. + + Args: + new_xyz (Vec3IntLike): The new x, y and z coordinates for the bottomright corner. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. + """ new_bottomright = self._get_attr_with_replaced_xyz("bottomright", new_xyz) return self.with_bottomright(new_bottomright) def with_index_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with changed x, y and z index. + + Args: + new_xyz (Vec3IntLike): The new x, y and z index for the bounding box. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the updated x, y and z index. + """ new_index = self._get_attr_with_replaced_xyz("index", new_xyz) return self.with_index(new_index) @@ -336,7 +500,18 @@ def padded_with_margins( def intersected_with( self, other: "NDBoundingBox", dont_assert: bool = False ) -> "NDBoundingBox": - """If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0))""" + """ + Returns the intersection of two bounding boxes. + + If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0)) + + Args: + other (NDBoundingBox): The other bounding box to intersect with. + dont_assert (bool): If True, the method may return empty bounding boxes. + + Returns: + NDBoundingBox: The intersection of the two bounding boxes. + """ self._check_compatibility(other) topleft = self.topleft.pairmax(other.topleft) @@ -353,6 +528,15 @@ def intersected_with( return intersection def extended_by(self, other: "NDBoundingBox") -> "NDBoundingBox": + """ + Returns the smallest bounding box that contains both bounding boxes. + + Args: + other (NDBoundingBox): The other bounding box to extend with. + + Returns: + NDBoundingBox: The smallest bounding box that contains both bounding boxes. + """ self._check_compatibility(other) if self.is_empty(): return other @@ -366,9 +550,24 @@ def extended_by(self, other: "NDBoundingBox") -> "NDBoundingBox": return attr.evolve(self, topleft=topleft, size=size) def is_empty(self) -> bool: + """ + Boolean check whether the boundung box is empty. + + Returns: + bool: True if the bounding box is empty, False otherwise. + """ return not self.size.is_positive(strictly_positive=True) def in_mag(self, mag: Mag) -> "NDBoundingBox": + """ + Returns the bounding box in the given mag. + + Args: + mag (Mag): The magnification to convert the bounding box to. + + Returns: + NDBoundingBox: The bounding box in the given magnification. + """ mag_vec = mag.to_vec3_int() assert ( @@ -383,6 +582,15 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": ) def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": + """ + Returns the bounging box in the finest magnification (Mag(1)). + + Args: + from_mag (Mag): The current magnification of the bounding box. + + Returns: + NDBoundingBox: The bounding box in the given magnification. + """ mag_vec = from_mag.to_vec3_int() return self.with_topleft_xyz(self.topleft_xyz * mag_vec).with_size_xyz( @@ -412,9 +620,15 @@ def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": def align_with_mag( self, mag: Union[Mag, Vec3Int], ceil: bool = False ) -> "NDBoundingBox": - """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. + """ + Rounds the bounding box, so that both topleft and bottomright are divisible by mag. - :argument ceil: If true, the bounding box is enlarged when necessary. If false, it's shrinked when necessary. + Args: + mag (Union[Mag, Vec3Int]): The magnification to align the bounding box to. + ceil (bool): If True, the bounding box is enlarged when necessary. If False, it's shrinked when necessary. + + Returns: + NDBoundingBox: The aligned bounding box. """ # This does the same as _align_with_mag_slow, which is more readable. # Same behavior is asserted in test_align_with_mag_against_numpy_implementation @@ -437,8 +651,16 @@ def align_with_mag( ) def contains(self, coord: VecIntLike) -> bool: - """Check whether a point is inside of the bounding box. - Note that the point may have float coordinates in the ndarray case""" + """ + Check whether a point is inside of the bounding box. + Note that the point may have float coordinates in the ndarray case + + Args: + coord (VecIntLike): The coordinates to check. + + Returns: + bool: True if the point is inside of the bounding box, False otherwise. + """ if isinstance(coord, np.ndarray): assert coord.shape == ( @@ -459,6 +681,15 @@ def contains(self, coord: VecIntLike) -> bool: ) def contains_bbox(self, inner_bbox: "NDBoundingBox") -> bool: + """ + Check whether a bounding box is completely inside of the bounding box. + + Args: + inner_bbox (NDBoundingBox): The bounding box to check. + + Returns: + bool: True if the bounding box is completely inside of the bounding box, False otherwise. + """ self._check_compatibility(inner_bbox) return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox @@ -467,11 +698,20 @@ def chunk( chunk_shape: VecIntLike, chunk_border_alignments: Optional[VecIntLike] = None, ) -> Generator["NDBoundingBox", None, None]: - """Decompose the bounding box into smaller chunks of size `chunk_shape`. + """ + Decompose the bounding box into smaller chunks of size `chunk_shape`. Chunks at the border of the bounding box might be smaller than chunk_shape. If `chunk_border_alignment` is set, all border coordinates *between two chunks* will be divisible by that value. + + Args: + chunk_shape (VecIntLike): The size of the chunks to generate. + chunk_border_alignments (Optional[VecIntLike]): The alignment of the chunk borders. + + + Yields: + Generator[NDBoundingBox]: A generator of the chunks. """ start = self.topleft.to_np() @@ -529,18 +769,36 @@ def chunk( ) def volume(self) -> int: + """ + Returns the volume of the bounding box. + """ return self.size.prod() def slice_array(self, array: np.ndarray) -> np.ndarray: + """ + Returns a slice of the given array that corresponds to the bounding box. + """ return array[self.to_slices()] def to_slices(self) -> Tuple[slice, ...]: + """ + Returns a tuple of slices that corresponds to the bounding box. + """ return tuple( slice(topleft, topleft + size) for topleft, size in zip(self.topleft, self.size) ) def offset(self, vector: VecIntLike) -> "NDBoundingBox": + """ + Returns a new NDBoundingBox object with the specified offset. + + Args: + vector (VecIntLike): The offset to apply to the bounding box. + + Returns: + NDBoundingBox: A new NDBoundingBox object with the specified offset. + """ vec_int = VecInt(vector) if len(vec_int) == 3: return self.with_topleft_xyz(self.topleft_xyz + vec_int) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index 673f5725d..b2a5e7a01 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -8,6 +8,10 @@ class VecInt(tuple): + """ + Class to represent a ND vector of integer values. + """ + def __new__( cls, vec: Union[int, "VecIntLike"], @@ -18,8 +22,7 @@ def __new__( ) -> "VecInt": """ Class to represent a ND vector. Inherits from tuple and provides useful - methods and operations on top. The vector has a minimal length of 3 and - it is assumed that the first three axes are `x`, `y` and `z`. + methods and operations on top. The vector has a minimal length of 3. A small usage example: @@ -74,6 +77,15 @@ def __new__( @staticmethod def from_str(string: str) -> "VecInt": + """ + Returns a new ND Vector from a string representation. + + Args: + string (str): The string representation of the vector. + + Returns: + VecInt: The new vector. + """ return VecInt(tuple(map(int, re.findall(r"\d+", string)))) def with_replaced(self, index: int, new_element: int) -> "VecInt": @@ -82,24 +94,48 @@ def with_replaced(self, index: int, new_element: int) -> "VecInt": return VecInt(*self[:index], new_element, *self[index + 1 :]) def to_np(self) -> np.ndarray: + """ + Returns the vector as a numpy array. + """ return np.array(self) def to_list(self) -> List[int]: + """ + Returns the vector as a list. + """ return list(self) def to_tuple(self) -> Tuple[int, ...]: + """ + Returns the vector as a tuple. + """ return tuple(self) def contains(self, needle: int) -> bool: + """ + Checks if the vector contains a given element. + """ return any(element == needle for element in self) def is_positive(self, strictly_positive: bool = False) -> bool: + """ + Checks if all elements in the vector are positive. + + Args: + strictly_positive (bool): If True, checks if all elements are strictly positive. + + Returns: + bool: True if all elements are positive, False otherwise. + """ if strictly_positive: return all(i > 0 for i in self) return all(i >= 0 for i in self) def is_uniform(self) -> bool: + """ + Checks if all elements in the vector are the same. + """ first = self[0] return all(element == first for element in self) @@ -139,15 +175,27 @@ def __neg__(self) -> "VecInt": return self.__class__(-elem for elem in self) def ceildiv(self, other: Union[int, "VecIntLike"]) -> "VecInt": + """ + Returns a new VecInt with the ceil division of each element by the other. + """ return (self + other - 1) // other def pairmax(self, other: Union[int, "VecIntLike"]) -> "VecInt": + """ + Returns a new VecInt with the maximum of each pair of elements from the two vectors. + """ return self._element_wise(other, max) def pairmin(self, other: Union[int, "VecIntLike"]) -> "VecInt": + """ + Returns a new VecInt with the minimum of each pair of elements from the two vectors. + """ return self._element_wise(other, min) def prod(self) -> int: + """ + Returns the product of all elements in the vector. + """ return int(np.prod(self.to_np())) def __repr__(self) -> str: @@ -156,6 +204,15 @@ def __repr__(self) -> str: ) def add_or_none(self, other: Optional["VecInt"]) -> Optional["VecInt"]: + """ + Adds two VecInts or returns None if the other is None. + + Args: + other (Optional[VecInt]): The other vector to add. + + Returns: + Optional[VecInt]: The sum of the two vectors or None if the other is None. + """ return None if other is None else self + other def moveaxis( @@ -165,6 +222,13 @@ def moveaxis( Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified source so that the other elements move when necessary. + + Args: + source (Union[int, List[int]]): The index of the element to move. + target (Union[int, List[int]]): The index where the element should be moved to. + + Returns: + VecInt: A new vector with the moved element. """ # Piggy-back on np.moveaxis by creating an auxiliary array where the indices 0, 1 and @@ -177,14 +241,42 @@ def moveaxis( @classmethod def zeros(cls, length: int) -> "VecInt": + """ + Returns a new ND Vector with all elements set to 0. + + Args: + length (int): The length of the vector. + + Returns: + VecInt: The new vector. + """ return cls((0 for _ in range(length))) @classmethod def ones(cls, length: int) -> "VecInt": + """ + Returns a new ND Vector with all elements set to 1. + + Args: + length (int): The length of the vector. + + Returns: + VecInt: The new vector. + """ return cls((1 for _ in range(length))) @classmethod def full(cls, an_int: int, length: int) -> "VecInt": + """ + Returns a new ND Vector with all elements set to the same value. + + Args: + an_int (int): The value of the elements. + length (int): The length of the vector. + + Returns: + VecInt: The new vector. + """ return cls((an_int for _ in range(length))) From ffbe7f7aece218f03e02601b39645a53b65ff5a9 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 18 Mar 2024 10:06:07 +0100 Subject: [PATCH 37/41] Implement requested changes. --- webknossos/examples/convert_4d_tiff.py | 1 + webknossos/examples/download_segments.py | 2 +- webknossos/examples/download_tiff_stack.py | 2 +- .../script_collection/globalize_floodfill.py | 10 +- .../dataset/test_add_layer_from_images.py | 6 +- webknossos/tests/test_annotation.py | 2 +- webknossos/tests/test_examples.py | 4 +- webknossos/webknossos/_nml/parameters.py | 20 +- .../webknossos/cli/export_wkw_as_tiff.py | 20 +- webknossos/webknossos/dataset/_array.py | 44 ++-- .../webknossos/dataset/_upsampling_utils.py | 2 +- .../dataset/_utils/buffered_slice_reader.py | 4 +- .../dataset/_utils/buffered_slice_writer.py | 5 +- .../infer_bounding_box_existing_files.py | 2 +- .../webknossos/dataset/_utils/pims_images.py | 18 +- webknossos/webknossos/dataset/dataset.py | 30 +-- webknossos/webknossos/dataset/layer.py | 10 +- webknossos/webknossos/dataset/mag_view.py | 16 +- .../webknossos/geometry/nd_bounding_box.py | 133 ++++++------ webknossos/webknossos/geometry/vec3_int.py | 49 +++-- webknossos/webknossos/geometry/vec_int.py | 195 +++++++++++------- 21 files changed, 341 insertions(+), 234 deletions(-) diff --git a/webknossos/examples/convert_4d_tiff.py b/webknossos/examples/convert_4d_tiff.py index 82caba6c7..f85fd33c8 100644 --- a/webknossos/examples/convert_4d_tiff.py +++ b/webknossos/examples/convert_4d_tiff.py @@ -26,6 +26,7 @@ def main() -> None: ) data = mag_view.read(absolute_bounding_box=read_bbox) # data.shape -> (1, 1, 5, 167, 439) + # The data shape is different to the read_bbox size because it includes the channel dimension # Write some data to a given position mag_view.write(data, absolute_bounding_box=read_bbox.offset((2, 0, 0, 0))) diff --git a/webknossos/examples/download_segments.py b/webknossos/examples/download_segments.py index c24e3c49e..581ec6316 100644 --- a/webknossos/examples/download_segments.py +++ b/webknossos/examples/download_segments.py @@ -14,7 +14,7 @@ def main() -> None: ) mag_view = dataset.get_segmentation_layers()[0].get_mag(MAG) - z = mag_view.bounding_box.topleft_xyz.z + z = mag_view.bounding_box.topleft.z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/examples/download_tiff_stack.py b/webknossos/examples/download_tiff_stack.py index 595ac769a..293dbe5e6 100644 --- a/webknossos/examples/download_tiff_stack.py +++ b/webknossos/examples/download_tiff_stack.py @@ -15,7 +15,7 @@ def main() -> None: ) mag_view = dataset.get_layer(LAYER_NAME).get_mag(MAG) - z = mag_view.bounding_box.topleft_xyz.z + z = mag_view.bounding_box.topleft.z with mag_view.get_buffered_slice_reader() as reader: for slice_data in reader: slice_data = slice_data[0] # First channel only diff --git a/webknossos/script_collection/globalize_floodfill.py b/webknossos/script_collection/globalize_floodfill.py index 4249c89d0..f580cfced 100755 --- a/webknossos/script_collection/globalize_floodfill.py +++ b/webknossos/script_collection/globalize_floodfill.py @@ -97,9 +97,9 @@ def create_parser() -> argparse.ArgumentParser: def get_chunk_pos_and_offset( global_position: Vec3Int, chunk_shape: Vec3Int ) -> Tuple[Vec3Int, Vec3Int]: - offset = Vec3Int(global_position % chunk_shape) + offset = global_position % chunk_shape return ( - Vec3Int(global_position - offset), + global_position - offset, offset, ) @@ -179,12 +179,10 @@ def execute_floodfill( already_processed_bbox.contains(global_neighbor_pos) and cube_data[neighbor_pos] == target_id ): - seeds_in_current_chunk.add(Vec3Int(neighbor_pos)) + seeds_in_current_chunk.add(neighbor_pos) else: chunk_with_relative_seed.append( - get_chunk_pos_and_offset( - Vec3Int(global_neighbor_pos), Vec3Int(cube_size) - ) + get_chunk_pos_and_offset(global_neighbor_pos, cube_size) ) time_stop("traverse cube") diff --git a/webknossos/tests/dataset/test_add_layer_from_images.py b/webknossos/tests/dataset/test_add_layer_from_images.py index 5711b48c1..47a6a2023 100644 --- a/webknossos/tests/dataset/test_add_layer_from_images.py +++ b/webknossos/tests/dataset/test_add_layer_from_images.py @@ -55,8 +55,10 @@ def test_compare_nd_tifffile(tmp_path: Path) -> None: chunk_shape=(8, 8, 8), chunks_per_shard=(8, 8, 8), ) - assert l.bounding_box.topleft == wk.VecInt(0, 55, 100, 100) - assert l.bounding_box.size == wk.VecInt(7, 5, 167, 439) + assert l.bounding_box.topleft == wk.VecInt( + 0, 55, 100, 100, axes=("t", "z", "y", "x") + ) + assert l.bounding_box.size == wk.VecInt(7, 5, 167, 439, axes=("t", "z", "y", "x")) read_with_tifffile_reader = TiffFile( "testdata/4D/4D_series/4D-series.ome.tif" ).asarray() diff --git a/webknossos/tests/test_annotation.py b/webknossos/tests/test_annotation.py index 927444b81..71092732b 100644 --- a/webknossos/tests/test_annotation.py +++ b/webknossos/tests/test_annotation.py @@ -199,7 +199,7 @@ def test_annotation_from_url(url: str) -> None: def test_reading_bounding_boxes() -> None: def check_properties(annotation: wk.Annotation) -> None: assert len(annotation.user_bounding_boxes) == 2 - assert annotation.user_bounding_boxes[0].topleft_xyz.x == 2371 + assert annotation.user_bounding_boxes[0].topleft.x == 2371 assert annotation.user_bounding_boxes[0].name == "Bounding box 1" assert annotation.user_bounding_boxes[0].is_visible diff --git a/webknossos/tests/test_examples.py b/webknossos/tests/test_examples.py index 93f0a57f1..c0be46d36 100644 --- a/webknossos/tests/test_examples.py +++ b/webknossos/tests/test_examples.py @@ -312,7 +312,7 @@ def test_download_segments() -> None: assert ( len(list(output_path.iterdir())) - == 2 * mag_view.layer.bounding_box.size_xyz.z / mag_view.mag.z + == 2 * mag_view.layer.bounding_box.size.z / mag_view.mag.z ) @@ -329,7 +329,7 @@ def test_download_tiff_stack() -> None: assert ( len(list(output_path.iterdir())) - == mag_view.bounding_box.size_xyz.z / mag_view.mag.z + == mag_view.bounding_box.size.z / mag_view.mag.z ) diff --git a/webknossos/webknossos/_nml/parameters.py b/webknossos/webknossos/_nml/parameters.py index cdc283af8..c58275458 100644 --- a/webknossos/webknossos/_nml/parameters.py +++ b/webknossos/webknossos/_nml/parameters.py @@ -35,20 +35,22 @@ def _dump_bounding_box( color = bounding_box.color or DEFAULT_BOUNDING_BOX_COLOR attributes = { - "name": _DEFAULT_BBOX_NAME - if bounding_box.name is None - else str(bounding_box.name), + "name": ( + _DEFAULT_BBOX_NAME + if bounding_box.name is None + else str(bounding_box.name) + ), "isVisible": "true" if bounding_box.is_visible else "false", "color.r": str(color[0]), "color.g": str(color[1]), "color.b": str(color[2]), "color.a": str(color[3]), - "topLeftX": str(bounding_box.topleft_xyz.x), - "topLeftY": str(bounding_box.topleft_xyz.y), - "topLeftZ": str(bounding_box.topleft_xyz.z), - "width": str(bounding_box.size_xyz.x), - "height": str(bounding_box.size_xyz.y), - "depth": str(bounding_box.size_xyz.z), + "topLeftX": str(bounding_box.topleft.x), + "topLeftY": str(bounding_box.topleft.y), + "topLeftZ": str(bounding_box.topleft.z), + "width": str(bounding_box.size.x), + "height": str(bounding_box.size.y), + "depth": str(bounding_box.size.z), } if bbox_id is not None: attributes["id"] = str(bbox_id) diff --git a/webknossos/webknossos/cli/export_wkw_as_tiff.py b/webknossos/webknossos/cli/export_wkw_as_tiff.py index 366592c80..52f5c1197 100644 --- a/webknossos/webknossos/cli/export_wkw_as_tiff.py +++ b/webknossos/webknossos/cli/export_wkw_as_tiff.py @@ -74,9 +74,9 @@ def export_tiff_slice( tiff_data = view.read() else: padded_tiff_bbox_size = Vec3Int( - tiling_size[0] * ceil(tiff_bbox.size_xyz.x / tiling_size[0]), - tiling_size[1] * ceil(tiff_bbox.size_xyz.y / tiling_size[1]), - tiff_bbox.size_xyz.z, + tiling_size[0] * ceil(tiff_bbox.size.x / tiling_size[0]), + tiling_size[1] * ceil(tiff_bbox.size.y / tiling_size[1]), + tiff_bbox.size.z, ) tiff_data = view.read() padded_tiff_data = np.zeros( @@ -87,9 +87,9 @@ def export_tiff_slice( :, 0 : tiff_data.shape[1], 0 : tiff_data.shape[2], 0 : tiff_data.shape[3] ] = tiff_data tiff_data = padded_tiff_data - for slice_index in range(tiff_bbox.size_xyz.z): + for slice_index in range(tiff_bbox.size.z): slice_name_number = ( - tiff_bbox_mag1.topleft_xyz.z + slice_index + 1 - start_slice_index + tiff_bbox_mag1.topleft.z + slice_index + 1 - start_slice_index ) if tiling_size is None: tiff_file_name = _make_tiff_name(name, slice_name_number) @@ -100,12 +100,12 @@ def export_tiff_slice( logging.debug("Saved slice %s", slice_name_number) else: - for y_tile_index in range(ceil(tiff_bbox.size_xyz.y / tiling_size[1])): + for y_tile_index in range(ceil(tiff_bbox.size.y / tiling_size[1])): tile_tiff_path = ( dest_path / str(slice_name_number) / str(y_tile_index + 1) ) tile_tiff_path.mkdir(parents=True, exist_ok=True) - for x_tile_index in range(ceil(tiff_bbox.size_xyz.x / tiling_size[0])): + for x_tile_index in range(ceil(tiff_bbox.size.x / tiling_size[0])): tile_tiff_filename = f"{x_tile_index + 1}.tiff" tile_image = _slice_to_image( tiff_data[ @@ -264,11 +264,7 @@ def main( mag_view = Dataset.open(source).get_layer(layer_name).get_mag(mag) - bbox = ( - BoundingBox(mag_view.bounding_box.topleft, mag_view.bounding_box.size) - if bbox is None - else bbox - ) + bbox = BoundingBox.from_ndbbox(mag_view.bounding_box) if bbox is None else bbox logging.info("Starting tiff export for bounding box: %s", bbox) executor_args = Namespace( diff --git a/webknossos/webknossos/dataset/_array.py b/webknossos/webknossos/dataset/_array.py index 9b791a86b..2cc4a02f6 100644 --- a/webknossos/webknossos/dataset/_array.py +++ b/webknossos/webknossos/dataset/_array.py @@ -70,9 +70,9 @@ class ArrayInfo: voxel_type: np.dtype chunk_shape: Vec3Int chunks_per_shard: Vec3Int - shape: VecInt = VecInt(1, 1, 1, 1) + shape: VecInt = VecInt(c=1, x=1, y=1, z=1) dimension_names: Tuple[str, ...] = ("c", "x", "y", "z") - axis_order: VecInt = VecInt(3, 2, 1, 0) + axis_order: VecInt = VecInt(c=3, x=2, y=1, z=0) compression_mode: bool = False @property @@ -82,7 +82,7 @@ def shard_size(self) -> Vec3Int: @property def shard_shape(self) -> Vec3Int: - return Vec3Int(self.chunk_shape * self.chunks_per_shard) + return self.chunk_shape * self.chunks_per_shard class BaseArray(ABC): @@ -375,13 +375,15 @@ def ensure_size( align_with_shards: bool = True, warn: bool = False, ) -> None: - new_shape = VecInt(new_bbox.size) + new_shape = VecInt(new_bbox.size, axes=new_bbox.axes) zarray = self._zarray new_shape_tuple = (zarray.shape[0],) + tuple( - max(zarray.shape[i + 1], new_shape[i]) - if len(zarray.shape) > i - else new_shape[i] + ( + max(zarray.shape[i + 1], new_shape[i]) + if len(zarray.shape) > i + else new_shape[i] + ) for i in range(len(new_shape)) ) if new_shape_tuple != zarray.shape: @@ -407,7 +409,7 @@ def ensure_size( zarray.resize(new_shape_tuple) def write(self, bbox: NDBoundingBox, data: np.ndarray) -> None: - """Writes a ZarrArray. If offset and bbox are given the bbox is prefered to enable writing of n-dimensional data.""" + """Writes a ZarrArray. If offset and bbox are given, the bbox is preferred to enable writing of n-dimensional data.""" # If data is 3-dimensional, it is assumed that num_channels=1. if data.ndim == 3: @@ -574,18 +576,20 @@ def create(cls, path: Path, array_info: ArrayInfo) -> "ZarritaArray": codecs=[ zarrita.codecs.sharding_codec( chunk_shape=chunk_shape, - codecs=[ - zarrita.codecs.transpose_codec(array_info.axis_order), - zarrita.codecs.bytes_codec(), - zarrita.codecs.blosc_codec( - typesize=array_info.voxel_type.itemsize - ), - ] - if array_info.compression_mode - else [ - zarrita.codecs.transpose_codec(array_info.axis_order), - zarrita.codecs.bytes_codec(), - ], + codecs=( + [ + zarrita.codecs.transpose_codec(array_info.axis_order), + zarrita.codecs.bytes_codec(), + zarrita.codecs.blosc_codec( + typesize=array_info.voxel_type.itemsize + ), + ] + if array_info.compression_mode + else [ + zarrita.codecs.transpose_codec(array_info.axis_order), + zarrita.codecs.bytes_codec(), + ] + ), ) ], ) diff --git a/webknossos/webknossos/dataset/_upsampling_utils.py b/webknossos/webknossos/dataset/_upsampling_utils.py index 94f07596c..cd6ea56b1 100644 --- a/webknossos/webknossos/dataset/_upsampling_utils.py +++ b/webknossos/webknossos/dataset/_upsampling_utils.py @@ -56,7 +56,7 @@ def upsample_cube_job( ) for tile in tiles: - target_offset = Vec3Int(Vec3Int(tile) * buffer_shape) + target_offset = Vec3Int(tile) * buffer_shape source_offset = _vec3int_mulf(target_offset, mag_factors) source_size = source_view.bounding_box.in_mag(source_view.mag).size source_size = _vec3int_mulf(buffer_shape, mag_factors).pairmin( diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py index 3876d37ab..41d33b68a 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_reader.py @@ -70,9 +70,7 @@ def _get_slice_generator(self) -> Generator[np.ndarray, None, None]: absolute_bounding_box=chunk.from_mag_to_mag1(self.view.mag) ) - for current_slice in np.rollaxis( - data, chunk.index_xyz[self.dimension] - ): # The '+1' is important because the first dimension is the channel + for current_slice in np.rollaxis(data, chunk.index_xyz[self.dimension]): yield current_slice def __enter__(self) -> Generator[np.ndarray, None, None]: diff --git a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py index 8d8911a86..296a02453 100644 --- a/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py +++ b/webknossos/webknossos/dataset/_utils/buffered_slice_writer.py @@ -186,8 +186,9 @@ def _flush_buffer(self) -> None: section_topleft.x : section_bottomright.x, section_topleft.y : section_bottomright.y, ] - # Section chunk already includes x and y axes. All other axes are added to - # adapt the shape of the section chunk to the shape of the chunk_bbox. + # Section chunk includes the axes c, x, y. The remaining axes are added by considering + # the length of the bbox. Since the bbox does not contain the channel, we subtract 2 + # instead of 3. section_chunk = section_chunk[ (slice(None), slice(None), slice(None)) + tuple(np.newaxis for _ in range(len(bbox) - 2)) diff --git a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py index 5ea220daf..47c4fcb6c 100644 --- a/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py +++ b/webknossos/webknossos/dataset/_utils/infer_bounding_box_existing_files.py @@ -10,7 +10,7 @@ def infer_bounding_box_existing_files(mag_view: MagView) -> BoundingBox: The returned bounding box is measured in Mag(1) voxels.""" return reduce( - lambda acc, bbox: BoundingBox.from_ndbbox(acc.extended_by(bbox)), + lambda acc, bbox: acc.extended_by(BoundingBox.from_ndbbox(bbox)), mag_view.get_bounding_boxes_on_disk(), BoundingBox.empty(), ) diff --git a/webknossos/webknossos/dataset/_utils/pims_images.py b/webknossos/webknossos/dataset/_utils/pims_images.py index b0b8e8d1e..64ff59b76 100644 --- a/webknossos/webknossos/dataset/_utils/pims_images.py +++ b/webknossos/webknossos/dataset/_utils/pims_images.py @@ -89,8 +89,8 @@ def __init__( """ During initialization the pims objects are examined and configured to produce ndarrays that follow the following form: - (self._iter_axis, *self._bundle_axis) - self._iter_axis can be a list of different axis or an empty list if the image is 2D. + (self._iter_axes, *self._bundle_axis) + self._iter_axes can be a list of different axes or an empty list if the image is 2D. In the latter case, the inner 2D image is still wrapped in a single-element list by _open_images() to be consistent with 3D images. self._bundle_axis can consist of "x", "y" and "c", where "c" is optional and must be @@ -197,9 +197,9 @@ def __init__( # the axes are identified by their index in the _iter_axes list # the last axis is the fastest iterating axis, therfore the size of the loop # for the last axis is 1. For all other axes it is the product of all previous axes sizes. - # self._iter_axis[-1:0:-1] is a reversed copy of self._iter_axis without the last element + # self._iter_axes[-1:0:-1] is a reversed copy of self._iter_axes without the last element # e.g. [1,2,3,4] -> [4,3,2] - # self._iter_axis[-2::-1] is a reversed copy of self._iter_axis without the first element + # self._iter_axes[-2::-1] is a reversed copy of self._iter_axes without the first element # e.g. [1,2,3,4] -> [3,2,1] self._iter_loop_size[other_axis] = ( iter_size := iter_size * images.sizes[axis] @@ -268,7 +268,7 @@ def __init__( raise RuntimeError( f"Got {len(images.shape)} axes for the images, " + "but don't have axes information. Try to open " - + "a N-dimensional image file with use_bioformats=" + + "an N-dimensional image file with use_bioformats=" + "True." ) @@ -608,7 +608,7 @@ def expected_bbox(self) -> NDBoundingBox: axes = ("z", "c", "y", "x") if self._iter_loop_size is None: - # There is no or only one iter_axis, so a 3D bounding box is sufficient. + # There is no or only one element in self._iter_axes, so a 3D bounding box is sufficient. x_index, y_index = ( axes.index("x"), axes.index("y"), @@ -639,7 +639,7 @@ def expected_bbox(self) -> NDBoundingBox: for axis in axes_names ] axes_index = list(range(1, len(axes_names) + 1)) - topleft = VecInt.zeros(len(axes_names)) + topleft = VecInt.zeros(tuple(axes_names)) if self._swap_xy: x_index, y_index = axes_names.index("x"), axes_names.index("y") @@ -650,9 +650,9 @@ def expected_bbox(self) -> NDBoundingBox: return NDBoundingBox( topleft, - axes_sizes, + VecInt(axes_sizes, axes=axes_names), axes_names, - axes_index, + VecInt(axes_index, axes=axes_names), ) raise ValueError( diff --git a/webknossos/webknossos/dataset/dataset.py b/webknossos/webknossos/dataset/dataset.py index ffbb670b7..e3def97bc 100644 --- a/webknossos/webknossos/dataset/dataset.py +++ b/webknossos/webknossos/dataset/dataset.py @@ -189,8 +189,8 @@ def _to_callable( elif self == ConversionLayerMapping.ENFORCE_SINGLE_LAYER: return lambda p: input_path.name elif self == ConversionLayerMapping.ENFORCE_LAYER_PER_FOLDER: - return ( - lambda p: input_path.name + return lambda p: ( + input_path.name if p.parent == Path() else p.parent.as_posix().replace("/", "_") ) @@ -199,16 +199,18 @@ def _to_callable( elif self == ConversionLayerMapping.INSPECT_EVERY_FILE: # If a file has z dimensions, it becomes its own layer, # if it's 2D, the folder becomes a layer. - return ( - lambda p: str(p) + return lambda p: ( + str(p) if has_image_z_dimension( input_path / p, use_bioformats=use_bioformats, is_segmentation=guess_if_segmentation_path(p), ) - else input_path.name - if p.parent == Path() - else p.parent.as_posix().replace("/", "_") + else ( + input_path.name + if p.parent == Path() + else p.parent.as_posix().replace("/", "_") + ) ) elif self == ConversionLayerMapping.INSPECT_SINGLE_FILE: # As before, but only a single image is inspected to determine 2D vs 3D. @@ -219,8 +221,8 @@ def _to_callable( ): return str else: - return ( - lambda p: input_path.name if p.parent == Path() else p.parts[-2] + return lambda p: ( + input_path.name if p.parent == Path() else p.parts[-2] ) else: raise ValueError(f"Got unexpected ConversionLayerMapping value: {self}") @@ -318,9 +320,11 @@ def __init__( layer_properties.num_channels, UPath(dataset_path), layer_properties.name, - layer_properties.mags[0].mag - if len(layer_properties.mags) > 0 - else None, + ( + layer_properties.mags[0].mag + if len(layer_properties.mags) > 0 + else None + ), ) layer_properties.num_channels = num_channels @@ -1256,7 +1260,7 @@ def add_layer_from_images( additional_axes = [] z_shape = bbox.get_shape("z") - bbox = bbox.with_topleft(VecInt.zeros(len(bbox))) + bbox = bbox.with_topleft(VecInt.zeros(bbox.axes)) for z_start in range(0, z_shape, batch_size): z_size = min(batch_size, z_shape - z_start) z_bbox = bbox.with_bounds("z", z_start, z_size) diff --git a/webknossos/webknossos/dataset/layer.py b/webknossos/webknossos/dataset/layer.py index 813e2ee04..d98c956de 100644 --- a/webknossos/webknossos/dataset/layer.py +++ b/webknossos/webknossos/dataset/layer.py @@ -570,9 +570,11 @@ def add_copy_mag( chunk_shape=chunk_shape or foreign_mag_view._array_info.chunk_shape, chunks_per_shard=chunks_per_shard or foreign_mag_view._array_info.chunks_per_shard, - compress=compress - if compress is not None - else foreign_mag_view._array_info.compression_mode, + compress=( + compress + if compress is not None + else foreign_mag_view._array_info.compression_mode + ), ) if extend_layer_bounding_box: @@ -738,7 +740,7 @@ def downsample( sampling_mode = SamplingModes.parse(sampling_mode) - if self._properties.bounding_box.size_xyz.z == 1: + if self._properties.bounding_box.size.z == 1: if sampling_mode != SamplingModes.CONSTANT_Z: warnings.warn( "[INFO] The sampling_mode was changed to 'CONSTANT_Z'. Downsampling 2D data with a different sampling mode mixes in black and thus leads to darkened images." diff --git a/webknossos/webknossos/dataset/mag_view.py b/webknossos/webknossos/dataset/mag_view.py index 1c877bbe5..18a20886f 100644 --- a/webknossos/webknossos/dataset/mag_view.py +++ b/webknossos/webknossos/dataset/mag_view.py @@ -10,7 +10,7 @@ from cluster_tools import Executor from upath import UPath -from ..geometry import BoundingBox, Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt +from ..geometry import Mag, NDBoundingBox, Vec3Int, Vec3IntLike, VecInt from ..utils import ( NDArrayLike, get_executor_for_args, @@ -78,8 +78,14 @@ def __init__( chunk_shape=chunk_shape, chunks_per_shard=chunks_per_shard, compression_mode=compression_mode, - axis_order=VecInt(0, *layer.bounding_box.index), - shape=VecInt(layer.num_channels, *VecInt.ones(len(layer.bounding_box))), + axis_order=VecInt( + 0, *layer.bounding_box.index, axes=("c",) + layer.bounding_box.axes + ), + shape=VecInt( + layer.num_channels, + *VecInt.ones(layer.bounding_box.axes), + axes=("c",) + layer.bounding_box.axes, + ), dimension_names=("c",) + layer.bounding_box.axes, ) if create: @@ -96,7 +102,7 @@ def __init__( # Overwrites of View methods: @property - def bounding_box(self) -> Union[NDBoundingBox, BoundingBox]: + def bounding_box(self) -> NDBoundingBox: # Overwrites View's method since no extra bbox is stored for a MagView, # but the Layer's bbox is used: return self.layer.bounding_box.align_with_mag(self._mag, ceil=True) @@ -286,7 +292,7 @@ def get_view( def get_bounding_boxes_on_disk( self, - ) -> Iterator[Union[NDBoundingBox, BoundingBox]]: + ) -> Iterator[NDBoundingBox]: """ Returns a Mag(1) bounding box for each file on disk. diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index 4fc320200..012d595e1 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -1,6 +1,16 @@ from collections import defaultdict from itertools import product -from typing import Dict, Generator, Iterable, List, Optional, Tuple, Union, cast +from typing import ( + Dict, + Generator, + Iterable, + List, + Optional, + Tuple, + TypeVar, + Union, + cast, +) import attr import numpy as np @@ -11,6 +21,8 @@ _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" +T = TypeVar("T", bound="NDBoundingBox") + def str_tpl(str_list: Iterable[str]) -> Tuple[str, ...]: # Fix for mypy bug https://github.com/python/mypy/issues/5313. @@ -63,13 +75,17 @@ def __attrs_post_init__(self) -> None: new_topleft = tuple( val1 + val2 for val1, val2 in zip(self.topleft, negative_size) ) - new_size = (max(value, -value) for value in self.size) - object.__setattr__(self, "topleft", VecInt(new_topleft)) - object.__setattr__(self, "size", VecInt(new_size)) + new_size = (abs(value) for value in self.size) + object.__setattr__(self, "topleft", VecInt(new_topleft, axes=self.axes)) + object.__setattr__(self, "size", VecInt(new_size, axes=self.axes)) # Compute bottomright to avoid that it's recomputed every time # it is needed. - object.__setattr__(self, "bottomright", self.topleft + self.size) + object.__setattr__( + self, + "bottomright", + self.topleft + self.size, + ) def _sort_positions_of_axes(self) -> None: # Bring topleft and size in required order @@ -80,15 +96,15 @@ def _sort_positions_of_axes(self) -> None: zip(self.size, self.topleft, self.axes, self.index), key=lambda x: x[3] ) ) - object.__setattr__(self, "size", VecInt(size)) - object.__setattr__(self, "topleft", VecInt(topleft)) + object.__setattr__(self, "size", VecInt(size, axes=axes)) + object.__setattr__(self, "topleft", VecInt(topleft, axes=axes)) object.__setattr__(self, "axes", axes) - object.__setattr__(self, "index", index) + object.__setattr__(self, "index", VecInt(index, axes=axes)) def _is_sorted(self) -> bool: return all(self.index[i - 1] < self.index[i] for i in range(1, len(self.index))) - def with_name(self, name: Optional[str]) -> "NDBoundingBox": + def with_name(self: T, name: Optional[str]) -> T: """ Returns a new instance of `NDBoundingBox` with the specified name. @@ -100,7 +116,7 @@ def with_name(self, name: Optional[str]) -> "NDBoundingBox": """ return attr.evolve(self, name=name) - def with_topleft(self, new_topleft: VecIntLike) -> "NDBoundingBox": + def with_topleft(self: T, new_topleft: VecIntLike) -> T: """ Returns a new NDBoundingBox object with the specified top left coordinates. @@ -110,9 +126,9 @@ def with_topleft(self, new_topleft: VecIntLike) -> "NDBoundingBox": Returns: - NDBoundingBox: A new NDBoundingBox object with the updated top left coordinates. """ - return attr.evolve(self, topleft=VecInt(new_topleft)) + return attr.evolve(self, topleft=VecInt(new_topleft, axes=self.axes)) - def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": + def with_size(self: T, new_size: VecIntLike) -> T: """ Returns a new NDBoundingBox object with the specified size. @@ -122,9 +138,9 @@ def with_size(self, new_size: VecIntLike) -> "NDBoundingBox": Returns: - A new NDBoundingBox object with the specified size. """ - return attr.evolve(self, size=VecInt(new_size)) + return attr.evolve(self, size=VecInt(new_size, axes=self.axes)) - def with_index(self, new_index: VecIntLike) -> "NDBoundingBox": + def with_index(self: T, new_index: VecIntLike) -> T: """ Returns a new NDBoundingBox object with the specified index. @@ -134,9 +150,10 @@ def with_index(self, new_index: VecIntLike) -> "NDBoundingBox": Returns: NDBoundingBox: A new NDBoundingBox object with the updated index. """ - return attr.evolve(self, index=VecInt(new_index)) + axes, _ = zip(*sorted(zip(self.axes, new_index), key=lambda x: x[1])) + return attr.evolve(self, index=VecInt(new_index, axes=axes)) - def with_bottomright(self, new_bottomright: VecIntLike) -> "NDBoundingBox": + def with_bottomright(self: T, new_bottomright: VecIntLike) -> T: """ Returns a new NDBoundingBox with an updated bottomright value. @@ -146,11 +163,11 @@ def with_bottomright(self, new_bottomright: VecIntLike) -> "NDBoundingBox": Returns: NDBoundingBox: A new NDBoundingBox object with the updated bottom right corner. """ - new_size = VecInt(new_bottomright) - self.topleft + new_size = VecInt(new_bottomright, axes=self.axes) - self.topleft return self.with_size(new_size) - def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": + def with_is_visible(self: T, is_visible: bool) -> T: """ Returns a new NDBoundingBox object with the specified visibility. @@ -162,9 +179,7 @@ def with_is_visible(self, is_visible: bool) -> "NDBoundingBox": """ return attr.evolve(self, is_visible=is_visible) - def with_color( - self, color: Optional[Tuple[float, float, float, float]] - ) -> "NDBoundingBox": + def with_color(self: T, color: Optional[Tuple[float, float, float, float]]) -> T: """ Returns a new instance of NDBoundingBox with the specified color. @@ -178,8 +193,8 @@ def with_color( return attr.evolve(self, color=color) def with_bounds( - self, axis: str, new_topleft: Optional[int], new_size: Optional[int] - ) -> "NDBoundingBox": + self: T, axis: str, new_topleft: Optional[int], new_size: Optional[int] + ) -> T: """ Returns a new NDBoundingBox object with updated bounds along the specified axis. @@ -283,7 +298,12 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": axes += (axis["name"],) index += (axis["index"],) - return cls(topleft=topleft, size=size, axes=axes, index=index) + return cls( + topleft=VecInt(topleft, axes=axes), + size=VecInt(size, axes=axes), + axes=axes, + index=VecInt(index, axes=axes), + ) def to_wkw_dict(self) -> dict: """ @@ -403,7 +423,7 @@ def _get_attr_with_replaced_xyz(self, attr_name: str, xyz: Vec3IntLike) -> VecIn index = self.axes.index(axis) modified_attr[index] = value[i] - return VecInt(modified_attr) + return VecInt(modified_attr, axes=self.axes) @property def topleft_xyz(self) -> Vec3Int: @@ -429,7 +449,7 @@ def index_xyz(self) -> Vec3Int: return self._get_attr_xyz("index") - def with_topleft_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + def with_topleft_xyz(self: T, new_xyz: Vec3IntLike) -> T: """ Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. @@ -443,7 +463,7 @@ def with_topleft_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": return self.with_topleft(new_topleft) - def with_size_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + def with_size_xyz(self: T, new_xyz: Vec3IntLike) -> T: """ Returns a new NDBoundingBox object with changed x, y and z size. @@ -457,7 +477,7 @@ def with_size_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": return self.with_size(new_size) - def with_bottomright_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + def with_bottomright_xyz(self: T, new_xyz: Vec3IntLike) -> T: """ Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. @@ -471,7 +491,7 @@ def with_bottomright_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": return self.with_bottomright(new_bottomright) - def with_index_xyz(self, new_xyz: Vec3IntLike) -> "NDBoundingBox": + def with_index_xyz(self: T, new_xyz: Vec3IntLike) -> T: """ Returns a new NDBoundingBox object with changed x, y and z index. @@ -497,9 +517,7 @@ def padded_with_margins( ) -> "NDBoundingBox": raise NotImplementedError() - def intersected_with( - self, other: "NDBoundingBox", dont_assert: bool = False - ) -> "NDBoundingBox": + def intersected_with(self: T, other: T, dont_assert: bool = False) -> T: """ Returns the intersection of two bounding boxes. @@ -516,7 +534,7 @@ def intersected_with( self._check_compatibility(other) topleft = self.topleft.pairmax(other.topleft) bottomright = self.bottomright.pairmin(other.bottomright) - size = (bottomright - topleft).pairmax(VecInt.zeros(len(self.size))) + size = (bottomright - topleft).pairmax(VecInt.zeros(self.axes)) intersection = attr.evolve(self, topleft=topleft, size=size) @@ -527,7 +545,7 @@ def intersected_with( return intersection - def extended_by(self, other: "NDBoundingBox") -> "NDBoundingBox": + def extended_by(self: T, other: T) -> T: """ Returns the smallest bounding box that contains both bounding boxes. @@ -558,7 +576,7 @@ def is_empty(self) -> bool: """ return not self.size.is_positive(strictly_positive=True) - def in_mag(self, mag: Mag) -> "NDBoundingBox": + def in_mag(self: T, mag: Mag) -> T: """ Returns the bounding box in the given mag. @@ -581,7 +599,7 @@ def in_mag(self, mag: Mag) -> "NDBoundingBox": self.size_xyz // mag_vec ) - def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": + def from_mag_to_mag1(self: T, from_mag: Mag) -> T: """ Returns the bounging box in the finest magnification (Mag(1)). @@ -597,7 +615,7 @@ def from_mag_to_mag1(self, from_mag: Mag) -> "NDBoundingBox": self.size_xyz * mag_vec ) - def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": + def _align_with_mag_slow(self: T, mag: Mag, ceil: bool = False) -> T: """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. :argument ceil: If true, the bounding box is enlarged when necessary. If false, it's shrinked when necessary. @@ -617,9 +635,7 @@ def _align_with_mag_slow(self, mag: Mag, ceil: bool = False) -> "NDBoundingBox": bottomright = align(self.bottomright, np.floor) return attr.evolve(self, topleft=topleft, size=bottomright - topleft) - def align_with_mag( - self, mag: Union[Mag, Vec3Int], ceil: bool = False - ) -> "NDBoundingBox": + def align_with_mag(self: T, mag: Union[Mag, Vec3Int], ceil: bool = False) -> T: """ Rounds the bounding box, so that both topleft and bottomright are divisible by mag. @@ -674,13 +690,13 @@ def contains(self, coord: VecIntLike) -> bool: # In earlier versions, we simply converted to ndarray to have # a unified calculation here, but this turned out to be a performance bottleneck. # Therefore, the contains-check is performed on the tuple here. - coord = VecInt(coord) + coord = VecInt(coord, axes=self.axes) return all( self.topleft[i] <= coord[i] < self.bottomright[i] for i in range(len(self.axes)) ) - def contains_bbox(self, inner_bbox: "NDBoundingBox") -> bool: + def contains_bbox(self: T, inner_bbox: T) -> bool: """ Check whether a bounding box is completely inside of the bounding box. @@ -694,10 +710,10 @@ def contains_bbox(self, inner_bbox: "NDBoundingBox") -> bool: return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox def chunk( - self, + self: T, chunk_shape: VecIntLike, chunk_border_alignments: Optional[VecIntLike] = None, - ) -> Generator["NDBoundingBox", None, None]: + ) -> Generator[T, None, None]: """ Decompose the bounding box into smaller chunks of size `chunk_shape`. @@ -723,25 +739,27 @@ def chunk( chunk_shape = Vec3Int(chunk_shape) chunk_shape = ( - self.with_size(VecInt.ones(len(self))) + self.with_size(VecInt.ones(self.axes)) .with_size_xyz(chunk_shape) .size.to_np() ) except AssertionError: - chunk_shape = VecInt(chunk_shape).to_np() + chunk_shape = VecInt(chunk_shape, axes=self.axes).to_np() - start_adjust = VecInt.zeros(len(self)).to_np() + start_adjust = VecInt.zeros(self.axes).to_np() if chunk_border_alignments is not None: try: chunk_border_alignments = Vec3Int(chunk_border_alignments) chunk_border_alignments = ( - self.with_size(VecInt.ones(len(self))) + self.with_size(VecInt.ones(self.axes)) .with_size_xyz(chunk_border_alignments) .size.to_np() ) except AssertionError: - chunk_border_alignments = VecInt(chunk_border_alignments).to_np() + chunk_border_alignments = VecInt( + chunk_border_alignments, axes=self.axes + ).to_np() assert np.all( chunk_shape % chunk_border_alignments == 0 @@ -760,9 +778,9 @@ def chunk( ] ): yield self.intersected_with( - NDBoundingBox( - topleft=coordinates, - size=chunk_shape, + self.__class__( + topleft=VecInt(coordinates, axes=self.axes), + size=VecInt(chunk_shape, axes=self.axes), axes=self.axes, index=self.index, ) @@ -789,7 +807,7 @@ def to_slices(self) -> Tuple[slice, ...]: for topleft, size in zip(self.topleft, self.size) ) - def offset(self, vector: VecIntLike) -> "NDBoundingBox": + def offset(self: T, vector: VecIntLike) -> T: """ Returns a new NDBoundingBox object with the specified offset. @@ -799,8 +817,7 @@ def offset(self, vector: VecIntLike) -> "NDBoundingBox": Returns: NDBoundingBox: A new NDBoundingBox object with the specified offset. """ - vec_int = VecInt(vector) - if len(vec_int) == 3: - return self.with_topleft_xyz(self.topleft_xyz + vec_int) - - return self.with_topleft(self.topleft + vec_int) + try: + return self.with_topleft_xyz(self.topleft_xyz + Vec3Int(vector)) + except AssertionError: + return self.with_topleft(self.topleft + VecInt(vector, axes=self.axes)) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index e2bbc5c1e..872b5b96d 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -11,10 +11,8 @@ class Vec3Int(VecInt): def __new__( cls, - vec: Union[int, "Vec3IntLike"], - *args: int, - y: Optional[int] = None, - z: Optional[int] = None, + *args: Union["Vec3IntLike", Iterable[str], int], + axes: Optional[Iterable[str]] = ("x", "y", "z"), **kwargs: int, ) -> "Vec3Int": """ @@ -34,13 +32,36 @@ def __new__( ``` """ - if isinstance(vec, Vec3Int): - return vec + if args: + if isinstance(args[0], Vec3Int): + return args[0] - as_tuple = super().__new__(cls, vec, *args, y=y, z=z, **kwargs) - assert as_tuple is not None and len(as_tuple) == 3, VALUE_ERROR + assert axes is not None, VALUE_ERROR - return cast(Vec3Int, as_tuple) + if isinstance(args[0], Iterable): + self = super().__new__(cls, *args[0], axes=("x", "y", "z")) + assert self is not None and len(self) == 3, VALUE_ERROR + + return cast(Vec3Int, self) + + assert len(args) == 3 and len(tuple(axes)) == 3, VALUE_ERROR + assert kwargs is None or len(kwargs) == 0, VALUE_ERROR + assert "x" in axes and "y" in axes and "z" in axes, VALUE_ERROR + values, _ = zip(*sorted(zip(args, axes), key=lambda x: x[1])) + else: + assert "x" in kwargs and "y" in kwargs and "z" in kwargs, VALUE_ERROR + assert len(kwargs) == 3, VALUE_ERROR + values = kwargs["x"], kwargs["y"], kwargs["z"] + + self = super().__new__(cls, *values, axes=("x", "y", "z")) + self.axes = ("x", "y", "z") + + assert self is not None and len(self) == 3, VALUE_ERROR + + return cast(Vec3Int, self) + + def __getnewargs__(self) -> Tuple[Tuple[int, ...], Tuple[str, ...]]: + return (self.to_tuple(), self.axes) @property def x(self) -> int: @@ -72,7 +93,9 @@ def from_xyz(x: int, y: int, z: int) -> "Vec3Int": # By calling __new__ of tuple directly, we circumvent # the tolerant (and potentially) slow Vec3Int.__new__ method. - return tuple.__new__(Vec3Int, (x, y, z)) + vec3int = tuple.__new__(Vec3Int, (x, y, z)) + vec3int.axes = ("x", "y", "z") + return vec3int @staticmethod def from_vec3_float(vec: Tuple[float, float, float]) -> "Vec3Int": @@ -93,15 +116,15 @@ def from_str(string: str) -> "Vec3Int": return Vec3Int.full(int(string)) @classmethod - def zeros(cls, _length: int = 3) -> "Vec3Int": + def zeros(cls, _axes: Tuple[str, ...] = ("x", "y", "z")) -> "Vec3Int": return cls(0, 0, 0) @classmethod - def ones(cls, _length: int = 3) -> "Vec3Int": + def ones(cls, _axes: Tuple[str, ...] = ("x", "y", "z")) -> "Vec3Int": return cls(1, 1, 1) @classmethod - def full(cls, an_int: int, _length: int = 3) -> "Vec3Int": + def full(cls, an_int: int, _axes: Tuple[str, ...] = ("x", "y", "z")) -> "Vec3Int": return cls(an_int, an_int, an_int) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index b2a5e7a01..b83a429db 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -1,79 +1,124 @@ import re from operator import add, floordiv, mod, mul, sub -from typing import Any, Callable, Iterable, List, Optional, Tuple, Union, cast +from typing import Any, Callable, Iterable, List, Optional, Tuple, TypeVar, Union, cast import numpy as np VALUE_ERROR = "VecInt can be instantiated with int values `VecInt(1,2,3,4) or with `VecIntLike` object `VecInt([1,2,3,4])." +T = TypeVar("T", bound="VecInt") + class VecInt(tuple): """ - Class to represent a ND vector of integer values. + Class to represent an ND vector of integer values. """ + axes: Tuple[str, ...] + _x_pos: Optional[int] + _y_pos: Optional[int] + _z_pos: Optional[int] + def __new__( cls, - vec: Union[int, "VecIntLike"], - *args: int, - y: Optional[int] = None, - z: Optional[int] = None, + *args: Union["VecIntLike", Iterable[str], int], + axes: Optional[Iterable[str]] = None, **kwargs: int, ) -> "VecInt": """ Class to represent a ND vector. Inherits from tuple and provides useful - methods and operations on top. The vector has a minimal length of 3. + methods and operations on top. The vector stores the axes names together with the values. A small usage example: ```python from webknossos import VecInt - vector_1 = VecInt(1, y=2, z=3, t=4) - vector_2 = VecInt.full(1, 4) + # To create a vector with 4 elements and axes x, y, z, t: + vector_1 = VecInt(1, 2, 3, 4, axes=("x", "y", "z", "t")) + # or + vector_1 = VecInt([1, 2, 3, 4], axes=("x", "y", "z", "t")) + # or + vector_1 = VecInt(x=1, y=2, z=3, t=4) + + vector_2 = VecInt.full(1, axes=("x", "y", "z", "t")) assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] - assert vector_1 + vector_2 == (2, 3, 4, 5) + assert vector_1 + vector_2 == VecInt(2, 3, 4, 5) ``` """ - - if isinstance(vec, VecInt): - return vec - as_tuple: Optional[Tuple[int, ...]] = None - if isinstance(vec, int): - if args: - assert all(isinstance(arg, int) for arg in args), VALUE_ERROR - as_tuple = (vec, *args) + if args: + if isinstance(args[0], VecInt): + return args[0] + if isinstance(args[0], np.ndarray): + assert np.count_nonzero(args[0] % 1) == 0, VALUE_ERROR + if isinstance(args[0], str): + return cls.from_str(args[0]) + if isinstance(args[0], Iterable): + as_tuple = tuple(int(item) for item in args[0]) + if args[1:] and isinstance(args[1], Iterable): + assert all(isinstance(arg, str) for arg in args[1]), VALUE_ERROR + axes = tuple(args[1]) # type: ignore + elif isinstance(args, Iterable): + as_tuple = tuple(int(arg) for arg in args) # type: ignore else: - assert y is not None and z is not None, VALUE_ERROR - remaining_axes = [] - for key, value in kwargs.items(): - assert key not in [ - "x", - "y", - "z", - ], "Additional axis must not be called x, y or z." - remaining_axes.append((key, value)) - as_tuple = ( - vec, - y, - z, - *[x[1] for x in sorted(remaining_axes, key=lambda x: x[0])], - ) - else: - if args: raise ValueError(VALUE_ERROR) - if isinstance(vec, np.ndarray): - assert np.count_nonzero(vec % 1) == 0, VALUE_ERROR - if isinstance(vec, str): - return cls.from_str(vec) - if isinstance(vec, Iterable): - as_tuple = tuple(int(item) for item in vec) - assert as_tuple is not None and len(as_tuple) >= 3, VALUE_ERROR + assert axes is not None, VALUE_ERROR + else: + assert kwargs, VALUE_ERROR + assert axes is None, VALUE_ERROR + as_tuple = tuple(kwargs.values()) + + assert as_tuple is not None, VALUE_ERROR + + self = super().__new__(cls, cast(Iterable, as_tuple)) + # self.axes is set in __new__ instead of __init__ so that pickling/unpickling + # works without problems. As long as the deserialization of a tree instance + # is not finished, the object is only half-initialized. Since self.axes + # is needed after deepcopy, an error would be raised otherwise. + # Also see: + # https://stackoverflow.com/questions/46283738/attributeerror-when-using-python-deepcopy + self.axes = tuple(axes or kwargs.keys()) + self._x_pos = self.axes.index("x") if "x" in self.axes else None + self._y_pos = self.axes.index("y") if "y" in self.axes else None + self._z_pos = self.axes.index("z") if "z" in self.axes else None + + return self + + def __getnewargs__(self) -> Tuple[Tuple[int, ...], Tuple[str, ...]]: + return (self.to_tuple(), self.axes) + + @property + def x(self) -> int: + """ + Returns the x component of the vector. + """ + if self._x_pos is not None: + return self[self._x_pos] + + raise ValueError("The vector does not have an x component.") - return super().__new__(cls, cast(Iterable, as_tuple)) + @property + def y(self) -> int: + """ + Returns the y component of the vector. + """ + if self._y_pos is not None: + return self[self._y_pos] + + raise ValueError("The vector does not have an y component.") + + @property + def z(self) -> int: + """ + Returns the z component of the vector. + """ + if self._z_pos is not None: + return self[self._z_pos] + + raise ValueError("The vector does not have an z component.") @staticmethod def from_str(string: str) -> "VecInt": @@ -88,10 +133,12 @@ def from_str(string: str) -> "VecInt": """ return VecInt(tuple(map(int, re.findall(r"\d+", string)))) - def with_replaced(self, index: int, new_element: int) -> "VecInt": + def with_replaced(self: T, index: int, new_element: int) -> T: """Returns a new ND Vector with a replaced element at a given index.""" - return VecInt(*self[:index], new_element, *self[index + 1 :]) + return self.__class__( + *self[:index], new_element, *self[index + 1 :], axes=self.axes + ) def to_np(self) -> np.ndarray: """ @@ -140,53 +187,58 @@ def is_uniform(self) -> bool: return all(element == first for element in self) def _element_wise( - self, other: Union[int, "VecIntLike"], fn: Callable[[int, Any], int] - ) -> "VecInt": + self: T, other: Union[int, "VecIntLike"], fn: Callable[[int, Any], int] + ) -> T: if isinstance(other, int): - other_imported = VecInt.full(other, len(self)) + other_imported = VecInt.full(other, axes=self.axes) else: - other_imported = VecInt(other) + other_imported = VecInt(other, axes=self.axes) assert len(other_imported) == len( self ), f"{other} and {self} are not equally shaped." return self.__class__( - (fn(self[i], other_imported[i]) for i in range(len(self))) + **{ + axis: fn(self[i], other_imported[i]) for i, axis in enumerate(self.axes) + }, + axes=None, ) - # note: (arguments incompatible with superclass, do not add VecInt to plain tuple! Hence the type:ignore) - def __add__(self, other: Union[int, "VecIntLike"]) -> "VecInt": # type: ignore[override] + # Note: When adding regular tuples the first tuple is extended with the second tuple. + # For VecInt we want to add the elements at the same index. + # Do not add VecInt to plain tuple! Hence the type:ignore) + def __add__(self: T, other: Union[int, "VecIntLike"]) -> T: # type: ignore[override] return self._element_wise(other, add) - def __sub__(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def __sub__(self: T, other: Union[int, "VecIntLike"]) -> T: return self._element_wise(other, sub) # Note: When multiplying regular tuples with an int those are repeated, # which is a different behavior in the superclass! Hence the type:ignore. - def __mul__(self, other: Union[int, "VecIntLike"]) -> "VecInt": # type: ignore[override] + def __mul__(self: T, other: Union[int, "VecIntLike"]) -> T: # type: ignore[override] return self._element_wise(other, mul) - def __floordiv__(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def __floordiv__(self: T, other: Union[int, "VecIntLike"]) -> T: return self._element_wise(other, floordiv) - def __mod__(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def __mod__(self: T, other: Union[int, "VecIntLike"]) -> T: return self._element_wise(other, mod) - def __neg__(self) -> "VecInt": - return self.__class__(-elem for elem in self) + def __neg__(self: T) -> T: + return self.__class__((-elem for elem in self), axes=self.axes) - def ceildiv(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def ceildiv(self: T, other: Union[int, "VecIntLike"]) -> T: """ Returns a new VecInt with the ceil division of each element by the other. """ return (self + other - 1) // other - def pairmax(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def pairmax(self: T, other: Union[int, "VecIntLike"]) -> T: """ Returns a new VecInt with the maximum of each pair of elements from the two vectors. """ return self._element_wise(other, max) - def pairmin(self, other: Union[int, "VecIntLike"]) -> "VecInt": + def pairmin(self: T, other: Union[int, "VecIntLike"]) -> T: """ Returns a new VecInt with the minimum of each pair of elements from the two vectors. """ @@ -203,7 +255,7 @@ def __repr__(self) -> str: f"{self.__class__.__name__}({','.join((str(element) for element in self))})" ) - def add_or_none(self, other: Optional["VecInt"]) -> Optional["VecInt"]: + def add_or_none(self: T, other: Optional["VecInt"]) -> Optional[T]: """ Adds two VecInts or returns None if the other is None. @@ -216,8 +268,8 @@ def add_or_none(self, other: Optional["VecInt"]) -> Optional["VecInt"]: return None if other is None else self + other def moveaxis( - self, source: Union[int, List[int]], target: Union[int, List[int]] - ) -> "VecInt": + self: T, source: Union[int, List[int]], target: Union[int, List[int]] + ) -> T: """ Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified @@ -237,10 +289,11 @@ def moveaxis( np.zeros(tuple(i for i in range(len(self)))), source, target ).shape arr = self.to_np()[np.array(indices)] - return self.__class__(arr) + axes = np.array(self.axes)[np.array(indices)] + return self.__class__(arr, axes=axes) @classmethod - def zeros(cls, length: int) -> "VecInt": + def zeros(cls, axes: Tuple[str, ...]) -> "VecInt": """ Returns a new ND Vector with all elements set to 0. @@ -250,10 +303,10 @@ def zeros(cls, length: int) -> "VecInt": Returns: VecInt: The new vector. """ - return cls((0 for _ in range(length))) + return cls((0 for _ in range(len(axes))), axes=axes) @classmethod - def ones(cls, length: int) -> "VecInt": + def ones(cls, axes: Tuple[str, ...]) -> "VecInt": """ Returns a new ND Vector with all elements set to 1. @@ -263,10 +316,10 @@ def ones(cls, length: int) -> "VecInt": Returns: VecInt: The new vector. """ - return cls((1 for _ in range(length))) + return cls((1 for _ in range(len(axes))), axes=axes) @classmethod - def full(cls, an_int: int, length: int) -> "VecInt": + def full(cls, an_int: int, axes: Tuple[str, ...]) -> "VecInt": """ Returns a new ND Vector with all elements set to the same value. @@ -277,7 +330,7 @@ def full(cls, an_int: int, length: int) -> "VecInt": Returns: VecInt: The new vector. """ - return cls((an_int for _ in range(length))) + return cls((an_int for _ in range(len(axes))), axes=axes) VecIntLike = Union[VecInt, Tuple[int, ...], np.ndarray, Iterable[int]] From 2bfe96120482ba8011d3a8871ce39be33a86fe10 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 18 Mar 2024 11:30:34 +0100 Subject: [PATCH 38/41] Changes init of NDBoundingBoxes. --- .../webknossos/geometry/nd_bounding_box.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index fd05c31ae..e8d12207f 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -48,10 +48,10 @@ class NDBoundingBox: ``` """ - topleft: VecInt = attr.field(converter=VecInt) - size: VecInt = attr.field(converter=VecInt) + topleft: VecInt = attr.field(converter=tuple) # type: ignore + size: VecInt = attr.field(converter=tuple) # type: ignore axes: Tuple[str, ...] = attr.field(converter=str_tpl) - index: VecInt = attr.field(converter=VecInt) + index: VecInt = attr.field(converter=tuple) # type: ignore bottomright: VecInt = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True @@ -65,6 +65,12 @@ def __attrs_post_init__(self) -> None: + f"{len(self.size)}, {len(self.axes)} and {len(self.index)}) do not match." ) assert 0 not in self.index, "Index 0 is reserved for channels." + + # Convert the delivered tuples to VecInts + object.__setattr__(self, "topleft", VecInt(self.topleft, axes=self.axes)) + object.__setattr__(self, "size", VecInt(self.size, axes=self.axes)) + object.__setattr__(self, "index", VecInt(self.index, axes=self.axes)) + if not self._is_sorted(): self._sort_positions_of_axes() @@ -679,8 +685,8 @@ def contains(self, coord: VecIntLike) -> bool: """ if isinstance(coord, np.ndarray): - assert coord.shape == ( - len(self.size), + assert ( + coord.shape == (len(self.size),) ), f"Numpy array BoundingBox.contains must have shape ({len(self.size)},), got {coord.shape}." return cast( bool, From 0575eb9b698f6528e95c5b8afd367b360c8eeeb1 Mon Sep 17 00:00:00 2001 From: markbader Date: Mon, 18 Mar 2024 12:56:53 +0100 Subject: [PATCH 39/41] Add converter for VecInt attributes of nd bounding box to pass typechecks. --- webknossos/webknossos/geometry/nd_bounding_box.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index e8d12207f..b4cd92ad5 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -30,6 +30,12 @@ def str_tpl(str_list: Iterable[str]) -> Tuple[str, ...]: return tuple(str_list) +def int_tpl(vec_int_like: VecIntLike) -> VecInt: + return VecInt( + vec_int_like, axes=(f"unset_{i}" for i in range(len(list(vec_int_like)))) + ) + + @attr.frozen class NDBoundingBox: """ @@ -48,10 +54,10 @@ class NDBoundingBox: ``` """ - topleft: VecInt = attr.field(converter=tuple) # type: ignore - size: VecInt = attr.field(converter=tuple) # type: ignore + topleft: VecInt = attr.field(converter=int_tpl) + size: VecInt = attr.field(converter=int_tpl) axes: Tuple[str, ...] = attr.field(converter=str_tpl) - index: VecInt = attr.field(converter=tuple) # type: ignore + index: VecInt = attr.field(converter=int_tpl) bottomright: VecInt = attr.field(init=False) name: Optional[str] = _DEFAULT_BBOX_NAME is_visible: bool = True From 1a51e9bf96818368ac56e3ae0edeab327e2d0671 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 28 Mar 2024 17:31:01 +0100 Subject: [PATCH 40/41] Enhance documentation. --- docs/mkdocs.yml | 2 + .../webknossos-py/examples/convert_4d_tiff.md | 5 +- webknossos/examples/convert_4d_tiff.py | 22 +- .../webknossos/geometry/nd_bounding_box.py | 190 ++++++++++-------- webknossos/webknossos/geometry/vec3_int.py | 18 +- webknossos/webknossos/geometry/vec_int.py | 126 ++++++------ 6 files changed, 197 insertions(+), 166 deletions(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6456d0c3c..bade6d083 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -113,8 +113,10 @@ nav: - Overview: api/webknossos.md - Geometry: - BoundingBox: api/webknossos/geometry/bounding_box.md + - NDBoundingBox: api/webknossos/geometry/nd_bounding_box.md - Mag: api/webknossos/geometry/mag.md - Vec3Int: api/webknossos/geometry/vec3_int.md + - VecInt: api/webknossos/geometry/vec_int.md - Dataset: - Dataset: api/webknossos/dataset/dataset.md - Layer: api/webknossos/dataset/layer.md diff --git a/docs/src/webknossos-py/examples/convert_4d_tiff.md b/docs/src/webknossos-py/examples/convert_4d_tiff.md index 036d35d64..10edc2298 100644 --- a/docs/src/webknossos-py/examples/convert_4d_tiff.md +++ b/docs/src/webknossos-py/examples/convert_4d_tiff.md @@ -1,7 +1,10 @@ # Convert 4D Tiff -This example uses the [from_images method](../../api/webknossos/dataset/dataset.md#Dataset.from_images) to creates a Zarr3 dataset from a 4D TIFF image, accesses specific layers and views, [reads data](../../api/webknossos/dataset/mag_view.md#MagView.read) within a bounding box, and [writes data](../../api/webknossos/dataset/mag_view.md#MagView.write) to a different position within the dataset. +This example demonstrates the basic interactions with Datasets that have more than three dimensions. +In order to manipulate 4D data in WEBKNOSSOS, we first convert the 4D Tiff dataset into a Zarr3 dataset. This conversion is achieved using the [from_images method](../../api/webknossos/dataset/dataset.md#Dataset.from_images). + +Once the dataset is converted, we can access specific layers and views, [read data](../../api/webknossos/dataset/mag_view.md#MagView.read) from a defined bounding box, and [write data](../../api/webknossos/dataset/mag_view.md#MagView.write) to a different position within the dataset. The [NDBoundingBox](../../api/webknossos/geometry/nd_bounding_box.md#NDBoundingBox) is utilized to select a 4D region of the dataset. ```python --8<-- diff --git a/webknossos/examples/convert_4d_tiff.py b/webknossos/examples/convert_4d_tiff.py index f85fd33c8..184bee12c 100644 --- a/webknossos/examples/convert_4d_tiff.py +++ b/webknossos/examples/convert_4d_tiff.py @@ -17,16 +17,28 @@ def main() -> None: layer = dataset.get_color_layers()[0] mag_view = layer.get_finest_mag() - # Read the data of the dataset within a bounding box + # To get the bounding box of the dataset use layer.bounding_box + # -> NDBoundingBox(topleft=(0, 0, 0, 0), size=(7, 5, 167, 439), axes=('t', 'z', 'y', 'x')) + + # Read all data of the dataset + data = mag_view.read() + # data.shape -> (1, 7, 5, 167, 439) # first value is the channel dimension + + # Read data for a specific time point (t=3) of the dataset + data = mag_view.read( + absolute_bounding_box=layer.bounding_box.with_bounds("t", 3, 1) + ) + # data.shape -> (1, 1, 5, 167, 439) + + # Create a NDBoundingBox to read data from a specific region of the dataset read_bbox = wk.NDBoundingBox( - topleft=(2, 0, 0, 0), - size=(1, 5, 167, 439), + topleft=(2, 0, 67, 39), + size=(2, 5, 100, 400), axes=("t", "z", "y", "x"), index=(1, 2, 3, 4), ) data = mag_view.read(absolute_bounding_box=read_bbox) - # data.shape -> (1, 1, 5, 167, 439) - # The data shape is different to the read_bbox size because it includes the channel dimension + # data.shape -> (1, 2, 5, 100, 400) # first value is the channel dimension # Write some data to a given position mag_view.write(data, absolute_bounding_box=read_bbox.offset((2, 0, 0, 0))) diff --git a/webknossos/webknossos/geometry/nd_bounding_box.py b/webknossos/webknossos/geometry/nd_bounding_box.py index b4cd92ad5..def386881 100644 --- a/webknossos/webknossos/geometry/nd_bounding_box.py +++ b/webknossos/webknossos/geometry/nd_bounding_box.py @@ -21,7 +21,7 @@ _DEFAULT_BBOX_NAME = "Unnamed Bounding Box" -T = TypeVar("T", bound="NDBoundingBox") +_T = TypeVar("_T", bound="NDBoundingBox") def str_tpl(str_list: Iterable[str]) -> Tuple[str, ...]: @@ -39,18 +39,31 @@ def int_tpl(vec_int_like: VecIntLike) -> VecInt: @attr.frozen class NDBoundingBox: """ - This class is used to represent an axis-aligned, n-dimensional cuboid. - The top-left coordinate is inclusive and the bottom-right coordinate is exclusive. - The index parameter defines the axis order of the data, all values have to be greater or equal to 1, as index 0 is reserved for channel data. + The NDBoundingBox class is a generalized version of the 3-dimensional BoundingBox class. It is designed to represent bounding boxes in any number of dimensions. - A small usage example: + The bounding box is characterized by its top-left corner, the size of the box, the names of the axes for each dimension, and the index (or order) of the axes. Each axis must have a unique index, starting from 1 (index 0 is reserved for channel information). + + The top-left coordinate is inclusive, while the bottom-right coordinate is exclusive. + + Here's a brief example of how to use it: ```python - from webknossos import NDBoundingBox - bbox_1 = NDBoundingBox(top_left=(0, 0, 0), size=(100, 100, 100), axes=("x", "y", "z"), index=(1,2,3)) - bbox_2 = NDBoundingBox(top_left=(75, 75, 75, 0), size=(100, 100, 100, 20), axes=("x", "y", "z", "t"), index=(2,3,4,1)) + # Create a 2D bounding box + bbox_1 = NDBoundingBox( + top_left=(0, 0), + size=(100, 100), + axes=("x", "y"), + index=(1,2) + ) + # Create a 4D bounding box + bbox_2 = NDBoundingBox( + top_left=(75, 75, 75, 0), + size=(100, 100, 100, 20), + axes=("x", "y", "z", "t"), + index=(2,3,4,1) + ) ``` """ @@ -116,19 +129,19 @@ def _sort_positions_of_axes(self) -> None: def _is_sorted(self) -> bool: return all(self.index[i - 1] < self.index[i] for i in range(1, len(self.index))) - def with_name(self: T, name: Optional[str]) -> T: + def with_name(self: _T, name: Optional[str]) -> _T: """ Returns a new instance of `NDBoundingBox` with the specified name. Args: - name (Optional[str]): The name to assign to the new `NDBoundingBox` instance. + - name (Optional[str]): The name to assign to the new `NDBoundingBox` instance. Returns: - NDBoundingBox: A new instance of `NDBoundingBox` with the specified name. + - NDBoundingBox: A new instance of `NDBoundingBox` with the specified name. """ return attr.evolve(self, name=name) - def with_topleft(self: T, new_topleft: VecIntLike) -> T: + def with_topleft(self: _T, new_topleft: VecIntLike) -> _T: """ Returns a new NDBoundingBox object with the specified top left coordinates. @@ -140,7 +153,7 @@ def with_topleft(self: T, new_topleft: VecIntLike) -> T: """ return attr.evolve(self, topleft=VecInt(new_topleft, axes=self.axes)) - def with_size(self: T, new_size: VecIntLike) -> T: + def with_size(self: _T, new_size: VecIntLike) -> _T: """ Returns a new NDBoundingBox object with the specified size. @@ -152,74 +165,74 @@ def with_size(self: T, new_size: VecIntLike) -> T: """ return attr.evolve(self, size=VecInt(new_size, axes=self.axes)) - def with_index(self: T, new_index: VecIntLike) -> T: + def with_index(self: _T, new_index: VecIntLike) -> _T: """ Returns a new NDBoundingBox object with the specified index. Args: - new_index (VecIntLike): The new axis order for the bounding box. + - new_index (VecIntLike): The new axis order for the bounding box. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated index. + - NDBoundingBox: A new NDBoundingBox object with the updated index. """ axes, _ = zip(*sorted(zip(self.axes, new_index), key=lambda x: x[1])) return attr.evolve(self, index=VecInt(new_index, axes=axes)) - def with_bottomright(self: T, new_bottomright: VecIntLike) -> T: + def with_bottomright(self: _T, new_bottomright: VecIntLike) -> _T: """ Returns a new NDBoundingBox with an updated bottomright value. Args: - new_bottomright (VecIntLike): The new bottom right corner coordinates. + - new_bottomright (VecIntLike): The new bottom right corner coordinates. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated bottom right corner. + - NDBoundingBox: A new NDBoundingBox object with the updated bottom right corner. """ new_size = VecInt(new_bottomright, axes=self.axes) - self.topleft return self.with_size(new_size) - def with_is_visible(self: T, is_visible: bool) -> T: + def with_is_visible(self: _T, is_visible: bool) -> _T: """ Returns a new NDBoundingBox object with the specified visibility. Args: - is_visible (bool): The visibility value to set. + - is_visible (bool): The visibility value to set. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated visibility value. + - NDBoundingBox: A new NDBoundingBox object with the updated visibility value. """ return attr.evolve(self, is_visible=is_visible) - def with_color(self: T, color: Optional[Tuple[float, float, float, float]]) -> T: + def with_color(self: _T, color: Optional[Tuple[float, float, float, float]]) -> _T: """ Returns a new instance of NDBoundingBox with the specified color. Args: - color (Optional[Tuple[float, float, float, float]]): The color to set for the bounding box. - The color should be specified as a tuple of four floats representing RGBA values. + - color (Optional[Tuple[float, float, float, float]]): The color to set for the bounding box. + The color should be specified as a tuple of four floats representing RGBA values. Returns: - NDBoundingBox: A new instance of NDBoundingBox with the specified color. + - NDBoundingBox: A new instance of NDBoundingBox with the specified color. """ return attr.evolve(self, color=color) def with_bounds( - self: T, axis: str, new_topleft: Optional[int], new_size: Optional[int] - ) -> T: + self: _T, axis: str, new_topleft: Optional[int], new_size: Optional[int] + ) -> _T: """ Returns a new NDBoundingBox object with updated bounds along the specified axis. Args: - axis (str): The name of the axis to update. - new_topleft (Optional[int]): The new value for the top-left coordinate along the specified axis. - new_size (Optional[int]): The new size along the specified axis. + - axis (str): The name of the axis to update. + - new_topleft (Optional[int]): The new value for the top-left coordinate along the specified axis. + - new_size (Optional[int]): The new size along the specified axis. Returns: - NDBoundingBox: A new NDBoundingBox object with updated bounds. + - NDBoundingBox: A new NDBoundingBox object with updated bounds. Raises: - ValueError: If the given axis name does not exist. + - ValueError: If the given axis name does not exist. """ try: @@ -245,10 +258,10 @@ def get_bounds(self, axis: str) -> Tuple[int, int]: Returns the bounds of the given axis. Args: - axis (str): The name of the axis to get the bounds for. + - axis (str): The name of the axis to get the bounds for. Returns: - Tuple[int, int]: A tuple containing the top-left and bottom-right coordinates along the specified axis. + - Tuple[int, int]: A tuple containing the top-left and bottom-right coordinates along the specified axis. """ try: index = self.axes.index(axis) @@ -282,13 +295,13 @@ def from_wkw_dict(cls, bbox: Dict) -> "NDBoundingBox": Create an instance of NDBoundingBox from a dictionary representation. Args: - bbox (Dict): The dictionary representation of the bounding box. + - bbox (Dict): The dictionary representation of the bounding box. Returns: - NDBoundingBox: An instance of NDBoundingBox. + - NDBoundingBox: An instance of NDBoundingBox. Raises: - AssertionError: If additionalAxes are present but axisOrder is not provided. + - AssertionError: If additionalAxes are present but axisOrder is not provided. """ topleft: Tuple[int, ...] = bbox["topLeft"] @@ -322,7 +335,7 @@ def to_wkw_dict(self) -> dict: Converts the bounding box object to a json dictionary. Returns: - dict: A json dictionary representing the bounding box. + - dict: A json dictionary representing the bounding box. """ topleft = [None, None, None] width, height, depth = None, None, None @@ -365,7 +378,7 @@ def to_config_dict(self) -> dict: Returns a dictionary representation of the bounding box. Returns: - dict: A dictionary representation of the bounding box. + - dict: A dictionary representation of the bounding box. """ return { "topleft": self.topleft.to_list(), @@ -378,7 +391,7 @@ def to_checkpoint_name(self) -> str: Returns a string representation of the bounding box that can be used as a checkpoint name. Returns: - str: A string representation of the bounding box. + - str: A string representation of the bounding box. """ return f"{'_'.join(str(element) for element in self.topleft)}_{'_'.join(str(element) for element in self.size)}" @@ -403,10 +416,10 @@ def get_shape(self, axis_name: str) -> int: Returns the size of the bounding box along the specified axis. Args: - axis_name (str): The name of the axis to get the size for. + - axis_name (str): The name of the axis to get the size for. Returns: - int: The size of the bounding box along the specified axis. + - int: The size of the bounding box along the specified axis. """ try: index = self.axes.index(axis_name) @@ -457,61 +470,61 @@ def bottomright_xyz(self) -> Vec3Int: @property def index_xyz(self) -> Vec3Int: - """The index of x, y and z axis within the""" + """The index of x, y and z axis within the bounding box.""" return self._get_attr_xyz("index") - def with_topleft_xyz(self: T, new_xyz: Vec3IntLike) -> T: + def with_topleft_xyz(self: _T, new_xyz: Vec3IntLike) -> _T: """ Returns a new NDBoundingBox object with changed x, y and z coordinates of the topleft corner. Args: - new_xyz (Vec3IntLike): The new x, y and z coordinates for the topleft corner. + - new_xyz (Vec3IntLike): The new x, y and z coordinates for the topleft corner. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. + - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the topleft corner. """ new_topleft = self._get_attr_with_replaced_xyz("topleft", new_xyz) return self.with_topleft(new_topleft) - def with_size_xyz(self: T, new_xyz: Vec3IntLike) -> T: + def with_size_xyz(self: _T, new_xyz: Vec3IntLike) -> _T: """ Returns a new NDBoundingBox object with changed x, y and z size. Args: - new_xyz (Vec3IntLike): The new x, y and z size for the bounding box. + - new_xyz (Vec3IntLike): The new x, y and z size for the bounding box. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z size. + - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z size. """ new_size = self._get_attr_with_replaced_xyz("size", new_xyz) return self.with_size(new_size) - def with_bottomright_xyz(self: T, new_xyz: Vec3IntLike) -> T: + def with_bottomright_xyz(self: _T, new_xyz: Vec3IntLike) -> _T: """ Returns a new NDBoundingBox object with changed x, y and z coordinates of the bottomright corner. Args: - new_xyz (Vec3IntLike): The new x, y and z coordinates for the bottomright corner. + - new_xyz (Vec3IntLike): The new x, y and z coordinates for the bottomright corner. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. + - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z coordinates of the bottomright corner. """ new_bottomright = self._get_attr_with_replaced_xyz("bottomright", new_xyz) return self.with_bottomright(new_bottomright) - def with_index_xyz(self: T, new_xyz: Vec3IntLike) -> T: + def with_index_xyz(self: _T, new_xyz: Vec3IntLike) -> _T: """ Returns a new NDBoundingBox object with changed x, y and z index. Args: - new_xyz (Vec3IntLike): The new x, y and z index for the bounding box. + - new_xyz (Vec3IntLike): The new x, y and z index for the bounding box. Returns: - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z index. + - NDBoundingBox: A new NDBoundingBox object with the updated x, y and z index. """ new_index = self._get_attr_with_replaced_xyz("index", new_xyz) @@ -519,6 +532,7 @@ def with_index_xyz(self: T, new_xyz: Vec3IntLike) -> T: def _check_compatibility(self, other: "NDBoundingBox") -> None: """Checks if two bounding boxes are comparable. To be comparable they need the same number of axes, with same names and same order.""" + if self.axes != other.axes: raise ValueError( f"Operation with two bboxes is only possible if they have the same axes and axes order. {self.axes} != {other.axes}" @@ -529,18 +543,18 @@ def padded_with_margins( ) -> "NDBoundingBox": raise NotImplementedError() - def intersected_with(self: T, other: T, dont_assert: bool = False) -> T: + def intersected_with(self: _T, other: _T, dont_assert: bool = False) -> _T: """ Returns the intersection of two bounding boxes. If dont_assert is set to False, this method may return empty bounding boxes (size == (0, 0, 0)) Args: - other (NDBoundingBox): The other bounding box to intersect with. - dont_assert (bool): If True, the method may return empty bounding boxes. + - other (NDBoundingBox): The other bounding box to intersect with. + - dont_assert (bool): If True, the method may return empty bounding boxes. Returns: - NDBoundingBox: The intersection of the two bounding boxes. + - NDBoundingBox: The intersection of the two bounding boxes. """ self._check_compatibility(other) @@ -557,15 +571,15 @@ def intersected_with(self: T, other: T, dont_assert: bool = False) -> T: return intersection - def extended_by(self: T, other: T) -> T: + def extended_by(self: _T, other: _T) -> _T: """ Returns the smallest bounding box that contains both bounding boxes. Args: - other (NDBoundingBox): The other bounding box to extend with. + - other (NDBoundingBox): The other bounding box to extend with. Returns: - NDBoundingBox: The smallest bounding box that contains both bounding boxes. + - NDBoundingBox: The smallest bounding box that contains both bounding boxes. """ self._check_compatibility(other) if self.is_empty(): @@ -584,19 +598,19 @@ def is_empty(self) -> bool: Boolean check whether the boundung box is empty. Returns: - bool: True if the bounding box is empty, False otherwise. + - bool: True if the bounding box is empty, False otherwise. """ return not self.size.is_positive(strictly_positive=True) - def in_mag(self: T, mag: Mag) -> T: + def in_mag(self: _T, mag: Mag) -> _T: """ Returns the bounding box in the given mag. Args: - mag (Mag): The magnification to convert the bounding box to. + - mag (Mag): The magnification to convert the bounding box to. Returns: - NDBoundingBox: The bounding box in the given magnification. + - NDBoundingBox: The bounding box in the given magnification. """ mag_vec = mag.to_vec3_int() @@ -611,15 +625,15 @@ def in_mag(self: T, mag: Mag) -> T: self.size_xyz // mag_vec ) - def from_mag_to_mag1(self: T, from_mag: Mag) -> T: + def from_mag_to_mag1(self: _T, from_mag: Mag) -> _T: """ Returns the bounging box in the finest magnification (Mag(1)). Args: - from_mag (Mag): The current magnification of the bounding box. + - from_mag (Mag): The current magnification of the bounding box. Returns: - NDBoundingBox: The bounding box in the given magnification. + - NDBoundingBox: The bounding box in the given magnification. """ mag_vec = from_mag.to_vec3_int() @@ -627,7 +641,7 @@ def from_mag_to_mag1(self: T, from_mag: Mag) -> T: self.size_xyz * mag_vec ) - def _align_with_mag_slow(self: T, mag: Mag, ceil: bool = False) -> T: + def _align_with_mag_slow(self: _T, mag: Mag, ceil: bool = False) -> _T: """Rounds the bounding box, so that both topleft and bottomright are divisible by mag. :argument ceil: If true, the bounding box is enlarged when necessary. If false, it's shrinked when necessary. @@ -647,16 +661,16 @@ def _align_with_mag_slow(self: T, mag: Mag, ceil: bool = False) -> T: bottomright = align(self.bottomright, np.floor) return attr.evolve(self, topleft=topleft, size=bottomright - topleft) - def align_with_mag(self: T, mag: Union[Mag, Vec3Int], ceil: bool = False) -> T: + def align_with_mag(self: _T, mag: Union[Mag, Vec3Int], ceil: bool = False) -> _T: """ Rounds the bounding box, so that both topleft and bottomright are divisible by mag. Args: - mag (Union[Mag, Vec3Int]): The magnification to align the bounding box to. - ceil (bool): If True, the bounding box is enlarged when necessary. If False, it's shrinked when necessary. + - mag (Union[Mag, Vec3Int]): The magnification to align the bounding box to. + - ceil (bool): If True, the bounding box is enlarged when necessary. If False, it's shrinked when necessary. Returns: - NDBoundingBox: The aligned bounding box. + - NDBoundingBox: The aligned bounding box. """ # This does the same as _align_with_mag_slow, which is more readable. # Same behavior is asserted in test_align_with_mag_against_numpy_implementation @@ -684,10 +698,10 @@ def contains(self, coord: VecIntLike) -> bool: Note that the point may have float coordinates in the ndarray case Args: - coord (VecIntLike): The coordinates to check. + - coord (VecIntLike): The coordinates to check. Returns: - bool: True if the point is inside of the bounding box, False otherwise. + - bool: True if the point is inside of the bounding box, False otherwise. """ if isinstance(coord, np.ndarray): @@ -708,24 +722,24 @@ def contains(self, coord: VecIntLike) -> bool: for i in range(len(self.axes)) ) - def contains_bbox(self: T, inner_bbox: T) -> bool: + def contains_bbox(self: _T, inner_bbox: _T) -> bool: """ Check whether a bounding box is completely inside of the bounding box. Args: - inner_bbox (NDBoundingBox): The bounding box to check. + - inner_bbox (NDBoundingBox): The bounding box to check. Returns: - bool: True if the bounding box is completely inside of the bounding box, False otherwise. + - bool: True if the bounding box is completely inside of the bounding box, False otherwise. """ self._check_compatibility(inner_bbox) return inner_bbox.intersected_with(self, dont_assert=True) == inner_bbox def chunk( - self: T, + self: _T, chunk_shape: VecIntLike, chunk_border_alignments: Optional[VecIntLike] = None, - ) -> Generator[T, None, None]: + ) -> Generator[_T, None, None]: """ Decompose the bounding box into smaller chunks of size `chunk_shape`. @@ -734,12 +748,12 @@ def chunk( *between two chunks* will be divisible by that value. Args: - chunk_shape (VecIntLike): The size of the chunks to generate. - chunk_border_alignments (Optional[VecIntLike]): The alignment of the chunk borders. + - chunk_shape (VecIntLike): The size of the chunks to generate. + - chunk_border_alignments (Optional[VecIntLike]): The alignment of the chunk borders. Yields: - Generator[NDBoundingBox]: A generator of the chunks. + - Generator[NDBoundingBox]: A generator of the chunks. """ start = self.topleft.to_np() @@ -819,15 +833,15 @@ def to_slices(self) -> Tuple[slice, ...]: for topleft, size in zip(self.topleft, self.size) ) - def offset(self: T, vector: VecIntLike) -> T: + def offset(self: _T, vector: VecIntLike) -> _T: """ Returns a new NDBoundingBox object with the specified offset. Args: - vector (VecIntLike): The offset to apply to the bounding box. + - vector (VecIntLike): The offset to apply to the bounding box. Returns: - NDBoundingBox: A new NDBoundingBox object with the specified offset. + - NDBoundingBox: A new NDBoundingBox object with the specified offset. """ try: return self.with_topleft_xyz(self.topleft_xyz + Vec3Int(vector)) diff --git a/webknossos/webknossos/geometry/vec3_int.py b/webknossos/webknossos/geometry/vec3_int.py index 872b5b96d..ed1f7b6be 100644 --- a/webknossos/webknossos/geometry/vec3_int.py +++ b/webknossos/webknossos/geometry/vec3_int.py @@ -5,7 +5,7 @@ from .vec_int import VecInt -VALUE_ERROR = "Vector components must be three integers or a Vec3IntLike object." +_VALUE_ERROR = "Vector components must be three integers or a Vec3IntLike object." class Vec3Int(VecInt): @@ -36,27 +36,27 @@ def __new__( if isinstance(args[0], Vec3Int): return args[0] - assert axes is not None, VALUE_ERROR + assert axes is not None, _VALUE_ERROR if isinstance(args[0], Iterable): self = super().__new__(cls, *args[0], axes=("x", "y", "z")) - assert self is not None and len(self) == 3, VALUE_ERROR + assert self is not None and len(self) == 3, _VALUE_ERROR return cast(Vec3Int, self) - assert len(args) == 3 and len(tuple(axes)) == 3, VALUE_ERROR - assert kwargs is None or len(kwargs) == 0, VALUE_ERROR - assert "x" in axes and "y" in axes and "z" in axes, VALUE_ERROR + assert len(args) == 3 and len(tuple(axes)) == 3, _VALUE_ERROR + assert kwargs is None or len(kwargs) == 0, _VALUE_ERROR + assert "x" in axes and "y" in axes and "z" in axes, _VALUE_ERROR values, _ = zip(*sorted(zip(args, axes), key=lambda x: x[1])) else: - assert "x" in kwargs and "y" in kwargs and "z" in kwargs, VALUE_ERROR - assert len(kwargs) == 3, VALUE_ERROR + assert "x" in kwargs and "y" in kwargs and "z" in kwargs, _VALUE_ERROR + assert len(kwargs) == 3, _VALUE_ERROR values = kwargs["x"], kwargs["y"], kwargs["z"] self = super().__new__(cls, *values, axes=("x", "y", "z")) self.axes = ("x", "y", "z") - assert self is not None and len(self) == 3, VALUE_ERROR + assert self is not None and len(self) == 3, _VALUE_ERROR return cast(Vec3Int, self) diff --git a/webknossos/webknossos/geometry/vec_int.py b/webknossos/webknossos/geometry/vec_int.py index b83a429db..0c64bc5c0 100644 --- a/webknossos/webknossos/geometry/vec_int.py +++ b/webknossos/webknossos/geometry/vec_int.py @@ -4,14 +4,36 @@ import numpy as np -VALUE_ERROR = "VecInt can be instantiated with int values `VecInt(1,2,3,4) or with `VecIntLike` object `VecInt([1,2,3,4])." +_VALUE_ERROR = "VecInt can be instantiated with int values `VecInt(1,2,3,4) or with `VecIntLike` object `VecInt([1,2,3,4])." -T = TypeVar("T", bound="VecInt") +_T = TypeVar("_T", bound="VecInt") class VecInt(tuple): """ - Class to represent an ND vector of integer values. + The VecInt class is designed to represent a vector of integers. This class is a subclass of the built-in tuple class, and it extends the functionality of tuples by providing additional methods and operations. + + One of the key features of the VecInt class is that it allows for the storage of axis names along with their corresponding values. + + Here is a brief example demonstrating how to use the VecInt class: + + ```python + from webknossos import VecInt + + # Creating a VecInt instance with 4 elements and axes x, y, z, t: + vector_1 = VecInt(1, 2, 3, 4, axes=("x", "y", "z", "t")) + # Alternative ways to create the same VecInt instance: + vector_1 = VecInt([1, 2, 3, 4], axes=("x", "y", "z", "t")) + vector_1 = VecInt(x=1, y=2, z=3, t=4) + + # Creating a VecInt instance with all elements set to 1 and axes x, y, z, t: + vector_2 = VecInt.full(1, axes=("x", "y", "z", "t")) + # Asserting that all elements in vector_2 are equal to 1: + assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] + + # Demonstrating the addition operation between two VecInt instances: + assert vector_1 + vector_2 == VecInt(2, 3, 4, 5) + ``` """ axes: Tuple[str, ...] @@ -25,53 +47,31 @@ def __new__( axes: Optional[Iterable[str]] = None, **kwargs: int, ) -> "VecInt": - """ - Class to represent a ND vector. Inherits from tuple and provides useful - methods and operations on top. The vector stores the axes names together with the values. - - A small usage example: - - ```python - from webknossos import VecInt - - # To create a vector with 4 elements and axes x, y, z, t: - vector_1 = VecInt(1, 2, 3, 4, axes=("x", "y", "z", "t")) - # or - vector_1 = VecInt([1, 2, 3, 4], axes=("x", "y", "z", "t")) - # or - vector_1 = VecInt(x=1, y=2, z=3, t=4) - - vector_2 = VecInt.full(1, axes=("x", "y", "z", "t")) - assert vector_2[0] == vector_2[1] == vector_2[2] == vector_2[3] - - assert vector_1 + vector_2 == VecInt(2, 3, 4, 5) - ``` - """ as_tuple: Optional[Tuple[int, ...]] = None if args: if isinstance(args[0], VecInt): return args[0] if isinstance(args[0], np.ndarray): - assert np.count_nonzero(args[0] % 1) == 0, VALUE_ERROR + assert np.count_nonzero(args[0] % 1) == 0, _VALUE_ERROR if isinstance(args[0], str): return cls.from_str(args[0]) if isinstance(args[0], Iterable): as_tuple = tuple(int(item) for item in args[0]) if args[1:] and isinstance(args[1], Iterable): - assert all(isinstance(arg, str) for arg in args[1]), VALUE_ERROR + assert all(isinstance(arg, str) for arg in args[1]), _VALUE_ERROR axes = tuple(args[1]) # type: ignore elif isinstance(args, Iterable): as_tuple = tuple(int(arg) for arg in args) # type: ignore else: - raise ValueError(VALUE_ERROR) - assert axes is not None, VALUE_ERROR + raise ValueError(_VALUE_ERROR) + assert axes is not None, _VALUE_ERROR else: - assert kwargs, VALUE_ERROR - assert axes is None, VALUE_ERROR + assert kwargs, _VALUE_ERROR + assert axes is None, _VALUE_ERROR as_tuple = tuple(kwargs.values()) - assert as_tuple is not None, VALUE_ERROR + assert as_tuple is not None, _VALUE_ERROR self = super().__new__(cls, cast(Iterable, as_tuple)) # self.axes is set in __new__ instead of __init__ so that pickling/unpickling @@ -126,14 +126,14 @@ def from_str(string: str) -> "VecInt": Returns a new ND Vector from a string representation. Args: - string (str): The string representation of the vector. + - string (str): The string representation of the vector. Returns: - VecInt: The new vector. + - VecInt: The new vector. """ return VecInt(tuple(map(int, re.findall(r"\d+", string)))) - def with_replaced(self: T, index: int, new_element: int) -> T: + def with_replaced(self: _T, index: int, new_element: int) -> _T: """Returns a new ND Vector with a replaced element at a given index.""" return self.__class__( @@ -169,10 +169,10 @@ def is_positive(self, strictly_positive: bool = False) -> bool: Checks if all elements in the vector are positive. Args: - strictly_positive (bool): If True, checks if all elements are strictly positive. + - strictly_positive (bool): If True, checks if all elements are strictly positive. Returns: - bool: True if all elements are positive, False otherwise. + - bool: True if all elements are positive, False otherwise. """ if strictly_positive: return all(i > 0 for i in self) @@ -187,8 +187,8 @@ def is_uniform(self) -> bool: return all(element == first for element in self) def _element_wise( - self: T, other: Union[int, "VecIntLike"], fn: Callable[[int, Any], int] - ) -> T: + self: _T, other: Union[int, "VecIntLike"], fn: Callable[[int, Any], int] + ) -> _T: if isinstance(other, int): other_imported = VecInt.full(other, axes=self.axes) else: @@ -206,39 +206,39 @@ def _element_wise( # Note: When adding regular tuples the first tuple is extended with the second tuple. # For VecInt we want to add the elements at the same index. # Do not add VecInt to plain tuple! Hence the type:ignore) - def __add__(self: T, other: Union[int, "VecIntLike"]) -> T: # type: ignore[override] + def __add__(self: _T, other: Union[int, "VecIntLike"]) -> _T: # type: ignore[override] return self._element_wise(other, add) - def __sub__(self: T, other: Union[int, "VecIntLike"]) -> T: + def __sub__(self: _T, other: Union[int, "VecIntLike"]) -> _T: return self._element_wise(other, sub) # Note: When multiplying regular tuples with an int those are repeated, # which is a different behavior in the superclass! Hence the type:ignore. - def __mul__(self: T, other: Union[int, "VecIntLike"]) -> T: # type: ignore[override] + def __mul__(self: _T, other: Union[int, "VecIntLike"]) -> _T: # type: ignore[override] return self._element_wise(other, mul) - def __floordiv__(self: T, other: Union[int, "VecIntLike"]) -> T: + def __floordiv__(self: _T, other: Union[int, "VecIntLike"]) -> _T: return self._element_wise(other, floordiv) - def __mod__(self: T, other: Union[int, "VecIntLike"]) -> T: + def __mod__(self: _T, other: Union[int, "VecIntLike"]) -> _T: return self._element_wise(other, mod) - def __neg__(self: T) -> T: + def __neg__(self: _T) -> _T: return self.__class__((-elem for elem in self), axes=self.axes) - def ceildiv(self: T, other: Union[int, "VecIntLike"]) -> T: + def ceildiv(self: _T, other: Union[int, "VecIntLike"]) -> _T: """ Returns a new VecInt with the ceil division of each element by the other. """ return (self + other - 1) // other - def pairmax(self: T, other: Union[int, "VecIntLike"]) -> T: + def pairmax(self: _T, other: Union[int, "VecIntLike"]) -> _T: """ Returns a new VecInt with the maximum of each pair of elements from the two vectors. """ return self._element_wise(other, max) - def pairmin(self: T, other: Union[int, "VecIntLike"]) -> T: + def pairmin(self: _T, other: Union[int, "VecIntLike"]) -> _T: """ Returns a new VecInt with the minimum of each pair of elements from the two vectors. """ @@ -255,32 +255,32 @@ def __repr__(self) -> str: f"{self.__class__.__name__}({','.join((str(element) for element in self))})" ) - def add_or_none(self: T, other: Optional["VecInt"]) -> Optional[T]: + def add_or_none(self: _T, other: Optional["VecInt"]) -> Optional[_T]: """ Adds two VecInts or returns None if the other is None. Args: - other (Optional[VecInt]): The other vector to add. + - other (Optional[VecInt]): The other vector to add. Returns: - Optional[VecInt]: The sum of the two vectors or None if the other is None. + - Optional[VecInt]: The sum of the two vectors or None if the other is None. """ return None if other is None else self + other def moveaxis( - self: T, source: Union[int, List[int]], target: Union[int, List[int]] - ) -> T: + self: _T, source: Union[int, List[int]], target: Union[int, List[int]] + ) -> _T: """ Allows to move one element at index `source` to another index `target`. Similar to np.moveaxis, this is *not* a swap operation but instead it moves the specified source so that the other elements move when necessary. Args: - source (Union[int, List[int]]): The index of the element to move. - target (Union[int, List[int]]): The index where the element should be moved to. + - source (Union[int, List[int]]): The index of the element to move. + - target (Union[int, List[int]]): The index where the element should be moved to. Returns: - VecInt: A new vector with the moved element. + - VecInt: A new vector with the moved element. """ # Piggy-back on np.moveaxis by creating an auxiliary array where the indices 0, 1 and @@ -298,10 +298,10 @@ def zeros(cls, axes: Tuple[str, ...]) -> "VecInt": Returns a new ND Vector with all elements set to 0. Args: - length (int): The length of the vector. + - axes (Tuple[str, ...]): The axes of the vector. Returns: - VecInt: The new vector. + - VecInt: The new vector. """ return cls((0 for _ in range(len(axes))), axes=axes) @@ -311,10 +311,10 @@ def ones(cls, axes: Tuple[str, ...]) -> "VecInt": Returns a new ND Vector with all elements set to 1. Args: - length (int): The length of the vector. + - axes (Tuple[str, ...]): The axes of the vector. Returns: - VecInt: The new vector. + - VecInt: The new vector. """ return cls((1 for _ in range(len(axes))), axes=axes) @@ -324,11 +324,11 @@ def full(cls, an_int: int, axes: Tuple[str, ...]) -> "VecInt": Returns a new ND Vector with all elements set to the same value. Args: - an_int (int): The value of the elements. - length (int): The length of the vector. + - an_int (int): The value to set all elements to. + - axes (Tuple[str, ...]): The axes of the vector. Returns: - VecInt: The new vector. + - VecInt: The new vector. """ return cls((an_int for _ in range(len(axes))), axes=axes) From f21ac09daf3a89c8b180cbdd2139360245965d27 Mon Sep 17 00:00:00 2001 From: markbader Date: Thu, 28 Mar 2024 17:49:54 +0100 Subject: [PATCH 41/41] Update Changelog.md --- webknossos/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/webknossos/Changelog.md b/webknossos/Changelog.md index bb493f1e9..758a139ad 100644 --- a/webknossos/Changelog.md +++ b/webknossos/Changelog.md @@ -21,6 +21,7 @@ For upgrade instructions, please check the respective _Breaking Changes_ section - The rules for naming the layers have been tightened to match the allowed layer names on webknossos. [#1016](https://github.com/scalableminds/webknossos-libs/pull/1016) - Replaced PyLint linter + black formatter with Ruff for development. [#1013](https://github.com/scalableminds/webknossos-libs/pull/1013) - The remote operations now use the WEBKNOSSOS API version 6. [#1018](https://github.com/scalableminds/webknossos-libs/pull/1018) +- The conversion of 4D Tiff files to a Zarr3 Dataset is possible. NDBoundingBoxes and VecInt classes are introduced to support working with more than 3 dimensions. [#966](https://github.com/scalableminds/webknossos-libs/pull/966) ### Fixed

~?6)xe8ia>H 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 z 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