Skip to content

Commit

Permalink
Merge pull request #18 from alisterburt/expanded-tile-shape
Browse files Browse the repository at this point in the history
Expand tile shape according to numpy broadcasting semantics
  • Loading branch information
the-lay authored Jan 19, 2022
2 parents 927fda4 + c0b5a5b commit b9adc5f
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 40 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ![tiler_logo](https://user-images.githubusercontent.com/1889128/148645934-2b1545bc-e7ea-4f02-88fb-10100b6aa9be.png) tiler
# ![tiler_baby_logo](misc/baby_logo.png) tiler

![Tiler teaser image](misc/teaser/tiler_teaser.png)

Expand Down Expand Up @@ -136,7 +136,8 @@ This section is a work in progress.

**How do I create tiles with less dimensions than the data array?**

Tiler expects `tile_shape` to have the same length as `data_shape`.
However you can specify the unwanted dimension as just 1.
For example, if you want to get 2d tiles out from 3d array you can specify depth dimension of 1:
Tiler expects `tile_shape` to have less than or the same number of elements as `data_shape`.
If `tile_shape` has less elements than `data_shape`, `tile_shape` will be prepended with
ones to match the size of `data_shape`.
For example, if you want to get 2d tiles out from 3d array you can initialize Tiler like this: `Tiler(data_shape=(128,128,128), tile_shape=(128, 128))` and it will be equivalent to
`Tiler(data_shape=(128,128,128), tile_shape=(1, 128, 128))`.
77 changes: 53 additions & 24 deletions docs/index.html

Large diffs are not rendered by default.

Binary file added misc/baby_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion misc/docs.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cd $(dirname "$file_name")/..
cd "$(dirname "$file_name")"/.. || exit

# build docs
pdoc -o docs -d google tiler
Expand Down
4 changes: 4 additions & 0 deletions tests/test_tiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def test_init(self):
overlap="unsupported_overlap",
)

# test tile shape broadcasting
tiler = Tiler(data_shape=(300, 300), tile_shape=(10,))
assert np.allclose(tiler.tile_shape, (1, 10))

def test_repr(self):
# gotta get that coverage
tiler = Tiler(
Expand Down
11 changes: 7 additions & 4 deletions tiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
if "pdoc" in sys.modules: # pragma: no cover
with open("README.md", "r") as f:
_readme = f.read()
_readme = _readme.split("# tiler", 1)[1] # remove header
_readme = _readme.replace(
"misc/teaser/tiler_teaser.png", "tiler_teaser.png"
) # replace image path

# remove baby logo and header
_readme = _readme.split("\n", 2)[2]

# replace teaser image path
_readme = _readme.replace("misc/teaser/tiler_teaser.png", "tiler_teaser.png")
_readme = _readme.replace("misc/baby_logo.png", "baby_logo.png")
__doc__ = _readme
25 changes: 18 additions & 7 deletions tiler/tiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def __init__(
If there is a channel dimension, it should be included in the shape.
tile_shape (tuple, list or np.ndarray): Shape of a tile, e.g. (256, 256, 3), [64, 64, 64] or np.ndarray([3, 128, 128]).
Tile must have the same number of dimensions as data.
Tile must have the same number of dimensions as data or less.
If less, the shape will be automatically prepended with ones to match data_shape size.
overlap (int, float, tuple, list or np.ndarray): Specifies overlap between tiles.
If integer, the same overlap of overlap pixels applied in each dimension, except channel_dimension.
Expand Down Expand Up @@ -93,19 +94,29 @@ def recalculate(

# Data and tile shapes
if data_shape is not None:
self.data_shape = np.asarray(data_shape).astype(int)
self.data_shape = np.asarray(data_shape, dtype=np.int64)
if tile_shape is not None:
self.tile_shape = np.asarray(tile_shape).astype(int)
self.tile_shape = np.atleast_1d(np.asarray(tile_shape, dtype=np.int64))

# Append ones to match data_shape size
if self.tile_shape.size <= self.data_shape.size:
size_difference = self.data_shape.size - self.tile_shape.size
self.tile_shape = np.insert(
arr=self.tile_shape, obj=0, values=np.ones(size_difference), axis=0
)
warnings.warn(
f"Tiler automatically adjusted tile_shape from {tuple(tile_shape)} to {tuple(self.tile_shape)}."
)
self._n_dim: int = len(self.data_shape)
if (self.tile_shape <= 0).any() or (self.data_shape <= 0).any():
raise ValueError(
"Tile and data shapes must be tuple or lists of positive numbers."
"Tile and data shapes must be tuple, list or ndarray of positive integers."
)
if self.tile_shape.size != self.data_shape.size:
raise ValueError(
"Tile and data shapes must have the same length. "
"Hint: if you require tiles with less dimensions than data, put 1 in sliced dimensions, "
"e.g. to get 1d 64px lines of 2d 64x64px image would mean tile_shape of (64, 1)."
"Tile shape must have less or equal number of elements compared to the data shape. "
"If less, your tile shape will be prepended with ones to match the data shape, "
"e.g. data_shape=(28, 28), tile_shape=(28) -> tile_shape=(1, 28)."
)

# Tiling mode
Expand Down

0 comments on commit b9adc5f

Please sign in to comment.