Merge pull request #780 from mapbox/default-proj-env

Use CHECK_WITH_INVERT_PROJ=True in default Env
This commit is contained in:
Sean Gillies 2016-06-13 09:24:22 -07:00 committed by GitHub
commit dd1612b656
4 changed files with 105 additions and 36 deletions

View File

@ -16,6 +16,10 @@ _env = None
log = logging.getLogger(__name__)
# Rasterio defaults
default_options = {
'CHECK_WITH_INVERT_PROJ': True
}
class Env(object):
"""Abstraction for GDAL and AWS configuration
@ -154,6 +158,7 @@ def defenv():
log.debug("Environment %r exists", _env)
else:
_env = GDALEnv()
_env.update_config_options(**default_options)
log.debug(
"New GDAL environment %r created", _env)

View File

@ -320,7 +320,7 @@ def calculate_default_transform(
Note
----
Should be called within a raster.env.Env() context
Should be called within a rasterio.Env() context
Some behavior of this function is determined by the
CHECK_WITH_INVERT_PROJ environment variable

View File

@ -12,6 +12,7 @@ import rasterio
from rasterio._drivers import (del_gdal_config, get_gdal_config,
set_gdal_config)
from rasterio.env import defenv, delenv, getenv, setenv, ensure_env
from rasterio.env import default_options
from rasterio.errors import EnvError
from rasterio.rio.main import main_group
@ -48,7 +49,10 @@ def test_env_accessors(gdalenv):
"""High level GDAL env access."""
defenv()
setenv(foo='1', bar='2')
assert getenv() == rasterio.env._env.options == {'foo': '1', 'bar': '2'}
expected = default_options.copy()
expected.update({'foo': '1', 'bar': '2'})
assert getenv() == rasterio.env._env.options
assert getenv() == expected
assert get_gdal_config('foo') == '1'
assert get_gdal_config('bar') == '2'
delenv()
@ -84,10 +88,13 @@ def test_env_options(gdalenv):
env = rasterio.Env(foo='x')
assert env.options == {'foo': 'x'}
assert not env.previous_options
assert getenv() == rasterio.env._env.options == {}
expected = default_options.copy()
assert getenv() == rasterio.env._env.options == expected
expected.update({'foo': 'x'})
with env:
assert getenv() == rasterio.env._env.options == {'foo': 'x'}
assert getenv() == rasterio.env._env.options == {}
assert getenv() == rasterio.env._env.options == expected
del expected['foo']
assert getenv() == rasterio.env._env.options == expected
def test_aws_session(gdalenv):
@ -108,22 +115,26 @@ def test_aws_session_credentials(gdalenv):
aws_access_key_id='id', aws_secret_access_key='key',
aws_session_token='token', region_name='null-island-1')
s = rasterio.env.Env(aws_session=aws_session)
assert getenv() == rasterio.env._env.options == {}
expected = default_options.copy()
assert getenv() == rasterio.env._env.options == expected
s.get_aws_credentials()
assert getenv() == rasterio.env._env.options == {
expected.update({
'aws_access_key_id': 'id', 'aws_region': 'null-island-1',
'aws_secret_access_key': 'key', 'aws_session_token': 'token'}
'aws_secret_access_key': 'key', 'aws_session_token': 'token'})
assert getenv() == rasterio.env._env.options == expected
def test_with_aws_session_credentials(gdalenv):
"""Create an Env with a boto3 session."""
with rasterio.Env(aws_access_key_id='id', aws_secret_access_key='key',
aws_session_token='token', region_name='null-island-1') as s:
assert getenv() == rasterio.env._env.options == {}
expected = default_options.copy()
assert getenv() == rasterio.env._env.options == expected
s.get_aws_credentials()
assert getenv() == rasterio.env._env.options == {
expected.update({
'aws_access_key_id': 'id', 'aws_region': 'null-island-1',
'aws_secret_access_key': 'key', 'aws_session_token': 'token'}
'aws_secret_access_key': 'key', 'aws_session_token': 'token'})
assert getenv() == rasterio.env._env.options == expected
def test_session_env_lazy(monkeypatch, gdalenv):

View File

@ -4,6 +4,7 @@ import sys
import pytest
from affine import Affine
import numpy as np
from packaging.version import parse
import rasterio
from rasterio.enums import Resampling
@ -18,6 +19,27 @@ logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
DST_TRANSFORM = Affine.from_gdal(-8789636.708, 300.0, 0.0, 2943560.235, 0.0, -300.0)
def supported_resampling(method):
if method == Resampling.gauss:
return False
gdal110plus_only = (
Resampling.mode, Resampling.average)
gdal2plus_only = (
Resampling.max, Resampling.min, Resampling.med,
Resampling.q1, Resampling.q3)
version = parse(rasterio.__gdal_version__)
if version < parse('1.10'):
return method not in gdal2plus_only and method not in gdal110plus_only
if version < parse('2.0'):
return method not in gdal2plus_only
return True
reproj_expected = (
({'CHECK_WITH_INVERT_PROJ': False}, 6215),
({'CHECK_WITH_INVERT_PROJ': True}, 4005))
class ReprojectParams(object):
"""Class to assist testing reprojection by encapsulating parameters."""
@ -254,11 +276,12 @@ def test_reproject_out_of_bounds():
assert not out.any()
def test_reproject_nodata():
@pytest.mark.parametrize("options, expected", reproj_expected)
def test_reproject_nodata(options, expected):
params = default_reproject_params()
nodata = 215
with rasterio.Env():
with rasterio.Env(**options):
source = np.ones((params.width, params.height), dtype=np.uint8)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -275,15 +298,16 @@ def test_reproject_nodata():
dst_nodata=nodata
)
assert (out == 1).sum() == 6215
assert (out == 1).sum() == expected
assert (out == nodata).sum() == (params.dst_width *
params.dst_height - 6215)
params.dst_height - expected)
def test_reproject_nodata_nan():
@pytest.mark.parametrize("options, expected", reproj_expected)
def test_reproject_nodata_nan(options, expected):
params = default_reproject_params()
with rasterio.Env():
with rasterio.Env(**options):
source = np.ones((params.width, params.height), dtype=np.float32)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -300,16 +324,17 @@ def test_reproject_nodata_nan():
dst_nodata=np.nan
)
assert (out == 1).sum() == 6215
assert (out == 1).sum() == expected
assert np.isnan(out).sum() == (params.dst_width *
params.dst_height - 6215)
params.dst_height - expected)
def test_reproject_dst_nodata_default():
@pytest.mark.parametrize("options, expected", reproj_expected)
def test_reproject_dst_nodata_default(options, expected):
"""If nodata is not provided, destination will be filled with 0."""
params = default_reproject_params()
with rasterio.Env():
with rasterio.Env(**options):
source = np.ones((params.width, params.height), dtype=np.uint8)
out = np.zeros((params.dst_width, params.dst_height),
dtype=source.dtype)
@ -324,9 +349,9 @@ def test_reproject_dst_nodata_default():
dst_crs=params.dst_crs
)
assert (out == 1).sum() == 6215
assert (out == 1).sum() == expected
assert (out == 0).sum() == (params.dst_width *
params.dst_height - 6215)
params.dst_height - expected)
def test_reproject_invalid_dst_nodata():
@ -597,12 +622,52 @@ def test_reproject_unsupported_resampling_guass():
resampling=Resampling.gauss)
@pytest.mark.parametrize("method", Resampling)
def test_resample_default_invert_proj(method):
"""Nearest and bilinear should produce valid results
with the default Env
"""
if not supported_resampling(method):
pytest.skip()
with rasterio.Env():
with rasterio.open('tests/data/world.rgb.tif') as src:
source = src.read(1)
profile = src.profile.copy()
dst_crs = {'init': 'EPSG:32619'}
# Calculate the ideal dimensions and transformation in the new crs
dst_affine, dst_width, dst_height = calculate_default_transform(
src.crs, dst_crs, src.width, src.height, *src.bounds)
profile['height'] = dst_height
profile['width'] = dst_width
out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8)
out = np.empty(src.shape, dtype=np.uint8)
reproject(
source,
out,
src_transform=src.transform,
src_crs=src.crs,
dst_transform=dst_affine,
dst_crs=dst_crs,
resampling=method)
assert out.mean() > 0
@pytest.mark.xfail()
@pytest.mark.parametrize("method", Resampling)
def test_resample_no_invert_proj(method):
"""Nearest and bilinear should produce valid results with
CHECK_WITH_INVERT_PROJ = False
"""
if not supported_resampling(method):
pytest.skip()
with rasterio.Env(CHECK_WITH_INVERT_PROJ=False):
with rasterio.open('tests/data/world.rgb.tif') as src:
source = src.read(1)
@ -619,19 +684,7 @@ def test_resample_no_invert_proj(method):
out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8)
# nearest works fine
reproject(
source,
out,
src_transform=src.transform,
src_crs=src.crs,
dst_transform=dst_affine,
dst_crs=dst_crs,
resampling=Resampling.nearest)
assert out.mean() > 0
# some other methods succeed but produce blank images
# see #614, some resamplin methods succeed but produce blank images
out = np.empty(src.shape, dtype=np.uint8)
reproject(
source,