Skip to content

Commit 75919e3

Browse files
authored
Fix Unexpected shape error with errors_as_nodata (#256)
Opted not to refactor `NodataReader` as described in comments because #232 removes it all together, and I don't need even more merge conflicts someday. Fixes #243
1 parent 7ca5eac commit 75919e3

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

stackstac/nodata_reader.py

+3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
State = Tuple[np.dtype, Union[int, float]]
1010

1111

12+
# NOTE: this really should be a `ThreadsafeRioDataset` in `rio_reader.py`,
13+
# not a `Reader` (it's never used as one).
1214
class NodataReader:
1315
"Reader that returns a constant (nodata) value for all reads"
16+
1417
scale_offset = (1.0, 0.0)
1518

1619
def __init__(

stackstac/rio_reader.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def _curthread():
4242
open=dict(
4343
GDAL_DISABLE_READDIR_ON_OPEN="EMPTY_DIR",
4444
# ^ stop GDAL from requesting `.aux` and `.msk` files from the bucket (speeds up `open` time a lot)
45-
VSI_CACHE=True
45+
VSI_CACHE=True,
4646
# ^ cache HTTP requests for opening datasets. This is critical for `ThreadLocalRioDataset`,
4747
# which re-opens the same URL many times---having the request cached makes subsequent `open`s
4848
# in different threads snappy.
@@ -70,11 +70,9 @@ def _curthread():
7070
class ThreadsafeRioDataset(Protocol):
7171
scale_offset: Tuple[Union[int, float], Union[int, float]]
7272

73-
def read(self, window: Window, **kwargs) -> np.ndarray:
74-
...
73+
def read(self, window: Window, **kwargs) -> np.ndarray: ...
7574

76-
def close(self) -> None:
77-
...
75+
def close(self) -> None: ...
7876

7977

8078
class SingleThreadedRioDataset:
@@ -408,8 +406,14 @@ def read(self, window: Window, **kwargs) -> np.ndarray:
408406
result = np.ma.masked_array(result[0], mask=result[1] == 0)
409407
elif result.shape[0] == 1:
410408
result = result[0]
411-
else:
412-
raise RuntimeError(f"Unexpected shape {result.shape}, expected exactly 1 band.")
409+
elif result.ndim != 2:
410+
# We should only be getting `result.ndim == 2` in the case when `_open` produced a `NodataReader`.
411+
# `Reader`s always return 2D arrays, whereas `rasterio.read` returns 3D. Pedantically, `NodataReader`
412+
# shouldn't be a `Reader`, but a `ThreadsafeRioDataset`, and it should return a 3D array,
413+
# just to be more consistent.
414+
raise RuntimeError(
415+
f"Unexpected shape {result.shape}, expected exactly 1 band."
416+
)
413417

414418
scale, offset = self.scale_offset
415419

@@ -419,9 +423,9 @@ def read(self, window: Window, **kwargs) -> np.ndarray:
419423
result += offset
420424

421425
result = np.ma.filled(result, fill_value=self.fill_value)
422-
assert np.issubdtype(result.dtype, self.dtype), (
423-
f"Expected result array with dtype {self.dtype!r}, got {result.dtype!r}"
424-
)
426+
assert np.issubdtype(
427+
result.dtype, self.dtype
428+
), f"Expected result array with dtype {self.dtype!r}, got {result.dtype!r}"
425429
return result
426430

427431
def close(self) -> None:

0 commit comments

Comments
 (0)