mirror of
https://github.com/rasterio/rasterio.git
synced 2026-02-01 14:34:43 +00:00
merge origin/master, alpha authors
This commit is contained in:
commit
ead10a0c5a
42
AUTHORS.txt
42
AUTHORS.txt
@ -1,32 +1,34 @@
|
||||
Authors
|
||||
=======
|
||||
|
||||
Sean Gillies <sean@mapbox.com>
|
||||
Brendan Ward <bcward@consbio.org>
|
||||
Matthew Perry <perrygeo@gmail.com>
|
||||
Kevin Wurster <wursterk@gmail.com>
|
||||
James McBride <jmcbride@berkeley.edu>
|
||||
Amit Kapadia <amit@planet.com>
|
||||
Kelsey Jordahl <kjordahl@alum.mit.edu>
|
||||
Even Rouault <even.rouault@spatialys.com>
|
||||
Mike Toews <mwtoews@gmail.com>
|
||||
Maxim Dubinin <sim@gis-lab.info>
|
||||
Ryan Grout <rgrout@continuum.io>
|
||||
Asger Petersen <asgerpetersen@gmail.com>
|
||||
Joshua Arnott <josh@snorfalorpagus.net>
|
||||
Aldo Culquicondor <alculquicondor@gmail.com>
|
||||
Alessandro Amici <alexamici@gmail.com>
|
||||
Johan Van de Wauw <johan.vandewauw@gmail.com>
|
||||
Alexander <spatial.hast@gmail.com>
|
||||
Amit Kapadia <amit@planet.com>
|
||||
AsgerPetersen <asgerpetersen@gmail.com>
|
||||
Bas Couwenberg <sebastic@xs4all.nl>
|
||||
Brendan Ward <bcward@consbio.org>
|
||||
Etienne B. Racine <etiennebr@gmail.com>
|
||||
Even Rouault <even.rouault@spatialys.com>
|
||||
Jacques Tardie <hi@jacquestardie.org>
|
||||
James McBride <jmcbride@berkeley.edu>
|
||||
James Seppi <james.seppi@gmail.com>
|
||||
Jeffrey Gerard <jgerard@climate.com>
|
||||
Johan Van de Wauw <johan.vandewauw@gmail.com>
|
||||
Joshua Arnott <josh@snorfalorpagus.net>
|
||||
Kelsey Jordahl <kjordahl@alum.mit.edu>
|
||||
Kevin Wurster <wursterk@gmail.com>
|
||||
Martijn Visser <mgvisser@gmail.com>
|
||||
Matt Savoie <github@flamingbear.com>
|
||||
Matthew Perry <perrygeo@gmail.com>
|
||||
Maxim Dubinin <sim@gis-lab.info>
|
||||
Mike Toews <mwtoews@gmail.com>
|
||||
Nat Wilson <njwilson23@gmail.com>
|
||||
Patrick Young <patrick.young@digitalglobe.com>
|
||||
Robin Wilson <robin@rtwilson.com>
|
||||
Jacques Tardie <hi@jacquestardie.org>
|
||||
Etienne B. Racine <etiennebr@gmail.com>
|
||||
Bas Couwenberg <sebastic@xs4all.nl>
|
||||
Ryan Grout <rgrout@continuum.io>
|
||||
Sean Gillies <sean@mapbox.com>
|
||||
Trevor R.H. Clarke <tclarke@ball.com>
|
||||
cgohlke <cgohlke@uci.edu>
|
||||
Martijn Visser <mgvisser@gmail.com>
|
||||
Aldo Culquicondor <alculquicondor@gmail.com>
|
||||
James Seppi <james.seppi@gmail.com>
|
||||
|
||||
See also https://github.com/mapbox/rasterio/graphs/contributors.
|
||||
|
||||
35
CHANGES.txt
35
CHANGES.txt
@ -1,6 +1,41 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
0.32.0 (2016-03-22)
|
||||
-------------------
|
||||
- Bug fix: geometry factories and warp operations are properly deallocated
|
||||
in normal and error situations (#494, #568).
|
||||
- Bug fix: a code block in rio-merge's help has been better formatted (#535).
|
||||
- Bug fix: the rasterio.vfs module is imported in __init__.py to assist
|
||||
cx_Freeze (#536).
|
||||
- Bug fix: old usage of `read_band()` has been replaced by `read()` throughout
|
||||
the docs (#537).
|
||||
- Bug fix: accidental overwriting of existing files is now prevented by the
|
||||
`resolve_inout()` function in `rasterio.rio.helpers`. Commands that take
|
||||
one or more input files plus an output file should use this helper and force
|
||||
overwrite either by using a `--force-overwrite` option or by using the
|
||||
`-o output` option, which implicitly forces overwriting (#539, #540).
|
||||
- Bug fix: missing support for NaN nodata value in rio-warp added (#542, #544).
|
||||
- Bug fix: missing documentation of `rasterize()`'s `fill` parameter added
|
||||
(#543).
|
||||
- Bug fix: raster dataset bounds are densified before transforming so that
|
||||
the projected output of rio-bounds is correct (#556, #557).
|
||||
- Bug fix: add 'line' to the `Interleaving` enum (#560).
|
||||
- Bug fix: convert `matplotlib` import errors to a `RuntimeWarning` (#562).
|
||||
- Bug fix: deallocate CPL strings in error cases (#573).
|
||||
- Bug fix: non-invertable affine transforms are prevented using
|
||||
`__future__.division` *#580).
|
||||
- Bug fix: rio-warp clips output regions to the limits of the destination
|
||||
CRS unless disabled with `--no-check-invert-proj` (#597).
|
||||
- New feature: the functionality previously available only in rio-mask is now
|
||||
available as `rasterio.tools.mask.mask()` (#552).
|
||||
- New feature: raster bounds are used to label axes in `rasterio.tool.show()`
|
||||
(#553).
|
||||
- New feature: GDAL's suggested warp bounds algorithm is wrapped and exposed
|
||||
for use in `warp()` and rio-warp (#574).
|
||||
- Breaking change: align rio-warp's `--bounds` option with rio-merge's: these
|
||||
are in destination CRS units (#541, #545).
|
||||
|
||||
0.31.0 (2015-12-18)
|
||||
-------------------
|
||||
- Warn when rasters have no georeferencing and when the default identity
|
||||
|
||||
@ -329,7 +329,7 @@ option.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ rio info tests/data/RGB.byte.tif --indent 2
|
||||
$ rio info tests/data/RGB.byte.tif --indent 2 --verbose
|
||||
{
|
||||
"count": 3,
|
||||
"crs": "EPSG:32618",
|
||||
|
||||
@ -23,7 +23,7 @@ from rasterio import _err, coords, enums, vfs
|
||||
|
||||
__all__ = [
|
||||
'band', 'open', 'drivers', 'copy', 'pad']
|
||||
__version__ = "0.31.0"
|
||||
__version__ = "0.32.0"
|
||||
|
||||
log = logging.getLogger('rasterio')
|
||||
class NullHandler(logging.Handler):
|
||||
|
||||
@ -20,7 +20,7 @@ from rasterio._drivers import driver_count, GDALEnv
|
||||
from rasterio._err import cpl_errs, GDALError
|
||||
from rasterio import dtypes
|
||||
from rasterio.coords import BoundingBox
|
||||
from rasterio.errors import RasterioDriverRegistrationError
|
||||
from rasterio.errors import DriverRegistrationError
|
||||
from rasterio.five import text_type, string_types
|
||||
from rasterio.transform import Affine
|
||||
from rasterio.enums import ColorInterp, MaskFlags, Resampling
|
||||
@ -1851,7 +1851,7 @@ cdef class InMemoryRaster:
|
||||
|
||||
cdef void *memdriver = _gdal.GDALGetDriverByName("MEM")
|
||||
if memdriver == NULL:
|
||||
raise RasterioDriverRegistrationError(
|
||||
raise DriverRegistrationError(
|
||||
"MEM driver is not registered.")
|
||||
|
||||
self.dataset = _gdal.GDALCreate(
|
||||
|
||||
@ -10,7 +10,7 @@ from rasterio cimport _base, _gdal, _ogr, _io, _features
|
||||
from rasterio import dtypes
|
||||
from rasterio._err import cpl_errs, GDALError
|
||||
from rasterio._io cimport InMemoryRaster
|
||||
from rasterio.errors import RasterioDriverRegistrationError
|
||||
from rasterio.errors import DriverRegistrationError
|
||||
from rasterio.transform import Affine, from_bounds
|
||||
|
||||
|
||||
@ -269,7 +269,7 @@ def _reproject(
|
||||
|
||||
hrdriver = _gdal.GDALGetDriverByName("MEM")
|
||||
if hrdriver == NULL:
|
||||
raise RasterioDriverRegistrationError(
|
||||
raise DriverRegistrationError(
|
||||
"'MEM' driver not found. Check that this call is contained "
|
||||
"in a `with rasterio.drivers()` or `with rasterio.open()` "
|
||||
"block.")
|
||||
@ -317,7 +317,7 @@ def _reproject(
|
||||
|
||||
hrdriver = _gdal.GDALGetDriverByName("MEM")
|
||||
if hrdriver == NULL:
|
||||
raise RasterioDriverRegistrationError(
|
||||
raise DriverRegistrationError(
|
||||
"'MEM' driver not found. Check that this call is contained "
|
||||
"in a `with rasterio.drivers()` or `with rasterio.open()` "
|
||||
"block.")
|
||||
|
||||
@ -7,7 +7,7 @@ class RasterioIOError(IOError):
|
||||
"""A failure to open a dataset using the presently registered drivers."""
|
||||
|
||||
|
||||
class RasterioDriverRegistrationError(ValueError):
|
||||
class DriverRegistrationError(ValueError):
|
||||
"""To be raised when, eg, _gdal.GDALGetDriverByName("MEM") returns NULL."""
|
||||
|
||||
|
||||
|
||||
@ -68,14 +68,16 @@ def x_dst_bounds_handler(ctx, param, value):
|
||||
@click.option('--resampling', type=click.Choice([r.name for r in Resampling]),
|
||||
default='nearest', help="Resampling method.",
|
||||
show_default=True)
|
||||
@click.option('--threads', type=int, default=2,
|
||||
@click.option('--threads', type=int, default=1,
|
||||
help='Number of processing threads.')
|
||||
@click.option('--check-invert-proj', type=bool, default=True,
|
||||
help='Constrain output to valid coordinate region in dst-crs')
|
||||
@options.force_overwrite_opt
|
||||
@options.creation_options
|
||||
@click.pass_context
|
||||
def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
|
||||
x_dst_bounds, bounds, res, resampling, threads, force_overwrite,
|
||||
creation_options):
|
||||
x_dst_bounds, bounds, res, resampling, threads, check_invert_proj,
|
||||
force_overwrite, creation_options):
|
||||
"""
|
||||
Warp a raster dataset.
|
||||
|
||||
@ -132,7 +134,8 @@ def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds,
|
||||
# Expand one value to two if needed
|
||||
res = (res[0], res[0]) if len(res) == 1 else res
|
||||
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2):
|
||||
with rasterio.drivers(CPL_DEBUG=verbosity > 2,
|
||||
CHECK_WITH_INVERT_PROJ=check_invert_proj):
|
||||
with rasterio.open(files[0]) as src:
|
||||
l, b, r, t = src.bounds
|
||||
out_kwargs = src.meta.copy()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
"""Raster warping and reprojection"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
from math import ceil
|
||||
import warnings
|
||||
@ -8,8 +9,10 @@ import warnings
|
||||
from affine import Affine
|
||||
import numpy as np
|
||||
|
||||
import rasterio
|
||||
from rasterio._base import _transform
|
||||
from rasterio._warp import _transform_geom, _reproject, Resampling
|
||||
from rasterio._warp import (_transform_geom, _reproject, Resampling,
|
||||
_calculate_default_transform)
|
||||
from rasterio.transform import guard_transform
|
||||
|
||||
|
||||
@ -251,8 +254,7 @@ def calculate_default_transform(
|
||||
bottom,
|
||||
right,
|
||||
top,
|
||||
resolution=None,
|
||||
densify_pts=21):
|
||||
resolution=None):
|
||||
"""
|
||||
Transforms bounds to destination coordinate system, calculates resolution
|
||||
if not provided, and returns destination transform and dimensions.
|
||||
@ -260,13 +262,8 @@ def calculate_default_transform(
|
||||
|
||||
Destination transform is anchored from the left, top coordinate.
|
||||
|
||||
Destination width and height are calculated from the number of pixels on
|
||||
each dimension required to fit the destination bounds.
|
||||
|
||||
If resolution is not provided, it is calculated using a weighted average
|
||||
of the relative sizes of source width and height compared to the transformed
|
||||
bounds (pixels are assumed to be square).
|
||||
|
||||
Destination width and height (and resolution if not provided), are
|
||||
calculated using GDAL's method for suggest warp output.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@ -283,37 +280,50 @@ def calculate_default_transform(
|
||||
Bounding coordinates in src_crs, from the bounds property of a raster.
|
||||
resolution: tuple (x resolution, y resolution) or float, optional
|
||||
Target resolution, in units of target coordinate reference system.
|
||||
densify_pts: uint, optional
|
||||
Number of points to add to each edge to account for nonlinear
|
||||
edges produced by the transform process. Large numbers will produce
|
||||
worse performance. Default: 21 (gdal default).
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple of destination affine transform, width, and height
|
||||
|
||||
Note
|
||||
----
|
||||
Must be called within a raster.drivers() context
|
||||
|
||||
Some behavior of this function is determined by the
|
||||
CHECK_WITH_INVERT_PROJ environment variable
|
||||
YES: constrain output raster to extents that can be inverted
|
||||
avoids visual artifacts and coordinate discontinuties.
|
||||
NO: reproject coordinates beyond valid bound limits
|
||||
"""
|
||||
dst_affine, dst_width, dst_height = _calculate_default_transform(
|
||||
src_crs, dst_crs,
|
||||
width, height,
|
||||
left, bottom, right, top)
|
||||
|
||||
xmin, ymin, xmax, ymax = transform_bounds(
|
||||
src_crs, dst_crs, left, bottom, right, top, densify_pts)
|
||||
# If resolution is specified, Keep upper-left anchored
|
||||
# adjust the transform resolutions
|
||||
# adjust the width/height by the ratio of estimated:specified res (ceil'd)
|
||||
if resolution:
|
||||
|
||||
x_dif = xmax - xmin
|
||||
y_dif = ymax - ymin
|
||||
size = float(width + height)
|
||||
# resolutions argument into tuple
|
||||
try:
|
||||
res = (float(resolution), float(resolution))
|
||||
except TypeError:
|
||||
res = (resolution[0], resolution[0]) \
|
||||
if len(resolution) == 1 else resolution[0:2]
|
||||
|
||||
if resolution is None:
|
||||
# TODO: compare to gdalwarp default (see
|
||||
# _calculate_default_transform() in _warp.pyx.
|
||||
avg_resolution = (
|
||||
(x_dif / float(width)) * (float(width) / size) +
|
||||
(y_dif / float(height)) * (float(height) / size)
|
||||
)
|
||||
resolution = (avg_resolution, avg_resolution)
|
||||
# Assume yres is provided as positive,
|
||||
# needs to be negative for north-up affine
|
||||
xres = res[0]
|
||||
yres = -res[1]
|
||||
|
||||
elif not isinstance(resolution, (tuple, list)):
|
||||
resolution = (resolution, resolution)
|
||||
xratio = dst_affine.a / xres
|
||||
yratio = dst_affine.e / yres
|
||||
|
||||
dst_affine = Affine(resolution[0], 0, xmin, 0, -resolution[1], ymax)
|
||||
dst_width = max(int(ceil(x_dif / resolution[0])), 1)
|
||||
dst_height = max(int(ceil(y_dif / resolution[1])), 1)
|
||||
dst_affine = Affine(xres, dst_affine.b, dst_affine.c,
|
||||
dst_affine.d, yres, dst_affine.f)
|
||||
|
||||
dst_width = ceil(dst_width * xratio)
|
||||
dst_height = ceil(dst_height * yratio)
|
||||
|
||||
return dst_affine, dst_width, dst_height
|
||||
|
||||
BIN
tests/data/world.byte.tif
Normal file
BIN
tests/data/world.byte.tif
Normal file
Binary file not shown.
@ -114,11 +114,12 @@ def test_warp_reproject_dst_crs(runner, tmpdir):
|
||||
with rasterio.open(outputname) as output:
|
||||
assert output.count == src.count
|
||||
assert output.crs == {'init': 'epsg:4326'}
|
||||
assert output.width == 824
|
||||
assert output.height == 686
|
||||
assert output.width == 835
|
||||
assert output.height == 696
|
||||
assert numpy.allclose(output.bounds,
|
||||
[-78.95864996545055, 23.564424693996177,
|
||||
-76.57259451863895, 25.550873767433984])
|
||||
[-78.95864996545055, 23.564787976164418,
|
||||
-76.5759177302349, 25.550873767433984])
|
||||
|
||||
|
||||
def test_warp_reproject_dst_crs_error(runner, tmpdir):
|
||||
srcname = 'tests/data/RGB.byte.tif'
|
||||
@ -301,3 +302,18 @@ def test_warp_reproject_like(runner, tmpdir):
|
||||
assert numpy.allclose([0.001, 0.001], [output.affine.a, -output.affine.e])
|
||||
assert output.width == 10
|
||||
assert output.height == 10
|
||||
|
||||
|
||||
def test_warp_reproject_nolostdata(runner, tmpdir):
|
||||
srcname = 'tests/data/world.byte.tif'
|
||||
outputname = str(tmpdir.join('test.tif'))
|
||||
result = runner.invoke(warp.warp, [srcname, outputname,
|
||||
'--dst-crs', 'EPSG:3857'])
|
||||
assert result.exit_code == 0
|
||||
assert os.path.exists(outputname)
|
||||
|
||||
with rasterio.open(outputname) as output:
|
||||
arr = output.read()
|
||||
# 50 column swath on the right edge should have some ones (gdalwarped has 7223)
|
||||
assert arr[0, :, -50:].sum() > 7000
|
||||
assert output.crs == {'init': 'epsg:3857'}
|
||||
|
||||
@ -131,9 +131,9 @@ def test_transform_bounds_densify_out_of_bounds():
|
||||
|
||||
def test_calculate_default_transform():
|
||||
target_transform = Affine(
|
||||
0.0028956983577810586, 0.0, -78.95864996545055,
|
||||
0.0, -0.0028956983577810586, 25.550873767433984
|
||||
)
|
||||
0.0028535715391804096, 0.0, -78.95864996545055,
|
||||
0.0, -0.0028535715391804096, 25.550873767433984)
|
||||
|
||||
with rasterio.drivers():
|
||||
with rasterio.open('tests/data/RGB.byte.tif') as src:
|
||||
wgs84_crs = {'init': 'EPSG:4326'}
|
||||
@ -141,8 +141,8 @@ def test_calculate_default_transform():
|
||||
src.crs, wgs84_crs, src.width, src.height, *src.bounds)
|
||||
|
||||
assert dst_transform.almost_equals(target_transform)
|
||||
assert width == 824
|
||||
assert height == 686
|
||||
assert width == 835
|
||||
assert height == 696
|
||||
|
||||
|
||||
def test_calculate_default_transform_single_resolution():
|
||||
@ -270,9 +270,9 @@ def test_reproject_nodata():
|
||||
dst_nodata=nodata
|
||||
)
|
||||
|
||||
assert (out == 1).sum() == 4461
|
||||
assert (out == 1).sum() == 6215
|
||||
assert (out == nodata).sum() == (params.dst_width *
|
||||
params.dst_height - 4461)
|
||||
params.dst_height - 6215)
|
||||
|
||||
|
||||
def test_reproject_nodata_nan():
|
||||
@ -296,9 +296,9 @@ def test_reproject_nodata_nan():
|
||||
dst_nodata=numpy.nan
|
||||
)
|
||||
|
||||
assert (out == 1).sum() == 4461
|
||||
assert (out == 1).sum() == 6215
|
||||
assert numpy.isnan(out).sum() == (params.dst_width *
|
||||
params.dst_height - 4461)
|
||||
params.dst_height - 6215)
|
||||
|
||||
|
||||
|
||||
@ -325,9 +325,9 @@ def test_reproject_dst_nodata_default():
|
||||
dst_crs=params.dst_crs
|
||||
)
|
||||
|
||||
assert (out == 1).sum() == 4461
|
||||
assert (out == 1).sum() == 6215
|
||||
assert (out == 0).sum() == (params.dst_width *
|
||||
params.dst_height - 4461)
|
||||
params.dst_height - 6215)
|
||||
|
||||
|
||||
def test_reproject_invalid_dst_nodata():
|
||||
|
||||
@ -3,7 +3,7 @@ from rasterio._warp import _calculate_default_transform
|
||||
from rasterio.transform import Affine, from_bounds
|
||||
|
||||
|
||||
def test_indentity():
|
||||
def test_identity():
|
||||
"""Get the same transform and dimensions back for same crs."""
|
||||
# Tile: [53, 96, 8]
|
||||
# [-11740727.544603072, 4852834.0517692715, -11584184.510675032, 5009377.085697309]
|
||||
@ -36,3 +36,28 @@ def test_gdal_transform_notnull():
|
||||
right=-80,
|
||||
top=70)
|
||||
assert True
|
||||
|
||||
|
||||
def test_gdal_transform_fail_dst_crs():
|
||||
with rasterio.drivers():
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
{'init': 'EPSG:4326'},
|
||||
'+proj=foobar',
|
||||
width=80,
|
||||
height=80,
|
||||
left=-120,
|
||||
bottom=30,
|
||||
right=-80,
|
||||
top=70)
|
||||
|
||||
def test_gdal_transform_fail_src_crs():
|
||||
with rasterio.drivers():
|
||||
dt, dw, dh = _calculate_default_transform(
|
||||
'+proj=foobar',
|
||||
{'init': 'EPSG:32610'},
|
||||
width=80,
|
||||
height=80,
|
||||
left=-120,
|
||||
bottom=30,
|
||||
right=-80,
|
||||
top=70)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user