This commit is contained in:
Sean Gillies 2019-11-12 22:12:44 -07:00
parent 37681fd367
commit 7a1d295dfb
4 changed files with 69 additions and 20 deletions

View File

@ -1,9 +1,12 @@
Changes
=======
1.1.1 (2019-11-12)
1.1.1 (2019-11-13)
------------------
- Calling a dataset's sample method with coordinates outside the extent of a
dataset with a nodata value of None has raised a TypeError (#1822). Now, it
gives the values we would get from a boundless read of the dataset's values.
- Use new set_proj_search_path() function to set the PROJ data search path. For
GDAL versions before 3.0 this sets the PROJ_LIB environment variable. For
GDAL version 3.0 this calls OSRSetPROJSearchPaths(), which overrides

View File

@ -762,30 +762,35 @@ cdef class DatasetReaderBase(DatasetBase):
mask = mask | self.read_masks(i, **kwargs)
return mask
def sample(self, xy, indexes=None):
def sample(self, xy, indexes=None, masked=False):
"""Get the values of a dataset at certain positions
Values are from the nearest pixel. They are not interpolated.
Parameters
----------
xy : iterable, pairs of floats
A sequence or generator of (x, y) pairs.
indexes : list of ints or a single int, optional
If `indexes` is a list, the result is a 3D array, but is
a 2D array if it is a band index number.
xy : iterable
Pairs of x, y coordinates (floats) in the dataset's
reference system.
indexes : int or list of int
Indexes of dataset bands to sample.
masked : bool, default: False
Whether to mask samples that fall outside the extent of the
dataset.
Returns
-------
Iterable, yielding dataset values for the specified `indexes`
as an ndarray.
------
iterable
Arrays of length equal to the number of specified indexes
containing the dataset values for the bands corresponding to
those indexes.
"""
# In https://github.com/mapbox/rasterio/issues/378 a user has
# found what looks to be a Cython generator bug. Until that can
# be confirmed and fixed, the workaround is a pure Python
# generator implemented in sample.py.
return sample_gen(self, xy, indexes)
return sample_gen(self, xy, indexes=indexes, masked=masked)
@contextmanager

View File

@ -5,8 +5,29 @@ import numpy
from rasterio.windows import Window
def sample_gen(dataset, xy, indexes=None):
"""Generator for sampled pixels"""
def sample_gen(dataset, xy, indexes=None, masked=False):
"""Sample pixels from a dataset
Parameters
----------
dataset : rasterio Dataset
Opened in "r" mode.
xy : iterable
Pairs of x, y coordinates in the dataset's reference system.
indexes : int or list of int
Indexes of dataset bands to sample.
masked : bool, default: False
Whether to mask samples that fall outside the extent of the
dataset.
Yields
------
array
A array of length equal to the number of specified indexes
containing the dataset values for the bands corresponding to
those indexes.
"""
index = dataset.index
read = dataset.read
@ -15,9 +36,9 @@ def sample_gen(dataset, xy, indexes=None):
for x, y in xy:
row_off, col_off = index(x, y)
if row_off < 0 or col_off < 0:
yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata
else:
# if row_off < 0 or col_off < 0:
# yield numpy.ones((dataset.count,), dtype=dataset.dtypes[0]) * dataset.nodata
# else:
window = Window(col_off, row_off, 1, 1)
data = read(indexes, window=window, masked=False)
data = read(indexes, window=window, masked=masked, boundless=True)
yield data[:, 0, 0]

View File

@ -1,3 +1,5 @@
import numpy
import rasterio
@ -13,6 +15,24 @@ def test_sampling_beyond_bounds():
assert list(data) == [0, 0, 0]
def test_sampling_beyond_bounds_no_nodata():
with rasterio.open('tests/data/RGB2.byte.tif') as src:
data = next(src.sample([(-10, 2719200.0)]))
assert list(data) == [0, 0, 0]
def test_sampling_beyond_bounds_masked():
with rasterio.open('tests/data/RGBA.byte.tif') as src:
data = next(src.sample([(-10, 2719200.0)], masked=True))
assert list(data.mask) == [True, True, True, False]
def test_sampling_beyond_bounds_nan():
with rasterio.open('tests/data/float_nan.tif') as src:
data = next(src.sample([(-10, 0.0)]))
assert numpy.isnan(data)
def test_sampling_indexes():
with rasterio.open('tests/data/RGB.byte.tif') as src:
data = next(src.sample([(220650.0, 2719200.0)], indexes=[2]))