Skip to content

Commit 3b296da

Browse files
committed
fix indices in _read_chunks()
1 parent fc26342 commit 3b296da

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

src/spatialdata_io/readers/_utils/_image.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ def _compute_chunks(
5454

5555

5656
def _read_chunks(
57-
# TODO: expand type hints for ...
5857
func: Callable[..., NDArray[np.number]],
5958
slide: Any,
6059
coords: NDArray[np.int_],
@@ -94,13 +93,23 @@ def _read_chunks(
9493
Returns
9594
-------
9695
list[list[da.array]]
97-
List (length: n_row_x) of lists (length: n_row_y) of chunks.
98-
Represents all chunks of the full image.
96+
(Outer) list (length: n_row_y) of (inner) lists (length: n_row_x) of chunks with axes
97+
(c, y, x). Represents all chunks of the full image.
98+
99+
Notes
100+
-------
101+
As seen in _compute_chunks(), since coords are in format (x, y, width, height), the
102+
inner list there (dim=-1) runs over the y values and the outer list (dim=-2) runs
103+
over the x values. In _read_chunks() we have the more common (y, x) format, where
104+
the inner list (dim=-1) runs over the x values and the outer list (dim=-2) runs over
105+
the y values.
106+
107+
The above can be confusing, and a way to address this is to define coords to be
108+
in format (y, x, height, width) instead of (x, y, width, height).
99109
"""
100110
func_kwargs = func_kwargs if func_kwargs else {}
101111

102112
# Collect each delayed chunk as item in list of list
103-
# TODO: check, wasn't it x, y and not y, x?
104113
# Inner list becomes dim=-1 (cols/x)
105114
# Outer list becomes dim=-2 (rows/y)
106115
# see dask.array.block
@@ -109,21 +118,18 @@ def _read_chunks(
109118
da.from_delayed(
110119
delayed(func)(
111120
slide,
112-
x0=coords[y, x, 0],
113-
y0=coords[y, x, 1],
114-
width=coords[y, x, 2],
115-
height=coords[y, x, 3],
121+
x0=coords[x, y, 0],
122+
y0=coords[x, y, 1],
123+
width=coords[x, y, 2],
124+
height=coords[x, y, 3],
116125
**func_kwargs,
117126
),
118127
dtype=dtype,
119-
# TODO: double check the [3, 2] with debugger
120128
shape=(n_channel, *coords[y, x, [3, 2]]),
121129
)
122-
# TODO: seems inconsistent with coords docstring
123-
for x in range(coords.shape[1])
130+
for x in range(coords.shape[0])
124131
]
125-
# TODO: seems inconsistent with coords docstring
126-
for y in range(coords.shape[0])
132+
for y in range(coords.shape[1])
127133
]
128134
return chunks
129135

src/spatialdata_io/readers/generic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def _tiff_to_chunks(input: Path, axes_dim_mapping: dict[str, int]) -> list[list[
116116
chunk_coords = _compute_chunks(slide_dimensions, chunk_size=DEFAULT_CHUNKSIZE)
117117

118118
# Define reader func
119-
def _reader_func(slide: NDArray[np.number], x0: int, y0: int, width: int, height: int) -> NDArray[np.number]:
119+
def _reader_func(slide: np.memmap, x0: int, y0: int, width: int, height: int) -> NDArray[np.number]:
120120
return np.array(slide[:, y0 : y0 + height, x0 : x0 + width])
121121

122122
return _read_chunks(_reader_func, slide, coords=chunk_coords, n_channel=n_channel, dtype=slide.dtype)
@@ -142,7 +142,6 @@ def image(input: Path, data_axes: Sequence[str], coordinate_system: str) -> Data
142142

143143
# Edge case: Compressed images are not memory-mappable
144144
except ValueError as e:
145-
# TODO: change to logger warning
146145
logger.warning(
147146
f"Exception occurred: {str(e)}\nPossible troubleshooting: image data "
148147
"is not memory-mappable, potentially due to compression. Trying to "

0 commit comments

Comments
 (0)