Skip to content

Commit

Permalink
Add out_shape to read_masks(), and tests. Slighly modified the out vs…
Browse files Browse the repository at this point in the history
…. out_shape logic in read().
  • Loading branch information
geowurster committed Jun 3, 2016
1 parent c3f79de commit c71ddf1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 22 deletions.
33 changes: 26 additions & 7 deletions rasterio/_io.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -657,13 +657,13 @@ cdef class RasterReader(_base.DatasetReader):
array. In other words, `out` is likely to be an
incomplete representation of the method's results.
Cannot be combined with `out_shape`.
Cannot combined with `out_shape`.
out_shape : tuple, optional
A tuple describing the output array's shape. Allows for decimated
reads without constructing an output Numpy array.
Cannot be combined with `out`.
Cannot combined with `out`.
window : a pair (tuple) of pairs of ints, optional
The optional `window` argument is a 2 item tuple. The first
Expand Down Expand Up @@ -763,11 +763,13 @@ cdef class RasterReader(_base.DatasetReader):

if out is not None and out_shape is not None:
raise ValueError("out and out_shape are exclusive")
elif out is not None or out_shape is not None:
elif out_shape is not None:
if out_shape:
if len(out_shape) == 2:
out_shape = (1, ) + out_shape
out_shape = (1,) + out_shape
out = np.empty(out_shape, dtype=dtype)

if out is not None:
if out.dtype != dtype:
raise ValueError(
"the array's dtype '%s' does not match "
Expand Down Expand Up @@ -903,7 +905,8 @@ cdef class RasterReader(_base.DatasetReader):
return out


def read_masks(self, indexes=None, out=None, window=None, boundless=False):
def read_masks(self, indexes=None, out=None, out_shape=None, window=None,
boundless=False):
"""Read raster band masks as a multidimensional array
Parameters
Expand All @@ -912,7 +915,7 @@ cdef class RasterReader(_base.DatasetReader):
If `indexes` is a list, the result is a 3D array, but is
a 2D array if it is a band index number.
out: numpy ndarray, optional
out : numpy ndarray, optional
As with Numpy ufuncs, this is an optional reference to an
output array with the same dimensions and shape into which
data will be placed.
Expand All @@ -921,6 +924,14 @@ cdef class RasterReader(_base.DatasetReader):
array. In other words, `out` is likely to be an
incomplete representation of the method's results.
Cannot combine with `out_shape`.
out_shape : tuple, optional
A tuple describing the output array's shape. Allows for decimated
reads without constructing an output Numpy array.
Cannot combined with `out`.
window : a pair (tuple) of pairs of ints, optional
The optional `window` argument is a 2 item tuple. The first
item is a tuple containing the indexes of the rows at which
Expand Down Expand Up @@ -973,6 +984,13 @@ cdef class RasterReader(_base.DatasetReader):

dtype = 'uint8'

if out is not None and out_shape is not None:
raise ValueError("out and out_shape are exclusive")
elif out_shape is not None:
if len(out_shape) == 2:
out_shape = (1,) + out_shape
out = np.zeros(out_shape, 'uint8')

if out is not None:
if out.dtype != np.dtype(dtype):
raise ValueError(
Expand All @@ -982,9 +1000,10 @@ cdef class RasterReader(_base.DatasetReader):
raise ValueError(
"'out' shape %s does not match window shape %s" %
(out.shape, win_shape))
if out is None:
else:
out = np.zeros(win_shape, 'uint8')


# We can jump straight to _read() in some cases. We can ignore
# the boundless flag if there's no given window.
if not boundless or not window:
Expand Down
43 changes: 28 additions & 15 deletions tests/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,39 +274,52 @@ def test_read_no_band(self):


@pytest.mark.parametrize("shape,indexes", [
((72, 80), 1), # Single band
((72, 80), 1), # Single band
((2, 72, 80), (1, 3)), # Multiband
((3, 72, 80), None) # All bands
])
def test_out_shape(path_rgb_byte_tif, shape, indexes):

"""Test read(out_shape)
"""Test read(out_shape) and read_masks(out_shape). The tests are identical
aside from the method call.
The pytest parameters are:
* shape - tuple passed to out_shape
* indexes - The bands to read
The resulting images have been decimated by a factor of 10.
"""

with rasterio.open(path_rgb_byte_tif) as src:

out_shape = src.read(indexes, out_shape=shape)
out = src.read(indexes, out=np.empty(shape, dtype=src.dtypes[0]))
for attr in 'read', 'read_masks':

reader = getattr(src, attr)

out_shape = reader(indexes, out_shape=shape)
out = reader(indexes, out=np.empty(shape, dtype=src.dtypes[0]))

assert out_shape.shape == out.shape
assert (out_shape == out).all()

assert shape[-2:] == (72, 80)
assert out_shape.shape == out.shape
assert (out_shape == out).all()
# Sanity check fo the test itself
assert shape[-2:] == (72, 80)


def test_out_shape_exceptions(path_rgb_byte_tif):

with rasterio.open(path_rgb_byte_tif) as src:
with pytest.raises(ValueError):
out = np.empty((src.count, src.height, src.width))
out_shape = (src.count, src.height, src.width)
src.read(out=out, out_shape=out_shape)

with rasterio.open(path_rgb_byte_tif) as src:
with pytest.raises(ValueError):
out_shape = (5, src.height, src.width)
src.read(1, out_shape=out_shape)
for attr in 'read', 'read_masks':

reader = getattr(src, attr)

with pytest.raises(ValueError):
out = np.empty((src.count, src.height, src.width))
out_shape = (src.count, src.height, src.width)
reader(out=out, out_shape=out_shape)

with pytest.raises(ValueError):
out_shape = (5, src.height, src.width)
reader(1, out_shape=out_shape)

0 comments on commit c71ddf1

Please sign in to comment.