rasterio/tests/test_boundless_read.py
Sean Gillies 24d79d54af
Merge 1.4.3 (#3270)
* Eliminate boundless reads in merge, new compositing implementation (#3234)

* Eliminate boundless reads in merge, new compositing implementation

Resolves #3228

* Fix nits

* Compare non-zero mean of arrays

* Implement and use Window.align()

Combines the effects of Window.round_offsets and
Window.round_lengths, producing the same effect as gdal_merge.py

* Remove unused math import

* Add more docs about align()

Also increase the fraction used in round_offsets() to be
consistent with align()

* Move align() to a private func, use two existing methods in tests

* Add a test for merging WarpedVRTs (#3237)

Resolves #3196

* Backport of #3217 (#3243)

* Backport of #3217

* Update change log

* Increment GDAL and Python versions for CI (#3244)

* Rewrite _matches() to better support to_authority() and to_epsg() (#3255)

* Rewrite _matches() to better support to_authority() and to_epsg()

Resolves #3239

* Remove list() call and update change log

* Use to_epsg() in is_epsg_code() (#3258)

* Use to_epsg() in is_epsg_code()

Resolves #3248

* Update change log

* Allow MRF compression to surface in properties (#3259)

* Allow MRF compression to surface in properties

Resolves #3256

* Update change log

* Register drivers at most once per process (#3260)

* Register drivers at most once per process

Resolves #3250

* Appease flake8

* Add a note about GDAL_SKIP in the change log

* Support all GDALFillNodata() options in rasterio.fill (#3265)

* Support all GDALFillNodata() options

Resolve #3175.

* Cast values to str and update docs

* Update change log

* Prevent rasterio from trying to open a dataset object (#3266)

Resolves #3105.

* Fix typos discovered by codespell (#3264) (#3267)

* Fix typos discovered by codespell

* crasher



---------

Co-authored-by: Christian Clauss <cclauss@me.com>

* Fix erroneous masking of 0-valued data (#3268)

* Fix erroneous masking of 0-valued data

Resolves #3245

* Add an assertion about data values and update change log

* This is 1.4.3

---------

Co-authored-by: Christian Clauss <cclauss@me.com>
2024-12-02 10:43:14 -07:00

203 lines
7.6 KiB
Python

"""Test of boundless reads"""
from affine import Affine
import shutil
from hypothesis import example, given
import hypothesis.strategies as st
import numpy
from numpy.testing import assert_almost_equal
import pytest
import rasterio
from rasterio.io import MemoryFile
from rasterio.windows import Window
@given(col_start=st.integers(min_value=-700, max_value=0),
row_start=st.integers(min_value=-700, max_value=0),
col_stop=st.integers(min_value=0, max_value=700),
row_stop=st.integers(min_value=0, max_value=700))
def test_outer_boundless_pixel_fidelity(
path_rgb_byte_tif, col_start, row_start, col_stop, row_stop):
"""An outer boundless read doesn't change pixels"""
with rasterio.open(path_rgb_byte_tif) as dataset:
width = dataset.width + col_stop - col_start
height = dataset.height + row_stop - row_start
window = Window(col_start, row_start, width, height)
rgb_padded = dataset.read(window=window, boundless=True)
assert rgb_padded.shape == (dataset.count, height, width)
rgb = dataset.read()
assert numpy.all(
rgb
== rgb_padded[
:, -row_start : height - row_stop, -col_start : width - col_stop
]
)
@pytest.mark.xfail(reason="The bug reported in gh-2382")
@given(height=st.integers(min_value=500, max_value=20000))
@example(height=9508)
def test_issue2382(height):
data_array = numpy.arange(height, dtype="f4").reshape((height, 1))
with MemoryFile() as memfile:
with memfile.open(
driver='GTiff',
count=1,
height=height,
width=1,
dtype=data_array.dtype,
transform=Affine(1.0, 0.0, 0, 0.0, -1.0, 0),
) as dataset:
dataset.write(data_array[numpy.newaxis, ...])
with memfile.open(driver='GTiff') as dataset:
# read first column, rows 0-388
a = dataset.read(
1,
window=Window(col_off=0, row_off=0, width=1, height=388),
boundless=True,
fill_value=-9999,
)[:, 0]
assert_almost_equal(a, numpy.arange(388))
b = dataset.read(
1,
window=Window(col_off=0, row_off=-12, width=1, height=400),
boundless=True,
fill_value=-9999,
)[:, 0]
# the expected result is 12 * -9999 and then the same as above
assert_almost_equal(b, numpy.concatenate([[-9999] * 12, a]))
@pytest.mark.xfail(reason="Likely the bug reported in gh-2382")
@given(
col_start=st.integers(min_value=-700, max_value=0),
row_start=st.integers(min_value=-700, max_value=0),
col_stop=st.integers(min_value=0, max_value=700),
row_stop=st.integers(min_value=0, max_value=700),
)
def test_outer_upper_left_boundless_pixel_fidelity(
path_rgb_byte_tif, col_start, row_start, col_stop, row_stop
):
"""A partially outer boundless read doesn't change pixels"""
with rasterio.open(path_rgb_byte_tif) as dataset:
width = dataset.width - col_stop - col_start
height = dataset.height - row_stop - row_start
window = Window(col_start, row_start, width, height)
rgb_boundless = dataset.read(window=window, boundless=True)
assert rgb_boundless.shape == (dataset.count, height, width)
rgb = dataset.read()
assert numpy.all(
rgb[:, 0 : height + row_start, 0 : width + col_start]
== rgb_boundless[:, -row_start:height, -col_start:width]
)
def test_image(red_green):
"""Read a red image with black background"""
with rasterio.Env():
with rasterio.open(str(red_green.join("red.tif"))) as src:
data = src.read(boundless=True, window=Window(-src.width, -src.height, src.width * 3, src.height * 3))
image = numpy.moveaxis(data, 0, -1)
assert image[63, 63, 0] == 0
assert image[64, 64, 0] == 204
def test_hit_ovr(red_green):
"""Zoomed out read hits the overviews"""
# GDAL doesn't log overview hits for local files , so we copy the
# overviews of green.tif over the red overviews and expect to find
# green pixels below.
green_ovr = red_green.join("green.tif.ovr")
shutil.move(green_ovr, red_green.join("red.tif.ovr"))
assert not green_ovr.exists()
with rasterio.open(str(red_green.join("red.tif.ovr"))) as ovr:
data = ovr.read()
assert (data[1] == 204).all()
with rasterio.Env():
with rasterio.open(str(red_green.join("red.tif"))) as src:
data = src.read(out_shape=(3, 32, 32))
image = numpy.moveaxis(data, 0, -1)
assert image[0, 0, 0] == 17
assert image[0, 0, 1] == 204
def test_boundless_mask_not_all_valid():
"""Confirm resolution of issue #1449"""
with rasterio.open("tests/data/red.tif") as src:
masked = src.read(1, boundless=True, masked=True, window=Window(-1, -1, 66, 66))
assert not masked.mask.all()
assert masked.mask[:, 0].all()
assert masked.mask[:, -1].all()
assert masked.mask[0, :].all()
assert masked.mask[-1, :].all()
def test_boundless_fill_value():
"""Confirm resolution of issue #1471"""
with rasterio.open("tests/data/red.tif") as src:
filled = src.read(1, boundless=True, fill_value=5, window=Window(-1, -1, 66, 66))
assert (filled[:, 0] == 5).all()
assert (filled[:, -1] == 5).all()
assert (filled[0, :] == 5).all()
assert (filled[-1, :] == 5).all()
def test_boundless_masked_special():
"""Confirm resolution of special case in issue #1471"""
with rasterio.open("tests/data/green.tif") as src:
masked = src.read(2, boundless=True, masked=True, window=Window(-1, -1, 66, 66))
assert not masked[:, 0].any()
assert not masked[:, -1].any()
assert not masked[0, :].any()
assert not masked[-1, :].any()
def test_boundless_mask_special():
"""Confirm resolution of special case in issue #1471"""
with rasterio.open("tests/data/green.tif") as src:
mask = src.read_masks(2, boundless=True, window=Window(-1, -1, 66, 66))
assert not mask[:, 0].any()
assert not mask[:, -1].any()
assert not mask[0, :].any()
assert not mask[-1, :].any()
def test_boundless_fill_value_overview_masks():
"""Confirm a more general resolution to issue #1471"""
with rasterio.open("tests/data/cogeo.tif") as src:
data = src.read(1, boundless=True, window=Window(-300, -335, 1000, 1000), fill_value=5, out_shape=(512, 512))
assert (data[:, 0] == 5).all()
def test_boundless_masked_fill_value_overview_masks():
"""Confirm a more general resolution to issue #1471"""
with rasterio.open("tests/data/cogeo.tif") as src:
data = src.read(1, masked=True, boundless=True, window=Window(-300, -335, 1000, 1000), fill_value=5, out_shape=(512, 512))
assert data.fill_value == 5
assert data.mask[:, 0].all()
def test_boundless_open_options():
"""Open options are taken into account"""
with rasterio.open("tests/data/cogeo.tif", overview_level=1) as src:
data1 = src.read(1, boundless=True)
with rasterio.open("tests/data/cogeo.tif", overview_level=2) as src:
data2 = src.read(1, boundless=True)
assert not numpy.array_equal(data1, data2)
def test_issue3245(data):
"""Boundless read of a dataset without a mask should have no masking."""
with rasterio.open(data / "RGB.byte.tif", "r+") as dst:
dst.nodata = None
assert not dst.read(masked=True).mask.any()
data = dst.read(boundless=True, masked=True, window=Window(0, 0, dst.width, dst.height))
assert not data.mask.any()
assert (data >= 0).all()